Skip to content

Meanshift 和 Camshift

在本章中,

  • 我们将学习 Meanshift 和 Camshift 算法来跟踪视频中的目标。

meanshift_basics.jpg meanshift_face.gif

meanshift 背后的直觉很简单。假设你有一组点。(它可以是像直方图反向投影那样的像素分布)。给定一个小窗口(可能是圆形),你必须将该窗口移动到像素密度最大(或点数最多)的区域。这在下面给出的简单图像中进行了说明:

初始窗口显示为名为 “C1” 的蓝色圆圈。其原始中心标记为蓝色矩形,名为 “C1_o”。但如果你找到该窗口内点的质心,你会得到点 “C1_r”(标记为小蓝色圆圈),这是窗口的真正质心。它们肯定不匹配。因此,移动你的窗口,使新窗口的圆圈与之前的质心匹配。再次找到新的质心。很可能,它仍然不匹配。所以再次移动它,并继续迭代,直到窗口的中心及其质心落在同一位置(或在所需的小误差范围内)。所以最终你获得的是一个具有最大像素分布的窗口。它用名为 “C2” 的绿色圆圈标记。正如你在图像中所见,它具有最多的点数。整个过程在下面的静态图像上演示:

所以我们通常传入直方图反向投影图像和初始目标位置。当目标移动时,显然这种移动会反映在直方图反向投影图像中。因此,meanshift 算法将我们的窗口移动到具有最大密度的新位置。

meanshift_result.jpg

要在 OpenCV 中使用 meanshift,首先我们需要设置目标,找到其直方图,以便我们可以在每一帧上反向投影目标来计算 meanshift。我们还需要提供窗口的初始位置。对于直方图,这里只考虑 Hue。此外,为了避免由于低光照导致的错误值,使用 cv.inRange() 函数丢弃低光照值。

  • 可下载代码:点击 这里

  • 代码一览: 代码见下方示例

  • 可下载代码:点击 这里

  • 代码一览: 代码见下方示例

  • 可下载代码:点击 这里

  • 代码一览: 代码见下方示例 我使用的视频中的三帧如下所示:

camshift_face.gif

你仔细观察了最后的结果吗?存在一个问题。无论汽车是离相机非常远还是非常近,我们的窗口总是具有相同的尺寸。这不好。我们需要根据目标的尺寸和旋转来调整窗口大小。再一次,解决方案来自 “OpenCV Labs”,它被称为 CAMshift(Continuously Adaptive Meanshift,持续自适应 Meanshift),由 Gary Bradsky 在他 1998 年的论文 “Computer Vision Face Tracking for Use in a Perceptual User Interface” 中发表 [Bradski98] 。

它首先应用 meanshift。一旦 meanshift 收敛,它会按 s=2×M00256s = 2 \times \sqrt{\frac{M_{00}}{256}} 更新窗口的尺寸。它还计算与之最佳拟合椭圆的朝向。然后用新的缩放搜索窗口和之前的窗口位置再次应用 meanshift。该过程持续进行,直到满足所需的精度。

camshift_result.jpg

它类似于 meanshift,但返回一个旋转矩形(即我们的结果)和 box 参数(在下一次迭代中作为搜索窗口传入)。参见下面的代码:

  • 可下载代码:点击 这里

  • 代码一览: 代码见下方示例

  • 可下载代码:点击 这里

  • 代码一览: 代码见下方示例

  • 可下载代码:点击 这里

  • 代码一览: 代码见下方示例 结果的三帧如下所示:

  1. 关于 Camshift 的法语维基百科页面。(这两个动画取自那里)
  2. Bradski, G.R., “Real time face and object tracking as a component of a perceptual user interface,” Applications of Computer Vision, 1998. WACV ‘98. Proceedings., Fourth IEEE Workshop on , vol., no., pp.214,219, 19-21 Oct 1998
  1. OpenCV 附带一个用于 camshift 交互式演示的 Python 示例。使用它、改造它、理解它。