Opencv 之ORB特征提取与匹配API简介及使用例程

Opencv 之ORB特征提取与匹配API简介及使用例程

  • ORB因其速度较快常被用于视觉SLAM中的位姿估计、视觉里程、图像处理中的特征提取与匹配及图像拼接等领域
  • 本文将详细给出使用例程及实现效果展示

1. API 简介

  • 创建
static Ptr<ORB> cv::ORB::create	(int nfeatures = 500,                                   //nfeatures 最终输出最大特征点数目float scaleFactor = 1.2f,                            // scaleFactor 金字塔上采样比率int nlevels = 8,                                            // nlevels 金字塔层数int edgeThreshold = 31,                                // edgeThreshold 边缘阈值int firstLevel = 0,int WTA_K = 2,                                                // WTA_K这个是跟BRIEF描述子用的ORB::ScoreType 	scoreType = ORB::HARRIS_SCORE,        //  scoreType 对所有的特征点进行排名用的方法int patchSize = 31,int fastThreshold = 20 
)
  • 检测
void cv::Feature2D::detect	(	InputArray 	image,   //输入图像std::vector< KeyPoint > & 	keypoints,    //待搜索特征点InputArray 	mask = noArray()    //操作掩码)	
  • 计算
void cv::Feature2D::compute	(	InputArrayOfArrays 	images,    //输入图像std::vector< std::vector< KeyPoint > > & 	keypoints,OutputArrayOfArrays 	descriptors   //描述子)	
  • 检测与计算
 void cv::Feature2D::detectAndCompute	(	InputArray 	image,InputArray 	mask,std::vector< KeyPoint > & 	keypoints,OutputArray 	descriptors,bool 	useProvidedKeypoints = false )	
  • 绘制特征点
void cv::drawMatches	(	InputArray 	img1,const std::vector< KeyPoint > & 	keypoints1,InputArray 	img2,const std::vector< KeyPoint > & 	keypoints2,const std::vector< DMatch > & 	matches1to2,InputOutputArray 	outImg,const Scalar & 	matchColor = Scalar::all(-1),const Scalar & 	singlePointColor = Scalar::all(-1),const std::vector< char > & 	matchesMask = std::vector< char >(),DrawMatchesFlags 	flags = DrawMatchesFlags::DEFAULT )	
  • 绘制匹配点对
void cv::drawMatches	(	InputArray 	img1,const std::vector< KeyPoint > & 	keypoints1,InputArray 	img2,const std::vector< KeyPoint > & 	keypoints2,const std::vector< DMatch > & 	matches1to2,InputOutputArray 	outImg,const Scalar & 	matchColor = Scalar::all(-1),const Scalar & 	singlePointColor = Scalar::all(-1),const std::vector< char > & 	matchesMask = std::vector< char >(),DrawMatchesFlags 	flags = DrawMatchesFlags::DEFAULT )	

2. 特征提取

  • 讲述特征点提取与描述子计算,实现如下:
int main()
{Mat img = imread("./data/test3/lena.png");if (!img.data || img.empty()){cout << "图像读取错误!" << endl;return -1;}//创建ORB关键点Ptr<ORB> orb = ORB::create(500, 1.2f);double t1 = getTickCount();vector<KeyPoint>Keypoints;Mat descriptions;
#if 0//计算ORB关键点orb->detect(img, Keypoints);//计算ORB描述子orb->compute(img, Keypoints, descriptions);
#elseorb->detectAndCompute(img, cv::Mat(), Keypoints, descriptions);
#endif // 0double t2 = (getTickCount() - t1) / getTickFrequency() * 1000;cout << "img.size = " << img.size() << " , cost time = " << t2 << "ms\n";//绘制特征点Mat imgAngle;img.copyTo(imgAngle);//绘制不含角度和大小的结果drawKeypoints(img, Keypoints, img, Scalar(255, 255, 255));//绘制含有角度和大小的结果drawKeypoints(img, Keypoints, imgAngle, Scalar(255, 255, 255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);//显示结果string wname1 = "不含角度和大小的结果", wname2 = "含角度和大小的结果";namedWindow(wname1, WINDOW_NORMAL);namedWindow(wname2, 0);imshow(wname1, img);imshow(wname2, imgAngle);waitKey(0);return 1;
}

在这里插入图片描述

3. 特征匹配

  • 暴力匹配实现:
#include<iostream>
#include<opencv2/opencv.hpp>
#include<vector>using namespace std;
using namespace cv;int main()
{//灰度格式读取Mat img1, img2;img1 = imread("./data/test3/1.jpg",IMREAD_GRAYSCALE);img2 = imread("./data/test3/2.jpg",0);if (img1.empty() || img2.empty()){cout << "img.empty!!!\n";return -1;}//提取orb特征点vector<KeyPoint>Keypoints1, Keypoints2;Mat descriptions1, descriptions2;//计算特征点orb_features(img1, Keypoints1, descriptions1);orb_features(img2, Keypoints2, descriptions2);//特征点匹配vector<DMatch>matches; BFMatcher matcher(NORM_HAMMING); //定义特征点匹配的类,使用汉明距离matcher.match(descriptions1, descriptions2, matches);cout << "matches = " << matches.size() << endl;//通过汉明距离筛选匹配结果double min_dist = 10000, max_dist = 0;for (int i = 0; i < matches.size(); ++i){double dist = matches[i].distance;min_dist = min_dist < dist ? min_dist : dist;max_dist = max_dist > dist ? max_dist : dist;}//输出计算的最大、最小距离cout << "min_dist = " << min_dist << endl;cout << "max_dist = " << max_dist << endl;//通过距离提出误差大的点vector<DMatch>goodmatches;for (int i = 0; i < matches.size(); ++i){if (matches[i].distance <= MAX(1.8 * min_dist, 30)) //需调参{goodmatches.push_back(matches[i]);}}cout << "good_min = " << goodmatches.size() << endl;//绘制结果Mat outimg, outimg1;drawMatches(img1, Keypoints1, img2, Keypoints2, matches, outimg);drawMatches(img1, Keypoints1, img2, Keypoints2, goodmatches, outimg1);string wname1 = "未筛选结果", wname2 = "最小汉明距离筛选";namedWindow(wname1, WINDOW_NORMAL);namedWindow(wname2, 0);imshow(wname1, outimg);imshow(wname2, outimg1);waitKey(0);return 1;
}

其效果如下:

在这里插入图片描述

在这里插入图片描述

  • 最近邻匹配实现如下:
if (descriptions1.type() != CV_32F){descriptions1.convertTo(descriptions1, CV_32F);descriptions2.convertTo(descriptions2, CV_32F);}//特征点匹配vector<DMatch>matches;FlannBasedMatcher matcher; //定义特征点匹配的类,使用汉明距离matcher.match(descriptions1, descriptions2, matches);cout << "matches = " << matches.size() << endl;//通过汉明距离筛选匹配结果double min_dist = 10000, max_dist = 0;for (int i = 0; i < matches.size(); ++i){double dist = matches[i].distance;min_dist = min_dist < dist ? min_dist : dist;max_dist = max_dist > dist ? max_dist : dist;}//输出计算的最大、最小距离cout << "min_dist = " << min_dist << endl;cout << "max_dist = " << max_dist << endl;//通过距离提出误差大的点vector<DMatch>goodmatches;for (int i = 0; i < matches.size(); ++i){if (matches[i].distance <= 0.6 * max_dist) //需调参{goodmatches.push_back(matches[i]);}}cout << "good_min = " << goodmatches.size() << endl;

其效果如下:
在这里插入图片描述
在这里插入图片描述

  • RANSAC优化匹配
void ransac(vector<DMatch>matches, vector<KeyPoint>queryKeyPoint,vector<KeyPoint>trainKeyPoint, vector<DMatch>& matches_ransac)
{//定义保存匹配点对坐标vector<Point2f>srcPoints(matches.size()), dstPoints(matches.size());//保存从关键点中提取到的匹配点对坐标for (int i = 0; i < matches.size(); ++i){srcPoints[i] = queryKeyPoint[matches[i].queryIdx].pt;dstPoints[i] = trainKeyPoint[matches[i].trainIdx].pt;}//匹配点对RANSAC过滤vector<int>inlierMask(srcPoints.size());findHomography(srcPoints, dstPoints, RANSAC, 5, inlierMask);//手动保留RANSAC过滤后的匹配点对for (int i = 0; i < inlierMask.size(); ++i){if (inlierMask[i])matches_ransac.push_back(matches[i]);}
}//*************************RANSAC*******************************************
//main函数中放在暴力匹配代码后://特征点匹配vector<DMatch>matches; BFMatcher matcher(NORM_HAMMING); //定义特征点匹配的类,使用汉明距离matcher.match(descriptions1, descriptions2, matches);cout << "matches = " << matches.size() << endl;//通过汉明距离筛选匹配结果double min_dist = 10000, max_dist = 0;for (int i = 0; i < matches.size(); ++i){double dist = matches[i].distance;min_dist = min_dist < dist ? min_dist : dist;max_dist = max_dist > dist ? max_dist : dist;}//输出计算的最大、最小距离cout << "min_dist = " << min_dist << endl;cout << "max_dist = " << max_dist << endl;//通过距离提出误差大的点vector<DMatch>goodmatches;for (int i = 0; i < matches.size(); ++i){if (matches[i].distance <= MAX(1.8 * min_dist, 30)) //需调参{goodmatches.push_back(matches[i]);}}cout << "good_min = " << goodmatches.size() << endl;//RANSAC优化:vector<DMatch>good_ransac;ransac(goodmatches, Keypoints1, Keypoints2, good_ransac);cout << "good_ransac = " << good_ransac.size() << endl;Mat output_;drawMatches(img1, Keypoints1, img2, Keypoints2, good_ransac, output_);namedWindow("ransac", 0);imshow("ransac", output_);

在这里插入图片描述

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

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

相关文章

无涯教程-Perl - use函数

描述 此函数将MODULE导出的所有功能(或仅LIST引用的功能)导入当前包的名称空间。有效等效于- BEGIN { require "Module.pm"; Module->import(); }也用于在当前脚本上强加编译器指令(编译指示),尽管从本质上讲它们只是模块。 请注意,use语句在编译时进行判断。在…

springcloud3 hystrix实现服务熔断的案例配置3

一 hystrix的熔断原理 1.1 hystrix的熔断原理 在springcloud的框架里&#xff0c;熔断机制是通过hystrix实现&#xff0c;hystrix会监控服务之间的调用。当失败调用达到一定的阈值&#xff0c;默认是5s内失败20次&#xff0c;就会启用hystrix的熔断机制&#xff0c;使用命Hy…

【C++ 记忆站】缺省参数

文章目录 缺省参数的概念缺省参数的分类1、全缺省参数2、半缺省参数 缺省参数实际应用场景 缺省参数的概念 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时&#xff0c;如果没有指定实参则采用该形参的缺省值&#xff0c;否则使用指定的实参 正常调用一…

Docker部署ES服务,canal全量同步的时候内存爆炸,ES/Canal Adapter自动关闭,CPU100%

文章目录 问题解决方案1. 对ES的限制2. 对Canal-Adapter的限制 问题 使用canal-adapter全量同步&#xff08;参考Canal Adapter1.1.5版本API操作服务&#xff0c;手动同步数据&#xff08;4&#xff09;&#xff09;的时候 小批量数据可以正常运行&#xff08;几千条&#xf…

Llama 2免费托管及API提供

Llama 2 是 Meta 最新的文本生成模型&#xff0c;目前其性能优于所有开源替代方案。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 1、强大的Llama 2 它击败了 Falcon-40B&#xff08;之前最好的开源基础模型&#xff09;&#xff0c;与 GPT-3.5 相当&#xff0c;仅低…

【uni-app】 .sync修饰符与$emit(update:xxx)实现数据双向绑定

最近在看uni-app文档&#xff0c;看到.sync修饰符的时候&#xff0c;觉得很有必要记录一下 其实uni-app是一个基于Vue.js和微信小程序开发框架的跨平台开发工具 所以经常会听到这样的说法&#xff0c;只要你会vue&#xff0c;uni-app就不难上手 在看文档的过程中&#xff0c;发…

.netcore grpc客户端工厂及依赖注入使用

一、客户端工厂概述 gRPC 与 HttpClientFactory 的集成提供了一种创建 gRPC 客户端的集中方式。可以通过依赖包Grpc.Net.ClientFactory中的AddGrpcClient进行gRPC客户端依赖注入AddGrpcClient函数提供了许多配置项用于处理一些其他事项&#xff1b;例如AOP、重试策略等 二、案…

miniExcel 生成excel

一、nuget dotnet add package MiniExcel --version 1.31.2 二、新建表及数据 ExampleProducts 三、这里我用了Dapper.Query方法 读取excel public virtual async Task<IActionResult> Anonymous(){try{//using (var connection _dbContext.GetDbConnection())//{//…

linux中的ifconfig和ip addr

在linux操作系统中ifconfig和ip addr都是显示网卡配置信息的命令&#xff0c;好多人有疑惑它们有什么区别呢 区别1&#xff1a;对于linux发行的版本不一样 ip addr是对新发行版本的linux使用会比较多&#xff1b;而ifconfig是老版本遇到使用的会比较多。 区别2&#xff1a;显…

基于 KubeSphere 的应用容器化在智能网联汽车领域的实践

公司简介 某国家级智能网联汽车研究中心成立于 2018 年&#xff0c;是担当产业发展咨询与建议、共性技术研发中心、创新成果转化的国家级创新平台&#xff0c;旨在提高我国在智能网联汽车及相关产业在全球价值链中的地位。 目前着力建设基于大数据与云计算的智能汽车云端运营…

RestTemplate

RestTemplate介绍 RestTemplate是Spring提供的用于访问RESTful服务的客户端&#xff0c;RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。RestTemplate默认依赖JDK提供http连接的能力&#xff08;HttpURLConnection&#xff09;&#xff0c;…

【数据结构】链表常见题目

文章目录 链表合并两个有序链表反转链表复制带随机指针的链表环形链表环形链表II相交链表移除链表元素链表中倒数第k个节点链表分割链表的回文结构链表的中间节点旋转链表链表排序链表求和 (逆序求)链表求和II (正序求)重排链表奇偶链表反转链表II <==> 链表内指定区间反…

(二)掌握最基本的Linux服务器用法——Linux下简单的C/C++ 程序、项目编译

1、静态库与动态库 静态库(Static Library)&#xff1a;静态库是编译后的库文件&#xff0c;其中的代码在编译时被链接到程序中&#xff0c;因此它会与程序一起形成一个独立的可执行文件。每个使用静态库的程序都会有自己的库的副本&#xff0c;这可能会导致内存浪费。常用后缀…

opencv简单使用

cv2库安装&#xff0c; conda install opencv-python注意cv2使用时&#xff0c;路径不能有中文。&#xff08;不然会一直’None’ _ update # 处理中文路径问题 def cv_imread(file_path): #使用之前需要导入numpy、cv2库&#xff0c;file_path为包含中文的路径return cv2.imd…

idea入门与maven配置的一些介绍

idea入门与maven配置的一些介绍 1.确保Java和Maven已安装2.创建一个新的Maven项目3.导航到要创建项目的目录配置Maven4.配置项目的pom.xml文件5.配置其他Tomcat和设置jdk6.构建和运行项目 关于idea入门基础配置 步骤1&#xff1a;安装IntelliJ IDEA 首先&#xff0c;从IntelliJ…

计算机竞赛 python+大数据校园卡数据分析

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于yolov5的深度学习车牌识别系统实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;4分工作量&#xff1a;4分创新点&#xff1a;3分 该项目较为新颖&am…

记录一个编译TubeTK时的报错:at_check问题

在使用如下命令安装TubeTK的cuda_nms时&#xff0c;报了一个错误&#xff0c;记录一下这个错误和解决办法 (base) redmeryredmery:~/Desktop/MOT/TubeTK/post_processing/nms$ python setup.py build_ext --inplace因为这个命令是在/home/redmery/Desktop/MOT/TubeTK/install/…

Talk | ACL‘23 杰出论文奖上海交通大学吴蔚琪:预训练语言模型对本体知识的记忆与理解

本期为TechBeat人工智能社区第523期线上Talk&#xff01; 北京时间8月17日(周四)20:00&#xff0c;上海交通大学硕士研究生—吴蔚琪的Talk已准时在TechBeat人工智能社区开播&#xff01; 她与大家分享的主题是: “预训练语言模型对本体知识的记忆与理解”&#xff0c;分享了预训…

Python入门【TCP建立连接的三次握手、 TCP断开连接的四次挥手、套接字编程实战、 TCP编程的实现、TCP双向持续通信】(二十七)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小王&#xff0c;CSDN博客博主,Python小白 &#x1f4d5;系列专栏&#xff1a;python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 &#x1f4e7;如果文章知识点有错误…