![]() |
OpenCV 4.12.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 | 迭代搜索算法的停止标准。 |