OpenCV 4.11.0
开源计算机视觉
|
MeanShift 的基本原理很简单。假设你有一组点。(它可以是像直方图反投影这样的像素分布)。给你一个小的窗口(可能是一个圆形),你必须将该窗口移动到像素密度最大(或点数最多)的区域。下图简单地说明了这一点
初始窗口显示为蓝色圆圈,名称为“C1”。其原始中心用蓝色矩形标记,命名为“C1_o”。但是,如果你找到窗口内点的质心,你将得到点“C1_r”(用小的蓝色圆圈标记),它是窗口的实际质心。当然它们并不匹配。因此,移动你的窗口,使新窗口的圆圈与之前的质心匹配。再次找到新的质心。很可能,它不会匹配。所以再次移动它,并继续迭代,直到窗口的中心及其质心落在同一位置(或具有小的期望误差)。所以最终你得到的是一个具有最大像素分布的窗口。它用绿色的圆圈标记,命名为“C2”。正如你在图像中看到的,它具有最多的点。整个过程在下方的静态图像上进行了演示
因此,我们通常传递直方图反投影图像和初始目标位置。当物体移动时,运动显然会反映在直方图反投影图像中。结果,MeanShift 算法将我们的窗口移动到具有最大密度的新位置。
要在 OpenCV.js 中使用 MeanShift,首先我们需要设置目标,找到它的直方图,以便我们可以将目标反投影到每一帧中以计算 MeanShift。我们还需要提供窗口的初始位置。对于直方图,这里只考虑色调。此外,为了避免由于光线不足而导致的错误值,使用cv.inRange() 函数丢弃低光值。
我们使用函数:cv.meanShift (probImage, window, criteria)
probImage | 对象的直方图反投影。详情请参阅 cv.calcBackProject。 |
window | 初始搜索窗口。 |
criteria | 迭代搜索算法的停止条件。 |
你仔细观察了最后的结果吗?有一个问题。当物体离得更远并且非常靠近摄像头时,我们的窗口大小始终相同。这不好。我们需要根据目标的大小和旋转来调整窗口大小。再次,“OpenCV Labs”给出了解决方案,它被称为 CamShift(连续自适应 MeanShift),由 Gary Bradsky 在他 1988 年的论文“用于感知用户界面的计算机视觉人脸跟踪”中发表。
它首先应用 MeanShift。一旦 MeanShift 收敛,它就会更新窗口的大小,为 \(s = 2 \times \sqrt{\frac{M_{00}}{256}}\)。它还计算最适合它的椭圆的方向。它再次使用新的缩放搜索窗口和之前的窗口位置应用 MeanShift。该过程持续进行,直到满足所需的精度。
它几乎与 MeanShift 相同,但它返回一个旋转矩形(这是我们的结果)和框参数(用于在下次迭代中作为搜索窗口传递)。
我们使用函数:cv.CamShift (probImage, window, criteria)
probImage | 对象的直方图反投影。详情请参阅 cv.calcBackProject。 |
window | 初始搜索窗口。 |
criteria | 迭代搜索算法的停止条件。 |