1. 程式人生 > >【翻譯】把滑鼠當做一個畫筆

【翻譯】把滑鼠當做一個畫筆

⚠️這個系列是自己瞎翻的,文法很醜,跳著跳著撿重要的部分翻,翻錯了不負責,就這樣。

⚠️基於3.4.3,Mouse as a Paint-Brush,原文

目標 

簡單示例 

現在,我們建立一個簡單的應用,在我們滑鼠雙擊的地方畫一個圓圈。

首先我們建立一個由滑鼠事件觸發的滑鼠回撥方法。滑鼠事件可以是任何與滑鼠相關的操作,比如按下滑鼠左鍵,彈起滑鼠左鍵,雙擊滑鼠左鍵等等。它返回給我們滑鼠事件發生的座標點 (x,y) 。有了這些事件型別和發生事件的位置點,我們可以做出任何我們喜歡的操作。要列出所有被允許的滑鼠事件,在python控制檯上執行下面的程式碼。 

import cv2 as cv

events = [i for i in dir(cv) if 'EVENT' in i]

print( events )

建立滑鼠回撥方法,有一個走到哪都一樣的固定格式。唯一不同的點在於方法本身做什麼。因此我們的滑鼠回撥方法只幹一個事情,它畫一個圓圈在我們雙擊的地方。然後看下面的程式碼,程式碼自帶註釋:

import numpy as np
import cv2 as cv
# mouse callback function
def draw_circle(event,x,y,flags,param):
    if event == cv.EVENT_LBUTTONDBLCLK:
        cv.circle(img,(x,y),100,(255,0,0),-1)
# Create a black image, a window and bind the function to window
img = np.zeros((512,512,3), np.uint8)
cv.namedWindow('image')
cv.setMouseCallback('image',draw_circle)
while(1):
    cv.imshow('image',img)
    if cv.waitKey(20) & 0xFF == 27:
        break
cv.destroyAllWindows()

更復雜的示例 

現在我們要來一個更好玩的應用。在這個應用裡,我們使用好像畫圖軟體中那種拖動滑鼠的方式,要麼畫框框要麼畫圓圈(取決於我們選擇的模式)。因此我們的滑鼠回撥方法分為兩部分,一部分畫一個方框,另一部分畫一個圓圈。這個特殊的示例會真的幫助到我們建立和理解一些有趣的應用比如object tracking、image segmentation等等。i

import numpy as np
import cv2 as cv
drawing = False # true if mouse is pressed
mode = True # if True, draw rectangle. Press 'm' to toggle to curve
ix,iy = -1,-1
# mouse callback function
def draw_circle(event,x,y,flags,param):
    global ix,iy,drawing,mode
    if event == cv.EVENT_LBUTTONDOWN:
        drawing = True
        ix,iy = x,y
    elif event == cv.EVENT_MOUSEMOVE:
        if drawing == True:
            if mode == True:
                cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
            else:
                cv.circle(img,(x,y),5,(0,0,255),-1)
    elif event == cv.EVENT_LBUTTONUP:
        drawing = False
        if mode == True:
            cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
        else:
            cv.circle(img,(x,y),5,(0,0,255),-1)

然後咱們必須要繫結這個滑鼠回撥方法到一個Opencv的視窗上,在主迴圈下,我們得為m鍵設定一個鍵盤繫結,用來在畫方框和畫圓圈之間切換。

img = np.zeros((512,512,3), np.uint8)
cv.namedWindow('image')
cv.setMouseCallback('image',draw_circle)
while(1):
    cv.imshow('image',img)
    k = cv.waitKey(1) & 0xFF
    if k == ord('m'):
        mode = not mode
    elif k == 27:
        break
cv.destroyAllWindows()

額外資源 

練習 

  • 在我們的示例中,我們畫了一個被填滿的矩形。 自行修改程式碼畫一個沒有被填滿的。

上篇:【翻譯】OpenCV裡的畫圖方法

下篇:【翻譯】把拖動條當做調色盤