前言
图像拼接|——OpenCV3.4 stitching模块分析(一)特征点检测
参考opencv_赵春江的专栏_zhaocj-CSDN博客
特征点检测
OpenCV3.4中实现了surf、orb、sift等特征检测算法,默认的是surf。
特征检测算法的实现主要包含在 “opencv2/stitching/detail/matchers.hpp” 中。
源码
首先定义了一个ImageFeatures结构体用于存放特征信息,包括图片序号、尺寸、特征点信息及描述子矩阵:
struct CV_EXPORTS ImageFeatures
{
int img_idx;
Size img_size;
std::vector<KeyPoint> keypoints;
UMat descriptors;
};
定义FeaturesFinder基类,其中的成员函数find()是用来寻找特征信息:
class CV_EXPORTS FeaturesFinder
{
public:
virtual ~FeaturesFinder() {}
//重载
void operator ()(InputArray image, ImageFeatures &features);
//寻找给定图像特征
void operator ()(InputArray image, ImageFeatures &features, const std::vector<cv::Rect> &rois);
//并行寻找给定图像特征
void operator ()(InputArrayOfArrays images, std::vector<ImageFeatures> &features,
const std::vector<std::vector<cv::Rect> > &rois);
//重载
void operator ()(InputArrayOfArrays images, std::vector<ImageFeatures> &features);
//释放内存
virtual void collectGarbage() {}
protected:
//纯虚函数,根据用户所选取的特征类别,调用不同子类的find函数
virtual void find(InputArray image, ImageFeatures &features) = 0;
//判断是否可以并行
bool isThreadSafe() const;
};
FeaturesFinder基类派生出SurfFeaturesFinder、SiftFeaturesFinder、OrbFeaturesFinder等派生类。
SurfFeaturesFinder派生类定义:
class CV_EXPORTS SurfFeaturesFinder : public FeaturesFinder
{
public:
SurfFeaturesFinder(double hess_thresh = 300., int num_octaves = 3, int num_layers = 4,
int num_octaves_descr = /*4*/3, int num_layers_descr = /*2*/4);
private:
void find(InputArray image, ImageFeatures &features) CV_OVERRIDE;
Ptr<FeatureDetector> detector_;
Ptr<DescriptorExtractor> extractor_;
Ptr<Feature2D> surf;
};
SiftFeaturesFinder派生类定义:
class CV_EXPORTS SiftFeaturesFinder : public FeaturesFinder
{
public:
SiftFeaturesFinder();
private:
void find(InputArray image, ImageFeatures &features) CV_OVERRIDE;
Ptr<Feature2D> sift;
};
OrbFeaturesFinder派生类定义:
class CV_EXPORTS OrbFeaturesFinder : public FeaturesFinder
{
public:
OrbFeaturesFinder(Size _grid_size = Size(3,1), int nfeatures=1500, float scaleFactor=1.3f, int nlevels=5);
private:
void find(InputArray image, ImageFeatures &features) CV_OVERRIDE;
Ptr<ORB> orb;
Size grid_size;
};
关于各个特征检测算法的具体实现,就不具体展开了,一般只要知道怎样调用高级API即可。
应用
#include <iostream>
#include "opencv2/highgui.hpp"
#include "opencv2/stitching/detail/matchers.hpp"
using namespace std;
using namespace cv;
using namespace cv::detail;
int main()
{
Mat img = imread("4.jpg");
Ptr<FeaturesFinder> finder1, finder2, finder3;
finder1 = makePtr<SurfFeaturesFinder>();
finder2 = makePtr<OrbFeaturesFinder>();
finder3 = makePtr<SiftFeaturesFinder>();
ImageFeatures features1, features2, features3;
(*finder1)(img, features1);
(*finder2)(img, features2);
(*finder3)(img, features3);
Mat output_img1, output_img2, output_img3;
//调用drawKeypoints函数绘制特征
drawKeypoints(img, features1.keypoints, output_img1, Scalar(255, 0, 0));
drawKeypoints(img, features2.keypoints, output_img2, Scalar(255, 0, 0));
drawKeypoints(img, features3.keypoints, output_img3, Scalar(255, 0, 0));
cout << "Number of surf keypoints: " << features1.keypoints.size() << endl;
cout << "Number of orb keypoints: " << features2.keypoints.size() << endl;
cout << "Number of sift keypoints: " << features3.keypoints.size() << endl;
namedWindow("surf");
imshow("surf", output_img1);
namedWindow("orb");
imshow("orb", output_img2);
namedWindow("sift");
imshow("sift", output_img3);
waitKey(0);
return 0;
}
运行结果:
|
|
|
Number of surf keypoints: 1403
Number of orb keypoints: 1346
Number of sift keypoints: 1287
主观视觉上还是SIFT更稳健一些,不过stitching默认使用的是surf。