1. 学习目标
- 学习如何在OpenCV中处理鼠标事件;
- 学习鼠标事件与回调;
- 学习鼠标事件回调函数的基本流程。
2. Callback 基本流程
3. 鼠标事件 cv.setMouseCallback 函数说明
3.1 cv.setMouseCallback() 函数使用
cv.setMouseCallback(winname,onMouse,userdata)
3.2 参数说明
参数 |
说明 |
winname |
表示监听鼠标事件的窗口。 |
onMouse |
表示响应函数,即当鼠标事件触发时调用的函数。 |
userdata |
表示默认值0。这个参数是用户传递给回调函数的数据,用来处理轨迹条事件。如果使用的第三个参数value是全局变量,完全可以不去管这个userdata参数。传给回调函数的参数!!! |
3.3 返回参数
typedef void(*cv::MouseCallback)(int event, int x, int y, int flags, void *userdata)
3.4 返回参数说明
参数 |
说明 |
event |
表示当前鼠标执行的事件。 |
x |
表示当前鼠标坐标值x。 |
y |
表示当前鼠标坐标值y。 |
flags |
表示鼠标状态。 |
userdata |
表示用户定义的传递到setMouseCallback函数调用的参数。 |
3.5 event 参数说明
值 |
说明 |
EVENT_MOUSEMOVE (0) |
表示滑动事件。 |
EVENT_LBUTTONDOWN (1) |
表示左键点击事件。 |
EVENT_RBUTTONDOWN (2) |
表示右键点击事件。 |
EVENT_MBUTTONDOWN (3) |
表示中键点击事件。 |
EVENT_LBUTTONUP (4) |
表示左键放开事件。 |
EVENT_RBUTTONUP (5) |
表示右键放开事件。 |
EVENT_MBUTTONUP (6) |
表示中键放开事件。 |
EVENT_LBUTTONDBLCLK (7) |
表示左键双击事件。 |
EVENT_RBUTTONDBLCLK (8) |
表示右键双击事件。 |
EVENT_MBUTTONDBLCLK (9) |
表示中键双击事件。 |
3.6 flags 参数说明
值 |
说明 |
EVENT_FLAG_LBUTTON (1) |
表示左键拖曳事件。 |
EVENT_FLAG_RBUTTON (2) |
表示右键拖曳事件。 |
EVENT_FLAG_MBUTTON (4) |
表示中键拖曳事件。 |
EVENT_FLAG_CTRLKEY (8) |
表示(8~15)按 Ctrl 不放。 |
EVENT_FLAG_SHIFTKEY (16) |
表示(16~31)按 Shift 不放。 |
EVENT_FLAG_ALTKEY (32) |
表示(32~39)按 Alt 不放。 |
4. 【通过鼠标绘制随机颜色矩形】实例
4.1 实例代码
import cv2 as cv
import numpy as np
flagMove = False
oldImg = None
startX,startY = -1,-1
endX,endY = -1,-1
b,g,r = 0,0,0
def create_demo():
global oldImg
# 创建一个500*500的白色背景图片
img = np.ones((500,500,3), dtype=np.uint8)*255
# 复制一个一样大小的白色背景图
oldImg = np.ones_like(img) * 255
# 创建一个窗口
cv.namedWindow('mouse_img')
# 监听这个窗口的鼠标事件
cv.setMouseCallback('mouse_img', draw_rectangle, img)
# 每10毫秒显示一次图片
while True:
cv.imshow("mouse_img", img)
# 监听每10毫秒是否按退出键
if cv.waitKey(10) & 0xFF == 27:
break
# 销毁所有窗口
cv.destroyAllWindows()
# 鼠标回调函数,绘制矩形
def draw_rectangle(event,x,y,flags,img):
global flagMove,startX,startY,endX,endY,oldImg,b,g,r
# 点击起点
if event == cv.EVENT_LBUTTONDOWN:
# 当前次鼠标左键开始坐标
startX,startY = x,y
# 开始后允许对移动中坐标进行记录
flagMove = True
# 产生随机颜色
b,g,r = np.random.randint(0,256,size=3)
b,g,r = int(b),int(g),int(r)
# 移动终点
if event == cv.EVENT_MOUSEMOVE and flagMove:
# 将上次绘制的结果给当前图片,为了将当前次移动过程中产生的绘制清除
img[:] = oldImg[:]
# 当前次移动结束的坐标
endX,endY = x,y
# 绘制移动中的当前矩形
cv.rectangle(img, (startX,startY), (endX,endY), (b,g,r), lineType=cv.LINE_AA)
# 最后终点
if event == cv.EVENT_LBUTTONUP:
# 当前次坐标点绘制结束坐标点,结束鼠标移动监听
endX,endY = x,y
flagMove = False
# 绘制当前次鼠标左键按下到放开起点和终点组成的矩形
cv.rectangle(img, (startX,startY), (endX,endY), (b,g,r), lineType=cv.LINE_AA)
# 保存当前次绘制的图片
oldImg[:] = img[:]
# 坐标点还原
startX,startY = -1,-1
endX,endY = -1,-1
if __name__ == "__main__":
create_demo()
4.2 代码解析
- 创建一个500*500的白色背景图片;
- 复制一个一样大小的白色背景图;
- 创建一个窗口,监听这个窗口的鼠标事件;
- 鼠标回调函数,绘制矩形;
- 当前次鼠标左键开始坐标;
- 开始后允许对移动中坐标进行记录;
- 产生随机颜色;
- 将上次绘制的结果给当前图片,为了将当前次移动过程中产生的绘制清除;
- 当前次移动结束的坐标,绘制移动中的当前矩形;
- 当前次坐标点绘制结束坐标点,结束鼠标移动监听;
- 绘制当前次鼠标左键按下到放开起点和终点组成的矩形;
- 保存当前次绘制的图片,坐标点还原;
- 每10毫秒显示一次图片;
- 监听每10毫秒是否按退出键;
- 销毁所有窗口。
4.3 实例运行结果
5. 注意
- 随机颜色的生成的时候,bgr的值必须是int类型;
- 每次绘制完成,必须对当前次绘制图片进行保存;
- 在移动过程中必须在绘制开始将上次绘制结果的图片覆盖给当前次,否则会出现移动一次一个矩形绘制;
- 可以使用鼠标监听事件方法实现图片截图,下一篇实战实现图片截图功能!