Ultralytics YOLO27: ウェイトリストに登録する。
Get Started
コンピュータービジョンの基礎·タスクを選ぶ·レッスン 3/10
レッスン初級

物体検出を理解する

検出モデルの出力(クラス、ボックス、信頼度)を読み取り、各種ミスのコストに基づいて信頼度とIoUのしきい値を設定します。

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

成果

コードでYOLO26の検出結果を読み取り、見逃しと誤警報のコストに基づいてconfとiouを選択します。

短期集中コース
すでに使い方をご存じの方は、こちらをご覧ください。
  1. 各検出結果は、クラス、ボックス、信頼度スコアで構成されます。

  2. confは信頼度の低いボックスを除外します(デフォルトは0.25)。iouはNMSが2つのボックスを重複とみなす条件を決めます(デフォルトは0.7)。

  3. 見逃しのコストが高い場合は、confを下げます。誤警報が目立つ場合は、値を上げます。

  4. 隣接するボックスが消える場合は、iouを上げます。

  5. 信頼度はボックスの順位付けに使うスコアであり、較正済みの確率ではありません。

実践的

検出モデルが返すもの#

Ultralytics YOLOの検出結果が表示されたウォーターフロントの遊歩道:人、自転車に乗る人2人、犬、車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.xyxyn0~1に正規化された角の座標解像度が変わっても機能するルール
boxes.xywhn0~1に正規化された中心座標とサイズYOLOラベルファイル

候補から最終的な一覧へ#

モデル内部では、オブジェクトごとに多数の候補ボックスをスコア付けします。2つのフィルターによって、候補が最終的に表示される一覧に絞られます。

信頼度フィルター。 confはしきい値を下回るボックスを除外します。予測時のデフォルトは0.25です。バスの画像では、しきい値を変えると検出数がすぐに変わります。

confbus.jpg内のボックス
0.107
0.255
0.505
0.754

重複フィルター。 非最大抑制(NMS)は、信頼度が最も高いボックスを残し、同じクラスの他のボックスのうち、iouを超える割合でそのボックスと重なるものを除外します(デフォルトは0.7)。重なりの度合いは交差領域と和領域の比で測定します。共有領域を結合領域で割った値です。

鳥の画像における交差領域と和領域の比:予測ボックスと正解ボックス、および対応するマスクが重なっており、IoUは重なり部分を和領域で割った値です

ioubus.jpg内のボックス効果
0.35厳格: 重複するボックスを統合します
0.75デフォルト
0.958寛容: 近似重複を残します

誤りのコストに基づいてしきい値を選びます#

もし…その場合…
見逃しのコストが高い場合(安全アラート、不良品)confを下げ、誤警報をある程度許容します
誤警報がユーザーに見える場合(検索、タグ付け)confを上げます
個数を報告します検証画像でconfを変えながら評価し、個数の誤差が最小の値を選びます
密集した状況では、近接する実物体が消えてしまいますiouを上げます(例: 0.7 → 0.8)
同じ物体に2つのボックスが付けられますiouを下げます
クラスによって難易度が異なります必要な範囲で最も低いconfで予測し、その後コードでクラスごとにフィルタリングします

倉庫の安全監視は低いしきい値が典型的に必要なケースです。Predictモードには、すべての推論引数が記載されています。

よくある落とし穴#

信頼度を確率として読み取る

症状: 「モデルはこれがバスである確率を88%と見ています」と解釈し、直感でしきい値を選んでいます。対処法: 信頼度はランキングスコアとして扱います。YOLO26では、「物体が存在すること」と「そのクラスであること」の両方を1つのスコアで表しますが、このスコアはキャリブレーションされていません。数値の意味からではなく、検証データに基づいてしきい値を選びます。

隣り合う2人のうち1人が消える場合はNMSを確認

2人が肩を並べて立っていると、ボックスが大きく重なり、NMSが実際にいる人を「重複」として削除することがあります。iouを大きくすると、2つ目のボックスが再び表示されます。YOLO26にはNMSがまったく不要なエンドツーエンドヘッドも搭載されています。これを使うにはnms=Falseを渡します。

1枚の画像だけで調整する

症状: デモ画像では完璧に見えるしきい値が、実際のカメラでは機能しません。対処法: 配備先のカメラで撮影した検証セットを使ってしきい値を網羅的に試します。1枚の画像から分かるのは、各設定値の働きだけです。

間違いの4つのパターン#

失敗問題点一般的な対処法
クラスは正しいが、ボックスが大きすぎる位置推定ボックスのルールをより厳密かつ一貫性のあるものにし、小さな物体ではimgszを大きくします
ボックスは正しいが、クラスが間違っている分類混同されるクラスの組み合わせの例を増やすか、クラスを統合します
ボックスがまったくない再現率その状態の例を増やします(照明、サイズ、オクルージョン)
背景上のボックス適合率モデルが誤認した対象を含む、判別が難しい負例画像

診断をすばやく進めるには、2つのリストを作成します。信頼度が低い真陽性(実物体に対してモデルが確信を持てていない)と、信頼度が高い偽陽性(間違った対象を確信している)です。それぞれ異なる対処法が必要です。

試してみる

conf=0.05でソリューションを実行し、保存された画像を開きます。0.5未満の各ボックスに真陽性または偽陽性の印を付け、偽陽性が発生した理由を記録します。次に、このカメラで歩行者カウンターを運用する場合に採用するconfを書き出し、根拠を1文で説明します。

完了条件
以下のすべてを満たすと、レッスンは完了です。
  • bus.jpg内の0.5未満のボックスすべてについて、真陽性か偽陽性かを理由とともに記録したリストがあります。

  • 歩行者カウンター用のconfの値と、その値によって防げる誤りを記録しています。

  • IoUテーブルを使って、iouを上げると抑制された近接物体が再び検出される理由を説明できます。

解答を表示
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の切れた人物から、実物体のスコアがしきい値にどれほど近づくかが分かります。

次のステップ

次は、長方形では不十分で、物体の正確な形状が必要な場合について説明します。