OpenCV Python - Meanshift 和 Camshift


在本章中,让我们了解 OpenCV-Python 中的均值平移和凸轮平移。首先,我们先来了解一下什么是意义转移。

均值漂移

均值平移算法识别数据集中数据点或聚类高度集中的位置。该算法在每个数据点放置一个核,并将它们加在一起以进行核密度估计(KDE)。

KDE 将分别具有高和低数据点密度的位置。Meanshift 是一种非常有用的方法,可以跟踪视频中的特定对象。

视频的每个实例都以该帧中像素分布的形式进行检查。作为感兴趣区域(ROI)的初始窗口通常是正方形或圆形。为此,通过硬编码指定位置并识别最大像素分布的区域。

随着视频的运行,ROI 窗口向最大像素分布区域移动。移动方向取决于跟踪窗口的中心与该窗口内所有 k 像素的质心之间的差异。

为了在OpenCV中使用Meanshift,首先找到我们目标的直方图(其中仅考虑色调),并将其目标反投影到每一帧上以计算Meanshift。我们还需要提供 ROI 窗口的初始位置。

我们反复计算直方图的反投影并计算Meanshift以获得跟踪窗口的新位置。随后,我们使用框架上的尺寸绘制一个矩形。

功能

程序中使用的 openCV 函数是 -

  • cv.calcBackProject() - 计算直方图的反投影。

  • cv.meanShift() - 使用迭代搜索算法的初始搜索窗口和停止条件对对象直方图进行反向投影。

例子

这是 Meanshift 的示例程序 -

import numpy as np
import cv2 as cv

cap = cv.VideoCapture('traffic.mp4')

ret,frame = cap.read()

# dimensions of initial location of window
x, y, w, h = 300, 200, 100, 50
tracker = (x, y, w, h)

region = frame[y:y+h, x:x+w]
hsv_reg = cv.cvtColor(region, cv.COLOR_BGR2HSV)
mask = cv.inRange(hsv_reg, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
reg_hist = cv.calcHist([hsv_reg],[0],mask,[180],[0,180])
cv.normalize(reg_hist,reg_hist,0,255,cv.NORM_MINMAX)

# Setup the termination criteria
criteria = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1 )

while(1):
   ret, frame = cap.read()

   if ret == True:
      hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
      dst = cv.calcBackProject([hsv],[0],reg_hist,[0,180],1)

      # apply meanshift
      ret, tracker = cv.meanShift(dst, tracker, criteria)

      # Draw it on image
      x,y,w,h = tracker
      img = cv.rectangle(frame, (x,y), (x+w,y+h), 255,2)
      cv.imshow('img',img)

      k = cv.waitKey(30) & 0xff
      if k==115:
         cv.imwrite('capture.png', img)
      if k == 27:
         break

当程序运行时,Meanshift 算法将我们的窗口移动到具有最大密度的新位置。

输出

这是移动窗口的快照 -

均值漂移

卡姆西夫

Meanshift 算法的缺点之一是无论物体距相机的距离如何,跟踪窗口的大小都保持不变。此外,仅当对象位于该对象的区域中时,窗口才会跟踪该对象。因此,我们必须对窗口进行手动硬编码,并且应该小心地进行。

CAMshift(代表连续自适应均值漂移)给出了这些问题的解决方案。一旦meanshift收敛,Camshift算法就会更新窗口的大小,使得跟踪窗口的大小可以改变,甚至可以旋转以更好地与被跟踪对象的运动相关联。

在以下代码中,使用 camshift() 函数而不是meanshift() 函数。

首先,它使用meanShift找到对象中心,然后调整窗口大小并找到最佳旋转。该函数返回对象的位置、大小和方向。使用 polylines() 绘制函数在框架上绘制位置。

例子

使用 CamShift() 函数代替早期程序中的 Meanshift() 函数,如下所示 -

# apply camshift
ret, tracker = cv.CamShift(dst, tracker, criteria)
pts = cv.boxPoints(ret)
pts = np.int0(pts)
img = cv.polylines(frame,[pts],True, 255,2)
cv.imshow('img',img)

输出

修改后的程序结果的一张快照显示了跟踪窗口的旋转矩形,如下所示 -

卡姆西夫