探秘SLAM之RANSAC算法

4 篇文章 5 订阅
2 篇文章 0 订阅

一.初识RANSAC算法

  随机抽样一致算法(RANdom SAmple Consensus),简称RANSAC算法 ,采用迭代的方式从一组包含离群的被观测数据中估算出数学模型的参数。其广泛应用在计算机视觉领域和数学领域,例如直线拟合、平面拟合、计算图像或点云间的变换矩阵、计算基础矩阵等方面。

  RANSAC算法基本思想:

  1. 从数据集中随机选出一组局内点(其数目要保证能够求解出模型的所有参数),计算出一套模型参数。

  2. 用得到的模型去测试其他所有的数据点,如果某点的误差在设定的误差阈值之内,就判定其为局内点,否则为局外点,只保留目前为止局内点数目最多的模型,将其记录为最佳模型。

  3. 重复执行1,2步足够的次数(即达到预设的迭代次数)后,使用最佳模型对应的局内点来最终求解模型参数。

  4. 最后可以通过估计局内点与模型的错误率来评估模型。

  为了更好的理解我们举个栗子:

  如下图有很多离散的点,我们打算拟合出一条直线。
1

  首先随机取两个点,计算直线模型,根据设定的误差阈值判断局内点和局外点。
2

  重复上面过程,达到一定迭代次数后,将最佳模型作为问题的解。
3

如果想要对RANSAC算法有更多了解请参见维基百科

二.RANSAC算法应用

  这里我们用RANSAC算法实现对特征点匹配的优化。

#include <iostream>  
#include "opencv2/opencv.hpp"  
#include "opencv2/core/core.hpp"  
#include "opencv2/features2d/features2d.hpp"  
#include "opencv2/highgui/highgui.hpp" 

using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
    //读取图片
    Mat img_1 = imread("1.png");     
    Mat img_2 = imread("2.png");   
    if (img_1.empty() || img_2.empty())
    {
        cout << "Can't open the picture!\n";
        return 0;
    }
    vector<KeyPoint> img_1_keypoints, img_2_keypoints;
    Mat img_1_descriptors, img_2_descriptors;
    Ptr<ORB> detector=ORB::create();     //采用ORB算法提取特征点 
    //检测FAST角点位置
    detector->detect(img_1, img_1_keypoints);
    detector->detect(img_2, img_2_keypoints);
    //根据角点位置计算BRIEF描述子
    detector->compute(img_1, img_1_keypoints, img_1_descriptors);
    detector->compute(img_2, img_2_keypoints, img_2_descriptors);
    //汉明距离做为相似度度量
    BFMatcher matcher(NORM_HAMMING, true);   
    vector<DMatch> matches;
    matcher.match(img_1_descriptors, img_2_descriptors, matches);
    Mat match_img;
    drawMatches(img_1, img_1_keypoints, img_2, img_2_keypoints, matches, match_img);
    imshow("所有匹配", match_img);

    //采用RANSAC算法优化
    //保存匹配对序号  
    vector<int> queryIdxs(matches.size()), trainIdxs(matches.size());
    for (size_t i = 0; i < matches.size(); i++)
    {
        queryIdxs[i] = matches[i].queryIdx;
        trainIdxs[i] = matches[i].trainIdx;
    }

    Mat homography_matrix;   //变换矩阵  

    vector<Point2f> points1; KeyPoint::convert(img_1_keypoints, points1, queryIdxs);
    vector<Point2f> points2; KeyPoint::convert(img_2_keypoints, points2, trainIdxs);
    int ransacReprojThreshold = 5;  //拒绝阈值  


    homography_matrix = findHomography(Mat(points1), Mat(points2), CV_RANSAC, ransacReprojThreshold);
    vector<char> matchesMask(matches.size(), 0);
    Mat points1t;
    perspectiveTransform(Mat(points1), points1t, homography_matrix);
    for (size_t i = 0; i < points1.size(); i++)  //保存‘局内点’  
    {
        if (norm(points2[i] - points1t.at<Point2f>((int)i, 0)) <= ransacReprojThreshold) //给局内点做标记  
        {
            matchesMask[i] = 1;
        }
    }
    Mat match_img2;   //滤除‘局外点’后  
    drawMatches(img_1, img_1_keypoints, img_2, img_2_keypoints, matches, match_img2, Scalar(0, 0, 255), Scalar::all(-1), matchesMask);
    imshow("优化后的匹配", match_img2);
    waitKey(0);

    return 0;
}

  这里在openCV的findHomography函数中使用RANSAC来优化。在VS上面运行结果如下:

3

4

  特征点匹配的还可以按照汉明距离小于最小汉明距离两倍的筛选原则优化。

  • 5
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不放弃的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值