社会人研究者が色々頑張るブログ

pythonで画像処理やパターン認識をやっていきます

画像のハッシュ値

ハッシュ値とは

ハッシュ関数(Hash Function)は任意のデータを別の値に置き換える関数です。
一般にハッシュ関数から得られる値(ハッシュ値)はデータの容量よりも十分に小さく、データの内容毎にユニークな値になります。
その性質を利用し、データの比較や検索や改ざん検出に応用されています。

画像のハッシュ値

画像のハッシュ関数では、画像の見た目を反映した※ハッシュ値を返してくれると、類似画像の検索や比較に用いる事ができてとても嬉しいです。
※この性質を連続性といいます。
ハッシュ関数としてよく用いられるMD5やSHAは画像の見た目に対する連続性は担保していません。
画像向けのハッシュ関数として、Average Hash(aHash)やPerceptual Hash(pHash)、Difference Hash(dHash)がよく知られています。
今回は、aHash, pHashをpythonで実装していきます。

Average Hash

画像の各領域と輝度平均を比較してハッシュ値を求める手法です。

  1. グレースケール化
  2. N x Nにリサイズ(N=8が多い)
  3. 輝度値の平均を求める
  4. 各画素に対し、輝度値が平均以上なら1, そうでなければ0とする
import cv2
import numpy as np


def aHash(img, N):
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.resize(img, (N, N))
    ave = np.mean(img)
    out = np.zeros_like(img)
    out[img >= ave] = 1
    return out


if __name__ == "__main__":
    img = cv2.imread("image.png")
    ah = aHash(img, 8)

Difference Hash

隣接領域との差分を用いてハッシュ値を求めます。

  1. グレースケール化
  2. N x Nにリサイズ(N=8が多い)
  3. 各画素毎に、右隣と比較して小さければ0、そうでなければ1とする。
import cv2
import numpy as np


def dHash(img, N):
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.resize(img, (N+1, N))
    
    out = img[:, 1:] > img[:, :-1]
    return out.astype(np.int64)


if __name__ == "__main__":
    img = cv2.imread("image.png")
    dh = dHash(img, 8)

実行例

このサイトからお借りした画像を用いてaHash, dHashを求めてみました。

画像 aHash dHash
f:id:nsr_9:20210808010454j:plain f:id:nsr_9:20210808010604p:plain f:id:nsr_9:20210808010612p:plain
f:id:nsr_9:20210808010530j:plain f:id:nsr_9:20210808010621p:plain f:id:nsr_9:20210808010630p:plain
f:id:nsr_9:20210808010537p:plain f:id:nsr_9:20210808010638p:plain f:id:nsr_9:20210808010645p:plain

aHashは輝度平均との比較なので、直感的にそれっぽい結果になってる雰囲気がありますね。
次はこのハッシュ値を用いて、画像検索なんかをやっていきたいです。