如果你处理过实时视频流,你肯定知道其中的痛苦:闪烁的灯光、拉伸的阴影,以及道路或障碍物等大量静态干扰物,让画面变得杂乱无章。我们的目标是清晰地提取出移动的车辆,以便后续进行跟踪或分类。接下来,我们将详细介绍我使用 OpenCV 构建的处理流程——其中没有用到神经网络。
首先使用 MOG2 进行背景减除
关键在于将前景(运动物体)与背景(静止的道路)分离。我使用了 OpenCV 的高斯混合模型背景/前景分割方法,也就是 cv2.createBackgroundSubtractorMOG2()。它具有自适应性,能够很好地处理光照变化等渐变情况。
基本上,它会分析前几帧图像,将“空”场景建模为每个像素的一系列高斯分布。然后,对于每一帧新图像,它会将任何不符合模型的内容标记为前景。移动的车辆会显示为黑色遮罩中的白色斑点。
以下是一个简单的代码片段,可以帮助你快速上手:
import cv2mog2 = cv2.createBackgroundSubtractorMOG2(history=500, varThreshold=50, detectShadows=True)# In your video loop:foreground_mask = mog2.apply(frame)
为了获得更稳定的模型,我将历史帧数设置为 500,提高了 varThreshold 值以捕捉细微的运动,并启用了阴影检测功能,将阴影标记为灰色(接下来我们会进行清理)。虽然它并不完美——例如挡风玻璃等深色区域可能会出现孔洞,或者阴影会使形状显得臃肿——但这已经是一个不错的开始。
形态学操作的抛光
原始的 MOG2 输出需要清理。这时就需要用到形态学:它通过简单的操作来优化二值图像。
首先,要设定一个明确的界限,使其完全黑白分明,摒弃灰色:
_, binary_mask = cv2.threshold(foreground_mask, 127, 255, cv2.THRESH_BINARY)threshold(foreground_mask, 127, 255, cv2.THRESH_BINARY)
然后,“闭合”以填充孔洞:膨胀(扩大白色区域),然后腐蚀(收缩回缩),使用椭圆核以获得平滑的车辆形状。
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, ( 5 , 5 ))closed_mask = cv2.morphologyEx(binary_mask, cv2.MORPH_CLOSE, kernel)
最后,稍加扩张,将同一车辆的任何分裂部分合并在一起:
dilated_mask = cv2.morphologyEx(closed_mask, cv2.MORPH_DILATE, kernel, iterations= 2 )
结果如何?车辆轮廓清晰、纯净,呈白色,可用于绘制边界框或进行跟踪。不再有孔洞或阴影变形。
307