7.13. Non-max suppression¶
検出ネットワークは通常、同じ実世界の物体の周囲に複数の重なり合う候補ボックスを生成します。物体付近の各アンカーが似たようなスコアで発火し、後処理はそれらすべてを目にすることになります。Non-max suppression(NMS)は、このクラスタを1つのボックスにまとめるステップです。
アルゴリズムは簡潔です。候補ボックスをスコア順にソートし、最高スコアのものを取り、選んだしきい値を超えて重なる他のすべてのボックスを抑制し、次に残りの中から最高スコアのものを取って、これを繰り返します。重なりの指標は intersection-over-union(IoU)です。2つのボックスの共有面積をそれらの合計面積で割った値で、0(重なりなし)から 1(同一のボックス)の間の値をとります。出荷されるすべての後処理が持つ nms_threshold コンストラクタ引数は、既に保持されているボックスの重複として扱われるかどうかのカットオフです。
NMSは重なり合う検出のクラスタを最高スコアのものに集約します。¶
7.13.1. Soft-NMS¶
出荷される ml.utils.NMS クラスは Soft-NMS を実装しています。これは、重なり合うボックスを完全に除外するのではなく、重なりの度合いに応じた量だけスコアを減衰させる改良版です。下げられたスコアがしきい値を下回ればボックスは除外されます。そうでなければ、減衰したスコアのまま生き残り、次のラウンドで競合します。
nms_sigma パラメータは減衰の積極性を制御します。小さい nms_sigma(出荷時のデフォルトは 0.1)では減衰が急峻です。大きく重なるボックスのスコアはほぼゼロまで引き下げられ、Soft-NMSは古典的なNMSに帰着します。大きい nms_sigma では減衰が緩やかになり、異なる物体の重なり合うボックスがより頻繁に生き残ります。これは、同じクラスの実世界の物体が実際に重なる場合(顔の群衆、手のひらの集まりなど)に重要です。
nms_sigma を <= 0 に設定すると減衰は完全に無効になります。重なり合うボックスは元のスコアのまま通過し、スコアしきい値だけがそれらをフィルタリングします。
7.13.2. 直接構築する¶
出荷されるすべての後処理は、推論ごとに新しい NMS を構築し、各候補をそれに追加し、最後に get_bounding_boxes() を呼び出します。カスタム後処理も同じパターンに従います:
from ml.utils import NMS
iw = model.input_shape[0][2]
ih = model.input_shape[0][1]
nms = NMS(iw, ih, inputs[0].roi)
for box, score, class_idx in candidates:
nms.add_bounding_box(box.xmin, box.ymin,
box.xmax, box.ymax,
score, class_idx)
result = nms.get_bounding_boxes(threshold=nms_threshold,
sigma=nms_sigma)
コンストラクタはネットワークの入力幅と高さをピクセル単位で受け取り、モデルが実行された元画像のROIを受け取ります。add_bounding_box() はそのネットワーク入力ピクセル空間でのボックス座標を受け取り、get_bounding_boxes() はROIを使って生き残ったものを画像座標に再マッピングします。再マッピングは 正規化のストレッチ を自動的に考慮します。予測器が見たのと同じROIを使ってボックスを投影し直すため、返されるボックスはキャプチャされたフレームに描画する準備が整っています。
戻り値の形状は、add_bounding_box に渡された label_index でインデックス付けされた、クラスごとのリストのリストです。空のクラスリストも保持され、インデックスがモデルのクラスインデックスと一致するようになっています。enumerate(result) でクラスとその検出結果を一緒にたどることができます。