简体   繁体   English

OpenCV - 使用带有 ORB 描述符的 FLANN 来匹配特征

[英]OpenCV - Use FLANN with ORB descriptors to match features

I am using OpenCV 3.2我正在使用 OpenCV 3.2

I am trying to use FLANN to match features descriptors in a faster way than brute force.我正在尝试使用 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]);
    }
}

This code is working me with SURF and SIFT descriptors, but not with ORB.这段代码适用于 SURF 和 SIFT 描述符,但不适用于 ORB。

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

As it's said here , FLANN needs the descriptors to be of type CV_32F so we need to convert them.正如这里所说,FLANN 需要描述符类型为 CV_32F,因此我们需要转换它们。

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

However, this supposed fix is returning me another error in convertTo function.但是,这个假设的修复在convertTo函数中返回了另一个错误。

OpenCV Error: Assertion failed (!fixedType() || ((Mat*)obj)->type() == mtype) in create

This assertion is in opencv/modules/core/src/matrix.cpp file, line 2277.这个断言在opencv/modules/core/src/matrix.cpp文件的第 2277 行。

What's happening?发生了什么?


Code to replicate issue.复制问题的代码。

#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);
}

Did you adjust the FLANN parameters?您是否调整了 FLANN 参数?

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

While using ORB, you can pass the following.在使用 ORB 时,您可以传递以下内容。 The commented values are recommended as per the docs, but it didn't provide required results in some cases.根据文档推荐注释值,但在某些情况下它没有提供所需的结果。 Other values worked fine.:其他值工作正常。:

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

Probably you can convert that to C++ api?也许您可以将其转换为 C++ api?

According to the comment, the C++ way is:根据评论,C++方式是:

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

Binary-string descriptors - ORB, BRIEF, BRISK, FREAK, AKAZE etc.二进制字符串描述符- ORB、BRIEF、BRISK、FREAK、AKAZE 等。

Floating-point descriptors - SIFT, SURF, GLOH etc.浮点描述符- SIFT、SURF、GLOH 等。


Feature matching of binary descriptors can be efficiently done by comparing their Hamming distance as opposed to Euclidean distance used for floating-point descriptors.二进制描述符的特征匹配可以通过比较它们的汉明距离而不是用于浮点描述符的欧几里德距离来有效地完成。

For comparing binary descriptors in OpenCV, use FLANN + LSH index or Brute Force + Hamming distance .要比较 OpenCV 中的二进制描述符,请使用FLANN + LSH 索引Brute Force + Hamming distance

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

By default FlannBasedMatcher works as KDTreeIndex with L2 norm.默认情况下,FlannBasedMatcher 用作具有 L2 规范的 KDTreeIndex。 This is the reason why it works well with SIFT/SURF descriptors and throws an exception for ORB descriptor.这就是为什么它可以很好地与 SIFT/SURF 描述符配合使用并为 ORB 描述符抛出异常的原因。

Binary features and Locality Sensitive Hashing (LSH) 二元特征和局部敏感哈希(LSH)

Performance comparison between binary and floating-point descriptors 二进制和浮点描述符之间的性能比较

I believe there is a bug in the OpenCV3 version: FLANN error in OpenCV 3我相信 OpenCV3 版本中存在一个错误: OpenCV 3 中的 FLANN 错误

You need to convert your descriptors to a 'CV_32F'.您需要将描述符转换为“CV_32F”。

There is a function convert desxriptor to cv-32f.有一个函数将 desxriptor 转换为 cv-32f。 Please add this function then the above code will work.请添加此功能,然后上面的代码将起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM