Opencv Surf算子特征提取与最优匹配
Opencv中Surf算子提取特征,生成特征描述子,匹配特征的流程跟Sift是完全一致的,这里主要介绍一下整个过程中需要使用到的主要的几个Opencv方法。
1. 特征提取
特征提取使用SurfFeatureDetector类中的detect方法,先定义一个SurfFeatureDetector类的对象,通过对象调用detect方法就可以提取输入图像的Surf特征。可以使用不带参数的默认构造函数构建SurfFeatureDetector对象,也可以使用含参数的构造函数:
CV_WRAP SURF(double hessianThreshold,
int nOctaves=4, int nOctaveLayers=2,
bool extended=true, bool upright=false);
从参数分布上可以看出,我们可以自定义Hessian阈值和尺度空间的组和层的个数。
特别要关注一下第一个参数hessianThreshold是图像Hessian矩阵判别式的阈值,值越大检测出的特征点就越少,也就意味着特征点越稳定。
2. 特征点绘制
特征点绘制是为了把检测出来的Surf特征点在原图上绘制出来,这一步是为了把特征点直观的显示出来给我们看,跟整个Surf算子的特征提取和匹配流程没关系。
绘制使用drawKeypoints方法:
void drawKeypoints( const Mat& image, const vector<KeyPoint>& keypoints, CV_OUT Mat& outImage,
const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT );
第一个参数image:原始图像,可以使三通道或单通道图像;
第二个参数keypoints:特征点向量,向量内每一个元素是一个KeyPoint对象,包含了特征点的各种属性信息;
第三个参数outImage:特征点绘制的画布图像,可以是原图像;
第四个参数color:绘制的特征点的颜色信息,默认绘制的是随机彩色;
第五个参数flags:特征点的绘制模式,其实就是设置特征点的那些信息需要绘制,那些不需要绘制,有以下几种模式可选:
DEFAULT:只绘制特征点的坐标点,显示在图像上就是一个个小圆点,每个小圆点的圆心坐标都是特征点的坐标。
DRAW_OVER_OUTIMG:函数不创建输出的图像,而是直接在输出图像变量空间绘制,要求本身输出图像变量就 是一个初始化好了的,size与type都是已经初始化好的变量
NOT_DRAW_SINGLE_POINTS:单点的特征点不被绘制
DRAW_RICH_KEYPOINTS:绘制特征点的时候绘制的是一个个带有方向的圆,这种方法同时显示图像的坐 标,size,和方向,是最能显示特征信息的一种绘制方式。
3. 特征点描述
特征点描述使用SurfDescriptorExtractor类中的compute方法。
4. 特征点匹配
特征点匹配可以使用BruteForceMatcher类或FlannBasedMatcher类的match方法。
5. 最优匹配点筛选
通过以上步骤获取的匹配特征点可能有很多,会有很多误匹配,实际使用中,往往需要有限个数的最优匹配点即可,用于定位、融合、拼接或3D重构等。
最优匹配点的筛选可以通过按一定比例提取出排名靠前的匹配点来实现。
6. 绘制匹配点
绘制匹配点使用drawMatches方法实现。
drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
const Mat& img2, const vector<KeyPoint>& keypoints2,
const vector<DMatch>& matches1to2, Mat& outImg,
const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1),
const vector<char>& matchesMask=vector<char>(), int flags=DrawMatchesFlags::DEFAULT );
参数很多,重点说一下最后一个参数flags,它跟drawKeypoints方法中flags的含义是一样的。
当仅使用筛选出的最优匹配点进行匹配的时候,意味着会有很多非最优的特征点不会被匹配,这时候可以设置flags=DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ,意味着那些不是最优特征点的点不会被绘制出来,图上不会再有那么多花花绿绿的小圆圈了,这个简单的设置可以拯救很多重度密集恐怖症患者的生命。
以下是整个流程的Opencv实现:
#include "highgui/highgui.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/legacy/legacy.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc,char *argv[])
{
Mat image01=imread(argv[1]);
Mat image02=imread(argv[2]);
Mat image1,image2;
image1=image01.clone();
image2=image02.clone();
//提取特征点
SurfFeatureDetector surfDetector(4000); //hessianThreshold,海塞矩阵阈值,并不是限定特征点的个数
vector<KeyPoint> keyPoint1,keyPoint2;
surfDetector.detect(image1,keyPoint1);
surfDetector.detect(image2,keyPoint2);
//绘制特征点
drawKeypoints(image1,keyPoint1,image1,Scalar::all(-1),DrawMatchesFlags::DEFAULT);
drawKeypoints(image2,keyPoint2,image2,Scalar::all(-1),DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
imshow("KeyPoints of image1",image1);
imshow("KeyPoints of image2",image2);
//特征点描述,为下边的特征点匹配做准备
SurfDescriptorExtractor SurfDescriptor;
Mat imageDesc1,imageDesc2;
SurfDescriptor.compute(image1,keyPoint1,imageDesc1);
SurfDescriptor.compute(image2,keyPoint2,imageDesc2);
//特征点匹配并显示匹配结果
//BruteForceMatcher<L2<float>> matcher;
FlannBasedMatcher matcher;
vector<DMatch> matchePoints;
matcher.match(imageDesc1,imageDesc2,matchePoints,Mat());
//提取强特征点
double minMatch=1;
double maxMatch=0;
for(int i=0;i<matchePoints.size();i++)
{
//匹配值最大最小值获取
minMatch=minMatch>matchePoints[i].distance?matchePoints[i].distance:minMatch;
maxMatch=maxMatch<matchePoints[i].distance?matchePoints[i].distance:maxMatch;
}
//最大最小值输出
cout<<"最佳匹配值是: "<<minMatch<<endl;
cout<<"最差匹配值是: "<<maxMatch<<endl;
//获取排在前边的几个最优匹配结果
vector<DMatch> goodMatchePoints;
for(int i=0;i<matchePoints.size();i++)
{
if(matchePoints[i].distance<minMatch+(maxMatch-minMatch)/2)
{
goodMatchePoints.push_back(matchePoints[i]);
}
}
//绘制最优匹配点
Mat imageOutput;
drawMatches(image01,keyPoint1,image02,keyPoint2,goodMatchePoints,imageOutput,Scalar::all(-1),
Scalar::all(-1),vector<char>(),DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
imshow("Mathch Points",imageOutput);
waitKey();
return 0;
}
输入图像的特征点在原图对应位置上做了标注,这里使用了默认的绘制方式,特征点只标注了位置,没有方向和尺度信息:
目标图像特征点的绘制使用了DrawMatchesFlags::DRAW_RICH_KEYPOINTS绘制方式,特征点包含了位置、尺度、方向信息:
特征点的匹配是经过筛选的最优匹配点,匹配对数较少,并且不显示匹配失败的特征点:
不筛选最优匹配点的话,会有比较多的特征点配对成功,当然误匹配会更多:
Opencv Surf算子特征提取与最优匹配的更多相关文章
- Opencv Surf算子中keyPoints,描述子Mat矩阵,配对向量DMatch里都包含了哪些好玩的东东?
Surf算法是一把牛刀,我们可以很轻易的从网上或各种Opencv教程里找到Surf的用例,把例程中的代码或贴或敲过来,满心期待的按下F5,当屏幕终于被满屏花花绿绿的小圆点或者N多道连接线条霸占时,内心 ...
- Opencv Sift算子特征提取与匹配
SIFT算法的过程实质是在不同尺度空间上查找特征点(关键点),用128维方向向量的方式对特征点进行描述,最后通过对比描述向量实现目标匹配. 概括起来主要有三大步骤: 1.提取关键点: 2.对关键点附加 ...
- OpenCV——SURF特征检测、匹配与对象查找
SURF原理详解:https://wenku.baidu.com/view/2f1e4d8ef705cc1754270945.html SURF算法工作原理 选择图像中的POI(Points of i ...
- [OpenCV-Python] OpenCV 中图像特征提取与描述 部分 V (二)
部分 V图像特征提取与描述 OpenCV-Python 中文教程(搬运)目录 34 角点检测的 FAST 算法 目标 • 理解 FAST 算法的基础 • 使用 OpenCV 中的 FAST 算法相关函 ...
- 3. opencv进行SIFT特征提取
opencv中sift特征提取的步骤 使用SiftFeatureDetector的detect方法检测特征存入一个向量里,并使用drawKeypoints在图中标识出来 SiftDescriptorE ...
- SURF算子(1)
SURF算子,参考这篇文章的解释http://www.ipol.im/pub/art/2015/69/ SURF 是 Speeded Up Robust Features 加速鲁棒特征的含义. T ...
- poj 2195 二分图最优匹配 或 最小费用最大流
就是最基本的二分图最优匹配,将每个人向每个房子建一条边,权值就是他们manhattan距离.然后对所有权值取反,求一次最大二分图最优匹配,在将结果取反就行了. #include<iostream ...
- 51nod 算法马拉松4 D装盒子(网络流 / 二分图最优匹配)
装盒子 基准时间限制:1 秒 空间限制:131072 KB 分值: 160 有n个长方形盒子,第i个长度为Li,宽度为Wi,我们需要把他们套放.注意一个盒子只可以套入长和宽分别不小于它的盒子,并且 ...
- hdu2255 奔小康赚大钱 km算法解决最优匹配(最大权完美匹配)
/** 题目:hdu2255 奔小康赚大钱 km算法 链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 题意:lv 思路:最优匹配(最大权完美匹配) ...
随机推荐
- ArcGIS小技巧——提取面要素的质心点
如下图,现在要做这样一件事,提取面图层中每一个图斑的质心点,然后使用质心点提取图层中的一个属性值,并在此基础上进行克里金插值,生成该属性的空间插值图.当然,今天这段文字主要简单说一下怎样提取面图层的质 ...
- Xcode6:No architectures to compile for(ONLY_ACTIVE_ARCH=YES...)
1.问题描写叙述 Xcode6真机測试旧project,不能执行,报错例如以下: 2.解决方式 问题非常明显,当前的执行模式设置了ONLY_ACTIVE_ARCH为Yes,当时的project的Val ...
- 6 Spring Boot 静态资源处理
转自:https://blog.csdn.net/catoop/article/details/50501706
- 86.八千万qq密码按相似度排序并统计密码出现次数,生成密码库
存储qq的文件地址以及按照密码相似度排序的文件地址 //存储qq的文件的地址 ] = "QQ.txt"; //按照密码相似度排序的文件地址 ] = "QQpassword ...
- loadrunner监控apache服务
一.apache配置步骤(假设apache服务已安装) 1.使用find / -name httpd.conf命令查找httpd.conf文件 2.使用cd opt/lampp/apache2/con ...
- POJ 1166 The Clocks 高斯消元 + exgcd(纯属瞎搞)
依据题意可构造出方程组.方程组的每一个方程格式均为:C1*x1 + C2*x2 + ...... + C9*x9 = sum + 4*ki; 高斯消元构造上三角矩阵,以最后一个一行为例: C*x9 = ...
- JS学习笔记 - fgm练习 - 鼠标移入/移出div样式改变
思路: div的默认样式正常设置. 鼠标移入时,发生改变的样式有3个,即 边框颜色,div背景色,字体颜色. 把这三个css改变设置在一个类名下,再通过js给div动态 添加/去除这个类名,实现div ...
- python分解质因数
将一个正整数分解质因数.例如:输入90,打印出90=2*3*3*5. # !/usr/bin/env python # -*- coding:utf-8 -*- # Author:Hiuhung Wa ...
- jQuery笔记---选择器(三)
1.1查找隐藏的tr元素的个数 $(“table tr:hidden”).size() 查找所有可见的tr元素的个数 $(“table tr:not(:hidden)”).size() 一般是不使 ...
- radare, the reverse engineering framework
History The radare project [http://radare.org/] started in February of 2006 aiming to provide a free ...