CoolFace
Modelpublic

AnnotateIt/edgecrafter-ecdet-m-onnx

sourceHugging Faceapache-2.0updated 8d agoView on Hugging Face
1likes19downloads
Model Card

<!-- annotateit-brand:start --> <p><a href="https://huggingface.co/AnnotateIt"><img src="https://huggingface.co/spaces/AnnotateIt/README/resolve/d399a89b9d5dcf41afbe7cf29bf99c9028bc51e2/assets/annotateit-logo.png" width="48" height="48" alt="AnnotateIt"></a></p>

[AnnotateIt](https://annotateit.ai/) · [Open the app](https://app.annotateit.ai/) · [Models & datasets](https://huggingface.co/AnnotateIt) · [Documentation](https://annotateit.ai/docs/) <!-- annotateit-brand:end -->

Unofficial ONNX conversion of EdgeCrafter ECDet-M

Single-file FP32 ONNX (opset 17) conversion of the official EdgeCrafter ECDet-M object-detection checkpoint, exporting the raw model outputs (no NMS, no sigmoid, no top-k, no resizing — all pre/postprocessing stays outside the graph).

This is an unofficial conversion. It is a modification of the original EdgeCrafter release (PyTorch → ONNX, plus embedded metadata and validation artifacts) and is not endorsed by the EdgeCrafter authors.

Provenance

Upstream projectEdgeCrafter — Compact ViTs for Edge Dense Prediction via Task-Specialized Distillation
Source code commitb17f0f340af687e7adf2dff42a49e2eb8250ee20
Model configecdetseg/configs/ecdet/ecdet_m.yml
Checkpointecdet_m.pth (78,160,384 bytes)
Checkpoint SHA-256c4cdf8bcd3b27c7903e422acd03caf733b5e1bfd664550bce43e50e2a3bbdc6e
model.onnx SHA-256fbf2a0e6d4c6273e4850c06912e9767e8d0105dc6ea7aec62fe009b891977fbc (78,156,688 bytes)
Upstream-reported metricCOCO val2017 AP 54.3 (as published in the EdgeCrafter README; not re-measured for this conversion)

The checkpoint was loaded on CPU with strict=True (0 missing / 0 unexpected keys) following the official export flow, switched to deploy/eval mode, and traced with the TorchScript ONNX exporter. See export/export_raw_onnx.py for the exact, reproducible procedure (repeated runs produce a byte-identical file).

Input contract

nameimages
dtype / layoutfloat32, NCHW
shape[batch, 3, 640, 640] — batch is dynamic, height/width fixed

Preprocessing (must be done outside the model):

  1. 1.Decode to RGB.
  2. 2.Resize (stretch) directly to 640×640 — no letterbox, no aspect preservation.
  3. 3.float32, divide by 255.
  4. 4.Normalize: x = (x - mean) / std with mean = [0.485, 0.456, 0.406], std = [0.229, 0.224, 0.225] (per channel, RGB order).
  5. 5.HWC → CHW, add batch dimension.

This mirrors the official evaluation pipeline (configs/ecdet/ecdet.yml val transforms: Resize [640,640] → ConvertPILImage(float32, scale=True) → Normalize(mean, std)).

Output contract

outputshapemeaning
pred_logits[batch, 300, 80]raw class logits (sigmoid/focal scheme; sigmoid is not applied inside the graph)
pred_boxes[batch, 300, 4]normalized `cxcywh` boxes, relative to the 640×640 input

300 object queries, 80 contiguous COCO2017 classes. There is no orig_target_sizes input and no labels/scores postprocessing — apply your own.

Required external postprocessing:

python
probs  = 1 / (1 + np.exp(-pred_logits))        # sigmoid
scores = probs.max(-1); labels = probs.argmax(-1)
keep   = scores >= threshold                    # e.g. 0.4 (or use top-k)
cx, cy, w, h = boxes[keep].T                    # normalized cxcywh
xyxy = np.stack([cx-w/2, cy-h/2, cx+w/2, cy+h/2], -1).clip(0, 1)
xyxy *= [orig_w, orig_h, orig_w, orig_h]        # scale to the ORIGINAL image size

DETR-style set prediction — NMS is not required.

Class mapping

Contiguous COCO2017 ids 0..79 (0=person, 1=bicycle, 2=car, …, 79=toothbrush), taken from the official EdgeCrafter dataset code (engine/data/dataset/coco_dataset.py, mscoco_category2name). The full mapping is embedded in the ONNX metadata key names and duplicated in config.json. Identical for ECDet-S and ECDet-M.

ONNX Runtime example

python
import json, numpy as np, onnxruntime as ort
from PIL import Image

sess = ort.InferenceSession("model.onnx", providers=["CPUExecutionProvider"])
names = json.loads(sess.get_modelmeta().custom_metadata_map["names"])

img = Image.open("photo.jpg").convert("RGB")
ow, oh = img.size
x = np.asarray(img.resize((640, 640), Image.BILINEAR), np.float32) / 255.0
x = (x - [0.485, 0.456, 0.406]) / [0.229, 0.224, 0.225]
x = x.transpose(2, 0, 1)[None].astype(np.float32)

logits, boxes = sess.run(None, {"images": x})
probs = 1 / (1 + np.exp(-logits[0]))
scores, labels = probs.max(-1), probs.argmax(-1)
for i in np.where(scores >= 0.4)[0]:
    cx, cy, w, h = boxes[0, i]
    box = [(cx-w/2)*ow, (cy-h/2)*oh, (cx+w/2)*ow, (cy+h/2)*oh]
    print(names[str(labels[i])], round(float(scores[i]), 3), [round(v, 1) for v in box])

Validation summary

Full machine-readable results: validation-report.json (status: passed). Highlights:

  • —onnx.checker (full) + strict shape inference pass; single file, no external data, no custom operator domains; opset 17.
  • —ONNX Runtime CPU: batch 1 and batch 2 verified; batched rows are bit-identical to single-image runs (dynamic batch works).
  • —PyTorch vs ONNX Runtime parity (rtol=1e-3, atol=1e-4, np.testing.assert_allclose): 6 of 7 cases pass strictly. On one real image two queries with encoder scores tying within ~1e-6 appear in swapped order between PyTorch and ONNX Runtime; after row matching, all 300 query rows satisfy the strict tolerance (documented in detail in the report — this is float-tie reordering inside the model's internal TopK, not an export defect).
  • —Semantic parity on 12 real COCO val2017 images with identical external postprocessing: detections match 1:1 (12/12 images).
  • —Re-running the export produces a byte-identical model.onnx.

Limitations

  • —Some low-confidence raw queries may produce box coordinates outside [0,1]. Apply confidence filtering and clip coordinates before scaling to the original image.
  • —Fixed 640×640 input; only the batch dimension is dynamic.
  • —FP32 only (no FP16/INT8 variants in this release).
  • —pred_logits/pred_boxes are raw — you must apply sigmoid, thresholding and coordinate scaling yourself (see above).
  • —The internal encoder TopK orders the 300 queries by score; queries whose scores tie within float precision may appear in a different order across runtimes. Treat the output as an unordered set.
  • —COCO AP was not re-measured for the ONNX model; the AP figure above is the upstream-reported PyTorch number.
  • —The trace fixes the ViT spatial resolution; use exactly 3×640×640 inputs.

License and attribution

Released under the Apache License 2.0 (see LICENSE), the same license as the upstream project. Original work: © 2026 The EdgeCrafter Authors (Intellindust AI Lab), with components derived from D-FINE and RT-DETR — see NOTICE. The ONNX conversion is a modification of the original model; this repository is not endorsed by the EdgeCrafter developers.