Pythonで写真や画像の大きさ変更、切り抜き方法(サンプルコード付)

スポンサーリンク
Python/DeepLearning

どうもこんにちは!

最近プログラミング熱が上がってきました、みやしんです!

この記事ではpythonで写真や画像の大きさ(画素数)を変更したり、一部を切り抜いたりする方法をご紹介したいと思います。

特に画像分類や物体検出のディープラーニングを行うときのデータセット作成で必要となってくるテクニックと思いますので、皆さん是非チャレンジしてみてください。

では早速、やっていきましょう!

スポンサーリンク

フォルダー構成

今回は下記のようなフォルダー構成で画像を加工していきます。

Pathlibでフォルダーパスを扱う

python3.4以降でpathlibというライブラリが導入されています。

まずはメインクラスのPathをインポートします。

from pathlib import Path

今回、カレントフォルダを「PictureProcess」とした時に、下記のようにフォルダを指定します。

input_folder = Path('input')  #inputフォルダー
output_folder = Path('output')   #outputフォルダー

Pillowを使った画像処理の基本

PillowはPythonの画像処理ライブラリです。Pillowでは下記のような編集ができます。

  • 画像フォーマットの変換
  • 画像の拡大や縮小
  • 画像の切り取り
  • 画像の色調整
  • 画像への文字の書き込み 等

今回は、画像の拡大や縮小、画像の切り取りを行います。

まずは、下記のようにPILモジュールからImageクラスをインポートします。

from PIL import Image

例えば、画像ファイルを開くときは、

img = Image.open('ファイル名')

のように記述します。

それでは順にコードを確認していきたいと思います。

サンプルコード説明

必要なライブラリ(Path, Image)をインポートします。

from pathlib import Path
from PIL import Image

各変数を定義します。

# 最終的に調整したい画像のサイズ:box_size = 320 (縦横のpixel数)
box_size = 320
# inputする画像を入れるフォルダのパス
input_folder = Path('input')
# outputされた(サイズ調整された)画像が保存されるフォルダのパス
output_folder = Path('output')
# outputフォルダーを作成。exist_ok = Trueとすると既存のフォルダーを対象としてもエラーにならない。(dirはディレクトリの略、ディレクトリ=フォルダー)
output_folder.mkdir(exist_ok=True) 

画像の大きさを調整する。

# .glob()でフォルダー内のファイル名を返す。('*.jpg')でjpgのファイルを指定。
for f in input_folder.glob('*.jpg'):
  # jpgファイルを開く
    img = Image.open(f)
    # img.sizeで幅と高さタプル
    width, height = img.size
    # 最終的な画像サイズ(box_size=320)が画像短辺の何倍か比率を算出
    ratio = box_size / min(img.size)
    # img.resize(幅, 高さ)で画像の大きさを変更する。幅と高さはintにキャスト(変換)しないとエラーになる。
    resized_img = img.resize((int(width * ratio), int(height * ratio)))

ここまでの処理で下記のように画像のサイズを変えています。(input画像が320pixより大きい場合は縮小します)

続いて、長方形の画像を320×320の大きさに切り抜きます。

    # width > heightの場合
    if width > height:
        # resized_img.size[0]は幅、resized_img.size[1]は高さ
        # 画像を切り抜く大きさを求める
        strip_size = resized_img.size[0] - box_size
        # img.crop((left, top, right, bottom))で画像を切り抜く
        cropped_img = resized_img.crop((
            strip_size / 2,
            0,
            resized_img.size[0] - strip_size / 2,
            resized_img.size[1]
        ))

    # width =< heightの場合
    else:
        # resized_img.size[0]は幅、resized_img.size[1]は高さ
        # 画像を切り抜く大きさを求める
        strip_size = resized_img.size[1] - box_size
        # img.crop((left, top, right, bottom))で画像を切り抜く
        cropped_img = resized_img.crop((
            0,
            strip_size / 2,
            resized_img.size[0],
            resized_img.size[1] - strip_size / 2
        ))

最後にファイルに保存します。

    # output_folder.joinpath()でoutput_folderのパスにjoinpath()のカッコ内のパスを連結。
    # f.nameでファイル名
    save_path = output_folder.joinpath(f.name)
    # .saveで保存する
    cropped_img.save(save_path)
    # img.close()で画像ファイルを閉じる
    img.close()  

サンプルコード

サンプルコードの載せますので、コピペして使ってください^^

from pathlib import Path
from PIL import Image

# 最終的に調整したい画像のサイズ:box_size = 320 (縦横のpixel数)
box_size = 320
# inputする画像を入れるフォルダのパス
input_folder = Path('input')
# outputされた(サイズ調整された)画像が保存されるフォルダのパス
output_folder = Path('output')
# outputフォルダーを作成。exist_ok = Trueとすると既存のフォルダーを対象としてもエラーにならない。(dirはディレクトリの略、ディレクトリ=フォルダー)
output_folder.mkdir(exist_ok=True) 

# .glob()でフォルダー内のファイル名を返す。('*.jpg')でjpgのファイルを指定。
for f in input_folder.glob('*.jpg'):
  # jpgファイルを開く
    img = Image.open(f)
    # img.sizeで幅と高さタプル
    width, height = img.size
    # 最終的な画像サイズ(box_size=320)が画像短辺の何倍か比率を算出
    ratio = box_size / min(img.size)
    # img.resize(幅, 高さ)で画像の大きさを変更する。幅と高さはintにキャスト(変換)しないとエラーになる。
    resized_img = img.resize((int(width * ratio), int(height * ratio)))

    # width > heightの場合
    if width > height:
        # resized_img.size[0]は幅、resized_img.size[1]は高さ
        # 画像を切り抜く大きさを求める
        strip_size = resized_img.size[0] - box_size
        # img.crop((left, top, right, bottom))で画像を切り抜く
        cropped_img = resized_img.crop((
            strip_size / 2,
            0,
            resized_img.size[0] - strip_size / 2,
            resized_img.size[1]
        ))

    # width =< heightの場合
    else:
        # resized_img.size[0]は幅、resized_img.size[1]は高さ
        # 画像を切り抜く大きさを求める
        strip_size = resized_img.size[1] - box_size
        # img.crop((left, top, right, bottom))で画像を切り抜く
        cropped_img = resized_img.crop((
            0,
            strip_size / 2,
            resized_img.size[0],
            resized_img.size[1] - strip_size / 2
        ))

    # output_folder.joinpath()でoutput_folderのパスにjoinpath()のカッコ内のパスを連結。
    # f.nameでファイル名
    save_path = output_folder.joinpath(f.name)
    # .saveで保存する
    cropped_img.save(save_path)
    # img.close()で画像ファイルを閉じる
    img.close() 

【更に実力UP!】自分が買って良かったオススメ本

僕が買ってみて良かったオススメ本をご紹介します。

<おススメな点>

  • コードがしっかり記載してあって、そのままコードを使える
  • 説明が分かりやすく初心者から使える
  • 機能を分解してあって使い回しがきく
  • 画像、csvやEXCELの操作、Webスクレイピングなど、すぐ使えるものばかり
  • 作業の自動化を目的に書かれているので普段の仕事に活きる

<おススメな人>

  • python初心者から中級者
  • 普段の作業を効率化したい人
  • pythonを勉強し始めたばかりで、何かに役立てたいと思っている人

実際にPythonを使えるようになってくると、どんどん楽しくなってきます!

合わせて読みたい

Matplotlibを使った図形の描画方法なんかも参考になると思います!ご興味のある方はこちらをご参照ください。

物体検出も面白いです!

yoloの物体検出モデルをファインチューニングしたい方はこちらをどうぞ

その他にもプログラミングやIT関係の情報に興味のある方はこちらをご参考にしてみてください。

404 NOT FOUND | みやしんのプログラミングスキル通信
Pythonの基礎から実用的なスキル & 便利なライブラリ紹介

以上になります。最後まで読んでくださりありがとうございました。

Python/DeepLearning
スポンサーリンク
記事が良かったらSNSでシェアを宜しくお願いします!
みやしんをフォローすると役立つ情報がいっぱいにゃ!
スポンサーリンク

コメント

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