ここでは画像データにおけるAverage Hashを利用したハッシュ値の取得方法について解説しています。
行ったこと
下記の画像のハッシュ値を取得しました。ハッシュ値を取得することで、画像の類似度や比較が可能なので、ぜひ知っておきたい方法の1つです。
プログラム
from PIL import Image
import numpy as np
#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 np2hash(n):
hash_c = []
#11---リスト型に変換
for nl in ahash.tolist():
hashl = [str(i) for i in nl]
hash2 = "".join(hashl)
#12---整数に変換
i = int(hash2, 2)
hash_c.append("%04x" % i)
return "".join(hash_c)
#13---関数の呼び出し
ahash = average_hash('noodle.JPG')
ahash1 = average_hash('noodle1.JPG')
#14---出力結果
print(ahash)
print(np2hash(ahash))
print(ahash1)
print(np2hash(ahash1))
上記がプログラムになります。
それでは解説していきます。
#1---Average Hashの取得
def average_hash(fname, size = 16):
1の部分では、関数としてハッシュ値の計算を行っています。指定のサイズでリサイズしています。ハッシュ値は「データを混ぜ合わせて一定の長さのデータを作り出す関数から算出された値」のことです。
#2---画像データを開く
img_data = Image.open(fname)
2の部分では、画像データを開いています。今回開いているのは「noodle.JPG」「noodle1.JPG」になります。
#3---グレースケールに変換
img_data = img_data.convert('L')
3の部分では開いた画像をグレースケールに変換しています。引数の「L」はグレースケールを示しています。他には「RGB」「CMYK」などのモードもあります。
#4---リサイズ
img_data = img_data.resize((size, size), Image.ANTIALIAS)
4の部分ではリサイズしています。「ANTIALIAS」はアンチエイリアス処理をしていることを意味しています。ここでは、リサイズ時のエイリアシング(画像のギザギザ)を抑制するために指定しています。
#5---ピクセルデータを得る
pixel_data = img_data.getdata()
5の部分ではピクセルデータを取得しています。getdata()関数を用いて画像データを取得しています。
#6---Numpyに変換
pixels = np.array(pixel_data)
6の部分では取得したデータをnumpyに放り込んでいます。数値計算が得意なnumpyを用いることで処理を楽にしています。
#7---二次元の配列に変換
pixels = pixels.reshape((size, size))
7の部分では二次元配列に変換しています。これは平均を算出するためのデータ整形の一つだと思って下さい。
#8---平均算出
average = pixels.mean()
8の部分ではmean()関数を用いて平均を算出しています。
#9---値を1と0に変換
out_pix = 1 * (pixels > average)
return out_pix
9の部分では取得した値を0か1の2値に振り分けています。平均より大きいかそれ以下で振り分けています。
#10---ハッシュ値に変換
def np2hash(n):
hash_c = []
#11---リスト型に変換
for nl in ahash.tolist():
hashl = [str(i) for i in nl]
hash2 = "".join(hashl)
#12---整数に変換
i = int(hash2, 2)
hash_c.append("%04x" % i)
return "".join(hash_c)
10の部分では、ハッシュ値に変換しています。1と0の2進数から16進数に変換しています。11の部分ではnumpy配列からリストに変換しています。12の部分では整数に変換しています。
#13---関数の呼び出し
ahash = average_hash('noodle.JPG')
ahash1 = average_hash('noodle1.JPG')
13の部分ではデータを指定しているのと関数を呼び出しています。
#14---出力結果
print(ahash)
print(np2hash(ahash))
print(ahash1)
print(np2hash(ahash1))
14の部分では結果を出力しています。ハッシュ値と2進数の値を可視化しています。
結果
似ているようで2進数の出力が変わっていることが分かります。ハッシュ値としては「000007e07ffefffff187c7e38ee18fc087c080818001c003f00ffffe3ff80000」となりました。
写真の2進数化とハッシュ値の取得ができたので類似度などを調べられそうなことが確認できました。
その他、Average Hashを用いた使用例
項目 | 内容 |
Average Hashを利用して画像のハミング距離を算出するプログラム | リンク先では「【Python応用】画像データにおけるAverage Hashを利用したハッシュ値の取得方法」の応用としてハミング距離を算出するプログラムを紹介しています。 |