关于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,如下:

[cpp] view plain copy  
  1. CvMat* ransac_xform( struct feature* features, int n, int mtype,
  2. ransac_xform_fn xform_fn, int m, double p_badxform,
  3. ransac_err_fn err_fn, double err_tol,
  4. 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算法计算出的变换矩阵,若为空,表示出错或无法计算出可接受矩阵

注释如下:

[cpp] view plain copy  
  1. CvMat* ransac_xform( struct feature* features, int n, int mtype,
  2. ransac_xform_fn xform_fn, int m, double p_badxform,
  3. ransac_err_fn err_fn, double err_tol,
  4. struct feature*** inliers, int* n_in )
  5. {
  6. //matched:所有具有mtype类型匹配点的特征点的数组,也就是样本集
  7. //sample:单个样本,即4个特征点的数组
  8. //consensus:当前一致集;
  9. //consensus_max:当前最大一致集(即当前的最好结果的一致集)
  10. struct feature** matched, ** sample, ** consensus, ** consensus_max = NULL;
  11. struct ransac_data* rdata;//每个特征点的feature_data域的ransac数据指针
  12. CvPoint2D64f* pts, * mpts;//每个样本对应的两个坐标数组:特征点坐标数组pts和匹配点坐标数组mpts
  13. CvMat* M = NULL;//当前变换矩阵
  14. //p:当前计算出的模型的错误概率,当p小于p_badxform时迭代停止
  15. //in_frac:内点数目占样本总数目的百分比
  16. double p, in_frac = RANSAC_INLIER_FRAC_EST;
  17. //nm:输入的特征点数组中具有mtype类型匹配点的特征点个数
  18. //in:当前一致集中元素个数
  19. //in_min:一致集中元素个数允许的最小值,保证RANSAC最终计算出的转换矩阵错误的概率小于p_badxform所需的最小内点数目
  20. //in_max:当前最优一致集(最大一致集)中元素的个数
  21. //k:迭代次数,与计算当前模型的错误概率有关
  22. int i, nm, in, in_min, in_max = 0, k = 0;
  23. //找到特征点数组features中所有具有mtype类型匹配点的特征点,放到matched数组(样本集)中,返回值nm是matched数组的元素个数
  24. nm = get_matched_features( features, n, mtype, &matched );
  25. //若找到的具有匹配点的特征点个数小于计算变换矩阵需要的最小特征点对个数,出错
  26. if( nm < m )
  27. {   //出错处理,特征点对个数不足
  28. fprintf( stderr, "Warning: not enough matches to compute xform, %s" \
  29. " line %d\n", __FILE__, __LINE__ );
  30. goto end;
  31. }
  32. /* initialize random number generator */
  33. srand( time(NULL) );//初始化随机数生成器
  34. //计算保证RANSAC最终计算出的转换矩阵错误的概率小于p_badxform所需的最小内点数目
  35. in_min = calc_min_inliers( nm, m, RANSAC_PROB_BAD_SUPP, p_badxform );
  36. //当前计算出的模型的错误概率,内点所占比例in_frac越大,错误概率越小;迭代次数k越大,错误概率越小
  37. p = pow( 1.0 - pow( in_frac, m ), k );
  38. i = 0;
  39. //当前错误概率大于输入的允许错误概率p_badxform,继续迭代
  40. while( p > p_badxform )
  41. {
  42. //从样本集matched中随机抽选一个RANSAC样本(即一个4个特征点的数组),放到样本变量sample中
  43. sample = draw_ransac_sample( matched, nm, m );
  44. //从样本中获取特征点和其对应匹配点的二维坐标,分别放到输出参数pts和mpts中
  45. extract_corresp_pts( sample, m, mtype, &pts, &mpts );
  46. //调用参数中传入的函数xform_fn,计算将m个点的数组pts变换为mpts的矩阵,返回变换矩阵给M
  47. M = xform_fn( pts, mpts, m );//一般传入lsq_homog()函数
  48. if( ! M )//出错判断
  49. goto iteration_end;
  50. //给定特征点集,变换矩阵,误差函数,计算出当前一致集consensus,返回一致集中元素个数给in
  51. in = find_consensus( matched, nm, mtype, M, err_fn, err_tol, &consensus);
  52. //若当前一致集大于历史最优一致集,即当前一致集为最优,则更新最优一致集consensus_max
  53. if( in > in_max )
  54. {
  55. if( consensus_max )//若之前有最优值,释放其空间
  56. free( consensus_max );
  57. consensus_max = consensus;//更新最优一致集
  58. in_max = in;//更新最优一致集中元素个数
  59. in_frac = (double)in_max / nm;//最优一致集中元素个数占样本总个数的百分比
  60. }
  61. else//若当前一致集小于历史最优一致集,释放当前一致集
  62. free( consensus );
  63. cvReleaseMat( &M );
  64. iteration_end:
  65. release_mem( pts, mpts, sample );
  66. p = pow( 1.0 - pow( in_frac, m ), ++k );
  67. }
  68. //根据最优一致集计算最终的变换矩阵
  69. /* calculate final transform based on best consensus set */
  70. //若最优一致集中元素个数大于最低标准,即符合要求
  71. if( in_max >= in_min )
  72. {
  73. //从最优一致集中获取特征点和其对应匹配点的二维坐标,分别放到输出参数pts和mpts中
  74. extract_corresp_pts( consensus_max, in_max, mtype, &pts, &mpts );
  75. //调用参数中传入的函数xform_fn,计算将in_max个点的数组pts变换为mpts的矩阵,返回变换矩阵给M
  76. M = xform_fn( pts, mpts, in_max );
  77. /***********下面会再进行一次迭代**********/
  78. //根据变换矩阵M从样本集matched中计算出一致集consensus,返回一致集中元素个数给in
  79. in = find_consensus( matched, nm, mtype, M, err_fn, err_tol, &consensus);
  80. cvReleaseMat( &M );
  81. release_mem( pts, mpts, consensus_max );
  82. //从一致集中获取特征点和其对应匹配点的二维坐标,分别放到输出参数pts和mpts中
  83. extract_corresp_pts( consensus, in, mtype, &pts, &mpts );
  84. //调用参数中传入的函数xform_fn,计算将in个点的数组pts变换为mpts的矩阵,返回变换矩阵给M
  85. M = xform_fn( pts, mpts, in );
  86. if( inliers )
  87. {
  88. *inliers = consensus;//将最优一致集赋值给输出参数:inliers,即内点集合
  89. consensus = NULL;
  90. }
  91. if( n_in )
  92. *n_in = in;//将最优一致集中元素个数赋值给输出参数:n_in,即内点个数
  93. release_mem( pts, mpts, consensus );
  94. }
  95. else if( consensus_max )
  96. {   //没有计算出符合要求的一致集
  97. if( inliers )
  98. *inliers = NULL;
  99. if( n_in )
  100. *n_in = 0;
  101. free( consensus_max );
  102. }
  103. //RANSAC算法结束:恢复特征点中被更改的数据域feature_data,并返回变换矩阵M
  104. end:
  105. for( i = 0; i < nm; i++ )
  106. {
  107. //利用宏feat_ransac_data来提取matched[i]中的feature_data成员并转换为ransac_data格式的指针
  108. rdata = feat_ransac_data( matched[i] );
  109. //恢复feature_data成员的以前的值
  110. matched[i]->feature_data = rdata->orig_feat_data;
  111. free( rdata );//释放内存
  112. }
  113. free( matched );
  114. return M;//返回求出的变换矩阵M
  115. }

实验测试:

[cpp] view plain copy  
  1. //特征提取和匹配
  2. void match(IplImage *img1,IplImage *img2)
  3. {
  4. IplImage *img1_Feat = cvCloneImage(img1);//复制图1,深拷贝,用来画特征点
  5. IplImage *img2_Feat = cvCloneImage(img2);//复制图2,深拷贝,用来画特征点
  6. struct feature *feat1, *feat2;//feat1:图1的特征点数组,feat2:图2的特征点数组
  7. int n1, n2;//n1:图1中的特征点个数,n2:图2中的特征点个数
  8. struct feature *feat;//每个特征点
  9. struct kd_node *kd_root;//k-d树的树根
  10. struct feature **nbrs;//当前特征点的最近邻点数组
  11. int matchNum;//经距离比值法筛选后的匹配点对的个数
  12. struct feature **inliers;//精RANSAC筛选后的内点数组
  13. int n_inliers;//经RANSAC算法筛选后的内点个数,即feat1中具有符合要求的特征点的个数
  14. //默认提取的是LOWE格式的SIFT特征点
  15. //提取并显示第1幅图片上的特征点
  16. n1 = sift_features( img1, &feat1 );//检测图1中的SIFT特征点,n1是图1的特征点个数
  17. export_features("feature1.txt",feat1,n1);//将特征向量数据写入到文件
  18. draw_features( img1_Feat, feat1, n1 );//画出特征点
  19. cvShowImage("img1_Feat",img1_Feat);//显示
  20. //提取并显示第2幅图片上的特征点
  21. n2 = sift_features( img2, &feat2 );//检测图2中的SIFT特征点,n2是图2的特征点个数
  22. export_features("feature2.txt",feat2,n2);//将特征向量数据写入到文件
  23. draw_features( img2_Feat, feat2, n2 );//画出特征点
  24. cvShowImage("img2_Feat",img2_Feat);//显示
  25. Point pt1,pt2;//连线的两个端点
  26. double d0,d1;//feat1中每个特征点到最近邻和次近邻的距离
  27. matchNum = 0;//经距离比值法筛选后的匹配点对的个数
  28. //将2幅图片合成1幅图片,上下排列
  29. stacked = stack_imgs( img1, img2 );//合成图像,显示经距离比值法筛选后的匹配结果
  30. stacked_ransac = stack_imgs( img1, img2 );//合成图像,显示经RANSAC算法筛选后的匹配结果
  31. //根据图2的特征点集feat2建立k-d树,返回k-d树根给kd_root
  32. kd_root = kdtree_build( feat2, n2 );
  33. //遍历特征点集feat1,针对feat1中每个特征点feat,选取符合距离比值条件的匹配点,放到feat的fwd_match域中
  34. for(int i = 0; i < n1; i++ )
  35. {
  36. feat = feat1+i;//第i个特征点的指针
  37. //在kd_root中搜索目标点feat的2个最近邻点,存放在nbrs中,返回实际找到的近邻点个数
  38. int k = kdtree_bbf_knn( kd_root, feat, 2, &nbrs, KDTREE_BBF_MAX_NN_CHKS );
  39. if( k == 2 )
  40. {
  41. d0 = descr_dist_sq( feat, nbrs[0] );//feat与最近邻点的距离的平方
  42. d1 = descr_dist_sq( feat, nbrs[1] );//feat与次近邻点的距离的平方
  43. //若d0和d1的比值小于阈值NN_SQ_DIST_RATIO_THR,则接受此匹配,否则剔除
  44. if( d0 < d1 * NN_SQ_DIST_RATIO_THR )
  45. {   //将目标点feat和最近邻点作为匹配点对
  46. pt1 = Point( cvRound( feat->x ), cvRound( feat->y ) );//图1中点的坐标
  47. pt2 = Point( cvRound( nbrs[0]->x ), cvRound( nbrs[0]->y ) );//图2中点的坐标(feat的最近邻点)
  48. pt2.y += img1->height;//由于两幅图是上下排列的,pt2的纵坐标加上图1的高度,作为连线的终点
  49. cvLine( stacked, pt1, pt2, CV_RGB(255,0,255), 1, 8, 0 );//画出连线
  50. matchNum++;//统计匹配点对的个数
  51. feat1[i].fwd_match = nbrs[0];//使点feat的fwd_match域指向其对应的匹配点
  52. }
  53. }
  54. free( nbrs );//释放近邻数组
  55. }
  56. qDebug()<<tr("经距离比值法筛选后的匹配点对个数:")<<matchNum<<endl;
  57. //显示并保存经距离比值法筛选后的匹配图
  58. cvNamedWindow(IMG_MATCH1);//创建窗口
  59. cvShowImage(IMG_MATCH1,stacked);//显示
  60. //利用RANSAC算法筛选匹配点,计算变换矩阵H
  61. CvMat * H = ransac_xform(feat1,n1,FEATURE_FWD_MATCH,lsq_homog,4,0.01,homog_xfer_err,3.0,&inliers,&n_inliers);
  62. qDebug()<<tr("经RANSAC算法筛选后的匹配点对个数:")<<n_inliers<<endl;
  63. //遍历经RANSAC算法筛选后的特征点集合inliers,找到每个特征点的匹配点,画出连线
  64. for(int i=0; i<n_inliers; i++)
  65. {
  66. feat = inliers[i];//第i个特征点
  67. pt1 = Point(cvRound(feat->x), cvRound(feat->y));//图1中点的坐标
  68. pt2 = Point(cvRound(feat->fwd_match->x), cvRound(feat->fwd_match->y));//图2中点的坐标(feat的匹配点)
  69. qDebug()<<"("<<pt1.x<<","<<pt1.y<<")--->("<<pt2.x<<","<<pt2.y<<")"<<endl;
  70. pt2.y += img1->height;//由于两幅图是上下排列的,pt2的纵坐标加上图1的高度,作为连线的终点
  71. cvLine(stacked_ransac,pt1,pt2,CV_RGB(255,0,255),1,8,0);//画出连线
  72. }
  73. cvNamedWindow(IMG_MATCH2);//创建窗口
  74. cvShowImage(IMG_MATCH2,stacked_ransac);//显示
  75. }

结果:

RANSAC筛选前

RANSAC筛选后

                                 

RANSAC筛选前                                                                                                  RANSAC筛选后

RANSAC筛选前

RANSAC筛选后

                                                     

RANSAC筛选前                                                                                       RANSAC筛选后

RANSAC筛选前

RANSAC筛选后

RANSAC筛选前

RANSAC筛选后

                                        

RANSAC筛选前                                                                              RANSAC筛选后

                                    

RANSAC筛选前                                                                         RANSAC筛选后

               

RANSAC筛选前                                                                                         RANSAC筛选后

RANSAC筛选前

RANSAC筛选后

RANSAC筛选前

RANSAC筛选后

RANSAC筛选前

RANSAC筛选后

from: http://blog.csdn.net/masibuaa/article/details/9145441

利用RANSAC算法筛选SIFT特征匹配相关推荐

  1. matlab怎么匹配特征参数,sift特征匹配matlab

    首先对彩色壁画图像提取 SIFT 特征 点与特征向量,然后对每个特征点提取 HSI 彩色特征,最后按定义的相似性度 量公式计算两个特征点之间的距离,确定二者是否匹配.... 通过计算机中 的 Matl ...

  2. 图片SIFT特征匹配处理

    1.SIFT特征原理描述 SIFT的全称是Scale Invariant Feature Transform,由加拿大教授David G.Lowe提出的.SIFT特征不只具有尺度不变性,即使改变旋转角 ...

  3. python SIFT特征匹配

    python SIFT特征匹配 SIFT(尺度不变特征变换) 兴趣点 描述子 检测兴趣点 匹配描述子 匹配地理标记图像 用局部描述子进行匹配 可视化连接的图像 实验代码 实验结果 结果分析 SIFT( ...

  4. ML之xgboost:利用xgboost算法(自带,特征重要性可视化+且作为阈值训练模型)训练mushroom蘑菇数据集(22+1,6513+1611)来预测蘑菇是否毒性(二分类预测)

    ML之xgboost:利用xgboost算法(自带,特征重要性可视化+且作为阈值训练模型)训练mushroom蘑菇数据集(22+1,6513+1611)来预测蘑菇是否毒性(二分类预测) 目录 输出结果 ...

  5. (三)计算机视觉 --SIFT特征匹配、地理标记图像匹配及RANSAC图像拼接

    目录 一.sift特征检测概述 1.1特征点 1.2sift特征检测 二.sift特征提取与匹配 2.1特征提取并展示 2.2对两张图片进行特征匹配计算 2.3给定一张图片,输出与其匹配最多的三张图片 ...

  6. 利用 ransac 算法拟合平面

    1.前言 最近项目中遇到一个问题, 老板给了一组数据然后要求获取其中处于同一个平面上的数据点的信息, 很明显就是使用ransac 算法进行处理. 2. ransac算法思想 这里我们使用自己的理解来说 ...

  7. sift特征匹配源码matlab,SIFT特征匹配 MATLAB 实现

    [实例简介] matlab实现的SIFT特征提取的全代码,可运行 可测试 很不错的sift原代码 [实例截图] [核心代码] sift的matlab代码,是最新的,效果不错,其中有很多详细说明,可以试 ...

  8. Matlab实现 sift 特征匹配(代码源自网络)

    源码下载: 链接:https://pan.baidu.com/s/191COIwM515XP1rEDEP5H1Q 提取码:owqt 注:解压后将siftWin32放至matlab的bin文件夹下. 脚 ...

  9. OpenCV2.4.4中调用SIFT特征检测器进行图像匹配

    OpenCV中一些相关结构说明: 特征点类: [cpp] view plain copy   class KeyPoint { Point2f  pt;  //坐标 float  size; //特征 ...

最新文章

  1. 我在兰亭这三年之开展自动化
  2. 业界 | 李彦宏:中国人愿意用隐私交换便利性;无人车事故是“人咬狗”新闻...
  3. python六十一: __module__属性
  4. 盘点2020 最烂密码大曝光,第一名的竟然是它?
  5. [转]LVS负载均衡(LVS简介、三种工作模式、十种调度算法)
  6. Web前端笔记-element ui中table中禁止换行,使用...进行省略
  7. 周志华《机器学习》-所有公式推导集合
  8. 账龄分析表excel模板_这种高端表格模板你会做吗?Excel制作带照片的员工信息查询表...
  9. ADB连接手机的三种方式USB、WLAN、WIFI
  10. java jsessionid 会话_jsessionid 对JAVA WEB jsessionid的剖析
  11. 墨卡托投影参数设置_[转载]MRT投影参数设置及原理
  12. 深圳名校最新出炉 学校学区房房价飙升-查查吧深圳学区房地图
  13. jdk1.8新特性:函数式接口、方法引用、函数式编程、常用函数式接口
  14. imp命令导入指定表_oracle 导入imp 命令
  15. java写netcdf_[转]netcdf入门
  16. window7系统为什么老是弹出交互式服务检测
  17. ng alain的简单使用
  18. vue未登录跳转至登录页面
  19. Apple M1芯片版Mac系统重装教程
  20. 用python写一个下载器

热门文章

  1. Transformer结构详解(有图,有细节)
  2. Face Recognition 人脸识别
  3. 从微信AI首席顾问到金融文档智能
  4. 实现主成分分析和白化
  5. APM - 使用JavaAgent+Javassit 插桩C3P0
  6. MySQL - Explain深度剖析
  7. Apache Kafka-初体验Kafka(01)-入门整体认识kafka
  8. HTML内嵌式CSS背景图填充满无截断重复
  9. c语言矩阵乘法优化,c语言矩阵相乘
  10. python 用队列实现栈