2017-09-28 3 views
0

私はOpenCVでPythonで最初のステップを進めています。
私がしたいことは、画像が与えられ、参照画像のコレクションからその「元の」画像を見つけることです。クエリーイメージはイメージ全体(カード)のシンプルな写真なので、「写真の中のオブジェクトを見つける」というシナリオではなく、単に「類似」テストです。
私の最終的なデータベースはかなり大きくなります(約25 000イメージ)が、私は小さなスケール(わずか270イメージ)でいくつかのテストをやり始めました。
認識は完全に機能しますが、かなり遅いです:270画像すべてを繰り返し処理するのに8秒かかります。ディスクリプタをディスクに保存して読み込み、計算する代わりにディスクリプタを保存することで、スピードアップすることができました。とにかくそれはまだ遅いです。画像のデータベースから画像を探す

私はFLANNで作業を始めました。いくつかの結果が得られましたが、私の主な問題は、一致する画像を見つけることです。私はポイントの全体の配列を取得しますが、私は正しいイメージを取得する方法を知らない。
これは私のコードです:私が最も類似した画像をバック参照することができる方法についての

scanned = 'tests/temp_bw.png' 
surf = cv2.xfeatures2d.SURF_create(400) 
surf.setUpright(True) 

img1 = cv2.imread(scanned, 0) 
kp1, des1 = surf.detectAndCompute(img1, None) 

FLANN_INDEX_KDTREE = 1 
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) 

des_all = None 
for filename in os.listdir('images'): 
    img2 = cv2.imread('images/' + filename, 0) 
    kp2, des2 = surf.detectAndCompute(img2, None) 
    if des_all is None: 
     des_all = des2 
    else: 
     des_all = np.concatenate((des_all, des2)) 

flann = cv2.flann.Index() 
print "Training..." 
flann.build(des_all, index_params) 
print "Matching..." 
indexes, matches = flann.knnSearch(des1, 10) 
# and now??? 

任意の提案ですか?

EDIT これは、これらはflann.knnSearchからの戻り値ですdes2

print des2.shape 
(1731, 64) 
(2144, 64) 
(1811, 64) 
(1649, 64) 

の形状である:

pprint(matches[0]) 
array([ 0.0463759], dtype=float32) 

pprint(indexes[0]) 
array([249106], dtype=int32) 
+0

問題は表示されません。あなたの最初のアプローチではいくつかの類似度計算が使用されており、線形検索を使用して最大値を見つけました。今、近似検索を使用すると、10人の候補が得られます。これらの10個を同じようにするだけです(おそらくインデックスを使用して比較するデータを取得できますが、それはflann - > docsに依存します)。またはちょうど最初の場所で1人の候補者を尋ねる、または... – sascha

答えて

1

あなたdes_allを構築しながら、同じ長さを持つリストを作成記述子の数。各要素は、この記述子の元になったイメージのインデックスです。

マッチしたフィーチャが見つかったら、そのフィーチャがどのイメージに一致したかをリストで調べることができます。次に、正しいイメージを簡単に多数決するか、距離の逆数を使用します重要度で票の重さを測る


編集:あなたは多数決による投票を行う場合

for index, filename in enumerate(os.listdir('images')): 
    img2 = cv2.imread('images/' + filename, 0) 
    kp2, des2 = surf.detectAndCompute(img2, None) 
    indexList.extend([index]*des2.shape[0]) 

:あなたはこのようなループのためにあなたを変更した場合、あなたは特徴画像が生成された数を持つリストを作成することができます、あなたはマッチの距離を用いて比較検討したい場合は、あなたが再はずです

votes = indexList[indexes] 
from collections import Counter 
votes = Counter() 
likelyMatch = votes.most_common()[0][0] 

このように(それがマッチしています画像のための各特徴票を、そして最も多くの票を有する画像が勝利)行うことができますメンバーはmatchesの距離が2乗されており、平方根をとる必要があります。これらの距離は逆の重みとして使用することができ、一致の良さに応じて、それぞれの特徴がより高いまたはより低い重みで投票するようにすることができる。

+0

私は思う*私はあなたが言っているものを持っているが、私はいくつかのビットがありません。いくつかのコードを共有してもよろしいですか? 「距離による重み」について:「インデックス」や「マッチ」に距離情報があるので使用できないと思います(間違った方法を使用したかもしれません) – tampe125

+0

「des2」のサイズを教えてください。答えにいくつかのコードを追加しようとすることができます。 'matches'は2つの記述子の間のユークリッド距離の2乗でなければなりません。 – Atnas

+0

変数と返された値に関するいくつかの情報で質問を更新しました – tampe125

0

単純な(そして非常に古い、少なくとも1980年代の)手法は、各画像から空間ハッシュを計算し、ハッシュにマッチさせることです。たとえば:

http://www.hackerfactor.com/blog/?/archives/529-Kind-of-Like-That.html

あなたは非常に迅速に正確に一致を見つけることができます。

おおよその一致を見つけることはもう少し難しい:低解像度のハッシュを保存し、それらにマッチさせてから、大きなハッシュのハミング距離を計算する必要があります。実装の多くは、例えば、dhashためのImageMagickに基づいてRubyの逸品です、周りにあり

です:また、ヒストグラムを比較することができ

https://github.com/maccman/dhash

。彼らは回転の下で不変であるという利点があります。

+0

情報をありがとうが、照会イメージはカメラから取得されますが、テストデータベースには高品質スキャンされたものがありますので、完全に一致することはできません。 'dhash'に関して、私は同じ問題をもう一度受けるだろうと思う:すべてのファイルを一つずつ反復する必要がある。 – tampe125

+0

dhashの仕事は驚くほどうまくいく。確かに試してみる価値があります。 – user894763

+0

@ tampe125、ここではもう少しアルゴリズムがあり、ハミング距離の隣人検索を改善するための4つのリンクを提供しました:https://github.com/Nakilon/dhash-vips – Nakilon

関連する問題