Переглянути як 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 є спеціалізованим варіантом: монокулярною моделлю геометрії з одним прямим проходом і трьома розмірами енкодера. LibreYOLO не копіює ці контрольні точки до своєї організації; під час завантаження відповідний розмір отримується з офіційних репозиторіїв у зафіксованій ревізії та перевіряється за записаною контрольною сумою SHA-256.

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

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

Під час першого використання ваги 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() візуалізує поле; метод визначено для результатів нормалей і країв.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: dataset
train: images/train
val: images/val
normals_dir: normals
masks_dir: masks
nc: 1
names: {0: normal}

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

Навчання

Жодне сімейство нормалей не має реалізації навчання: train() породжує NotImplementedError для обох. На сторінці 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.5.0.