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…

神经网络基础-神经网络补充概念-44-minibatch梯度下降法

概念 小批量梯度下降法&#xff08;Mini-Batch Gradient Descent&#xff09;是梯度下降法的一种变体&#xff0c;它结合了批量梯度下降&#xff08;Batch Gradient Descent&#xff09;和随机梯度下降&#xff08;Stochastic Gradient Descent&#xff09;的优点。在小批量梯…

Apache Doris大规模数据使用指南

目录 发展历史 架构介绍 弹性MPP架构-极简架构 逻辑架构 基本访问架构 分区 创建单分区表

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

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

音频解码及如何在Java实现

本人并不干这个&#xff0c;但是被迫下水了解了一下这个&#xff0c;稍微做了一下整理。再就是感觉现在网上以及ChatGPT在这方面给出的答案太水了&#xff0c;在此开辟一篇。无意放出代码&#xff0c;这里只介绍一些可能重要的点。 本来以为有了ChatGPT写这些就没有必要了&…

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;显…

神经网络基础-神经网络补充概念-32-神经网络与大脑

概念 神经网络&#xff08;Neural Networks&#xff09;是受到生物神经系统启发而设计的机器学习模型&#xff0c;用于处理和学习复杂的数据模式。尽管神经网络的设计和工作原理与大脑有一些相似之处&#xff0c;但它们并不完全相同&#xff0c;以下是神经网络和大脑之间的一些…

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

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

RestTemplate

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

js拼接字符串

在js中&#xff0c;你可以使用字符串拼接的方式创建新的字符串。 下面是一些常用的方法&#xff1a; 1、使用运算符&#xff1a; var str1 "Hello"; var str2 "World"; var result str1 " " str2; console.log(result); // 输出&#xf…

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

文章目录 链表合并两个有序链表反转链表复制带随机指针的链表环形链表环形链表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…