物体検出を理解する
検出モデルの出力(クラス、ボックス、信頼度)を読み取り、各種ミスのコストに基づいて信頼度とIoUのしきい値を設定します。
本番環境のビジョンシステムの多くは、カウンター、トラッカー、エリアアラート、プライバシー保護のためのぼかしなど、検出にロジックを加えたものです。これらが正しく動作しない場合、原因はモデルではなく、意図的に設定されていないしきい値であることがほとんどです。検出モデルが何を返し、その一覧を左右する2つのパラメーターが何かを正確に把握すれば、検出を基盤とするほぼあらゆるものをデバッグできます。
実践的
検出モデルが返すもの#

画像内の各ラベルは、出力の1行に相当します。クラス名、信頼度、対象を囲むボックスです。検出モデルは、この一覧をそのまま返します。
- クラス — 整数インデックスを
result.namesを介して名前に対応付けます(0はperson、5はbusです)。 - ボックス — オブジェクトの位置を示す4つの数値です。
xyxyは左上と右下の角をピクセル単位で示します。 - 信頼度 — 検出結果の順位付けとフィルタリングに使う、0から1までのスコアです。
これらの出力行を使ったカウント、アラート、トラッキング、ぼかしは、上に重ねて自分で記述するコードです。
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
result = model("https://ultralytics.com/images/bus.jpg", verbose=False)[0]
for box in result.boxes:
name = result.names[int(box.cls)]
x1, y1, x2, y2 = box.xyxy[0].tolist()
print(f"{name:8} conf={float(box.conf):.2f} box=({x1:.0f}, {y1:.0f}, {x2:.0f}, {y2:.0f})")bus conf=0.88 box=(0, 230, 803, 751)
person conf=0.87 box=(49, 398, 240, 902)
person conf=0.86 box=(223, 405, 345, 861)
person conf=0.85 box=(670, 395, 810, 880)
person conf=0.65 box=(0, 553, 60, 871)行ごとに見ていきましょう。バスが左端からはみ出しているため、バスのボックスはx=0から始まります。3人の信頼度は0.85~0.87です。左端で一部が切れている4人目の信頼度は0.65にとどまります。モデルには体の半分しか見えていないためです。一部が切れたオブジェクトの信頼度が低いのは正常であり、しきい値の影響が最初に表れるケースです。
各ボックスは4種類の形式で取得できます。後続のコードが必要とする形式を使ってください。
| 属性 | 形式 | 一般的な用途 |
|---|---|---|
boxes.xyxy | 角のピクセル座標(x1、y1、x2、y2) | 切り抜き、描画、重なりのルール |
boxes.xywh | 中心のピクセル座標と幅・高さ | サイズフィルター、動き |
boxes.xyxyn | 0~1に正規化された角の座標 | 解像度が変わっても機能するルール |
boxes.xywhn | 0~1に正規化された中心座標とサイズ | YOLOラベルファイル |
候補から最終的な一覧へ#
モデル内部では、オブジェクトごとに多数の候補ボックスをスコア付けします。2つのフィルターによって、候補が最終的に表示される一覧に絞られます。
信頼度フィルター。 confはしきい値を下回るボックスを除外します。予測時のデフォルトは0.25です。バスの画像では、しきい値を変えると検出数がすぐに変わります。
conf | bus.jpg内のボックス |
|---|---|
| 0.10 | 7 |
| 0.25 | 5 |
| 0.50 | 5 |
| 0.75 | 4 |
重複フィルター。 非最大抑制(NMS)は、信頼度が最も高いボックスを残し、同じクラスの他のボックスのうち、iouを超える割合でそのボックスと重なるものを除外します(デフォルトは0.7)。重なりの度合いは交差領域と和領域の比で測定します。共有領域を結合領域で割った値です。

iou | bus.jpg内のボックス | 効果 |
|---|---|---|
| 0.3 | 5 | 厳格: 重複するボックスを統合します |
| 0.7 | 5 | デフォルト |
| 0.95 | 8 | 寛容: 近似重複を残します |
誤りのコストに基づいてしきい値を選びます#
| もし… | その場合… |
|---|---|
| 見逃しのコストが高い場合(安全アラート、不良品) | confを下げ、誤警報をある程度許容します |
| 誤警報がユーザーに見える場合(検索、タグ付け) | confを上げます |
| 個数を報告します | 検証画像でconfを変えながら評価し、個数の誤差が最小の値を選びます |
| 密集した状況では、近接する実物体が消えてしまいます | iouを上げます(例: 0.7 → 0.8) |
| 同じ物体に2つのボックスが付けられます | iouを下げます |
| クラスによって難易度が異なります | 必要な範囲で最も低いconfで予測し、その後コードでクラスごとにフィルタリングします |
倉庫の安全監視は低いしきい値が典型的に必要なケースです。Predictモードには、すべての推論引数が記載されています。
よくある落とし穴#
症状: 「モデルはこれがバスである確率を88%と見ています」と解釈し、直感でしきい値を選んでいます。対処法: 信頼度はランキングスコアとして扱います。YOLO26では、「物体が存在すること」と「そのクラスであること」の両方を1つのスコアで表しますが、このスコアはキャリブレーションされていません。数値の意味からではなく、検証データに基づいてしきい値を選びます。
2人が肩を並べて立っていると、ボックスが大きく重なり、NMSが実際にいる人を「重複」として削除することがあります。iouを大きくすると、2つ目のボックスが再び表示されます。YOLO26にはNMSがまったく不要なエンドツーエンドヘッドも搭載されています。これを使うにはnms=Falseを渡します。
症状: デモ画像では完璧に見えるしきい値が、実際のカメラでは機能しません。対処法: 配備先のカメラで撮影した検証セットを使ってしきい値を網羅的に試します。1枚の画像から分かるのは、各設定値の働きだけです。
間違いの4つのパターン#
| 失敗 | 問題点 | 一般的な対処法 |
|---|---|---|
| クラスは正しいが、ボックスが大きすぎる | 位置推定 | ボックスのルールをより厳密かつ一貫性のあるものにし、小さな物体ではimgszを大きくします |
| ボックスは正しいが、クラスが間違っている | 分類 | 混同されるクラスの組み合わせの例を増やすか、クラスを統合します |
| ボックスがまったくない | 再現率 | その状態の例を増やします(照明、サイズ、オクルージョン) |
| 背景上のボックス | 適合率 | モデルが誤認した対象を含む、判別が難しい負例画像 |
診断をすばやく進めるには、2つのリストを作成します。信頼度が低い真陽性(実物体に対してモデルが確信を持てていない)と、信頼度が高い偽陽性(間違った対象を確信している)です。それぞれ異なる対処法が必要です。
解答を表示
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
result = model("https://ultralytics.com/images/bus.jpg", conf=0.05, save=True, verbose=False)[0]
for box in sorted(result.boxes, key=lambda b: -float(b.conf)):
name, conf = result.names[int(box.cls)], float(box.conf)
x1, y1, x2, y2 = box.xyxy[0].tolist()
print(f"{conf:.2f} {name:10} ({x1:.0f}, {y1:.0f}, {x2:.0f}, {y2:.0f})")0.88 bus (0, 230, 803, 751)
0.87 person (49, 398, 240, 902)
0.86 person (223, 405, 345, 861)
0.85 person (670, 395, 810, 880)
0.65 person (0, 553, 60, 871)
0.18 person (0, 600, 40, 871)
0.12 stop sign (0, 252, 35, 326)
0.08 handbag (43, 732, 78, 812)
0.07 skateboard (669, 822, 808, 881)
0.06 handbag (225, 634, 291, 705)0.5未満のボックスはすべて偽陽性です。0.18のpersonは、左端で切れている0.65の人物を重複して検出しています。0.12のstop signは、クラスが間違っている実際の道路標識です。ハンドバッグとスケートボードは、手や靴の上にあります。実物体はすべて0.6を超えているため、歩行者カウンターではconf=0.5を使うと4人全員を検出し、ノイズを取り除けます。これは二重カウントを防ぎます。運用を開始する前に、実際のカメラで撮影した検証セットで確認してください。0.65の切れた人物から、実物体のスコアがしきい値にどれほど近づくかが分かります。