利用RANSAC算法筛选SIFT特征匹配

article/2025/9/12 18:05:10

关于RANSAC算法的基本思想,可从网上搜索找到,这里只是RANSAC用于SIFT特征匹配筛选时的一些说明。

RANSAC算法在SIFT特征筛选中的主要流程是:

(1) 从样本集中随机抽选一个RANSAC样本,即4个匹配点对

(2) 根据这4个匹配点对计算变换矩阵M

(3) 根据样本集,变换矩阵M,和误差度量函数计算满足当前变换矩阵的一致集consensus,并返回一致集中元素个数

(4) 根据当前一致集中元素个数判断是否最优(最大)一致集,若是则更新当前最优一致集

(5) 更新当前错误概率p,若p大于允许的最小错误概率则重复(1)至(4)继续迭代,直到当前错误概率p小于最小错误概率


下面结合RobHess的源码说明一下RANSAC算法在SIFT特征匹配筛选中的实现,

具体的源码分析见此系列文章:RobHess的SIFT源码分析:综述

在RobHess的源码中,RANSAC算法的声明和实现在xform.h和xform.c文件中

实现RANSAC算法的主函数是ransac_xform,如下:

CvMat* ransac_xform( struct feature* features, int n, int mtype,ransac_xform_fn xform_fn, int m, double p_badxform,ransac_err_fn err_fn, double err_tol,struct feature*** inliers, int* n_in )

函数说明:利用RANSAC算法进行特征点筛选,计算出最佳匹配的变换矩阵
参数:
features:特征点数组,只有当mtype类型的匹配点存在时才被用来进行单应性计算
n:特征点个数
mtype:决定使用每个特征点的哪个匹配域进行变换矩阵的计算,应该是FEATURE_MDL_MATCH,
    FEATURE_BCK_MATCH,FEATURE_MDL_MATCH中的一个。若是FEATURE_MDL_MATCH,
    对应的匹配点对坐标是每个特征点的img_pt域和其匹配点的mdl_pt域,
    否则,对应的匹配点对是每个特征点的img_pt域和其匹配点的img_pt域。
xform_fn:函数指针,指向根据输入的点对进行变换矩阵计算的函数,一般传入lsq_homog()函数
m:在函数xform_fn中计算变换矩阵需要的最小特征点对个数
p_badxform:允许的错误概率,即允许RANSAC算法计算出的变换矩阵错误的概率,当前计算出的模型的错误概率小于p_badxform时迭代停止
err_fn:函数指针,对于给定的变换矩阵,计算推定的匹配点对之间的变换误差,一般传入homog_xfer_err()函数
err_tol:容错度,对于给定的变换矩阵,在此范围内的点对被认为是内点
inliers:输出参数,指针数组,指向计算出的最终的内点集合,若为空,表示没计算出符合要求的一致集
               此数组的内存将在本函数中被分配,使用完后必须在调用出释放:free(*inliers)
n_in:输出参数,最终计算出的内点的数目
返回值:RANSAC算法计算出的变换矩阵,若为空,表示出错或无法计算出可接受矩阵


注释如下:

CvMat* ransac_xform( struct feature* features, int n, int mtype,ransac_xform_fn xform_fn, int m, double p_badxform,ransac_err_fn err_fn, double err_tol,struct feature*** inliers, int* n_in )
{//matched:所有具有mtype类型匹配点的特征点的数组,也就是样本集//sample:单个样本,即4个特征点的数组//consensus:当前一致集;//consensus_max:当前最大一致集(即当前的最好结果的一致集)struct feature** matched, ** sample, ** consensus, ** consensus_max = NULL;struct ransac_data* rdata;//每个特征点的feature_data域的ransac数据指针CvPoint2D64f* pts, * mpts;//每个样本对应的两个坐标数组:特征点坐标数组pts和匹配点坐标数组mptsCvMat* M = NULL;//当前变换矩阵//p:当前计算出的模型的错误概率,当p小于p_badxform时迭代停止//in_frac:内点数目占样本总数目的百分比double p, in_frac = RANSAC_INLIER_FRAC_EST;//nm:输入的特征点数组中具有mtype类型匹配点的特征点个数//in:当前一致集中元素个数//in_min:一致集中元素个数允许的最小值,保证RANSAC最终计算出的转换矩阵错误的概率小于p_badxform所需的最小内点数目//in_max:当前最优一致集(最大一致集)中元素的个数//k:迭代次数,与计算当前模型的错误概率有关int i, nm, in, in_min, in_max = 0, k = 0;//找到特征点数组features中所有具有mtype类型匹配点的特征点,放到matched数组(样本集)中,返回值nm是matched数组的元素个数nm = get_matched_features( features, n, mtype, &matched );//若找到的具有匹配点的特征点个数小于计算变换矩阵需要的最小特征点对个数,出错if( nm < m ){   //出错处理,特征点对个数不足fprintf( stderr, "Warning: not enough matches to compute xform, %s" \" line %d\n", __FILE__, __LINE__ );goto end;}/* initialize random number generator */srand( time(NULL) );//初始化随机数生成器//计算保证RANSAC最终计算出的转换矩阵错误的概率小于p_badxform所需的最小内点数目in_min = calc_min_inliers( nm, m, RANSAC_PROB_BAD_SUPP, p_badxform );//当前计算出的模型的错误概率,内点所占比例in_frac越大,错误概率越小;迭代次数k越大,错误概率越小p = pow( 1.0 - pow( in_frac, m ), k );i = 0;//当前错误概率大于输入的允许错误概率p_badxform,继续迭代while( p > p_badxform ){//从样本集matched中随机抽选一个RANSAC样本(即一个4个特征点的数组),放到样本变量sample中sample = draw_ransac_sample( matched, nm, m );//从样本中获取特征点和其对应匹配点的二维坐标,分别放到输出参数pts和mpts中extract_corresp_pts( sample, m, mtype, &pts, &mpts );//调用参数中传入的函数xform_fn,计算将m个点的数组pts变换为mpts的矩阵,返回变换矩阵给MM = xform_fn( pts, mpts, m );//一般传入lsq_homog()函数if( ! M )//出错判断goto iteration_end;//给定特征点集,变换矩阵,误差函数,计算出当前一致集consensus,返回一致集中元素个数给inin = find_consensus( matched, nm, mtype, M, err_fn, err_tol, &consensus);//若当前一致集大于历史最优一致集,即当前一致集为最优,则更新最优一致集consensus_maxif( in > in_max ){if( consensus_max )//若之前有最优值,释放其空间free( consensus_max );consensus_max = consensus;//更新最优一致集in_max = in;//更新最优一致集中元素个数in_frac = (double)in_max / nm;//最优一致集中元素个数占样本总个数的百分比}else//若当前一致集小于历史最优一致集,释放当前一致集free( consensus );cvReleaseMat( &M );iteration_end:release_mem( pts, mpts, sample );p = pow( 1.0 - pow( in_frac, m ), ++k );}//根据最优一致集计算最终的变换矩阵/* calculate final transform based on best consensus set *///若最优一致集中元素个数大于最低标准,即符合要求if( in_max >= in_min ){//从最优一致集中获取特征点和其对应匹配点的二维坐标,分别放到输出参数pts和mpts中extract_corresp_pts( consensus_max, in_max, mtype, &pts, &mpts );//调用参数中传入的函数xform_fn,计算将in_max个点的数组pts变换为mpts的矩阵,返回变换矩阵给MM = xform_fn( pts, mpts, in_max );/***********下面会再进行一次迭代**********///根据变换矩阵M从样本集matched中计算出一致集consensus,返回一致集中元素个数给inin = find_consensus( matched, nm, mtype, M, err_fn, err_tol, &consensus);cvReleaseMat( &M );release_mem( pts, mpts, consensus_max );//从一致集中获取特征点和其对应匹配点的二维坐标,分别放到输出参数pts和mpts中extract_corresp_pts( consensus, in, mtype, &pts, &mpts );//调用参数中传入的函数xform_fn,计算将in个点的数组pts变换为mpts的矩阵,返回变换矩阵给MM = xform_fn( pts, mpts, in );if( inliers ){*inliers = consensus;//将最优一致集赋值给输出参数:inliers,即内点集合consensus = NULL;}if( n_in )*n_in = in;//将最优一致集中元素个数赋值给输出参数:n_in,即内点个数release_mem( pts, mpts, consensus );}else if( consensus_max ){   //没有计算出符合要求的一致集if( inliers )*inliers = NULL;if( n_in )*n_in = 0;free( consensus_max );}//RANSAC算法结束:恢复特征点中被更改的数据域feature_data,并返回变换矩阵M
end:for( i = 0; i < nm; i++ ){//利用宏feat_ransac_data来提取matched[i]中的feature_data成员并转换为ransac_data格式的指针rdata = feat_ransac_data( matched[i] );//恢复feature_data成员的以前的值matched[i]->feature_data = rdata->orig_feat_data;free( rdata );//释放内存}free( matched );return M;//返回求出的变换矩阵M
}

实验测试:

//特征提取和匹配
void match(IplImage *img1,IplImage *img2)
{IplImage *img1_Feat = cvCloneImage(img1);//复制图1,深拷贝,用来画特征点IplImage *img2_Feat = cvCloneImage(img2);//复制图2,深拷贝,用来画特征点struct feature *feat1, *feat2;//feat1:图1的特征点数组,feat2:图2的特征点数组int n1, n2;//n1:图1中的特征点个数,n2:图2中的特征点个数struct feature *feat;//每个特征点struct kd_node *kd_root;//k-d树的树根struct feature **nbrs;//当前特征点的最近邻点数组int matchNum;//经距离比值法筛选后的匹配点对的个数struct feature **inliers;//精RANSAC筛选后的内点数组int n_inliers;//经RANSAC算法筛选后的内点个数,即feat1中具有符合要求的特征点的个数//默认提取的是LOWE格式的SIFT特征点//提取并显示第1幅图片上的特征点n1 = sift_features( img1, &feat1 );//检测图1中的SIFT特征点,n1是图1的特征点个数export_features("feature1.txt",feat1,n1);//将特征向量数据写入到文件draw_features( img1_Feat, feat1, n1 );//画出特征点cvShowImage("img1_Feat",img1_Feat);//显示//提取并显示第2幅图片上的特征点n2 = sift_features( img2, &feat2 );//检测图2中的SIFT特征点,n2是图2的特征点个数export_features("feature2.txt",feat2,n2);//将特征向量数据写入到文件draw_features( img2_Feat, feat2, n2 );//画出特征点cvShowImage("img2_Feat",img2_Feat);//显示Point pt1,pt2;//连线的两个端点double d0,d1;//feat1中每个特征点到最近邻和次近邻的距离matchNum = 0;//经距离比值法筛选后的匹配点对的个数//将2幅图片合成1幅图片,上下排列stacked = stack_imgs( img1, img2 );//合成图像,显示经距离比值法筛选后的匹配结果stacked_ransac = stack_imgs( img1, img2 );//合成图像,显示经RANSAC算法筛选后的匹配结果//根据图2的特征点集feat2建立k-d树,返回k-d树根给kd_rootkd_root = kdtree_build( feat2, n2 );//遍历特征点集feat1,针对feat1中每个特征点feat,选取符合距离比值条件的匹配点,放到feat的fwd_match域中for(int i = 0; i < n1; i++ ){feat = feat1+i;//第i个特征点的指针//在kd_root中搜索目标点feat的2个最近邻点,存放在nbrs中,返回实际找到的近邻点个数int k = kdtree_bbf_knn( kd_root, feat, 2, &nbrs, KDTREE_BBF_MAX_NN_CHKS );if( k == 2 ){d0 = descr_dist_sq( feat, nbrs[0] );//feat与最近邻点的距离的平方d1 = descr_dist_sq( feat, nbrs[1] );//feat与次近邻点的距离的平方//若d0和d1的比值小于阈值NN_SQ_DIST_RATIO_THR,则接受此匹配,否则剔除if( d0 < d1 * NN_SQ_DIST_RATIO_THR ){   //将目标点feat和最近邻点作为匹配点对pt1 = Point( cvRound( feat->x ), cvRound( feat->y ) );//图1中点的坐标pt2 = Point( cvRound( nbrs[0]->x ), cvRound( nbrs[0]->y ) );//图2中点的坐标(feat的最近邻点)pt2.y += img1->height;//由于两幅图是上下排列的,pt2的纵坐标加上图1的高度,作为连线的终点cvLine( stacked, pt1, pt2, CV_RGB(255,0,255), 1, 8, 0 );//画出连线matchNum++;//统计匹配点对的个数feat1[i].fwd_match = nbrs[0];//使点feat的fwd_match域指向其对应的匹配点}}free( nbrs );//释放近邻数组}qDebug()<<tr("经距离比值法筛选后的匹配点对个数:")<<matchNum<<endl;//显示并保存经距离比值法筛选后的匹配图cvNamedWindow(IMG_MATCH1);//创建窗口cvShowImage(IMG_MATCH1,stacked);//显示//利用RANSAC算法筛选匹配点,计算变换矩阵HCvMat * H = ransac_xform(feat1,n1,FEATURE_FWD_MATCH,lsq_homog,4,0.01,homog_xfer_err,3.0,&inliers,&n_inliers);qDebug()<<tr("经RANSAC算法筛选后的匹配点对个数:")<<n_inliers<<endl;//遍历经RANSAC算法筛选后的特征点集合inliers,找到每个特征点的匹配点,画出连线for(int i=0; i<n_inliers; i++){feat = inliers[i];//第i个特征点pt1 = Point(cvRound(feat->x), cvRound(feat->y));//图1中点的坐标pt2 = Point(cvRound(feat->fwd_match->x), cvRound(feat->fwd_match->y));//图2中点的坐标(feat的匹配点)qDebug()<<"("<<pt1.x<<","<<pt1.y<<")--->("<<pt2.x<<","<<pt2.y<<")"<<endl;pt2.y += img1->height;//由于两幅图是上下排列的,pt2的纵坐标加上图1的高度,作为连线的终点cvLine(stacked_ransac,pt1,pt2,CV_RGB(255,0,255),1,8,0);//画出连线}cvNamedWindow(IMG_MATCH2);//创建窗口cvShowImage(IMG_MATCH2,stacked_ransac);//显示
}

结果:


RANSAC筛选前



RANSAC筛选后


                                                   

                                                       RANSAC筛选前                                                                                                  RANSAC筛选后



RANSAC筛选前



RANSAC筛选后


                                                                                                                                  

                                                                RANSAC筛选前                                                                                       RANSAC筛选后



RANSAC筛选前



RANSAC筛选后



RANSAC筛选前



RANSAC筛选后


                                                                        

                                                                   RANSAC筛选前                                                                              RANSAC筛选后                  

                                                                                                          

                                                                              RANSAC筛选前                                                                         RANSAC筛选后


                                 

                                                                            RANSAC筛选前                                                                                         RANSAC筛选后          



RANSAC筛选前



RANSAC筛选后



RANSAC筛选前



RANSAC筛选后



RANSAC筛选前



RANSAC筛选后


参考

利用RANSAC算法筛选SIFT特征匹配

                    






http://chatgpt.dhexx.cn/article/JAxWOAQ6.shtml

相关文章

Ransac算法学习python版

初学小白,注释的代码比较详细 import numpy as np import scipy as sp import scipy.linalg as sldef ransac(data, model, n, k, t, d, debug False, return_all False):"""参考:http://scipy.github.io/old-wiki/pages/Cookbook/RANSAC伪代码:http://en.wi…

RANSAC算法实现 + 直线拟合

一、RANSAC算法 1.参考资料 [1]题目来源与解析&#xff1a;商汤科技SLAM算法岗的RANSAC编程题 [2]牛客网题目&#xff1a;[编程题]线性回归 [3]牛客网解答参考&#xff1a;商汤科技某算法岗的编程题有点过分了啊 [4]RANSAC算法原理&#xff1a;RANSAC翻译、经典RANSAC以及…

精匹配——Opencv实现RANSAC算法进行误匹配对剔除,并和最小二乘法对比

精匹配——RANSAC算法思想及优缺点 目录 精匹配——RANSAC算法思想及优缺点前言一、RANSAC简介二、RANSAC基本思想1.步骤2.迭代次数的公式3.举例&#xff08;拟合直线&#xff0c;拟合最佳单应性矩阵&#xff09; 三、最小二乘法1、最小二乘法的主要思想2、最小二乘解3、仿射变…

ransca算法详细介绍

1、算法概述&#xff1a; RANSAC算法的基本假设是样本中包含正确数据(inliers&#xff0c;可以被模型描述的数据)&#xff0c;也包含异常数据(outliers&#xff0c;偏离正常范围很远、无法适应数学模型的数据)&#xff0c;即数据集中含有噪声。这些异常数据可能是由于错误的测…

RANSAC 特征匹配算法解析

一、RANSAC特征匹配算法简介   RANSAC算法是RANdom SAmple Consensus的缩写&#xff0c;意为随机抽样一致。表面上的意思就是从匹配样本中随机取样&#xff0c;寻找一致的样本点。RANSAC算法是根据一组包含异常数据的样本数据集&#xff0c;计算出数据的数学模型参数&#x…

RANSAC算法(原理及代码实现+迭代次数参数自适应)

RANSAC算法 前言算法流程Python代码RANSAC算法迭代参数的自适应 前言 随机样本一致性 (RANSAC) 是一种迭代方法&#xff0c;用于从一组包含异常值的观察数据中估计数学模型的参数&#xff0c;此时异常值不会对估计值产生影响。简言之&#xff0c;RANSAC是一种滤除异常值的常用算…

RANSAC算法简介

文章目录 1 算法简介2 基本思想3 参数4 应用案例&#xff08;直线拟合&#xff09; 1 算法简介 RANSAC算法的基本假设是样本中包含正确数据(inliers&#xff0c;可以被模型描述的数据)&#xff0c;也包含异常数据(outlies&#xff0c;偏离正常范围很远、无法适应数学模型的数据…

关于RANSAC的理解

先说最小二乘。 ok&#xff0c;你手头有一堆数据&#xff0c;比如这些蓝点&#xff1a; 那么我们假设它符合一个直线模型&#xff1a;yaxb&#xff0c;用最小二乘就可以很容易求解出未知参数a和b。最小二乘大法确实好哇&#xff0c;毕竟高斯用它来估计谷神星的轨道&#xff08…

RANSAC基本原理

计算机视觉基本原理——RANSAC 1. RANSAC简介2. 基本思想3. 范例4. 迭代次数推导 Reference&#xff1a; 1.计算机视觉基本原理——RANSAC 1. RANSAC简介 RANSAC(RAndom SAmple Consensus,随机采样一致)算法是从一组含有“外点”(outliers)的数据中正确估计数学模型参数的迭代…

RANSAC算法的理解与使用

随机抽样一致算法(random sample consensus, RANSAC)&#xff0c;其实就是采用迭代的方法从一组包含离群的被观测数据中估算出数学模型的参数。(比如通过一群点拟合一条直线等) 基本假设 模型假设&#xff1a;事先知道真实数据满足的数学模型&#xff0c;不知道的只是模型的具…

【特征匹配】RANSAC算法原理与源码解析

转载请注明出处&#xff1a;http://blog.csdn.net/luoshixian099/article/details/50217655 勿在浮沙筑高台 随机抽样一致性&#xff08;RANSAC&#xff09;算法&#xff0c;可以在一组包含“外点”的数据集中&#xff0c;采用不断迭代的方法&#xff0c;寻找最优参数模型&…

RANSAC算法详解+Python实现

1.算法描述 RANSAC的基本假设是&#xff1a; &#xff08;1&#xff09;数据由“局内点”组成&#xff0c;例如&#xff1a;数据的分布可以用一些模型参数来解释&#xff1b; &#xff08;2&#xff09;“局外点”是不能适应该模型的数据&#xff1b; &#xff08;3&#xff0…

RANSAC算法与原理(一)

目录 算法介绍举例 算法的基本思想和流程算法的实现流程&#xff1a;迭代次数的推导算法的实现 python代码实现References 算法介绍 首先我们从Random sample consensus - Wikipedia上找到RANSAC原理的介绍。 RANSAC算法的中文名称是随机抽样一致算法(Random Sample Consenus…

RANSAC算法——看完保证你理解

目录 1 最小二乘算法的缺陷2 RANSAC算法2.1 原理2.2 实例2.3 参数 参考感谢阅读 RANSAC全程Random sample consensus&#xff0c;中文即“随机抽样一致算法”&#xff0c;该方法采用迭代的方式从一组包含离群&#xff08;outlier或者错误数据&#xff09;的被观测数据中估算出数…

RANSAC算法介绍

一、RANSAC介绍 随机抽样一致算法&#xff08;RANdom SAmple Consensus,RANSAC&#xff09;,采用迭代的方式从一组包含离群的被观测数据中估算出数学模型的参数。RANSAC算法假设数据中包含正确数据和异常数据&#xff08;或称为噪声&#xff09;。正确数据记为内点&#xff08;…

RANSAC算法讲解

RANSAC是“RANdom SAmple Consensus&#xff08;随机抽样一致&#xff09;”的缩写。它可以从一组包含“局外点”的观测数据集中&#xff0c;通过迭代方式估计数学模型的参数。它是一种不确定的算法——它有一定的概率得出一个合理的结果&#xff1b;为了提高概率必须提高迭代次…

RANSAC介绍(Matlab版直线拟合+平面拟合)

RANSAC介绍&#xff08;Matlab版直线拟合平面拟合&#xff09; 本人邮箱&#xff1a;sylvester0510163.com&#xff0c;欢迎交流讨论&#xff0c; 欢迎转载&#xff0c;转载请注明网址http://blog.csdn.net/u010128736/ 一、RANSAC介绍 随机抽样一致算法&#xff08;RANdom SA…

RANSAC算法(仅供学习使用)

1.定义 RANSAC&#xff08;Random Sample Consensus&#xff09;算法是一种基于随机采样的迭代算法&#xff0c;用于估计一个数学模型参数。它最初由Fischler和Bolles于1981年提出&#xff0c;主要用于计算机视觉和计算机图形学中的模型拟合和参数估计问题。 RANSAC算法的基本…

前端调试手机app

有时候应用在电脑网页端显示是正常的&#xff0c;但是一安装到手机上或者在手机浏览器上打开&#xff0c;就会显示各种问题问题。 在网上找了很长时间&#xff0c;最方便的就是利用在电脑上利用谷歌浏览器进行调试&#xff0c;输入网址chrome://inspect/#devices&#xff0c;进…

跨平台应用开发进阶(三十七)uni-app前端监控方案 Sentry 探究

文章目录 一、前言二、Sentry 简介三、Sentry 部署3.1 docker 的部署 (mac版)3.2 部署 sentry3.3 创建项目3.4 前端部署&#xff0c;注入监控代码 四、sentry 操作界面介绍五、拓展阅读 一、前言 在日益发达的网络时代&#xff0c;web应用也是越来越复杂&#xff0c;尤其是前端…