やったこと
「爪切り」を検出できる物体検出はどれか?
物体検出というと YOLO が定番ですが、Google Cloud にも選択肢が2つあります。
- Cloud Vision API(OBJECT_LOCALIZATION)
- Gemini(Vertex AI)— 実はバウンディングボックスを出せる
この3つにまったく同じ写真を見せて、何をどこまで検出できるか比べてみました。
使った写真はこれです。床に キーボード・マウス・スマホ・爪切り を並べて自分で撮りました。
なぜこの4つかというと、YOLO が標準で検出できるのは COCO データセットの80クラスだけだからです。
keyboard・mouse・cell phone は80クラスに入っていますが、爪切りは入っていません。
つまり爪切りは「学習済みクラスの壁」を試すための刺客です。
結果を先に
| 検出対象 | Cloud Vision API | YOLO26n | Gemini 2.5 Flash |
|---|---|---|---|
| キーボード | 0.90 | 0.95 | 0.96 |
| マウス | 0.80 | 0.93 | 0.94 |
| スマホ | 0.81 | 0.62 | 0.95 |
| 爪切り | ✗ | ✗(remote 0.41 と誤検出) | 0.93 |

※ YOLO はライブラリが注釈画像を出力。Vision API と Gemini は JSON(座標)が返るので、それをもとに枠を描画
Gemini だけが4つ全部を検出し、しかも「爪切り」と日本語ラベルで返してきました。
3方式それぞれの叩き方と結果
Cloud Vision API
Google Cloud の画像分析 API です。
ラベル検出・OCR・顔検出など画像系の機能が一通り揃っていて、今回はそのうちの 物体検出(OBJECT_LOCALIZATION) を使います。
モデルの用意も学習も不要で、REST に画像を投げるだけ。認証はアクセストークンで済みます。
TOKEN=$(gcloud auth print-access-token)
curl -s \
-H "Authorization: Bearer ${TOKEN}" \
-H "x-goog-user-project: YOUR_PROJECT" \
-H "Content-Type: application/json" \
-d @request.json \
https://vision.googleapis.com/v1/images:annotate
request.json はこの形です。<base64画像> の部分には base64 -i photo.jpg(macOS の場合)の出力を入れます。
{
"requests": [{
"image": {"content": "<base64画像>"},
"features": [{"type": "OBJECT_LOCALIZATION", "maxResults": 20}]
}]
}
手で埋めるのは大変なので、作るならワンライナーが楽です。
echo "{\"requests\":[{\"image\":{\"content\":\"$(base64 -i photo.jpg)\"},\"features\":[{\"type\":\"OBJECT_LOCALIZATION\",\"maxResults\":20}]}]}" > request.json
結果は3件。爪切りは検出されませんでした。

※ Vision API は JSON(座標)を返すので、レスポンスをもとに枠を描画しています
Vision API のラベルは「Computer keyboard」「Mobile phone」のような汎用カテゴリです。
カテゴリの語彙はユーザー側で追加できないため、今回試した限りでは爪切りのようなマイナーな物体は拾えませんでした。
一方でモデルの管理が一切不要で、月1,000ユニットまでの無料枠(執筆時点)があるのは強いです。
YOLO26n
リアルタイム物体検出の定番オープンソースモデルです。
クラウドではなく手元のマシンで推論します。今回は執筆時点の最新世代 YOLO26 の最小モデル(nano)を使いました。
ultralytics を入れれば数行で動きます。
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
results = model("desk_items.jpg")
results[0].save(filename="annotated.jpg") # 注釈付き画像も一発
キーボード 0.95、マウス 0.93、スマホ 0.62 と、COCO クラス内の3つは検出できました。
面白いのは爪切りです。物体があること自体は認識しているのに、「remote(リモコン)0.41」と誤検出しました。
COCO 80クラスに爪切りは存在しないので、「爪切り」と答えることは原理的にできません。
取りうる挙動は「何も検出しない」か「80クラスのどれかとして検出する」かの2つで、今回は後者になりました。
クラスにない物体は「検出されない」だけでなく「別の何かとして誤検出される」こともある、という学習済みクラスの壁の実例になりました。
代わりに、推論は完全ローカル・無料・高速です。
手元の Mac(CPU 推論)で計測したら1枚あたり**平均0.05秒(46ms)**でした。リアルタイム動画処理ができるのは3つの中で YOLO だけです。
ハマりどころ: YOLO26 は ultralytics 8.4系以降が必要です。
手元の 8.3.247 では yolo26n.pt がエラーなく読み込めるのに出力がデタラメ(画像全体を refrigerator 0.59 と検出)になり、しばらく悩みました。
pip install -U ultralytics で正常化します。
Gemini 2.5 Flash(Vertex AI)
Google の生成 AI(マルチモーダル LLM)です。
物体検出の専用サービスではありませんが、画像を渡してプロンプトで頼むと、バウンディングボックス座標を返せます。
Vertex AI 経由なら Google Cloud の IAM 認証(アクセストークン)が使えるので、API キーの管理も不要です。
TOKEN=$(gcloud auth print-access-token)
curl -s \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d @request.json \
"https://aiplatform.googleapis.com/v1/projects/YOUR_PROJECT/locations/global/publishers/google/models/gemini-2.5-flash:generateContent"
request.json は「画像+プロンプト」を parts に並べるだけです。
{
"contents": [{
"role": "user",
"parts": [
{"inlineData": {"mimeType": "image/jpeg", "data": "<base64画像>"}},
{"text": "画像内のすべての物体を検出してください。JSON配列で出力し、各要素は label(日本語の物体名)、confidence(0-1)、box_2d([ymin, xmin, ymax, xmax] を 0-1000 に正規化)を含めてください。JSONのみ出力してください。"}
]
}],
"generationConfig": {"responseMimeType": "application/json"}
}
物体検出専用のパラメータは何もありません。
この text がプロンプトのすべてで、generationConfig の responseMimeType で出力を JSON に固定しているだけです。
返ってきた JSON がこちら。
[
{"label": "スマートフォン", "confidence": 0.95, "box_2d": [15, 17, 459, 282]},
{"label": "爪切り", "confidence": 0.93, "box_2d": [108, 392, 336, 537]},
{"label": "マウス", "confidence": 0.94, "box_2d": [63, 674, 334, 848]},
{"label": "キーボード", "confidence": 0.96, "box_2d": [486, 30, 867, 979]}
]

※ Gemini も JSON(座標)を返すので、レスポンスをもとに枠を描画しています
爪切りを 0.93 で検出。座標もかなり正確です。
固定の学習済みクラス一覧を持たず、検出対象を言葉で自由に指定できる(オープンボキャブラリ)のが決定的な違いです。
ラベルの言語すらプロンプトで指定できます(今回は日本語指定)。
ただし LLM なので指示が無視されることもあります。
3回試したうち1回は、日本語指定にもかかわらず英語ラベル(nail clipper 等)で返ってきました。
検出自体は3回とも4物体すべて安定していたので、出力を厳密に使う場合はラベルの揺れへの対処が必要です。
コスト比較
| 方式 | 料金 |
|---|---|
| Cloud Vision API | 月1,000ユニットまで無料(執筆時点。以降は従量課金) |
| YOLO | 無料(ローカル実行) |
| Gemini 2.5 Flash | 今回の1リクエストは入力1,874+出力753トークン(執筆時点の料金で概算1円未満) |
どれも検証レベルなら誤差みたいなコストです。
使い分けの整理
| こういうとき | これ |
|---|---|
| リアルタイム動画・大量画像・オフライン | YOLO(ただし検出したい物が COCO 80クラスにあるか要確認) |
| 一般的な物体をサクッと、インフラ持ちたくない | Cloud Vision API |
| ニッチな物体・日本語ラベル・柔軟な指示(「危険物だけ」等) | Gemini |
今回いちばんの発見は、「物体検出タスクに LLM を使う」のがもはや現実的な選択肢だということです。
従来なら爪切りを検出したければ、爪切りの画像を集めてアノテーションしてファインチューニング…という世界でした。Gemini ならプロンプト1行です。
一方で Gemini のレスポンスは実測で3〜5秒(3回計測: 4.9秒 / 3.2秒 / 2.7秒)。
YOLO の約0.05秒とは60〜100倍の差なので、リアルタイム性が必要なら YOLO 一択のままです。
「速さの YOLO、手軽さの Vision API、語彙の Gemini」という住み分けでした。
まとめ
- 学習済みクラスにある物体は3方式とも検出できた
- クラスにない物体(爪切り)を検出できたのは Gemini だけ。YOLO は「リモコン」と誤検出した
- Gemini はラベルの言語や検出対象をプロンプトで指定できる(ただし LLM なので出力に揺れはある)
- コストは3方式とも検証用途ならほぼ無料
- リアルタイム性が必要なら今も YOLO 一択
「何を検出したいか」が COCO 80クラス(あるいは Vision API の語彙)に収まるかどうかが、最初の分岐点になりそうです。

