(一)跟踪
最近与同学完成了一个小项目,做了其中的一部分工作,现在答辩完了,也就可以拿出来分享一下思路:
跟踪是在识别手之后开始的,手的识别是由Hu矩加上轮廓的面积周长比:
double contArea = fabs(contourArea(contours[i]));
double contLength = arcLength(contours[i], false);
double contCircularity = contLength*contLength / contArea;//周长面积比
Moments omement;
omement = moments(contours[i]);
Mat hu;
HuMoments(omement, hu);//hu矩,主要用到前两个矩 <span style="font-family: Arial, Helvetica, sans-serif;">//然后将两者结合起来判断</span>
(这个可以加上各种学习算法优化,但不是我的主要想谈论的点,因为学习之类的算法接触得比较少,不理解原理),也就是说,识别到手之后,给跟踪器一个初始化的框,这个框的选取非常重要,可以通过框选中的内容的特征如颜色直方图,梯度等,这些决定之后的跟踪是否能够很好地收敛于目标物体。
跟踪一开始打算采取的是CamShift跟踪,因为它能够简单地判断是否跟丢物体,
简单地来说,CamShift通过MeanShift和颜色直方图来获得当前帧目标的一些尺度信息,然后再利用上一帧得到的结果作为初始值一直迭代下去,直到不符合跟踪条件,跳出跟踪。MeanShift获取反向投影图的过程是这样的:图像--->直方图--->反向投影图,反向投影亮的地方,表明物体出现在该处的概率大,可以看作是概率密度函数的表征:
unsigned int colourModel::findBin(unsigned char R,unsigned char G,unsigned char B)
{
//根据RGB颜色返回直方图的位置
unsigned int r,g,b;
r = (unsigned int)floor( (float)(R/BINSIZE) );
g = (unsigned int)floor( (float)(G/BINSIZE) );
b = (unsigned int)floor( (float)(B/BINSIZE) );
return (r + BPC*g + BPC*BPC*b);
}
之后选取Epanechnikov作为核函数计算目标模型直方图,用公式表示就是:
double CMsTracker::kernel(int x,int y,int half_x,int half_y)
{
double euclideanDistance = sqrt( pow( ( (double)(x)/(double)(half_x) ) ,2.0) +pow( ( (double) (y)/(double)(half_y) ) ,2.0) );
if (euclideanDistance > 1)
return( 0.0);
else
return(1.0-pow(euclideanDistance,2));
}
void CMsTracker::evalKernel (double*** kArray,int half_x,int half_y)//计算核函数直方图
{
for (int x = -half_x; x < half_x; x+&