Camshift函数的原型为:RotatedRect CamShift(InputArray probImage, Rect& window, TermCriteria criteria)。
其中probImage为输入图像直方图的反向投影图,window为要跟踪目标的初始位置矩形框,criteria为算法结束条件。函数返回一个有方向角度的矩阵。该函数的实现首先是利用meanshift算法计算出要跟踪的中心,然后调整初始窗口的大小位置和方向角度。在camshift内部调用了meanshift算法计算目标的重心。
一、概括:
CamShift算法,全称是 Continuously AdaptiveMeanShift,顾名思义,它是对Mean Shift 算法的改进,能够自动调节搜索窗口大小来适应目标的大小,可以跟踪视频中尺寸变化的目标。它也是一种半自动跟踪算法,需要手动标定跟踪目标。基本思想是以视频图像中运动物体的颜色信息作为特征,对输入图像的每一帧分别作 Mean-Shift 运算,并将上一帧的目标中心和搜索窗口大小(核函数带宽)作为下一帧 Mean shift 算法的中心和搜索窗口大小的初始值,如此迭代下去,就可以实现对目标的跟踪。因为在每次搜索前将搜索窗口的位置和大小设置为运动目标当前中心的位置和大小,而运动目标通常在这区域附近,缩短了搜索时间;另外,在目标运动过程中,颜色变化不大,故该算法具有良好的鲁棒性。已被广泛应用到运动人体跟踪,人脸跟踪等领域。
二、算法
具体步骤如下:
步骤一:计算目标区域内的颜色直方图。
通常是将输入图像转换到HSV颜色空间,目标区域为初始设定的搜索窗口范围,分离出色调H分量做该区域的色调直方图计算。因为 RGB 颜色空间对光线条件的改变较为敏感,要减小该因素对跟踪效果的影响,CamShift 算法通常采用 HSV 色彩空间进行处理,当然也可以用其它颜色空间计算。这样即得到目标模板的颜色直方图。
步骤二:根据获得的颜色直方图将原始输入图像转化成颜色概率分布图像,
该过程称为“反向投影"。所谓直方图反向投影,就是输入图像在已知目标颜色直方图的条件下的颜色概率密度分布图,包含了目标在当前帧中的相干信息。对于输入图像中的每一个像素,查询目标模型颜色直方图,对于目标区域内的像素,可得到该像素属于目标像素的概率,而对于非目标区域内的像素,该概率为0。
步骤三:Mean Shift迭代过程。
即右边大矩形框内的部分,它是 CamShift 算法的核心,目的在于找到目标中心在当前帧中的位置。首先在颜色概率分布图中选择搜索窗口的大小和初始位置,然后计算搜索窗口的质心位置。设像素点(i, j)位于搜索窗口内,I(i, j)是颜色直方图的反向投影图中该像素点对应的值,定义搜索窗口的零阶矩 M00 和一阶矩M10,M01如下:
则搜索窗口的质心位置为:(M10/M00, M01/M00)。
接着调整搜索窗口中心到质心。零阶矩反映了搜索窗口尺寸,依据它调整窗口大小,并将搜索窗口的中心移到质心,如果移动距离大于设定的阈值,则重新计算调整后的窗口质心,进行新一轮的窗口位置和尺寸调整。直到窗口中心与质心之间的移动距离小于阈值,或者迭代次数达到某一最大值,认为收敛条件满足,将搜索窗口位置和大小作为下一帧的目标位置输入,开始对下一帧图像进行新的目标搜索。
三、总结
CamShift算法改进了 Mean-Shift 跟踪算法的第二个缺陷,在跟踪过程中能够依据目标的尺寸调节搜索窗口大小,对 有尺寸变化的目标可准确定位。但是,一方面 CamShfit 算法在计算目标模板直方图分布时,没有使用核函数进行加权处理,也就是说目标区域内的每个像素点在目标模型中有着相同的权重,故 CamShfit 算法的抗噪能力低于Mean-Shift跟踪算法。另一方面,CamShift 算法中没有定义候选目标,直接利用目标模板进行跟踪。除此以外,CamShift 算法采用 HSV 色彩空间的H分量建立目标直方图模型,仍然只是依据目标的色彩信息来进行跟踪,当目标与背景颜色接近或者被其他物体遮挡时,CamShift 会自动将其包括在内,导致跟踪窗口扩大,有时甚至会将跟踪窗口扩大到整个视频大小,导致目标定位的不准确,连续跟踪下去造成目标的丢失。
四、程序流程:
1、打开摄像头
2、显示帮助信息:
3、鼠标响应:当鼠标左键按下时,保存此时的坐标origion= Pont(x,y),并且
selectObject=1;执行if里面的语句,selection保存鼠标选择区域,当鼠
标松开时,selectObject=0,trackObject=-1。
4、如果没有按下暂停键”c”,图像由BGR转化为HSV,inRange()将HSV中的
(0-180,30-256,10-256)保存在mask中,分离H通道并保存在hue中。
5、如果鼠标选择区域松开后,根据鼠标的选择区域计算直方图并且归一化到
0-255,将selection区域保存在trackWindow中,且track Object=1。
6、绘制目标区域的方向投影的直方图:创建buf(1*16的3通道矩阵,并赋值
为(0-168,255,255),以这个渐变的颜色作为直方图的色彩显示。)
7、计算反向投影,,就是首先计算图像中的某一特征,然后根据特征寻找图像中
存在的特征。
8、目标跟踪:CamShift函数返回一个有方向角度的矩阵。该函数的实现首先是
利用meanshift算法计算出要跟踪的中心,然后调整初始窗口的大小位置和方
向角度。在camshift内部调用了meanshift算法计算目标的重心。
9、如果跟踪的矩形框的面积小于1,重新定义跟踪窗口,否则保持不变
10、转化为BGR,并绘制出椭圆形状,如果继续跟踪,转到步奏8。
函数解释:
1、inRange(hsv,Scalar(0,smin,MIN(_vmin,-vmax)),Scalar(180,256,MAX(_vmin,-vm
ax)),mask):检查元素的取值范围是否在另两个矩阵的元素取值之间,返回ma
sk验证矩阵。
2、mixChannels(&hsv,1,&hue,1.ch,1):抽取 hsv图像中的通道0
&hsv:一系列输入图像的数组, 被拷贝的通道的来源
1:输入数组中图像的数目
&hue:一系列目的图像的数组, 储存拷贝的通道
1:目的数组中图像的数目
ch[] = {0,0}:通道索引对的数组,指示如何将输入图像的某一通道拷贝到目的
图像的某一通道。在这里,&hsv图像的Hue(0) 通道被拷贝到&hue图像(单
通道)的0 通道。
1:通道索引对德数目
3、roi(hue,selection):设置hue中的感兴趣区域,如果设置了感兴趣区域,那么在使
用OpenCV函数的时候,只会对ROI区域操作,其它区域忽略。
4、maskroi(mask,selection):掩码
5、calcHist(&roi,1,0,maskroi,hist,1,&hist,&phranges):计算直方图
&roi:输入图像
1:第一个参数中存放了多少张图像
0:需要统计的通道索引
maskroi:输入图像的mask,可选的操作掩码,这里的非零掩码元素用于标记出统计直方图的数组元素数据
hist:,输出的目标直方图
1:需要计算的直方图的维度
&hist:存放每个维度的直方图尺寸的数组
&phranges:每一维数取值范围。
6、normalize(hist,hist,0,255,CV_MINMAX):归一化
7、Rectangle(histimg,Point(i*binW,histimg.rows),Point((i+1)*binW),histimg.rows-val),S
calar(buf.at<Vec3b>(i),-1,8);
C++: void rectangle(Mat& img,Point pt1, Pointpt2, const Scalar&color, intthickness=1,intlineType=8, intshift=0)
C++: void rectangle(Mat& img,Rect rec, const Scalar&color, intthickness=1, intlineType=8,intshift=0 )
img – 画矩形的对象
pt1 – 矩形的一个顶点,左上角的.
pt2 – 另一个顶点,右下角的.
rec – 确定矩形的另一种方式,给左上角坐标和长宽
color – 指定矩形的颜色或亮度(灰度图像)
thickness – 矩形边框的粗细. 负值(like CV_FILLED)表示要画一个填充的矩形
lineType – 边框线型.
8 (or 0) - 8-connected line(8邻接)连接线。4 - 4-connected line(4邻接)连接线。CV_AA - antialiased 线条。
8、calcBackProject(&hue,1,0,hist,backProj,&phranges)
Hue:输入图像
1:输入图像的个数
0:需要统计的通道索引
Hist:输入的直方图
backProj:目标反向投影阵列,必须为单通道
Phranges:每一个维度数组的边界
9、CamShift(backProj,trackWindow,TerCriteria(CV_TERMCRIT_EPS |
CV_TERMCRIT_ITER,10,1))
backProj:输入图像直方图的反向投影图
trackWindow:跟踪目标的初始位置矩形框
TerCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER,10,1):算法结束条件