我发现OpenCV的新课程SURF与SurfFeatureDetector
的行为不同。怎么了?
有两张照片的例子:
.................................. img_1
........ .................................................. ........... img_2
.................................. 。
像./a.out ./img_1.png ./img_2.png
// STL
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
// C-Standard
#include <cstdio>
#include <ctime>
#include <cstdlib>
// OpenCV
#include <opencv2/opencv.hpp>
#include <opencv2/legacy/legacy.hpp>
#include <opencv2/nonfree/nonfree.hpp>
void print(const std::string & filename, const std::vector<std::vector<cv::DMatch>> & vec) {
FILE *file = fopen(filename.c_str(), "w");
fprintf(file, "{\n");
for(auto & i : vec)
fprintf(file, " { {%d,%d,%f}, {,%d,%d,%f} },\n",
i[0].queryIdx, i[0].trainIdx, i[0].distance,
i[1].queryIdx, i[1].trainIdx, i[1].distance);
fprintf(file, "}\n");
fclose(file);
}
void test1(const std::string & imgf_1, const std::string & imgf_2) {
cv::Mat img_1;
cv::Mat img_2;
std::vector<cv::KeyPoint> keypoints_1, keypoints_2;
cv::Mat descriptors_1, descriptors_2;
std::vector<std::vector<cv::DMatch>> matches;
img_1 = cv::imread(imgf_1);
img_2 = cv::imread(imgf_2);
int minhessin = 400;
cv::SurfFeatureDetector detector(minhessin);
cv::SurfDescriptorExtractor extractor;
cv::BFMatcher bfMatcher(cv::NORM_L2);
keypoints_1.clear(); keypoints_2.clear();
detector.detect(img_1, keypoints_1);
extractor.compute(img_1, keypoints_1, descriptors_1);
detector.detect(img_2, keypoints_2);
extractor.compute(img_2, keypoints_2, descriptors_2);
matches.clear();
bfMatcher.knnMatch(descriptors_1, descriptors_2, matches, 2);
print("main_bak.log", matches);
}
void test2(const std::string & imgf_1, const std::string & imgf_2) {
cv::Mat img_1;
cv::Mat img_2;
std::vector<cv::KeyPoint> keypoints_1, keypoints_2;
cv::Mat descriptors_1, descriptors_2;
std::vector<std::vector<cv::DMatch>> matches;
img_1 = cv::imread(imgf_1);
img_2 = cv::imread(imgf_2);
const double hessianThreshold = 400;
cv::SURF detector2(hessianThreshold);
cv::BFMatcher bfMatcher(cv::NORM_L2);
keypoints_1.clear(); keypoints_2.clear();
detector2(img_1, cv::Mat(), keypoints_1, descriptors_1);
detector2(img_2, cv::Mat(), keypoints_2, descriptors_2);
matches.clear();
bfMatcher.knnMatch(descriptors_1, descriptors_2, matches, 2);
print("main.log", matches);
}
int main(int argc, char * argv[])
{
if(argc < 3) {
std::cout << "usage: " << argv[0] << " img_1 img_2" << std::endl;
return 1;
}
test1(argv[1], argv[2]);
test2(argv[1], argv[2]);
return 0;
}
此处显示了日志的标题5行:
main_bak.log :
{
{ {0,0,0.000787}, {,0,2,0.126846} },
{ {1,1,0.001695}, {,1,167,0.353709} },
{ {2,2,0.000860}, {,2,0,0.127105} },
{ {3,3,0.002939}, {,3,5,0.333215} },
{ {4,4,0.001360}, {,4,115,0.294008} },
main.log :
{
{ {0,0,0.000900}, {,0,2,0.143810} },
{ {1,1,0.024048}, {,1,107,0.621702} },
{ {2,2,0.003646}, {,2,0,0.144049} },
{ {3,3,0.032238}, {,3,5,0.604136} },
{ {4,4,0.001449}, {,4,87,0.591502} },
答案 0 :(得分:2)
班级cv::SurfFeatureDetector
和cv::SurfDescriptorExtractor
是班级cv::SURF
的别名。结果的差异是由于以下原因:
在函数test1
中,detector
和extractor
个对象正在使用不同的参数进行初始化。 detector
使用minHessian
值 400 ,而提取器使用的是opencv实现定义的默认值。
在函数test2
中,使用cv::SURF
值 400 的hessianThreshold
个对象完成关键点检测和描述符计算。
要在test2
中重现test1
的结果,请使用相同的参数初始化这两个对象:
int minhessin = 400;
cv::SurfFeatureDetector detector(minhessin);
cv::SurfDescriptorExtractor extractor(minHessian);