第一节 特征检测与描述
OpenCV提供了丰富的特征检测算法,比如SIFT(Scale Invariant Feature Transform)、AffineFeature、AgastFeatureDetector、AKAZE、BRISK、FastFeatureDetector、GFTTDetector、KAZE、MSER、ORB、SimpleBlobDetector等
1、SIFT
尺度不变特征变换算法提取图像特征
SIFT类继承了cv::Feature2D类,通过create静态方法创建。
static Ptr cv::SIFT::create(int nfeatures = 0,int nOctaveLayers = 3,double contrastThreshold = 0.04,double edgeThreshold = 10,double sigma = 1.6)
参数如下:
参数名称 | 参数描述 |
---|---|
nfeatures | 保留的最佳特征的数量;特征按其得分排名 |
nOctaveLayers | 每个八度中的层数。 3是D.Lowe谁中使用的值。 八度的数量是根据图像分辨率自动计算的。 |
contrastThreshold | 对比度阈值,用于过滤半均匀(低对比度)区域中的弱点。 阈值越大,检测器产生的特征越少。 |
edgeThreshold | 用于过滤边缘特征的阈值。 请注意,其含义与contrastThreshold不同,即edgeThreshold越大,滤除的特征越少(保留的特征越多)。 |
sigma | 高斯的sigma应用于八度为#0的输入图像。 如果使用带软镜头的弱相机拍摄图像,则可能需要减少数量。 |
注意:应用过滤时,对比度阈值将被nOctaveLayers除。 当nOctaveLayers设置为默认值并且如果要使用D.Lowe论文中使用的值0.03时,请将此参数设置为0.09。
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
int main()
{
// 读取图像
cv::Mat src = cv::imread("images/f1.jpg");
if(src.empty()){
cerr << "cannot read image.\n";
return EXIT_FAILURE;
}
// 转换成灰度图像
cv::Mat gray;
cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
// 创建SIFT特征提取器
cv::Ptr<cv::SIFT> feature = cv::SIFT::create(1024,3,0.04,120,1.5);
// 检测特征点
vector<cv::KeyPoint> keypoints;
cv::Mat descriptor;
feature->detectAndCompute(gray,cv::Mat(),keypoints,descriptor);
// 绘制特征点
cv::Mat output;
cv::drawKeypoints(src,keypoints,output,cv::Scalar(0,0,255));
cv::imshow("src",src);
cv::imshow("output",output);
cv::waitKey();
return 0;
}
2、 AffineFeature
用于实现使检测器和提取器具有仿射不变的包装器的类,在[Guoshen Yu and Jean-Michel Morel. Asift: An algorithm for fully affine invariant comparison. Image Processing On Line, 1:11–38, 2011.]中描述为ASIFT。
AffineFeature类继承了cv::Feature2D类,通过create静态方法创建。
static Ptr cv::AffineFeature::create(const Ptr< Feature2D > & backend,int maxTilt = 5,int minTilt = 0,float tiltStep = 1.4142135623730951f,float rotateStepBase = 72)
参数如下:
参数 | 参数描述 |
---|---|
backend | 用作后端的检测器/提取器。 |
maxTilt | 倾斜系数的最高功率指标。 在纸张中使用5作为倾斜采样范围n。 |
minTilt | 最低的倾斜系数功率指数。 本文使用0。 |
tiltStep | 倾斜采样步骤δt。 |
rotateStepBase | 旋转采样阶跃系数b |
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
int main()
{
// 读取图像
cv::Mat src = cv::imread("images/f1.jpg");
if(src.empty()){
cerr << "cannot read image.\n";
return EXIT_FAILURE;
}
// 转换成灰度图像
cv::Mat gray;
cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
// 使用SIFT特征检测算法创建
cv::Ptr<cv::AffineFeature> feature = cv::AffineFeature::create(cv::SIFT::create(128));
// 检测特征点
vector<cv::KeyPoint> keypoints;
cv::Mat descriptor;
feature->detectAndCompute(gray,cv::Mat(),keypoints,descriptor);
// 绘制特征点
cv::Mat output;
cv::drawKeypoints(src,keypoints,output,cv::Scalar(0,0,255));
cv::imshow("src",src);
cv::imshow("output",output);
cv::waitKey();
return 0;
}
3、AgastFeatureDetector
使用AGAST方法进行特征检测的包装类。
AgastFeatureDetector类继承了cv::Feature2D类,通过create静态方法创建。
static Ptr cv::AgastFeatureDetector::create(int threshold = 10,bool nonmaxSuppression = true,AgastFeatureDetector::DetectorType type = AgastFeatureDetector::OAST_9_16)
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
int main()
{
// 读取图像
cv::Mat src = cv::imread("images/f1.jpg");
if(src.empty()){
cerr << "cannot read image.\n";
return EXIT_FAILURE;
}
// 转换成灰度图像
cv::Mat gray;
cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
// 创建AgastFeatureDetector特征提取器
cv::Ptr<cv::AgastFeatureDetector> feature = cv::AgastFeatureDetector::create();
// 检测特征点
vector<cv::KeyPoint> keypoints;
cv::Mat descriptor;
feature->detect(gray,keypoints);
// 绘制特征点
cv::Mat output;
cv::drawKeypoints(src,keypoints,output,cv::Scalar(0,0,255));
cv::imshow("src",src);
cv::imshow("output",output);
cv::waitKey();
return 0;
}
4、AKAZE
实现AKAZE关键点检测器和描述符提取器的类,在[Pablo F Alcantarilla, Jesús Nuevo, and Adrien Bartoli. Fast explicit diffusion for accelerated features in nonlinear scale spaces. Trans. Pattern Anal. Machine Intell, 34(7):1281–1298, 2011.]中进行了描述。
AKAZE类继承了cv::Feature2D类,通过create静态方法创建。
static Ptr cv::AKAZE::create (AKAZE::DescriptorType descriptor_type = AKAZE::DESCRIPTOR_MLDB,int descriptor_size = 0,int descriptor_channels = 3,float threshold = 0.001f,int nOctaves = 4,int nOctaveLayers = 4,KAZE::DiffusivityType diffusivity = KAZE::DIFF_PM_G2)
参数名称 | 参数描述 |
---|---|
descriptor_type | 提取的描述符的类型:DESCRIPTOR_KAZE,DESCRIPTOR_KAZE_UPRIGHT,DESCRIPTOR_MLDB或DESCRIPTOR_MLDB_UPRIGHT。 |
descriptor_size | 描述符的大小(以位为单位)。 0->全尺寸 |
descriptor_channels | 描述符中的通道数(1、2、3) |
threshold | 检测器响应阈值以接受点 |
nOctaves | 图像的最大八度演变 |
nOctaveLayers | 每个比例级别的默认子级别数 |
diffusivity | 扩散类型。 DIFF_PM_G1,DIFF_PM_G2,DIFF_WEICKERT或DIFF_CHARBONNIER |
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
int main()
{
// 读取图像
cv::Mat src = cv::imread("images/f1.jpg");
if(src.empty()){
cerr << "cannot read image.\n";
return EXIT_FAILURE;
}
// 转换成灰度图像
cv::Mat gray;
cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
// 创建AKAZE特征提取器
cv::Ptr<cv::AKAZE> feature = cv::AKAZE::create();
// 检测特征点
vector<cv::KeyPoint> keypoints;
cv::Mat descriptor;
feature->detect(gray,keypoints);
// 绘制特征点
cv::Mat output;
cv::drawKeypoints(src,keypoints,output,cv::Scalar(0,0,255));
cv::imshow("src",src);
cv::imshow("output",output);
cv::waitKey();
return 0;
}
5、BRISK
实现BRISK关键点检测器和描述符提取器的类,在[Stefan Leutenegger, Margarita Chli, and Roland Yves Siegwart. Brisk: Binary robust invariant scalable keypoints. In Computer Vision (ICCV), 2011 IEEE International Conference on, pages 2548–2555. IEEE, 2011.]中进行了描述。
BRISK类继承了cv::Feature2D类,通过create静态方法创建。
static Ptr cv::BRISK::create(int thresh = 30,int octaves=3,float patternScale=1.0f)
参数名称 | 参数描述 |
---|---|
thresh | AGAST检测阈值得分。 |
octaves | 检测八度。 使用0进行单刻度。 |
patternScale | 将此比例应用于用于采样关键点邻域的模式。 |
其他函数重载形式:
自定义模式的BRISK构造函数。
static Ptr cv::BRISK::create (const std::vector< float > & radiusList,const std::vector< int > & numberList,float dMax = 5.85f,float dMin = 8.2f,const std::vector< int > & indexChange=std::vector< int >())
参数名称 | 参数描述 |
---|---|
numberList | 定义采样圆上的采样点数。 必须与radiusList大小相同。 |
radiusList | 定义在关键点周围采样的半径(以像素为单位)(对于关键点比例1)。 |
dMax | 用于描述符形成的短配对的阈值(对于关键点比例1,以像素为单位)。 |
dMin | 用于方向确定的长配对的阈值(对于关键点比例1,以像素为单位)。 |
indexChange | 位的索引重新映射。 |
static Ptr cv::BRISK::create (int thresh,int octaves,const std::vector< float > & radiusList,const std::vector< int > & numberList,float dMax = 5.85f,float dMin = 8.2f,const std::vector< int > & indexChange = std::vector< int >())
参数名称 | 参数描述 |
---|---|
thresh | AGAST检测阈值得分。 |
octaves | 检测八度。 使用0进行单刻度。 |
radiusList | 定义在关键点周围采样的半径(以像素为单位)(对于关键点比例1)。 |
numberList | 定义采样圆上的采样点数。 必须与radiusList大小相同。 |
dMax | 用于描述符形成的短配对的阈值(对于关键点比例1,以像素为单位)。 |
dMin | 用于方向确定的长配对的阈值(对于关键点比例1,以像素为单位)。 |
indexChange | 位的索引重新映射。 |
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
int main()
{
// 读取图像
cv::Mat src = cv::imread("images/f1.jpg");
if(src.empty()){
cerr << "cannot read image.\n";
return EXIT_FAILURE;
}
// 转换成灰度图像
cv::Mat gray;
cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
// 创建BRISK特征提取器
cv::Ptr<cv::BRISK> feature = cv::BRISK::create();
// 检测特征点
vector<cv::KeyPoint> keypoints;
cv::Mat descriptor;
feature->detect(gray,keypoints);
// 绘制特征点
cv::Mat output;
cv::drawKeypoints(src,keypoints,output,cv::Scalar(0,0,255));
cv::imshow("src",src);
cv::imshow("output",output);
cv::waitKey();
return 0;
}
6、FastFeatureDetector
使用FAST方法进行特征检测的包装类。FastFeatureDetector类继承了cv::Feature2D类,通过create静态方法创建。
static Ptr cv::FastFeatureDetector::create(int threshold = 10,bool nonmaxSuppression = true,FastFeatureDetector::DetectorType type = FastFeatureDetector::TYPE_9_16)
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
int main()
{
// 读取图像
cv::Mat src = cv::imread("images/f1.jpg");
if(src.empty()){
cerr << "cannot read image.\n";
return EXIT_FAILURE;
}
// 转换成灰度图像
cv::Mat gray;
cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
// 创建FastFeatureDetector特征提取器
cv::Ptr<cv::FastFeatureDetector> feature = cv::FastFeatureDetector::create();
// 检测特征点
vector<cv::KeyPoint> keypoints;
cv::Mat descriptor;
feature->detect(gray,keypoints);
// 绘制特征点
cv::Mat output;
cv::drawKeypoints(src,keypoints,output,cv::Scalar(0,0,255));
cv::imshow("src",src);
cv::imshow("output",output);
cv::waitKey();
return 0;
}
7、GFTTDetector
使用goodFeaturesToTrack函数包装特征的包装类。GFTTDetector类继承了cv::Feature2D类,通过create静态方法创建。
static Ptr cv::GFTTDetector::create(int maxCorners=1000,double qualityLevel = 0.01,double minDistance = 1,int blockSize = 3,bool useHarrisDetector = false,double k = 0.04)
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
int main()
{
// 读取图像
cv::Mat src = cv::imread("images/f1.jpg");
if(src.empty()){
cerr << "cannot read image.\n";
return EXIT_FAILURE;
}
// 转换成灰度图像
cv::Mat gray;
cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
// 创建FastFeatureDetector特征提取器
cv::Ptr<cv::GFTTDetector> feature = cv::GFTTDetector::create();
// 检测特征点
vector<cv::KeyPoint> keypoints;
cv::Mat descriptor;
feature->detect(gray,keypoints);
// 绘制特征点
cv::Mat output;
cv::drawKeypoints(src,keypoints,output,cv::Scalar(0,0,255));
cv::imshow("src",src);
cv::imshow("output",output);
cv::waitKey();
return 0;
}
8、KAZE
实现KAZE关键点检测器和描述符提取器的类,在[Pablo Fernández Alcantarilla, Adrien Bartoli, and Andrew J Davison. Kaze features. In Computer Vision–ECCV 2012, pages 214–227. Springer, 2012.]中进行了描述。
AKAZE描述符只能与KAZE或AKAZE关键点一起使用。AKAZE类继承了cv::Feature2D类,通过create静态方法创建。参数如下:
static Ptr cv::KAZE::create(bool extended = false,bool upright = false,float threshold = 0.001f,int nOctaves = 4,int nOctaveLayers = 4,KAZE::DiffusivityType diffusivity = KAZE::DIFF_PM_G2)
参数 | 参数名称 |
---|---|
extended | 设置为启用扩展(128字节)描述符的提取。 |
upright | 设置为启用直立描述符(非旋转不变)。 |
threshold | 检测器响应阈值以接受点 |
nOctaves | 图像的最大八度演变 |
nOctaveLayers | 每个比例级别的默认子级别数 |
diffusivity | 扩散类型。 DIFF_PM_G1,DIFF_PM_G2,DIFF_WEICKERT或DIFF_CHARBONNIER |
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
int main()
{
// 读取图像
cv::Mat src = cv::imread("images/f1.jpg");
if(src.empty()){
cerr << "cannot read image.\n";
return EXIT_FAILURE;
}
// 转换成灰度图像
cv::Mat gray;
cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
// 创建FastFeatureDetector特征提取器
cv::Ptr<cv::KAZE> feature = cv::KAZE::create();
// 检测特征点
vector<cv::KeyPoint> keypoints;
cv::Mat descriptor;
feature->detect(gray,keypoints);
// 绘制特征点
cv::Mat output;
cv::drawKeypoints(src,keypoints,output,cv::Scalar(0,0,255));
cv::imshow("src",src);
cv::imshow("output",output);
cv::waitKey();
return 0;
}
9、MSER
最大限度地稳定的极值区域提取。该类封装了MSER提取算法的所有参数。MSER类继承了cv::Feature2D类,通过create静态方法创建。参数如下:
static Ptr cv::MSER::create(int _delta = 5,int _min_area = 60,int _max_area = 14400,double _max_variation = 0.25,double _min_diversity = .2,int _max_evolution = 200,double _area_threshold = 1.01,double _min_margin = 0.003,int _edge_blur_size = 5)
参数名称 | 参数描述 |
---|---|
_delta | 它比较(sizei-sizei-delta)/ sizei-delta |
_min_area | 修剪小于minArea的区域 |
_max_area | 修剪大于maxArea的区域 |
_max_variation | 修剪该区域的大小与其子面积相似 |
_min_diversity | 对于彩色图像,回溯以切断多样性小于min_diversity的mser |
_max_evolution | 对于彩色图像,演变步骤 |
_area_threshold | 对于彩色图像,导致重新初始化的面积阈值 |
_min_margin | 对于彩色图像,请忽略过小的边距 |
_edge_blur_size | 对于彩色图像,边缘模糊的光圈大小 |
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
int main()
{
// 读取图像
cv::Mat src = cv::imread("images/f1.jpg");
if(src.empty()){
cerr << "cannot read image.\n";
return EXIT_FAILURE;
}
// 转换成灰度图像
cv::Mat gray;
cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
// 创建FastFeatureDetector特征提取器
cv::Ptr<cv::MSER> feature = cv::MSER::create();
// 检测特征点
vector<cv::KeyPoint> keypoints;
cv::Mat descriptor;
feature->detect(gray,keypoints);
// 绘制特征点
cv::Mat output;
cv::drawKeypoints(src,keypoints,output,cv::Scalar(0,0,255));
cv::imshow("src",src);
cv::imshow("output",output);
cv::waitKey();
return 0;
}
10、ORB
实现ORB(面向Brief)关键点检测器和描述符提取器的类。
在[Ethan Rublee, Vincent Rabaud, Kurt Konolige, and Gary Bradski. Orb: an efficient alternative to sift or surf. In Computer Vision (ICCV), 2011 IEEE International Conference on, pages 2564–2571. IEEE, 2011.]中描述。 该算法在金字塔中使用FAST来检测稳定的关键点,使用FAST或Harris响应选择最强的特征,使用一阶矩找到它们的方向,并使用Brief来计算描述符(其中随机点对(或k元组)的坐标为 根据测量的方向旋转)。
ORB类继承了cv::Feature2D类,通过create静态方法创建。参数如下:
static Ptr cv::ORB::create(int nfeatures=500,float scaleFactor = 1.2f,int nlevels = 8,int edgeThreshold = 31,int firstLevel = 0,int WTA_K = 2,ORB::ScoreType scoreType = ORB::HARRIS_SCORE,int patchSize = 31,int fastThreshold = 20)
参数 | 参数描述 |
---|---|
nfeatures | 保留的最大特征数量。 |
scaleFactor | 金字塔抽取率大于1。scaleFactor == 2表示经典金字塔,其中每个下一个级别的像素比上一个少4倍,但是如此大的比例因子将大大降低特征匹配分数。 另一方面,太接近1的比例因子意味着要覆盖一定的比例范围,您将需要更多的金字塔等级,因此速度会受到影响。 |
nlevels | 金字塔等级的数量。 最小级别的线性大小等于input_image_linear_size / pow(scaleFactor,nlevels-firstLevel)。 |
edgeThreshold | 未检测到特征的边框的大小。 它应该与patchSize参数大致匹配。 |
firstLevel | 要放置源图像的金字塔等级。 先前的层填充有放大的源图像。 |
WTA_K | 产生定向的Brief描述符的每个元素的点数。 默认值2表示“ BRIEF”,我们采用一个随机点对并比较它们的亮度,因此得到0/1响应。 其他可能的值是3和4。例如,3表示我们取3个随机点(当然,这些点坐标是随机的,但它们是从预定义的种子生成的,因此,BRIEF描述符的每个元素都是从确定的 像素矩形),找到最大亮度的点和获胜者的输出指数(0、1或2)。 这样的输出将占用2位,因此将需要Hamming距离的特殊变体,表示为NORM_HAMMING2(每个bin 2位)。 当WTA_K = 4时,我们取4个随机点来计算每个bin(也将占用2位,可能的值为0、1、2或3)。 |
scoreType | 默认的HARRIS_SCORE表示将Harris算法用于对要素进行排名(分数被写入KeyPoint :: score并用于保留最佳nfeatures要素); FAST_SCORE是该参数的替代值,它产生的稳定关键点会稍少一些,但计算速度稍快一些。 |
patchSize | 定向的Brief描述符使用的补丁大小。 当然,在较小的金字塔层上,特征覆盖的感知图像区域将更大。 |
fastThreshold | 快速阈值 |
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
int main()
{
// 读取图像
cv::Mat src = cv::imread("images/f1.jpg");
if(src.empty()){
cerr << "cannot read image.\n";
return EXIT_FAILURE;
}
// 转换成灰度图像
cv::Mat gray;
cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
// 创建FastFeatureDetector特征提取器
cv::Ptr<cv::ORB> feature = cv::ORB::create();
// 检测特征点
vector<cv::KeyPoint> keypoints;
cv::Mat descriptor;
feature->detect(gray,keypoints);
// 绘制特征点
cv::Mat output;
cv::drawKeypoints(src,keypoints,output,cv::Scalar(0,0,255));
cv::imshow("src",src);
cv::imshow("output",output);
cv::waitKey();
return 0;
}
11、SimpleBlobDetector
用于从图像中提取斑点的类。 SimpleBlobDetector类继承了cv::Feature2D类,通过create静态方法创建。参数如下:
static Ptr cv::SimpleBlobDetector::create(const SimpleBlobDetector::Params & parameters = SimpleBlobDetector::Params())
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
int main()
{
// 读取图像
cv::Mat src = cv::imread("images/f1.jpg");
if(src.empty()){
cerr << "cannot read image.\n";
return EXIT_FAILURE;
}
// 转换成灰度图像
cv::Mat gray;
cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
// 创建FastFeatureDetector特征提取器
cv::Ptr<cv::SimpleBlobDetector> feature = cv::SimpleBlobDetector::create();
// 检测特征点
vector<cv::KeyPoint> keypoints;
cv::Mat descriptor;
feature->detect(gray,keypoints);
// 绘制特征点
cv::Mat output;
cv::drawKeypoints(src,keypoints,output,cv::Scalar(0,0,255));
cv::imshow("src",src);
cv::imshow("output",output);
cv::waitKey();
return 0;
}