7.12. Постпроцесори#
Мережа виявлення не видає рамки. Вона видає один або кілька тензорів, розташування яких залежить від архітектури, на якій навчалася модель – двовимірний тензор кандидатних передбачень для детектора сімейства YOLO, пара тензорів (boxes, scores) для детектора MediaPipe, плаский список координат ключових точок для мережі оцінки поз. Застосунок не може читати жоден з них безпосередньо; те, що він хоче – список рамок, список ключових точок, розбивку за класами – необхідно декодувати з необробленого тензора.
Цей декодер називається постпроцесором. Модуль ml.postprocessing групує їх за екосистемою джерела.
7.12.1. Darknet#
ml.postprocessing.darknet декодує моделі епохи оригінального YOLO. YOLO v2 ввів ідеї сітки та якорів, які більшість пізніших детекторів успадкували у тій чи іншій формі, тому розташування v2 є найзрозумілішою відправною точкою.
YOLO v2 починає з поділу вхідного зображення на грубу сітку – розмітка 13×13 для канонічного вхідного зображення 416 пікселів, менша для менших моделей – і навчає мережу так, щоб кожна клітинка сітки відповідала за виявлення будь-якого об’єкта, центр якого знаходиться всередині неї. Просторове розташування вихідного тензора відображає розташування вхідного: одна позиція у виході на кожну клітинку зображення.
У кожній клітинці сітки мережа не передбачає рамку з нічого. Вона вибирає серед кількох заздалегідь обраних еталонних форм, які називаються якорями – фіксованих пар (width, height), отриманих офлайн кластеризацією розмірів рамок у навчальному наборі, щоб вони охоплювали типові об’єкти, які модель має виявляти. Завдання мережі в кожній клітинці – передбачити для кожного якоря невеликий відступ центру рамки всередині клітинки, масштаб ширини і висоти якоря, оцінку об’єктності (ймовірність того, що там щось є), і вектор ймовірностей по класах. Сітка 13×13 зі стандартними 5 якорями та 20 класами тому видає 13 * 13 * 5 * (4 + 1 + 20) = 21,125 чисел на інференс.
YoloV2 декодує це розташування: він обходить клітинки, застосовує зміщення та масштаби кожного якоря для відновлення абсолютних координат рамки, поєднує об’єктність з ймовірністю класу для отримання оцінки по класах, застосовує порогування та надсилає відібрані значення до NMS. Клас приймає аргумент конструктора anchors=, коли модель навчалася проти власної таблиці якорів, і в іншому випадку повертається до вбудованого стандарту. Варіанти, налаштовані для конкретних наборів класів, постачаються в тому самому підмодулі.
7.12.2. Ultralytics#
ml.postprocessing.ultralytics декодує новіші покоління YOLO. YoloV8 читає вивід у стовпцево-майорному форматі, де кожен стовпець є одним передбаченням якоря, що містить координати рамки та вектор оцінок по класах – канал об’єктності, який несли попередні виходи YOLO, у v8 вилучено, а оцінки класів стоять самостійно. Розбір YOLOv8 крок за кроком проходить через декодування тензора. Старіші версії епохи Ultralytics постачаються в тому самому підмодулі для моделей, навчених на відповідних розташуваннях.
7.12.3. MediaPipe#
ml.postprocessing.mediapipe декодує легке сімейство Google для обробки на пристрої. BlazeFace — це детектор обличь, описаний у hello-blazeface: швидкий детектор на основі якорів, що видає рамки та шість координат орієнтирів на кожне обличчя, повернутих як кортежі (box, score, keypoints) з орієнтирами, прикріпленими до кожної рамки, а не як окремий вихідний список. Моделі виявлення рук, орієнтирів та поз з того самого сімейства постачаються разом і мають ту саму форму повернення з прикріпленими ключовими точками.
7.12.4. Вибір постпроцесора#
Правильний постпроцесор визначається архітектурою, на якій навчалася модель, а не тим, що хоче застосунок. YOLOv8 .tflite правильно декодується лише через YoloV8; BlazeFace .tflite – лише через BlazeFace. Вибір постпроцесора є частиною вибору моделі. Коли архітектура моделі не представлена вбудованим постпроцесором, написання власного є простим.
Мережі класифікації є винятком. Їхній єдиний вихідний тензор вже є тим, що хоче застосунок – список оцінок по класах – і постпроцесор не потрібен. Завантаження моделі без postprocess= та читання результату передбачення як плаского ndarray є правильним шляхом, як описано у розділі тензорний ввід/вивід.