TFLite

TFLite — это формат FlatBuffer, который LiteRT исполняет на мобильных и встраиваемых устройствах. LibreYOLO экспортирует статический граф ONNX, конвертирует его через onnx2tf в режиме flatbuffer-direct и кладёт метаданные модели рядом с артефактом в виде сопроводительного JSON-файла.

Флаг
export(format="tflite")
Записывает
Один файл .tflite плюс сопроводительный файл метаданных .tflite.json
Дополнительно
pip install "libreyolo[tflite]"
Загружается обратно
LibreYOLO("weights/LibreYOLO9t.tflite")
Формы
Только статические. dynamic=True отклоняется.
Точность
Только FP32. half=True и int8=True отклоняются.
Требуется
Python 3.12 или новее, потому что onnx2tf 2.4.x не публикует wheel-пакеты под более старые версии

Установка

Установка
# LiteRT — текущее название TensorFlow Lite у Google. Оба extra ставят# один и тот же тулчейн и дают на выходе один и тот же .tflite.pip install "libreyolo[tflite]"
Проверка версии Python
python -c "import sys; print(sys.version_info >= (3, 12))"

Этот extra подтягивает onnx2tf для конвертации и ai-edge-litert для запуска результата — обе зависимости за маркером Python 3.12. На более старом интерпретаторе экспорт вызывает ImportError, который называет требование к версии, а не падает внутри конвертера.

libreyolo[litert] ставит ровно то же самое. Строка формата litert — псевдоним для tflite, и выходной файл в обоих случаях .tflite.

Экспорт

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9t.pt") # Записывает weights/LibreYOLO9t.tflite и weights/LibreYOLO9t.tflite.jsonpath = model.export(format="tflite", imgsz=640)print(path)
CLI
libreyolo export --model LibreYOLO9t.pt --format tflite --imgsz 640 # "litert" принимается как псевдоним и ведёт к тому же экспортёру.libreyolo export --model LibreYOLO9t.pt --format litert --imgsz 640
Аргументы
model.export(    format="tflite",    imgsz=640,        # int или (высота, ширина)    batch=1,    simplify=True,    # onnxsim поверх промежуточного ONNX    output_path=None, # None пишет в weights/<stem>.tflite    verbose=False,    # True выводит лог onnx2tf) # dynamic=True вызывает ValueError: конвертеру нужны статические формы.# half=True и int8=True отклоняются ещё до трассировки.

Семейство и задача проверяются раньше всего остального, поэтому неподдерживаемая комбинация падает сразу же с конкретной ошибкой конвертера или среды выполнения, из-за которой её и не пустили, а не с общим сообщением. Сама конвертация — вызов onnx2tf в подпроцессе в режиме flatbuffer_direct поверх статического промежуточного ONNX.

Метаданные лежат в сопроводительном файле. weights/LibreYOLO9t.tflite.json несёт семейство, задачу, имена классов, размер входа и схему позы; в самом FlatBuffer поля метаданных LibreYOLO нет, поэтому два файла ходят вместе.

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

Через LibreYOLO
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("weights/LibreYOLO9t.tflite")result = model.predict(SAMPLE_IMAGE)print(result.boxes.xyxy[:3])
Чистый LiteRT
import json import numpy as npfrom ai_edge_litert.interpreter import Interpreter interpreter = Interpreter(model_path="weights/LibreYOLO9t.tflite")interpreter.allocate_tensors()detail = interpreter.get_input_details()[0]print(detail["shape"], detail["dtype"])   # NHWC, а не NCHW interpreter.set_tensor(detail["index"], np.zeros(detail["shape"], np.float32))interpreter.invoke()for output in interpreter.get_output_details():    print(output["name"], interpreter.get_tensor(output["index"]).shape) # Имена классов, задача и размер входа лежат в сопроводительном файле.meta = json.load(open("weights/LibreYOLO9t.tflite.json"))print(meta["model_family"], meta["task"], meta["names"]) # Предобработка, транспонирование NCHW в NHWC и постобработка — на вас.

LibreYOLO() выбирает ветку по суффиксу .tflite и возвращает тот же объект Results, что и чекпойнт. Бэкенд читает сопроводительный файл, транспонирует тензор NCHW в NHWC, когда интерпретатор просит вход с каналами в конце, применяет масштаб квантизации и нулевую точку интерпретатора там, где они есть, и транспонирует выходы обратно в раскладку, которую ждёт постобработка LibreYOLO.

Второй сниппет — путь через чистую среду выполнения. Предобработка, транспонирование раскладки, декодирование, NMS и пересчёт координат там целиком на вас, а деталь с раскладкой упускают чаще всего: onnx2tf выдаёт входы с каналами в конце, поэтому тензор формы (1, 3, 640, 640) не привяжется.

Ограничения

Только статические формы. dynamic=True вызывает ValueError ещё до трассировки, а холст экспорта фиксируется на том значении, в которое разрешился imgsz.

Только FP32. half=True и int8=True отклоняются на валидации, поэтому развёртывание с квантизацией через этот экспортёр сегодня недоступно.

Покрытие здесь уже, чем у графовых форматов, и определяется измерениями, а не семейством. Среди проверенных комбинаций — детекция на YOLO9, YOLOX и YOLO-NAS, семантическая сегментация PIDNet, четыре семейства CNN-классификации, эмбеддинги DINOv2 и SigLIP2, классификация SigLIP2, выделение границ TEED и DexiNed, восстановление Real-ESRGAN и SwinIR. У SwinIR есть дополнительная оговорка: паритет держится, когда размеры источника точно совпадают с холстом экспорта, а источники меньшего размера дополняются до холста перед запуском трансформера, и это может расходиться с нативным инференсом на переменном размере.

Заблокированные записи называют конкретную причину отказа, и её стоит прочитать до попыток обойти ограничение. Несколько примеров: детекция RF-DETR конвертируется на своём нативном холсте 384, но LiteRT не может её разместить, потому что STRIDED_SLICE получает вход выше поддерживаемого ранга 5-D; PicoDet отклоняется, потому что RESHAPE отображает 19 200 входных элементов в 9 600 выходных; D-FINE роняет конвертер на обработке форм в GatherElements; RTMDet экспортируется и загружается обратно с сохранением сырого паритета, но публичные рамки падают до 0.911 IoU с расхождением координат в 29.9 px.

Полную сетку семейств и задач смотрите в матрице экспорта. Для одной комбинации, вместе со строкой причины, стоящей за блокировкой:

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

Прочитано из libreyolo/export/tflite.py, libreyolo/export/exporter.py, libreyolo/export/support.py, libreyolo/backends/tflite.py и pyproject.toml в ветке dev.