Pythonでフォルダ内に同じ画像がないか検索してみた
同じフォルダの中に同じ画像がないかどうか、Pythonで調べてみました。
目次
一致する画像を検索したい
私は整理が苦手です。
ということで、画像ファイルがいろいろなフォルダに散乱しているのですが、なかには同じ画像であったり、同じ画像を拡大縮小したものだったりするファイルが存在します。困ったことに、ファイル名すらばらばらだったりします。私が悪いのですが。
というわけで画像ファイルを整理したいのです。面倒なことはPythonにやらせようということで、Pythonさんに同じ画像の判定をしてもらいたいと思います。
画そのもので同じ画像かどうかを判断したい
ファイルが重複するかどうか調べる方法としては、例えば、ファイル名・作成者・タイムスタンプ・ファイルサイズなどのファイルのメタ情報で比較するのが手っ取り早い方法です。ただ、クラウド上のオブジェクトをダウンロードした場合など、こういうメタ情報が変化しますのでこの方法は使えません。
ファイルのハッシュを計算して比較する方法もあります。フリーウェアのダウンロードサイトなどで使われる方法ですね。今回は画像の一致を調べたいのですが、拡大縮小されているとファイルのハッシュも変わると思いますので、この方法も使えません。
というわけで、画そのもので比較したいのです。
画像そのものの比較としてぱっと思いつくのは、各画素の輝度の比較やヒストグラムの比較、特徴点の比較です。
今回は、Perceptual hashという手法で画像そのものの比較をしてみます。 詳しく解説されているサイト がありますので、こちらを参考にしてください。
ImageHashライブラリで比較する
Pythonは便利なもので、画像のPerceptual hashを計算する ImageHash というライブラリが公開されています。
このライブラリでは、4種類のハッシュの計算ができます。
average hashing (aHash) 平均輝度からの差分を使う方法
perception hashing (pHash) DCTしてから差分を使う方法
difference hashing (dHash) 隣接領域との差分を使う方法
wavelet hashing (wHash) ウェーブレット変換してから差分を使う方法
手順としては、各画像のハッシュ値を計算して、画像間のハッシュ値の差が小さい(最小は0)ほど類似度が高いという判定をするということになります。
pipでインストールできます。PillowとSciPyが必要なようです。
> pip install ImageHash
ImageHashでの画像比較例
モデルは プロ生ちゃん のサイトからダウンロードさせていただいたIXYさんによるイラストです。元データはPSDファイルなので、PillowなどであらかじめJPEGに変換してから使用します。
比較した画像はこの5種類です。
test-1
test-2
test-3
test-4
test-5
では、test-1とtest-2の各ハッシュ値の差分を計算してみます。
from PIL import Image
import imagehash
hash_1a = imagehash.average_hash(Image.open('test-1.jpg'))
hash_1p = imagehash.phash(Image.open('test-1.jpg'))
hash_1d = imagehash.dhash(Image.open('test-1.jpg'))
hash_1w = imagehash.whash(Image.open('test-1.jpg'))
hash_2a = imagehash.average_hash(Image.open('test-2.jpg'))
hash_2p = imagehash.phash(Image.open('test-2.jpg'))
hash_2d = imagehash.dhash(Image.open('test-2.jpg'))
hash_2w = imagehash.whash(Image.open('test-2.jpg'))
print('ahash : ', hash_2a-hash_1a)
print('phash : ', hash_2p-hash_1p)
print('dhash : ', hash_2d-hash_1d)
print('whash : ', hash_2w-hash_1w)
> python test.py
ahash : 5
phash : 12
dhash : 6
whash : 6
こんな感じで数値になります。計算方法によって結果が結構異なりますね。
各画像のtest-1からの差を計算してみます。
test-1 |
test-2 |
test-3 |
test-4 |
test-5 |
|
---|---|---|---|---|---|
ahash |
0 |
5 |
4 |
0 |
13 |
phash |
0 |
12 |
16 |
0 |
30 |
dhash |
0 |
6 |
7 |
0 |
26 |
whash |
0 |
6 |
0 |
0 |
32 |
test-1とtest-1が一致するのは当然ですが、縮尺の違うtest-1とtest-4もきちんと一致しました。
whashでtest-1とtest-3が一致したのが謎ですね。得手不得手がありそうなので、試してから使用するのが良さそうです。
フォルダ内の類似の画像を検索する方法
では、フォルダ内の類似画像の検索をしてみます。
今回は、ahashでハッシュ値の差が0になるものを検出させます。
import os
from PIL import Image
import imagehash
userpath = '.' # 検索するパス
image_files = []
f = [os.path.join(userpath, path) for path in os.listdir(userpath)]
for i in f:
if i.endswith('.jpg') or i.endswith('.png'):
image_files.append(i)
imgs = {}
for img in sorted(image_files):
hash = imagehash.average_hash(Image.open(img))
if hash in imgs:
print('Similar image :', img, imgs[hash])
else:
imgs[hash] = img
出力はこうなります。
>python p.py
Similar image : .\test-4.jpg .\test-1.jpg
検出できました。
公開日
広告
Pythonで画像処理カテゴリの投稿
- Python (Pillow)でグラデーション画像を作る
- PythonでGIFアニメを作る(PILでファイルをつなげる編)
- PythonでOpenCVの画像データをMatplotlibで表示する
- PythonでPDFを画像に変換する(Windows10)
- PythonでPSDファイルをJPEGやPNGに変換する
- Pythonでカラー画像をグレイスケールに変換する(OpenCV編)
- Pythonでフォルダ内に同じ画像がないか検索してみた
- Pythonでマスク画像を作る方法(3選)
- Pythonで図形の外接矩形を描く(OpenCV編)
- Pythonで図形の輪郭の大きさを調べる(OpenCV編)
- Pythonで画像の余白を削除する(OpenCV編)
- Pythonで画像の余白を削除する(Pillow編)
- Pythonで画像の大きさやフォーマットを調べる(Pillow編)
- Pythonで画像の減色をする
- Pythonで画像をトリミングする(Pillow編)
- Pythonで画像を他の画像にペーストする(Pillow編)
- Pythonで画像を回転する(Pillow編)
- Pythonで画像を拡大縮小(リサイズ)する(Pillow編)
- Pythonで画像を読み込み、表示し、保存する(OpenCV編)
- Pythonで画像を読み込み、表示し、保存する(Pillow編)
- Pythonで画像を2値化する(OpenCV編)
- Pythonで記号の輪郭を検出する(OpenCV編)
- PythonとOpenCVで画像をグレースケールに変換してみた
- PythonとOpenCVで画像をネガポジ反転してみた