※このページではアフィリエイト広告を利用しています

【Python応用】Average Hashを利用して画像の類似度(ハミング距離)を算出するプログラム

Python

ここでは「【Python応用】画像データにおけるAverage Hashを利用したハッシュ値の取得方法」の応用としてハミング距離を算出するプログラムを紹介しています。

スポンサーリンク
スポンサーリンク

行ったこと

以下の担々麺の写真の類似度をハミング距離を算出して比較してみました。「とあるお店の担々麺1」を基準に「とあるお店の担々麺2」「とあるお店の味噌ラーメン3」との距離を算出しました。

とあるお店の担々麺1
とあるお店の担々麺2
とあるお店の味噌ラーメン3

ハミング距離とは

ハミング距離とは2元符号におけるそれぞれの符号間の距離を排他的論理和(XOR)を用いて算出したものです。

排他的論理和は以下になります。

XOR
0⊕00
0⊕11
1⊕01
1⊕10
ハミング距離の定義
  • 同じ位置にあるビットを比較し「0」「1」が異なっている個数
  • XORが1となるビットの個数を数える

プログラム

from PIL import Image
import numpy as np
import os, re

#1---Average Hashの取得
def average_hash(fname, size = 16):
#2---画像データを開く
    img_data = Image.open(fname)
#3---グレースケールに変換
    img_data = img_data.convert('L')
#4---リサイズ
    img_data = img_data.resize((size, size), Image.ANTIALIAS)
#5---ピクセルデータを得る
    pixel_data = img_data.getdata()
#6---Numpyに変換
    pixels = np.array(pixel_data)
#7---二次元の配列に変換
    pixels = pixels.reshape((size, size))
#8---平均算出
    average = pixels.mean()
#9---値を1と0に変換
    out_pix = 1 * (pixels > average)
    return out_pix
#10---ハミング距離の算出
def hamming_dist(a, b, c):
    aa = a.reshape(1, -1)
    ab = b.reshape(1, -1)
    ac = c.reshape(1,-1)
    dist = (aa != ab).sum()
    dist1 = (aa != ac).sum()
    return dist,dist1
#11---関数の呼び出し
ahash = average_hash('noodle.JPG')
ahash1 = average_hash('noodle1.JPG')
ahash2 = average_hash('noodle2.JPG')
hamming_ab,hamming_ac = hamming_dist(ahash,ahash1,ahash2)
#12---出力結果
print(ahash)
print("*****")
print(ahash1)
print("*****")
print(ahash2)
print("ハミング距離は",hamming_ab)
print("ハミング距離は",hamming_ac)

上記がプログラムになります。

それでは解説していきます。ここでは、1~9の部分は解説しません。1~9の解説は「【Python応用】画像データにおけるAverage Hashを利用したハッシュ値の取得方法」を参照下さい。

#10---ハミング距離の算出
def hamming_dist(a, b, c):
    aa = a.reshape(1, -1)
    ab = b.reshape(1, -1)
    ac = c.reshape(1,-1)
    dist = (aa != ab).sum()
    dist1 = (aa != ac).sum()
    return dist,dist1

10の部分ではハミング距離の算出を行っています。関数として「average_hash」で算出した画像のハッシュ値を引数にして、画像の「とあるお店の担々麺1」と「とあるお店の担々麺2」、「とあるお店の担々麺1」と「とあるお店の味噌ラーメン3」を比較しています。

「reshape(1, -1)」は1次元の配列に変更しています。その下で「(aa != ab).sum()」の箇所では比較しているビットが等しくないものの合計を算出しています。

最後に合計を戻り値として返しています。

#11---関数の呼び出し
ahash = average_hash('noodle.JPG')
ahash1 = average_hash('noodle1.JPG')
ahash2 = average_hash('noodle2.JPG')
hamming_ab,hamming_ac = hamming_dist(ahash,ahash1,ahash2)

11の部分では関数を呼び出しています。最初にAverage Hashを算出して、その結果を基にハミング距離を算出しています。

最後に12の部分で結果を出力しています。

結果

とあるお店の担々麺1
とあるお店の担々麺2
とあるお店の味噌ラーメン3

それぞれのAverage Hash値になります。ハミング距離の結果としては「1と2の距離が77」「1と3の距離が188」となりました。

何となく担々麺同士は近い値になり、担々麺と味噌ラーメンは遠い距離になっていることが分かります。

ハミング距離を基に画像の振り分けができそうですね。

タイトルとURLをコピーしました