Core ML
Core ML es el formato de modelos on-device de Apple. LibreYOLO traza el detector detrás de un wrapper de preprocesado propio de cada familia, de modo que el grafo convertido siempre recibe una entrada de imagen RGB canónica, y después escribe un .mlpackage en formato ML Program con los metadatos del modelo adjuntos.
- Flag
export(format="coreml")- Escribe
- Un bundle .mlpackage (un directorio) en formato ML Program
- Extra
pip install "libreyolo[coreml]"- Se recarga con
LibreYOLO("weights/LibreYOLO9t.mlpackage") en macOS- Formas
- Fijas. La entrada es un ct.ImageType de forma rígida.
- Precisión
- FP32, FP16 (half=True). Sin INT8.
- Familias
- Solo detección, para yolox, yolo9, rtdetr y rfdetr
Instalación
pip install "libreyolo[coreml]"La predicción necesita macOS. LibreYOLO() rechaza un .mlpackage en cualquier otra
plataforma con un mensaje que nombra la actual, y la matriz de soporte registra estas
combinaciones como disponibles porque la paridad en tiempo de ejecución necesita un runner macOS.
Exportación
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9t.pt") # Escribe el 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 convierte con precisión de cómputo FLOAT16 compute_units="all", # all | cpu_and_gpu | cpu_and_ne | cpu_only output_path=None, # None escribe weights/<stem>.mlpackage) # dynamic se acepta, pero la entrada es un ct.ImageType de forma fija,# y los metadatos embebidos registran dynamic=False en cualquier caso.El bundle se escribe en weights/ con el stem del checkpoint, añadiendo _fp16
cuando half=True. Un .mlpackage es un directorio, así que copia el árbol entero.
Todas las familias se trazan detrás de un wrapper de preprocesado, de modo que el grafo
convertido recibe una única entrada canónica: RGB, scale=1/255, sin bias, declarada como
ct.ImageType. El wrapper absorbe la convención propia de cada familia, que es BGR en
el rango de 0 a 255 para YOLOX, media y desviación estándar de ImageNet para RF-DETR,
e identidad para YOLO9 y RT-DETR. Por eso un consumidor de Core ML alimenta una
imagen normal en lugar de un tensor específico de la familia.
La conversión apunta a ML Program con un deployment target mínimo de iOS 15.
compute_units se almacena en el modelo convertido y se puede sobrescribir de nuevo
al cargar el artefacto.
Los metadatos del modelo van a user_defined_metadata como cadenas, que es de donde el
backend lee la familia, la tarea, los nombres de clase, el tamaño de entrada y el esquema de pose.
NMS embebido
from libreyolo import LibreYOLO # Solo detección con YOLOX y YOLO9, 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 envuelve el modelo en un pipeline de Core ML que termina en la capa
NonMaximumSuppression de Apple. El resultado tiene dos salidas: confidence, de forma
N por el número de clases, y coordinates, de forma N por 4 como xywh normalizado.
Se aplica solo a la detección con YOLOX y YOLO9, y exige batch 1. Las familias de
estilo DETR se rechazan por nombre, porque la predicción de conjuntos hace un top-k sobre
queries y clases sin paso de IoU y no puede usar esa capa. max_det tampoco se expone
aquí; cuando el tope de detecciones importa, usa el
NMS embebido de ONNX en su lugar.
Ejecutar el artefacto
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO( "weights/LibreYOLO9t.mlpackage", compute_units="all", # o cpu_and_ne para fijar el 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"]) # La entrada es una imagen llamada "image" con el tamaño fijo de exportación.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()}) # El letterboxing y el postprocesado corren de tu cuenta en esta ruta.LibreYOLO() reconoce un directorio con el sufijo .mlpackage y devuelve el
mismo objeto Results que el checkpoint. compute_units es el único argumento que la
factoría pasa a través para este formato, y acepta all, cpu_and_gpu,
cpu_and_ne y cpu_only. El argumento device se ignora, porque Core ML
enruta a través de las compute units.
El segundo snippet es la ruta del runtime a secas. Ahí el letterboxing, el decodificado, el NMS y
el reescalado de coordenadas corren de tu cuenta, y los nombres de clase viven en
user_defined_metadata.
Restricciones
Cuatro familias, solo detección: yolox, yolo9, rtdetr y rfdetr. Cualquier otra
cosa se rechaza en el preflight, porque el wrapper de preprocesado consciente de la familia es
lo que hace correcto el contrato de entrada de imagen fija, y una familia fuera de él se
convertiría con la normalización equivocada. El error nombra ONNX y TorchScript como
alternativas.
La forma de entrada queda fijada de manera rígida por ct.ImageType, así que dynamic=True no cambia nada
y los metadatos registran dynamic=False. Exporta un segundo bundle para una segunda
resolución.
half=True convierte con precisión de cómputo FP16. No hay ruta a INT8 desde este
exportador.
Para la rejilla completa de familias y tareas, consulta la matriz de exportación. Para el formato on-device más reciente de Apple, consulta Core AI. Para una sola combinación:
libreyolo formats --family yolo9 --task detect