OpenCV实现的F矩阵+RANSAC原理与实践

news2024/9/25 15:26:54

1 RANSAC 筛选

1.1 大致原理

Random sample consensus (RANSAC),即随机抽样一致性,其是一种用于估计模型参数的迭代方法,特别适用于处理包含离群点(outliers)的数据集

RANSAC 的主要思想是随机采样数据点,用这些采样点拟合一个模型,然后计算其他数据点到这个模型的拟合误差;根据误差和阈值,将数据点分为内点(inliers)外点(outliers);重复这个过程多次,选择具有最多内点的模型作为最终的估计

大致步骤为:

  1. 随机采样

    从数据集中随机选择一小部分数据点,通常是与所估计模型参数数量相等的数据点

  2. 模型拟合

    使用这些随机采样的数据点拟合一个模型,例如直线

  3. 内点检测

    计算所有数据点到模型的拟合误差,并将与模型拟合误差小于某个阈值的数据点标记为内点

  4. 判断是否满足条件

    如果内点的数量达到了某个设定的阈值,且模型参数的估计是合理的(例如,模型的拟合误差小于一定阈值),则认为找到了一个满足条件的模型

  5. 重复迭代

    重复上述过程多次(通常几百甚至上千次),并且记录具有最多内点的模型,以及该模型估计的内点

  6. 输出最佳模型

    在所有迭代中,选择具有最多内点的模型作为最终的估计模型。这些内点被认为是满足模型的数据点

1.2 优缺点

RANSAC 的一个优点是它能够对模型参数进行鲁棒估计,能够在存在大量噪声的情况下找到合适的模

RANSAC 的缺点是计算这些参数所需的时间没有上限,其需要进行大量的随机采样和模型拟合,因此对于大规模数据集来说,计算复杂度较高,可能需要较长的时间来运行

1.3 实践效果

请见 3 实践操作 步骤二

2 F矩阵

2.1 基本原理

基本矩阵(Fundamental Matrix)描述了两个摄像机之间的基本几何关系

在对极几何中,对于立体图像对中对应点的齐次图像坐标 p1p2F*p1描述了另一图像上的对应点 p2 必须位于其上的线(对极线)这意味着,对于所有对应点对都成立:
p 2 T ∗ F ∗ p 1 = 0 p_2^T * F * p_1 = 0 p2TFp1=0

2.2 函数实现

在 OpenCV 中,提供了 findFundamentalMat 函数,用于估计两幅图像之间的F矩阵

以下是 findFundamentalMat 函数的基本用法:

Mat fundamental_matrix = findFundamentalMat(points1, points2, mask, method, ransacReprojThreshold, confidence);

其中各参数的含义如下:

  • points1points2:两幅图像中的匹配点坐标,通常是 vector<Point2f> 类型,表示两幅图像中匹配点的像素坐标
  • mask:是一个输出数组通常是 vector<uchar> 类型,用于指示哪些匹配点被视为内点(inliers)和哪些被视为外点(outliers
  • method:用于指定计算基本矩阵的方法,可以是以下几种选项之一:
    • cv::FM_RANSAC:使用 RANSAC 算法进行估计,用于排除离群点
    • cv::FM_LMEDS:使用最小中值误差估计方法
    • cv::FM_8POINT:使用 8 点法估计基本矩阵
  • ransacReprojThreshold:RANSAC 算法中的重投影误差阈值,用于判断内点和外点,通常需要根据具体问题来选择适当的阈值,默认值为 3.0
  • confidence:置信度,通常为默认值 0.99

3 实践操作

之前通过SIFT+Flann+ratio=0.7的图像匹配和初步筛选,得到了 good_matchesvector<DMatch> 类型)

步骤一:保存匹配点对坐标

vector<DMatch> 类型的 good_matches 中的坐标信息提取出来存入 vector<Point2f> 类型的 matchedPoints1/2 ;以便于后续的几何计算将匹配点对的坐标提取出来,以便于后续的几何计算

// 声明用于保存匹配点对的容器
vector<Point2f> matchedPoints1, matchedPoints2;
for (int i = 0; i < good_matches.size(); ++i)
{
    matchedPoints1.push_back(keypoints1[good_matches[i].queryIdx].pt);
    matchedPoints2.push_back(keypoints2[good_matches[i].trainIdx].pt);
}

步骤二:进行基本矩阵F的估计

直接使用 findFundamentalMat 函数

这个函数在内部已经包含了 RANSAC 筛选步骤;具体来说,findFundamentalMat 函数会计算基本矩阵 F,同时使用 RANSAC 迭代方法来排除离群点,确保得到的基本矩阵对于图像匹配是稳健的

// 使用RANSAC进行基本矩阵F的估计
Mat F;
vector<uchar> inliers;
F = findFundamentalMat(matchedPoints1, matchedPoints2, inliers, RANSAC);
  • 为了查看 RANSAC 筛选的效果我们进行如下操作
    inliers 是一个二进制向量,指示哪些匹配点对被视为内点(符合基本矩阵约束),哪些被视为外点;我们接下来使用内点来进一步筛选匹配,只保留通过 RANSAC 筛选的匹配对在ransac_filtered_matches中,并打印出来

    // 进一步筛选匹配
    vector<DMatch> ransac_filtered_matches;
    for (int i = 0; i < inliers.size(); ++i)
    {
        if (inliers[i])
        {
            ransac_filtered_matches.push_back(good_matches[i]);
        }
    }
    // ransac_filtered_matches 包含了通过RANSAC筛选后的匹配对
    Mat ransac_filtered_img_matches;
    drawMatches(img1, keypoints1, img2, keypoints2, ransac_filtered_matches, ransac_filtered_img_matches);    
    imwrite(SAVE_PATH, ransac_filtered_img_matches);
    
    匹配点数量图像效果
    RANSAC 筛选前2949img_matches_3&4
    RANSAC 筛选后2581img_matches_3&4_

    可以明显看出,在 RANSAC 筛选后,消除了 368 对离群匹配,达到了非常好的匹配效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1026759.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot文件上传-阿里云OSS

1.打开阿里云 说明&#xff1a;登录阿里云账号 2.点击AccessKey管理 3.创建AccessKey 说明&#xff1a;记得复制accessKeyId&#xff0c;accessKeySecret并保存起来 4. 点击对象存储OSS 5.创建Bucket 说明&#xff1a;创建储存桶 6.查看SDK示例 7.Java简单上传 8.上传文件流…

已解决 AttributeError: ‘str‘ object has no attribute ‘decode‘

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页: &#x1f405;&#x1f43e;猫头虎的博客&#x1f390;《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f996…

相对论的应用:GPS导航

“但是数学享有盛誉还有另一个原因&#xff1a;正是数学为精确的自然科学提供了一定程度的安全保障&#xff0c;而没有数学&#xff0c;它们就无法实现这一点。” “就现实而言&#xff0c;数学定律是不确定的&#xff1b;就其确定而言&#xff0c;它们并不涉及现实。” —阿尔…

Mysql高级——索引优化和查询优化(1)

索引优化 1. 数据准备 学员表插50万条&#xff0c; 班级表插1万条。 建表 CREATE TABLE class (id INT ( 11 ) NOT NULL AUTO_INCREMENT,className VARCHAR ( 30 ) DEFAULT NULL,address VARCHAR ( 40 ) DEFAULT NULL,monitor INT NULL,PRIMARY KEY ( id ) ) ENGINE INNO…

解决Win11/10中Edge浏览器页面加载不出来、打不开问题|有网但是打不开,加载不了

问题症状 edge浏览器打不开&#xff0c;有网络能正常上网&#xff0c;但是edge浏览器无法浏览。网络质量很高&#xff0c;但是页面就是加载不出来&#xff0c;详情如下&#xff1a; &#xff08;我是在科学上网后造成这样子的原因&#xff0c;现在将我的方法分享一下&#xff…

Flask狼书笔记 | 09_图片社交网站 - 大型项目的架构与需求

文章目录 9 图片社交网站9.1 项目组织架构9.2 编写程序骨架9.3 高级用户认证9.4 基于用户角色的权限管理9.5 使用Flask-Dropzone优化文件上传9.6 使用Flask-Avatars处理用户头像9.7 图片展示与管理9.8 收藏图片9.9 用户关注9.10 消息提醒9.11用户资料与账户设置9.12 首页与探索…

近万采集各种典故网站文章大全ACCESS\EXCEL数据库

一个学语文的朋友问我有没有关于各种典故以及万物由来的数据&#xff0c;我看了看手头的资料发现还真没有&#xff0c;而且网上似乎也没有这一类的成品&#xff0c;因此就用程序采集了一个典故网的文章。 分类统计情况有&#xff1a;成语典故&#xff08;共4198条&#xff09;、…

第三、四、五场面试

第三场 共享屏幕做题&#xff08;三道简单题&#xff09; 替换空格成%20&#xff08;双指针&#xff09; 删除升序链表中的重复元素&#xff08;指针&#xff09;有效的括号&#xff08;栈&#xff09; 第四场、第五场 自我介绍 项目拷打 整个项目架构rpc模块的情况分析的数…

【UE 粒子练习】01——练习前的准备

步骤 1. 首先在虚幻商城中搜索如下资产然后创建工程 2. 打开新建的示例工程然后新建一个空白关卡 3. 将“BP_DemoRoom”拖入视口 这里设置“Base Room Size”为5 移入“BP_DemoDisplay” 这里“Description”设置为“Standard Sprite Emitter” 通过快捷键Alt来快速复制一份“…

FireFly PowerBASIC RAD编程,调用PowerBASIC COM对象

一、序言 初步看了看PowerBASIC编程&#xff0c;很类似用VC注册窗体后调用回调函数&#xff0c;先是一个Dialog new&#xff0c;然后添加组件 Control add ......&#xff0c; 然后在处理 Windows MSG和发给组件的消息&#xff0c;这种编程方式和早期DOS 25x80屏幕上编程一样&…

UWB学习——day5

旁瓣的控制 在UWB&#xff08;Ultra-Wideband&#xff0c;超宽带&#xff09;通信系统中&#xff0c;对主瓣和旁瓣进行控制和优化是重要的&#xff0c;因为这直接影响了信号的传输质量、抗干扰性和系统性能。 旁瓣出现的原因 频谱泄露&#xff0c;根据傅里叶变换原理&#x…

uniapp实时获取当前位置

首先我们需要先下载一个插件&#xff08;高德地图官网插件&#xff09; &#xff08;插件主要作用是获取当前地理定位或者是自身的位置&#xff0c;并且可以返回名称name&#xff09; 相关下载-微信小程序插件 | 高德地图API (amap.com)https://developer.amap.com/api/wx/do…

旅游出行类APP如何找到策略优势,最大化流量红利

刚刚结束了暑期出游&#xff0c;中秋国庆小长假马上到啦&#xff0c;出行计划又要安排起来了&#xff01;多样化的出行方式为大家旅行带来极大的便利&#xff0c;同时&#xff0c;伴随互联网模式的深化发展&#xff0c;各式各样的旅游出行类APP已经成长为旅行用户所依赖的一类工…

【LeetCode热题100】--128. 最长连续序列

128.最长连续序列 先对数组进行排序&#xff0c;不断尝试x1,x2,…是否存在&#xff0c;不断枚举并更新答案 class Solution {public int longestConsecutive(int[] nums) {if (nums null || nums.length 0){return 0;}Arrays.sort(nums);int maxLength 1,current 1;for(in…

LVM分区空间扩充

老早之前自己整理的&#xff0c;今天有同事问起&#xff0c;再整理一下发出来。 LVM的全称为Logical Volume Manager&#xff0c;它是Linux环境下对磁盘分区进行管理的一种机制&#xff0c;LVM是建立在硬盘和分区之上的一个逻辑层&#xff0c;来提高磁盘分区管理的灵活…

MySQL: 锁

一、table CREATE TABLE dog (id int(11) NOT NULL AUTO_INCREMENT,age int(11) DEFAULT NULL,weight int(11) DEFAULT NULL,PRIMARY KEY (id),KEY idx_age (age) ) ENGINEInnoDB AUTO_INCREMENT51 DEFAULT CHARSETutf8二、插入数据&#xff1a; 三、主键上锁的测试&#xff…

C++中的四种类型转换运算符

隐式类型转换是安全的,显式类型转换是有风险的,C语言之所以增加强制类型转换的语法,就是为了强调风险,让程序员意识到自己在做什么。但是,这种强调风险的方式还是比较粗放,粒度比较大,它并没有表明存在什么风险,风险程度如何。 再者,C风格的强制类型转换统一使用( ),…

linux上mysql数据备份(全量备份策略+增量备份策略)

执行备份策略前&#xff0c;先做好scp命令的准备 解决思路&#xff1a; 生成SSH公钥/私钥后&#xff0c;您需要将公钥添加到服务器上&#xff0c;从而使服务器可以使用该公钥来验证您的身份。 生成SSH公钥/私钥的命令为 ssh-keygen -t rsa -b 4096什么都不用输入&#xff0c…

用于无功补偿的固定电容晶闸管控制反应器研究(Simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

已解决 (org.springframework.beans.factory.BeanCreationException)

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页: &#x1f405;&#x1f43e;猫头虎的博客&#x1f390;《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f996…