Переглянути як Markdown

Нормалі поверхні

Оцінювання нормалей поверхні передбачає напрямок, у який повернута кожна видима поверхня. LibreYOLO надає його як задачу normal, що повертає щільне поле одиничних векторів на полотні початкового зображення.

Визначення

Задача normal передбачає за одним RGB-зображенням трикомпонентний одиничний вектор для кожного пікселя, тобто напрямок, у який повернута поверхня в цьому пікселі. На відміну від глибини, результат не має вільного масштабу, тому два передбачення можна безпосередньо порівнювати без вирівнювання.

Передбачення заповнює result.normal_map, корисне навантаження NormalMap із масивом float32 форми (H, W, 3) на полотні початкового зображення, яке також доступне як result.normals. Вектори використовують систему координат камери OpenCV у LibreYOLO: +x спрямовано праворуч, +y вниз, а +z углиб сцени. Вони повернуті до камери, тому фронтально-паралельна поверхня має значення (0, 0, -1). Метод .assert_normalized() перевіряє, що кожен піксель має скінченне значення й одиничну довжину в межах допуску. result.boxes залишається порожнім, тому conf, iou і max_det не впливають на результат, а Results.plot() підтримує цю задачу.

Моделі

Наведені нижче сімейства підтримують normal.

MoGe-2 спеціалізується на цьому завданні: монокулярна геометрична модель з одним прямим проходом і трьома розмірами енкодера. Розміри s і l використовують дзеркала LibreYOLO; b залишається у вихідному репозиторії.

LibreMODUS створює нормалі як один із цільових результатів моделі any-to-any та може приймати на вході карту глибини замість RGB-зображення. Для неї потрібне доповнення modus і власний автентифікований обліковий запис Hugging Face. Вона не підтримує ані val(), ані export(), тому не бере участі в описаних нижче валідації та експорті.

Marigold V2 також оцінює нормалі поверхні. Її типовий чотирибітний інференс потребує CUDA й додаткового пакета marigold; експорт не підтримується.

Передбачення

Під час першого використання ваги MoGe-2 завантажуються й кешуються локально.

Передбачити поле нормалей
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreMoGe2s-normal.pt")result = model(SAMPLE_IMAGE, save=True) normals = result.normal_mapprint(normals.data.shape)      # одиничні вектори float32 форми (H, W, 3)normals.assert_normalized()    # породжує помилку, якщо якийсь піксель не має одиничної довжини
Прочитати один піксель
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreMoGe2s-normal.pt")result = model(SAMPLE_IMAGE) # Система координат камери OpenCV: +x праворуч, +y вниз, +z углиб сцени. Поверхня,# повернута до камери, має значення, близьке до (0, 0, -1).field = result.normals.datah, w = field.shape[:2]print(field[h // 2, w // 2])
Зберегти візуалізацію
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreMoGe2s-normal.pt")result = model(SAMPLE_IMAGE) # plot() повертає візуалізоване поле як зображення PIL.result.plot().save("normals.png")

Значення imgsz має бути кратним розміру патча енкодера ViT, що LibreYOLO перевіряє до початку запуску. Для списку зображень виконується по одному прямому проходу на зображення; ця задача не має швидкого шляху зі складеним батчем. Докладніше про джерела, потокову обробку та роботу з результатами див. у розділі передбачення.

Формат датасету

Для валідації нормалей кожному зображенню відповідає триканальний 16-бітний файл PNG такої самої роздільної здатності й з такою самою основою назви, а також необов'язкова маска дійсності.

dataset/  data.yaml  images/    val/room.jpg  normals/    val/room.png  masks/    val/room.png
yaml
path: datasettrain: images/trainval: images/valnormals_dir: normalsmasks_dir: masksnc: 1names: {0: normal}

Цільовий PNG має точно три канали uint16, збережені як RGB. Декодування виконується за формулою n = png / 65535 * 2 - 1 із подальшим повторним нормалізуванням кожного вектора, а декодовані вектори використовують ту саму систему координат камери OpenCV, що й передбачення. Піксель маски вважається дійсним, якщо він ненульовий; якщо файлу маски немає, дійсним є кожен скінченний ненульовий декодований вектор. Недійсні й доповнені цільові пікселі зберігаються всередині як (0, 0, 0) і ніколи не враховуються в метриках. Повний контракт наведено в розділі форматів датасетів.

Навчання

Ці сімейства оцінювання нормалей не мають реалізації навчання. Сторінка MoGe-2 посилається на зафіксовані офіційні контрольні точки для передбачення, валідації та експорту.

Валідація

Метод val() вимірює кут між кожним передбаченим вектором і відповідним еталонним вектором для пікселів, позначених датасетом як дійсні.

Провалідувати й переглянути ключі метрик
from libreyolo import LibreYOLO model = LibreYOLO("LibreMoGe2s-normal.pt")metrics = model.val(data="my-dataset.yaml", imgsz=518) print(metrics["metrics/mean_angular_error"])     # градусиprint(metrics["metrics/median_angular_error"])   # градусиprint(metrics["metrics/within_11_25"])           # відсоток пікселівprint(metrics["metrics/within_22_5"], metrics["metrics/within_30"])

metrics/mean_angular_error і metrics/median_angular_error містять цей кут у градусах, і менше значення є кращим. metrics/within_11_25, metrics/within_22_5 і metrics/within_30 є відсотками дійсних пікселів, кутова похибка яких не перевищує 11.25, 22.5 і 30 градусів, тому більше значення є кращим. Зверніть увагу на одиницю: ці три значення є відсотками, а не частками. fitness дорівнює metrics/within_11_25, поділеному на 100, що приводить вибір найкращої контрольної точки до тієї самої шкали [0, 1], що й для всіх інших задач.

Експорт

Експортована модель нормалей знову завантажується через LibreYOLO() за суфіксом файлу, тому файл .onnx поводиться як контрольна точка й повертає той самий Results.

Експорт
from libreyolo import LibreYOLO model = LibreYOLO("LibreMoGe2s-normal.pt")model.export(format="onnx", imgsz=518)
Запустити експортований файл
from libreyolo import LibreYOLO, SAMPLE_IMAGE # Фабрика визначає маршрут за суфіксом файлу, тому експортований артефакт# завантажується як будь-яка контрольна точка й повертає той самий об'єкт Results.model = LibreYOLO("LibreMoGe2s-normal.onnx")result = model(SAMPLE_IMAGE) print(result.normal_map.data.shape)

Експорт нормалей використовує контракт середовища виконання з фіксованою роздільною здатністю й батчем 1: параметр dynamic і значення batch, відмінне від 1, відхиляються, а imgsz має бути кратним розміру патча енкодера. Підтримку окремих форматів наведено на сторінці MoGe-2 і в повній матриці експорту. Експорт містить аргументи, які приймає кожен формат.

Перевірено з LibreYOLO v1.6.0.