OpenCV Python Meanshift和Camshift
在本章中,让我们学习一下OpenCV-Python中的meanshift和camshift。首先,让我们了解一下什么是meanshift。
Meanshift
均值漂移算法识别数据集中具有高密度的数据点或簇。该算法在每个数据点上放置一个核,并将它们相加,以生成核密度估计(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算法将我们的窗口移动到具有最大密度的新位置。
输出
这是一个移动窗口的快照 –
Camshift
Meanshift算法的一个缺点是跟踪窗口的大小不会随着物体与摄像机的距离而变化。此外,只有当物体在该物体的区域内时,窗口才会跟踪该物体。因此,我们必须手动编码窗口,并且必须小心地进行。
这些问题的解决方案由CAMhift(代表 连续自适应Meanshift )提供。一旦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)
输出
修改后程序的结果之一是跟踪窗口中旋转的矩形,如下所示: