4

はじめに: 最初に紹介として、私は StackOverflow に関する最初の質問をすることを非常に「誇りに思っています」。他の人が私を助けてくれるのと同じくらい、私も他の人を助けることができたらいいなと思っています。

コンテキスト : SURF アルゴリズムを使用して画像内の特徴を検索するアプリケーションを開発しています。キーポイントを計算し、SURF で記述子を抽出します。次に、ユークリッド距離に基づくブルートフォース マッチャーを使用して、画像 1 の記述子を画像 2 と一致させます。ここに問題があります。プログラムを 2 回実行しても同じ結果が得られません (同じ画像を使用する場合、正確にする必要があります)。 :p)。

出力 : 出力は次 のとおりです。

3620 件中最初の 20 件の一致で最初のランタイム

0:  0   89  0.292352
1:  1   997 0.186256
2:  2   1531    0.25669
3:  3   2761    0.24148
4:  4   2116    0.286187
5:  5   2996    0.201048
6:  6   3109    0.266272
7:  7   2537    0.17112
8:  8   2743    0.211974
9:  9   2880    0.208735
10: 10  2167    0.269716
11: 11  2431    0.164508
12: 12  1474    0.281442
13: 13  1867    0.161129
14: 14  329 0.18388
15: 15  1580    0.229825
16: 16  1275    0.254946
17: 17  1749    0.203006
18: 18  305 0.221724
19: 19  1501    0.224663
20: 20  917 0.20708

3620 試合のうち最初の 20 試合で 2 回目の実行

0:  0   1455    0.25669
1:  1   963 0.186256
2:  2   3008    0.150252
3:  3   2936    0.24148
4:  4   2172    0.286187
5:  5   2708    0.211974
6:  6   730 0.185199
7:  7   3128    0.266272
8:  8   750 0.181001
9:  9   2272    0.17112
10: 10  2842    0.208735
11: 11  55  0.229677
12: 12  2430    0.269716
13: 13  2360    0.164508
14: 14  1497    0.229825
15: 15  2443    0.254148
16: 16  1784    0.161129
17: 17  1209    0.254946
18: 18  311 0.18388
19: 19  944 0.228939
20: 20  533 0.221724

コード:これは私が使用するコードの一部です

SurfFeatureDetector detector(400);
vector<KeyPoint> keypoints1, keypoints2;
detector.detect(img1, keypoints1);
detector.detect(img2, keypoints2);

SurfDescriptorExtractor extractor;
Mat descriptors1, descriptors2;
extractor.compute(img1, keypoints1, descriptors1);
extractor.compute(img2, keypoints2, descriptors2);

vector<DMatch> filteredMatches;
matching(descriptors1,descriptors2,filteredMatches,1);

マッチング機能はこちら

void crossCheckMatching( const Mat& descriptors1, const Mat& descriptors2,
                     vector<DMatch>& filteredMatches12, int knn=1 )
{
    BruteForceMatcher<L2<float>> matcher;
    filteredMatches12.clear();
    vector<vector<DMatch> > matches12, matches21;

    matcher.knnMatch( descriptors1, descriptors2, matches12, knn );
    matcher.knnMatch( descriptors2, descriptors1, matches21, knn );

    debug_writeMatches("D:/jmartel/exec2-log.txt",matches12);
    ...
}

結論 : SURF アルゴリズムは「現実的な」出力を提供します。これは、同じ 2 つの画像を使用して 2 つのランタイムで検出されたキーポイントの数が同じであることによって部分的に証明されます。BruteForceMatcher は本当に奇妙な出力を提供します。これはログ ファイルによって証明されており、2 つのランタイムで同じように一致しないことを明確に示す出力可能な画像を使用できます。

また、このすべてのコードを GPU に実装しましたが、観察結果は同様です。ただし、SURF は GPU でより多くのポイントを提供します (同じパラメーターを使用)。

ポイントを注意深く見ると、一部の距離はまったく同じであり、可能性はありますが奇妙です (2 セットのポイント間の記述子が等しい場合でも...)。夫婦の例です

  (runtime 1) 1: 1 997 0.186256
/ (runtime 2) 1:1 963 0.186256 

またはさらに見知らぬ人

  (runtime 1) 14: 14  329 0.18388
/ (runtime 2) 18: 18  311 0.18388

OpenCV2.0 Doc には、私が読んだ内容から特に興味深いことは何も書かれていません。 ここで OpenCV2.1 の BruteForceMatcher C++ ドキュメントを参照してください。

説明があれば、またはコードを変更できるものがあれば、喜んでいます。ご協力いただきありがとうございます。

ジュリアン

4

3 に答える 3

6

フィーチャーの順序を確認できますか? 複数の CPU を使用している場合、コードが並行して実行される可能性があるため、機能が (毎回) 同じ順序にならないことがあります。

于 2011-07-15T20:53:03.253 に答える
0

並列で実行されている場合でも、アルゴリズムが異なる出力を提供する必要があるのはなぜですか?

しかし、私が例として示した出力は、並列実行があるため関連性がないということです。特定の場合の距離がまったく同じである理由を説明できます=>2ランタイム=2つの異なるランタイムインデックスを持つ2つの同じ記述子のペア処理の=2つの異なる出力順序...しかし、同じ画像結果が得られないという問題がまだあります...異なるペアがリンクされているのがわかります。並列処理のために変更する必要があるのはなぜですか?他に何かありませんか?

于 2011-07-20T14:26:58.797 に答える
0

違いが非常に小さい場合は、float と double を使用すると違いが生じる可能性があります。

これは推測にすぎませんが、ポインターアドレスをハッシュキーとして使用すると、非決定論が発生する可能性があります。

于 2011-07-25T16:02:19.073 に答える