Claudeで外観検査の不良品を写真から分類する — 一次仕分けと人の確認
不良品の写真をClaudeに渡し、傷・欠け・汚れなどの不具合モードに分類させる手順です。画像の枚数とサイズの上限、JSONでの返却、人の確認への振り分けまでを扱います。
Claudeに不良品の写真を渡すと、傷・欠け・汚れといった不具合モードの候補を付けて返せます。ただし、使える場面は「一次仕分け」までです。出荷判定を単独で任せる使い方は、公式の制限事項と噛み合いません。
この記事では、Claude APIで写真を1枚ずつ分類し、結果をJSONで受け取り、迷う写真だけを人に回す流れを組みます。画像の枚数やサイズの上限、微細な傷との相性も、公式の数字と記述に沿って書きます。
外観検査でのClaudeの役割は一次仕分けまで
外観検査の現場で欲しいのは、山のような不良品写真に「どの種類の不具合か」というラベルを付ける作業の肩代わりです。数百枚の写真を人が目で見て、傷・打痕・汚れの山に振り分けるのは時間がかかります。
Claudeは画像を読み、言葉にする力を持っています。不具合モードの定義を文章で渡せば、写真ごとに該当しそうなモードを選べます。
一方で、公式の制限事項には次の記述があります。
- 低品質・回転した写真・200ピクセル未満の非常に小さい画像では、誤りや作り話(ハルシネーション)が起こりうる
- 物体の個数は概算で、小さな物体が多数あると正確とは限らない
- 位置や座標の出力は近似値である
- 完全な精度が要るタスクや機微な画像の分析は、人の監督なしに任せない
微細な傷という語は、この制限事項には出てきません。ただ、微小な欠陥は写真の中では「小さく写る対象」になります。その見分けが、縮小や圧縮で崩れやすいのは次節以降で見るとおりです。
そこで運用は2段にします。Claudeが不具合の種類を仮に付け、迷うものや「不良なし」と返したものを人が確かめます。人の目を減らすのではなく、人の目が向く場所を絞る使い方です。
写真を渡す前に押さえる枚数・サイズ・解像度の上限
画像入力には、先に知っておくと設計が楽になる上限があります。
画像入力の主な上限
1リクエストの画像数
100枚 / 600枚
200kトークンのコンテキストのモデルは100枚、それ以外は600枚
1枚の最大寸法
8000×8000px
21枚以上では、より厳しい寸法上限が全画像に適用される
1枚の最大サイズ
10MB
base64エンコード後。BedrockとGoogle Cloudは5MB
claude.ai
20枚 / 10MB
1メッセージあたりの枚数と、1枚あたりのサイズ
検査ラインの写真をAPIで流すなら、効くのは次の3点です。
- 1リクエストに21枚以上を入れると、全画像に厳しい寸法上限が掛かります。超えた画像は
invalid_request_errorで拒否されます。切り抜く前提でも、長辺2000px以下か、21枚未満に収めると安全です - リクエスト全体のサイズ上限は標準のエンドポイントで32MBです。枚数の上限より先にここに達することがあります
- 枚数が多いときは、Files APIでアップロードして
file_idで参照すると、リクエストが膨らみません
対応形式はJPEG・PNG・GIF・WebPです。GIFはアニメーションが無効で、最初のフレームだけが使われます。
縮小で細かい傷が潰れないようにする
細かい不具合の見え方を左右するのは、解像度の扱いです。Claudeは画像を28×28ピクセルのパッチに分けて見ます。上限を超える画像は、処理の前に縮小されます。
| モデルの区分 | 長辺の上限 | 視覚トークンの上限 |
|---|---|---|
| 高解像度(Claude 4.7以降) | 長辺の上限2576px | 視覚トークンの上限4784 |
| 標準(それ以外) | 長辺の上限1568px | 視覚トークンの上限1568 |
3840×2160pxの写真は、標準区分では1456×819pxに縮みます。高解像度区分でも2576×1449pxまでです。部品全体を1枚に収めた4K写真から、数ミリの傷を読み取らせる使い方は、縮小の時点で材料が減ります。
対策は、検査したい面を切り抜いてから渡すことです。縮小のしくみとトークン計算はClaudeの画像のトークンコスト計算式にまとめています。
もう一つ、圧縮にも注意が要ります。JPEGやWebPの強い圧縮はリクエストを軽くしますが、圧縮の歪みが判定の妨げになることがあり、何度も再圧縮するほど悪化します。ラインから上がってくる写真は、判定に使う画質で保存して、実際にAPIへ送った画像を目で確かめてください。
メタデータも渡りません。Claudeは画像のExif情報などを受け取らないため、撮影日時やロット番号は、テキストとして一緒に送る必要があります。
不具合モードをenumで固定して返させる
分類の再現性を上げる最初の一手は、返してよいラベルを決めておくことです。自由記述で返させると、同じ傷が「擦り傷」「スクラッチ」「線状の傷」と揺れて、集計できません。
不具合モードは、自社の検査基準書の分類に合わせて決めます。下の表は書き方の一例で、実際の項目は工程や製品に合わせて差し替えます。
| コード | 不具合モード | 判定の目安(プロンプトに書く定義の例) |
|---|---|---|
| scratch | 不具合モード傷 | 判定の目安(プロンプトに書く定義の例)表面に線状・点状の擦れがある |
| dent | 不具合モード打痕 | 判定の目安(プロンプトに書く定義の例)面が凹んでおり、周囲に光の反射の乱れがある |
| chip | 不具合モード欠け | 判定の目安(プロンプトに書く定義の例)縁や角の一部が失われている |
| stain | 不具合モード汚れ・異物 | 判定の目安(プロンプトに書く定義の例)本来の素材にない付着物がある |
| discoloration | 不具合モード変色 | 判定の目安(プロンプトに書く定義の例)素材の色が部分的に変わっている |
| other | 不具合モードその他 | 判定の目安(プロンプトに書く定義の例)上記に当てはまらない不具合がある |
| none | 不具合モード不具合なし | 判定の目安(プロンプトに書く定義の例)基準書の不具合に当たるものが見当たらない |
| unclear | 不具合モード判定不能 | 判定の目安(プロンプトに書く定義の例)ピントや角度、写り込みで判断できない |
ここで unclear を用意するのが要点です。選択肢が不具合だけだと、判断できない写真も無理にどれかへ寄せられます。「分からない」を正式なラベルにしておけば、人に回す理由がデータに残ります。
出力の形は、APIのstructured outputsで指定します。JSON Schemaを output_config.format に渡すと、スキーマに沿ったJSONが返ります。使うときの条件は次のとおりです。
- オブジェクトには
additionalProperties: falseを付ける enumは文字列・数値・真偽値・nullだけで、複雑な型は入れられないminimumやmaxLengthのような数値・文字列の制約は使えないenumの大文字小文字は保証されないため、比較は大文字小文字を区別せずに行い、綴りだけが違う値は作らない
この制約の全体像はStructured outputsのJSON Schema制限で扱っています。
写真1枚を分類するPythonコード
下のコードは、1枚の写真とロット番号を渡し、不具合モードをJSONで受け取る最小の例です。モデル名と判定基準の文面は、自社の環境と基準書に合わせて置き換えてください。
import base64
import json
import anthropic
client = anthropic.Anthropic()
SCHEMA = {
"type": "object",
"properties": {
"defect_mode": {
"type": "string",
"enum": ["scratch", "dent", "chip", "stain",
"discoloration", "other", "none", "unclear"],
},
"location": {"type": "string"},
"note": {"type": "string"},
},
"required": ["defect_mode", "location", "note"],
"additionalProperties": False,
}
SYSTEM = (
"あなたは外観検査の一次仕分けを担当します。"
"写真に写る不具合を、定義に沿ってdefect_modeへ分類してください。"
"判断できないときは無理に分類せずunclearを返します。"
"locationは「左上の縁付近」のように大まかな位置を日本語で書き、"
"noteには判断の根拠を1文で書きます。\n"
"定義: scratch=線状・点状の擦れ / dent=面の凹み / "
"chip=縁や角の欠け / stain=付着物 / discoloration=部分的な変色"
)
def classify(path: str, lot_id: str) -> dict:
with open(path, "rb") as f:
data = base64.standard_b64encode(f.read()).decode()
resp = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=1024,
system=SYSTEM,
messages=[{
"role": "user",
"content": [
{"type": "image",
"source": {"type": "base64",
"media_type": "image/jpeg",
"data": data}},
{"type": "text",
"text": f"ロット{lot_id}の外観写真です。分類してください。"},
],
}],
output_config={"format": {"type": "json_schema", "schema": SCHEMA}},
)
if resp.stop_reason != "end_turn":
return {"defect_mode": "unclear", "location": "",
"note": f"stop_reason={resp.stop_reason}"}
return json.loads(resp.content[0].text)stop_reason を確かめる分岐は省略しないでください。安全上の理由で拒否されたときは refusal、出力が途中で切れたときは max_tokens となり、どちらもスキーマに合わない出力が返ることがあります。拒否でも課金され、ステータスは200です。例外にならないぶん、気づかないまま結果の列に混ざります。上のコードは、そうした場合を unclear に落として人に回しています。
location を「大まかな位置」で頼んでいるのは、座標の出力が近似値だからです。不具合の位置をピクセルで正確に取りたいときは、Claudeで座標・バウンディングボックスを正確に取得する方法の手順で、縮小と座標のずれを補正してください。
分類結果を人の確認に振り分ける
JSONで返ってきたラベルは、そのまま工程の判定にせず、振り分けの入力にします。
一次仕分けから人の確認までの流れ
- 1
写真を切り抜いて送る
検査面ごとに切り抜き、縮小されない大きさで1枚ずつ渡します。ロット番号などの付帯情報はテキストで添えます。
- 2
ラベルで3つの山に分ける
不具合モードが付いたもの、
noneのもの、unclearやotherのものに分けます。 - 3
人が確かめる対象を決める
unclearとotherは全数を人が見ます。noneは一定数を抜き取って人が見ます。不具合モードが付いたものは、モード別に並べて人がまとめて追認します。 - 4
食い違いを記録する
人が直したラベルとClaudeのラベルの食い違いを残し、定義の文面や切り抜き方の見直しに使います。
最も気をつけたいのは、none の山です。見落としは、ラベルが付いた写真ではなく「不具合なし」に分類された写真の中に隠れます。モード別の山は見れば間違いに気づけますが、none は人が見ない限り間違いに気づけません。
ここの抜き取り率は、製品のリスクで決めます。出荷後に事故につながる欠陥が混ざりうる製品は、none も全数を見る運用が現実的です。見た目だけで済む軽微な欠陥なら、抜き取りで足りる場合があります。どちらにするかは、後述の自社写真での試験結果を見て判断してください。
大量の写真はバッチAPIで流す
その日の検査分をまとめて分類するなら、Message Batches APIが使えます。通常のAPI価格の50%で処理でき、即時の応答は要りません。
- 1バッチは、10万件のリクエストか256MBの、先に達したほうが上限
- 多くのバッチは1時間以内に終わるが、24時間で完了しなければ期限切れになる
- 各リクエストには
custom_idを付ける。1〜64文字の英数字・ハイフン・アンダースコアのみで、写真の識別子と結びつけるのに使う
custom_id に「ロット番号-写真番号」を入れておけば、結果の突き合わせが楽になります。結果は元のリクエスト順とは限らないため、並びではなく custom_id で対応させてください。
実装はMessage Batches SDKの実装記事で、Python・TypeScript・Ruby・Javaの書き方を比べています。バッチの結果にも、応答が拒否された件や途中で切れた件が混ざりえます。結果を取り込むときは、各件の応答が正常に完了したかを見て、そうでない件を人に回す分岐を入れておきます。
運用前に自社の写真で測る
公式の記述からは、「一次仕分けに使える」とも「使えない」とも判断できません。自社の製品、照明、不具合の出方で変わるためです。
導入前に、次の試験を勧めます。
- 人が正解のラベルを付けた写真を用意する(不具合の種類ごとに十分な枚数と、良品)
- 同じ写真をClaudeに分類させる
- 正解と食い違った写真を、「不具合を見逃して
noneにした」「違うモードに分けた」「良品を不具合にした」に分けて数える
見るべきは、全体の正解率ではなく見逃しの数です。良品を不具合と誤る誤りは人が見れば直せますが、不具合を none にした誤りは人の目に触れません。
試験では、写真の撮り方も変えて比べます。切り抜きの大きさ、照明、圧縮の強さを変えると、結果が動くことがあります。同じプロンプトでも、写真の条件が変われば別物です。変えた条件を記録しておけば、判定が崩れたときに原因を探せます。
文字を読む用途では、同じ画像入力でも精度の見極め方が違います。OCRの精度はClaude VisionでOCRした日本語PDFの精度をどう見極めるかで扱っています。外観の分類は、文字が読めるかではなく、見た目の差を言葉に落とせるかが問われる別の課題です。
まとめ
外観検査でClaudeに任せやすいのは、不具合モードの一次仕分けです。画像はAPIで100枚か600枚まで、1枚10MBまでという上限があり、縮小で細部が潰れるため、検査面の切り抜きが精度を左右します。不具合モードを enum で固定し、「判定不能」を用意しておけば、人に回す理由が結果に残ります。
運用の分かれ目は none の扱いです。自社の写真で見逃しの数を測り、抜き取りで足りるか全数を見るかを決めてから、一次仕分けの範囲を広げてください。