计算机视觉CV 之 CMT跟踪算法分析四

1 前言

在上一部分我们已经分析到了计算特征点的缩放和旋转,这里最后分析去掉不好的特征点的方法。

2 最后步骤分析

vote的基本思想就是这些特征点相对中心的相对距离在把缩放旋转考虑进去之后是相对不变的,也就是按道理下一帧的特征点相对中心的位置是不变的。

但是由于图像本身的变化,不可能得到完全一样的相对位置,这个时候,有一些会离中心近,有一些会偏差很大。那么,作者就采用聚类的方法,选择最大的一类作为最好的特征点。其他的不要。

上面这个图应该可以很好的理解这个过程。再看作者自己官网上的图大家应该可以理解。

代码上作者找了一个聚类的库来做,具体我没有深入分析了:

void Consensus::findConsensus(const vector<Point2f> & points, const vector<int> & classes,
        const float scale, const float rotation,
        Point2f & center, vector<Point2f> & points_inlier, vector<int> & classes_inlier)
{

    //If no points are available, reteurn nan
    if (points.size() == 0)
    {
        center.x = numeric_limits<float>::quiet_NaN();
        center.y = numeric_limits<float>::quiet_NaN();

        return;
    }

    //Compute votes 计算投票:基本方法就是计算点相对于正规化且计算其旋转加缩放后的点的相对位置 保持相对一致
    vector<Point2f> votes(points.size());
    for (size_t i = 0; i < points.size(); i++)
    {
        votes[i] = points[i] - scale * rotate(points_normalized[classes[i]], rotation);
    }

    t_index N = points.size();

    float * D = new float[N*(N-1)/2]; //This is a lot of memory, so we put it on the heap
    cluster_result Z(N-1);

    //Compute pairwise distances between votes
    //计算votes点之间的相对距离
    int index = 0;
    for (size_t i = 0; i < points.size(); i++)
    {
        for (size_t j = i+1; j < points.size(); j++)
        {
            //TODO: This index calculation is correct, but is it a good thing?
            //int index = i * (points.size() - 1) - (i*i + i) / 2 + j - 1;
            // 计算相对距离
            D[index] = norm(votes[i] - votes[j]);
            index++;
        }
    }

    MST_linkage_core(N,D,Z);

    union_find nodes(N);

    //Sort linkage by distance ascending
    std::stable_sort(Z[0], Z[N-1]);

    //S are cluster sizes
    int * S = new int[2*N-1];
    //TODO: Why does this loop go to 2*N-1? Shouldn‘t it be simply N? Everything > N gets overwritten later
    for(int i = 0; i < 2*N-1; i++)
    {
        S[i] = 1;
    }

    t_index parent = 0; //After the loop ends, parent contains the index of the last cluster
    for (node const * NN=Z[0]; NN!=Z[N-1]; ++NN)
    {
        // Get two data points whose clusters are merged in step i.
        // Find the cluster identifiers for these points.
        t_index node1 = nodes.Find(NN->node1);
        t_index node2 = nodes.Find(NN->node2);

        // Merge the nodes in the union-find data structure by making them
        // children of a new node
        // if the distance is appropriate
        if (NN->dist < thr_cutoff)
        {
            parent = nodes.Union(node1, node2);
            S[parent] = S[node1] + S[node2];
        }
    }

    //Get cluster labels
    int * T = new int[N];
    for (t_index i = 0; i < N; i++)
    {
        T[i] = nodes.Find(i);
    }

    //Find largest cluster
    int S_max = distance(S, max_element(S, S + 2*N-1));

    //Find inliers, compute center of votes
    points_inlier.reserve(S[S_max]);
    classes_inlier.reserve(S[S_max]);
    center.x = center.y = 0;

    for (size_t i = 0; i < points.size(); i++)
    {
        //If point is in consensus cluster
        if (T[i] == S_max)
        {
            points_inlier.push_back(points[i]);
            classes_inlier.push_back(classes[i]);
            center.x += votes[i].x;
            center.y += votes[i].y;
        }

    }

    center.x /= points_inlier.size();
    center.y /= points_inlier.size();

    delete[] D;
	delete[] S;
	delete[] T;

}

通过这样的算法得到inlier

然后在代码中,作者又做了一次匹配,matchlocal,在我看来和findconsensus的目的是一样的,也是通过相对的点的距离来判定是不是要的特征,然后在对这些特征做一次匹配,是就选进来,最后将inlier的点和matchlocal的点合并,作为最终的特征点。

matchlocal的代码如下:

void Matcher::matchLocal(const vector<KeyPoint> & keypoints, const Mat descriptors,
        const Point2f center, const float scale, const float rotation,
        vector<Point2f> & points_matched, vector<int> & classes_matched)
{

    if (keypoints.size() == 0) {
        return;
    }

    //Transform initial points
    vector<Point2f> pts_fg_trans;
    pts_fg_trans.reserve(pts_fg_norm.size());
    for (size_t i = 0; i < pts_fg_norm.size(); i++)
    {
        // 同样是计算相对位置
        pts_fg_trans.push_back(scale * rotate(pts_fg_norm[i], -rotation));
    }

    //Perform local matching
    for (size_t i = 0; i < keypoints.size(); i++)
    {
        //Normalize keypoint with respect to center
        Point2f location_rel = keypoints[i].pt - center;

        //Find potential indices for matching
        vector<int> indices_potential;
        for (size_t j = 0; j < pts_fg_trans.size(); j++)
        {
            // 计算位置偏差
            float l2norm = norm(pts_fg_trans[j] - location_rel);

            // 设置一个阈值
            if (l2norm < thr_cutoff) {
                indices_potential.push_back(num_bg_points + j);
            }

        }

        //If there are no potential matches, continue
        if (indices_potential.size() == 0) continue;

        //Build descriptor matrix and classes from potential indices
        Mat database_potential = Mat(indices_potential.size(), database.cols, database.type());
        for (size_t j = 0; j < indices_potential.size(); j++) {
            database.row(indices_potential[j]).copyTo(database_potential.row(j));
        }

        //Find distances between descriptors
        vector<vector<DMatch> > matches;
        // 对选出的特征点进行特征匹配
        bfmatcher->knnMatch(descriptors.row(i), database_potential, matches, 2);

        vector<DMatch> m = matches[0];

        float distance1 = m[0].distance / desc_length;
        float distance2 = m.size() > 1 ? m[1].distance / desc_length : 1;

        if (distance1 > thr_dist) continue;
        if (distance1/distance2 > thr_ratio) continue;

        int matched_class = classes[indices_potential[m[0].trainIdx]];

        points_matched.push_back(keypoints[i].pt);
        classes_matched.push_back(matched_class);
    }

}

好了,由于时间关系,CMT算法就分析到这了。有很多不足,可能也分析不到位甚至有错的地方,请批评指正。

文章原创,转载麻烦注明出处:blog.csdn.net/songrotek

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-12 17:40:19

计算机视觉CV 之 CMT跟踪算法分析四的相关文章

计算机视觉CV 之 CMT跟踪算法分析二

1 前言 在上一篇文章中,我对CMT算法做了初步的介绍,并且初步分析了一下CppMT的代码,在本篇文章中,我将结合作者的论文更全面细致的分析CMT算法. 这里先说明一下,作者关于CMT算法写了两篇文章: Consensus-based Matching and Tracking of Keypoints for Object Tracking (wacv2014 best paper reward) Clustering of Static-Adaptive Correspondences fo

计算机视觉CV 之 CMT跟踪算法分析3

1 前言 在上一篇blog中,我们分析了CMT的整体算法流程及前面几步的实现分析,接下来我们继续分析后面的几步. 2 Step 4,5,6 特征点匹配与数据融合 这几步就是通过跟踪和特征匹配来获取这一帧的特征点,将两者融合在一起. 上一篇文章分析了光流,这里再分析一下特征匹配.源代码如下: //Detect keypoints, compute descriptors 计算当前图像的关键点 vector<KeyPoint> keypoints; detector->detect(im_g

CV学习资料《卷积神经网络与视觉计算》+《深度学习实践计算机视觉》+《视觉SLAM十四讲从理论到实践》电子资料代码分析

视觉和图形学真是一家,基础都一样! 如果学习图像识别,计算机视觉,推荐电子书<视觉SLAM十四讲:从理论到实践>,系统介绍了视觉SLAM(同时定位与地图构建)所需的基本知识与核心算法,既包括数学理论基础,如三维空间的刚体运动.非线性优化,又包括计算机视觉的算法实现,例如多视图几何.回环检测等. 一个周读完了,代码很清晰!Particle Filtering,KF,EKF, Batch Optimization, Lie Group,ICP,LK光流... 尤其惊喜的是文末作者看好的IMU-SL

自然语言处理(nlp)比计算机视觉(cv)发展缓慢,而且更难!

https://mp.weixin.qq.com/s/kWw0xce4kdCx62AflY6AzQ 1.  抢跑的nlp nlp发展的历史非常早,因为人从计算机发明开始,就有对语言处理的需求.各种字符串算法都贯穿于计算机的发展历史中.伟大的乔姆斯基提出了生成文法,人类拥有的处理语言的最基本框架,自动机(正则表达式),随机上下文无关分析树,字符串匹配算法KMP,动态规划. nlp任务里如文本分类,成熟的非常早,如垃圾邮件分类等,用朴素贝叶斯就能有不错的效果.20年前通过纯统计和规则都可以做机器翻译

【计算机视觉】粒子滤波跟踪

粒子滤波步骤 1.初始化随机选取N个点,权重统一赋值1/N 2.选取目标特征,颜色直方图等等,用于获取先验概率密度,对比相似度 3.确定状态转移矩阵,用于预测下一帧目标位置 循环开始 4.根据状态转移矩阵,对每个粒子,预测目标新位置 5.获得系统观测值,计算观测位置处特征 6.计算每个预测位置处特征,与观测处位置特征对比,相似度高的赋予较大的权重,反之,赋予较小的权重 7.对粒子加权获取当前的目标最佳位置 8.粒子重采样 循环结束 上面是我自己的理解,有些问题仍然不明白: 1.都有观测值了还修正

计算机视觉 之 在iOS上测试跟踪算法Visual Object Tracking Algorithm

前言 在计算机视觉CV领域,视觉跟踪是其中一个重要的子问题.从我的角度看,视觉跟踪就是用在机器人上,用在移动设备上,因此,何不把一些跟踪算法放在iPhone上看看实际的跟踪效果.这才是最真实的对比,使用一些视频毕竟不实际,而且关键是不能很好的对比实时性.对于移动设备而已,实时性是最重要的吧.之所以有跟踪问题的出现,也是因为绝大多数的物体检测Object Detection算法实在是太慢了,根本无法用在视频当中.因此才有了Object Tracking的问题.最终的目标也就是Real Time V

为什么深度学习几乎成了计算机视觉研究的标配?

https://zhuanlan.zhihu.com/p/21533690 标签: 深度学习计算机视觉研究标配 2016-07-09 16:38 1951人阅读 评论(0) 收藏 举报  分类: 计算机视觉CV(308)  目录(?)[+] 本次CVPR 2016上,深度学习几乎成了如今计算机视觉研究的标配,人脸识别.图像识别.视频识别.行人检测.大规模场景识别的相关论文里都用到了深度学习的方法,加上Google,Facebook这样的大企业助力,很多人疑惑,为什么深度学习相比其它的AI实现方法

Sql Server Profiler保存与重演跟踪

重演跟踪的作用 可以将一个跟踪当做测试工具,当按照正确的顺序调用某些存储过程是肯能会重新生成特定的故障. 跟踪模板 保存跟踪有四个选项(文件->另存为) 1. 跟踪文件选项用来将数据保存成二进制格式的文件中,保存数据最快速,同时也是占用磁盘字节最少的方法. 2. 跟踪表选项用来将数据保存至用户选择的数据库中一个新的或预先创建好的表.适用于适用T-SQL 操作或报告数据. 3. 跟踪XML文件选项将数据保存到一个XML格式的文件中. 4. 重演跟踪XML文件选项将数据保存至一个XML文本文件,但是

Linux内核跟踪之syscall tracer 【转】

转自:http://blog.chinaunix.net/uid-20543183-id-1930847.html ------------------------------------------ 本文系本站原创,欢迎转载! 转载请注明出处:http://ericxiao.cublog.cn/ ------------------------------------------ 一: 前言 Syscall tracer是用来跟踪系统调用的,它会检测所有系统调用的入口和出口,再将相关的信息保存