OpenCV-基础篇

1.创建和显示窗口

1. cv2.namedWindow(winname, flags)

  • 作用 :提前创建窗口,自定义窗口属性;不调用此函数直接imshow会生成默认不可缩放窗口
  • 参数:
    • winname:窗口唯一名称,后续操作窗口都靠名称匹配
    • flags窗口模式:
      • cv2.WINDOW_NORMAL:窗口可拖拽缩放
      • cv2.WINDOW_AUTOSIZE:默认,自适应图像大小,不能手动拉伸
      • cv2.WINDOW_FREERATIO:自由比例缩放,不受原图比例限制

2. cv2.resizeWindow(winname, width, height)

  • 作用:强制设置窗口像素宽高,仅对WINDOW_NORMAL模式窗口生效
  • 注意:数值是窗口尺寸,不是图片分辨率

3. cv2.imshow(winname, mat)

  • 作用:在指定窗口渲染图像
  • mat=0:代表创建一张全黑空白单通道画布;正常使用时传入读取的图片矩阵,如cv2.imread("test.jpg")

4. cv2.waitKey(delay)

  • delay:等待毫秒数,0代表无限等待按键;1持续刷新监听
  • & 0xFF:兼容 64 位系统,只取按键 ASCII 低 8 位,避免数值异常
  • 常用按键 ASCII:q=113esc=27

5. cv2.destroyWindow(winname) / cv2.destroyAllWindows()

  • destroyWindow:关闭指定名称窗口
  • destroyAllWindows():一次性关闭所有 OpenCV 窗口(推荐收尾使用)

cv2.waitKey() 返回的是数字 ASCII 码,不是字符串

key == 'q' 永远不成立,'q' 的 ASCII 码是 113 ,应该判断数字 113ord('q')

2.图片的读取

python运行

复制代码
image = cv2.imread(filename, flags=cv2.IMREAD_COLOR)
  1. 参数 1 filename 文件路径

    • 代码中使用原始字符串 r"路径",避免 Windows 反斜杠\转义报错,推荐写法;
    • 支持绝对路径(如截图完整 C 盘路径)、相对路径;
    • ⚠️常见坑:路径包含中文 / 空格、文件不存在、后缀写错,都会返回None,窗口显示空白。
  2. 参数 2 flags 读取模式(可选)

    表格

    参数 效果
    cv2.IMREAD_COLOR 默认 彩色图,丢弃透明度通道
    cv2.IMREAD_GRAYSCALE 以灰度单通道读取
    cv2.IMREAD_UNCHANGED 完整读取,保留透明 Alpha 通道

3.图片的保存

函数作用

将内存中的图像矩阵写入本地磁盘,保存为图片文件。

语法

python

运行

复制代码
cv2.imwrite(filename, img, params=None)
  1. filename:保存路径 + 文件名(代码:../data/1.png
    • ../ 代表上级目录 ,表示在代码文件的上一层新建data文件夹,输出1.png
    • 支持相对路径、绝对路径;支持格式:png/jpg/bmp/tiff 等;
    • ⚠️关键坑:路径中不存在 data 文件夹会保存失败,不会自动创建目录。
  2. img:要保存的图像矩阵 必须是cv2.imread()读取得到的 numpy 数组,不能传 None。
  3. params(可选) :图片质量压缩参数
    • JPG:[cv2.IMWRITE_JPEG_QUALITY, 0~100] 数值越大画质越高
    • PNG:[cv2.IMWRITE_PNG_COMPRESSION, 0~9] 数值越大压缩率越高

返回值

布尔值:True保存成功;False保存失败(目录不存在、矩阵为空、格式不支持)。v

4.视频的采集

语法与参数

python

运行

复制代码
cap = cv2.VideoCapture(source)
  1. source=0(代码中使用) 代表读取本机默认摄像头设备;
    • 外接多摄像头可填 1、2... 切换设备;
    • 传入视频文件路径字符串(如test.mp4)可读取本地视频;
    • 传入网络 RTSP/RTMP 流地址可读取监控视频流。
  2. 返回值 cap:视频捕获对象,用于读取帧、释放设备、获取视频参数。

关键判断方法

cap.isOpened():返回布尔值,判断摄像头 / 视频是否成功打开,防止设备占用、找不到设备报错。

ret, frame = cap.read()

  • 作用:读取视频下一帧画面
  • 返回两个参数:
    1. ret:布尔值,True正常读到帧;False视频结束 / 摄像头断开 / 读取失败
    2. frame:numpy 图像矩阵(BGR 三通道),无画面时为None
  • 循环核心逻辑,视频 / 摄像头必备

5.视频文件的读取

6.视频的录制以及保存

要设计好编码方式以及分辨率大小要和设备相适应,不然会损坏文件格式,导致文件不能读取

一、红框 1:cv2.VideoWriter_fourcc(*'mp4v')

作用

生成视频编码格式的 4 字节标识符(FourCC 编码),用于指定输出视频的压缩标准。

参数说明

  • *'mp4v':解包字符串,代表 MPEG-4 编码,配套后缀.mp4,兼容性最强;
  • 其他常用编码:
    • *'XVID' → 输出.avi
    • *'avc1' → H.264 高清 mp4

返回值

数字编码 ID,作为VideoWriter的入参。

二、红框 2:获取摄像头分辨率 + cv2.VideoWriter()

1. 分辨率读取 API cap.get()

python

运行

复制代码
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
  • cap.get(属性ID):读取视频捕获设备参数
  • cv2.CAP_PROP_FRAME_WIDTH/HEIGHT:获取摄像头原生宽高
  • 必须转int,返回值默认浮点型

2. cv2.VideoWriter(保存路径, fourcc, fps, (width,height)) 视频写入器构造函数

参数逐项解析:

  1. '../data/4.mp4':输出视频相对路径;data 文件夹不存在会录制失败
  2. fourcc:第一步生成的编码标识符
  3. 20.0:录制帧率 20fps,要和摄像头实际帧率匹配,画面才不会变速
  4. (w, h):输出视频分辨率,必须和写入的 frame 尺寸完全一致,否则保存黑屏

返回值

vw视频写入对象,所有保存操作依赖该对象。

三、红框 3:vw.write(frame)

作用

将单帧图像矩阵写入视频文件流,循环执行即可拼接成完整视频。

要求

传入的frame必须是 BGR 三通道图像,尺寸严格等于VideoWriter初始化设置的(w,h)

四、红框 4:vw.release()

核心作用

关闭视频文件流,完成文件封装、写入磁盘缓存; ⚠️ 必写:不调用该函数,视频文件会损坏、无法打开。

7.设置鼠标监听事件

一、红框 1:鼠标回调函数 def mouse_callback(event, x, y, flags, userdata)

函数固定参数(5 个参数顺序不可改变)

  1. event:鼠标事件类型(整数常量)

    表格

    常量 含义
    cv2.EVENT_LBUTTONDOWN 左键按下
    cv2.EVENT_RBUTTONDOWN 右键按下
    cv2.EVENT_MBUTTONDOWN 中键按下
    cv2.EVENT_MOUSEMOVE 鼠标移动
    cv2.EVENT_LBUTTONUP 左键松开
    cv2.EVENT_MOUSEWHEEL 滚轮滚动
  2. x, y:鼠标当前在窗口图像上的像素坐标

  3. flags:按键标记,判断是否按住 Ctrl/Shift/ 鼠标左右键等组合操作

  4. userdatasetMouseCallback 传入的自定义额外参数,无需求可传None

代码作用

触发鼠标动作时自动执行此函数,示例中直接打印所有参数查看鼠标状态。


二、红框 2:绑定鼠标回调 cv2.setMouseCallback(windowName, mouse_callback, param=None)

参数解析

  1. windowName:要监听鼠标的窗口名称,必须和namedWindow创建的窗口名完全一致(图中mouse
  2. mouse_callback:自定义鼠标回调函数名(无需加括号,只传函数引用)
  3. param(可选):传给回调函数第 5 个参数userdata的自定义数据

核心功能

将自定义鼠标处理函数和指定窗口绑定,窗口内所有鼠标动作都会自动触发回调函数。


三、红框 3:创建空白画布 img = np.zeros((600, 800, 3), dtype=np.uint8)

依赖 numpy 库生成黑色图像矩阵,作为鼠标操作的背景面板:

  1. (600, 800, 3):形状 (高度h, 宽度w, 通道数),600 行 800 列 3 通道彩色图
  2. np.uint8:像素数据类型,取值 0~255,OpenCV 图像标准类型
  3. np.zeros:全部像素初始化为 0,即纯黑色画布

8.创建trackbar函数

一、第一组红框:cv2.createTrackbar() 创建滑动条

函数语法

python

运行

复制代码
cv2.createTrackbar(trackbarName, windowName, value, count, onChange)

参数拆解

  1. trackbarName:滑动条名称(图中R/G/B,用于后续读取数值)
  2. windowName:绑定到的窗口名称,必须和namedWindow窗口名完全一致(图中trackbar
  3. value:滑动条初始默认值(代码截图省略,一般填 0)
  4. count:滑动条最大值,调色场景固定 255(像素 0~255)
  5. onChange:滑动拖动时触发的回调函数,代码中传入callback空函数pass

作用

在指定窗口顶部生成可视化拖动滑块,用于动态调节数值。

二、第二组红框:img = np.zeros((512, 512, 3), np.uint8) 创建调色画布

基于 NumPy 生成彩色黑色底板:

  1. (512, 512, 3)(高度,宽度,通道数),512×512 三通道彩色图
  2. np.uint8:像素标准数据类型,取值 0~255
  3. 初始全 0,默认纯黑色,后续用滑动条 RGB 数值覆盖底色

三、第三组红框:cv2.getTrackbarPos() 读取滑块数值

函数语法

python

运行

复制代码
val = cv2.getTrackbarPos(trackbarname, winname)

参数拆解

  1. trackbarname:滑动条名称,和createTrackbar第一个参数对应(R/G/B
  2. winname:窗口名称

返回值

当前滑块拖动到的整数数值(0~255)

代码逻辑

python

运行

复制代码
r = cv2.getTrackbarPos('R','trackbar')
g = cv2.getTrackbarPos('G','trackbar')
b = cv2.getTrackbarPos('B','trackbar')

实时获取红、绿、蓝三个通道的滑块值。

四、第四组红框:画布赋值与窗口渲染

python

运行

复制代码
img[:] = np.array([b, g, r])
cv2.imshow('trackbar', img)
  1. img[:] = np.array([b,g,r]) OpenCV 图像通道顺序是BGR,所以赋值顺序为蓝、绿、红;整幅画布所有像素统一设置为当前滑块组合的颜色。
  2. cv2.imshow:循环刷新窗口,实时展示调色后的画布。

9.颜色空间转换

复制代码
import cv2
# 滑动条必填空回调
def callback(val):
    pass
# 1. 创建窗口+读取图片
cv2.namedWindow('color', cv2.WINDOW_NORMAL)
img = cv2.imread('../data/1.png')
# 判空,防止图片找不到报错
if img is None:
    print("图片文件不存在!")
    exit()

# 2. 定义所有颜色转换规则
colorspaces = [
    cv2.COLOR_BGR2RGBA,
    cv2.COLOR_BGR2BGRA,
    cv2.COLOR_BGR2GRAY,
    cv2.COLOR_BGR2HSV,
    cv2.COLOR_BGR2YUV
]

# 3. 创建滑动条 范围0~4
cv2.createTrackbar('curcolor', 'color', 0, 4, callback)

# 4. 循环切换颜色空间
while True:
    index = cv2.getTrackbarPos('curcolor', 'color')
    # 颜色转换核心
    cvt_img = cv2.cvtColor(img, colorspaces[index])
    cv2.imshow('color', cvt_img)

    key = cv2.waitKey(10)
    if key & 0xFF == ord('a'):
        break

cv2.destroyAllWindows()

二、颜色空间转换常量数组

python

运行

复制代码
# 定义列表,存放5种BGR转其他空间的转换标识
colorspaces = [
    cv2.COLOR_BGR2RGBA,   # 0:BGR → RGBA(带透明通道4通道)
    cv2.COLOR_BGR2BGRA,   # 1:BGR → BGRA(自带透明通道4通道)
    cv2.COLOR_BGR2GRAY,   # 2:BGR → 灰度单通道
    cv2.COLOR_BGR2HSV,    # 3:BGR → HSV(色相饱和度,图像分割常用)
    cv2.COLOR_BGR2YUV     # 4:BGR → YUV(视频、摄像头图像处理)
]

列表下标 0、1、2、3、4 对应 5 种转换方式,后面用滑动条数值选取。

三、创建滑动条 Trackbar

python

运行

复制代码
# 创建名为curcolor的滑块,绑定color窗口
# 初始值0,最大值4,拖动触发callback函数
cv2.createTrackbar('curcolor', 'color', 0, 4, callback)
  • 最大值设为 4,刚好匹配数组colorspaces长度(下标 0~4),拖动滑块取值对应转换方式。
  • callback:必须提前定义空回调函数,示例最简写法:def callback(val): pass

四、循环核心逻辑(滑动条联动颜色转换)

python

运行

复制代码
while True:
    # 1. 获取当前滑块数值 0~4
    index = cv2.getTrackbarPos('curcolor', 'color')
    
    # 2. 核心API:cv2.cvtColor 颜色空间转换
    cvt_img = cv2.cvtColor(img, colorspaces[index])
    
    # 3. 渲染转换后的图像
    cv2.imshow('color', cvt_img)
    
    # 等待10ms按键输入
    key = cv2.waitKey(10)
    print(key)
    # 按下a键退出循环
    if key & 0xFF == ord('a'):
        break

核心 API:cv2.cvtColor(src, code)

  1. src :原始图像(这里是读取的 BGR 原图img
  2. code :转换编码(列表colorspaces里的常量)
  3. 返回值:转换后新图像矩阵cvt_img

滑动条联动逻辑

  • 滑块拖到 0 → colorspaces[0]COLOR_BGR2RGBA
  • 滑块拖到 2 → colorspaces[2]COLOR_BGR2GRAY 灰度图
  • 滑块拖到 3 → colorspaces[3] → HSV 颜色空间

各个颜色空间作用通俗解释

表格

转换常量 输出通道 用途
COLOR_BGR2RGBA 4 通道 (R+G+B + 透明) 前端图片、透明贴图
COLOR_BGR2BGRA 4 通道 (B+G+R + 透明) OpenCV 原生透明图
COLOR_BGR2GRAY 单通道灰度 轮廓检测、人脸识别、简化计算
COLOR_BGR2HSV 3 通道 (H 色相,S 饱和度,V 明度) 颜色筛选、目标跟踪(提取红色 / 蓝色物体)
COLOR_BGR2YUV 3 通道 (Y 亮度,U/V 色度) 摄像头、视频流处理,降低亮度干扰

效果如图所示

10.深拷贝与浅拷贝

1. 浅拷贝(你的代码 image2 = image

python

运行

复制代码
image2 = image
  1. 只复制栈内存的引用指针,不会新开像素存储内存;
  2. imageimage2 指向同一块像素堆内存
  3. 任意一个变量修改像素,另一个同步变化;
  4. 开销极小,只复制表头信息,不复制图像像素。

流程图:

plaintext

复制代码
image 指针 ──┐
             ├─→ 同一份像素数据内存
image2指针 ──┘

2. 深拷贝(完全独立新图像)

使用 .copy() 方法开辟全新像素内存:

python

运行

复制代码
image2 = image.copy()
  1. 复制栈表头信息 + 完整复制堆里全部像素数据
  2. imageimage2 是两块完全独立内存;
  3. 修改任意一张图,另一张完全不受影响;
  4. 开销更大,大图复制会占用双倍内存。

11.通道的分割与合并

cv2.line 官方函数原型

python

运行

复制代码
cv2.line(img, pt1, pt2, color, thickness=None, lineType=None, shift=None)

逐个参数拆解:

1. img

  • 类型:numpy.ndarray(OpenCV 图像数组)
  • 含义:要绘制线条的目标图像画布,绘图会直接修改这张图(浅拷贝原地修改)
  • 你的代码:img = np.zeros((512,512,3), np.uint8) 黑色画布作为绘图载体

2. pt1

  • 类型:元组 (x1, y1)
  • 含义:直线起点坐标
  • 图像坐标系规则:
    • 图片左上角是原点 (0,0)
    • x 轴:水平向右(列)
    • y 轴:垂直向下(行)
  • 你的代码:(100, 100) → 起点:横向 100,纵向 100

3. pt2

  • 类型:元组 (x2, y2)
  • 含义:直线终点坐标
  • 你的代码:(200, 200) → 终点:横向 200,纵向 200

4. color

  • 类型:元组 (B, G, R)
  • 重点:OpenCV 颜色通道顺序是 BGR,不是 RGB!
  • 你的代码:(0,0,255)
    • B=0,G=0,R=255 → 纯红色线条
    • 举例:(255,0,0)= 蓝色,(0,255,0)= 绿色,(255,255,255)= 白色

5. thickness

  • 类型:整数
  • 含义:线条粗细像素值
  • 你的代码:5 → 线条宽度 5 个像素
  • 补充:如果填负数,不会变成空心,line()仅支持实线粗细,填充图形(矩形 / 圆)才支持 - 1 填充。

6. lineType(你代码里传的 4)

线条渲染类型,抗锯齿 / 普通直线模式:

表格

参数值 常量名 效果说明
4 cv2.LINE_4 4 连通直线,锯齿明显,速度快
8 cv2.LINE_8 8 连通直线,默认值,锯齿轻微
16 cv2.LINE_AA 抗锯齿直线,线条最平滑,计算稍慢

你代码里写 4 = cv2.LINE_4,使用 4 邻域插值绘制直线。

7. shift(可选,你没传)

坐标小数精度缩放,默认 0;用于亚像素高精度绘图,日常开发几乎不用。

12.画椭圆

cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness, lineType, shift)

1. img

  • 含义:画布图像,numpy.ndarray 数组
  • 作用:椭圆 / 椭圆弧会直接绘制在这张图上,原地修改。

2. 中心点 center

  • 格式:元组 (x, y)
  • 含义:椭圆几何中心的像素坐标,图像坐标系原点在左上角,x 向右、y 向下。

3. 长宽的一半 axes

  • 格式:元组 (半长轴, 半短轴)
  • 关键点:是轴长的一半(半径),不是完整直径
    • axes=(100,50) → 椭圆完整宽度 200,高度 100。

4. 角度 angle

单位:度(°)

  • 含义:椭圆整体绕中心点逆时针旋转的角度。
  • 示例:angle=30 → 椭圆本体倾斜 30 度。

5. 从哪个角度开始 startAngle

6. 到哪个角度结束 endAngle

单位:度(°),用来控制绘制一段椭圆弧,而非完整椭圆

  • 基准 0°:旋转后椭圆的右侧水平端点(x 轴正方向)
  • 绘制方向:从 startAngle 逆时针走到 endAngle
    • startAngle=0, endAngle=360:绘制完整闭合椭圆
    • startAngle=0, endAngle=180:只画上半椭圆弧

后置可选参数(图片未标出)

  1. color:绘制颜色,单通道灰度填数值,彩色图填 (B,G,R)
  2. thickness:轮廓线宽度
    • 正数:空心轮廓;-1/cv2.FILLED:填充椭圆
  3. lineType:线条抗锯齿类型(默认 8 邻域)
  4. shift:坐标小数精度,日常绘图填 0 即可

13.绘制多边形

函数原型(Python)

python

运行

复制代码
cv2.polylines(img, pts, isClosed, color, thickness, lineType, shift)

图片中标注了前 4 个核心参数,后面为可选绘图参数。

参数逐句对应解析

1. img

画布图像(numpy 数组),绘制的折线 / 多边形会直接修改该图像。

2. pts 点集

  • 格式要求:三维数组 [[[x1,y1],[x2,y2],[x3,y3]]],支持同时绘制多个多边形(多组点嵌套)
  • 含义:按顺序连接的顶点坐标列表,绘图顺序严格按照数组内点的先后顺序连线。

3. isClosed 是否闭环

  • True:自动把最后一个顶点和第一个顶点相连,形成闭合多边形
  • False:仅按顺序连接顶点,只绘制开放折线,首尾不相连

4. color 颜色

彩色图像传入 (B, G, R) 元组;灰度图传入单通道数值。

末尾可选参数(... 省略部分)

  1. thickness:线条宽度,只能为正数 ,该函数无法填充图形(填充多边形使用 cv2.fillPoly()
  2. lineType:线条渲染类型,默认 8 邻域,cv2.LINE_AA 开启抗锯齿
  3. shift:坐标小数精度,常规绘图填 0 即可

14.绘制文本

完整函数原型(Python)

python

运行

复制代码
cv2.putText(img, text, org, fontFace, fontScale, color, thickness, lineType, bottomLeftOrigin)

图片中标注了前 5 个核心参数,剩余为可选参数。

参数逐段对应解析

1. img

画布图像(numpy 数组),文字会直接绘制在该图像上,原地修改。

2. text 字符串

需要绘制的文字内容; ⚠️ 限制:OpenCV 原生仅支持英文、数字、符号,直接传入中文会乱码,中文需借助 PIL 或加载自定义字体实现。

3. org 启始点

坐标元组 (x, y); 坐标系规则:默认该点是文字左下角(图像原点左上角,x 向右、y 向下)。

4. fontFace 字体

OpenCV 内置字体常量,常用值:

  • cv2.FONT_HERSHEY_SIMPLEX:常规无衬线字体
  • cv2.FONT_HERSHEY_PLAIN:小号细字体
  • cv2.FONT_HERSHEY_DUPLEX:加粗字体
  • cv2.FONT_HERSHEY_SCRIPT_SIMPLEX:手写花体

5. fontScale 字号

字体缩放系数,浮点数;

  • 1.0 = 默认标准大小
  • >1 放大文字,<1 缩小文字

图片省略的可选参数

  1. color:文字颜色,彩色图传 (B,G,R),灰度图传单数值
  2. thickness:文字线条粗细,正数;填 -1 无填充效果
  3. lineType:线条抗锯齿,推荐 cv2.LINE_AA 消除锯齿
  4. bottomLeftOrigin:布尔值,默认False;设为True时,org变为文字左上角基准点

15.综合案例

复制代码
import math

import cv2
import numpy as np

'''
基本功能:
1.按住l键,可以画线
2.按住r键盘,可以画矩形
3.按下c键,可以画圆
'''
curshape = 0
startpos = (0,0)
#创建面板
cv2.namedWindow('drawshape', cv2.WINDOW_NORMAL)
#显示窗口和背景
img = np.zeros((600, 800, 3), dtype=np.uint8)
#设置回调函数
def mouse_callback(event, x, y, flags, userdata):
    global startpos, curshape, img
    if event == cv2.EVENT_LBUTTONDOWN:
        startpos = (x,y)
    elif event == cv2.EVENT_LBUTTONUP:
        if curshape ==0:
            cv2.line(img,startpos,(x,y),(0,0,255))
        elif curshape ==1:
            cv2.rectangle(img,startpos,(x,y),(0,0,255))
        elif curshape ==2:
            a=x-startpos[0]
            b=y-startpos[1]
            r=int(math.sqrt(a**2+b**2))
            cv2.circle(img,startpos,r,(0,0,255))
    # print(event,x,y,flags,userdata)
# 设置鼠标回调函数
cv2.setMouseCallback('drawshape', mouse_callback)

while True:
    cv2.imshow('drawshape',img)
    key=cv2.waitKey(1) & 0xFF
    if key == ord('q'):
        break
    elif key == ord('l'):
        curshape = 0
    elif key == ord('r'):
        curshape = 1
    elif key == ord('c'):
        curshape = 2


cv2.destroyAllWindows()

1. 为什么只执行一次就永久监听?

这个函数的作用是注册绑定

  1. 你告诉 OpenCV:名为drawshape的窗口,后续所有鼠标动作,统一交给mouse_callback函数处理;
  2. 注册完成后,OpenCV 内部会单独维护一套鼠标消息监听机制,和你的while主循环完全分开;
  3. 只要窗口不关闭,鼠标事件会持续自动触发回调,不需要重复注册。

如果错误放进 while 循环会发生什么?

python

运行

复制代码
# 错误写法,千万不要这么写
while True:
    cv2.setMouseCallback('drawshape', mouse_callback)
    cv2.imshow(...)

每 1ms 就重复绑定一次回调,造成:

  • 资源冗余,程序卡顿;
  • 多次重复绑定,鼠标一次动作会多次执行绘图逻辑;
  • 无任何收益,纯浪费性能。

2. 两种监听的核心区别(帮你巩固理解)

鼠标监听(setMouseCallback)

  • 模式:事件驱动、被动监听
  • 执行时机:程序启动只调用 1 次注册;鼠标操作时系统自动调用回调
  • 位置:写在while True循环外部

键盘监听(cv2.waitKey)

如果错误放进 while 循环会发生什么?

python

运行

复制代码
# 错误写法,千万不要这么写
while True:
    cv2.setMouseCallback('drawshape', mouse_callback)
    cv2.imshow(...)

每 1ms 就重复绑定一次回调,造成:

2. 两种监听的核心区别(帮你巩固理解)

鼠标监听(setMouseCallback)

键盘监听(cv2.waitKey)

  • 模式:轮询、主动查询

  • 执行时机:必须放在循环内部,每隔 1ms 主动询问一次键盘有没有按键

  • 位置:写在while True循环内部

    1. 为什么只执行一次就永久监听?

    这个函数的作用是注册绑定

  • 你告诉 OpenCV:名为drawshape的窗口,后续所有鼠标动作,统一交给mouse_callback函数处理;

  • 注册完成后,OpenCV 内部会单独维护一套鼠标消息监听机制,和你的while主循环完全分开;

  • 只要窗口不关闭,鼠标事件会持续自动触发回调,不需要重复注册。

  • 资源冗余,程序卡顿;

  • 多次重复绑定,鼠标一次动作会多次执行绘图逻辑;

  • 无任何收益,纯浪费性能。

  • 模式:事件驱动、被动监听

  • 执行时机:程序启动只调用 1 次注册;鼠标操作时系统自动调用回调

  • 位置:写在while True循环外部

  • 模式:轮询、主动查询

  • 执行时机:必须放在循环内部,每隔 1ms 主动询问一次键盘有没有按键

  • 位置:写在while True循环内部

相关推荐
程序员老猫3 小时前
当 AI 能写 80% 的代码时,后端工程师的核心价值还剩什么?
人工智能
想会飞的蒲公英3 小时前
计算机怎样读取中文文本:编码、清洗与标准化
人工智能·python·自然语言处理
CIO_Alliance3 小时前
AI+iPaaS解决方案深度整合:让跨系统业务流程自动化一步到位
人工智能·ipaas·系统集成·ai+ipaas·企业cio联盟·企业级ai化转型
苏州IT威翰德3 小时前
算力资产“续命”专家:苏州威翰德科技赋能NVIDIA高端AI芯片芯片级维修
大数据·人工智能
天上路人4 小时前
A59P双波束语音模块:神经网络降噪在远场拾音中的工程实现分析
人工智能·深度学习·神经网络·ai降噪·ai语音·麦克风·回音消除
冬奇Lab4 小时前
AI 评测系列(03):LLM-as-Judge——让 LLM 评价 LLM 的正确姿势
人工智能·llm
Miao121314 小时前
某海外住宿平台如何在大规模场景下实现指标一致性:Minerva 指标平台实践
大数据·数据库·人工智能
冬奇Lab4 小时前
每日一个开源项目(第164篇):毕昇(BISHENG)- 面向企业的开源 LLM DevOps 平台
人工智能·开源·agent
深度研习笔记4 小时前
OpenCV工业视觉实战09|项目EXE打包+工控机无环境部署+后台常驻运行,彻底脱离Python环境,完成项目最终交付
python·opencv·webpack
声讯电子5 小时前
录音笔AI降噪方案:从录得到到听得清的听觉革命
人工智能·语音识别