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.

Balra három, egymást átfedő határoló doboz egyetlen alany körül, 0.92, 0.83 és 0.71 pontszámmal címkézve. Egy nyíl jobbra mutat, ahol egyetlen túlélő doboz marad 0.92 pontszámmal. A két alacsonyabb pontszámú dobozt a magasabb pontszámú nyomja el, mert az azzal vett intersection-over-union értékük meghaladja a küszöbértéket.

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.