我一直在尝试使用功能匹配解决问题,利用C中OpenCV库提供的功能匹配算法 .

现在有一个例子,ORB给了我比SIFT更好的比赛,让我惊讶的是 . 我认为ORB试图提供与SIFT相当的质量,同时需要更少的同步时间 . 这就是我认为我的SIFT匹配可能出错的原因 . 但是,与其他图像一起使用效果很好 .

我所说的例子是二进制图像 . 以下是使用SIFT获得的结果:

enter image description here

这是使用ORB的结果:

enter image description here

第一个结果是使用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();

这是另一个筛选效果很好的案例:

enter image description here

这是相同图像的两倍,但稍微旋转和缩放 .