代码如下:

// 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. 现代化 React UI 库:Material-UI 详解!

    随着 React 在前端开发中的流行,越来越多的 UI 框架和库开始涌现,以帮助开发者更高效地构建现代化.响应式的用户界面.其中,Material-UI 是基于 Google Material Des ...

  2. 基于 KubeSphere 的运管系统落地实践

    作者:任建伟,某知名互联网公司云原生工程师,容器技术信徒,云原生领域的实践者. 背景介绍 在接触容器化之前,我们团队内部的应用一直都是基于虚拟机运管,由开发人员自行维护. 由于面向多开发部门服务,而开 ...

  3. WebUploader 文件上传,兼容ios和安卓

    var upImg = WebUploader.create({ auto: true, swf: 'webuploader-0.1.5/Uploader.swf', // 图片接收服务端. serv ...

  4. MySQL,你只需看这一篇文章就够了!

    MySQL--DAY02 distinct 去重 把查询结果去除重复记录[distinct] 注意:原表数据不会被修改,只是查询结果去重. 去重需要使用一个关键字:distinct mysql> ...

  5. DDCA —— 大缓存、虚拟内存:多核缓存、NUCA缓存、页表等

    1. 缓存中的多核问题 1.1 多核系统中的缓存 Intel Montecito缓存 两个 core,每个都有一个私有的12 MB的L3缓存和一个1 MB的L2缓存,图中深蓝色部分均为L3缓存. 在多 ...

  6. 解密prompt系列42. LLM通往动态复杂思维链之路

    最近大家都在探讨和尝试复现OpenAI O1的思考效果,解码出的关键技术方向,包括之前已经探讨过的Inference Time Scaling在推理过程中进行路径决策和选择.但想要更优的Inferen ...

  7. Memcached笔记——(一)安装&常规错误&监控

    08年的时候接触过Memcached,当时还对它的客户端产品嗤之以鼻,毕竟手工代码没有各种ORM原生XML配置方便.尽管如此,Memcached现在已经成了服务器架构里不可或缺的一部分! 相关链接:  ...

  8. 编写kickstart脚本,执行时遇到的问题

    KickStart脚本 #!/bin/bash #declare var yum_ins="yum -y install" sys_res="systemctl rest ...

  9. vue3 父子组件传值

    父传子组件 <template> <div> <!-- 通过自定义属性传递值 --> <Subassembly :value="doc"/ ...

  10. 从Delphi到Lazarus——Delphi转换器

    0.前言 在Lazarus中使用Delphi编写的文件是一件很简单的事情,这是因为Lazarus可以直接打开Delphi的任何文件,甚至有些文件可以不做任何修改就可以直接使用到你的Lazarus程序中 ...