8

1 つの入力画像と比較してリストに多数の画像がある C++ プログラムを作成しようとしています。すべてが機能し、プログラムはDMatch一致を作成しています。

現在、ソース画像と比較した画像のリストのどれが最も一致するかを判断しようとしています。私は最初に、画像間のどこにいくつの一致があるかを比較するだけでこれを実行しようとしましたが、問題は、生成された画像に多くのキーポイントがある場合です。また、少なくとも私のプログラムでは、多くの一致がある傾向があります。

では、どの画像配列がソース画像に最もよく一致するかを判断するにはどうすればよいでしょうか? このループを使用して一致を判断していますが、実際には機能しません:

vector< vector<DMatch> > filteredMatches;
vector<int> goodIds;
Ptr<DescriptorMatcher> matcher(new BFMatcher(NORM_HAMMING, false));

printf("bad matches: ");

for(size_t i = 0; i < images.size();i++){
    vector<DMatch> matches, good_matches;

    matcher->clear();
    matcher->match(images[i], tex_des, matches);
    if(matches.size() < 8){
        printf("F%d,", (int)i + 1);
        continue;
    }

    double min_dist = 100;

    for(size_t j = 0; j < matches.size(); j++ ){ 
        double dist = matches[j].distance;
        if( dist < min_dist ) 
            min_dist = dist;
    }

    if(min_dist > 50.0){
        printf("D%d,", (int)i + 1);
        continue;
    }

    double good_dist = min_dist * 3;
    for(size_t j = 0; j < matches.size(); j++ ){
        if(matches[j].distance < good_dist)
            good_matches.push_back(matches[j]);
    }

    size_t size = good_matches.size();
    if(size < 8){
        printf("M%d,", (int)i + 1);
        continue;
    }

    vector<Point2f> srcPoints(size);
    vector<Point2f> dstPoints(size);

    for(size_t j = 0; j < size; j++){
        srcPoints[j] = destination[good_matches[j].trainIdx].pt;    
        dstPoints[j] = keyPoints[i][good_matches[j].queryIdx].pt;   
    }

    vector<unsigned char> inliersMask(srcPoints.size());
    Mat H = findHomography(srcPoints, dstPoints, CV_FM_RANSAC, 3.0, inliersMask);

    vector<DMatch> inliers;
    for(size_t j = 0; j < inliersMask.size(); j++){
        if(inliersMask[j]){
            inliers.push_back(good_matches[j]);
        }
    }
    if(inliers.size() < 4){
        printf("S%d,", (int)i + 1);
        continue;
    }

    filteredMatches.push_back(inliers);
    goodIds.push_back((int)i);

    H.release();
}

printf(" good matches: ");

int best = -1;
int amount = 0;
for(size_t i = 0; i < filteredMatches.size(); i++){
    int size = (int)filteredMatches.at(i).size();
    if(size < 8) continue;

    printf("%d,", goodIds[i] + 1);

    if(amount < size){
        amount = size;
        best = i;
    }
}

if(best >= 0) printf(" best match on image: %d, keypoints: %d, ", goodIds[best] + 1, amount);

誰かが私が使用しなければならない関数またはロジックを教えてくれれば、とても感謝しています!

4

4 に答える 4

1

リスト内の画像が何であるかによって異なります。世界中のすべての視力の問題に 1 つの解決策を用意することはできません。たとえば、私が取り組んでいるプロジェクトでは、壁の写真の素材を認識する必要があります。異なる素材の壁の写真と比較して、一致することを期待することはできません。

私の場合、記述子を作成する必要がありました。記述子は、別の画像の他の値と比較できる値を出力するアルゴリズムです。LBP、SURF など、openCV ではすでに多くの記述子が使用可能です。簡単に言うと、画像を比較するのではなく、画像 1 の記述子の出力値をすべての記述子の値と比較します。リストの画像。

実生活で一致を見つけるために目/脳が使用する記述子を取得する必要があります。たとえば、マッチングが色に基づく場合、CLD または DCD を使用できます。マッチングがテクスチャに基づく場合は、LBP を使用します。私のプロジェクトで行ったように、多くの記述子を使用し、訓練されたデータ アルゴリズムで機械学習を使用して、最適な一致を見つけることもできます。

要約すると、すべての視力の問題を解決できる特効薬はありません。ソリューションを問題に適応させる必要があります。

それが役に立てば幸い!

于 2013-03-12T15:42:46.343 に答える
1

簡単な答えはありません。より良い結果を得るには、距離を合計するだけでなく、何らかの変換を実装し、変換されたマップでクラスタリングを行う必要があります。それは難しく、公開することさえできます

それ以外の場合は、次元フィルタリングやヒストグラム フィルタリングなどのより実用的な手法を使用する必要があります。OpenCV のスティッチャーを見て、興味のあるモジュールを分離し、必要に応じてソース コードをカスタマイズできます。

于 2013-03-12T15:51:30.500 に答える
0

あなたの問題を簡単に検索すると、opencvの回答セクションに次のエントリが表示されました。

/履歴書回答フォーラム

あなたが抱えていると思われる質問への答えを提供しているようです。回答で提案されているように取得した結果をフィルタリングするには、RANSAC アルゴリズムを調べて、一致する選択で最良の結果を見つけます。

RANSAC の説明ウィキペディア

少なくとも、これはあなたを正しい方向に向けるはずです。

于 2013-03-12T07:57:22.730 に答える
0

本当に安定した通信を選択する必要があります。OpenCV 2 Computer Vision Application Programming Cookbook - Chapter 9 - Matching images using random sample consensus ( http://opencv-cookbook.googlecode.com/svn/trunk/Chapter%2009/ ) を読むことをお勧めします。

于 2013-03-11T16:47:53.743 に答える