web-dev-qa-db-ja.com

OpenCV-機能を一致させるためにORB記述子でFLANNを使用する

OpenCV3.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);
}
4
Santiago Gil

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));
5
Micka

OpenCV3バージョンにはバグがあると思います: OpenCV 3のFLANNエラー

記述子を「CV_32F」に変換する必要があります。

1
Hayley

バイナリ文字列記述子-ORB、BRIEF、BRISK、FREAK、AKAZEなど。

浮動小数点記述子-SIFT、SURF、GLOHなど。


バイナリ記述子の機能マッチングは、浮動小数点記述子に使用されるユークリッド距離とは対照的に、ハミング距離を比較することで効率的に実行できます。

OpenCVでバイナリ記述子を比較するには、FLANN + LSHインデックスまたはブルートフォース+ハミング距離を使用します。

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

デフォルトでは、FlannBasedMatcherはL2ノルムのKDTreeIndexとして機能します。これが、SIFT/SURF記述子でうまく機能し、ORB記述子の場合は 例外をスローする である理由です。

バイナリ機能と局所性鋭敏型ハッシュ(LSH)

バイナリ記述子と浮動小数点記述子のパフォーマンス比較

1
Nirmal