これは最善の解決策ではありませんが、解決策です。より良いテクニックを学びたい:
画像を回転または拡大縮小しない場合は、画像の単純な相互相関を使用できます。大きな画像で小さな画像が発生する場所に明るいピークがあります。
FFTメソッドを使用すると相互相関を高速化できますが、小さなソースイメージと大きなターゲットイメージを一致させるだけの場合、ブルートフォース乗加算メソッドの方が(通常ではありませんが)速くなります。
ソース:
ターゲット:
相互相関:
2つの明るいスポットは一致する場所です。
しかし、あなたがないあなたの例の画像で回転パラメータを持っているので、それはそれだけでは動作しません。スケーリングのみではなく回転のみが許可されている場合でも、相互相関を使用できますが、相互相関、ソースの回転、ターゲットイメージ全体との相互相関、再回転などが必要です。すべての回転。
これは必ずしも画像を見つけるとは限らないことに注意してください。ソース画像がランダムノイズであり、ターゲットがランダムノイズである場合、正確に正しい角度で検索しない限り、それは見つかりません。通常の状況では、おそらく検出されますが、画像のプロパティと検索する角度によって異なります。
このページは、それがどのように行われるかの例を示していますが、アルゴリズムを示していません。
合計がしきい値を超えるオフセットは一致します。ソースイメージをそれ自体と相関させ、すべての合計をこの数で割ることにより、一致の良さを計算できます。完全に一致するのは1.0です。
ただし、これは非常に計算量が多く、おそらくドットのパターンを一致させるためのより良い方法があります(これについて知りたい)。
グレースケールとFFTメソッドを使用した簡単なPythonの例:
from __future__ import division
from pylab import *
import Image
import ImageOps
source_file = 'dots source.png'
target_file = 'dots target.png'
# Load file as grayscale with white dots
target = asarray(ImageOps.invert(Image.open(target_file).convert('L')))
close('all')
figure()
imshow(target)
gray()
show()
source_Image = ImageOps.invert(Image.open(source_file).convert('L'))
for angle in (0, 180):
source = asarray(source_Image.rotate(angle, expand = True))
best_match = max(fftconvolve(source[::-1,::-1], source).flat)
# Cross-correlation using FFT
d = fftconvolve(source[::-1,::-1], target, mode='same')
figure()
imshow(source)
# This only finds a single peak. Use something that finds multiple peaks instead:
peak_x, peak_y = unravel_index(argmax(d),shape(d))
figure()
plot(peak_y, peak_x,'ro')
imshow(d)
# Keep track of all these matches:
print angle, peak_x, peak_y, d[peak_x,peak_y] / best_match
1色のビットマップ
ただし、1色のビットマップの場合、これははるかに高速です。相互相関は次のようになります。
- ソース画像をターゲット画像の上に配置
- ソース画像を1ピクセル移動する
- ビットごとのANDすべての重複ピクセル
- すべての1を合計する
- ...
グレースケール画像をバイナリにしきい値処理し、これを行うことで十分な場合があります。
点群
ソースとターゲットが両方ともドットのパターンである場合、より高速な方法は、各ドットの中心を見つけ(既知のドットと1回相互相関してからピークを見つけ)、それらをポイントのセットとして保存し、ソースを一致させることです2つのセットの最も近いポイント間の最小二乗誤差を回転、変換、および検索することにより、ターゲットを設定します。