2013-03-04 24 views
6

リストに1つの入力画像と比較して多数の画像があるC++プログラムを作成しようとしています。私は全部働いて、プログラムは一致するDMatchを作成しています。OpenCV:ORBを使用して複数の画像を比較する

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

どのようにして、どのイメージの配列がソースイメージに最も適しているかを判断できますか?私は試合を決定するために、このループを使用していますが、それは実際に動作しません:

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

誰かが、私はそれを大幅に感謝機能や、私が使用しなければならないロジックに私を指すことができれば!

+0

「は、ほとんどのインライアとの試合は私のベストマッチである。」と言っに問題は何ですか? –

+0

それは私が思った最初のことでしたが、試してみると正確な結果は得られませんでした。 – tversteeg

+0

OKだから、画像(偽のものも)はかなり類似していると思います。すべてのマッチまたはすべてのインライアの平均距離をとった場合の正確さはどのようになりますか?これが失敗する場所のサンプル画像を投稿できますか? –

答えて

0

本当に安定した対応を選択する必要があります。私は読むことをお勧めします:OpenCV 2コンピュータビジョンアプリケーションプログラミングクックブック - 第9章 - ランダムサンプルコンセンサス(http://opencv-cookbook.googlecode.com/svn/trunk/Chapter%2009/)を使用してイメージをマッチングする。

0

あなたの問題のための短い検索は、OpenCVの解答セクションに次のエントリを私に与え:

/CV Answer forum

あなたが持っているように見えるの質問に答えを供給するように思われました。答えに示唆したように結果をフィルタリングするには、RANSACアルゴリズムを見て、マッチ選択で最良の結果を見つけます。

RANSAC desctiption Wikipedia

少なくとも、これは正しい方向にあなたを指している必要があります。

+0

私のコードを見ると、すでにRANSACを使用していることがわかります。 – tversteeg

0

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

私の場合、ディスクリプタを作成する必要がありました。 Descriptorsは、別のピクチャの他の値と比較できる出力値を出力するアルゴリズムです。 openCVにはLBP、SURFなどのような多くの記述子が既に用意されています。単純に言えば、イメージをもう比較しないで、イメージ1のディスクリプタの出力値をすべてのディスクリプタ値と比較します。リスト内の画像。

あなたの目や脳が実際にマッチするものを見つけるために使用する記述子を選択する必要があります。たとえば、マッチングが色に基づいている場合は、CLDまたはDCDを使用できます。マッチングがテクスチャに基づいている場合は、LBPを使用します。私は自分のプロジェクトでやったようにして、多くのディスクリプタを使用し、訓練されたデータアルゴリズムを使ってMachine Learningを使用して最適なマッチングを見つけることもできます。

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

希望すると助かります!

1

直接的な回答はありません。より良い結果を得るには、ある種の変換を実装し、距離を合計するのではなく、変換されたマップ上でクラスタリングする必要があります。これは難しく、さらにpublishableです。

そうしないと、あなたは次元のヒストグラムフィルタリングのような、より実践的なテクニックを使用する必要があります。 OpenCVのstitcherを見て、興味のあるモジュールを分離し、必要に応じてソースコードをカスタマイズすることができます。

関連する問題