鼠标作为画笔

目标

在本次会议中:

简单例子

这里,我们创建一个简单的程序,在图像的任何位置双击在上面画一个圆。

首先我们创建一个鼠标回调函数,该函数在鼠标事件发生时执行。鼠标事件可以是与鼠标有关的任何内容,比如鼠标左键按下,左键弹起,左键双击等等。所有鼠标事件都给我们提供坐标 (x,y)。通过这个事件和位置,我们能做任何我们喜欢的事情。要列出所有可用事件,在 Python 终端执行以下代码:

  1. import cv2 as cv
  2. events = [i for i in dir(cv) if 'EVENT' in i]
  3. print( events )

创建鼠标回调函数是有特定的格式,在任何地方都一样。它仅仅是函数的功能不同。因此我们的鼠标回调函数是做一件事,就是我们双击的地方画圆。所以看下面的代码。代码注释能让你明白。

  1. import numpy as np
  2. import cv2 as cv
  3. # 鼠标回调函数
  4. def draw_circle(event,x,y,flags,param):
  5. if event == cv.EVENT_LBUTTONDBLCLK:
  6. cv.circle(img,(x,y),100,(255,0,0),-1)
  7. # 创建一个黑色图像,一个窗口,然后和回调绑定
  8. img = np.zeros((512,512,3), np.uint8)
  9. cv.namedWindow('image')
  10. cv.setMouseCallback('image',draw_circle)
  11. while(1):
  12. cv.imshow('image',img)
  13. if cv.waitKey(20) & 0xFF == 27:
  14. break
  15. cv.destroyAllWindows()

更多高级例子

现在我们寻求更好的应用。这次,我们通过拖动鼠标绘制矩形或者圆 (取决于我们选的模式),就像在 Paint 程序中一样。因此我们的鼠标回调函数有两个,一个画矩形一个画圆形。这个具体的例子将有助于我们创建和理解交互式程序,像对象跟踪,图像分割等等。

  1. import numpy as np
  2. import cv2 as cv
  3. drawing = False # 如果 True 是鼠标按下
  4. mode = True # 如果 True,画矩形,按下‘m’切换到曲线
  5. ix,iy = -1,-1
  6. # 鼠标回调函数
  7. def draw_circle(event,x,y,flags,param):
  8. global ix,iy,drawing,mode
  9. if event == cv.EVENT_LBUTTONDOWN:
  10. drawing = True
  11. ix,iy = x,y
  12. elif event == cv.EVENT_MOUSEMOVE:
  13. if drawing == True:
  14. if mode == True:
  15. cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
  16. else:
  17. cv.circle(img,(x,y),5,(0,0,255),-1)
  18. elif event == cv.EVENT_LBUTTONUP:
  19. drawing = False
  20. if mode == True:
  21. cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
  22. else:
  23. cv.circle(img,(x,y),5,(0,0,255),-1)

下面我们用鼠标回调函数和 OpenCV 窗口绑定。在主循环中,我们应该设置一个‘m‘按健绑定以在矩形和圆形之间切换。

  1. img = np.zeros((512,512,3), np.uint8)
  2. cv.namedWindow('image')
  3. cv.setMouseCallback('image',draw_circle)
  4. while(1):··
  5. cv.imshow('image',img)
  6. k = cv.waitKey(1) & 0xFF
  7. if k == ord('m'):
  8. mode = not mode
  9. elif k == 27:
  10. break
  11. cv.destroyAllWindows()

其他资源

练习

  1. 在我们的最后一个例子中,我们绘制了填充矩形。 您修改代码以绘制未填充的矩形。