zoukankan      html  css  js  c++  java
  • OpenCV —— 跟踪与运动

    理解物体运动主要包含两个部分:识别和建模

    识别在视频流后续的帧中找出之前某帧镇南关的感兴趣物体

    寻找角点

    可跟踪的特征点都称为角点,从直观上讲,角点(而非边缘)是一类含有足够信息且能从当前帧和下一帧中都能提取出来的点

    Harris 角点位于图像二阶导数的自相关矩阵有两个最大特征值的地方,这在本质上表示以此点为中心周围存在至少两个不同方向的纹理,正如实际的角点是由至少两个边缘相交于一点而产生

    cvGoodFeaturesToTrack 采用Shi 和Tomasi提出的方法,先计算二阶导数,在计算特征值,返回满足易于跟踪的定义的一系列点(角点数组)

    void cvGoodFeaturesToTrack(

    const CvArrr* image,   8为或32位单通道图像

    CvArr* eigImage,   每个元素包含了输入图像中对应点的最小特征值

    CvArr* tempImage,   临时变量

    CvPoint2D32f* corners,   输出

    int * corner_count,   可以返回的最大角点数目

    double quality_level,   认为是角点的可接受的最小特征值,不应超过1

    double min_distance,  剔除距离较近的角点

    const CvArr* mask = NULL,

    int block_size=3,

    int use_harris=0,

    double k=0.4

    );


    亚像素级角点

    cvFindCornerSubPix 用于发现亚像素精度的角点位置

    实际计算亚像素级的角点位置时,解的是一个点积的表达式为0的方程组,其中每一个方程都是由q邻域的一个点产生。

    搜索窗口的中心是整数坐标值的角点并从中心点在每个方向上扩展窗口尺寸指定的像素


    不变特征

    SIFT 在一点处检测主要梯度方向,根据这个方向记录局部梯度直方图结果,拥有旋转不变性


    光流

    可以将图像中的每个像素与速度关联,或者等价地,与表示像素在连续两帧之间的位移关联。这样得到的是稠密光流 —— 每个像素都与速度关联

    稀疏光流的计算需要在被跟踪之前指定一组点 —— 角点

    Lucas – Kanade 方法

    LK算法只需要每个兴趣点周围小窗口的局部信息,所以它可以应用于稀疏内容。

    不足 —— 较大的运动会将点移出这个小窗口

    解决 —— 金字塔,跟踪图像金字塔允许小窗口捕获较大的运动

    算法原理

    1,亮度恒定 —— 场景中物体被跟踪部分的亮度不变

    2,时间连续或者运动是“小运动” —— 运动相对于帧率是缓慢的

    3,空间一致 —— 相邻的店保持相邻

    在图像金字塔的最高层计算光流,用得到的运动估计结果作为下一层金字塔的起始点,重复这个过程直到到达金字塔的最底层,这样就将不满足运动假设的可能性降到最小。

    cvCalcOpticalFlowLK —— 非金字塔的LK稠密光流算法

    cvCalcOpticalFlowPyrLK —— 金字塔的LK代码

      图像金字塔的计算量较大,计算得到的图像对的后面一帧被作为下次计算的图像对的初始帧

    #include <cv.h>
    #include <cxcore.h>
    #include <highgui.h>
    
    
    const int MAX_CORNERS=500;
    
    int main(int argc,char** argv)
    {
        IplImage* imgA=cvLoadImage("image0.jpg",CV_LOAD_IMAGE_GRAYSCALE);
        IplImage* imgB=cvLoadImage("image1.jpg",CV_LOAD_IMAGE_GRAYSCALE);
    
        CvSize img_sz=cvGetSize(imgA);
        int win_size=10;
    
        IplImage* imgC=cvLoadImage("",CV_LOAD_IMAGE_UNCHANGED);
    
        // get the features
    
        IplImage* eig_image=cvCreateImage(img_sz,IPL_DEPTH_32F,1);
        IplImage* tmp_image=cvCreateImage(img_sz,IPL_DEPTH_32F,1);
    
        int corner_count=MAX_CORNERS;
        CvPoint2D32f* cornersA=new CvPoint2D32f[MAX_CORNERS];
    
        cvGoodFeaturesToTrack(
            imgA,
            eig_image,
            tmp_image,
            cornersA,
            &corner_count,
            0.01,
            5.0,
            0,
            3,
            0,
            0.04);
    
        cvFindCornerSubPix(
            imgA,
            cornersA,
            corner_count,
            cvSize(win_size,win_size),
            cvSize(-1,-1),
            cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03);
            );
    
            // LK
            
            char features_found[MAX_CORNERS];
            float fearture_errors[MAX_CORNERS];
            
            CvSize pyr_sz=cvSize(imgA->width+8,imgB->height/3);
            
            IplImage* pyrA=cvCreateImage(pyr_sz,IPL_DEPTH_32F,1);
            IplImage* pyrB=cvCreateImage(pyr_sz,IPL_DEPTH_32F,1);
    
            CvPoint2D32f* cornersB=new CvPoint2D32f[MAX_CORNERS];
    
            cvCalcOpticalFlowPyrLK(
                imgA,
                imgB,
                pyrA,
                pyrB,
                cornersA,
                cornersB,
                corner_count,
                cvSize(win_size,win_size),
                5,
                features_found,
                fearture_errors,
                cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.3),
                0
                );
    
            // 结果显示
            for (int i=0;i<corner_count;i++)
            {
                if (features_found[i]==0||fearture_errors[i]>550)
                {
                    printf("Error is %f
    ",fearture_errors[i]);
                    continue;
                }
                printf("Got it
    ");
                CvPoint  p0=cvPoint(cvRound(cornersA[i].x),cvRound(cornersA[i].y));
    
                cvPoint p1=cvPoint(cvRound(cornersB[i].x),cvRound(cornersB[i].y));
    
                cvLine(imgC,p0,p1,CV_RGB(255,0,0),2);
            }
    
    }

    稠密跟踪方法

    亮度恒定假设,速度的平滑约束 (通过对光流速度分量的二阶导数进行规则化获得)

    与LK算法一样,HornSchunck方法也要通过迭代来解微分方程

    cvCalcOpticalFlowHS


    mean – shift

    在一组数据的密度分布中寻找局部极值的稳定的方法

    mean – shift 等价于先对连续分布用 mean-shift核进行卷积,然后再应用爬山算法

    cvMeanShift

    反向投影图 —— 概率密度图,用输入图像的某一位置上像素值对应直方图bin上的值来代替该像素值

    Camshift 搜索窗口会自我调整尺寸

    cvCamShift


    运动模板

    可应用于姿态识别

    运动模板需要知道物体的轮廓

    运动历史图像

    OpenCV 中完成运动模板构建的函数是 cvUpdateMotionHistory

    一旦运动模板记录了不同时间的物体轮廓,就可以用计算运动模板图像的梯度来获取全局运动信息

    cvCalcMotionGradient 计算梯度 (输入有允许的最小和最大的梯度值)

    cvCalcGlobalOrientation 计算有效梯度方向矢量和来获取全局运动方向

    cvSegmentMotion 分割和计算局部运动


    预估器

    预测阶段 —— 用从过去得到的信息进一步修正模型以取得下一个将会出现的位置

    矫正阶段 —— 获得一个测量,然后与基于前一次测量的预期值进行调整

    Kalman 滤波器

    若有一组强而合理的假设,给出系统的历史测量值,则可以建立最大化这些早前测量值的后验概率的系统状态模型

    假设:1,被建模的系统是线性的;2,影响测量的噪声属于白噪声;3,噪声本质上是高斯分布的

    额,这个内容挺多的,应该专门看一下

  • 相关阅读:
    fragment、ListFragment使用ListView及自定义Listview等初始化操作
    【LeetCode】 sort list 单清单归并
    HDU 1251 统计拼图 Trie解决问题的方法
    Oracle推断领域包括中国
    hust1384---The value of F[n]
    ffmpeg参数具体解释
    什么是大数据的核心价值?
    还是畅通project(杭州电1233)
    Redis源代码分析(二十七)--- rio制I/O包裹
    回想一下著名的BigTable论题
  • 原文地址:https://www.cnblogs.com/sprint1989/p/3816639.html
Copyright © 2011-2022 走看看