简介:本文围绕 OpenCV 在图像识别中的基础能力展开,系统梳理图像输入输出、窗口交互、绘图与数组处理等核心模块。读者可掌握常用接口的使用方式、参数要点与工程注意事项,为后续实现特征提取、目标检测和图像分类等视觉任务打下扎实基础。
图像识别通常指从图像或视频中提取有意义信息,并据此完成分类、检测、分割、跟踪等任务。OpenCV 作为一个广泛使用的计算机视觉库,并不直接提供完整的深度学习训练框架,但它在图像预处理、特征提取、目标区域定位、结果可视化以及视频流处理等环节中起着不可替代的作用。
在实际工程中,一个典型的图像识别流程往往包含以下步骤:
本文重点讨论 OpenCV 在上述流程中的基础能力,尤其是图像输入输出、窗口交互、绘图工具以及常用的 NumPy 数组操作。掌握这些内容是构建更复杂图像识别系统的前提。
OpenCV 提供 imread 函数将磁盘中的图片读取为内存中的 NumPy 数组。该函数的常用形式如下:
import cv2 as cvimg = cv.imread(path, flags)
其中 flags 控制读取模式:
0 表示灰度模式;1 表示彩色模式,默认值;-1 表示保留原始通道,包括透明度信息。读取后的图像以数组形式存在,彩色图像默认采用 BGR 通道顺序,而不是常见的 RGB 顺序。这一点在与其他库配合时尤其需要注意,避免颜色通道错位。
此外,工程经验表明,imread 对路径中的中文字符支持并不稳定,建议统一使用英文路径。读取失败时函数返回 None,因此在后续处理前必须进行判空处理,否则容易触发空指针或数组维度错误。
图像处理完成后,往往需要将结果写回磁盘。imwrite 函数支持根据扩展名自动选择编码格式:
cv.imwrite(save_path, img, [params])
对于 JPEG 格式,可以通过参数控制压缩质量,例如:
cv.imwrite("out.jpg", img, [cv.IMWRITE_JPEG_QUALITY, 80])
需要注意,JPEG 不支持透明通道,若图像包含 Alpha 通道,应保存为 PNG 格式。同时,保存路径也应尽量避免中文字符,以免出现写入失败或编码异常。
视频本质上是连续的图像帧序列。OpenCV 使用 VideoCapture 读取摄像头或视频文件:
cap = cv.VideoCapture(0) # 摄像头编号,也可传入视频文件路径ret, frame = cap.read()
ret 为布尔值,指示当前帧是否读取成功;frame 则是当前帧图像。处理完成后必须调用 release 释放资源,否则可能影响后续设备访问。
视频写入使用 VideoWriter,需要指定编码格式、帧率和分辨率:
fourcc = cv.VideoWriter_fourcc(*'mp4v')out = cv.VideoWriter("output.mp4", fourcc, fps, (w, h))out.write(frame)out.release()
分辨率必须与实际写入图像严格一致,否则可能导致视频文件无法正常播放。编码格式的选择会影响兼容性与文件大小,mp4v 是较为通用的方案之一。
imshow 用于在窗口中展示图像:
cv.imshow("window_name", img)
需要注意,调用 imshow 后必须配合 waitKey,否则窗口可能一闪而过。waitKey 返回按键的 ASCII 码,常用于设置显示时长或响应键盘操作:
key = cv.waitKey(0) # 0 表示永久等待
在 64 位系统中,返回值可能存在高位干扰,通常使用 key & 0xFF 进行判断。完成所有操作后,建议调用 destroyAllWindows 关闭窗口并释放相关资源。
在目标检测和标注场景中,人工选择感兴趣区域是一个常见需求。selectROI 允许用户通过鼠标框选矩形区域:
x, y, w, h = cv.selectROI("win", img)
返回值为矩形左上角坐标与宽高。框选后按回车确认,按 ESC 取消。
更灵活的方式是使用 setMouseCallback 绑定自定义回调:
def on_mouse(event, x, y, flags, param):if event == cv.EVENT_LBUTTONDOWN:print(x, y)cv.setMouseCallback("win", on_mouse)
回调函数必须使用固定参数顺序 (event, x, y, flags, param)。需注意,窗口必须先用 imshow 创建,否则绑定无法生效。
在图像识别流程中,将检测结果、关键点或区域边界直观绘制出来是必不可少的一环。OpenCV 提供了丰富的几何图形绘制接口。
cv.line(img, (x1, y1), (x2, y2), color, thickness)
thickness 设为 -1 时表示填充,具体行为可能因图形类型而异。
cv.rectangle(img, (x1, y1), (x2, y2), color, thickness)
其中 (x1, y1) 为左上角,(x2, y2) 为右下角。该函数常用于标注检测框。
cv.circle(img, (cx, cy), r, color, thickness)
适用于关键点展示、热点标记等场景。
cv.putText(img, text, (x, y), font, scale, color, thickness)
OpenCV 内置字体默认不支持中文显示,如需输出中文,需要引入额外的字体库并配合其他绘图方案。
cv.drawContours(img, contours, idx, color, thickness)
idx 设为 -1 时绘制全部轮廓。轮廓通常由边缘检测或连通域分析得到,是形状分析与目标分割的重要输入。
OpenCV 中的图像本质上就是 NumPy 数组,因此熟练使用 NumPy 是高效处理图像的关键。创建空白图像的常用命令为:
import numpy as nparr = np.zeros((H, W, C), dtype=np.uint8)
其中 H 为高度,W 为宽度,C 为通道数。数据类型必须为 uint8,这是 OpenCV 图像处理的默认像素表示方式。通道数需要与原图匹配,例如灰度图为 1,彩色图为 3,带透明通道的图像为 4。
在图像拼接、掩膜生成、像素级操作以及特征图后处理中,NumPy 的广播机制、切片操作和条件筛选都能显著简化代码逻辑。
将上述基础能力整合到图像识别项目时,以下建议有助于提升代码健壮性与可维护性:
release,窗口使用后调用销毁函数;OpenCV 为图像识别提供了从数据接入、预处理到结果展示的完整基础能力。掌握其图像输入输出、窗口交互、绘图工具以及 NumPy 数组操作,是构建更加复杂视觉系统的第一步。后续无论采用传统特征提取方法,还是结合深度学习模型进行推理,这些基础模块都会反复出现。对于希望深入图像识别领域的开发者来说,扎实掌握这些内容具有长期价值。