OpenCV-python小玩意2 摄像头预览时画线以及line的用法
0.我要做什么?
用OpenCV启动摄像头后,在预览界面用鼠标点击两点,画一条线。
1.初步方案或待解决的问题
本文依然是原型阶段,使用Python版的OpenCV。
画线的工作可以使用cv2.line方法;
鼠标事件使用setMouseCallback回调,监听左键下落事件。
整个流程简单描述为:
开始—监听鼠标—摄像头启动—记录鼠标左键按下的坐标—满足两点坐标,进行画线
2.函数介绍
2.1 cv2.line()
画线操作在图像处理中属于必备技能,函数原型如下:
cv2.line(img, pt1, pt2, color, thickness=None, lineType=None, shift=None)
参数说明如下:
参数 | 类型 | 描述 | 默认值 |
---|---|---|---|
img | ndarray | 要在其上绘制直线的目标图像(numpy 数组) | 无 |
pt1 | tuple | 直线起点坐标 (x1, y1) | 无 |
pt2 | tuple | 直线终点坐标 (x2, y2) | 无 |
color | tuple | 直线颜色 (B, G, R) 格式 | 无 |
thickness | int | 直线宽度(像素) | 1 |
lineType | int | 直线类型: - cv2.LINE_4 : 4-connected 线- cv2.LINE_8 : 8-connected 线- cv2.LINE_AA : 抗锯齿线 | cv2.LINE_8 |
shift | int | 坐标点的小数位数 | 0 |
使用方法,咱举个栗子:
import cv2
import numpy as np# 创建空白图像
image = np.zeros((400, 600, 3), dtype=np.uint8)# 水平红线(起点(100,200),终点(500,200))
cv2.line(image, (100, 200), (500, 200), (0, 0, 255), 2)# 垂直线(起点(300,100),终点(300,300))
cv2.line(image, (300, 100), (300, 300), (0, 255, 0), 3)# 对角线(蓝色,抗锯齿)
cv2.line(image, (100, 100), (500, 300), (255, 0, 0), 2, cv2.LINE_AA)# 显示结果
cv2.imshow('Lines Example', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
需要注意:
- 坐标系统:
- 原点在左上角 (0, 0)
- 坐标使用整数元组 (x, y)
- x 轴向右递增
- y 轴向下递增
- 颜色表示:
- 使用 BGR 格式(不是常见的 RGB)
- 每个通道值在 0-255 范围内,比如(0, 0, 255) 表示红色
- 线型选择:
- LINE_4:4-connected 线(快速绘制,锯齿明显)
- LINE_8:8-connected 线(默认,效果较好)
- LINE_AA:抗锯齿线(平滑效果,但计算量稍大)
2.2 cv2.setMouseCallback()
该方法用来处理鼠标的回调,它的函数原型如下:
cv2.setMouseCallback(windowName, onMouse, userdata=None)
参数说明:
windowName
(str): 目标窗口名称。需与cv2.namedWindow()
或cv2.imshow()
的窗口名严格一致。onMouse
(function):️ 鼠标回调函数,需按固定格式定义:
def onMouse(event, x, y, flags, userdata): ...
userdata
(可选): 向回调函数传递额外数据(如图像对象、类实例等),类型为void*
(Python中用None
或对象)。
2.3 回调函数onMouse()
监听鼠标事件的回调函数,需要开发者自己定义,原型如下:
def onMouse(event, x, y, flags, userdata):
参数说明:
event
(int): 鼠标事件类型,常用值如下:
事件类型 | 值 | 说明 |
---|---|---|
cv2.EVENT_MOUSEMOVE | 0 | 鼠标移动 |
cv2.EVENT_LBUTTONDOWN | 1 | 左键按下 |
cv2.EVENT_LBUTTONUP | 4 | 左键释放 |
cv2.EVENT_RBUTTONDOWN | 2 | 右键按下 |
cv2.EVENT_LBUTTONDBLCLK | 7 | 左键双击 |
cv2.EVENT_MOUSEWHEEL | 10 | 滚轮滚动 |
x, y
(int): 鼠标在图像坐标系中的坐标。flags
(int): 组合状态标志,常用值如下:
标志位 | 值 | 说明 |
---|---|---|
cv2.EVENT_FLAG_LBUTTON | 1 | 左键拖拽中 |
cv2.EVENT_FLAG_CTRLKEY | 8 | 按下 Ctrl 键 |
cv2.EVENT_FLAG_SHIFTKEY | 16 | 按下 Shift 键 |
userdata
: 接收setMouseCallback
传递的额外数据。
3.代码实现
import cv2points = [] # 存储坐标点def mouse_draw(event, x, y, flags, param):global pointsif event == cv2.EVENT_LBUTTONDOWN:points.append((x, y)) # 添加当前点到列表cv2.namedWindow('image')
cv2.setMouseCallback('image', mouse_draw)
cap = cv2.VideoCapture(1) # 0是默认的,这里使用外接摄像头while True:ret, frame = cap.read()if not ret:break# 绘制所有线段if len(points) >= 2:for i in range(1, len(points)):cv2.line(frame, points[i - 1], points[i], (255, 0, 0), 2)cv2.imshow('image', frame)key = cv2.waitKey(30)if key == ord('q'):breakelif key == ord('c'): # 清除功能points = []cap.release()
cv2.destroyAllWindows()
该程序也增加了键盘按键的响应,q键退出,c键清除屏幕的画线。
至此,我们又前进了一些,继续加油。
最终实现效果图: