7.12. Post-procesory#
Detekční síť nevypouští rámečky. Vypouští jeden nebo více tenzorů, jejichž rozložení závisí na architektuře, na které byl model trénován – 2D tenzor kandidátních predikcí pro detektor z rodiny YOLO, dvojici tenzorů (boxes, scores) pro detektor MediaPipe, plochý seznam souřadnic klíčových bodů pro síť odhadu pózy. Aplikace nedokáže žádný z nich číst přímo; to, co chce – seznam rámečků, seznam klíčových bodů, rozpis podle tříd – musí být z hrubého tenzoru dekódováno.
Tímto dekodérem je post-procesor. Modul ml.postprocessing je seskupuje podle zdrojového ekosystému.
7.12.1. Darknet#
ml.postprocessing.darknet dekóduje modely z původní éry YOLO. YOLO v2 zavedl myšlenky mřížky a kotvy, které většina pozdějších detektorů v nějaké podobě zdědila, takže rozložení v2 je nejčistším výchozím bodem.
YOLO v2 začíná rozdělením vstupního obrazu na hrubou mřížku – rozložení 13 × 13 pro kanonický 416pixelový vstup, menší pro menší modely – a trénuje síť tak, aby každá buňka mřížky byla zodpovědná za detekci jakéhokoli objektu, jehož střed do ní spadá. Prostorové rozložení výstupního tenzoru zrcadlí rozložení vstupu: jedna pozice ve výstupu na každou buňku v obraze.
V každé buňce mřížky síť nepredikuje rámeček z ničeho. Vybírá z několika předem zvolených referenčních tvarů zvaných kotvy – pevných dvojic (width, height) odvozených offline shlukováním velikostí rámečků v trénovací sadě tak, aby pokrývaly typické objekty, které má model očekávat. Úkolem sítě v každé buňce je predikovat pro každou kotvu malý posun středu rámečku v rámci buňky, měřítko šířky a výšky kotvy, skóre objektnosti (pravděpodobnost, že tam vůbec něco je) a vektor pravděpodobností podle tříd. Mřížka 13 × 13 s výchozími 5 kotvami a 20 třídami tedy vypouští na jednu inferenci 13 * 13 * 5 * (4 + 1 + 20) = 21,125 čísel.
YoloV2 toto rozložení dekóduje: prochází buňky, aplikuje posuny a měřítka každé kotvy k získání absolutních souřadnic rámečku, kombinuje objektnost s pravděpodobností třídy do skóre podle tříd, prahuje a posílá přeživší do NMS. Třída přijímá argument konstruktoru anchors=, byl-li model trénován vůči vlastní tabulce kotev, jinak se vrací k vestavěné výchozí hodnotě. Varianty vyladěné pro konkrétní sady tříd jsou dodávány ve stejném submodulu.
7.12.2. Ultralytics#
ml.postprocessing.ultralytics dekóduje novější generace YOLO. YoloV8 čte výstup uspořádaný po sloupcích, kde každý sloupec je jedna predikce kotvy obsahující souřadnice rámečku a vektor skóre podle tříd – kanál objektnosti, který nesly dřívější výstupy YOLO, byl ve v8 vypuštěn a skóre tříd stojí samostatně. Průchod YOLOv8 provádí dekódováním tenzor po tenzoru. Starší verze z éry Ultralytics jsou dodávány ve stejném submodulu pro modely trénované vůči jejich rozložením.
7.12.3. MediaPipe#
ml.postprocessing.mediapipe dekóduje lehkou rodinu modelů Google pro běh přímo na zařízení. BlazeFace je detektor tváří popsaný v hello-blazeface: rychlý detektor založený na kotvách, který vypouští rámečky a šest souřadnic význačných bodů na tvář, vracené jako n-tice (box, score, keypoints) s význačnými body připojenými ke každému rámečku, nikoli jako samostatný výstupní seznam. Modely pro detekci rukou, význačných bodů a pózy ze stejné rodiny jsou dodávány spolu s ním a řídí se stejným návratovým tvarem s připojenými klíčovými body.
7.12.4. Výběr jednoho#
Správný post-procesor je dán architekturou, na které byl model trénován, nikoli tím, co chce aplikace. .tflite typu YOLOv8 se správně dekóduje pouze přes YoloV8; .tflite typu BlazeFace pouze přes BlazeFace. Výběr post-procesoru je součástí výběru modelu. Pokud architektura modelu není zastoupena dodávaným post-procesorem, napsat vlastní je přímočaré.
Výjimkou jsou klasifikační sítě. Jejich jediný výstupní tenzor je už tím, co aplikace chce – seznamem skóre podle tříd – a žádný post-procesor není potřeba. Načtení modelu bez postprocess= a čtení výsledku predikce jako plochého ndarray je správná cesta, jak pokryl tenzorový vstup/výstup.