Opencv(C++)系列学习---SIFT、SURF、ORB算子特征检测

简介: Opencv(C++)系列学习---SIFT、SURF、ORB算子特征检测

         对于特征检测和描述子的运行原理本文先不做具体介绍,在后续的更新中会依次详细解释。本文主要介绍常用三种特征检测算法的参数信息和简单应用。

1.SIFT、SURF、ORB三种算子的参数介绍

【1】SIFT算子定义介绍

static Ptr<SIFT> create(
    int  nfeatures =0,//需要的特征点的数量,是对特征点的质量进行排名,返回最好的前几个;
    int  n0ctaveLayers =3,//金字塔的层数;
    double contrastThrehold =0.04,//过滤特征点的阈值;
    double edgeThreshold =10;//过滤边缘效应的阈值;
    double sigma=1.6;//用于预处理光滑的;

(1)对于nfeature参数是需要的特征点的数量,当设置为0是,返回找到的所有特征点

(2)对于n0ctavelayers计算金字塔的层数是在设定值的基础上加3。

(3)对于contrasthreshold阈值,是过滤掉质量较差的阈值,值越大,过滤的越多。

(4)edgeThreshold过滤边缘效应的阈值,值越大,过滤的越少。

(5)sigma用于图像的光滑预处理,在图像中存在噪声或者其他干扰的情况下,值大一些还是挺有效果的。

【2】SURF算子定义介绍

static Ptr<SURF> create(
double hessianThreshold=100,//SURF中使用的hessian关键点检测器的阈值
int nOctaves = 4, //关键点检测器将使用的金字塔组数量
int nOctaveLayers = 3,//高斯金字塔每个组内图像的层数
bool extended = false, //扩展描述符标志(true使用扩展的128个元素的描述符,false使用64个元素的描述符)
bool upright = false//旋转的特征标志(true不计算方向,false计算方向)
);

检测流程如下:

(1)尺度空间的极值检测:搜索所有尺度空间上的图像,通过Hessian来识别潜在的对尺度和选择不变的兴趣点

(2)特征点过滤并进行精确定位

(3)特征方向赋值:统计特征点圆形领域内的Harr小波特征。即在60°扇形内,每次将60°扇形区域旋转0.2弧度进行统计,将值最大的哪个扇形的方向作为特征点的主方向

(4)特征点描述:沿着特征点主方向周围的邻域内,取4X4X4个矩形区域,统计每个小区域的Harr特征,然后每个区域得到一个4维的特征向量。一个特征点共有64维的特征向量作为SURF特征的描述子。

【3】ORB算子定义介绍

      ORB的全称是ORiented Brief,采用FAST(features from accelerated segment test)算法来检测特征点。与Brisk,AKAZE类似,ORB也分两部分,即特征点提取和特征点描述。特征提取是由FAST(Features from Accelerated Segment Test)算法发展来的,它基于特征点周围的图像灰度值,检测候选特征点周围一圈的像素值,如果候选点周围领域内有足够多的像素点与该候选点的灰度值差别够大,则认为该候选点为一个特征点。而特征点描述是根据BRIEF(Binary Robust Independent Elementary Features)特征描述算法改进的。

       将FAST特征点的检测方法与BRIEF特征描述子结合起来,并在它们原来的基础上做了改进与优化。据说ORB算法的速度是sift的100倍,是surf的10倍。ORB算法是为解决BRIEF的缺陷而改进的,主要解决两个缺点:噪声敏感、旋转不变性。

Ptr<ORB> create(
int nfeatures =500,
float scaleFactor=1.2f,
int nlevels=8,
int edgeThreshold=31,
int firstLevel=0,
int WTA_K=2,
int scoreTyoe=0,
int patchSize=31,
int fastThreshold=20
);

(1)nfeatures 为最多提取的特征点的数量;

(2)scaleFactor - 金字塔图像之间的尺度参数,类似于SIFT中的;

(3)nlevels – 高斯金字塔的层数;

(4)edgeThreshold – 边缘阈值,这个值主要是根据后面的patchSize来定的,靠近边缘edgeThreshold以内的像素是不检测特征点的。

(5)firstLevel - 看过SIFT都知道,我们可以指定第一层的索引值,这里默认为0。

(6)WET_K - 用于产生BIREF描述子的 点对的个数,一般为2个,也可以设置为3个或4个,那么这时候描述子之间的距离计算就不能用汉明距离了,而是应该用一个变种。OpenCV中,如果设置WET_K = 2,则选用点对就只有2个点,匹配的时候距离参数选择NORM_HAMMING,如果WET_K设置为3或4,则BIREF描述子会选择3个或4个点,那么后面匹配的时候应该选择的距离参数为NORM_HAMMING2。

(7)scoreType - 用于对特征点进行排序的算法,你可以选择HARRIS_SCORE,也可以选择FAST_SCORE,但是它也只是比前者快一点点而已。

(8)patchSize – 用于计算BIREF描述子的特征点邻域大小。

(9)FastThreshold-是Fast特征检测器的阈值。

关于ORB算子的更多介绍:

2.代码示例

#include<opencv2\opencv.hpp>
#include<opencv2\xfeatures2d.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\xfeatures2d\nonfree.hpp>
#include<iostream>
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;
int main(int argc,char** argv)
{
  //【0】改变字体颜色
  system("color 2F");
  //【1】载入源图片并显示
  Mat srcImage1 = imread("E:\\乔大花进度\\11-17\\surf特征检测\\1.jpg",1);
  Mat srcImage2 = imread("E:\\乔大花进度\\11-17\\surf特征检测\\2.jpg", 1);
  //【2】显示图片
  imshow("原始图1",srcImage1);
  imshow("原始图2",srcImage2);
  int minHessian = 400;//默认值为100
  vector<KeyPoint>keyPoints, keyPoints1;
  Mat resultImg, resultImage1;
  //关于定义的方法主要有两种
  //第一种指针形式定义
  //  Ptr<SURF\SIFT\ORB>detector = SURF\SIFT\ORB::create(minHessian, 4, 3, false, false);
  //第二种算子形式定义
  //SiftFeatureDetector\SurfFeatureDetector定义
  //第一种定义方式更普遍使用
  //SURF特征检测  //也可以写成SURF::create(minHessian)
  Ptr<SURF>detector = SURF::create(minHessian, 4, 3, false, false);
  
  detector->detect(srcImage1, keyPoints, Mat());
    //绘制关键点
  drawKeypoints(srcImage1, keyPoints, resultImg, Scalar::all(-1), DrawMatchesFlags::DEFAULT);
  imshow("KetPoint image", resultImg);
  //SIFT特征检测
  Ptr<SIFT>detector1 = SIFT::create();
  detector1->detect(srcImage2, keyPoints1, Mat());
  //绘制关键点
  drawKeypoints(srcImage2, keyPoints1, resultImage1, Scalar::all(-1), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
  imshow("KetPoint image1" ,resultImage1);
  waitKey(0);
  system("pause");
  return 0;
}

(1)在特征检测器定义完成后,通过detect可以提取检测出的特征点,存储在keypoints中。

(2)关于drawkeypoints算子是用来绘制显示检测的特征点的。其中显示方式有两种常用的

第一种是默认的DEFAULT,小圆圈圈出关键点。第二种是DRAW_RICH_KEYPOINTS,用带有半径和方向的圆圈出关键点。

显示结果:

相关文章
|
28天前
|
算法 C语言 C++
C++语言学习指南:从新手到高手,一文带你领略系统编程的巅峰技艺!
【8月更文挑战第22天】C++由Bjarne Stroustrup于1985年创立,凭借卓越性能与灵活性,在系统编程、游戏开发等领域占据重要地位。它继承了C语言的高效性,并引入面向对象编程,使代码更模块化易管理。C++支持基本语法如变量声明与控制结构;通过`iostream`库实现输入输出;利用类与对象实现面向对象编程;提供模板增强代码复用性;具备异常处理机制确保程序健壮性;C++11引入现代化特性简化编程;标准模板库(STL)支持高效编程;多线程支持利用多核优势。虽然学习曲线陡峭,但掌握后可开启高性能编程大门。随着新标准如C++20的发展,C++持续演进,提供更多开发可能性。
45 0
|
4天前
|
存储 计算机视觉 C++
在C++中实现Armadillo库与OpenCV库之间的数据格式转换
在C++中实现Armadillo库与OpenCV库之间的数据格式转换是一项常见且实用的技能。上述步骤提供了一种标准的方法来进行这种转换,可以帮助开发者在两个库之间高效地转移和处理数据。虽然转换过程相对直接,但开发者应留意数据类型匹配和性能优化等关键细节。
23 11
|
5天前
|
存储 计算机视觉 C++
在C++中实现Armadillo库与OpenCV库之间的数据格式转换
在C++中实现Armadillo库与OpenCV库之间的数据格式转换是一项常见且实用的技能。上述步骤提供了一种标准的方法来进行这种转换,可以帮助开发者在两个库之间高效地转移和处理数据。虽然转换过程相对直接,但开发者应留意数据类型匹配和性能优化等关键细节。
14 3
|
2月前
|
机器学习/深度学习 传感器 算法
OpenCV4工业缺陷检测的六种方法
OpenCV4工业缺陷检测的六种方法
|
2月前
|
存储 安全 编译器
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
|
2月前
|
人工智能 分布式计算 Java
【C++入门 一 】学习C++背景、开启C++奇妙之旅
【C++入门 一 】学习C++背景、开启C++奇妙之旅
|
2月前
|
存储 自然语言处理 编译器
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
|
2月前
|
小程序 C++
【C++入门 二 】学习使用C++命名空间及其展开
【C++入门 二 】学习使用C++命名空间及其展开
|
11天前
|
算法 计算机视觉
opencv图像形态学
图像形态学是一种基于数学形态学的图像处理技术,它主要用于分析和修改图像的形状和结构。
27 4
|
21天前
|
算法 计算机视觉 Python
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
该文章详细介绍了使用Python和OpenCV进行相机标定以获取畸变参数,并提供了修正图像畸变的全部代码,包括生成棋盘图、拍摄标定图像、标定过程和畸变矫正等步骤。
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)