OpenCV_005-OpenCV 鼠標作爲畫筆

本文主要內容來自於 OpenCV-Python 教程OpenCV 中的 GUI 功能 部分,這個部分的主要內容如下:

目標

簡單的演示程序

這裏,我們將創建一個簡單的應用程序,當雙擊鼠標左鍵時,它在一幅圖像上繪製一個圓。

首先我們創建一個鼠標事件回調函數,當鼠標事件發生時它將被執行。鼠標事件可以是任何與鼠標相關的事件,比如左鍵按下,左鍵擡起,左鍵雙擊等等。它給我們每個鼠標事件的座標 (x,y)。通過這個事件和位置,我們可以做任何我們想做的。要列出所有可用的事件,可以在 Python 終端中執行如下的代碼:

events = [i for i in dir(cv) if 'EVENT' in i]
print('\n'.join(events))

執行這段代碼將得到類似下面這樣的輸出:

EVENT_FLAG_ALTKEY
EVENT_FLAG_CTRLKEY
EVENT_FLAG_LBUTTON
EVENT_FLAG_MBUTTON
EVENT_FLAG_RBUTTON
EVENT_FLAG_SHIFTKEY
EVENT_LBUTTONDBLCLK
EVENT_LBUTTONDOWN
EVENT_LBUTTONUP
EVENT_MBUTTONDBLCLK
EVENT_MBUTTONDOWN
EVENT_MBUTTONUP
EVENT_MOUSEHWHEEL
EVENT_MOUSEMOVE
EVENT_MOUSEWHEEL
EVENT_RBUTTONDBLCLK
EVENT_RBUTTONDOWN
EVENT_RBUTTONUP

創建鼠標事件回調函數具有特定的格式,在任何地方都是相同的。它們僅在函數做什麼方面不同。即鼠標事件回調函數可以是參數列表滿足條件的任何函數。我們的鼠標事件回調函數只做一件事,它在雙擊發生的位置繪製一個圓。參見下面的代碼。代碼是自解釋的:

def draw_circle_follow_mouse():
    img = np.zeros((512, 512, 3), np.uint8)

    # mouse callback function
    def draw_circle(event, x, y, flags, param):
        if event == cv.EVENT_LBUTTONDBLCLK:
            # Create a black image, a window and bind the function to window
            img.fill(0)
            cv.circle(img, (x, y), 100, (255, 0, 0), -1)
            cv.imshow('image', img)

    cv.namedWindow('image')
    cv.imshow('image', img)
    cv.setMouseCallback('image', draw_circle)
    while (1):
        if cv.waitKey(20) & 0xFF == 27:
            break
    cv.destroyAllWindows()

這裏的鼠標事件回調函數其實是個閉包,它綁定了局部上下文。爲了防止兩次鼠標雙擊事件中的繪製相互干擾,每次在鼠標事件回調函數中繪製之前都會先清空圖像。ASCII 碼 27 表示 ESC 鍵,即按下 ESC 鍵是應用程序退出。

更高級的演示程序

現在我們繼續開發一個更好的應用程序。這次,我們像在 Paint 應用程序中一樣,通過拖動鼠標繪製矩形或者圓(依賴我們選擇的模式)。因此我們的鼠標事件回調函數有兩部分,一部分用於繪製矩形,另一部分用於繪製圓形。這個具體的例子將非常有助於創建和理解一些交互式應用程序,如對象跟蹤、圖像分割等。

def draw_shape_follow_mouse():
    drawing = False  # true if mouse is pressed
    mode = True  # if True, draw rectangle. Press 'm' to toggle to curve
    ix, iy = -1, -1

    img = np.zeros((512, 512, 3), np.uint8)
    # mouse callback function
    def draw_shape(event, x, y, flags, param):
        nonlocal ix, iy, drawing, mode
        if event == cv.EVENT_LBUTTONDOWN:
            drawing = True
            ix, iy = x, y
            img.fill(0)
        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)

        cv.imshow('image', img)

    cv.namedWindow('image')
    cv.imshow('image', img)
    cv.setMouseCallback('image', draw_shape)
    while (1):
        key = cv.waitKey(20) & 0xFF
        if key == ord('m'):
            mode = not mode
        elif key == 27:
            break
    cv.setMouseCallback(None)
    cv.destroyAllWindows()

這裏的鼠標事件回調函數同樣是閉包,通過 cv.setMouseCallback() 將回調函數綁定到 OpenCV 窗口。在主循環中,我們應該爲鍵 'm' 設置一個鍵盤綁定,以在矩形和圓形之間切換。

參考文檔

Mouse as a Paint-Brush

Done.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章