把鼠标作为画笔
目标
- 学会在OpenCv中处理鼠标事件
- 你将要学习这个函数:cv2.setMouseCallback()
4.1 简单的演示
在这里,我们创建一个简单的应用程序,只要双击它,它就在图像上绘制一个圆。
首先,我们创建一个鼠标回调函数,该函数在鼠标事件发生时执行。鼠标事件可以是鼠标上的任何动作,比如左键按下,左键松开,左键双击等。我们可以通过鼠标事件获得与鼠标光标对应的图片上的座标。根据这些信息我们可以做任何我们想做的事。你可以通过执行下列代码查看所有被支持的鼠标事件。
import cv2
events = [i for i in dir(cv2) if 'EVENT' in i]
print(events)
创建鼠标回调函数有一个特定的形式,在任何地方都是相同的。它们仅仅是函数的功能不同。所以我们的鼠标回调函数只能做一件事,它在鼠标双击的地方画一个圆。下面是代码,不懂得地方可以看注释。
import cv2
import numpy as np
#鼠标回调函数
def draw_circle(event,x,y,flags,param):
if event == cv2.EVENT_LBUTTONDBLCLK:
cv2.circle(img,(x,y),100,(255,0,0),-1)
#创建一个黑色图片,一个窗口并且将函数绑定到这个窗口
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()
4.2 高级一点的示例
现在我们创建一个更好的程序。这次我们的程序要完成的任务是根据我们选择的模式在拖动鼠标时绘制矩形或者是圆圈(就像画图程序中一样)。所以我们的回调函数包括两部分,一部分画矩形,一部分画圆。这是一个典型的例子,它可以帮助我们更好的理解与构建人机交互程序,比如物体跟踪,图像分割等。
import cv2
import numpy as np
drawing = False #如果按下鼠标,则为true
mode = True #如果是 True 则画矩形。按 m 键变成绘制曲线。
#鼠标回调函数
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)
下面我们要把这个回调函数与 OpenCv 窗口绑定在一起。在主循环中我们需要讲键盘上的 “m“ 键与模式转换绑定在一起。
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
elif k == 27:
break
cv2.destroyAllWindows()