7.13. Non-max suppression¶
Egy észlelő hálózat jellemzően több, egymást átfedő jelölt dobozt állít elő ugyanazon valós tárgy körül: a tárgy közelében lévő minden horgony hasonló pontszámmal aktiválódik, és az utófeldolgozó mindegyiket látja. A non-max suppression (NMS) az a lépés, amely ezt a csoportot egyetlen dobozzá alakítja.
Az algoritmus rövid: rendezd a jelölt dobozokat pontszám szerint, vedd a legmagasabb pontszámút, nyomj el minden más dobozt, amely egy választott küszöbértéken túl átfedi azt, majd vedd a megmaradottak közül a következő legmagasabbat, és ismételd. Az átfedési mérőszám az intersection-over-union (IoU) – két doboz közös területe a kombinált területükkel osztva, 0 (nincs átfedés) és 1 (azonos dobozok) közötti érték. Minden szállított utófeldolgozó nms_threshold konstruktorargumentuma az a határ, amely felett a dobozokat egy már megtartott doboz duplikátumaként kezeljük.
Az NMS az egymást átfedő észlelések csoportját a legmagasabb pontszámúra szűkíti.¶
7.13.1. Soft-NMS¶
A szállított ml.utils.NMS osztály a Soft-NMS eljárást valósítja meg, ami egy finomítás: az egymást átfedő doboz pontszámát az átfedés mértékétől függő mennyiséggel csökkenti, ahelyett, hogy a dobozt egyből eldobná. Ha a csökkentett pontszám a küszöbérték alá esik, a dobozt eldobja; egyébként a csökkentett pontszámmal túlél és a következő körben versenyez.
A nms_sigma paraméter szabályozza, hogy a csökkentés mennyire agresszív. Kis nms_sigma érték esetén (a szállított alapértelmezett 0.1) a csökkentés meredek: egy erősen átfedő doboz pontszáma majdnem nullára csökken, és a Soft-NMS a klasszikus NMS-re egyszerűsödik. Nagyobb nms_sigma esetén a csökkentés enyhe, és a különböző tárgyak egymást átfedő dobozai gyakrabban túlélnek, ami akkor számít, amikor ugyanazon osztály valós tárgyai ténylegesen átfedik egymást (egy tömeg arc, egy tenyérfürt).
A nms_sigma <= 0 értékre állítása teljesen kikapcsolja a csökkentést: az átfedő dobozok eredeti pontszámukkal mennek át, és csak a pontszámküszöb szűri őket.
7.13.2. Közvetlen felépítés¶
Minden szállított utófeldolgozó egy friss NMS példányt épít minden következtetéskor, hozzáadja az egyes jelölteket, és a végén meghívja a get_bounding_boxes() metódust. Egy egyéni utófeldolgozó ugyanezt a mintát követi:
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)
A konstruktor a hálózat bemeneti szélességét és magasságát képpontban, valamint az eredeti kép ROI-ját veszi át, amellyel szemben a modell futott; a add_bounding_box() a doboz koordinátáit ebben a hálózati bemeneti képpont-térben veszi át, a get_bounding_boxes() pedig a túlélőket a ROI segítségével visszaképezi kép-koordinátákba. A visszaképezés automatikusan figyelembe veszi a normalizálási nyújtást – ugyanazt a ROI-t használja a dobozok visszavetítéséhez, amelyet a prediktor látott –, így a visszaadott dobozok készen állnak a rögzített képkockára való rajzolásra.
A visszatérési alakzat osztályonkénti listák listája, amelyet az add_bounding_box metódusnak átadott label_index indexel. Az üres osztálylisták megmaradnak, hogy az index megfeleljen a modell osztályindexének; az enumerate(result) az osztályokat az észleléseikkel együtt járja be.