导读
本教程将系统梳理 OpenCV 图像处理的核心知识点,并通过两个完整的实战项目——图像融合与噪声去除——来巩固所学。我们将基于 Python + OpenCV 环境,涵盖图像读取、几何变换、颜色空间、视频捕获、图像融合、噪声生成、滤波降噪等关键内容,每个知识点均配有 API 说明、参数详解与可运行的代码示例。
一、OpenCV 概述与环境准备
1.1 OpenCV 简介
OpenCV(Open Source Computer Vision Library)是一个开源的跨平台计算机视觉库,由 Intel 发起,支持 Windows、Linux、Android、macOS 等操作系统,提供 C++、Python、Java 等多语言接口。它包含 2500 多个 个优化算法,涵盖图像处理、视频分析、物体检测、机器学习、相机标定、3D 重建等众多领域。
1.2 Python 环境安装
在 Python 中使用 OpenCV 需安装opencv-python包:
pipinstallopencv-python# 核心模块pipinstallopencv-contrib-python# 含额外模块(推荐)pipinstallnumpy# 数组运算依赖本教程代码均需先执行import cv2与import numpy as np。
1.3 核心模块速览
| 模块 | 说明 | 常见用途 |
|---|---|---|
| core | 核心数据结构与基础运算 | Mat 数组、加法、位运算 |
| imgproc | 图像处理 | 滤波、几何变换、颜色空间、阈值 |
| videoio / highgui | 视频读写与图形界面 | 摄像头捕获、窗口显示 |
| imgcodecs | 图像编解码 | imread / imwrite |
| features2d | 特征检测与描述 | 角点、SIFT、ORB |
| dnn | 深度学习推理 | 加载预训练模型做检测分类 |
二、图像的读取、显示与保存
2.1 读取图像cv2.imread
语法:retval = cv2.imread(filename[, flags])
- 返回值:读取成功返回 NumPy 数组(BGR 通道顺序);文件不存在或路径错误时返回
None。
flags 读取标志详解
| 标志 | 数值 | 说明 |
|---|---|---|
cv2.IMREAD_COLOR | 1 | 彩色加载(默认),忽略 alpha 通道,3 通道 BGR |
cv2.IMREAD_GRAYSCALE | 0 | 灰度加载,单通道 |
cv2.IMREAD_UNCHANGED | -1 | 包含 alpha 通道的原始加载 |
cv2.IMREAD_REDUCED_COLOR_2 | 17 | 彩色加载并缩为 1/2 大小 |
cv2.IMREAD_REDUCED_GRAYSCALE_4 | 32 | 灰度加载并缩为 1/4 大小 |
注意:OpenCV 读取的图像通道顺序为BGR(蓝、绿、红),而非 RGB,在与 Matplotlib、PIL 交互时需用cv2.cvtColor转换。
2.2 显示图像cv2.imshow
语法:cv2.imshow(winname, mat)
winname:窗口名称(字符串),同名窗口只创建一次。mat:要显示的图像数组(NumPy ndarray)。
2.3 等待按键cv2.waitKey
语法:retval = cv2.waitKey([delay])
delay:等待按键的毫秒数。0表示无限等待直到有按键;正数表示等待指定毫秒。- 返回值:按下键的 ASCII 码;超时无按键返回
-1。
代码中两种典型用法:
# 用法一:阻塞显示单张图片,按任意键关闭cv2.waitKey(0)# 用法二:视频循环中非阻塞刷新,每 1ms 检测一次按键key=cv2.waitKey(1)&0xFFifkey==27:# 27 = ESC 键 ASCII 码break& 0xFF的作用:waitKey在某些系统返回 32 位整数,与0xFF按位与可截取低 8 位,保证跨平台获取正确的 ASCII 码。
2.4 关闭窗口cv2.destroyAllWindows
cv2.destroyAllWindows()销毁所有由 OpenCV 创建的窗口,释放资源。若只需关闭指定窗口可用cv2.destroyWindow(winname)。
2.5 保存图像cv2.imwrite
语法:retval = cv2.imwrite(filename, img[, params])
将图像保存到文件,返回布尔值表示是否成功。params可指定压缩质量等参数。
cv2.imwrite('output.jpg',img)# 默认质量cv2.imwrite('output.jpg',img,[cv2.IMWRITE_JPEG_QUALITY,95])# JPEG 质量 0-100cv2.imwrite('output.png',img,[cv2.IMWRITE_PNG_COMPRESSION,3])# PNG 压缩级 0-9三、图像几何变换 — 缩放
3.1cv2.resize详解
语法:dst = cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
| 参数 | 类型 | 说明 |
|---|---|---|
src | ndarray | 输入图像 |
dsize | tuple (w, h) | 目标尺寸;设为None时由fx/fy计算 |
fx | float | 水平缩放比例 |
fy | float | 垂直缩放比例 |
interpolation | int | 插值方法(见下表) |
注意:dsize的顺序是(width, height),而 NumPy 数组的shape是(height, width, channels),二者顺序相反,极易混淆,使用时需特别注意。
# 方式一:指定目标尺寸(宽, 高)img=cv2.resize(img,(640,480))# 方式二:按比例缩放(dsize 设 None)img=cv2.resize(img,None,fx=0.5,fy=0.5)# 缩小一半# 方式三:等比缩放,只指定宽h,w=img.shape[:2]new_w=640new_h=int(h*new_w/w)img=cv2.resize(img,(new_w,new_h))3.2 插值方法对比
缩放本质上是像素的重采样,不同插值方法在速度与质量间取舍:
| 插值方法 | 标志 | 适用场景 | 特点 |
|---|---|---|---|
| 最近邻插值 | cv2.INTER_NEAREST | 像素风格图、速度优先 | 最快,但放大后锯齿明显 |
| 双线性插值 | cv2.INTER_LINEAR | 通用默认(放大缩小均可用) | 质量与速度均衡,resize默认方法 |
| 双三次插值 | cv2.INTER_CUBIC | 高质量放大 | 更平滑,速度较慢 |
| Lanczos 插值 | cv2.INTER_LANCZOS4 | 高质量缩放 | 质量最高,速度最慢 |
| 区域插值 | cv2.INTER_AREA | 图像缩小(降采样) | 缩小首选,可避免摩尔纹 |
选择策略:缩小图像推荐INTER_AREA,放大图像推荐INTER_CUBIC或INTER_LANCZOS4。
四、颜色空间转换
4.1cv2.cvtColor详解
语法:dst = cv2.cvtColor(src, code[, dstCn])
src:输入图像。code:颜色空间转换标志码。dstCn:输出通道数,默认自动推断。
4.2 常见颜色空间
| 颜色空间 | 通道含义 | 典型用途 |
|---|---|---|
| BGR | 蓝、绿、红(OpenCV 默认) | OpenCV 读取与显示的默认格式 |
| GRAY | 单通道灰度 | 边缘检测、人脸检测预处理 |
| RGB | 红、绿、蓝 | Matplotlib 显示、PIL 交互 |
| HSV | 色相 H、饱和度 S、明度 V | 颜色分割、追踪特定颜色物体 |
| HLS | 色相 H、亮度 L、饱和度 S | 图像增强、亮度调整 |
| YCrCb | 亮度 Y、红/蓝色差 Cr/Cb | 肤色检测、视频压缩 |
| LAB | 亮度 L、a(绿红)、b(蓝黄) | 感知均匀、色彩差异计算 |
4.3 常用转换标志
| 转换标志 | 说明 |
|---|---|
cv2.COLOR_BGR2GRAY | BGR 转灰度(加权:0.299R+0.587G+0.114B) |
cv2.COLOR_GRAY2BGR | 灰度转 BGR(三通道值相同,仍为灰色) |
cv2.COLOR_BGR2RGB | BGR 转 RGB(交换 R/B 通道) |
cv2.COLOR_BGR2HSV | BGR 转 HSV |
cv2.COLOR_HSV2BGR | HSV 转 BGR |
cv2.COLOR_BGR2YCrCb | BGR 转 YCrCb |
灰度转换公式:Gray = 0.299*R + 0.587*G + 0.114*B,该权重源于人眼对绿色最敏感的视觉特性。
五、视频与摄像头捕获
5.1cv2.VideoCapture
VideoCapture是 OpenCV 用于视频捕获的类,可打开摄像头、视频文件或网络视频流。
# 打开默认摄像头(索引 0)cap=cv2.VideoCapture(0)# 打开第二个摄像头cap=cv2.VideoCapture(1)# 打开视频文件cap=cv2.VideoCapture('test.avi')# 打开网络流(RTSP/HTTP)cap=cv2.VideoCapture('rtsp://192.168.1.100:554/stream')5.2 读取帧cap.read()
语法:ret, frame = cap.read()
ret:布尔值,True表示成功读取一帧;False表示读取失败或视频结束。frame:当前帧图像(NumPy 数组,BGR 格式)。
视频本质上是连续的图像帧序列,循环调用read()即可逐帧处理。
5.3 获取与设置属性cap.get/cap.set
| 属性 | 标志 | 说明 |
|---|---|---|
| 宽度 | cv2.CAP_PROP_FRAME_WIDTH | 帧宽度(像素) |
| 高度 | cv2.CAP_PROP_FRAME_HEIGHT | 帧高度(像素) |
| 帧率 | cv2.CAP_PROP_FPS | 每秒帧数 |
| 总帧数 | cv2.CAP_PROP_FRAME_COUNT | 视频总帧数 |
| 亮度 | cv2.CAP_PROP_BRIGHTNESS | 摄像头亮度(仅摄像头) |
| 对比度 | cv2.CAP_PROP_CONTRAST | 摄像头对比度 |
# 获取帧率与总帧数fps=cap.get(cv2.CAP_PROP_FPS)total=cap.get(cv2.CAP_PROP_FRAME_COUNT)# 设置摄像头分辨率cap.set(cv2.CAP_PROP_FRAME_WIDTH,1280)cap.set(cv2.CAP_PROP_FRAME_HEIGHT,720)5.4 释放资源cap.release()
使用完毕后必须调用cap.release()释放摄像头或视频文件资源,否则设备将一直被占用,导致其他程序无法访问。
完整的视频处理标准流程:VideoCapture打开 → 循环read()→ 处理帧 →imshow显示 →waitKey控制刷新 →release()释放 →destroyAllWindows()关闭窗口。
六、图像融合技术
6.1 加权融合cv2.addWeighted
这是实战项目一的核心 API,将两幅图像按权重线性叠加。
语法:dst = cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst])
融合公式:dst = src1 * alpha + src2 * beta + gamma
| 参数 | 说明 |
|---|---|
src1 | 第一幅输入图像 |
alpha | 第一幅图像的权重(0~1) |
src2 | 第二幅输入图像 |
beta | 第二幅图像的权重(0~1) |
gamma | 加到总和上的标量亮度偏移(通常为 0) |
注意:两幅图像的尺寸和数据类型必须完全一致,否则会报错。
# alpha=0.5, beta=0.5, gamma=0 → 各占 50% 透明度color_merge=cv2.addWeighted(frame,0.5,bg_img,0.5,0)# 调整权重实现不同透明度效果merge=cv2.addWeighted(frame,0.7,bg_img,0.3,0)# 摄像头占 70%# 加入亮度偏移merge=cv2.addWeighted(frame,0.5,bg_img,0.5,30)# 整体提亮 306.2 其他图像运算方式
6.2.1 饱和加法cv2.add
对应像素相加,超过 255 则截断为 255(饱和运算),不会溢出回绕(即不会发生环绕)。
# 像素值 200 + 100 = 300 → 截断为 255dst=cv2.add(img1,img2)6.2.2 NumPy 加法(取模)
直接用+运算符,超过 255 取模(256 环绕为 0),可能导致颜色翻转。
# 像素值 200 + 100 = 300 % 256 = 44(颜色突变)dst=img1+img2# NumPy 加法6.2.3 图像减法cv2.subtract
对应像素相减,小于 0 则截断为 0(饱和运算)。
dst=cv2.subtract(img1,img2)# 饱和减法,负值截为 0dst=img1-img2# NumPy 减法,负值取模回绕6.2.4 位运算融合cv2.bitwise_*
通过掩膜(mask)实现图像的局部叠加,常用于水印、ROI 区域提取:
dst=cv2.bitwise_and(src1,src2[,mask])# 与运算dst=cv2.bitwise_or(src1,src2[,mask])# 或运算dst=cv2.bitwise_xor(src1,src2[,mask])# 异或运算dst=cv2.bitwise_not(src[,mask])# 非运算(取反)6.3 图像加法方式对比
| 方式 | API | 溢出处理 | 适用场景 |
|---|---|---|---|
| 加权融合 | cv2.addWeighted | 按权重线性组合 | 透明度叠加、图像过渡 |
| 饱和加法 | cv2.add | 超过 255 截断为 255 | 亮度提升、图像合成 |
| NumPy 加法 | img1 + img2 | 超过 255 取模环绕(溢出回绕) | 需避免,易致颜色异常 |
| 饱和减法 | cv2.subtract | 小于 0 截断为 0 | 背景减除、差异检测 |
| 位运算 | cv2.bitwise_* | 按位逻辑运算 | 掩膜操作、ROI 提取 |