pythonを使ってORBとPerceptual Hashで画像の類似度を比べてみる
どうも、くずきです。
今回はPython
を使って画像の類似度を求めました。
なぜやりたいのかというと、インスタグラムなどのSNSで画像を設定していない人を除外したい。つまり、
この画像か、近しい画像を設定している人が見つけ出せれば良い。
比較対象の画像
ファイル名 | 画像 | 説明 |
---|---|---|
01.jpg | 今回の比較画像 | |
02.jpg | 女性の画像(インスタから持ってきたのでここではモザイク) | |
03.jpg | 男性の画像(インスタから持ってきたのでここではモザイク) | |
05.jpg | 比較画像と同じ | |
06.png | 比較画像の男風 | |
07.png | 比較画像の女風 | |
08.png | 化粧してる風な背景が比較画像に近い | |
11.jpg | 背景青い人の画像 | |
12.jpg | 背景青い人の画像 | |
13.jpg | 比較画像に少し文字載せたやつ | |
15.jpg | 比較画像にかなり文字載せたやつ |
ORBを使って類似度を求める
この方の記事の特徴点のマッチングの部分を参考にさせていただきました。
コードはほぼそのままお借りさせていただいたので、結果のみ。
TARGET_FILE: 01.jpg 02.jpg 86.5 03.jpg 76.0 05.jpg 0.0 06.png 57.0 07.png 20.0 08.png 93.0 11.jpg 66.0 12.jpeg 74.5 13.jpg 3.5 15.jpg 59.0
0になれば一致してる画像とみなされている。
06.png
、15.jpg
は除外したかったが思った以上に数値が高くなってしまい、閾値が設定しづらい。同じものが移動したり、回転したりしても特徴点を捉えることで同じものと認識する方法のためこういう結果なのは仕方ない。。
Perceptual Hashを使って類似度を求める
次に、画像をハッシュ値(64bit)に変換して、その距離を測ることによって類似度を求めるPerceptual Hash
というアルゴリズムを試してみる。
この方達の記事が参考になる。
Python
のimagehash
というライブラリで実装済みのため、それを利用する。
コード
from PIL import Image import imagehash import numpy import scipy import scipy.fftpack TARGET_FILE = '01.jpg' IMG_DIR = '/Users/SayKicho/images/' target_img_path = IMG_DIR + TARGET_FILE target_hash = imagehash.average_hash(Image.open(target_img_path)) files = os.listdir(IMG_DIR) print('TARGET_FILE: %s' % (TARGET_FILE), target_hash) print('files: %s' % (files)) for file in files: if file == '.DS_Store' or file == TARGET_FILE: continue comparing_img_path = IMG_DIR + file try: hash = imagehash.average_hash(Image.open(comparing_img_path)) haming = target_hash - hash except cv2.error: ret = 100000 print(file, hash, haming)
比較画像のハッシュ値(target_hash
)から比較対象のハッシュ値(hash
)を引き算してるところでハミング距離をだしてます。
TARGET_FILE: 01.jpg 00183c18183cffff 02.jpg ffe7c70707010302 51 03.jpg f4e0e9c7c7838330 47 05.jpg 00183c18183cffff 0 06.png 00383c3c18183cff 9 07.png 0018183c18187fff 7 08.png 0018181c1c18183c 16 11.jpg 00000306fcffffff 20 12.jpeg 103f1f8f82c7cfcf 28 13.jpg 00183c18183cffff 0 15.jpg 00181818181cffff 3
一番右がハミング距離。これが0になれば同じ画像と認識される。
さきほどORB
のほうで値が高くなってしまった、06.png
、15.jpg
の画像がかなり低く抑えられている。閾値はだいたい10
くらいにしておけば近しい画像と認識されそう。
急ぎ足で書いてしまったけど、Perceptual Hash
はあくまでも64bitのハッシュ値をもとめるアルゴリズムの総称をいっているので、細かくいうとAverage Hash
, Perceptive Hash
, Differece Hash
などがある。以下の記事に少し詳しく書いてあるので、気になる方はみとくといいかも。
感想
今回はPerceptual Hash
のAverage Hash
が一番効果よかったのでそれを用いて、インスタグラムの設定していない画像を見つけ出すことに成功した。
あまり画像周りに詳しくないので、他のアルゴリズムなども勉強しないとなー。