MNN

MNN є полегшеним рушієм інференсу Alibaba. LibreYOLO експортує статичний граф ONNX, перетворює його інструментом mnnconvert із пакета MNN і записує супровідний файл JSON із назвами входів та виходів, фіксованою формою входу й назвами класів.

Прапорець
export(format="mnn")
Створює
Один файл .mnn і супровідний файл метаданих .mnn.json
Додатково
pip install "libreyolo[mnn]"
Повторне завантаження
LibreYOLO("weights/LibreYOLO9t.mnn")
Форми
Фіксовані NCHW. dynamic=True відхиляється.
Точність
Лише FP32 і лише CPU.
Завдання
У цій версії лише виявлення

Встановлення

Встановлення
# Додатковий набір містить libreyolo[onnx]: MNN перетворює проміжний файл ONNX.pip install "libreyolo[mnn]"
Перевірити наявність конвертера в шляху
mnnconvert --version

Додатковий набір залежностей містить libreyolo[onnx], оскільки перетворення виконується через проміжний файл ONNX. Він також установлює виконуваний файл mnnconvert, який експортер спочатку шукає поряд з активним інтерпретатором Python, а потім у PATH. Якщо конвертера немає, виникає ImportError із назвою команди встановлення замість збою посеред перетворення.

Експорт

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9t.pt") # Створює weights/LibreYOLO9t.mnn і weights/LibreYOLO9t.mnn.jsonpath = model.export(format="mnn", imgsz=640)print(path)
CLI
libreyolo export --model LibreYOLO9t.pt --format mnn --imgsz 640
Аргументи
model.export(    format="mnn",    imgsz=640,        # ціле число або (висота, ширина)    batch=1,          # вбудовується в артефакт    simplify=True,    # onnxsim для проміжного файлу ONNX    output_path=None, # None створює weights/<stem>.mnn    verbose=False,    # True транслює журнал mnnconvert) # dynamic=True спричиняє ValueError. half=True та int8=True відхиляються.

Перед передаванням графа експортер читає контракт входу ONNX і відхиляє все, що не може виразити: більше одного входу зображення або форму входу із символьною розмірністю. MNN у цій версії потребує повністю фіксованої форми NCHW, а batch вбудовується в артефакт, а не узгоджується під час завантаження.

Супровідний файл не є необов'язковим службовим записом. weights/LibreYOLO9t.mnn.json містить назви входів і виходів, фіксовану форму входу, батч, назви класів, використану версію MNN і бекенд, для якого побудовано артефакт. Середовище виконання перевіряє кожне з цих полів під час завантаження.

У Windows MNN 3.6.1 іноді завершує перетворення, а потім аварійно закривається під час завершення процесу з порушенням доступу або станом fail-fast. Експортер розпізнає ці конкретні коди виходу й вважає перетворення успішним, якщо вихідний файл наявний.

Запуск артефакту

Через LibreYOLO
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("weights/LibreYOLO9t.mnn")result = model.predict(SAMPLE_IMAGE)print(result.boxes.xyxy[:3])
Безпосередньо через MNN
import json import MNNimport numpy as np meta = json.load(open("weights/LibreYOLO9t.mnn.json"))print(meta["mnn_input_names"], meta["mnn_output_names"], meta["mnn_input_shape"]) runtime = MNN.nn.create_runtime_manager(    ({"backend": 0, "precision": 1, "numThread": 4},))module = MNN.nn.load_module_from_file(    "weights/LibreYOLO9t.mnn",    meta["mnn_input_names"],    meta["mnn_output_names"],    runtime_manager=runtime,    dynamic=False,    shape_mutable=False,) blob = np.zeros(meta["mnn_input_shape"], dtype=np.float32)input_var = MNN.expr.const(    blob, list(blob.shape), MNN.expr.NCHW, MNN.expr.float)outputs = module.forward([input_var])for out in outputs:    print(np.array(MNN.expr.convert(out, MNN.expr.NCHW).read()).shape) # На цьому шляху попередня та подальша обробка покладаються на вас.

LibreYOLO() визначає маршрут за суфіксом .mnn і повертає той самий об'єкт Results, що й контрольна точка. Завантаження навмисно суворе: супровідний файл має оголосити format=mnn, mnn_backend=cpu, dynamic=false, precision=fp32, розмір, завдання виявлення, фіксовану додатну форму NCHW, що узгоджується із записаним розміром зображення, і назви класів для кожного індексу від 0 до nc - 1. Будь-яка невідповідність спричиняє помилку без спроб угадати значення.

Передбачення з imgsz, відмінним від використаного для побудови артефакту, також спричиняє помилку, а device ігнорується з попередженням, оскільки тут експортовані моделі MNN працюють на CPU.

Другий фрагмент показує шлях безпосередньо через середовище виконання. На цьому шляху попередня обробка, декодування, NMS і масштабування координат покладаються на вас, а назви входів і виходів беруться із супровідного файлу, оскільки завантажувачу модулів MNN їх потрібно передати явно.

Обмеження

Лише виявлення. Бекенд відмовляється завантажувати будь-яке інше завдання, і сторона експорту поводиться так само: за межами записаних комбінацій попередня перевірка спричиняє помилку «MNN v1 не має реалізованого контракту середовища виконання для цього сімейства й завдання».

FP32, CPU і фіксована форма. dynamic=True спричиняє ValueError, а half=True та int8=True відхиляються під час валідації.

Валідовані сімейства виявлення: YOLO9, YOLO9-E2E, YOLO9-P2, RF-DETR, EC, RT-DETR, RT-DETRv2, RT-DETRv4, D-FINE, DEIM і YOLO-NAS. Кожне з них охоплено перетворенням, повторним завантаженням свіжого артефакту, виконанням MNN на CPU, перевірками метаданих і зіставленим паритетом виявлень після NMS із моделлю PyTorch. DEIMv2 перетворюється, повторно завантажується, виконується та зберігає виявлення після NMS, але його проміжний шлях ONNX має неповний паритет оцінок на рівні запитів, тому його записано як доступний, а не валідований.

Повну таблицю сімейств і завдань наведено в матриці експорту. Для однієї комбінації:

Перевірити сімейство й завдання перед експортом
libreyolo formats --family yolo9 --task detect

Перевірено за файлами libreyolo/export/mnn.py, libreyolo/export/exporter.py, libreyolo/export/support.py, libreyolo/backends/mnn.py і pyproject.toml у гілці dev.