AnnotateIt · Open the app · Models & datasets · Documentation
Unofficial ONNX conversion of EdgeCrafter ECDet-S
Single-file FP32 ONNX (opset 17) conversion of the official EdgeCrafter ECDet-S 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 project | EdgeCrafter — Compact ViTs for Edge Dense Prediction via Task-Specialized Distillation |
| Source code commit | b17f0f340af687e7adf2dff42a49e2eb8250ee20 |
| Model config | ecdetseg/configs/ecdet/ecdet_s.yml |
| Checkpoint | ecdet_s.pth (39,938,420 bytes) |
| Checkpoint SHA-256 | 35340a45101d24a094becf8776aeaa327c9e6b37453e5e81dfd2923c134c4619 |
| model.onnx SHA-256 | e0919a2c617682d049617f97c67ea986d7c9d908220647eb3e26a55c4c24bf87 (40,492,596 bytes) |
| Upstream-reported metric | COCO val2017 AP 51.7 (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
| name | images |
| dtype / layout | float32, NCHW |
| shape | [batch, 3, 640, 640] — batch is dynamic, height/width fixed |
Preprocessing (must be done outside the model):
- Decode to RGB.
- Resize (stretch) directly to 640×640 — no letterbox, no aspect preservation.
float32, divide by 255.- Normalize:
x = (x - mean) / stdwithmean = [0.485, 0.456, 0.406],std = [0.229, 0.224, 0.225](per channel, RGB order). - 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
| output | shape | meaning |
|---|---|---|
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:
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
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): all 7 cases pass strictly (random batch 1 and 2, four real images, real-image batch 2). - Semantic parity on 12 real COCO val2017 images with identical external postprocessing: detections match 1:1 (12/12 images, max box diff < 0.1 px).
- 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_boxesare 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.
Model discussions
Share what you know. Help others. Build trust.
Loading comments...
Keep it about the model. No spam, scams or personal attacks. Links are not allowed in comments or replies. Comment policy