はじめに
みなさん、Gemini では物体検出もできることをご存知ですか?
近年のマルチモーダル大規模言語モデル(VLM)は、画像理解と自然言語生成を組み合わせた高度な推論が可能になっています。
Gemini 3 もその一つであり、画像内の要素を言語的に説明したり、対象物のおおよその位置を推定することができます。
今回は、Gemini API を用いた python による自然言語での物体検出の方法を紹介します。
※本記事で扱う「物体検出」は、YOLO 等の従来型 CV モデルによる検出とは異なり、Gemini のマルチモーダル生成能力を用いて自然言語に基づき物体位置を推定する手法を指しています。
物体検出とは
物体検出は、画像内に含まれる対象オブジェクトを検出し、それぞれの位置(バウンディングボックス)とクラスラベルを出力する視覚認識タスクです。
Gemini 3 Flash で物体検出してみる
適当な画像を用意して Gemini 3 flash で日本の硬貨を検出ができるか試してみます。
今回は、日本の硬貨で検証してみました。
from google import genai
from google.genai import types
from PIL import Image
from pydantic import BaseModel, Field
class BBox(BaseModel):
box_2d: list[int] = Field(
...,
description="0-1000に正規化された座標[y1, x1, y2, x2]",
min_length=4,
max_length=4,
)
label: str = Field(..., description="オブジェクトのラベル名")
client = genai.Client(
vertexai=True,
project=GC_PROJECT_ID,
location="global",
)
image = Image.open(image_path)
system_prompt = "バウンディングボックスと対象のラベルをJSON配列として返してください。"
user_prompt = "日本の硬貨をすべて検出して"
response = client.models.generate_content(
model="gemini-3-flash-preview",
contents=[image, user_prompt],
config=types.GenerateContentConfig(
system_instruction=system_prompt,
temperature=0.2, # ランダム性を下げるために 0 付近に設定する
thinking_config=types.ThinkingConfig(thinking_level=types.ThinkingLevel("minimal")),
media_resolution=types.MediaResolution.MEDIA_RESOLUTION_LOW,
response_mime_type = "application/json",
response_schema=list[BBox],
),
)
※可視化する実装
import json
from PIL import ImageDraw, ImageFont
# 日本語を表示するためにフォントを設定する
font_path = "/Library/Fonts/Arial Unicode.ttf" # Mac の場合
font = ImageFont.truetype(font_path, size=10)
def plot_bounding_boxes(img: Image.Image, bbox_list: list) -> None:
"""バウンディングボックスをプロットする
Args:
img: 画像
bbox_list: バウンディングボックスのリスト
"""
width, height = img.size
draw = ImageDraw.Draw(img)
colors = [
"red",
"green",
"blue",
"yellow",
"orange",
"pink",
]
label_to_color = {}
color_index = 0
for bounding_box in bbox_list:
label = bounding_box.get("label", "unknown")
# まだこのラベルに色が割り当てられていない場合、新しい色を割り当てる
if label not in label_to_color:
label_to_color[label] = colors[color_index % len(colors)]
color_index += 1
color = label_to_color[label]
# 座標変換(正規化座標 0-1000 -> 画素数)
abs_y1 = int(bounding_box["box_2d"][0] / 1000 * height)
abs_x1 = int(bounding_box["box_2d"][1] / 1000 * width)
abs_y2 = int(bounding_box["box_2d"][2] / 1000 * height)
abs_x2 = int(bounding_box["box_2d"][3] / 1000 * width)
# 座標の最小・最大を保証
x_min, x_max = min(abs_x1, abs_x2), max(abs_x1, abs_x2)
y_min, y_max = min(abs_y1, abs_y2), max(abs_y1, abs_y2)
# ボックスの描画
draw.rectangle(((x_min, y_min), (x_max, y_max)), outline=color, width=3)
# ラベルテキストの描画
if "label" in bounding_box:
draw.text((x_min + 5, y_min + 2), label, fill=color, font=font)
img.show()
plot_bounding_boxes(image, json.loads(response.text))
結果
実装のポイント
Gemini 3 で画像認識を行う場合のポイントを紹介します。
- Gemini のレスポンスに含まれる座標は 0-1000 に正規化された座標です。
実際の画像に適用する場合は、画像サイズに合わせて変換する必要があります - 単純な画像認識タスクでは基本的に思考は必要ないので、thinking_level を low や minimal(gemini 3 flashのみ)に設定するのがおすすめです。
思考レベルを下げることでコストや応答時間を小さくすることが可能です - Gemini 3 では一つのリクエスト内でファイルごとに画像認識時の最大トークン数を指定できるようになりました。
そのため、複雑な画像や高精度に判定したい画像に対しては解像度を高く設定し、それ以外には低く設定することが可能です
Gemini による物体検出が向かないケース
一方で Gemini 等の VLM が適さないケースについても簡単に触れておきます。
VLM では従来の CV モデルと異なり、検出結果がプロンプトや温度設定に依存し、決定的な出力が難しいです。
また、API では応答に時間がかかる等の理由から以下のケースでは利用が難しいです。
- 高精度・高再現性が求められる物体検出
- リアルタイム処理
- 製造・医療・自動運転などのミッションクリティカル用途
まとめ
本記事では、Gemini 3 のマルチモーダル生成能力を用いて、自然言語ベースで物体の位置を推定する手法を検証しました。
このアプローチの最大の利点は、学習用アノテーションや専用モデルの準備なしに、柔軟な物体検出を実現できる点です。
比較的簡単なタスクの場合や正確性をある程度欠いても良い場面では Gemini による物体検出を検討してはいかがでしょうか。

