3、图像处理基础回顾:色彩空间、滤波、边缘检测与特征点提取
各位同学,欢迎来到第三章。在正式进入视频行为识别之前,咱们得先把图像处理的老底子翻出来晒一晒。你想想看,视频说白了就是一帧一帧的图像在快速播放。如果连单张图像的基本操作都搞不定,那视频分析就是空中楼阁。
这一章,我会带你快速过一遍四个核心模块:色彩空间、图像滤波、边缘检测、特征点提取。嗯,都是老面孔了,但咱们这次换个视角——从「视频行为识别」的角度重新审视它们。
3.1 色彩空间:RGB 与 HSV
先说色彩空间。RGB 大家最熟了,红绿蓝三通道叠加。但说实话,在视频分析里,RGB 有时候并不好用。为什么?因为 RGB 对光照变化太敏感了。你想想看,同一个动作,白天和晚上拍出来的 RGB 值可能天差地别。
我个人习惯在行为识别任务中,优先尝试 HSV 色彩空间。H 是色调,S 是饱和度,V 是明度。把亮度信息单独拎出来,这样算法就不容易被光照干扰了。
核心区别:
- RGB:面向硬件显示,三通道强相关,光照敏感
- HSV:面向人类视觉感知,色调和亮度分离,光照鲁棒
我在项目中遇到过这样一个场景:做室内跌倒检测,白天效果很好,一到晚上灯光偏黄,RGB 模型直接崩了。后来我把输入转成 HSV,只取 H 和 S 通道,效果立马稳住了。
# OpenCV 中 RGB 转 HSV
import cv2
import numpy as np
img_bgr = cv2.imread('frame.jpg') # OpenCV 默认是 BGR
img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)
# 提取色调和饱和度,忽略明度
hue = img_hsv[:, :, 0]
sat = img_hsv[:, :, 1]
val = img_hsv[:, :, 2] # 这个可以扔掉,或者做归一化
小技巧:OpenCV 里 HSV 的 H 范围是 0-179,不是 0-359。别问我为什么,问就是历史遗留问题。我第一次用的时候踩过这个坑,调了半天颜色阈值都不对。
3.2 图像滤波:高斯滤波与中值滤波
滤波说白了就是去噪。视频里噪声太多了,传感器噪声、压缩噪声、运动模糊……不滤波直接做检测,结果会很难看。
3.2.1 高斯滤波
高斯滤波是线性滤波,用高斯核做卷积。它对高斯噪声(比如传感器热噪声)效果很好。但有个问题——它会模糊边缘。你想想看,边缘信息对行为识别多重要,模糊了还怎么判断姿势?
# 高斯滤波
blurred = cv2.GaussianBlur(img, (5, 5), sigmaX=1.5)
参数 (5,5) 是核大小,sigmaX 是标准差。核越大越模糊,sigma 越大也越模糊。我建议在视频预处理中,核大小不要超过 5,否则细节丢太多。
3.2.2 中值滤波
中值滤波是非线性的。它取窗口内所有像素的中位数,而不是平均值。这玩意儿对椒盐噪声(就是那种黑白点噪声)简直是克星。
我曾经在工厂监控视频里做异常检测,画面里经常有电火花产生的椒盐噪声。用高斯滤波根本去不干净,换成中值滤波,世界清净了。
# 中值滤波
median = cv2.medianBlur(img, 5) # 核大小必须是奇数
注意:中值滤波计算量比高斯滤波大,尤其是核窗口大的时候。实时视频处理要权衡一下。我一般用 3x3 或 5x5,再大就扛不住了。
3.3 边缘检测:Canny 算子
边缘检测是行为识别的基石。人体轮廓、肢体边缘、物体边界……这些信息对理解「人在做什么」至关重要。
Canny 算子是目前最经典的边缘检测算法,没有之一。它分四步走:
- 高斯滤波去噪——先模糊一下,避免噪声被当成边缘
- 计算梯度幅值和方向——用 Sobel 算子算一下
- 非极大值抑制——只保留梯度方向上的局部最大值,把粗边缘变细
- 双阈值检测——高阈值确定强边缘,低阈值连接弱边缘
嗯,这里要注意:双阈值是 Canny 的精髓。高阈值设太高,边缘断断续续;设太低,一堆假边缘。我一般设高阈值 100-150,低阈值 50-75,具体看场景调。
# Canny 边缘检测
edges = cv2.Canny(img, threshold1=50, threshold2=150)
在视频行为识别中,我经常把 Canny 结果作为额外的输入通道,跟 RGB 一起喂给网络。效果嘛,谁用谁知道。
避坑指南:我曾经在低光照视频上直接用 Canny,结果全是噪声。后来发现要先做一次直方图均衡化,把对比度拉起来,Canny 才能正常工作。
3.4 特征点提取:SIFT 与 ORB
特征点提取,说白了就是找图像里「与众不同」的点。角点、斑点、纹理突变处……这些点在视频帧之间相对稳定,可以用来做匹配、跟踪、甚至动作识别。
3.4.1 SIFT(尺度不变特征变换)
SIFT 是经典中的经典。它提取的特征点对旋转、尺度缩放、光照变化都有很强的鲁棒性。但缺点也很明显——慢,而且有专利保护(虽然过期了)。
# SIFT 特征提取
sift = cv2.SIFT_create()
keypoints, descriptors = sift.detectAndCompute(img, None)
# 绘制特征点
img_with_kp = cv2.drawKeypoints(img, keypoints, None)
每个 SIFT 特征点有 128 维的描述子。在视频里,你可以用这些描述子做帧间匹配,判断运动是否异常。比如,正常行走时特征点的运动轨迹是有规律的,突然乱飞可能就是异常。
个人经验:SIFT 在纹理丰富的场景下表现极好,但在纯色墙面、光滑地面这种「没纹理」的地方,特征点会很少。这时候别硬用,换个方法。
3.4.2 ORB(定向 FAST 和旋转 BRIEF)
ORB 是 SIFT 的「轻量替代品」。它结合了 FAST 角点检测和 BRIEF 描述子,速度比 SIFT 快一个数量级。在实时视频处理中,我几乎首选 ORB。
# ORB 特征提取
orb = cv2.ORB_create(nfeatures=500)
keypoints, descriptors = orb.detectAndCompute(img, None)
# ORB 描述子是二进制,可以用汉明距离匹配
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(descriptors1, descriptors2)
ORB 的缺点是对尺度变化比较敏感。如果视频里人忽远忽近,ORB 匹配效果会下降。这时候我可能会用 SIFT,或者对图像做多尺度处理。
性能对比:
| 算法 | 速度 | 鲁棒性 | 适用场景 |
|---|---|---|---|
| SIFT | 慢 | 高(尺度、旋转、光照) | 离线分析、高精度匹配 |
| ORB | 快 | 中(旋转好,尺度差) | 实时视频、移动端 |
3.5 本章小结
好,这一章咱们把图像处理的老底子翻了一遍。色彩空间、滤波、边缘检测、特征点提取——这四个模块在视频行为识别里各有各的用处。
我个人建议,在实际项目中不要死磕某一个方法。RGB 不行就换 HSV,高斯不行就换中值,SIFT 太慢就换 ORB。灵活组合才是王道。
下一章,咱们会正式进入视频处理的核心——光流法与帧差法。到时候你会发现,今天讲的这些基础,全都会用上。
一句话总结:图像处理是视频分析的「地基」。地基不稳,楼盖得再高也得塌。