OpenCV中Camshift算法原理与Python实现详解
本文深入解析OpenCV中的Camshift(连续自适应Meanshift)算法,旨在解决传统Meanshift在目标距离变化时窗口大小固定及无法处理旋转的问题。通过Python代码示例,演示如何结合直方图反向投影与Camshift函数实现自适应窗口大小的目标跟踪,并解析其返回值含义及迭代优化过程。
Camshift算法背景与引入原因
在前文学习Meanshift算法时,观察其标记结果会发现一个明显缺陷,具体表现如下图所示:

当目标(如汽车)距离较远时,使用较小的窗口即可将其框住,这符合近大远小的视觉投影原理;然而,当目标靠近时,情况如下所示:

此时,固定大小的窗口已无法完全包围目标,导致跟踪失效。为了解决这一问题,引入了Camshift(Continuously Adaptive Meanshift,连续自适应Meanshift)算法。此外,该算法还能有效判断物体的旋转方向,这也是其重要功能之一。该算法源自1998年发表的论文《Computer Vision Face Tracking for Use in a Perceptual User Interface》。
Camshift算法工作原理
Camshift算法的执行流程如下:首先应用Meanshift算法找到概率密度最大的区域,随后更新窗口的大小,并计算能够最佳包裹该区域的椭圆;若结果仍不满足条件,则进入下一轮迭代,直到满足Meanshift的收敛条件且窗口大小适配为止。
Camshift函数返回两个关键值:第一个值ret代表旋转后的窗口参数,第二个值是用于下一次搜索的窗口位置。具体代码示例如下:
Python代码实现与解析
#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import numpy as np
import cv2
from matplotlib import pyplot as plt
capture = cv2.VideoCapture(1)
if not capture.isOpened:
print('Unable to open: ')
exit(0)
#获取第一帧图片
ret,frame = capture.read()
#设置目标窗口
#读取文件
find = cv2.imread('luohu1.png')
h,w = find.shape[:2]
roi = find[10: 120, 10: 120]
x = 10
y = 10
width = 120 - x
height = 120 - y
track_window = (x, y, w, h)
print(track_window)
#跟踪目标
hsv_roi = cv2.cvtColor(roi, 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)
#设置迭代条件,每10移动一点
term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 )
while(1):
ret, frame = capture.read()
if ret == True:
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1)#反向投影
#使用 meanshift获得新位置
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,0,0),2)
cv2.imshow('img2',img2)
cv2.imshow("dst", dst)
cv2.imshow("roi", roi)
keyboard = cv2.waitKey(1)
if keyboard == ord('q') or keyboard == ord('Q'):
break
else:
break
capture.release()
cv2.destroyAllWindows()
运行结果展示
程序运行后的输出结果如下所示:

以下是目标距离较远时的跟踪效果照片:

以下是目标距离较近时的跟踪效果照片:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









