❇️

🖼️ FastAPI 実践入門:第八歩目で学ぶ 画像処理とPillowの活用

に公開

🧩 はじめに

第八歩目では、アップロードされた画像に対して「画像処理」を加える方法を学習します。ここでは、Pythonの画像処理ライブラリ「Pillow(PIL)」を使って、サムネイルの生成、画像のリサイズ、フォーマットの変換、グレースケール化、画像の形式変換など、WebアプリやAPIでよく使われる実用的な処理を詳細に解説します。
Pillowは軽量でありながら非常に強力な機能を持っており、FlaskやFastAPIといったWebフレームワークと組み合わせることで、画像処理をAPIの一部として取り入れることができます。

🔧 Pillowのインストールと基本の使い方

まずは、Pillowライブラリをインストールします。これはPython Imaging Library(PIL)のフォークであり、画像の読み込み・変換・保存などを簡単に行えます。

pip install pillow

次に、画像を読み込んでリサイズや保存を行う基本的なコード例を紹介します。

from PIL import Image

image = Image.open("sample.jpg")
image = image.resize((300, 300))
image.save("resized.jpg")

このコードでは、300×300ピクセルに画像をリサイズし、新しいファイルとして保存します。

🗂️ FastAPIで画像を処理するエンドポイント

FastAPIとPillowを組み合わせて、アップロードされた画像に対して処理を加えるAPIエンドポイントを実装します。以下の例では、サムネイル画像を作成して保存しています。

from fastapi import FastAPI, File, UploadFile
from PIL import Image
import shutil

app = FastAPI()

@app.post("/thumbnail/")
async def generate_thumbnail(file: UploadFile = File(...)):
    with open(f"temp_{file.filename}", "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)

    image = Image.open(f"temp_{file.filename}")
    image.thumbnail((128, 128))
    thumb_path = f"thumb_{file.filename}"
    image.save(thumb_path)

    return {"message": "サムネイルを作成しました", "thumbnail": thumb_path}

このサンプルでは、アップロードされた画像ファイルを一時的に保存し、その後サムネイル(128×128)に変換し、新しいファイルとして保存しています。

🎨 フォーマット変換やグレースケール処理

Webアプリでは、画像のフォーマット変換(例:JPEG→PNG)や色空間変換(カラー→グレースケール)も頻繁に求められます。以下の例では、カラー画像をグレースケールに変換し、PNG形式で保存しています。

@app.post("/convert/")
async def convert_image(file: UploadFile = File(...)):
    with open(f"temp_{file.filename}", "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)

    image = Image.open(f"temp_{file.filename}")
    gray = image.convert("L")  # グレースケール
    converted_path = f"gray_{file.filename}.png"
    gray.save(converted_path, format="PNG")

    return {"message": "変換しました", "output": converted_path}

この処理を活用すれば、プロフィール画像をモノクロにする、PDF生成前の下処理を行うなど多彩な用途が考えられます。

🧪 処理済み画像の返却(Base64またはResponse)

生成された画像をフロントエンドに返却する方法はいくつかあります。最もシンプルなのは FileResponse を使ってファイルとして返す方法です。

from fastapi.responses import FileResponse

@app.get("/get-thumb/{filename}")
async def get_thumbnail(filename: str):
    return FileResponse(path=f"thumb_{filename}", media_type="image/jpeg")

これにより、API経由で画像をダウンロード可能なリンクとして提供できます。画像の加工後に直接プレビューを返すようなケースでも活用できます。

🧰 応用:複数画像の一括処理やフォーマット選択

複数の画像を同時に受け取り、それぞれに処理を行うAPIも実装可能です。例えば、以下のようにすることで複数の画像に対して一括でグレースケール化処理を適用できます。

from typing import List

@app.post("/batch-convert/")
async def batch_convert(files: List[UploadFile] = File(...)):
    converted_files = []
    for file in files:
        with open(f"temp_{file.filename}", "wb") as buffer:
            shutil.copyfileobj(file.file, buffer)

        image = Image.open(f"temp_{file.filename}")
        gray = image.convert("L")
        out_path = f"gray_{file.filename}.png"
        gray.save(out_path, format="PNG")
        converted_files.append(out_path)

    return {"converted": converted_files}

このようなバッチ処理は、大量の画像を一括変換するツールや業務システムの一部として活用できます。

🎯 まとめ

  • Pillowを使えば、FastAPIアプリでサムネイル作成や画像フォーマット変換が簡単に実装できます。
  • アップロードされた画像は、必ずバリデーションや一時保存処理を組み合わせて安全性を担保しましょう。
  • 処理後の画像はAPI経由で直接返却したり、静的ファイルとして提供することでフロントエンドとの連携も容易になります。
  • 今回紹介した一括処理やフォーマット変換の応用によって、業務用アプリやCMSでも十分に利用できる構成が構築可能です。

株式会社ONE WEDGE

【Serverlessで世の中をもっと楽しく】 ONE WEDGEはServerlessシステム開発を中核技術としてWeb系システム開発、AWS/GCPを利用した業務システム・サービス開発、PWAを用いたモバイル開発、Alexaスキル開発など、元気と技術力を武器にお客様に真摯に向き合う価値創造企業です。
https://onewedge.co.jp/

Discussion