当前位置: 代码迷 >> 综合 >> Object Track(一):经典算法复现(1)-Meanshift and Camshift
  详细解决方案

Object Track(一):经典算法复现(1)-Meanshift and Camshift

热度:53   发布时间:2023-11-21 09:18:26.0

写在前面

1.复现一些经典算法,了解object track任务的发展
2.python简单些,节约时间,就用python
3.跟踪目标的选取:直接在视频的第一帧中框选ROI

4.核心代码是

cv.calcHist
cv.calcBackProject
cv.MeanShift
cv.CamShift

Meanshift

Meanshift的基本原理很简单,假设有一个点的集合。(可以是像素分布,例如直方图反投影)。设置一个小窗口(形状可能是一个圆形),目标是将该窗口移到最大像素密度(或区域内包含最大点的个数)的区域。如下图所示:

初始窗口以蓝色圆圈显示,名称为“C1”。其原始中心以蓝色矩形标记,名称为“C1_o”。但是,如果找到该窗口内点的质心(密度平均点),则会得到点“C1_r”(标记为蓝色小圆圈),它是此刻窗口的真实质心。当然现在的它们是不匹配的。因此需要移动窗口,使新窗口的圆与上一个质心匹配。假设我们通过移动再次找到了新的质心。但很可能也是不匹配的。所以我们需要再次移动它,并继续迭代,以使窗口的中心及其质心落在同一位置(或在很小的期望误差内)。满足结束条件(迭代收敛)时,最终会获得的是一个具有最大像素分布的窗口。它带有一个绿色圆圈,名为“C2”。如图所示,此刻具有最大的点数。整个过程在下面的静态图像上演示:

在OpenCV中使用Meanshift,首先需要设置目标,找到它的直方图,以便我们可以在每一帧上反投影目标以计算均值。此外还需要提供窗口的初始位置。注意对于直方图,这里只考虑色调。而且为了避免由于低光导致的错误值,需要使用cv.inRange() 函数丢弃低光值。

import numpy as np
import cv2 as cv
import argparse
parser = argparse.ArgumentParser(description='This sample demonstrates the meanshift algorithm. \The example file can be downloaded from: \https://www.bogotobogo.com/python/OpenCV_Python/images/mean_shift_tracking/slow_traffic_small.mp4')
parser.add_argument('image', type=str, help='path to image file')
args = parser.parse_args()
cap = cv.VideoCapture(args.image)
# 视频的第一帧
ret,frame = cap.read()
# 设置窗口的初始位置
x, y, w, h = 300, 200, 100, 50 # simply hardcoded the values
track_window = (x, y, w, h)
# 设置初始ROI来追踪
roi = frame[y:y+h, x:x+w]
hsv_roi =  cv.cvtColor(roi, cv.COLOR_BGR2HSV)
mask = cv.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
roi_hist = cv.calcHist([hsv_roi],[0],mask,[180],[0,180])
cv.normalize(roi_hist,roi_hist,0,255,cv.NORM_MINMAX)
# 设置终止条件,可以是10次迭代,也可以至少移动1 pt
term_crit = ( 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],roi_hist,[0,180],1)# 应用meanshift来获取新位置ret, track_window = cv.meanShift(dst, track_window, term_crit)# 在图像上绘制x,y,w,h = track_windowimg2 = cv.rectangle(frame, (x,y), (x+w,y+h), 255,2)cv.imshow('img2',img2)k = cv.waitKey(30) & 0xffif k == 27:breakelse:break

Camshift

如果仔细观察MeanShift的结果,应该会发现一个问题。无论汽车离相机很远或很近,窗口始终具有相同的大小。这是可能是不好的。我们需要根据目标的大小和旋转来调整窗口大小。该解决方案来自“ OpenCV Labs”,Gary Bradsky在其1998年的论文“用于感知用户界面中的计算机视觉面部跟踪”中发表的CAMshift(连续自适应均值偏移)。 它首先应用Meanshift。一旦Meanshift收敛,它将更新窗口的大小为。它还可以计算出最合适的椭圆的方向。再次将均值偏移应用于新的缩放搜索窗口和先前的窗口位置。该过程一直持续到达到要求的精度为止。

Camshift的实现与meanshift相似,但是额外返回一个旋转的矩形(即我们的结果)和box参数(用于在下一次迭代中作为搜索窗口传递)。请参见下面的代码:

import numpy as np
import cv2 as cv
import argparse
parser = argparse.ArgumentParser(description='This sample demonstrates the camshift algorithm. \The example file can be downloaded from: \https://www.bogotobogo.com/python/OpenCV_Python/images/mean_shift_tracking/slow_traffic_small.mp4')
parser.add_argument('image', type=str, help='path to image file')
args = parser.parse_args()
cap = cv.VideoCapture(args.image)
# 获取视频第一帧
ret,frame = cap.read()
# 设置初始窗口
x, y, w, h = 300, 200, 100, 50 # simply hardcoded the values
track_window = (x, y, w, h)
# 设置追踪的ROI窗口
roi = frame[y:y+h, x:x+w]
hsv_roi =  cv.cvtColor(roi, cv.COLOR_BGR2HSV)
mask = cv.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
roi_hist = cv.calcHist([hsv_roi],[0],mask,[180],[0,180])
cv.normalize(roi_hist,roi_hist,0,255,cv.NORM_MINMAX)
# 设置终止条件,可以是10次迭代,有可以至少移动1个像素
term_crit = ( 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],roi_hist,[0,180],1)# 应用camshift 到新位置ret, track_window = cv.CamShift(dst, track_window, term_crit)# 在图像上画出来pts = cv.boxPoints(ret)pts = np.int0(pts)img2 = cv.polylines(frame,[pts],True, 255,2)cv.imshow('img2',img2)k = cv.waitKey(30) & 0xffif k == 27:breakelse:break

  相关解决方案