对于特征检测和描述子的运行原理本文先不做具体介绍,在后续的更新中会依次详细解释。本文主要介绍常用三种特征检测算法的参数信息和简单应用。
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,用带有半径和方向的圆圈出关键点。
显示结果: