我一直在尝试使用功能匹配解决问题,利用C ++中OpenCV库提供的功能匹配算法。
现在有一个例子,ORB给了我比SIFT更好的比赛,让我惊讶的是。我认为ORB是一种尝试提供与SIFT相当的质量,同时需要更少的共同时间。这就是我认为我的SIFT匹配可能出错的原因。但是,使用其他图像效果很好。
我所说的例子是二进制图像。 以下是使用SIFT获得的结果:
以下是使用ORB的结果:
使用SIFT特征检测器和SIFT描述符提取器获得第一个结果。为了匹配,我使用了具有L2规范的强力匹配器。对于第二个,我使用了ORB特征检测器和ORB描述符提取器以及蛮力匹配器,但是使用了汉明距离。
我在两种情况下通过使用RANSAC离群值过滤方法计算单应性来过滤匹配,然后仅保留选定的点对。
我试图摆弄描述符匹配器的参数,但结果没有太大变化。
现在,您认为在这种情况下为什么ORB似乎表现更好有一个合理的解释吗?它可能更适合这种类型的图像吗?或者SIFT结果有问题吗?
编辑:一些代码:
void KeypointMatcher::computeMatches(cv::Mat image1, cv::Mat image2, FeatureDetectorType detectorType, DescriptorExtractorType extractorType, DescriptorMatcherType matcherType) {
cv::Ptr<cv::FeatureDetector> detector;
switch (detectorType) {
case FeatureDetectorType::FAST:
detector = cv::FeatureDetector::create("FAST");
break;
case FeatureDetectorType::STAR:
detector = cv::FeatureDetector::create("STAR");
break;
case FeatureDetectorType::SIFT:
detector = cv::FeatureDetector::create("SIFT");
break;
case FeatureDetectorType::SURF:
detector = cv::FeatureDetector::create("SURF");
break;
case FeatureDetectorType::ORB:
detector = cv::FeatureDetector::create("ORB");
break;
case FeatureDetectorType::BRISK:
detector = cv::FeatureDetector::create("BRISK");
break;
case FeatureDetectorType::MSER:
detector = cv::FeatureDetector::create("MSER");
break;
default:
detector = cv::FeatureDetector::create("SIFT");
break;
}
detector->detect(image1, _keypoints1);
detector->detect(image2, _keypoints2);
cv::Ptr<cv::DescriptorExtractor> extractor;
switch (extractorType) {
case DescriptorExtractorType::SIFT:
extractor = cv::DescriptorExtractor::create("SIFT");
break;
case DescriptorExtractorType::SURF:
extractor = cv::DescriptorExtractor::create("SURF");
break;
case DescriptorExtractorType::BRIEF:
extractor = cv::DescriptorExtractor::create("BRIEF");
break;
case DescriptorExtractorType::BRISK:
extractor = cv::DescriptorExtractor::create("BRISK");
break;
case DescriptorExtractorType::ORB:
extractor = cv::DescriptorExtractor::create("ORB");
break;
case DescriptorExtractorType::FREAK:
extractor = cv::DescriptorExtractor::create("FREAK");
break;
default:
extractor = cv::DescriptorExtractor::create("SIFT");
break;
}
extractor->compute(image1, _keypoints1, _descriptors1);
extractor->compute(image2, _keypoints2, _descriptors2);
if (!_descriptors1.empty() && !_descriptors2.empty()) {
switch (matcherType) {
case DescriptorMatcherType::BRUTE_FORCE:
if (extractorType == DescriptorExtractorType::ORB || extractorType == DescriptorExtractorType::BRISK || extractorType == DescriptorExtractorType::BRIEF) {
_matcher = cv::DescriptorMatcher::create("BruteForce-Hamming");
} else {
_matcher = cv::DescriptorMatcher::create("BruteForce");
}
break;
case DescriptorMatcherType::FLANN:
_matcher = cv::DescriptorMatcher::create("FlannBased");
break;
default:
_matcher = cv::DescriptorMatcher::create("BruteForce");
break;
}
_matcher->knnMatch(_descriptors1, _descriptors2, _matches, 2);
if (_matches.size() > 0) {
_matchesMask = std::vector<bool>(_matches.size(), true);
_matched = true;
} else {
std::cout << "No matching features could be found." << std::endl;
}
} else {
_matched = false;
std::cout << "No descriptors could be extracted." << std::endl;
}
}
void KeypointMatcher::homographyFilterMatches(OutlierFilter method) {
if (!_matched) {
std::cout << "Matching was not yet executed or no matches have been found." << std::endl;
return;
}
std::vector<cv::Point2d> matchingPoints1, matchingPoints2;
matchingPoints1.reserve(_matches.size());
matchingPoints2.reserve(_matches.size());
std::vector<int> indices;
indices.reserve(_matches.size());
for (int i = 0; i < _matchesMask.size(); ++i) {
if (_matchesMask[i] == true) {
matchingPoints1.push_back(_keypoints1[_matches[i][0].queryIdx].pt);
matchingPoints2.push_back(_keypoints2[_matches[i][0].trainIdx].pt);
indices.push_back(i);
}
}
int meth;
if (method == OutlierFilter::RANSAC) meth = cv::RANSAC; else meth = cv::LMEDS;
cv::Mat mask;
cv::findHomography(matchingPoints1, matchingPoints2, meth, 3, mask);
for (int i = 0; i < mask.rows; ++i) {
_matchesMask[indices[i]] = _matchesMask[indices[i]] && (mask.at<uchar>(i, 0) == 1);
}
}
从主要:
cv::Mat image1 = cv::imread("G:/Desktop/thresholded1.png");
cv::Mat image2 = cv::imread("G:/Desktop/thresholded2.png");
hb::KeypointMatcher matcher;
matcher.computeMatches(image1, image2, hb::KeypointMatcher::FeatureDetectorType::SIFT, hb::KeypointMatcher::DescriptorExtractorType::SIFT);
matcher.homographyFilterMatches();
以下是筛选效果良好的另一种情况:
这是相同图像的两倍,但稍微旋转和缩放。