【问题标题】:OpenCV - Use FLANN with ORB descriptors to match featuresOpenCV - 使用带有 ORB 描述符的 FLANN 来匹配特征
【发布时间】:2017-10-05 11:08:58
【问题描述】:

我正在使用 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

正如here 所说,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);
}

【问题讨论】:

    标签: c++ opencv orb flann feature-descriptor


    【解决方案1】:

    二进制字符串描述符 - 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 描述符和 throws an exception 用于 ORB 描述符的原因。

    Binary features and Locality Sensitive Hashing (LSH)

    Performance comparison between binary and floating-point descriptors

    【讨论】:

      【解决方案2】:

      有一个函数将 desxriptor 转换为 cv-32f。请添加此功能,然后上面的代码将起作用。

      【讨论】:

      • 为您的帖子添加更多详细信息(包括在哪里添加cv-32f)。
      【解决方案3】:

      我认为OpenCV3版本存在bug:FLANN error in OpenCV 3

      您需要将描述符转换为“CV_32F”。

      【讨论】:

        【解决方案4】:

        你调整了 FLANN 参数了吗?

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

        在使用 ORB 时,您可以传递以下内容。根据文档建议使用注释值,但在某些情况下它没有提供所需的结果。其他值工作正常。:

        index_params= dict(算法 = 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));
        

        【讨论】:

        • 确实有效。电话是cv::FlannBasedMatcher matcher = cv::FlannBasedMatcher(cv::makePtr&lt;cv::flann::LshIndexParams&gt;(12, 20, 2));
        • 另外,并不是所有的匹配都使用 ORB 和 FLANN 进行对应(也许使用其他描述符也会发生这种情况,但暂时不会)。然后,在第二次邻居比测试中,我添加了一个安全条件if (matches[i].size() &gt;= 2)
        • 可能值得一提的是FLANN_INDEX_LSH = 6
        • 还有一个关于multi_probe_level的评论是“在多探针中使用的级别数(标准LSH为0)”,所以使用multi_probe_level=0可能会更好。
        猜你喜欢
        • 2012-07-18
        • 2013-01-01
        • 2018-02-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-28
        • 2018-09-12
        • 2012-05-30
        相关资源
        最近更新 更多