番外4. Python OpenCV 中鼠標事件相關處理與常見問題解決方案

      網友投稿 1255 2025-04-02

      本系列專欄寫作方式

      番外4. Python OpenCV 中鼠標事件相關處理與常見問題解決方案

      本系列專欄寫作將采用首創的問答式寫作形式,快速讓你學習到 OpenCV 的初級、中級、高級知識。

      4. Python OpenCV 中鼠標事件相關處理與常見問題解決方案

      本篇博客主要分析 cv2.setMouseCallback 函數,以及該函數在日常編碼中出現問題是如何進行解決。

      本函數主要是 OpenCV 中用來處理鼠標相關事件的函數,通過它可以捕獲到數據觸發的事件,并對其進行處理。

      使用該函數前,可以先通過 help 函數查閱基本用法。

      該函數原型如下:

      setMouseCallback(windowName, onMouse [, param]) -> None

      可以看到該函數有兩個參數,其一是窗口的名稱,其二是回調函數,窗口名稱與cv2.imshow 中的名稱保持一致即可。

      通過函數原型,可以看出 cv2.setMouseCallback 函數是在給窗口設置一個回調函數。

      OpenCV 中鼠標都有哪些事件?

      查看事件的代碼如下,通過內置函數 dir 可以進行查閱。

      import cv2 def show_event(): events = [i for i in dir(cv2) if 'EVENT' in i] print(events) if __name__ == "__main__": show_event()

      運行結果如下,所有與 event(事件相關的函數,都羅列了出來)

      ['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']

      以上事件中,最常用的為 EVENT_LBUTTONDOWN,EVENT_LBUTTONUP,我們接下來就重點掌握。

      EVENT_LBUTTONDOWN 鼠標左鍵按下事件。

      先通過以下代碼呈現一個窗體,測試一下鼠標左鍵按下。

      import cv2 def show_event(): events = [i for i in dir(cv2) if 'EVENT' in i] print(events) def mouse_handler(event, x, y, flags, userdata): if event == 1: # cv2.EVENT_LBUTTONDOWN print("鼠標左鍵按下") if __name__ == "__main__": image = cv2.imread("./tt.jpg") cv2.namedWindow("mouse_event") cv2.imshow("mouse_event", image) cv2.setMouseCallback("mouse_event", mouse_handler) cv2.waitKey()

      代碼運行效果如下,在圖片上點擊鼠標左鍵,會在控制臺進行數據的輸入,輸出內容如截圖紅框位置所示。

      此時需要注意的問題是,即使你沒有加載任何圖片,只是使用 nameWindow 命名了一下窗體,對應的 setMouseCallback 函數也會綁定成功,具體測試代碼如下。

      # image = cv2.imread("./tt.jpg") cv2.namedWindow("mouse_event") # cv2.imshow("mouse_event", image) cv2.setMouseCallback("mouse_event", mouse_handler)

      由上面的案例,我們還能得到下述推論,cv2.setMouseCallback 函數中第二個參數回調函數onMouse ,具備某種格式,因為在上述代碼中出現了這樣一段內容:

      def mouse_handler(event, x, y, flags, userdata):

      這里其實對于所有鼠標事件,回調函數格式都是統一的,只是函數內部的具體實現不同。

      參數說明如下:

      event:鼠標事件名稱,通過該值可以獲取鼠標進行的何種事件操作;

      x, y:鼠標進行事件操作一瞬間,所在的坐標位置;

      flags:指的是與 event 相關的實踐中包含 FLAG 的事件;

      userdata:鼠標回調函數觸發時傳遞進來的參數。

      以上參數都非常容易理解,但是目前網絡上很多內容對 flags 參數都一帶而過,沒有進行說明。

      該參數其實就是我們在上文獲取到的所有事件的一個子集,在看一下之前獲取到的所有事件。

      ['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']

      在其中你重點尋找帶 flag 的值,檢索如下:

      'EVENT_FLAG_ALTKEY', 'EVENT_FLAG_CTRLKEY', 'EVENT_FLAG_LBUTTON', 'EVENT_FLAG_MBUTTON', 'EVENT_FLAG_RBUTTON', 'EVENT_FLAG_SHIFTKEY'

      稍微對英文進行一下翻譯,就能了解 flags 參數,例如我們想要實現按住鼠標左鍵的同時進行拖動,那核心代碼為:

      event == cv2.EVENT_MOUSEMOVE and flags == cv2.EVENT_FLAG_LBUTTON

      按住鍵盤 CTRL 的同時,按下鼠標左鍵,代碼如下

      event == cv2.EVENT_LBUTTONUP and flags == cv2.EVENT_FLAG_CTRLKEY

      接下來我們就實現一下如何按住鼠標左鍵并進行拖動,繪制一個矩形。

      import cv2 image = cv2.imread("./tt.jpg") cv2.namedWindow("mouse_event") x1, y1 = 0, 0 def show_event(): events = [i for i in dir(cv2) if 'EVENT' in i] print(events) def mouse_handler(event, x, y, flags, userdata): global x1, y1 if event == cv2.EVENT_LBUTTONDOWN: print("左鍵點擊") x1, y1 = x, y if event == cv2.EVENT_MOUSEMOVE and flags == cv2.EVENT_FLAG_LBUTTON: # print("鼠標左鍵按下拖動") cv2.rectangle(image, (x1, y1), (x, y), (0, 255, 0), -1) if __name__ == "__main__": cv2.setMouseCallback("mouse_event", mouse_handler) while True: cv2.imshow("mouse_event", image) k = cv2.waitKey(1) & 0xFF if k == 27: break cv2.destroyAllWindows()

      上述代碼,并未用到最后一個參數 userdata,接下來我們通過傳參的方式應用一下該參數。

      核心修改一個地方即可,在 cv2.setMouseCallback 函數部分將讀取的圖像 image 傳遞到回調的函數中去,具體如下

      cv2.setMouseCallback("mouse_event", mouse_handler, image)

      OpenCV 在視頻中捕獲鼠標事件的解決方案

      上文已經實現了在圖片中捕獲鼠標事件,接下來我們看一下如何去在視頻中進行相同的操作。

      由以前的知識已經知道,視頻處理就是對視頻的每一幀進行相應的操作,那可以按照下述代碼進行。

      import cv2 def mouse_handler(event, x, y, flags, frame): if frame is not None: # 獲取坐標,測試用 # print(x, y) if event == cv2.EVENT_MOUSEMOVE: cv2.putText(frame, "Hello OpenCV", (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 0, 0)) cv2.imshow("video", frame) if __name__ == "__main__": cap = cv2.VideoCapture("./test.mp4") while cap.isOpened(): ret, frame = cap.read() if ret: cv2.imshow("video", frame) cv2.setMouseCallback("video", mouse_handler, frame) if cv2.waitKey(25) & 0xFF == 27: break cap.release() cv2.destroyAllWindows()

      以上代碼因為綁定在 EVENT_MOUSEMOVE 事件上,所以當鼠標移動的時候,會出現一個 Hello OpenCV 的字樣,但是該方式會導致視頻不斷重復渲染,效率不好,頻繁刷新幾次之后,頁面就會崩潰掉。

      如果你單純為了測試,可以將 cv2.waitKey(25) 中的數字設置到 1000,這樣視頻播放速度就會變慢,即可抓取到最終效果。

      對于鼠標回調函數的學習,重點要掌握的依舊是各種事件,還有一個需要注意的是組合按鍵與鼠標位置的計算,你可以基于此實現一個簡單的 OpenCV 畫板,當然前提是你對之前學的圖形繪制函數已經十分熟悉。

      補充知識,OpenCV 繪制多邊形

      在 上一篇博客 中,我們缺少了一個函數,繪制多邊形,這里進行一下補充,該函數為 cv2.polylines,函數原型如下:

      polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]]) -> img

      其中最重要的參數 pts,該參數表示待繪制多邊形的折線數組,也可以理解為多邊形的頂點順序坐標。

      例如下述代碼:

      image = np.zeros((400, 400, 3), np.uint8) points = np.array( [[50, 50], [170, 100], [200, 150], [300, 320]], np.int32) cv2.polylines(image, [points], True, (255, 0, 0)) cv2.imshow('image',image) cv2.waitKey()

      繪制的多邊形如下:

      最后,你可以結合本文學到的 cv2.setMouseCallback 函數,加上繪制直線函數,實現一個多邊形手動繪制工具。

      OpenCV Python

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:wps表格中怎么轉換成圖片(wps如何將圖片轉換成表格)
      下一篇:智能客服系統哪些好(智能客服軟件哪家好)
      相關文章
      亚洲国产精品无码久久久不卡| 亚洲精品美女久久久久99小说| 亚洲av无码乱码国产精品| 中文字幕亚洲无线码| 亚洲色婷婷综合开心网| 亚洲不卡无码av中文字幕| 亚洲成a人一区二区三区| 国产亚洲精品国产福利在线观看| 亚洲av综合日韩| va亚洲va日韩不卡在线观看| 色窝窝亚洲av网| 亚洲 小说区 图片区 都市| 亚洲AV无码一区二区三区国产| vvvv99日韩精品亚洲| 亚洲一区二区三区国产精品| 中文亚洲成a人片在线观看| 国产亚洲综合久久系列| 亚洲av中文无码乱人伦在线播放 | 亚洲欧洲一区二区| 亚洲专区先锋影音| 亚洲精品第五页中文字幕| 亚洲H在线播放在线观看H| 中文字幕无码亚洲欧洲日韩| 色婷婷亚洲一区二区三区| 亚洲成aⅴ人片久青草影院| 国产亚洲欧洲Aⅴ综合一区| 国产精品亚洲片在线观看不卡| 久久精品国产亚洲AV果冻传媒| 久久精品国产亚洲AV嫖农村妇女| 亚洲狠狠狠一区二区三区| 自拍日韩亚洲一区在线| 亚洲av永久中文无码精品综合| 亚洲国产天堂久久综合| 亚洲精品无码专区久久久| 亚洲日本一区二区| 成人区精品一区二区不卡亚洲| 国产精品亚洲专区无码WEB| 伊人久久精品亚洲午夜| 亚洲第一精品在线视频| 亚洲一本之道高清乱码| 激情无码亚洲一区二区三区|