opencv中提取图像特征点的方式比较多,有ORB、FastFeatureDetector、BRISK、MSER、MSDDetector、KAZE、AKAZE、AgastFeatureDetector、GFTTDetector、SURF、SIFT等具体可以参考
https://www.p-chao.com/2017-06-14/opencv%E7%89%B9%E5%BE%81%E7%82%B9%E6%8F%90%E5%8F%96%E7%AE%97%E6%B3%95%E5%AF%B9%E6%AF%94/#Dense_SIFT
这里针对每个方法提取的特征点进行对比(包括点数、执行时间和可视化效果)
以下代码中Mattool.hpp的内容为 https://hpg123.blog.csdn.net/article/details/126427923 博文中代码。
关于上述特征点提取方法中,可用于计算特征向量的方法有以下6中
freak->compute(src1, keyPoint1, descriptors_1);
brief->compute(src1, keyPoint1, descriptors_1);
surf->compute(src1, keyPoint1, descriptors_1);
sift->compute(src1, keyPoint1, descriptors_1);
orb->compute(src1, keyPoint1, descriptors_1);
brisk->compute(src1, keyPoint1, descriptors_1);
#include"opencv2/core.hpp"
#include"opencv2/core/utility.hpp"
#include"opencv2/highgui.hpp"
#include"opencv2/features2d.hpp"
#include"opencv2/xfeatures2d.hpp"
#include"opencv2/imgproc.hpp"
#include"opencv2/flann.hpp"
#include "Mattool.hpp"
using namespace cv;
using namespace std;
template <class T>
std::string convertToString(T& value)
{
std::ostringstream oss;
oss << value;
std::string str(oss.str());
return str;
}
void showKeyPoint(string tilte,Mat src, vector<KeyPoint> &keyPoint1) {
Mat result1;
int kpSize = int(keyPoint1.size());
string kpSizeStr = convertToString(kpSize);
drawKeypoints(src, keyPoint1, result1, Scalar(0, 0, 255), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);//画出特征点
imshow(tilte+" "+ kpSizeStr, result1);
keyPoint1.clear();
}
std::chrono::steady_clock::time_point before, now;
//计算特征检测时间,绘制特征点并添加到vector中
void dear_kp(string ftype,Mat src1,vector<KeyPoint> keyPoint1, vector<Mat> &vms) {
now = std::chrono::steady_clock::now();
double duration_millsecond = std::chrono::duration<double, std::milli>(now- before).count();
std::cout << ftype <<"\t 提取特征数:\t" << keyPoint1.size() << "\t 执行时间:\t" << duration_millsecond << "毫秒" << std::endl;
Mat dkp;
drawKeypoints(src1, keyPoint1, dkp, Scalar(0, 0, 255), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);//画出特征点
vms.push_back(dkp);
keyPoint1.clear();
before = std::chrono::steady_clock::now();
}
int main(int argc, char** argv) {
vector<Mat> vms;
Mat src1,dkp;
src1 = imread("d\\6.jpg", 1);
resize(src1, src1, {
256,256 });
vms.push_back(src1);
before = std::chrono::steady_clock::now();
vector<KeyPoint> keyPoint1;
//特征点检测算子
Ptr<Feature2D> orb = ORB::create();
orb->detect(src1, keyPoint1);//compute
dear_kp("orb", src1, keyPoint1, vms);
Ptr<Feature2D> fast = FastFeatureDetector::create(600);
fast->detect(src1, keyPoint1);
dear_kp("fast", src1, keyPoint1, vms);
Ptr<Feature2D> brisk = BRISK::create(100);
brisk->detect(src1, keyPoint1);//compute
dear_kp("brisk", src1, keyPoint1, vms);
Ptr<Feature2D> mser = MSER::create();
mser->detect(src1, keyPoint1);
dear_kp("mser", src1, keyPoint1, vms);
Ptr<Feature2D> msd = xfeatures2d::MSDDetector::create();
msd->detect(src1, keyPoint1);
dear_kp("msd", src1, keyPoint1, vms);
Ptr<Feature2D> kaze = KAZE::create();//900ms
kaze->detect(src1, keyPoint1);
dear_kp("kaze", src1, keyPoint1, vms);
Ptr<Feature2D> akaze = AKAZE::create();//400ms
akaze->detect(src1, keyPoint1);
dear_kp("akaze", src1, keyPoint1, vms);
Ptr<Feature2D> agast = AgastFeatureDetector::create();//~0ms
agast->detect(src1, keyPoint1);
dear_kp("agast", src1, keyPoint1, vms);
Ptr<Feature2D> gftt = GFTTDetector::create();//200ms
gftt->detect(src1, keyPoint1);
dear_kp("gftt", src1, keyPoint1, vms);
Ptr<Feature2D>surf = xfeatures2d::SURF::create(800);
surf->detect(src1, keyPoint1);
dear_kp("surf", src1, keyPoint1, vms);
Ptr<Feature2D>sift = SIFT::create();
sift->detect(src1, keyPoint1);
dear_kp("sift", src1, keyPoint1, vms);
imshows("key point", vms,4);
//计算描述算子,可以试一下其他的描述算子、orb
surf->detect(src1, keyPoint1);
Ptr<Feature2D> freak = xfeatures2d::FREAK::create();
Ptr<Feature2D> brief = xfeatures2d::BriefDescriptorExtractor::create();
Mat descriptors_1;
freak->compute(src1, keyPoint1, descriptors_1);
brief->compute(src1, keyPoint1, descriptors_1);
surf->compute(src1, keyPoint1, descriptors_1);
sift->compute(src1, keyPoint1, descriptors_1);
orb->compute(src1, keyPoint1, descriptors_1);
brisk->compute(src1, keyPoint1, descriptors_1);
waitKey();
return 0;
}
代码执行效果如下所示
针对不同特征点的输出信息如下所示
orb 提取特征数: 500 执行时间: 155.222毫秒
fast 提取特征数: 4789 执行时间: 0.9115毫秒
brisk 提取特征数: 6335 执行时间: 74.3206毫秒
mser 提取特征数: 222 执行时间: 92.924毫秒
msd 提取特征数: 1147 执行时间: 97.3641毫秒
kaze 提取特征数: 1465 执行时间: 151.281毫秒
akaze 提取特征数: 878 执行时间: 27.2064毫秒
agast 提取特征数: 4746 执行时间: 4.1234毫秒
gftt 提取特征数: 1000 执行时间: 7.2168毫秒
surf 提取特征数: 3277 执行时间: 14.6069毫秒
sift 提取特征数: 1830 执行时间: 37.5664毫秒