Deploy

A package you drop into Xcode.

Training is PyTorch on a Mac. The phone runs Core ML. There is no Python on iOS.

Export

Inference-only trace, fused Conv–BN, static DFL grids, FP16 ML Program, iOS 16 / macOS 13. ReLU: 8-bit palettes on ANE. SiLU convert: dense FP16 on GPU. RF-DETR: FP16 on the Neural Engine, palettes off. Optional INT8.

Letterbox

The camera frame is padded to imgsz with gray 114. Same pad and ratio as training. Then boxes map back.

Host decode

DFL: class-aware NMS in Swift. E2E: top-300, no NMS. RF-DETR: (1, Q, 6), no NMS. Segmentation: three tensors, assemble after NMS.

Export

One command writes the artifact the iPhone loads.

coreyolo export --weights weights/app.coreyolo --imgsz 640
# ReLU: FP16 + 8-bit palettes, CPU_AND_NE
# SiLU convert: dense FP16, CPU_AND_GPU
# RF-DETR: FP16, CPU_AND_NE, palettes off, ImageNet norm inside the graph
# coreyolo export --weights weights/app.coreyolo --imgsz 640 --no-palette
# coreyolo export --weights weights/app.coreyolo --imgsz 640 --int8
model.export(imgsz=640)

The trace is inference-only: GELAN has no PGI aux nodes; E2E drops the one-to-many train head. DFL grids are cached as static buffers so Core ML never sees meshgrid, arange, or -1 views. Input shape is fixed (1, 3, imgsz, imgsz). ReLU-family graphs convert with CPU_AND_NE then palettize. Converted SiLU stays dense FP16 on GPU. RF-DETR follows LibreYOLO’s Core ML contract for this family — one fixed RGB image, ImageNet normalization inside the graph, set prediction, no NMS — and CoreYOLO pins that package to FP16 on the Neural Engine. Palettes stay off. Skip palettes with --no-palette; use --int8 for linear quant instead.

A Core ML package inherits the checkpoint’s license. Models you train here are MIT. See Licenses.

Built for the Neural Engine

Dynamic YOLO ops — train-time aux heads, meshgrid decoders, -1 reshapes — are what drop a Core ML graph to CPU or GPU. CoreYOLO keeps those out of the package.

Inference only

YOLOv9 PGI auxiliary branches add nothing at run time. This GELAN graph never had them. E2E export is the one-to-one head only.

Static grids

Anchor-free DFL decode uses cached buffers for the given imgsz. No torch.meshgrid or arange in the ML Program.

Static shapes

Every view / reshape on the export path is a known size. NMS stays on the host so the Neural Engine never runs it.

Swift

Use MLModel directly. This graph is raw tensors, not Vision VNRecognizedObjectObservation.

let config = MLModelConfiguration()
config.computeUnits = .cpuAndNeuralEngine   // ReLU and FP16 RF-DETR; .cpuAndGPU for converted SiLU
let model = try MLModel(contentsOf: url, configuration: config)

A camera sample lives in examples/ios: letterbox, host NMS, iOS 16+. It defaults to Neural Engine. Drag CoreYOLO.mlpackage into the Xcode target, set a signing team, run on a device.

Open the iOS sample ›

Compute units

Match the flag to the activation. ReLU, ReLU6, StarReLU, and HardSwish belong on the Neural Engine. Converted YOLOv9 weights are SiLU — prefer GPU for those, or train ReLU from scratch for ANE.

Flag Core ML Use
auto CPU_AND_NE, then GPU Core ML load: Neural Engine first. Use this for ReLU packages.
gpu CPU_AND_GPU CLI default. PyTorch MPS, or converted SiLU Core ML on GPU.
ane CPU_AND_NE ReLU / StarReLU fused graphs, and FP16 RF-DETR. iOS sample default.
all ALL Let the OS split GPU and ANE.
cpu CPU_ONLY Debug.