目标
学会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()