魏老师学生——Cecil:学习OpenCV-机器视觉之旅
Aim:使用Meanshift和Camshift算法在视频中找到并跟踪目标对象。
Meanshift算法
将窗口移动到图像中灰度密度最大的区域。此时质心与窗口几何中心极度近似。
opencv中的Meanshift算法
- 设置目标对象,计算其直方图,执行算法时将目标对象反向投影到每一帧。
- 提供窗口的起始位置。计算H(Hue)通道的直方图,使用函数cv2.inRange() 忽略低亮度值,避免低亮度产生影响。
代码演示
#coding=utf-8
import cv2
import numpy as np
cap=cv2.VideoCapture(0)
ret,frame=cap.read()
r,h,c,w=250,90,400,125 #设置本地窗口初始化
track_window=(c,r,w,h)
roi=frame[r:r+h,c:c+w] #设置跟踪ROI
hsv_roi=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
mask=cv2.inRange(hsv_roi,np.array((0.,60.,32.)),np.array((180.,255.,255.)))
roi_hist=cv2.calcHist([hsv_roi],[0],mask,[180],[0,180])
cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX)
term_crit=(cv2.TERM_CRITERIA_EPS|cv2.TERM_CRITERIA_COUNT,10,1)
#设置终止条件为十次迭代或者至少移动一次。
while(1):
ret,frame=cap.read()
if ret==True:
hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
dst=cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1)
ret,track_window=cv2.meanShift(dst,track_window,term_crit)
#使用meanshift获取新位置
x,y,w,h=track_window
img2=cv2.rectangle(frame,(x,y),(x+w,y+h),255,2)
cv2.imshow('img2',img2)
k=cv2.waitKey(60)&0xFF
if k==27:
break
else:
cv2.imshow('img2',img2)
else:
break
cv2.destroyAllWindows()
cap.release()
Camshift算法
Meanshift算法使用的窗口是大小固定的。
Camshift算法使用窗口的大小可调节。
- 首先使用Meanshift算法找到目标,再调整窗口大小。s=2x根(M00/256)。还计算目标对象的最佳外接椭圆的角度,从而调节窗口角度。再使用更新后的窗口大小和角度在原来的位置继续进行Meanshift算法。不断重复以达到所需精度。
代码演示
- 返回结果:带旋转角度的矩形(结果),矩形参数(用于下一次迭代过程)。
#coding=utf-8
import cv2
import numpy as np
cap=cv2.VideoCapture(0)
ret,frame=cap.read()
r,h,c,w=250,90,200,125
track_window=(c,r,w,h)
roi=frame[r:r+h,c:c+w]
hsv_roi=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
mask=cv2.inRange(hsv_roi,np.array((0.,60.,32.)),np.array((180.,255.,255.)))
roi_hist=cv2.calcHist([hsv_roi],[0],mask,[180],[0,180])
cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX)
term_crit=(cv2.TERM_CRITERIA_EPS|cv2.TERM_CRITERIA_COUNT,10,1)
while(1):
ret,frame=cap.read()
if ret==True:
hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
dst=cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1)
ret,track_window=cv2.CamShift(dst,track_window,term_crit)
pts=cv2.boxPoints(ret)
pts=np.int0(pts)
img2=cv2.polylines(frame,[pts],True,255,4)
cv2.imshow('img2',img2)
k=cv2.waitKey(60)&0xFF
if k==27:
break
else:
cv2.imshow('img2',img2)
else:
break
cv2.destroyAllWindows()
cap.release()