目录
前言
一直以为,camshift算法就是cvCamShift
API实现,经过几天的学习。突然发现,camshift算法其实包含3部分:获取概率密度图,找到概率密度图的最大密度位置,最后迭代。这部分先参考:
OpenCV直方图与匹配(二)——反向投影
学习!分享!感谢!
MeanShift函数解析
功能:在反向投影图中发现目标中心。在给定反向投影和初始搜素窗口位置的情况下,用迭代方法寻找目标中心。当搜索窗口中心的移动小于某个给定值时或者函数已经达到最大迭代次数时停止迭代。函数返回迭代次数。
int cvMeanShift( const CvArr* prob_image, CvRect window,
CvTermCriteria criteria, CvConnectedComp* comp );
参数1:prob_image
目标直方图的反向投影
参数2:window
初始搜素窗口
参数3:criteria
确定窗口搜索停止的准则
参数4:comp
生成的结构,包含收敛的搜索窗口坐标(comp->rect)与窗口内部所有像素点的和(comp->area字段)
CamShift函数解析
功能:发现目标中心、尺寸和方向
int cvCamShift( const CvArr* prob_image, CvRect window, CvTermCriteria criteria,
CvConnectedComp* comp, CvBox2D* box=NULL );
参数1:prob_image
目标直方图的反向投影
参数2:window
初始搜素窗口
参数3:criteria
确定窗口搜索停止的准则
参数4:comp
生成的结构,包含收敛的搜索窗口坐标(comp->rect)与窗口内部所有像素点的和(comp->area字段)
参数5:box
目标的带边界盒子。如果非NULL,则包含目标的尺寸和方向。cvCamShift
调用函数cvMeanShift
寻找目标中心,然后计算目标尺寸和方向。最后返回cvMeanShift
中的迭代次数。
CamShift跟踪原理
meanshift算法就是利用概率密度的梯度爬升来寻找局部最优。它要做的就是输入一个在图像的范围,然后一直迭代知道满足要求。
- 为什么输入必须是反向投影图?
反向投影图其实就是一张概率密度图。经过反向投影时输入是一个目标图像的直方图,另一个输入时当前图像,经过投影变换,输出的图像的像素表示一种概率,就是当前图像是目标图像一部分的概率。如果这个点越亮,说明这个点属于物体的概率越大。
int turns = cvCamShift (
imgBackProjection,
rectCamSW, // x,y,width,height, cvrect, window to search over
cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 20, 1 ), // criteria
&compTrack, // x,y, width, height
&boxTrack
// cvbox2d newly resized box, criteria for next imgFrame (as updated by tracker), center, size and angle
);
- CamshiftDemo工作过程
步骤1:选中物体,记录输入的方框和物体
步骤2:求有关物体的反向投影图
步骤3:根据反向投影图和输入的方框进行meanshift
迭代,由于它是重心移动,即向反向投影图中概率大的地方移动,所以始终会移动到目标上。
步骤4:下一帧图像使用上一帧输入的方框来迭代。
总结:反向投影图是一幅反映当前图像中每个像素点含有目标概率的图而已。
camshift利用目标的颜色直方图,将图像转换为颜色概率分布图,初始化一个搜索窗的大小和位置,并根据上一帧得到的结果自适应调整搜索窗口的位置和大小,从而定位出当前当前图像中目标的中心位置。
mixChannels
void mixChannels (const Mat* src , int nsrc , Mat* dst , int ndst , const int*
fromTo , size_t npairs );
功能:把输入的矩阵的某些通道拆分复制给对应的输出矩阵的某些通道中。
OpenCV之mixChannels()函数使用说明