OpenCV中Camshift算法原理与Python实现详解

夏知夏
夏知夏
发布时间:2026-10-13 | 2人浏览过
原创

本文深入解析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()

运行结果展示

程序运行后的输出结果如下所示:

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

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表