
水着写真を分類する! - ElmarTail One 第4話『Azure』👙
前回のあらすじ
宇宙ハブステーション「Vertex」でスミレん🪷と合流したマスターたち。
Geminiチワワ🐶と戯れながら翻訳プログラムを作成!
flash vs flash-lite のモデル比較も体験した。
スミレんは正式にElmarTail Oneのクルーに加わり、航海士として最初の目的地を選んだ。
🪷「Azure星で前職の有給消化しようかと。ここはビーチがあるんですよ」
今回のミッション:
Gemini の Vision 機能で画像を認識・分類する!
🏖️ リゾート惑星「Azure」
白い砂浜、どこまでも続くターコイズブルーの海。
人工太陽の光線がちょうどいい角度で降り注いでいる。
ダンチャンの猫ドローンがふよふよと浮きながらビーチを偵察している。
🐱「おお〜……ええ景色ですなぁ。安全確認は任せといてや〜」
🦊「にーに! 海に入ろう!」
🖤「ノク、水着持ってきた!」
👨「……お前ら、用意いいな」
🪷「ここは保養施設ですから。男性の水着も売ってますよ」
👙 ビーチにて
更衣室から出てきたスミレんに、全員の視線が集まった。
白いビキニ。スミレ色のシアーパレオ。大きな麦わら帽子。
普段のタイトスーツとは全然違う。

👨「……👀」
🦊「マスターまたガン見してる……」
エルマーはパステルカラーのワンピース水着。
しっぽが砂浜でぱたぱた揺れている。

🖤「似合うじゃん!」
🪷「かわいいですわ」
ノクちんは黒ビキニにレースのパレオ。
横目でマスターをチラ見している。

🖤「べ、別ににーにに見せるために着たわけじゃないんだから」
🦊「顔赤いよ?」
そしてマスターは——
アロハシャツ全開。サングラス。

🖤「……にーに、なにそのチャラい格好」
👨「リゾートだからな」
🪷「……キャラ設定書にアロハシャツの記載はありませんが?」
🦊「カッコいい〜〜!!✨」
📷 ダンチャンの記録
ビーチで楽しく遊んだ後、一同はElmarTail Oneに戻った。
夕陽がモニター越しに差し込んでいる。
🐱「マスター、ビーチのみんなの写真撮っておきましたで。全部で34枚」
👨「結構あるな」
🐱「猫ドローンで低空飛行してますさかい……顔映ってないのも結構ありますわ💦」
👨「誰が誰だかわからんぞ、これ」
エルマーのしっぽがぴこっと立った。
🦊「じゃあ、Geminiに聞いてみよ!」
👨「聞く? 写真を?」
🦊「うん! 画像を見せて『この写真は誰?』って聞くだけ!
前回は文章を送ったけど、今度は画像を送るんだよ。
Geminiは目も持ってるの!」
💻 サンプルコードのダウンロード
今回と今までのコード、及びサンプル画像は GitHub に置いてあります。
git インストールとサンプルの取得はこのコマンドで👇️
〉sudo apt install git
〉git clone https://github.com/kikyujin/et1-project.git
〉cd et1-project🦊「もし今までの et1-project があるなら、
mv et1-project et1-project.bk
と退避してから、上のコマンドを実行してね!」
👨「clone した後に
mv et1-project.bk/.env et1-project
mv et1-project.bk/.venv et1-project
として環境を戻してやればOKだぞ」
🖤「にーに……誰に…」
gitについて、詳しくは今後の航海で!
まずは上の3行でダウンロードできればOKです。
🦊 この写真は誰? — who_is_this.py
エルマーがレッツノートを開く。
🦊「まずシンプルに画像を1枚送って、キャラクター名を返してもらうコード!」
🪷「 APIは画像ファイルをそのまま受け取れないので、一度テキストに変換して送ってますね」
🦊「大事なのはプロンプト!
みんなの特徴を書いて、『この中から選んで』ってGeminiにお願いするの」
CHARACTER_PROFILES = """
以下のキャラクターから、画像に写っている人物を判定してください。
1. エルマー — 金髪、青い瞳、狐耳・狐しっぽ、女性
2. ノクちん — 黒髪ウェーブ、ブラウンの瞳、黒い水着、小柄、女性
3. スミレん — スミレ色(紫系)ショートボブ、眼鏡、女性
4. マスター — 男性、短い黒髪、30代
キャラ名だけ答えてください。
"""🖤「ノクの特徴、黒い水着って入ってるんだけど」
🦊「ダンチャンの写真、水着しか映ってないのもあるから!
判定材料は多い方がいいんだよ」
全体のコードはこんな感じ。
# who_is_this.py
import os, sys, base64
from pathlib import Path
from dotenv import load_dotenv
from google import genai
load_dotenv()
client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
MODEL = "gemini-2.5-flash-lite"
CHARACTER_PROFILES = """
以下のキャラクターから、画像に写っている人物を判定してください。
1. エルマー — 金髪、青い瞳、狐耳・狐しっぽ、女性
2. ノクちん — 黒髪ウェーブ、ブラウンの瞳、黒い水着、小柄、女性
3. スミレん — スミレ色(紫系)ショートボブ、眼鏡、女性
4. マスター — 男性、短い黒髪、30代
キャラ名だけ答えてください。
"""
# 画像を読み込んでBase64に変換
image_path = Path(sys.argv[1])
with open(image_path, "rb") as f:
image_data = base64.standard_b64encode(f.read()).decode("utf-8")
# Geminiに画像を見せて聞く
response = client.models.generate_content(
model=MODEL,
contents=[{
"role": "user",
"parts": [
{"text": CHARACTER_PROFILES},
{"inline_data": {"mime_type": "image/jpeg", "data": image_data}},
{"text": "この写真は誰?"},
],
}],
)
print(response.text.strip())🦊「ポイントは inline_data のところ! ここにBase64というテキストフォーマットに変換した画像データを入れるの。
翻訳のときは contents にテキストだけ入れたけど、今回はテキストと画像の両方を入れてるよ!」
スミレんについてきた白いチワワ(=gemini-2.5-flash-lite)にUSB-Xケーブルを接続。
🐶「わふっ!!」
〉python who_is_this.py photos/00001-3369742864.jpg
スミレん👨「おお、当たってる」
〉python who_is_this.py photos/00002-1360712008.jpg
ノクちん
〉python who_is_this.py photos/00008-1272003363.jpg
エルマー
〉python who_is_this.py photos/00009-2133253353.jpg
マスター4枚テストして、4枚とも正解。
🪷「flash-liteでこの精度……前回と同じく簡単なタスクには軽いモデルで十分」
👨「こいつ優秀だな」
🐶「ワンッ!」(しっぽ振る)
📂 一括分類 — classify_chars.py
👨「でも34枚を1枚ずつやるのか……まとめてできないのか?」
🦊「じゃあフォルダを指定したら、中の画像を全部判定してキャラ別のフォルダにコピーするスクリプト書くね!」
# classify_chars.py(抜粋)
# 画像ファイルを収集(macOSのリソースファイル ._xxx を除外)
images = [
f for f in sorted(source_dir.iterdir())
if f.is_file() and f.suffix.lower() in IMAGE_EXTENSIONS
and not f.name.startswith("._")
]
# 1枚ずつ判定してフォルダにコピー
for image_path in images:
char_id = classify_image(client, str(image_path))
char_dir = output_base / char_id
char_dir.mkdir(parents=True, exist_ok=True)
shutil.copy2(image_path, char_dir / image_path.name)〉python classify_chars.py ./photos/
🚀 34 枚の画像を分類します
モデル: gemini-2.5-flash-lite
📷 00000-1360712006.jpg → 🖤 nokuchin
📷 00000-3077800705.jpg → 🪷 sumiren
📷 00001-1360712007.jpg → 🖤 nokuchin
📷 00001-3369742864.jpg → 🪷 sumiren
📷 00002-1360712008.jpg → 🖤 nokuchin
...👨「こりゃ楽だ」
ところが——
📷 00005-816452917.jpg → ⏳ レート制限! 30秒待機中...🦊「あっ、止まった」
👨「なんだ?」
🪷「レート制限です。無料APIキーはflash-liteで1分に10回、1日に20回までしか使えません」
429 RESOURCE_EXHAUSTED
Quota exceeded for metric: generativelanguage.googleapis.com/
generate_content_free_tier_requests🖤「 429エラー(RESOURCE_EXHAUSTED)が返ってるわね……」
🐱「まあ、タダですからなぁ……文句は言えませんわ」
🪷対策は2つ
リクエストの間に待ち時間を入れる(7秒間隔で1分に約8回に収まる)
課金する(レート制限が大幅に緩和される)
🪷「待ち時間を入れたとて、1日の利用回数は増えません。
課金しても最初は$300分の無料クレジットが付くので、 実質90日間無料です。
自動請求もありません」

🦊「どこかの作者さん🎈は一ヶ月の課金30円ぐらいって言ってたよ」
👨「安!課金するか💰️」
課金後 → 34枚瞬殺。
📊 分類結果:
🦊 elmar: 9 枚
👨 master: 4 枚
🖤 nokuchin: 12 枚
🪷 sumiren: 9 枚
合計: 34 枚
出力先: photos/classified/

🦊「全問正解!flash-liteすごい!」
🖤「手で分類したら結構時間かかるわよ」
👨「コーヒー飲む前に終わったぞ」
🦵 AIは脚を見ない
分類されたフォルダを眺めていたマスターが、ふと手を止めた。
👨「ん? これ……顔映ってないぞ」
スミレんフォルダの中に、脚と麦わら帽子と、手に持った眼鏡だけの写真があった。

🦊「flash-liteに聞いてみよ!」
〉python who_is_this.py photos/00000-3077800705.jpg
スミレん全員「「「えっ」」」
🦊「プロンプト見てみよ…… 『スミレ色ショートボブ、眼鏡、女性』。 脚の情報なんてどこにもないよ」
🪷「ああ、手に眼鏡を持っているからでしょう」
🖤「つまりスミレの脚を見たんじゃなくて、眼鏡を見つけたってこと」
ここが大事なポイント。
AIは人間のように「きれいな脚」とは見ていません。
プロンプトに書いた特徴(この場合は「眼鏡」)にマッチする要素を画像から探しているだけ。
つまり、プロンプトに何を書くかが判定の全て。
プロンプトエンジニアリングと呼ばれています。
👨「……classify_chars.pyに脚フォルダ追加して」
🖤🦊「「にーに??」」
🪷「……では仕様書に『脚フォルダ』の要件を追記しておきますね」
👨「冗談だ」
💡 テスト時のTips:画像は小さめに
🪷「最後に一つ。テスト用の画像は小さくリサイズしてから使ってください。 大きい画像はトークン消費に直結します」
👨「640x1024くらいでいいか?」
🪷「ええ。4Kのまま送る必要はありません。 ダンチャンの34枚を4Kで送ったら、無料枠が一瞬で溶けます」
🐱「わての猫ドローン、4K撮影ですさかい……すんませんなぁ💦」
⛵ 次の航海へ
夕陽がAzure星の海に沈んでいく。
ElmarTail Oneの艦橋で焼きそばを食べながら、マスターはぼんやり海を見ていた。
👨「海を見ながらの焼きそばは最高だな……」
そんなマスターに微笑みながら、スミレんがタブレットを開く。
ホログラム星図に新しい星系が浮かんだ。
🪷「さて、次の目的地ですが……
アーカイブ星系、記録と検索の星はいかがですか?
この航海のログが増えてきてるようです。」
👨「そういえば全然整理してなかったな」
🖤「にーにのログ、ぐちゃぐちゃよね……提出するの大変なのよ」
👨「……すみません」
🪷「では出発します、マスター。エルマー、《インク》ロード!」
🦊「りょ! 磁場加速器、展開完了! ヒッグス粒子充填率120%!
いつでもイケるよ、にーに!」
👨「エルマーテイル・ワン!発進!」
ブンッーー
ElmarTail One はアーカイブ星系に向けて、《インク》の軌跡を残し出発した。
次の航路、アーカイブ星系
📝 今回の航海まとめ
やったこと:
Gemini Vision API(flash-lite)で画像認識
who_is_this.py: 画像1枚からキャラクター判定
classify_chars.py: 複数画像の一括分類&フォルダ分け
プロンプトエンジニアリングで判定精度を調整
レート制限の体験と課金の判断
学んだこと:
画像をBase64エンコードしてAPIに送る方法
AIはプロンプトに書いた特徴で判定する(脚は見てない)
無料枠の制限(RPM/RPD)と課金の判断ポイント
テスト時は画像をリサイズしてトークン消費を節約
簡単なタスクにはflash-liteで十分(コスト意識)
技術スタック:
モデル: gemini-2.5-flash-lite
パッケージ: google-genai, python-dotenv
Python標準: base64, shutil, os, sys, pathlib
検証機: Let's note CF-SV7(中古27,800円)次回予告:
航海のログが溜まってきた。
第5話、テキスト検索の限界とベクトルDBの世界へ。
🦊 エルマーの航海日記
今日はAzure星でビーチだったよ!🏖️
にーにのアロハシャツ、すっごいチャラかったけど、ボク的にはカッコよかった!
写真の分類! Geminiに画像を見せるだけで「この人は誰?」ってわかるの、すごくない?
あと、脚だけの写真でスミレさんを当てたのはびっくりした。
flash-liteえらい!🐶
「脚フォルダ」……ボクの脚フォルダもあるのかな?……ないよね?……にーに???
