上一个教程: 如何使用背景减除方法
下一个教程: 光流
在本章中,
均值漂移的原理很简单。假设你有一组点(它可以是像直方图反向投影那样的像素分布)。你有一个小窗口(可能是一个圆形),你需要将这个窗口移动到像素密度最大(或点数最多)的区域。这在下面的简单图像中有所说明:
初始窗口显示为蓝色圆形,名为“C1”。其原始中心用蓝色矩形标记,名为“C1_o”。但是,如果你找到该窗口内点的质心,你将得到点“C1_r”(用小的蓝色圆形标记),这是窗口的实际质心。显然它们不匹配。因此,移动你的窗口,使新窗口的圆心与上一个质心匹配。再次找到新的质心。很可能,它仍然不匹配。所以再次移动,并继续迭代,直到窗口中心和其质心落在相同的位置(或在小的期望误差范围内)。这样,最终你得到的是一个具有最大像素分布的窗口。它用绿色圆形标记,名为“C2”。如图像所示,它包含最大数量的点。整个过程在下面的静态图像中演示:
因此,我们通常传递直方图反向投影图像和初始目标位置。当物体移动时,移动显然会反映在直方图反向投影图像中。结果,均值漂移算法会将我们的窗口移动到密度最大的新位置。
要在OpenCV中使用均值漂移,首先我们需要设置目标,找到其直方图,以便我们可以在每一帧上反向投影目标以计算均值漂移。我们还需要提供窗口的初始位置。对于直方图,这里只考虑色调(Hue)。此外,为了避免低光照引起的错误值,使用 `cv.inRange()` 函数丢弃低光照值。
我使用的视频中的三帧如下所示
你仔细观察过上一个结果吗?存在一个问题。无论汽车离摄像头很远还是很近,我们的窗口总是保持相同的大小。这不好。我们需要根据目标的大小和旋转来调整窗口大小。解决方案再次来自“OpenCV实验室”,它被称为CAMshift(连续自适应均值漂移),由Gary Bradsky于1998年在其论文《用于感知用户界面的计算机视觉人脸跟踪》中发表 [40] 。
它首先应用均值漂移。一旦均值漂移收敛,它会更新窗口大小,公式为 \(s = 2 \times \sqrt{\frac{M_{00}}{256}}\)。它还会计算最适合的椭圆的方向。然后它再次应用均值漂移,使用新的缩放搜索窗口和之前的窗口位置。这个过程会持续进行直到达到所需的精度。
它类似于均值漂移,但返回一个旋转矩形(即我们的结果)和盒子参数(用于在下一次迭代中作为搜索窗口传递)。请看下面的代码:
结果的三帧如下所示
