博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
mean sift代码解析
阅读量:4149 次
发布时间:2019-05-25

本文共 4199 字,大约阅读时间需要 13 分钟。

在做目标跟踪的时候,mean sift算法是堪称经典,在opencv2.4.6中,mean sift的函数原型为如下:

       / /! updates the object tracking window using meanshift algorithm

       CV_EXPORTS_W int meanShift( InputArray probImage, CV_OUT CV_IN_OUT Rect& window, TermCriteria criteria );

其中,probImage:在目标跟踪时,probImage表示我们待搜索目标图像的反向投影图(概率分布图),其实就是一幅图像

                    window:是初始矩形框大小,这里它既是输入,又是输出

                    criteria:迭代搜索的准则(如需要迭代的次数和需要控制最小值)

在opencv2.4.6中,我们可以看到meanShift的源代码如下:

int cv::meanShift( InputArray _probImage, Rect& window, TermCriteria criteria ){    CvConnectedComp comp;    Mat probImage = _probImage.getMat(); //getMat()函数将传入的参数转换为Mat的结构,方便你函数内的操作   	CvMat c_probImage = probImage;    int iters = cvMeanShift(&c_probImage, window, (CvTermCriteria)criteria, &comp );    window = comp.rect;  //更新窗口    return iters;        //返回迭代次数}
我们可以看到,实际上meanShift本身也调用了cvMeanShift函数(这个函数在opencv2.0之前使用),也就是说meanShift函数,只是在cvMeanShift的基础上进行了封装而已,并且我们也可以看到,meanShift更新window窗口时通过comp来实现的,为此,我们需要进一步分析cvMeanShift函数的源代码。

        cvMeanShift函数的原型为:

        int cvMeanShift( const void* imgProb, CvRect windowIn,CvTermCriteria criteria, CvConnectedComp* comp ) 

其中, 参数1:imgProb:输入的一张图像(跟踪的时候,这是一张反向投影图)

                 参数2:windowln:开始迭代的方框

                 参数3:criteria: 迭代的条件

                 参数4:comp: 作为输出,迭代完成的位置

cvMeanShift函数源代码如下:

cvMeanShift( const void* imgProb, CvRect windowIn, CvTermCriteria criteria, CvConnectedComp* comp ){    CvMoments moments;      //计算多边形和光栅形状的最高达三阶的所有矩:    int    i = 0, eps;    CvMat  stub, *mat = (CvMat*)imgProb;  //概率分布图    CvMat  cur_win;    CvRect cur_rect = windowIn;           //初始的搜索窗口     if( comp )        comp->rect = windowIn;    moments.m00 = moments.m10 = moments.m01 = 0; //0矩,1矩	//得到一个矩阵    mat = cvGetMat( mat, &stub );    if( CV_MAT_CN( mat->type ) > 1 )        CV_Error( CV_BadNumChannels, cvUnsupportedFormat );    if( windowIn.height <= 0 || windowIn.width <= 0 )        CV_Error( CV_StsBadArg, "Input window has non-positive sizes" );	//重新设置搜索框大小:让概率图的窗口和初始的矩形框做交集	//windowIn被更新了    windowIn = cv::Rect(windowIn) & cv::Rect(0, 0, mat->cols, mat->rows);	//确定窗口搜索停止的准则(停止迭代的条件)    criteria = cvCheckTermCriteria( criteria, 1., 100 );	//收敛值    eps = cvRound( criteria.epsilon * criteria.epsilon );	//开始迭代,默认的迭代为:100次    for( i = 0; i < criteria.max_iter; i++ )    {        int dx, dy, nx, ny;        double inv_m00; //0阶矩		//确定当前搜索窗口的大小(交集运算)        cur_rect = cv::Rect(cur_rect) & cv::Rect(0, 0, mat->cols, mat->rows);       		//cur_rect为0		if( cv::Rect(cur_rect) == cv::Rect() )        {            cur_rect.x = mat->cols/2;            cur_rect.y = mat->rows/2;        }		//选择最大的边框        cur_rect.width = MAX(cur_rect.width, 1);        cur_rect.height = MAX(cur_rect.height, 1);		//从mat提取cur_rect大小的区域(cur_win)		//cvGetSubRect作用是从一个图像中提取出来一部分        cvGetSubRect( mat, &cur_win, cur_rect );		//对提取的cur_win,计算它的矩(m00,m01,m10)		//函数 cvMoments 计算最高达三阶的空间和中心矩,并且将结果存在结构 moments 中。		//矩用来计算形状的重心(亮度),面积,主轴和其它的形状特征,如 7 Hu 不变量等.        cvMoments( &cur_win, &moments ); //计算多边形(图像)和光栅形状的最高达三阶的所有矩(中心距):        /* Calculating center of mass */        if( fabs(moments.m00) < DBL_EPSILON )            break;        inv_m00 = moments.inv_sqrt_m00*moments.inv_sqrt_m00; //m00的倒数:1/m00        dx = cvRound( moments.m10 * inv_m00 - windowIn.width*0.5 ); //moments.m10 * inv_m00:当前窗口图像cur_win的重心的x:x=m10/m00        dy = cvRound( moments.m01 * inv_m00 - windowIn.height*0.5 );//moments.m01 * inv_m00: 当前窗口图像cur_win的重心的y:y=m01/m00		//将当前矩阵进行平移dx,dy        nx = cur_rect.x + dx;        ny = cur_rect.y + dy;        if( nx < 0 )            nx = 0;        else if( nx + cur_rect.width > mat->cols )            nx = mat->cols - cur_rect.width;        if( ny < 0 )            ny = 0;        else if( ny + cur_rect.height > mat->rows )            ny = mat->rows - cur_rect.height;        dx = nx - cur_rect.x;        dy = ny - cur_rect.y;		//更新当前矩阵的左上角坐标        cur_rect.x = nx;        cur_rect.y = ny;        /* Check for coverage centers mass & window */        if( dx*dx + dy*dy < eps )            break;    }		//迭代完成    if( comp ) //comp(位置)作为返回值    {        comp->rect = cur_rect; //最终有用的返回值        comp->area = (float)moments.m00;    }    return i;}
从上面的源代码,可以看出meansift算法在这里的作用就是在不断在寻找
矩形框框定的图像的重心,并不断迭代,即迭代的过程是向重心(x=m10/m00,y=m01/m00)转移.

在代码实现的过程中使用了关于的一些东西(空间距,中心距)可以参考[2],关于meansift的理论部分,可以参考[1]。

参考文献:

1. 

2.

转载地址:http://jbpti.baihongyu.com/

你可能感兴趣的文章
Oracle 分组排序函数
查看>>
删除weblogic 域
查看>>
VMware Workstation 14中文破解版下载(附密钥)(笔记)
查看>>
日志框架学习
查看>>
日志框架学习2
查看>>
SVN-无法查看log,提示Want to go offline,时间显示1970问题,error主要是 url中 有一层的中文进行了2次encode
查看>>
NGINX
查看>>
Qt文件夹选择对话框
查看>>
DeepLearning tutorial(5)CNN卷积神经网络应用于人脸识别(详细流程+代码实现)
查看>>
DeepLearning tutorial(6)易用的深度学习框架Keras简介
查看>>
DeepLearning tutorial(7)深度学习框架Keras的使用-进阶
查看>>
流形学习-高维数据的降维与可视化
查看>>
Python-OpenCV人脸检测(代码)
查看>>
python+opencv之视频人脸识别
查看>>
人脸识别(OpenCV+Python)
查看>>
6个强大的AngularJS扩展应用
查看>>
网站用户登录系统设计——jsGen实现版
查看>>
第三方SDK:讯飞语音听写
查看>>
第三方SDK:JPush SDK Eclipse
查看>>
第三方开源库:imageLoader的使用
查看>>