【Python】同じような画像が色々な組み合わせで存在する場合に重複分を削除するスクリプトを作った話

Code

はじまり

リサちゃん
リサちゃん

ただいマンドリル~

135ml
135ml

おかえリチャード・ギア~

そういや、リサちゃん宛に荷物が届いているぞ。

リサちゃん
リサちゃん

お?なんだなんだ。 ん、実家から来てる。

・・・・・・うわあ、服が届いた~。でも・・・昨日買った服と同じだ・・・。

135ml
135ml

あー、そういえば、重複した同じような画像が色々な組み合わせで出てきた際に、一気に削除してくれるスクリプトを作ったのを思い出したわ。

今回はそれを紹介するぜ。

リサちゃん
リサちゃん

今回、展開速いな!

そんな展開の仕方あり?

ツールの紹介

起動する関数は、RemoveDuplication()です。

今回重複を削除するファイルはこれらの画像になります。

スクリプトを起動して、それらの画像があるフォルダを選択します。

まず、削除する前に「Assessment」モードを選択します。

評価方法を選びます。「PixelMatch」を使います。

すると、画像の重複がどれぐらいあるのかをテキストファイルに吐き出します。

今回、Assessmentで調査した結果のテキストファイルから、前の画像と0.87の割合でピクセルが合致していたら、その画像を削除することにします。

再度、スクリプトを起動して、「Remove」モードにして「PixelMatch」モードを選択して、「87」(=0.87)を入力します。

削除処理が完了しました!(ちょっとデバッグしながらお届けしてます・・・。)

左が削除する前にバックアップしておいたもので、右が実際に削除したものです。

87%以上合致している画像は削除されています。

スクリプトの紹介

こちらがスクリプトになります。

ImageEditor.py

def RemoveDuplication(folderList):
    '''
    folderList    : List String absolutely path, of file filtered with extension in the selected folder.
    extracted_dir : String absolutely path of directory has selected file
    match_rate    : Float rate
    border_line   : border line
    '''
    if len(folderList) == 0:
        print('\nImageEditor exits because of no target files.')
        sys.exit(0)

    extracted_dir = os.path.dirname(folderList[0])

    # Error Handling
    if InputController.CheckWhetherSjisExists([folderList[0], extracted_dir], __file__) == True:
        sys.exit(0)

    # Decide to remove or don't
    executeMode = InputController.RepeatInputWithMultiChoices('\nYou wanna Remove or Assessment overlapped images? (R/A)', ['R', 'A'])

    assessMode = 'N'
    border_line = 70
    listForText = []
    # compare both image to remove img1 or not
    for i in range(0, len(folderList) - 1):
        imgName1 = os.path.splitext(os.path.basename(folderList[i]))[0]
        imgName2 = os.path.splitext(os.path.basename(folderList[i+1]))[0]
        # Decide method of assessment
        while assessMode != 'F' and assessMode != 'P':
            assessMode = InputController.RepeatInputWithMultiChoices('\nWhich method to assess?\n[ F: FeaturePoint, P: PixelMatch ] : ', ['F', 'P'])
            if executeMode == 'R':
                if assessMode == 'F':
                    border_line = InputController.RepeatInputWithMultiChoices('How many matches are required not to remove? : ', [0, 100])
                elif assessMode == 'P':
                    border_line = InputController.RepeatInputWithMultiChoices('How many matches are required to remove? : ', [0, 100])
            elif executeMode == 'S':
                pass
        # do assessment
        if assessMode == 'F':
            match_rate = JudgeMatchRateByFeaturePoint(folderList[i], folderList[i+1])
            match_rate = int(match_rate * 100)
            print('degree of similarity between "{imgName1}" and "{imgName2}" is {rate}'.format(imgName1=imgName1,imgName2=imgName2,rate=match_rate))
        elif assessMode == 'P':
            match_rate = JudgeMatchRateByPixelMatch(folderList[i], folderList[i+1])
            match_rate = int(match_rate * 100)
            print('match rate between "{imgName1}" and "{imgName2}" is {rate}'.format(imgName1=imgName1,imgName2=imgName2,rate=match_rate))
        listForText.append('"{imgName1}" and "{imgName2}" is {rate}'.format(imgName1=imgName1,imgName2=imgName2,rate=match_rate))
        # Remove files
        if executeMode == 'R':
            if assessMode == 'F':
                if match_rate <= border_line:
                    os.remove(folderList[i])
            elif assessMode == 'P':
                if match_rate >= border_line:
                    os.remove(folderList[i])
    # write to .txt file
    TextEditor.WriteText(DirEditor.GenerateFileName(extracted_dir, sep, 'match_rate.txt'), listForText)

    print('RemoveDuplication is terminated.\nCheck directory "{dirname}"'.format(dirname=extracted_dir))

ざっと書くと、以下の2軸での処理をこの関数で記載しています。まあ、ぶっちゃけ「FeaturePoint」の評価方法はあまり使っていませんね・・・。名残で残しているだけです。

評価方法「FeaturePoint」 評価方法「PixelMatch」
RemoveモードR、FR、P(今回はこれを使った)
AssessmentモードA、FA、P

おしまい

135ml
135ml

以上、重複を削除するツールでした。

以前に問題集が載っている動画を画像にしたことがあったけど、それと組み合わせると沢山ある同じ画像を減らせるってわけよ。

リサちゃん
リサちゃん

今回もだいぶ画像が減らせてたしね。機会があったら使ってみよーっと。

135ml
135ml

実家からの仕送りが他にもありそうだな。

リサちゃん
リサちゃん

そうだねえ。他には、セルカ棒、サングラス、麦わら帽子とかが入ってるね・・・。

なんか微妙に不要なものばかりだな・・・。

135ml
135ml

こういう仕送りって、生活必需品を送るもんじゃないのか・・・?

お母さん、奇天烈な人だね。

リサちゃん
リサちゃん

そうだねえ、いわゆる天然だね。まあ、退屈はしないよねえ。

手紙には「これで大学生活もっとEnjoyしてね!」だって。

135ml
135ml

なかなか・・・、ふざけてるつもりではないってことか・・・。

おい、その液体が入った袋は何だ?

リサちゃん
リサちゃん

な・・・!? やべえやべえ!!

・・・

なんか、袋の中に甘い匂いがする液体とガリガリ君の袋が入ってたわ・・・。

135ml
135ml

・・・マジか。一体どんな輩なんだ・・・。

以上になります!

このツールで重複を削除した後は・・・

この重複を除いた複数の画像を一気にトリミングしたい場合は、以下のツールで切り出してみてはいかがでしょうか?

こちらもPythonで動きます!

ちなみにこのツールを使う前段としての記事が以下に載っています。よければ見てみて下さい。

こちらもPythonで動きます。

おまけ

ペンギン
ペンギン

今回作ったWebアプリのソースは、以下のリポジトリのLandmasterLibraryに挙げています。

GitHub - landmaster135/Pyclone-Tornado: The memorandum for Python.
The memorandum for Python. Contribute to landmaster135/Pyclone-Tornado development by creating an account on GitHub.

コメント

タイトルとURLをコピーしました