第7章

YOLOで物体を検出する

静止画・動画・カメラから複数の物体を検出し、種類、確信度、検出枠の座標を取り出します。

この章で学ぶこと

  • YOLOの学習済みモデルで物体を検出する
  • 検出枠、クラス、確信度をPythonで取り出す
  • 見逃し、誤検出、IoUを使って結果を確認する
  • 自分の物体を追加学習するときのデータ形式を知る

1. 学習済みモデルを使う

前章の環境とコード一式を使います。本教材では小型の YOLO11n 検出モデル yolo11n.pt を選びます。これは実習でモデル名をそろえるための選択で、最新版という意味ではありません。YOLO11公式資料

ボトル、コップ、本などを机に置き、2〜3種類が写る写真を desk.jpg として保存します。

python yolo_detect.py --source desk.jpg --output detection-01

初回は公式のモデル重みをダウンロードするため、ネット接続が必要です。取得後はローカルの重みファイルを使います。教材コードは画像をローカルで推論します。重みの取得に失敗したら接続を確認し、公式配布のファイルを保存して --model で指定できます。

detection-01/last.png に検出枠付き画像、detections.jsonl に結果が保存されます。JSONLは1行が1フレームのJSONです。学習済みクラスにない独自の部品や道具が、そのまま検出できるとは限りません。

2. 枠とクラスを取り出す

完成コードの中心は次の処理です。

model = YOLO("yolo11n.pt")
result = model.predict(image, conf=0.35, device="cpu", verbose=False)[0]
for box in result.boxes:
    x1, y1, x2, y2 = box.xyxy[0].cpu().tolist()
    class_id = int(box.cls[0].item())
    label = result.names[class_id]
    confidence = float(box.conf[0].item())
値 意味
xyxy 左上 (x1, y1) と右下 (x2, y2)。元画像上のピクセル座標
cls クラス番号。名前は result.names で引く
conf 検出の確信度。現実世界で正しい確率の保証ではない
center_px 教材コードで計算した枠の中心

OpenCVのBGR画像をそのまま渡すと、ライブラリが推論用の前処理を行います。この入口では、自分でRGB変換や255による除算を重ねないでください。Ultralyticsの推論API

検出が0件でもログには空の detections を保存します。「何も写っていない」と「写っているが検出できなかった」は別なので、元画像も確認します。

3. 動画・カメラで試す

python yolo_detect.py --source desk.mp4 --output video-detection --show
python yolo_detect.py --source 0 --output camera-detection --show --max-frames 0

q で終了します。ログは全処理フレーム、画像は最後の1枚を保存します。既定は最大300フレームです。CPUで遅いときは、まず静止画で動作を確かめてください。

ログの index はそのフレーム内だけの番号です。次のフレームの同じ番号が同じ物体とは限りません。同一物体を継続して追うには、検出結果を時系列で対応付ける追跡処理が別途必要です。

4. 検出を評価する

同じ画像で --conf 0.2 と --conf 0.6 を比較し、正しく増減した枠と誤検出を数えます。しきい値を下げて枠が増えても、すべて正解とは限りません。

検出枠と正解枠の重なりは **IoU(Intersection over Union)**で表せます。

IoU = 2つの枠の共通部分の面積 / 2つの枠を合わせた領域の面積

クラスが合い、IoUが評価基準を満たす検出を正解として数えます。同じ正解物体へ複数の枠を対応させて正解数を増やしてはいけません。対応しない検出は誤検出、対応する検出がない正解物体は見逃しです。検出の評価では、背景に無数の候補領域があるため、画像分類の正解率をそのまま流用しません。

APは確信度のしきい値を変えたときの適合率と再現率をまとめた指標、mAPはクラスなどについて平均した指標です。mAP50 と mAP50-95 はIoUの評価条件が異なるため、同じ値として比べません。物体検出の学習・評価API

5. 発展:自分の物体を追加学習する

まずは学習済みモデルで検出と座標の取り出しを完了してください。独自クラスの学習へ進む場合は、学習用と検証用に分けた画像に正解の枠を付けます。

dataset/
  images/train/part01.jpg
  images/val/part02.jpg
  labels/train/part01.txt
  labels/val/part02.txt

ラベルは画像と同じファイル名の .txt に、物体1個につき1行、クラス番号 中心x 中心y 幅 高さ と書きます。座標と大きさは画像の幅・高さで割って0〜1に正規化します。xyxy のピクセル値をそのまま書かないでください。YOLOデータセット形式

data.yaml の例です。path は自分のデータの絶対パスに置き換えます。

path: /absolute/path/to/dataset
train: images/train
val: images/val
names:
  0: part
yolo detect train model=yolo11n.pt data=data.yaml epochs=20 imgsz=640 device=cpu

学習は推論より時間がかかります。表示された保存先の weights/best.pt を --model に指定して使います。独立したテスト画像を最後まで残し、撮影セッションが分割をまたがないようにします。

やってみよう

  1. 明るさ・距離・一部の隠れ方を変えて撮影し、見逃しが起きる条件を記録してください。
  2. 同じ番号の index を追跡IDとして使えないのはなぜでしょうか。
  3. 640×480画像の枠 (160, 120, 320, 360) を学習ラベルへ変換してください。

3の答えは、クラス番号を除くと 0.375 0.5 0.25 0.5 です。中心は (240, 240)、幅160、高さ240になります。