BRISK を OpenCV での機能の検出と説明に使用すると、パフォーマンスの問題が発生します。
基本的に、この画像から取得したすべての記述子を一致させようとします。
特徴の検出と説明のために LSH アルゴリズムと BRISK を備えた flann ベースのマッチャーを使用して、画像のデータベースから取得したすべての記述子に対して。
私の画像データベースは 242 枚の画像で構成されています。この 242 枚の画像には、上記の「複雑な」画像クエリで別々に取得された各オブジェクトに対応する 3 つの画像があります。
BRISK 検出に使用されるパラメーターは次のとおりです (デフォルトの opencv パラメーター): しきい値: 30、オクターブ: 4、パターン スケール: 1.0。
ベスト マッチ手法 (イメージ クエリの各記述子は、データベース記述子のセット内の最も近い近傍に関連付けられています) を使用したフラン マッチングの後、私のアルゴリズムは、一致のパーセンテージで並べ替えられたデータベース イメージのリストを出力しました。最初の 4 つの結果は次のとおりです。
- データベース内のボルトに対応する画像: 4 つの一致 / 15 の検出されたキーポイント => 一致率: 26.7%。
- データベース内のボトルに対応する画像には 4 つの一致 / 15 の検出されたキーポイントがあります => 一致率: 26.7%。
- データベース内のボルトに対応する画像には、10 件の一致 / 59 件のキーポイントが検出されています => 一致率: 16.9%。
- 画像クエリに存在しないオブジェクトに対応する画像: 1 つの一致 / 16 の検出されたキーポイント => 一致率: 16.7%。
ORB を機能の検出と説明として使用して、この結果を比較しました。使用されるパラメーターは次のとおりです: フィーチャの数: 2000、スケール係数: 1.2、ピラミッド レベルの数: 8。
ここに私が得る結果があります:
- データベース内のボルトに対応する画像: 576 一致 / 752 検出されたキーポイント => 一致率: 76.6%。
- データベース内のボトルに対応する画像には、111 件の一致 / 189 件のキーポイントが検出されています => 一致率: 58.7%。
- データベース内のペンに対応する画像には、124 の一致 / 293 の検出されたキーポイントがあります => 一致率: 42.3%。
- 画像クエリに存在しないオブジェクトに対応する画像: 2 つの一致 / 66 の検出されたキーポイント => 一致率: 3%。
ご覧のとおり、結果は ORB ではるかに優れています。まず、データベース内の各画像でより多くのキーポイントが検出され、良好なオブジェクトの一致率が大幅に向上します。さらに、適切なオブジェクトの一致率と不適切なオブジェクトの一致率の差はより顕著です。
なぜ BRISK 検出器が ORB 検出器よりもはるかに少ないキーポイントを検出するのか疑問に思っています。BRISK 検出器でより多くのキーポイントを検出する方法を見つけるために、さまざまなテストを行いました (しきい値を下げ、オクターブ数を下げます)。確かにもう少し多くのキーポイントを検出できますが、ORB 検出器との違いは依然として非常に重要です。BRISK 検出器がこのような動作をする理由がわかりましたか?
私の OpenCV バージョンは 2.4.8 ですが、次のステートメントに従って、2.4.4 および 2.4.9 バージョンで BRISK 検出部分を試しました。
http://code.opencv.org/issues/2491およびBRISK 機能検出器は、改善なしでゼロのキーポイントを検出します。
また、ORB 検出器と BRISK 記述を組み合わせようとしました。マッチング結果は、最初の方法 (完全な BRISK) よりも優れていますが、2 番目の方法 (完全な ORB) よりも劣っています。
- データベース内のボルトに対応する画像: 529 一致 / 708 検出されたキーポイント => 一致率: 74.7%。
- データベース内のボトルに対応する画像には 69 の一致 / 134 の検出されたキーポイントがあります => 一致率: 51.5%。
- データベース内のペンに対応する画像には、93 / 247 個のキーポイントが検出されています => 一致率: 37.6%。
- 画像クエリに存在しないオブジェクトに対応する画像: 5 つの一致 / 50 の検出されたキーポイント => 一致率: 10%。
各画像で検出されたキーポイントの数は、方法 2 と方法 3 で同じではないことに注意してください。実際に、このコードをテスト画像 (ここではボルトの画像) で実行すると、次のようになります。
// BRISK parameters
int Threshl=30;
int Octaves=4;
float PatternScales=1.0f;
// ORB parameters
int nFeatures=2000;
float scaleFactor=1.2f;
int nLevels=8;
BRISK BRISKD(Threshl, Octaves, PatternScales);
ORB ORBD(nFeatures, scaleFactor, nLevels);
vector<KeyPoint> kpts;
Mat descriptors;
Mat img = cv::imread("Path to the bolt image", IMREAD_GRAYSCALE );
ORBD.detect(img,kpts); // Number of keypoints detected = 752
BRISKD.compute(img, kpts, descriptors); // Number of descriptors = 708
BRISK は、記述子で検出されたすべてのキーポイントを計算していないようです (ORB 検出器によって検出された 752 個のキーポイント => BRISK 記述子によって計算された 708 個の記述子)。
ただし、ORB によって検出されたすべてのキーポイントが BRISK 記述子で計算されていない場合でも。これらの結果から、BRISK は ORB よりもキーポイントを記述するのに適していないように見えますか? 間違っていたら訂正してください。
私の結果を理解するのに役立つ要素がある場合、または OpenCV で BRISK に関する問題を既に経験している場合は、お知らせください。どんな助けでも大歓迎です:)。