logo
Published on

Imagededupで類似画像を抽出、検出する(Python)

Authors

Pythonのマシンラーニング、ディープラーニング、機械学習、AIライブラリ、imagededupを使用し、似ている画像、類似している画像、写真を検出するためのガイドです。 例えば、同じ画像でも画質や解像度が違う画像、少しだけ角度が違う、トリミングされている、など、単純なハッシュアルゴリズムでは検知できない類似性を見つけてくれます。 マシンラーニングに使用するための画像のフィルタとして使うのが定石のように思いますが、一般的な用途にも使うことはできるでしょう。

virtualenvで仮想環境を作成します。

virtualenv imagededup_dev
. .\imagededup_dev\Scripts\activate

imagededupパッケージをインストールします。

pip install imagededup

virtualenvをインストールしていない場合はインストールします。

pip install virtualenv

Pythonおよびpipをインストールしていない場合はインストールします。 Windowsのchocoでインストールした場合はコンソールの再起動をします。また、パスが通っていることを確認してください。

(Linux)

sudo apt update
sudo apt install python3-pip python3-dev

(Windows)

choco install python3 --version=3.7.6.20200110

(Powershell、パスの確認)

Start C:\Windows\system32\rundll32.exe sysdm.cpl, EditEnvironmentVariables

WindowsにChocoがインストールされていない場合はインストールします。

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
refreshenv

Imagededupの実行にはtensorflowが必要です。 インストールされていない場合はインストールします。

以下はサンプルコードです。 これにより、duplicates変数に検出された重複している画像ファイルのマッピングがされたオブジェクトが格納されます。

if __name__ == '__main__':
  from imagededup.methods import PHash
  phasher = PHash()
  encodings = phasher.encode_images(image_dir='C:/images/anime')
  duplicates = phasher.find_duplicates(encoding_map=encodings)

以下は僕の書いたimagededupのためのコマンドラインソフトウェアです。 ライセンスは指定していませんので、無許可のブログ、Githubなどオンラインへの転載などはお控えください。

if __name__ == '__main__':

    from imagededup.methods import PHash
    import json
    from pathlib import Path
    from imagededup.utils import plot_duplicates
    import fire

    def main (type = "get_json", path = "C:\pg\ml\_images\hent") :

        if ( type == "get_json" ) :
            phasher = PHash()
            encodings = phasher.encode_images(image_dir=path)
            duplicates = phasher.find_duplicates(encoding_map=encodings)

            Path('./tmp.json').write_text(json.dumps(duplicates))

        if ( type == "test" ) :
            duplicates = json.loads(Path('./tmp.json').read_text())
            for key, value in duplicates.items() :
                if ( value ) :
                    plot_duplicates(image_dir=path,
                                    duplicate_map=duplicates,
                                    filename=key)

        if ( type == "get_txt" ) :

            duplicates = json.loads(Path('./tmp.json').read_text())
            content = ""
            delete_values = []
            for key, value in duplicates.items() :
                if ( value and not key in delete_values ) :
                    for v in value:
                        content = content + v + "\n"
                        delete_values.append(v)

            Path('./duplicates.txt').write_text(content)

    print(fire.Fire(main))

以上のプログラムは以下のパッケージを使用します。以下のコマンドでインストールします。

pip install fire

以下、上記プログラムの使用例です。 以下コマンドを順番に実行してください。 --pathを画像フォルダのパスに指定してください。

python imagededup_dev.py --type get_json --path "B:_images\animeimages"でjsonファイルを生成します。

python imagededup_dev.py --type test --path "B:_images\animeimages"でjsonファイルをもとにテストを行います。これにより重複している画像が表示されます。重複している画像がなければ何も表示されません。

python imagededup_dev.py --type get_txt --path "B:_images\animeimages"でjsonファイルをもとに重複しているファイルのパスをリストしたテキストファイルduplicates.txtを作成します。

作成されたテキストファイルをもとに手動で画像ファイルを削除してもいいですが、 以下のようにLinuxコマンドでバッチとして削除できます。 (注意: 以下コマンドはカレントディレクトリ、フォルダのファイルを削除します。使い方についてはご自身でよく調べて利用してください。)

rm $( cat "/path/to/duplicates.txt" )

WindowsでLinuxを使用する方法については、当ブログで紹介しています。 "wsl"または"bash on windows"などで当ブログを検索してガイドを見つけてください。