使用ORB描述符和FLANN进行特征匹配的OpenCV

10

我正在使用OpenCV 3.2

我尝试使用FLANN以比暴力匹配更快地匹配特征描述符。

// Ratio to the second neighbor to consider a good match.
#define RATIO    0.75

void matchFeatures(const cv::Mat &query, const cv::Mat &target,
                   std::vector<cv::DMatch> &goodMatches) {
    std::vector<std::vector<cv::DMatch>> matches;
    cv::Ptr<cv::FlannBasedMatcher> matcher = cv::FlannBasedMatcher::create();
    // Find 2 best matches for each descriptor to make later the second neighbor test.
    matcher->knnMatch(query, target, matches, 2);
    // Second neighbor ratio test.
    for (unsigned int i = 0; i < matches.size(); ++i) {
        if (matches[i][0].distance < matches[i][1].distance * RATIO)
            goodMatches.push_back(matches[i][0]);
    }
}

这段代码可以用SURF和SIFT描述符正常工作,但是不能用于ORB。

OpenCV Error: Unsupported format or combination of formats (type=0) in buildIndex

正如此处所说,FLANN需要描述符的类型为CV_32F,因此我们需要进行转换。

if (query.type() != CV_32F) query.convertTo(query, CV_32F);
if (target.type() != CV_32F) target.convertTo(target, CV_32F);

然而,这个所谓的修复方法在convertTo函数中又返回了另一个错误。
OpenCV Error: Assertion failed (!fixedType() || ((Mat*)obj)->type() == mtype) in create

这个断言位于 opencv/modules/core/src/matrix.cpp 文件的第2277行。

发生了什么?


复现问题的代码。

#include <opencv2/opencv.hpp>

int main(int argc, char **argv) {
    // Read both images.
    cv::Mat image1 = cv::imread(argv[1], cv::IMREAD_GRAYSCALE);
    if (image1.empty()) {
        std::cerr << "Couldn't read image in " << argv[1] << std::endl;
        return 1;
    }
    cv::Mat image2 = cv::imread(argv[2], cv::IMREAD_GRAYSCALE);
    if (image2.empty()) {
        std::cerr << "Couldn't read image in " << argv[2] << std::endl;
        return 1;
    }
    // Detect the keyPoints and compute its descriptors using ORB Detector.
    std::vector<cv::KeyPoint> keyPoints1, keyPoints2;
    cv::Mat descriptors1, descriptors2;
    cv::Ptr<cv::ORB> detector = cv::ORB::create();
    detector->detectAndCompute(image1, cv::Mat(), keyPoints1, descriptors1);
    detector->detectAndCompute(image2, cv::Mat(), keyPoints2, descriptors2);
    // Match features.
    std::vector<cv::DMatch> matches;
    matchFeatures(descriptors1, descriptors2, matches);
    // Draw matches.
    cv::Mat image_matches;
    cv::drawMatches(image1, keyPoints1, image2, keyPoints2, matches, image_matches);
    cv::imshow("Matches", image_matches);
}
3个回答

14

您是否调整了FLANN参数?

取自http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_matcher/py_matcher.html

当使用ORB时,您可以传递以下参数。根据文档建议的注释值,在某些情况下无法提供所需结果。其他值效果很好:

index_params = dict(algorithm=FLANN_INDEX_LSH, table_number=6,# 12 key_size=12,# 20 multi_probe_level=1)#2

也许您可以将其转换为C ++ API?

根据评论, C ++ 的方法是:

cv::FlannBasedMatcher matcher = cv::FlannBasedMatcher(cv::makePtr<cv::flann::LshIndexParams>(12, 20, 2));

8
非常有效。该调用是 cv::FlannBasedMatcher matcher = cv::FlannBasedMatcher(cv::makePtr<cv::flann::LshIndexParams>(12, 20, 2)); - Santiago Gil
2
此外,并非所有匹配都可以使用ORB和FLANN进行对应(也许其他描述符也会出现这种情况,但目前还没有)。因此,在第二邻域比率测试中,我添加了一个安全条件 if (matches[i].size() >= 2) - Santiago Gil
4
值得一提的是,FLANN_INDEX_LSH = 6 - scrutari
1
还有一个关于multi_probe_level的注释,它是“在多探测中使用的级别数(标准LSH为0)”,因此最好使用multi_probe_level=0 - scrutari

12

二进制字符串描述符:ORB,BRIEF,BRISK,FREAK,AKAZE等。

浮点数描述符:SIFT,SURF,GLOH等。


使用汉明距离进行二进制描述符的特征匹配,而使用欧几里得距离进行浮点数描述符的特征匹配,可以有效提高匹配效率。

在OpenCV中,通过使用FLANN + LSH索引暴力匹配+汉明距离来比较二进制描述符。

http://answers.opencv.org/question/59996/flann-error-in-opencv-3/

默认情况下,FlannBasedMatcher作为KDTreeIndex使用L2范数。这就是为什么它能够很好地处理SIFT/SURF描述符,并且对ORB描述符抛出异常的原因。

二进制特征和局部敏感哈希(LSH)

二进制和浮点数描述符的性能比较


谢谢!我一直在寻找答案,终于找到了这篇文章。OpenCV的错误信息并不是很清晰。 - Herbz
请问您能否更新最后一个链接(Performance comparison between ...)?它已经失效了。非常感谢您的帮助! - Milan
1
@Milan 链接已更新。 - Nirmal

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接