Pythonで画像をトリミング・回転させる

プログラミング

Pythonによる画像処理:トリミングと回転

Pythonは、その豊富なライブラリによって、画像処理タスクを効率的に実行するための強力なツールとなります。本稿では、特に画像編集の基本的な操作である「トリミング」と「回転」に焦点を当て、それぞれの処理方法と関連する概念について、Pillowライブラリ(Python Imaging Libraryのフォーク)を用いた実装例とともに解説します。

トリミング:画像の特定領域の切り出し

トリミングとは、画像の一部分を切り出して、新たな画像を作成する操作です。画像の不要な部分を取り除いたり、被写体を強調したりする際に用いられます。Pillowライブラリでは、Imageオブジェクトのcrop()メソッドを使用してトリミングを実行します。このメソッドは、切り出す領域を左上隅の座標と右下隅の座標で指定するタプルを受け取ります。

トリミングの原理と座標系

Pillowにおける座標系は、画像の左上隅を原点(0, 0)とし、X軸は右方向、Y軸は下方向を正とします。crop()メソッドに渡すタプルは、(left, upper, right, lower)の形式で指定します。ここで、

  • left: 切り出す領域の左端のX座標
  • upper: 切り出す領域の上端のY座標
  • right: 切り出す領域の右端のX座標(この座標は含まれません)
  • lower: 切り出す領域の下端のY座標(この座標は含まれません)

例えば、画像の左上隅から幅100ピクセル、高さ150ピクセルの領域を切り出したい場合、(0, 0, 100, 150)を指定します。これは、左上隅の座標が(0, 0)、右下隅の座標が(100, 150)となる長方形を指定していることになります。ただし、rightlowerの座標は、その座標「まで」であり、その座標自身は切り出し範囲に「含まれない」点に注意が必要です。そのため、意図したサイズになるように座標を調整する必要があります。

Pillowによるトリミングの実装例

以下に、Pillowを使用して画像をトリミングするPythonコードの例を示します。


from PIL import Image

# 画像を開く
try:
    img = Image.open("sample.jpg") # 実際の画像ファイル名に置き換えてください
except FileNotFoundError:
    print("エラー: 画像ファイルが見つかりません。")
    exit()

# トリミングする領域を指定 (左上隅(0,0)から幅100, 高さ150の領域)
# rightとlowerは含まれないため、幅100px、高さ150pxの領域にするには (100, 150) を指定
crop_area = (0, 0, 100, 150)

# 画像をトリミング
cropped_img = img.crop(crop_area)

# トリミングした画像を保存
cropped_img.save("cropped_sample.jpg")

print("画像が正常にトリミングされ、cropped_sample.jpgとして保存されました。")

このコードでは、まずImage.open()で画像を読み込みます。次に、トリミングしたい領域をタプルcrop_areaで定義し、img.crop()メソッドを呼び出してトリミングを実行します。最後に、cropped_img.save()で結果を保存しています。

回転:画像の向きの変更

回転は、画像を一定の角度で回す操作です。写真の向きを修正したり、デザイン上の意図で画像を回転させたりする際に利用されます。Pillowライブラリでは、Imageオブジェクトのrotate()メソッドを使用して回転を実行します。このメソッドは、回転角度を度数法で指定する引数を受け取ります。

回転の原理と角度指定

rotate()メソッドは、指定された角度で画像を反時計回りに回転させます。例えば、90度を指定すると、画像は左に90度回転します。正の値を指定すると反時計回り、負の値を指定すると時計回りに回転します。

回転処理を行う際、画像のサイズやアスペクト比が変わる可能性があります。特に、90度、180度、270度以外の角度で回転させた場合、元の画像の四隅が画像の外部に出てしまうため、画像の全体を収めるためには画像のサイズを拡大するか、一部が切り取られることになります。rotate()メソッドには、expandという引数があり、これをTrueに設定すると、回転後の画像全体が収まるように画像のサイズが自動的に調整されます。デフォルトはFalseで、この場合、回転によって生じる画像の隙間は背景色(デフォルトは黒)で埋められます。

Pillowによる回転の実装例

以下に、Pillowを使用して画像を回転させるPythonコードの例を示します。


from PIL import Image

# 画像を開く
try:
    img = Image.open("sample.jpg") # 実際の画像ファイル名に置き換えてください
except FileNotFoundError:
    print("エラー: 画像ファイルが見つかりません。")
    exit()

# 画像を90度反時計回りに回転
rotated_img_90 = img.rotate(90)
rotated_img_90.save("rotated_90_sample.jpg")
print("画像が90度回転され、rotated_90_sample.jpgとして保存されました。")

# 画像を45度時計回りに回転 (expand=Trueでサイズを自動調整)
rotated_img_45_expand = img.rotate(-45, expand=True)
rotated_img_45_expand.save("rotated_45_expand_sample.jpg")
print("画像が45度時計回りに回転(サイズ自動調整)され、rotated_45_expand_sample.jpgとして保存されました。")

# 画像を45度時計回りに回転 (expand=Falseでサイズ固定、隙間は黒で埋まる)
rotated_img_45_no_expand = img.rotate(-45, expand=False)
rotated_img_45_no_expand.save("rotated_45_no_expand_sample.jpg")
print("画像が45度時計回りに回転(サイズ固定、隙間は黒)され、rotated_45_no_expand_sample.jpgとして保存されました。")

このコードでは、img.rotate(90)で90度反時計回りに回転させています。また、expand=Trueを指定して、回転後の画像全体が収まるようにサイズを自動調整する例や、expand=Falseでサイズを固定し、隙間が黒で埋まる例も示しています。回転角度は度数法で指定し、負の値を指定すると時計回りの回転となります。

その他の考慮事項と応用

画像フォーマットと互換性

Pillowは、JPEG、PNG、BMP、GIFなど、多くの一般的な画像フォーマットをサポートしています。トリミングや回転を行った画像も、これらのフォーマットで保存することができます。ただし、GIFのようなアニメーション画像の場合、Pillowは通常、最初のフレームのみを処理します。アニメーション全体を処理するには、追加のライブラリや工夫が必要となる場合があります。

リサイズとの組み合わせ

トリミングや回転は、しばしばリサイズ(画像の拡大・縮小)と組み合わせて使用されます。例えば、トリミング後に画像を特定のサイズに合わせたい場合や、回転後に画像のサイズを調整したい場合などです。Pillowでは、resize()メソッドを使用してリサイズを実行できます。


# トリミングした画像を幅200ピクセル、高さ150ピクセルにリサイズ
resized_cropped_img = cropped_img.resize((200, 150))
resized_cropped_img.save("resized_cropped_sample.jpg")

リサイズには、画像の品質を保つための様々な補間アルゴリズム(Image.NEAREST, Image.BILINEAR, Image.BICUBIC, Image.LANCZOSなど)があり、resize()メソッドのresample引数で指定できます。

パフォーマンスとバッチ処理

大量の画像を一度に処理する場合、パフォーマンスが重要になります。Pillowは比較的効率的ですが、さらに高速化するには、NumPyのような数値計算ライブラリと連携させる方法も考えられます。また、特定のディレクトリ内のすべての画像に対してトリミングや回転を適用したい場合は、Pythonのosモジュールやglobモジュールを使用してファイルリストを取得し、ループ処理で各画像に操作を適用するバッチ処理を実装することが一般的です。

エラーハンドリング

画像処理では、ファイルが存在しない、ファイルが破損している、サポートされていないフォーマットであるなど、様々なエラーが発生する可能性があります。try-exceptブロックを使用して、これらのエラーを適切に捕捉し、ユーザーに通知したり、処理を中断したりするなどのエラーハンドリングを実装することが重要です。本稿のコード例でも、FileNotFoundErrorを捕捉しています。

まとめ

PythonとPillowライブラリを使用することで、画像のトリミングと回転といった基本的な画像編集操作を簡単かつ効率的に行うことができます。トリミングではcrop()メソッド、回転ではrotate()メソッドが中心的な役割を果たし、それぞれ座標系や角度指定、expandオプションといったパラメータを理解することが重要です。これらの操作は、写真の整理、Webコンテンツの作成、データ拡張など、多岐にわたる応用が可能です。さらに、リサイズやバッチ処理、エラーハンドリングといった要素を組み合わせることで、より高度で堅牢な画像処理システムを構築することができます。