open——cv鼠标事件

615 阅读4分钟

目标

学会open cv鼠标事件

学会使用cv2.setMouseCallback()

因为在文档里面只是这样:

def setMouseCallback(windowName, onMouse, param=None): # real signature unknown; restored from __doc__
""" setMouseCallback(windowName, onMouse [, param]) -> None """
pass

源码又看不懂,所以只能看例子

例子

import cv2

import numpy as np

# mouse callback function

def draw_circle(event,x,y,flags,param):

if event == cv2.EVENT_LBUTTONDBLCLK:

cv2.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)

cv2.namedWindow('image')

cv2.setMouseCallback('image',draw_circle)

while(1):

cv2.imshow('image',img)

if cv2.waitKey(20) & 0xFF == 27:

break

cv2.destroyAllWindows()

只需要关注:

def draw_circle(event,x,y,flags,param):

if event == cv2.EVENT_LBUTTONDBLCLK:

cv2.circle(img,(x,y),100,(255,0,0),-1)

cv2.setMouseCallback('image',draw_circle)

前面定义了一个鼠标事件执行函数(也就是draw_circle),也就是检测鼠标操作的时候应该执行什么操作。实际上是定义一个函数,定义函数的时候需要给参数,但是在调用函数的时候不需要传入参数,而且这个函数在定义的时候五个参数一个都不能少,即使你可能没有用到它们。第一个参数是鼠标的操作,有鼠标点击,鼠标移动等,具体在下面提到。第二,三个参数是检测到鼠标时间的时候鼠标的坐标。第四个参数和第五个参数笔者暂时不知道有什么用。在文档里面提到,鼠标时间的定义方式都大致一样,就是执行的操作不一样,也就是检测到鼠标点击的时候是画圆还是其他什么操作。在定义了一个鼠标执行函数之后,就要只用cv2.setMouseCallback()函数指定需要在什么窗口执行哪一个鼠标操作函数。如果没有窗口,就需要使用cv2.nameWindows()函数创建一个窗口。cv2.setMouseCallback()像cv2.nameWindows()一样没有返回值。

鼠标事件分类

EVENT_FLAG_ALTKEY:字面意思是点击alt键,但是我用的是pycharm学生版,这个时间不发生作用

EVENT_FLAG_CTRLKEY:同上面那个事件,同样在学生版的pycharm里面没作用

EVENT_FLAG_LBUTTON:鼠标左键事件,无论是鼠标左键单击还是双击都会触发

EVENT_FLAG_MBUTTON:鼠标中键事件,中键点击会触发,但是中键的滚动不会触发

EVENT_FLAG_RBUTTON:同上

EVENT_FLAG_SHIFTKEY:同上,pycharm不发生作用

EVENT_LBUTTONDBLCLK:左键双击

EVENT_LBUTTONDOWN:左键按下

EVENT_LBUTTONUP:左键弹起

EVENT_MBUTTONDBLCLK:中键双击

EVENT_MBUTTONDOWN:中键按下

EVENT_MBUTTONUP:中键弹起

EVENT_MOUSEHWHEEL:这个没搞清

EVENT_MOUSEMOVE:鼠标移动

EVENT_MOUSEWHEEL:滚轮滑动

EVENT_RBUTTONDBLCLK:右键双击

EVENT_RBUTTONDOWN:右键按下

EVENT_RBUTTONUP:右键弹起

使用的过程中,发现了一些问题(我用的是pycharm学生免费版):

1、检测同一个按键的时候会有冲突,比如有两个检测左键的操作(单纯的if...elif...),一个是左键事件,一个是左键按下,那么在按下左键的时候只会检测一次,也就是放在面前的条件会被检测到,而不会检测第二次。

2、左键弹起和中键事件冲突,而且无论条件前后,中键事件优先。

3、一些按键功能没法用,像shift,alt和ctrl按键点击。


下面是文档的又一个例子:

#例子检测鼠标的左键是否按下,如果按下并且拖动鼠标(不放开鼠标),那么根据用

#户的需求画出一个圆或一个长方形,鼠标左键松开的时候停止绘画

import cv2

import numpy as np

drawing = False

#drawing记录是否开始绘画

mode = True

#用户可以改变mode的值,由此决定画圆还是长方形

ix,iy = -1,-1


def draw_circle(event,x,y,flags,param):

    global ix,iy,drawing,mode

    if event == cv2.EVENT_LBUTTONDOWN:

        drawing = True

        ix,iy = x,y

#按键按下,记录这个时候的坐标,作为起始坐标,并开始绘画

    elif event == cv2.EVENT_MOUSEMOVE:

        if drawing == True:

            if mode == True:

                cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)

            else:

                cv2.circle(img,(x,y),5,(0,0,255),-1)

#这里的绘制长方形只是一个框,但是随着鼠标移动,多个长方形框叠加,看起来就是一

#个被填充的长方形,圆形也是这样

    elif event == cv2.EVENT_LBUTTONUP:

        drawing = False

        if mode == True:

            cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)

        else:

            cv2.circle(img,(x,y),5,(0,0,255),-1)

#松开按键的时候也就意味着绘画结束,同时画最后一个图形

img = np.zeros((512,512,3), np.uint8)

cv2.namedWindow('image')

cv2.setMouseCallback('image',draw_circle)

while(1):

    cv2.imshow('image',img)

    k = cv2.waitKey(1) & 0xFF

    if k == ord('m'):

        mode = not mode

#m键改变绘制的图形

    elif k == 27:

        break

#esc键退出程序

cv2.destroyAllWindows()