RANSAC算法原理与源码解析

随机抽样一致性(RANSAC)算法,可以在一组包含“外点”的数据集中,采用不断迭代的方法,寻找最优参数模型,不符合最优模型的点,被定义为“外点”。在图像配准以及拼接上得到广泛的应用,本文将对RANSAC算法在OpenCV中角点误匹配对的检测中进行解析。1.RANSAC原理OpenCV中滤除误匹配对采用RANSAC算法寻找一个最佳单应性矩阵H,矩阵大小为3×3。RANSAC目的是找到最优的参数矩阵使得满足该矩阵的数据点个数最多,通常令h33=1来归一化矩阵。由于单应性矩阵有8个未知参数,至少需要8个线性方
摘要由CSDN通过智能技术生成

随机抽样一致性(RANSAC)算法,可以在一组包含“外点”的数据集中,采用不断迭代的方法,寻找最优参数模型,不符合最优模型的点,被定义为“外点”。在图像配准以及拼接上得到广泛的应用,本文将对RANSAC算法在OpenCV中角点误匹配对的检测中进行解析。

1.RANSAC原理

OpenCV中滤除误匹配对采用RANSAC算法寻找一个最佳单应性矩阵H,矩阵大小为3×3。RANSAC目的是找到最优的参数矩阵使得满足该矩阵的数据点个数最多,通常令h33=1来归一化矩阵。由于单应性矩阵有8个未知参数,至少需要8个线性方程求解,对应到点位置信息上,一组点对可以列出两个方程,则至少包含4组匹配点对。

 其中(x,y)表示目标图像角点位置,(x',y')为场景图像角点位置,s为尺度参数。
其中(x,y)表示目标图像角点位置,(x’,y’)为场景图像角点位置,s为尺度参数。

RANSAC算法从匹配数据集中随机抽出4个样本并保证这4个样本之间不共线,计算出单应性矩阵,然后利用这个模型测试所有数据,并计算满足这个模型数据点的个数与投影误差(即代价函数),若此模型为最优模型,则对应的代价函数最小。

在这里插入图片描述

ANSAC算法步骤:

      1. 随机从数据集中随机抽出4个样本数据 (此4个样本之间不能共线),计算出变换矩阵H,记为模型M;

      2. 计算数据集中所有数据与模型M的投影误差,若误差小于阈值,加入内点集 I ;

      3. 如果当前内点集 I 元素个数大于最优内点集 I_best , 则更新 I_best = I,同时更新迭代次数k ;

      4. 如果迭代次数大于k,则退出 ; 否则迭代次数加1,并重复上述步骤;

注:迭代次数k在不大于最大迭代次数的情况下,是在不断更新而不是固定的;
在这里插入图片描述 其中,为置信度,一般取0.995;w为"内点"的比例 ; m为计算模型所需要的最少样本数=4;

2.例程OpenCV中此功能通过调用findHomography函数调用,下面是个例程:

[cpp]  view plain  copy
 
 
#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 obj=imread("F:\\Picture\\obj.jpg");   //载入目标图像  
    Mat scene=imread("F:\\Picture\\scene.jpg"); //载入场景图像  
    if (obj.empty() || scene.empty() )  
    {
     
        cout<<"Can't open the picture!\n";  
        return 0;  
    }  
    vector<KeyPoint> obj_keypoints,scene_keypoints;  
    Mat obj_descriptors,scene_descriptors;  
    ORB detector;     //采用ORB算法提取特征点  
    detector.detect(obj,obj_keypoints);  
    detector.detect(scene,scene_keypoints);  
    detector.compute(obj,obj_keypoints,obj_descriptors);  
    detector.compute(scene,scene_keypoints,scene_descriptors);  
    BFMatcher matcher(NORM_HAMMING,true); //汉明距离做为相似度度量  
    vector<DMatch> matches;  
    matcher.match(obj_descriptors, scene_descriptors, matches);  
    Mat match_img;  
    drawMatches(obj,obj_keypoints,scene,scene_keypoints,matches,match_img);  
    imshow("滤除误匹配前",match_img);  
  
    //保存匹配对序号  
    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 H12;   //变换矩阵  
  
    vector<Point2f> points1; KeyPoint::convert(obj_keypoints, points1, queryIdxs);  
    vector<Point2f> points2; KeyPoint::convert(scene_keypoints, points2, trainIdxs);  
    int ransacReprojThreshold = 5;  //拒绝阈值  
  
  
    H12 = findHomography( Mat(points1), Mat(points2), CV_RANSAC, ransacReprojThreshold );  
    vector<char> matchesMask( matches.size(), 0 );    
    Mat points1t;  
    perspectiveTransform(Mat(points1), points1t, H12);  
    for( size_t i1 = 0; i1 < points1.size(); i1++ )  //保存‘内点’  
    {
     
        if( norm(points2[i1] - points1t.at<Point2f>((int)i1,0)) <= ransacReprojThreshold ) //给内点做标记  
        {
     
            matchesMask[i1] = 1;  
        }     
    }  
    Mat match_img2;   //滤除‘外点’后  
    drawMatches(obj,obj_keypoints,scene,scene_keypoints,matches,match_img2,Scalar(0,0,255),Scalar::all(-1),matchesMask);  
  
    //画出目标位置  
    std::vector<Point2f> obj_corners(4);  
    obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint( obj.cols, <
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值