Core ML
Core ML est le format de modèles on-device d'Apple. LibreYOLO trace le détecteur derrière un wrapper de prétraitement propre à chaque famille, de sorte que le graphe converti reçoit toujours une entrée image RGB canonique, puis écrit un .mlpackage au format ML Program avec les métadonnées du modèle attachées.
- Flag
export(format="coreml")- Écrit
- Un bundle .mlpackage (un répertoire) au format ML Program
- Extra
pip install "libreyolo[coreml]"- Se recharge avec
LibreYOLO("weights/LibreYOLO9t.mlpackage") sur macOS- Formes
- Fixes. L'entrée est un ct.ImageType à forme rigide.
- Précision
- FP32, FP16 (half=True). Pas d'INT8.
- Familles
- Détection uniquement, pour yolox, yolo9, rtdetr et rfdetr
Installation
pip install "libreyolo[coreml]"La prédiction exige macOS. LibreYOLO() refuse un .mlpackage sur toute autre
plateforme avec un message qui nomme la plateforme courante, et la matrice de support
enregistre ces combinaisons comme disponibles au motif que la parité au runtime exige un runner macOS.
Export
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9t.pt") # Écrit le bundle weights/LibreYOLO9t.mlpackagepath = model.export(format="coreml")print(path)libreyolo export --model LibreYOLO9t.pt --format coremlmodel.export( format="coreml", imgsz=640, batch=1, half=False, # True convertit en précision de calcul FLOAT16 compute_units="all", # all | cpu_and_gpu | cpu_and_ne | cpu_only output_path=None, # None écrit weights/<stem>.mlpackage) # dynamic est accepté, mais l'entrée est un ct.ImageType de forme fixe,# et les métadonnées embarquées enregistrent dynamic=False dans tous les cas.Le bundle est écrit dans weights/ sous le stem du checkpoint, avec _fp16
ajouté quand half=True. Un .mlpackage est un répertoire, donc copiez l'arbre entier.
Chaque famille est tracée derrière un wrapper de prétraitement, de sorte que le graphe
converti reçoit une seule entrée canonique : RGB, scale=1/255, sans biais, déclarée comme
ct.ImageType. Le wrapper absorbe la convention propre à chaque famille, à savoir BGR dans
la plage 0 à 255 pour YOLOX, moyenne et écart type ImageNet pour RF-DETR,
et identité pour YOLO9 et RT-DETR. C'est pourquoi un consommateur Core ML alimente une
image ordinaire plutôt qu'un tenseur spécifique à la famille.
La conversion vise ML Program avec un deployment target minimum d'iOS 15.
compute_units est stocké sur le modèle converti et peut être redéfini au moment où
l'artefact est chargé.
Les métadonnées du modèle vont dans user_defined_metadata sous forme de chaînes, et c'est là que le
backend lit la famille, la tâche, les noms de classe, la taille d'entrée et le schéma de pose.
NMS embarqué
from libreyolo import LibreYOLO # Détection YOLOX et YOLO9 uniquement, batch 1.LibreYOLO("LibreYOLO9t.pt").export( format="coreml", nms=True, conf=0.25, iou=0.45,)libreyolo export --model LibreYOLO9t.pt --format coreml --nms \ --conf 0.25 --iou 0.45nms=True enveloppe le modèle dans un pipeline Core ML qui se termine par la couche
NonMaximumSuppression d'Apple. Le résultat a deux sorties : confidence, de forme
N par le nombre de classes, et coordinates, de forme N par 4 en xywh normalisé.
Cela s'applique à la détection YOLOX et YOLO9 uniquement, et exige batch 1. Les familles de
style DETR sont refusées par leur nom, parce que la prédiction d'ensembles fait un top-k sur
les queries et les classes sans étape d'IoU et ne peut pas utiliser cette couche. max_det n'est pas
exposé ici non plus ; quand le plafond de détections compte, utilisez plutôt
le NMS embarqué d'ONNX.
Exécuter l'artefact
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO( "weights/LibreYOLO9t.mlpackage", compute_units="all", # ou cpu_and_ne pour fixer le Neural Engine)result = model.predict(SAMPLE_IMAGE)print(result.boxes.xyxy[:3])import coremltools as ctfrom PIL import Image mlmodel = ct.models.MLModel("weights/LibreYOLO9t.mlpackage")print(mlmodel.user_defined_metadata["model_family"])print(mlmodel.user_defined_metadata["names"]) # L'entrée est une image nommée "image" à la taille fixe d'export.image = Image.open(SAMPLE_IMAGE).convert("RGB").resize((640, 640))out = mlmodel.predict({"image": image})print({name: value.shape for name, value in out.items()}) # Le letterboxing et le postprocessing sont à votre charge sur ce chemin.LibreYOLO() reconnaît un répertoire portant le suffixe .mlpackage et renvoie le
même objet Results que le checkpoint. compute_units est le seul argument que la
factory transmet pour ce format, et il accepte all, cpu_and_gpu,
cpu_and_ne et cpu_only. L'argument device est ignoré, parce que Core ML
passe par les compute units à la place.
Le second snippet est le chemin du runtime brut. Le letterboxing, le décodage, le NMS et
le rééchelonnement des coordonnées y sont à votre charge, et les noms de classe vivent dans
user_defined_metadata.
Contraintes
Quatre familles, détection uniquement : yolox, yolo9, rtdetr et rfdetr. Tout le
reste est refusé au preflight, parce que le wrapper de prétraitement conscient de la famille est
ce qui rend correct le contrat d'entrée image fixe, et une famille en dehors de cet ensemble
convertirait avec la mauvaise normalisation. L'erreur nomme ONNX et TorchScript comme
alternatives.
La forme d'entrée est figée par ct.ImageType, donc dynamic=True ne change rien
et les métadonnées enregistrent dynamic=False. Exportez un second bundle pour une seconde
résolution.
half=True convertit en précision de calcul FP16. Il n'y a pas de chemin INT8 depuis cet
exporteur.
Pour la grille complète des familles et des tâches, voir la matrice d'export. Pour le format on-device plus récent d'Apple, voir Core AI. Pour une seule combinaison :
libreyolo formats --family yolo9 --task detect