[アスペクト比維持]Pythonで複数の画像を一括リサイズする方法

スポンサードリンク
Python
過去の自分
過去の自分

送られてきた画像の解像度が高すぎて重いから、小さくしたい…。
Pythonで複数のファイルを一括でリサイズする方法は無いの?

今の自分
今の自分

あります!
「アスペクト比(縦横比)を変えずにリサイズする方法」
できるだけわかりやすく解説いたします。

【著者情報】
Python歴3年。
入社2年目の春に先輩が突然トンズラし、業務を半分肩代わりするハメに…。
今までの1.5倍の仕事をこなせるはずもなく、苦しむ毎日。
業務効率化を模索中にPythonと出合う。
業務とPythonの相性が良く、2倍以上の効率化を実現。現在も効率化を進行中。

スポンサードリンク

Pythonで複数の画像をアスペクト比を維持したまま一括リサイズする方法

「Pillow」「for文」を使って一括処理します。
まずは「全コード」と「実行結果」をお見せします。

全コード

少し長いですが、後ほど各ブロックに分けて解説いたします。

from PIL import Image
import os

input_folder = 'C:/Utatane/img'
output_folder = 'C:/Utatane/resize_img'

for filename in os.listdir(input_folder):
    input_path = os.path.join(input_folder, filename)
    output_path = os.path.join(output_folder, filename)
    
    if os.path.isfile(input_path) and filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')):
        img = Image.open(input_path)
        
        width, height = img.size
        
        if width > height:
            new_width = min(width, 500)
            new_height = int(height * (new_width / width))
        else:
            new_height = min(height, 500)
            new_width = int(width * (new_height / height))
        
        resized_img = img.resize((new_width, new_height))
        
        resized_img.save(output_path)
        print(f"{filename} をリサイズして保存しました")

実行結果

事前準備

  • Pillowのインストール

画像ファイルを編集するには「Pillow」のインストールが必要です。

Pillowのインストール方法

pillowを初めて使用する場合は、下記コードを入力・実行して、インストールしてください。

pip install Pillow

Pillowを使用したことがある場合は、このインストール作業は不要です。

解説

※わかりやすさを重視しております。厳密には解釈が異なる場合がありますことをご了承ください。

インポート

from PIL import Image
import os

上記コードにて、「Pillow」と「os」をインポートしています。
「Pillow」は、画像の編集で使用し、「os」はファイルの取得で使用します。

<注意>
「Pillow」をインポートする場合、「PIL」と記述します。
「Pillow」ではありませんのでご注意ください。

取り込みフォルダ・出力フォルダの指定

次に、「取り込みフォルダ」と「出力フォルダ」を指定します。

input_folder = 'C:/Utatane/img'
output_folder = 'C:/Utatane/resize_img'

「取り込みフォルダ」はリサイズしたい画像ファイルが入っているフォルダを指定しましょう。
「出力フォルダ」は「取り込みフォルダ」とは別のフォルダを指定することで、元データが消えません。

  • 取り込みフォルダ:input_folder
  • 出力フォルダ:output_folder

今回は上記のような名前の変数にしましたが、変数名は何でも構いません。
分かりやすい名前をつけてください。

変数名には一部使えない文字があります。
詳細は下記記事をご参考ください。

右辺にはフォルダのフルパスを記述してください。
実際のフォルダを開いて、アドレスバーからパスをコピーしてくるのが無難です。
その際、「¥」は「/」に置き換えてください。

ファイルのフルパスを作成

for filename in os.listdir(input_folder):
    input_path = os.path.join(input_folder, filename)
    output_path = os.path.join(output_folder, filename)

上記コードにて、取り込みフォルダからファイルの一覧を取得し、ファイル名込みのフルパスを作成しています。

<コード6行目:ファイル一覧を取得>
a.jpg
b.jpg
c.jpg

<コード7行目:取り込みファイルのフルパスを作成(次項で使用)>
(前項で指定した取り込みフォルダ+ファイル名)
C:/Utatane/img/a.jpg
C:/Utatane/img/b.jpg
C:/Utatane/img/c.jpg

<コード8行目:出力ファイルのフルパスを作成(出力時に使用)>
(前項で指定した出力フォルダ+ファイル名)
C:/Utatane/resize_img/a.jpg
C:/Utatane/resize_img/b.jpg
C:/Utatane/resize_img/c.jpg

【listdir()】
フォルダ内のファイル一覧を取得する時に使います。

【join】
パスを結合するときにつかいます。
今回は、「C:/Utatane/img/」と「a.jpg」を結合して、「C:/Utatane/img/a.jpg」にしています。

for文の詳細は下記記事をご参考ください。

ファイルの取り込み

    if os.path.isfile(input_path) and filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')):
        img = Image.open(input_path)

上記コードにてファイルの取り込みを行っています。

前項で作成した取り込みファイルのフルパスを確認し、
ファイルの拡張子が「png、jpg、jpeg、gif」のどれかなら、変数「img」にファイルが取り込まれます。
この4種類の拡張子以外なら取り込まれずスキップされます。

たまに「JPG」など拡張子が大文字になっていることがあるため、
今回は取り込まれた画像ファイルの拡張子を小文字にして照合しています。
(実際に出力されるのは大文字のまま)

【lower()】
ファイル名を小文字にします。
今回は拡張子を小文字にして、指定した拡張子と照合しています。

【endswith()】
拡張子を指定します。

ファイルの縦・横サイズを取得

        width, height = img.size

上記一行にて、画像サイズの縦・横サイズを取得しています。

  • width:横方向のサイズ(横幅)が取得される
  • height:縦方向のサイズ(高さ)が取得される

リサイズ

        if width > height:
            new_width = min(width, 500)
            new_height = int(height * (new_width / width))
        else:
            new_height = min(height, 500)
            new_width = int(width * (new_height / height))

        resized_img = img.resize((new_width, new_height))

上記コードにて、画像サイズをリサイズしています。
前項で取得した「width」「height」を使って比較します。

<コード15~17行目>
width(画像の横幅)がheight(画像の高さ)より大きければ、widthを500にして、
widthと同じ縮小率でheightも縮小。
※この「500」は任意の数値に変更してください。

<コード18~20行目>
それ以外(heightの方が大きい)なら、heightを500にして、
heightと同じ縮小率でwidthも縮小。
※この「500」は任意の数値に変更してください。

<コード21行目>
画像のサイズを「新しいwidth」と「新しいheight」に変更

コードの16行目と19行目にmin()が付いています。
min()の効果により、画像の「width」と「height」がどちらも500より小さい場合、
リサイズは行われずそのままとなります。

出力

あとは前項でリサイズした画像を出力するだけです。

        resized_img.save(output_path)
        print(f"{filename} をリサイズして保存しました")

リサイズ画像を出力フォルダに保存します。
output_pathは「C:/Utatane/resize_img/a.jpg」などが入ります。

25行目のprintは、リサイズされたことをわかりやすくするため記述しています。
省いても構いません。

最後に再度実行結果を見てみましょう。

「b.jpg」を見ていただくとわかりやすいかと思います。
widthが「1000」から「500」に縮小され、半分になっています。
併せてheightも「200」から「100」というように半分になっていることがわかります。

「c.jpg」のように、「width」「height」両方とも500を超えていない画像はそのままとなっています。

スポンサードリンク

うまく動作しない場合の対処法

エラーが出る

FileNotFoundError:指定されたパスが見つかりません

実際に無いフォルダを指定した場合に出るエラーです。
構文のパス名が間違っている可能性がありますので、
フォルダのアドレスバーからパスをコピーし、構文に貼り付けて見比べてみてください。

○○ is not defined

今まで出てきていない変数などを処理しようとした時に出るエラーです。
変数名などが間違っていないかチェックしましょう。

詳しい解説は、下記記事をご参考ください。

その他のエラー

その他のエラーが出た場合は、エラー文をコピーしてNETで検索してみましょう。

スポンサードリンク

最後に

Pythonでアスペクト比(縦横比)を変えずに画像を一括リサイズする方法を解説いたしました。

当ブログでは、Pythonに関する情報を配信しております。
この記事がわかりやすいと感じた方は、他の記事も読んでいってください。

挫折せずにPythonを独学で学習する方法は特におすすめです。

最後までお読みいただき、ありがとうございました。がんばってください!

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