最近、研究室の教師は最初の簡単な課題を割り当てました。写真と、その文字から取られた目の写真を与え、完全な写真で目の位置を見つけるアルゴリズムを設計します。
まず直感的な効果に行き
、写真を入力してください
出力画像
入力画像
出力画像
このタスクを完了するために必要な前提知識(深く理解する必要はありません)には、ベクトル乗算の性質とたたみ込みの概念が含まれます。
簡単に言えば、いわゆる畳み込みは行列であり、行列の対応する要素はそれぞれ乗算されます(注:行列の乗算ではありません)。一般に、大きな画像の左上隅から右下隅まで、フィルターとして小さな行列があります。計算各小さな行列の畳み込みの合計(小さな行列のサイズはフィルター行列と同じです)。最大の合計に対応する点は、最も一致度の高い行列の左上隅です。
最大のたたみ込み和が最も一致するのはなぜですか?考えてみてください。たたみ込みのプロセスは、マトリックス内の対応するポイントの乗算です。これは、マトリックスを1次元ベクトルに拡張して乗算した結果と同じです。ベクトル乗算の特性から、角度が0でcos0 = 1であるため、2つのベクトルが平行である場合に乗算の最大値が得られることがわかります。もちろん、2つの同一のベクトルは平行です。そのため、たたみ込みの合計が最大になります。
しかし、それはまだ間違っています。あなたはそのような質問をするかもしれません。大きな行列は多くの小さな行列に分割することができます。2つの行列の値が互いに大きく異なり、フィルターの効果があまりない場合は、このときに何をすべきですか?何?答えは簡単です。つまり、大きな行列内の小さな行列ごとに、それ自体の平均値がフィルター行列との畳み込み前に差し引かれ、値のギャップが大きくなりすぎないようにします。
大きな行列の小さな行列の平均値が引かれたので、そうですか?
まあ、これを行う必要はありませんが、計算値を比較的小さくすることができます。
公式
上記の分析の波に加えて、分母を削除すると、実際には、最終バージョンは単に相関係数orzを見つけることです。相関係数が大きいほど、一致度は高くなります。
この時点で、アルゴリズムの構造は完成しており、コードは次のように非常に簡潔です。
import matplotlib.pyplot as plt # plt 用于显示图片
import numpy as np
from PIL import Image
def find_piece_in_pic(whole_pic, part_pic) :
#两个参数分别是两张图片的地址
part = Image.open(part_pic)
#转化为灰度图
part = part.convert('L')
part = np.array(part).astype('float64')
whole = Image.open(whole_pic)
whole = whole.convert('L')
whole = np.array(whole).astype('float64')
H, W = whole.shape
h, w = part.shape
part = part - int(np.average(part))
res = np.zeros((whole.shape))
for r in range(H - h + 1) :
for c in range(W - w + 1) :
cur_whole = whole[r : r + h, c : c + w]
cur_whole = cur_whole - np.average(cur_whole)
temp1 = (math.sqrt(np.sum(part * part)) * math.sqrt(np.sum(cur_whole * cur_whole)))
if temp1 == 0 : continue
temp = np.sum(cur_whole * part) / temp1
res[r ,c] = temp
topr, topc = np.where(res == np.max(res))
print(topr, topc)
print(np.max(res))
plt.figure()
plt.imshow(whole, cmap='gray')#灰度图要加上这个参数
plt.gca().add_patch(plt.Rectangle((topc,topr), w, h, color='black'))
plt.show()
find_piece_in_pic('einstain.png', 'eye.png')
Matlab関数
もちろん、そのような単純で適用性の高いアルゴリズムはMatlabに含まれている必要がありますが、関数はすべてカプセル化されているため、Matlabでは非常に単純になります。
それでもアインシュタインと彼の魅力的な大きな目を例にとります。
eye = rgb2gray(imread('eye.png'));
einstain = rgb2gray(imread('einstain.png'));
imshowpair(peppers,onion,'montage')
c = normxcorr2(eye,einstain); #就是这个函数
figure, surf(c), shading flat
[ypeak, xpeak] = find(c==max(c(:)));
yoffSet = ypeak-size(eye,1);
xoffSet = xpeak-size(eye,2);
figure
imshow(einstain);
imrect(gca, [xoffSet+1, yoffSet+1, size(eye,2), size(eye,1)]);