代码如下:

// BasisMatrixCalculate.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <iostream> #include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
//引用cv::KeyPoint 特征检测器通用接口
#include <opencv2/features2d/features2d.hpp>
# include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/nonfree/nonfree.hpp> //引用features2d.hpp中 SurfFeatureDetector
#include <opencv2/legacy/legacy.hpp>
int main()
{
//读取2张图像
cv::Mat image1 = cv::imread("../../aTestImage/church01.jpg", 0);
cv::Mat image2 = cv::imread("../../aTestImage/church03.jpg", 0);
if (!image1.data || !image2.data)
return 0;
//使用SURF特征 获取图像特征点
std::vector<cv::KeyPoint> keyPoints1;
std::vector<cv::KeyPoint> keyPoints2;
cv::SurfFeatureDetector surf(3000);
surf.detect(image1, keyPoints1);
surf.detect(image2, keyPoints2); //获取两幅图像的特征点 // //展示图像中的keyPoints
//cv::Mat imagekeyPt;
//cv::drawKeypoints(image1, keyPoints1, imagekeyPt, cv::Scalar(255, 255, 255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
//cv::namedWindow("image1SURFkeyPt");
//cv::imshow("image1SURFkeyPt", imagekeyPt);
//cv::drawKeypoints(image2, keyPoints2, imagekeyPt, cv::Scalar(255, 255, 255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
//cv::namedWindow("image2SURFkeyPt");
//cv::imshow("image2SURFkeyPt", imagekeyPt); //通过特征点获取描述子
cv::SurfDescriptorExtractor surfDesc; // 构造描述子提取器
cv::Mat descriptors1, descriptors2; //描述子记录局部强度差值/梯度变化/位置等信息
surfDesc.compute(image1, keyPoints1, descriptors1);
surfDesc.compute(image2, keyPoints2, descriptors2); //匹配图像的描述子 descriptors
cv::BruteForceMatcher< cv::L2<float> > matcher; //构造匹配器
std::vector<cv::DMatch> matches; //匹配描述子
matcher.match(descriptors1, descriptors2, matches);
std::cout << "matches size= " << matches.size() << std::endl; //选择部分描述子 使用 一对图像的基础矩阵 进行匹配观测
std::vector<cv::DMatch> partmatches; //部分匹配描述子 | 特征点对 的对应 索引结构体
partmatches.push_back(matches[14]); //选择第n个匹配描述子
partmatches.push_back(matches[16]);
partmatches.push_back(matches[141]);
partmatches.push_back(matches[242]);
partmatches.push_back(matches[236]);
partmatches.push_back(matches[238]);
//partmatches.push_back(matches[100]);
partmatches.push_back(matches[200]); //画出选择的匹配描述子 两幅图像连线
cv::Mat imagePartMatches;
cv::drawMatches(image1, keyPoints1, image2, keyPoints2,
partmatches, imagePartMatches, cv::Scalar(255, 255, 255));
cv::namedWindow("imagePartMatches");
cv::imshow("imagePartMatches", imagePartMatches); //将一维向量的keyPoints点转换成二维的Point2f点
std::vector <int> pointIndexes1;//记录选择的匹配特征点的索引向量
std::vector <int> pointIndexes2; for (std::vector<cv::DMatch>::const_iterator it = partmatches.begin();
it != partmatches.end(); ++it)
{
pointIndexes1.push_back(it->queryIdx); //查询图像1特征点索引
pointIndexes2.push_back(it->trainIdx); //训练图像2特征点索引
}
std::vector <cv::Point2f> selPoints1, selPoints2;
cv::KeyPoint::convert(keyPoints1, selPoints1, pointIndexes1);//将索引指定的 特征点 转换成2D点
cv::KeyPoint::convert(keyPoints2, selPoints2, pointIndexes2);
画出转换后的点二维点到原图像
std::vector<cv::Point2f>::const_iterator it = selPoints1.begin();
//while (it != selPoints1.end())
//{
// cv::circle(image1, *it, 3, cv::Scalar(255, 255, 255), 5);
// ++it;
//}
it = selPoints2.begin();
while (it != selPoints2.end())
{
cv::circle(image2, *it, 3, cv::Scalar(255, 255, 255), 2);
++it;
}
//cv::namedWindow("image1");
//cv::imshow("image1", image1);
//cv::namedWindow("image2");
//cv::imshow("image2", image2); // 获取该对图像的基础矩阵 (使用7个匹配描述子matches) CV_FM_7POINT cv::Mat fundemental = cv::findFundamentalMat(cv::Mat(selPoints1), cv::Mat(selPoints2),CV_FM_8POINT);//CV_FM_LMEDS
std::cout << "F-Matrix size= " << fundemental.rows << "," << fundemental.cols << std::endl; //使用基础矩阵 在对应图像上绘制外极线
std::vector<cv::Vec3f> lines1; //存储外极线
cv::computeCorrespondEpilines(cv::Mat(selPoints1), 1, fundemental, lines1);//获取图像1中的二维特征点 在图像2中对应的外极线
for (std::vector<cv::Vec3f>::const_iterator it = lines1.begin();
it != lines1.end(); ++it)
{
cv::line(image2,
cv::Point(0, -(*it)[2] / (*it)[1] ),
cv::Point(image2.cols , -( (*it)[2] + (*it)[0] * image2.cols )/(*it)[1] ),
cv::Scalar(255,255,255));
}
cv::namedWindow("Image2 Epilines");
cv::imshow("Image2 Epilines", image2); cv::waitKey(0);
return 0;
}

结果:

原文链接:https://blog.csdn.net/shyjhyp11/article/details/66526685

[转]OpenCV_Find Basis F-Matrix and computeCorrespondEpilines(获取一对图像的基础矩阵及对应极线)的更多相关文章

  1. XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem F. Matrix Game

    题目: Problem F. Matrix GameInput file: standard inputOutput file: standard inputTime limit: 1 secondM ...

  2. 2D-2D:对极几何 基础矩阵F 本质矩阵E 单应矩阵H

    对极约束 \[ \boldsymbol{x}_{2}^{T} \boldsymbol{F} \boldsymbol{x}_{1}=\boldsymbol{0} \quad \hat{\boldsymb ...

  3. Halcon学习之六:获取Image图像中Region区域的特征参数

    area_center_gray ( Regions, Image : : : Area, Row, Column )    计算Image图像中Region区域的面积Area和重心(Row,Colu ...

  4. 前端 JS 获取 Image 图像 宽高 尺寸

    前端 JS 获取 Image 图像 宽高 尺寸 简介 项目中用到获取图片的原始尺寸,然后适配宽高:网上的大部分前端解决方案,都是new Image()后,在onload事件中获取image的尺寸. 在 ...

  5. vc/mfc获取rgb图像数据后动态显示及保存图片的方法

    vc/mfc获取rgb图像数据后动态显示及保存图片的方法 该情况可用于视频通信中获取的位图数据回放显示或显示摄像头捕获的本地图像 第一种方法 #include<vfw.h> 加载 vfw3 ...

  6. Html5 中获取镜像图像 - 解决 WebGL 中纹理倒置问题

    Html5 中获取镜像图像 - 解决 WebGL 中纹理倒置问题 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致& ...

  7. WordPress获取特色图像的链接地址

    为什么要获取WordPress的特色图像呢? 这主要是因为,我们已经写好了静态模板文件,只有获取WordPress特色图像地址插入进去就可以了,非常方便. 还有就是有的时候,我们需要设置图片的宽度为1 ...

  8. Hi3516开发笔记(十):Qt从VPSS中获取通道图像数据存储为jpg文件

    前言   上一篇已经将himpp套入qt的基础上进行开发.那么qt中拿到frame则是很关键的交互,这是qt与海思可能编解码交叉开发的关键步骤.   受限制   因为直接配置sample的vi比较麻烦 ...

  9. 【枚举】【最小表示法】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem F. Matrix Game

    给你一个n*m的字符矩阵,将横向(或纵向)全部裂开,然后以任意顺序首尾相接,然后再从中间任意位置切开,问你能构成的字典序最大的字符串. 以横向切开为例,纵向类似. 将所有横排从大到小排序,枚举最后切开 ...

  10. 【图像处理】Golang 获取JPG图像的宽高

    一.背景 有些业务需要判断图片的宽高,来做一些图片相关缩放,旋转等基础操作. 但是图片缩放,旋转,拼接等操作需要将图片从 JPG 格式转成 RGBA 格式操作,操作完毕后,再转回 JPG 图片. 那如 ...

随机推荐

  1. 洛谷P1381单词背诵

    单词背诵 题目描述 灵梦有 \(n\) 个单词想要背,但她想通过一篇文章中的一段来记住这些单词. 文章由 \(m\) 个单词构成,她想在文章中找出连续的一段,其中包含最多的她想要背的单词(重复的只算一 ...

  2. Kubernetes CNI 插件选型和应用场景探讨

    作者:马伟,青云科技容器顾问,云原生爱好者,目前专注于云原生技术,云原生领域技术栈涉及 Kubernetes.KubeSphere.KubeKey 等. 本文介绍容器环境常见网络应用场景及对应场景的 ...

  3. 关于git的安装

    window平台下面: 步骤一: 首先去官网下载安装包: 官方链接:https://git-scm.com/download/win 至于选择32位还是64为的,各位就见仁见智了(根据自己的系统). ...

  4. ToDesk云电脑实测!轻松应对游戏电竞、AIGC创作、设计建模等场景

    万物智联时代,现代社会对数字计算的需求呈指数级增长.当算力成为推动技术创新和应用发展的重要引擎,云电脑产业正在悄然占据国内算力应用的市场,成为新时代的数字经济发展方向.1 云电脑,顾名思义,是一台随时 ...

  5. 写代码被大语言模型坑之使用LocalDateTime比较两个时间差了几天

    自从去年ChatGPT3.5发布后使用了几次,现在写代码基本上离不开它和它的衍生产品们了.一方面查资料很方便,快速提炼要点总结:另一方面想写什么样的代码一问就能生成出来,功能大差不差,稍微改改就能用, ...

  6. 工作中的技术总结 _Thymeleaf限制字符串的展示长度 _20210910

    工作中的技术总结 _Thymeleaf限制字符串的展示长度 _20210910 比较简单就这一行代码 #strings.abbreviate 应该是调用了 thymeleaf 的内置函数 这一个方法的 ...

  7. Java常见面试真题之中级进阶

    前言 本来想着给自己放松一下,刷刷博客,突然被几道面试题难倒!java反射的作用于原理?说说List,Set,Map三者的区别?Object 有哪些常用方法?大致说一下每个方法的含义?Java 创建对 ...

  8. 关于Requests交互超时的处理方式

    拿 https://aes.cryptohack.org/ecb_oracle 这道题来做示范. 由于这个链接的本地服务器在外国,因此我们很容易就会连接超时. 如下一个脚本: import reque ...

  9. 返璞归真!使用 alpinejs 开发交互式 web 应用,抛弃 node_modules 和 webpack 吧!

    前言 最近一直在使用 DjangoStarter 开发各种小项目,之前我是比较喜欢前后端分离的,后端用 Ninja API,前端 nextjs,开发起来也挺舒服的,交互体验也比较好. 不过我在网上冲浪 ...

  10. vue $forceUpdate()强制刷新

    改变列表的值 一直不渲染 <van-pull-refresh v-model="refreshing" @refresh="onRefresh"> ...