GEMINI LABEN
NANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定ですNANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定です
記事一覧/API / SDK
API / SDK/2026-05-09中級

Gemini API に画像を送る前に Pillow で縮小しておくべき理由

Gemini API のマルチモーダル入力で iPhone の写真をそのまま投げているとレイテンシも料金も静かに膨らみます。Pillow で前処理するだけで結果が変わった実例と、私が普段使っている縮小関数をまとめました。

gemini-api279multimodal24python103pillow2cost-optimization21

スマートフォンで撮った写真を、何の前処理もせず Gemini API に投げていた時期がありました。商品画像から名前と推定価格を JSON で取り出す個人プロジェクトで、レスポンスが返るまで毎回 8〜12 秒かかります。気になって usage_metadata を確認したら、画像 1 枚あたり 1,500 トークン前後を消費していました。

Pillow で長辺を 1024px に縮小してから送るように変えたところ、同じ精度のままレスポンスは 2〜3 秒、画像由来のトークンは 258 前後にまで下がりました。ここではなぜそうなるのかと、私が落ち着いた前処理パターンを共有します。

画像はファイル単位ではなく「タイル単位」で課金される

最初に押さえておきたいのは、Gemini API が画像を「ファイル 1 枚」ではなく「タイル」という単位に分割して処理することです。

Google の公式ドキュメントによれば、Gemini 2.5 系のモデルは画像を 768×768 ピクセルのタイルに切り、タイルごとに 258 トークン換算で料金を計算しています。1024×1024 の画像なら 4 タイル、4032×3024 ピクセル(iPhone 標準解像度)の写真なら 24 タイル前後です。

つまり、4032×3024 の写真をそのまま送ると、1 リクエストあたり 6,000 トークン以上を画像だけで使ってしまうことになります。Pillow で 1024px に縮小すれば 1〜4 タイル(258〜1,032 トークン)に収まり、商品識別やシーン理解の用途では精度はほぼ落ちません。

Gemini API のコスト最適化を体系的に整理した別記事 ではキャッシュ戦略の話題が中心ですが、画像の前処理は「キャッシュより先にやるべき節約」だと感じています。

なぜクライアント側での縮小が効くのか

API 側でも内部的に縮小処理は走りますが、それはあくまで上限を超えたときの救済です。クライアント側で先に整えておくと、3 つの効果がはっきり出ます。

  1. トークン消費が減る — タイル数が直接料金に効くので、長辺を半分にすればトークンも 1/4 に近づきます
  2. アップロードが速くなる — 4032×3024 の JPEG は数 MB ですが、1024px に縮小すれば 200KB 前後。家庭用回線で 2〜3 秒の差が出ました
  3. API 側の処理時間も短くなる — タイル数が減るぶん、モデルのビジョンエンコーダ側の前処理も軽くなります

私が触っているプロジェクトでは、平均レスポンスタイムが 9.2 秒から 2.7 秒へ、月間 API 料金は約 1/5 になりました。

私が普段使っている前処理関数

Pillow の thumbnail() を使うと、アスペクト比を保ちながら長辺を指定サイズに縮小できます。resize() だと縦横比を自分で計算する必要がありますが、thumbnail() は inplace で完結する点が便利です。

from PIL import Image, ImageOps
from io import BytesIO
 
def prepare_image_for_gemini(
    src_path: str,
    max_side: int = 1024,
    jpeg_quality: int = 85,
) -> tuple[bytes, str]:
    """Gemini API に渡すための画像前処理。
 
    - 長辺 max_side ピクセルに縮小(アスペクト比は保持)
    - JPEG として再エンコード(透過は捨てる)
    - 戻り値: (バイト列, mime_type)
    """
    with Image.open(src_path) as img:
        # EXIF の向きに合わせて回転(Gemini は EXIF を読まない)
        img = ImageOps.exif_transpose(img)
        # RGBA / P モードは RGB に変換(JPEG にするため)
        if img.mode != "RGB":
            img = img.convert("RGB")
        # アスペクト比を保ちながら長辺を max_side に
        img.thumbnail((max_side, max_side), Image.Resampling.LANCZOS)
        buf = BytesIO()
        img.save(buf, format="JPEG", quality=jpeg_quality, optimize=True)
        return buf.getvalue(), "image/jpeg"
 
# 使い方
from google import genai
 
client = genai.Client(api_key="YOUR_API_KEY")
image_bytes, mime = prepare_image_for_gemini("photo.jpg", max_side=1024)
 
resp = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=[
        {"inline_data": {"mime_type": mime, "data": image_bytes}},
        "この商品の名前と推定価格を JSON で返してください。",
    ],
)
print(resp.usage_metadata)
# 例: prompt_token_count=292  (画像 258 + テキスト 34)

Image.Resampling.LANCZOS は Pillow 9.1.0 以降の書き方で、それ以前のバージョンでは Image.LANCZOS を使ってください。ImageOps.exif_transpose() を入れているのは、Gemini が EXIF タグを読まないため、向きを先に補正しておかないと「横向きに撮った写真」を縦扱いで投げてしまうからです。これも私が一度ハマった箇所でした。

「画像が小さすぎて精度が落ちる」境目を知る

縮小しすぎると逆に認識精度が落ちます。私が手元の 200 枚程度の商品画像で実験したところ、用途別の目安は次のようになりました。

  • 商品ラベル・OCR が目的のとき: 長辺 1280px 以上を保つ(細かい文字が潰れない)
  • 物体識別・カテゴリ分類: 長辺 1024px で十分
  • シーン理解・全体的な状況把握: 長辺 768px でも精度はほぼ変わらない
  • 顔の特徴を扱う用途(プライバシーに配慮した範囲のみ): 長辺 1280px 以上

OCR 用途では、文字部分のみクロップしてから縮小するとさらに精度が安定します。pytesseract でラフな文字領域を検出し、その周辺だけ送るパターンを併用しています。

画像が認識されないときの診断記事 と組み合わせて読むと、mime_type の付け方や向きのトラブルも合わせて整理できます。

File API か inline_data か

20MB を超える画像は inline_data では送れず、File API 経由になります。ただし実用上、長辺 1024px に縮小しておけばインラインで困ることはほぼありません。

私が File API を選ぶのは、

  • 同じ画像を複数回のリクエストで使い回したいとき(File API は 48 時間キャッシュされる)
  • 動画や大容量 PDF など、inline_data では収まらないファイルを扱うとき

この 2 つに限定しています。単発の画像認識ならインラインのほうが round trip が 1 回少なく、体感も速いです。

リクエストごとのトークン消費を見える化したい場合は、usage_metadata の記録パターンをまとめた別記事 も参考にしてみてください。

サーバー側に任せると料金は減らない

少し細かい話ですが、Gemini はリクエストが大きすぎる画像でも内部で縮小処理を行います。ただし、これはあくまで上限を超えたときの「救済」であって、料金を抑える仕組みではありません。トークンはあくまで「サーバー側で正規化された後のタイル数」で計算されるため、API 任せにしていても課金額は下がりません。

タイル数を本当に減らしたいなら、API に渡す前にすでに小さい画像を用意するしかありません。これが、本記事をわざわざ書こうと思った理由です。

バッチ処理ではこの差が大きく出ます。私が触っているプロジェクトでは、数百枚の商品画像をまとめて処理するスクリプトが、前処理を入れる前は 3 時間で約 $4 かかっていました。prepare_image_for_gemini を挟むようにしてからは、40 分で $1 を切るようになっています。

自分のプロジェクトで効果を確認する

「本当にトークンが減るのか」を自分の環境で確かめたい場合は、次のような小さなスクリプトで十分です。

for size in (4032, 1280, 1024, 768):
    img_bytes, mime = prepare_image_for_gemini("test.jpg", max_side=size)
    resp = client.models.generate_content(
        model="gemini-2.5-flash",
        contents=[
            {"inline_data": {"mime_type": mime, "data": img_bytes}},
            "この画像に何が写っていますか?",
        ],
    )
    print(size, len(img_bytes), resp.usage_metadata.prompt_token_count)

実際の入力画像を 1 枚使い、サイズだけを変えて回すと、トークン数が階段状に下がるのが見えるはずです。私はこの結果を見て、すべてのマルチモーダル経路に前処理を入れる決心がつきました。

次に試してみてほしいこと

手元のプロジェクトでまだ生の写真を送っているなら、prepare_image_for_gemini を 1 関数挟むだけで構いません。次の月末に届く請求書を見比べると、効果は静かに、しかしはっきり現れるはずです。

お読みいただきありがとうございました。

シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

API / SDK2026-07-02
Gemma 4 ローカル推論と Gemini API の使い分けで月額¥32,000を¥9,000台にした — ハイブリッドルーターの本番設計
月額¥32,000のGemini APIコストを¥9,000台まで下げたハイブリッド推論構成の記録です。ルーティング設計・Python実装・本番の落とし穴に加え、2026年7月のGemma 4 API提供開始を踏まえた構成見直しの指針もまとめました。
API / SDK2026-05-18
Gemini Vision で壁紙アプリの自動カテゴリ分類を実装した話
個人開発の壁紙アプリで Gemini Vision API を使い、画像の自動カテゴリ分類を実装した実体験です。精度改善のプロセスと、公式ドキュメントには載っていない落とし穴、GPT-4o Vision とのコスト比較までまとめました。
API / SDK2026-05-16
Gemini Vision で壁紙アプリのカテゴリ自動分類を試した — 精度と落とし穴の実記録
壁紙アプリ(累計5,000万DL超)の運営者が Gemini Vision を使って画像カテゴリ自動分類を実装。精度67%→87%への改善プロセスと、個人開発者が実運用で感じた限界を具体的に紹介します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →