okpy

Pythonエンジニア兼テックリーダーが、多くのプロジェクトとチーム運営から得た実践的な知識を共有するブログです。

Pythonで画像リサイズやフィルター加工、まだ手作業で消耗してる?

Pythonで画像リサイズやフィルター加工、まだ手作業で消耗してる?

📝 TL;DR (3行要約)

Pillowは、Pythonで画像を自在に操るための定番ライブラリです。 画像の読み込み、リサイズ、トリミング、フィルター適用、保存といった基本的な操作を、驚くほど簡単なコードで実現できます。 Webアプリのサムネイル生成から、機械学習用のデータ拡張まで、画像が関わるあらゆるタスクを自動化するために広く使われています。


1. 🤔 一体Pillow (PIL)とは何?(核心的な役割と主な使用例)

プログラミングの世界に足を踏み入れたばかりの皆さん、こんにちは!今日は、Pythonで「画像」を扱う楽しさを教えてくれる、魔法のようなライブラリ「Pillow」をご紹介します。

核心的な役割: Python界の万能デジタルフォトエディター 🎨

皆さんは、PCで写真のサイズを変えたり、色合いを調整したり、文字を入れたりする時、どんなツールを使いますか?おそらく、PhotoshopGIMP、あるいはOS標準の写真アプリなどを使うでしょう。これらは、マウスで直感的に操作できる素晴らしいGUI(グラフィカル・ユーザー・インターフェース)ツールです。

Pillowは、まさにこれらの画像編集ツールが持つ機能を、Pythonのコードで実行できるようにしたライブラリです。言わば、「Pythonの世界における、デジタル版の万能フォトエディター」だと考えてみてください。

「でも、なぜわざわざコードで?マウス操作の方が簡単じゃない?」

そう思うのも当然です。しかし、ここにプログラミングの真価があります。もし、あなたが1000枚の画像すべてを「横幅300ピクセルにリサイズ」し、「右下に会社のロゴを入れる」という作業を頼まれたらどうでしょう?手作業では、日が暮れてしまいますよね。

Pillowを使えば、たった数十行のコードを書くだけで、コンピュータにこの退屈な作業をすべて自動で、しかも一瞬で終わらせてもらうことができます。これがPillowが解決する問題の核心です。単発の作業ではなく、繰り返し発生する、あるいは他のシステムと連携する必要がある画像処理を「自動化」するために作られたライブラリなのです。

主な使用例: Pillowが輝く瞬間 ✨

では、具体的にどんな場面でPillowは真価を発揮するのでしょうか?最も代表的な例を3つ見ていきましょう。

  1. Webアプリケーションのサムネイル画像生成 ブログやSNSECサイトなどを想像してください。ユーザーがスマートフォンで撮影した高解像度の写真をプロフィール画像としてアップロードしたとします。その巨大な画像を、一覧ページでそのまま表示したらどうなるでしょう?ページの読み込みは遅くなり、レイアウトも崩れてしまいます。 ここでPillowの出番です。ユーザーが画像をアップロードした瞬間に、サーバーサイドのPythonプログラムがPillowを使って自動的に複数のサイズのサムネイル(小さいプレビュー画像)を生成します。一覧ページでは小さいサムネイルを、クリックしたら中くらいの画像を表示する、といった最適化が簡単に行えるのです。これはWeb開発における必須テクニックの一つです。

  2. 機械学習のデータ拡張 (Data Augmentation) AI、特に画像認識モデルを訓練するには、膨大な量の学習データ(画像)が必要です。しかし、十分な数の画像を用意するのは大変なコストがかかります。 そこでPillowが活躍します。例えば、「猫」の画像が100枚しかない場合でも、Pillowを使えば1枚の元画像から「少し回転させた猫」「左右反転した猫」「明るさを変えた猫」「一部を切り取った猫」といった、微妙に異なる画像をプログラムで大量に生成できます。これをデータ拡張と呼び、AIに多様なパターンの画像を学習させることで、モデルの精度を劇的に向上させることができるのです。

  3. ウォーターマーク(透かし)の一括挿入 あなたが撮影した素敵な写真作品をWebサイトで公開する際、無断転載を防ぐために著作権情報やロゴ(ウォーターマーク)を入れたいと考えるかもしれません。Pillowを使えば、指定したフォルダ内にある全ての画像に対して、同じ位置に、同じデザインのウォーターマークを自動で挿入するスクリプトを簡単に作成できます。これもまた、手作業では考えられないほど効率的な作業です。

このように、Pillowは単純な画像編集にとどまらず、Web開発からAI開発、日常業務の自動化まで、非常に幅広い分野で活躍する、Python開発者にとっての力強い味方なのです。


2. 💻 インストール方法

Pillowのインストールは、他のPythonライブラリと同様にpipコマンド一つで完了します。とても簡単ですよ。 ターミナル(WindowsならコマンドプロンプトPowerShell)を開いて、以下のコマンドを実行してください。

pip install Pillow

これだけで、あなたのPython環境でPillowを使う準備が整いました!


3. 🛠️ 実際に動作するサンプルコード

百聞は一見に如かず。実際にPillowを動かしてみましょう! 以下のコードは、画像を開き、リサイズして白黒に変換し、中央に「Hello, Pillow!」というテキストを描画して、新しいファイルとして保存する、という一連の処理を行います。

準備: このコードを実行する前に、コードと同じフォルダに何か好きな画像ファイルを用意し、input.jpg という名前に変更しておいてください。

# 必要なライブラリの部品をインポート
from PIL import Image, ImageDraw, ImageFont

# --- 1. 画像の読み込み ---
try:
    # 'input.jpg'という名前の画像ファイルを開く
    original_image = Image.open('input.jpg')
    print("✅ 画像の読み込みに成功しました。")
except FileNotFoundError:
    print("❌ エラー: 'input.jpg'が見つかりません。同じフォルダに画像を置いてください。")
    exit()

# --- 2. 画像処理の実行 ---
# 元の画像オブジェクトをコピーして、処理用の新しいオブジェクトを作成
processed_image = original_image.copy()

# アスペクト比を維持したまま、最大サイズを 400x400 ピクセルにリサイズ
processed_image.thumbnail((400, 400))
print(f"🖼️  画像をリサイズしました。新しいサイズ: {processed_image.size}")

# 画像をグレースケール(白黒)に変換
processed_image = processed_image.convert('L')
print("🎨 画像をグレースケールに変換しました。")

# --- 3. テキストの描画 ---
# 描画用のオブジェクトを作成
draw = ImageDraw.Draw(processed_image)

# デフォルトのフォントを読み込む
# (特定のフォントを使いたい場合は ImageFont.truetype("your_font.ttf", size=30) のように指定)
try:
    font = ImageFont.load_default()
    print("🖋️  デフォルトフォントを読み込みました。")
except IOError:
    print("⚠️ デフォルトフォントが読み込めませんでした。テキスト描画をスキップします。")
    font = None

if font:
    # 描画するテキスト
    text = "Hello, Pillow!"

    # テキストの描画サイズを取得
    # Python 3.11以降では textbbox を推奨
    try:
        # (left, top, right, bottom)
        bbox = draw.textbbox((0, 0), text, font=font)
        text_width = bbox[2] - bbox[0]
        text_height = bbox[3] - bbox[1]
    except AttributeError:
        # 古いバージョン用のフォールバック
        text_width, text_height = draw.textsize(text, font=font)


    # テキストを中央に配置するための座標を計算
    img_width, img_height = processed_image.size
    x = (img_width - text_width) / 2
    y = (img_height - text_height) / 2

    # 計算した位置にテキストを描画(色は白=255)
    draw.text((x, y), text, font=font, fill=255)
    print(f"✍️  中央に '{text}' と描画しました。")

# --- 4. 結果の保存と表示 ---
# 処理後の画像をファイルに保存
output_filename = 'output_hello_pillow.jpg'
processed_image.save(output_filename)
print(f"💾 処理後の画像を '{output_filename}' として保存しました。")

# 処理後の画像を画面に表示(環境によっては動作しない場合があります)
processed_image.show()
print("🚀 処理が完了しました!")

このコードを実行すると、コンソールに処理の進捗が表示され、同じフォルダにoutput_hello_pillow.jpgという新しい画像ファイルが作成されているはずです。ぜひ開いて確認してみてください!


4. 🔍 コードの詳細説明

さて、先ほどのサンプルコードが何をしているのか、一つずつ丁寧に見ていきましょう。コードを塊(チャンク)ごとに分解して解説しますね。

インポート文: from PIL import ...

from PIL import Image, ImageDraw, ImageFont

ここでは、Pillowライブラリから今回使う「部品」を取り込んでいます。 - Image: 画像を開いたり、リサイズしたり、保存したりといった、画像本体に関するほとんどの操作を担当する中心的なクラスです。 - ImageDraw: 画像の上に線や図形、そしてテキストを描画するためのツールです。Imageオブジェクトを「キャンバス」として、その上に絵を描くイメージです。 - ImageFont: 描画するテキストのフォントやサイズを指定するためのツールです。

1. 画像の読み込み: Image.open()

try:
    original_image = Image.open('input.jpg')
except FileNotFoundError:
    # ...エラーメッセージ...
  • Image.open('ファイル名') は、指定された画像ファイルを読み込み、Pillowが操作できる「画像オブジェクト」に変換してくれます。このオブジェクトを、私たちは変数 original_image に入れています。
  • try...except FileNotFoundError で囲んでいるのは、もし input.jpg というファイルが存在しなかった場合にプログラムがエラーで停止するのを防ぐための、丁寧なエラー処理です。初心者の方は「プログラムは常に失敗する可能性がある」と考えて、このようにエラー処理を書く癖をつけると良いでしょう。

2. 画像処理の実行: .copy(), .thumbnail(), .convert()

processed_image = original_image.copy()
processed_image.thumbnail((400, 400))
processed_image = processed_image.convert('L')
  • original_image.copy(): 元の画像を直接変更してしまうと、後で元の状態と比較したり、別の処理に使ったりすることができなくなります。そのため、まず .copy() メソッドで画像の複製を作り、これからの処理はその複製に対して行うのが安全なプログラミングの作法です。
  • processed_image.thumbnail((400, 400)): ここがリサイズの核心部です。thumbnailメソッドは、画像の縦横比(アスペクト比)を保ったまま、指定したタプル (幅, 高さ) の中に収まるように画像を縮小してくれます。例えば、800x600の画像にこの処理を適用すると、400x300にリサイズされます。注意点として、thumbnailは元の画像オブジェクトを直接変更する(破壊的メソッド)ため、戻り値はありません。
  • processed_image.convert('L'): convertメソッドは、画像のカラーモードを変換します。引数に 'L' を指定すると、画像をルミナンス(輝度)に変換、つまりグレースケール(白黒)にしてくれます。他にもフルカラーの 'RGB' や、透明度情報を持つ 'RGBA' などがあります。こちらは新しい画像オブジェクトを返す非破壊的なメソッドなので、processed_image = ... の形で結果を再代入しています。

3. テキストの描画: ImageDraw.Draw, draw.text()

draw = ImageDraw.Draw(processed_image)
font = ImageFont.load_default()
# ...座標計算...
draw.text((x, y), text, font=font, fill=255)
  • ImageDraw.Draw(processed_image): グレースケールに変換した画像 processed_image をキャンバスとして、その上に描画を行うための「描画オブジェクト」を draw という変数に作成しています。
  • ImageFont.load_default(): Pillowに組み込まれているシンプルなデフォルトフォントを読み込んでいます。これにより、特定のフォントファイルがPCに無くても、どんな環境でもテキストを描画できます。
  • 座標計算: テキストをど真ん中に描画するために、画像の幅と高さ、そして描画したいテキスト自体の幅と高さを取得し、そこから描画を開始すべき左上の(x, y)座標を計算しています。draw.textbbox はテキストを描画した場合の領域(バウンディングボックス)を取得する便利なメソッドです。
  • draw.text(...): 実際にテキストを描画する命令です。(x, y) で指定した位置に、text の内容を、font を使って、fill=255 の色で描画しています。グレースケール画像では、色は0(黒)から255(白)までの数値で指定するため、255は「白」を意味します。

4. 結果の保存と表示: .save(), .show()

processed_image.save('output_hello_pillow.jpg')
processed_image.show()
  • processed_image.save('ファイル名'): これまでの全ての処理が適用された画像オブジェクトを、新しいファイルとしてディスクに書き出します。Pillowは拡張子から自動的にファイル形式(JPEG, PNGなど)を判断してくれるので非常に賢いです。
  • processed_image.show(): 処理結果をすぐに確認できるよう、画像ビューアを起動して表示してくれます。デバッグや簡単な確認にとても便利な機能です。

5. ⚠️ 注意点またはヒント

Pillowは非常に直感的ですが、初心者がハマりがちなポイントがいくつかあります。ここでは特に重要なものを1つだけ紹介します。

罠: resize()thumbnail() の決定的な違いを理解しよう!

Pillowには画像をリサイズするメソッドとして、主に resize()thumbnail() の2つがあります。これらは似ているようで、挙動が全く異なります。

  • thumbnail( (幅, 高さ) ):

    • アスペクト比を維持します。 これが最大の特長です。
    • 指定したサイズに「収まるように」縮小します。例えば、1000x800の画像に thumbnail((300, 300)) を適用すると、アスペクト比を保ったまま縮小され、最終的なサイズは 300x240 になります。画像が歪むことはありません。
    • 元の画像オブジェクトを直接変更します(in-place)。
  • resize( (幅, 高さ) ):

    • アスペクト比を無視します。 指定したサイズに強制的に変形させます。
    • 1000x800の画像に resize((300, 300)) を適用すると、文字通り 300x300 の正方形の画像になります。元の画像は縦に引き伸ばされたような、歪んだ見た目になります。
    • 新しい画像オブジェクトを返します。

ヒント: Webサイトのサムネイル作成など、画像の見た目が歪んでほしくない場合は、必ず thumbnail() を使いましょう。 一方で、機械学習の前処理などで、全ての画像を特定の固定サイズに無理やり合わせたい、という特殊なケースでは resize() が使われます。用途に応じて正しく使い分けることが、Pillowマスターへの第一歩です。


6. 🔗 一緒に見ておくと良いライブラリ

Pillowで画像処理の基本をマスターしたら、次の一歩として、このライブラリと連携させると非常に強力なツールをご紹介します。

OpenCV (opencv-python)

もしPillowが「デジタルフォトエディター」なら、OpenCVは「コンピュータビジョン(CV)の専門分析ラボ」です。

  • Pillow: 画像のリサイズ、トリミング、色調補正、描画といった「編集」や「加工」が得意です。
  • OpenCV: 顔検出、物体追跡、文字認識(OCR)、AR(拡張現実)など、画像の内容を「認識」したり「解析」したりする高度な機能が満載です。

これらは競合するのではなく、補完しあう関係にあります。例えば、「Pillowで画像を読み込んで適切なサイズに前処理し、その画像をOpenCVに渡して顔がいくつあるか検出する」といった連携が非常に一般的です。 画像処理の世界をさらに深く探求したいなら、次に学ぶべきライブラリとしてOpenCVは最適の選択肢でしょう。


7. 🎉 まとめ

今日一日で、私たちはPythonライブラリ「Pillow」の強力な世界を垣間見ました。もう一度、要点を振り返ってみましょう。

  • PillowはPythonのコードで画像処理を自動化するためのライブラリであること。
  • 画像の読み込み (Image.open)、リサイズ (thumbnail)、色変換 (convert)、描画 (ImageDraw)、保存 (save) といった基本的な操作が、驚くほど簡単なコードで実現できること。
  • Webアプリのサムネイル生成や機械学習のデータ拡張など、実社会の様々な場面で活用されていること。

理論を学ぶだけでは、知識はなかなか身につきません。一番の学習方法は、実際に手を動かしてみることです。

挑戦課題 🏆 さあ、この記事を閉じたら、ぜひ以下の課題に挑戦してみてください!

  1. あなたが持っているお気に入りの写真を用意します。
  2. その写真をPillowで読み込み、250x250ピクセルにリサイズしてみましょう。
  3. 画像にセピア調フィルターをかけてみましょう。(ヒント: セピア調にするには、ピクセル単位での色操作が必要です。「Pillow セピア」などで検索すると、素晴らしい先人たちの知恵が見つかるはずです!)
  4. 画像の右下に、あなたの名前やニックネームを小さな白い文字でウォーターマークとして追加してみましょう。

この課題がクリアできれば、あなたはもうPillow初心者を卒業です! PythonとPillowで、あなたのクリエイティブなアイデアをどんどん形にしていってくださいね。Happy Coding!