OpenCV学习笔记-CamShift

CamShift算法的全称是"Continuously Adaptive Mean-SHIFT",即:连续自适应的MeanShift算法。其基本思想是对视频序列的所有图像帧都作MeanShift运算,并将上一帧的结果(即搜索窗口的中心位置和窗口大小)作为下一帧MeanShift算法的搜索窗口的初始值,如此迭代下去。简单点说,meanShift是针对单张图片寻找最优迭代结果,而camShift则是针对视频序列来处理,并对该序列中的每一帧图片都调用meanShift来寻找最优迭代结果。正是由于camShift针对一个视频序列进行处理,从而保证其可以不断调整窗口的大小,如此一来,当目标的大小发生变化的时候,该算法就可以自适应地调整目标区域继续跟踪。

OpenCV自带的camShift的例子当中,是通过计算目标在HSV空间下的H分量直方图,通过直方图反向投影得到目标像素的概率分布,然后通过调用OpenCV的CAMSHIFT算法,自动跟踪并调整目标窗口的中心位置与大小。该算法对于简单背景下的单目标跟踪效果较好,但如果被跟踪目标与背景颜色或周围其它目标颜色比较接近,则跟踪效果较差。另外,由于采用颜色特征,所以它对被跟踪目标的形状变化有一定的抵抗能力。  

    OpenCV自带例子中的camShift算法,可以分为三个部分:

一、计算色彩投影图(反向投影):

(1)为了减少光照变化对目标跟踪的影响,首先将图像从RGB颜色空间转换到HSV颜色空间;

2)对H分量进行直方图统计,直方图代表了不同H分量取值出现的概率,或者说可以据此查找出H分量的大小为x时的概率或像素个数,即,得到颜色概率查找表;

3)将图像中每个像素的值用其颜色出现的概率进行替换,由此得到颜色概率分布图;

  以上三个步骤称之为反向投影,需要提醒的是,颜色概率分布图是一个灰度图像;

二、meanShift寻优

前面提到过meanShift算法(http://blog.csdn.net/carson2005/article/details/7337432)是一种非参数概率密度估计方法,它通过不断迭代计算得到最优搜索窗口的位置和大小。

三、camShift跟踪算法

前面提到, camShift其实就是在视频序列的每一帧当中都运用meanShift,并将上一帧的meanShift结果作为下一帧的初始值,如此不断循环迭代,就可以实现目标的跟踪了。
以上内容来自于:https://blog.csdn.net/carson2005/article/details/7439125

具体步骤详解参考meanshift,大致步骤一样: meanshift
具体代码:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

cap = cv.VideoCapture('img/slow.flv')
#读取第一帧图像
ret, frame = cap.read()
#设置初始窗口参数
r, h ,c, w = 190, 30, 300, 90
track_window = (c, r, w, h)

#设置ROI
roi = frame[r:r+h, c:c+w]
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
#色调直方图
lower_hsv = np.array([0, 0, 0])
upper_hsv = np.array([255, 255, 46]) # 黑色
mask = cv.inRange(hsv_roi, lowerb=lower_hsv, upperb=upper_hsv)
roi_hist = cv.calcHist([hsv_roi], [0], mask, [180], [0, 180])

#归一化
cv.normalize(roi_hist, roi_hist, 0, 255, cv.NORM_MINMAX)

#设置迭代终止条件
term_crit = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1)

while True:
    ret, frame = cap.read()

    if ret is True:
        hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
        #获得色调直方图的反向投影
        dst = cv.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)
        #返回新的窗口的坐标集合和新的窗口
        ret, track_window = cv.CamShift(dst, track_window, term_crit)
        #ret((center.x, center.y),(h, w), thate)
        # print(ret)
        # print(track_window)
        pts = cv.boxPoints(ret) #返回盒子的四个顶点
        pts = np.int0(pts)
        # print('len pts:', len(pts), pts)
        #绘制直线,isClose 直线是否闭合
        img2 = cv.polylines(frame, [pts], True, (255, 0, 0), 2)
        cv.imshow('img2', img2)

        k = cv.waitKey(60) & 0xff
        if k == 27:
            break
    else:
        break


cv.waitKey(0)
cv.destroyAllWindows()

猜你喜欢

转载自blog.csdn.net/qq_36387683/article/details/80600314
今日推荐