環境システム株式会社公式HP

〒660-0083 兵庫県尼崎市道意町7-1-3
尼崎リサーチ・インキュベーションセンター512

アイコン06-6657-5130

アイコンsales@hydrolab.co.jp

お問い合わせ

アイコン06-6657-5130

アイコンsales@hydrolab.co.jp

お問い合わせ

蛇使いな彼女BLOG

【第105回】輝度とパターンマッチング③~結果の参照~

2024.05.17

皆さんこんにちは!前回はZNCCのと計算方法を説明したので、今回は実際に2つの計算結果を比較してみましょう。

[方法1].

#入力画像とテンプレートの用意
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
temp=gray[195:280,55:168]


  # 走査窓毎にテンプレートとの相関係数を計算①
def scanning_window(img,temp):

     h,w=img.shape
     hi,wi=temp.shape

     img = np.array(img, dtype="float")
     temp = np.array(temp, dtype="float")
   
   #テンプレートのセンタリング
     t_mean=np.mean(temp)
     T=temp-t_mean

     #計算結果を書き込む配列
     res= np.tile(0,(h-hi, w-wi))

     for dy in range(0,h-hi):
         for dx in range(0,w-wi):

             win=img[dy:dy+hi,dx:dx+wi]
             w_mean=np.mean(win)

             #走査窓のセンタリング
             W=win-w_mean
  
             #ZNCC
             Mol=np.sum(W*T)
             Den=np.sqrt(np.sum(W**2))*np.sqrt(np.sum(T**2))
             ZNCC=Mol/Den

             try:
                 res[dy,dx]=ZNCC
             except ZeroDivisionError:
                 res[dy,dx]=0

     return res

score=scanning_window(gray,temp)
r,c=np.unravel_index(np.argmax(score), score.shape)
>>> print(r,c)
195 55
>>> 

最初の段階でテンプレートは入力画像[195:280,55:168]の位置に指定したことから、バッチリ成功していますね!

[方法2].

続いてもう一つの方法です。

 #入力画像とテンプレートの用意
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
temp=gray[195:280,55:168]

 # 走査窓毎にテンプレートとの相関係数を計算②
def scanning_window2(img,temp):

     h,w=img.shape
     hi,wi=temp.shape

     img = np.array(img, dtype="float")
     temp = np.array(temp, dtype="float")

     res= np.tile(0,(h-hi, w-wi))

     for dy in range(0,h-hi):
         for dx in range(0,w-wi):

             win=img[dy:dy+hi,dx:dx+wi]   
             
             #以下ZNCCの計算    
               
             #分散V
             V=np.mean(win**2)-(np.mean(win))**2
             V2=np.mean(temp**2)-(np.mean(temp))**2

             #分散V=標準偏差Sの2乗
             S=np.sqrt(V)*np.sqrt(V2)
             #共分散Cov
             Cov=np.mean((win-np.mean(win))*(temp-np.mean(temp)))

             ZNCC=Cov/S


             try:
                 res[dy,dx]=ZNCC

             except ZeroDivisionError:
                 res[dy,dx]=0

     return res

score=scanning_window2(gray,temp)
r,c=np.unravel_index(np.argmax(score), score.shape)
>>> print(r,c)
0 0
>>> 

[方法2].は計算結果が全て0になってしまったようです。

r、cは最も大きなZNCC値を持つ走査位置の行番号、列番号を示しますが、一番初期の(0,0)位置になっています。しかも、もう一点指摘すると前回の記事では今使ったテンプレートと全く同じ位置と走査位置(0,0)のZNCCは算出しましたよね。その結果は約「0.0511」だったはずですが

>>> score[r,c]
0
>>> 

このように0に丸められてしまっています・・・(°°;) これは何かがおかしい。

後でじっくりとコードを確認したんですが、桁落ちやアンダーフローではなく、単純に計算結果を格納する配列をnp.tileで指定していたことに問題がありました!!!(笑)

np.tileは初期値から上書きする際、整数型しか受付てくれないのでそりゃ全部0になるよね~('_')

ということで、以下の記述を

     #計算結果を書き込む配列
     res= np.tile(0,(h-hi, w-wi))

↓こっちに直してみたところ、[方法1]と[方法2]、どちらをとっても上手く正解へ導くことが出来ました✨

res= np.empty((h-hi, w-wi))

皆さま、毎度モトハシの凡ミスでご迷惑お掛けしております(*_*)

上記の[方法1]で結果が上手く出たのは、たまたま計算結果が1になったからだと考察しています・・・。(運がよかったので間違いに気づきませんでした)

気を取り直して、結果を画像として表示するとこのようになります。



ZNCCによるテンプレートマッチング結果


上図はZNCCで最も類似する位置に囲みをいれたもの。下図はZNCCの結果をマッピングしたもの。

完全一致の場所が赤く示されているのは当然ですが、テンプレートと同じ布地に対して類似度はほぼ0で、なぜかチョコの毛並み部分で若干数値が高いのは興味深いですね。

今回はZNCCの計算方法の紹介と式の変換など、統計学の基礎的な内容を含むお話でした。

pagetop