【Python】複数の画像を一気にトリミングするスクリプトを作った話

Code

はじまり

チュンチュン!・・・コケコッコー!・・・

リサちゃん
リサちゃん

はあ~、最近髪伸びてきたなあ、切ろっかな~。

135ml
135ml

そういえば、画像を一気に切り抜いてくれるツールを作ったのを思い出したわ!

今回はそのツールを紹介するぜ!

リサちゃん
リサちゃん

うわ、出た! 展開速いパターン!

ツールの紹介

Anaconda Promptで動かしていきます。

まず、切り抜きたい、トリミングしたい画像たちが入っているフォルダを指定します。

画像がないフォルダを選ぶとスクリプトは何もなく終了です。

1度選んだ範囲で全てトリミングするか、毎回トリミングする範囲を選んでトリミングするかを選びます。今回は「1」にします。(まあ、「1」が出来ることが今回のスクリプトの真骨頂なので。)

表示されているディレクトリがWindowsなのに「/」区切りになっているのが気になりますが、まあ、一旦進んでみましょう。

トリミングした後のファイルを保存するフォルダの名前を入力します。今回は「トリミング後」にします。

入力すると、実際にトリミングする画面になります。画面サイズは決めておらず、縦長の画像なので、最初はこんな風に歪みます。(デフォルトの画面サイズは設定できるんですかねえ? まあ、使えればいいので、これで良いですが。)

画面も縦長にすれば、まあ見れる感じになりました。

そして、下の4つのスライダーを動かすと、実際にトリムする範囲を指定できます。

上限が青の線、下限がオレンジの線、左限が緑の線、右限が赤の線です。

範囲を選んだら、ウインドウを×ボタンで閉じます。

すると・・・・、できない!!!

なぜ、できないんだ~。っていう過程はとりあえず置いておきます。実はここが日本語になってるのが原因だったりします。

直して正常に動いたものが以下になります。「このディレクトリを見て確認してね。」的なメッセージが出てきて、トリミングした画像たちも保存されています。

ソース貼りました。

ソースはライブラリとして、以下のリポジトリのLandmasterLibraryに入っています。

GitHub - Landmaster135/Pyclone-Tornado
Contribute to Landmaster135/Pyclone-Tornado development by creating an account on GitHub.

特に気をつけたところ

ここでは、ソースを組むに当たって気をつけたところを記載しています。

ディレクトリをWindowsの「\」で区切る。

以下、ソースの抜粋部分です。

DirEditor.py

def DecideNowDir():
    '''
    nowDir     : String absolutely directory default folder
    nowDirPath : String absolutely path selected folder
    '''
    nowDir = os.path.abspath(os.path.dirname(__file__))
    nowDirPath = filedialog.askdirectory(initialdir=nowDir)

    # Discrimination whether Windows or Mac.
    pf = platform.system()
    if pf == 'Windows': # OS is Windows
        nowDirPath = nowDirPath.replace('/', '\\')
    print("Folder's Absolutely Path: {quotation}{folderpath}{quotation}".format(quotation='"',folderpath=nowDirPath))
    return nowDirPath

該当箇所は、filedialog.askdirectory()の部分で、これで選択されたファイルのディレクトリはなぜかWindowsでもMacでも”/”区切りとなってしまうみたいなのです。

それで、後続処理に問題が出るかどうかは調べていませんが、どうにも気持ち悪いのでWindowsで動かした時は文字の置換処理が動くようにしています。

ディレクトリに日本語が入っていると処理を行わずに強制終了させる。

以下、ソースの抜粋部分です。

ImageEditor.py

def TrimImage(trimmed_img_ext):
    '''
    folderList       : List of file filtered with extension in the selected folder.
    selectTimes      : String of times to input.
    extracted_dir    : String absolutely path of directory has selected file.
    img              : Dictionary of pixels of image. (img [height] [width] [color channel])
    trimmed_img      : Dictionary of pixels of image.
    trimmed_img_ext : String of extension of trimmed_img.
    trimmed_img_name : String of filename of trimmed_img.
    '''
    fileList = FileListGetter.GetFileList(DirEditor.DecideNowDir(),trimmed_img_ext)

    # Error Handling
    if len(fileList) == 0:
        print('\nImageEditor exits because of no target files.')
        sys.exit(0)

    # Error Handling
    checkStr = re.compile('[\\a-zA-Z0-9\-\_\.\-\s\:\~\^\=]+')
    if checkStr.fullmatch(fileList[0]) == None:
        print('\nImageEditor exits because of the directory containing shift-jis character.')
        sys.exit(0)

    selectTimes = input('What times do you choosing? ("1" or "every"): ')
    while selectTimes != '1' and selectTimes != 'every':
        selectTimes = input('Retry. ("1" or "every"): ')
    extracted_dir = DirEditor.MakeDirectory(fileList[0])

 

2個目の「Error Handling」の部分になります。

僕も、この記事を書くために動かして気づいたのですが、この画像切り抜きに使用しているOpenCVというモジュールは、なんと指定したディレクトリに日本語(ちゃんと言うとShift_JIS)が入っていると、画像を読み取れません・・・。

OpenCVを作った人たちは、Shift_JISを文字だと思っていないようです・・・。日本語を文字だと思っていないようです・・・。

この不具合を回避するために、Pillowやnumpyなどのモジュールを使って処理する方法がありましたが、そこまでして日本語を使いたいわけではないので、いっそのこと、このモジュールを使う時には日本語のディレクトリは使用できないようにエラー処理を行わせるようにしました。

実装方法としては、ソース内で正規表現で指定した文字だけで表記されているディレクトリだけを使用できるようにしています。

# Error Handling
checkStr = re.compile('[\\a-zA-Z0-9\-\_\.\-\s\:\~\^\=]+')
if checkStr.fullmatch(fileList[0]) == None:
    print('\nImageEditor exits because of the directory containing shift-jis character.')
    sys.exit(0)

おしまい

135ml
135ml

まあ、今回はこんなところだ。

まさか、日本語が使えない仕様になっていたとは思わなんだ~。以前にMacで動かしたときは普通に動いていたからWindowsのせいかと思ったけど、そういや英数字しか使ってなかったような気がする・・・。

リサちゃん
リサちゃん

そういうこともあるのね。なんかもう日本語で生活するのが嫌になるような出来事ですな・・・。

135ml
135ml

本当だな~。英語に親しんだ生活をしていかなければならんな。

リサちゃん
リサちゃん

まじかあ。自己紹介とかどうすればいいんだろ。「那由多 リサ」ってどう言うんだろ?

135ml
135ml

普通に” Lisa Nayuta”でいいんじゃね?

ちなみに、1那由多は”novemdecillion”、1000那由多は”vigintillion”と英語では言うらしいよ。

リサちゃん
リサちゃん

おおー、かっこいいじゃん。

これから、”I’m novemdecillion Lisa.”って言いまくるわ。

135ml
135ml

「私は、10の60乗人のリサです。」???

まあいいや、言いまくった結果を後で聞いてみよう。

以上になります!

このツールでトリミングした後は・・・・

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

こちらのツールもPythonで動くものになっています!

おまけ

ペンギン
ペンギン

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

GitHub - Landmaster135/Pyclone-Tornado
Contribute to Landmaster135/Pyclone-Tornado development by creating an account on GitHub.
リサちゃん
リサちゃん

また、この前段として、以下の記事もあります。よければ、見てみて下さい!

コメント

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