[转]OpenCV_Find Basis F-Matrix and computeCorrespondEpilines(获取一对图像的基础矩阵及对应极线)
代码如下:
// 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(获取一对图像的基础矩阵及对应极线)的更多相关文章
- 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 ...
- 2D-2D:对极几何 基础矩阵F 本质矩阵E 单应矩阵H
对极约束 \[ \boldsymbol{x}_{2}^{T} \boldsymbol{F} \boldsymbol{x}_{1}=\boldsymbol{0} \quad \hat{\boldsymb ...
- Halcon学习之六:获取Image图像中Region区域的特征参数
area_center_gray ( Regions, Image : : : Area, Row, Column ) 计算Image图像中Region区域的面积Area和重心(Row,Colu ...
- 前端 JS 获取 Image 图像 宽高 尺寸
前端 JS 获取 Image 图像 宽高 尺寸 简介 项目中用到获取图片的原始尺寸,然后适配宽高:网上的大部分前端解决方案,都是new Image()后,在onload事件中获取image的尺寸. 在 ...
- vc/mfc获取rgb图像数据后动态显示及保存图片的方法
vc/mfc获取rgb图像数据后动态显示及保存图片的方法 该情况可用于视频通信中获取的位图数据回放显示或显示摄像头捕获的本地图像 第一种方法 #include<vfw.h> 加载 vfw3 ...
- Html5 中获取镜像图像 - 解决 WebGL 中纹理倒置问题
Html5 中获取镜像图像 - 解决 WebGL 中纹理倒置问题 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致& ...
- WordPress获取特色图像的链接地址
为什么要获取WordPress的特色图像呢? 这主要是因为,我们已经写好了静态模板文件,只有获取WordPress特色图像地址插入进去就可以了,非常方便. 还有就是有的时候,我们需要设置图片的宽度为1 ...
- Hi3516开发笔记(十):Qt从VPSS中获取通道图像数据存储为jpg文件
前言 上一篇已经将himpp套入qt的基础上进行开发.那么qt中拿到frame则是很关键的交互,这是qt与海思可能编解码交叉开发的关键步骤. 受限制 因为直接配置sample的vi比较麻烦 ...
- 【枚举】【最小表示法】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem F. Matrix Game
给你一个n*m的字符矩阵,将横向(或纵向)全部裂开,然后以任意顺序首尾相接,然后再从中间任意位置切开,问你能构成的字典序最大的字符串. 以横向切开为例,纵向类似. 将所有横排从大到小排序,枚举最后切开 ...
- 【图像处理】Golang 获取JPG图像的宽高
一.背景 有些业务需要判断图片的宽高,来做一些图片相关缩放,旋转等基础操作. 但是图片缩放,旋转,拼接等操作需要将图片从 JPG 格式转成 RGBA 格式操作,操作完毕后,再转回 JPG 图片. 那如 ...
随机推荐
- KubeSphere 社区双周报 | OpenFunction 发布 v1.1.1 | 2023.6.9-6.22
KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...
- .NET周刊【10月第3期 2024-10-20】
国内文章 我被 .NET8 JIT 的一个BUG反复折磨了半年之久(JIT tier1 finally optimizations) https://www.cnblogs.com/calvinK/p ...
- 基于surging 的木舟平台如何通过HTTP网络组件接入设备
一.概述 上篇文章介绍了木舟如何上传模块热部署,那么此篇文章将介绍如何利用HTTP网络组件接入设备,那么有些人会问木舟又是什么,是什么架构为基础,能做什么呢? 木舟 (Kayak) 是什么? 木舟(K ...
- Reviewbot 开源 | 为什么我们要打造自己的代码审查服务?
Reviewbot 是七牛云开源的一个项目,旨在提供一个自托管的代码审查服务, 方便做 code review/静态检查, 以及自定义工程规范的落地. 静态检查不是个新鲜事. 我记得早在几年前,我们就 ...
- AT开发FOTA远程升级:Air780EP低功耗4G模组
针对客户朋友的应用反馈,特本篇文章:基于Air780EP模组AT开发的FOTA远程升级指南. AT版本的远程升级主要是对AT固件版本进行升级,实际方式为通过合宙官方IoT平台升级或者使用自己搭建的 ...
- AI那么厉害,那测试开发和自动化测试这些职位是不是就多余了?
在当今科技飞速发展的时代,AI大模型如ChatGPT等如同璀璨星辰般闪耀登场,它们的强大功能引发了各个领域的诸多思考.在软件测试领域,不少人心里直犯嘀咕:这AI大模型都这么厉害了,那测试开发和自动化测 ...
- flask+gunicorn+supervisor部署项目
一.安装模块 pip install gunicorn gevent # 如果使用python supervisor,需要安装模块 pip install supervisor # 建议使用yum安装 ...
- MySQL底层概述—1.InnoDB内存结构
大纲 1.InnoDB引擎架构 2.Buffer Pool 3.Page管理机制之Page页分类 4.Page管理机制之Page页管理 5.Change Buffer 6.Log Buffer 1.I ...
- Linux C/C++编程之静态库
[图书推荐]<Linux C与C++一线开发实践(第2版)>_linux c与c++一线开发实践pdf-CSDN博客 <Linux C与C++一线开发实践(第2版)(Linux技术丛 ...
- git 推送代码到多个 远端仓库
业务场景 在开发代码时,有时希望将代码推送到两个远端仓库. 实现方法 git remote add origin giturl1 git remote add backup giturl2 git p ...