Hacker News
July 20, 20269 min read
Real-Time Object Detection, Instance and Semantic Segmentation
D-FINE-seg is a framework for real-time object detection , instance segmentation , and semantic segmentation - one codebase, one config flag ( task: detect | segment | sem_seg ), five model sizes (N -> X).
One frame, three tasks, one config flag:
Instance segmentation head ( task: segment ) - lightweight mask head on top of D-FINE's HybridEncoder PAN outputs: stride 8/16/32 features fused to 1/4 resolution, then a dot-product between per-query mask embeddings (3-layer MLP) and the shared mask features yields per-instance masks Semantic segmentation head ( task: sem_seg ) - reuses the pretrained instance-seg mask fuser on full-frame features, followed by a small conv neck and 1x1 classifier: no queries, no NMS Mask-aware training - box-cropped BCE + Dice mask losses (instance seg) and CE + multi-class soft Dice with ignore_index (semantic seg), mask supervision inside contrastive denoising, and Dice + sigmoid-focal mask costs in the Hungarian matcher - all train-time only, zero inference cost COCO-pretrained weights for detection and instance segmentation , auto-downloaded on first use - fine-tuning starts from a trained mask decoder, not from scratch Multi-channel inputs - train on RGB + thermal / depth / NIR stacks (4-channel .npy ), not just RGB Modern training stack - Muon optimizer, DDP, EMA, mosaic + affine augs, OneCycle, early stopping, WandB Beyond the model - ByteTrack tracking, SAM3 auto-labeling, Gradio demo, INT8 quantization (OpenVINO / CoreML / LiteRT) Quick Start Installation git clone https://github.com/ArgoHA/D-FINE-seg.git cd D-FINE-seg uv sync This creates a .venv/ with all dependencies pinned by uv.lock . Activate it with source .venv/bin/activate , or run anything via uv run ... (the Makefile already does this).
Pretrained weights are auto-downloaded from Hugging Face into pretrained/ on first use, so no manual setup is needed. To download manually instead, grab dfine_<size>_<dataset>.pt (size β {n, s, m, l, x}, dataset β {coco, obj2coco}) and place it in pretrained/ . Segmentation weights are also available in the Hugging Face model card.
Two annotation formats are supported: YOLO (default) and COCO JSON . Semantic segmentation uses PNG masks instead (see below).
data/dataset/ βββ images/ # all images: .jpg, .png, etc. (.npy for multi-channel - see below) βββ labels/ # all labels: one .txt per image (same filename stem) Detection labels : class_id xc yc w h (normalized)
Segmentation labels : class_id x1 y1 x2 y2 ... xN yN (normalized polygon coordinates)
Input types & channel order : 3-channel .jpg / .png (BGR, read via cv2.imread ), 3-channel .npy (RGB, read via np.load ), or 4-channel .npy (RGB+extras, e.g. RGB+thermal).
data/dataset/ βββ images/ # same as YOLO layout βββ labels/ # one single-channel uint8 .png per image (same stem), pixel value = class id Every pixel gets a class from label_to_name (background included). Pixels with value train.sem_seg.ignore_index (default 255) are excluded from loss and metrics and during inference 255 is the "background" or "ignored" class. make split works unchanged; keep_ratio: True is supported (letterbox pad is filled with ignore_index , so pad pixels don't supervise); coco_dataset: True is not supported for this task.
Set train.in_channels: N (default 3) to train on stacks beyond plain RGB. Supported range is N=3 (RGB) or N=4 (RGB + one extra modality, e.g. thermal, depth, NIR). Higher channel counts are not supported - cv2 / Albumentations ops cap at 4.
Layout is the same; drop the stacks as .npy files (uint8 HWC arrays):
data/dataset/ βββ images/ # one .npy per sample, shape (H, W, N), dtype uint8 βββ labels/ # YOLO .txt (same as 3-channel case) Loader rules (see src/dl/dataset.py ):
Channel-order convention: write the RGB triplet in the first three planes (channels 0..2 ) so they line up with the pretrained RGB stem; extra modalities go in channels 3..N-1 . Example for RGB + thermal: stack as [R, G, B, T] .
Example: src/etl/m3fd_to_yolo.py converts the M3FD RGB+thermal detection benchmark (PASCAL VOC XML + paired Vis/ / Ir/ PNGs) into this exact layout.
Place standard COCO JSON annotation files alongside your images folder. Splits are detected automatically by filename:
data/dataset/ βββ images/ # all images βββ train.json # COCO-format annotations for train split βββ val.json # COCO-format annotations for val split βββ test.json # (optional) COCO-format annotations for test split Enable COCO mode by setting coco_dataset: True in your config (see below). No CSV split generation step is needed - the splits are read directly from the JSON files.
task : detect # detect | segment | sem_seg exp_name : my_exp # experiment name (used in output paths) model_name : s # n / s / m / l / x train : root : /path/to/project # project root, will be used for outputs data_path : /path/to/dataset # folder with images/ and labels/ (YOLO) or *.json files (COCO) coco_dataset : False # set True to use COCO JSON annotations (train.json / val.json / test.json) label_to_name : 0 : class_a 1 : class_b epochs : 75 batch_size : 8 img_size : [640, 640] # (h, w) Usage make split # create train/val CSV splits (test split if configured) make train # train the model make export # export to ONNX, TensorRT, OpenVINO, CoreML, LiteRT make bench # benchmark all exported models on the val set make infer # run on test folder, save visualizations + YOLO txt predictions make check_errors # compare predictions against GT, save only mismatches (FP/FN) make test_batching # find optimal batch size for your GPU make ov_int8 # INT8 accuracy-aware quantization for OpenVINO (can take hours) Notes:
make # train -> export -> bench (does not run split) Or run overwriting configs from CLI
uv run python -m src.dl.train exp_name=my_exp Enable DDP (multi-GPU) by setting train.ddp.enabled: True and train.ddp.n_gpus: N in config. Then just run make train - it auto-launches with torchrun .
Feature Description Muon optimizer Optional NewtonβSchulz optimizer for encoder/decoder attention+MLP matrices DDP Multi-GPU distributed training with SyncBatchNorm AMP Automatic mixed precision (~40% less VRAM, ~15% faster) EMA Exponential moving average of weights Gradient accumulation Effective batch size = batch_size x b_accum_steps Gradient clipping Configurable max norm Mosaic augmentation 4-image mosaic with affine transforms (recommended for detection) Albumentations Rotation, flip, blur, noise, gamma, grayscale, coarse dropout, multiscale OneCycleLR scheduler Separate learning rates for backbone and head Early stopping Configurable patience WandB integration Automatic experiment tracking Optimal threshold search Auto-finds best confidence threshold after training Background warm-up Ignore background-only images for N initial epochs Autoresearch harness Tooling to run agent in autoresearch format, leaves under experiments/ Export Format Half Precision Notes ONNX - With optional fused postprocessor TensorRT FP16 Must be exported on the target GPU. Static input shape only OpenVINO FP16, INT8 Single export for FP32 or FP16 (pick during inference) and separate INT8 quantization script CoreML FP16, INT8 Cross-platform export, inference on macOS / iOS. FP32 and INT8 exported by default LiteRT INT8 On-device TFLite (mobile / edge). FP32 and INT8 exported by default Tip : FP16 is the best latency/accuracy trade-off for GPU (TensorRT) and CPU (OpenVINO). For Apple Silicon (CoreML), FP32 is faster.
After export, a parity self-check ( export.parity , on by default) runs each backend on a shared input and writes one cosine per backend - over the sorted top-K detection scores vs torch - to parity.csv next to the weights.
For task: sem_seg every backend gets the same fused-argmax graph: a single int32 sem_seg output [B, H, W] (label map at input resolution, no detection postprocessor), and parity compares per-pixel argmax agreement instead of score cosine.
Backends Six inference backends in src/infer/ :
Output contract: detection / instance segmentation wrappers return labels , boxes , scores (+ masks [N, H, W] for segment ); sem_seg wrappers return a single sem_seg [H, W] label map at original image resolution. For sem_seg, make infer writes palette overlays + GT-style grayscale PNG label maps (crops and tracking are box-based and skipped).
A simplified ByteTrack ( Zhang et al., ECCV 2022 ) is included for persistent object tracking across video frames - uses constant-velocity motion prediction with EMA-smoothed velocity instead of a Kalman filter, blends IoU with centroid distance in the match cost, and does per-class matching by default.
uv run python -m demo.demo A web UI for uploading images and running inference interactively.
Metrics Detection / instance segmentation - GT objects and predictions are matched one-to-one: a prediction is a TP if IoU > 0.5 (box for detect , mask for segment ) and the class matches; only the highest-IoU prediction per GT counts, extra overlapping ones are FPs; a class mismatch is one FP + one FN.
Semantic segmentation - all metrics come from one pixel confusion matrix accumulated over the whole eval set at original image resolution ( ignore_index pixels excluded). A pixel of class i predicted as j counts as an FN for i and an FP for j - each confused pixel penalizes both classes.
500 Cityscapes val images at original 2048x1024, TensorRT 10.13 FP16, batch 1, RTX 5070 Ti. Every framework runs its own shipped inference code , scored by one validator against the same GT. Confidence thresholds were calculated for each framework separately to maximixe the F1. Two latency columns - e2e (end-to-end, including each framework's CPU preprocessing) and engine (pure TensorRT execute) - because they can disagree. Full protocol and every known asymmetry: cityscapes-benchmark .
model params (M) input conf F1 precision recall IoU e2e ms engine ms D-FINE-seg S 10.29 640x640 0.5 0.703 0.817 0.617 0.446 2.0 1.38 YOLO26-M 21.79 640x640 0.25 0.691 0.792 0.613 0.432 3.03 1.59 RF-DETR-medium 33.39 576x576 0.35 0.673 0.769 0.599 0.409 10.2 1.45 Instance segmentation model params (M) input conf F1 precision recall IoU e2e ms engine ms D-FINE-seg S 11.87 640x640 0.5 0.661 0.749 0.591 0.376 4.1 1.91 YOLO26-M 26.98 640x640 0.25 0.599 0.688 0.53 0.312 5.24 2.08 RF-DETR-seg-medium 35.4 432x432 0.35 0.62 0.789 0.51 0.346 16.33 1.8 Semantic segmentation RF-DETR has no semantic segmentation task, so this one is D-FINE-seg vs YOLO26.
VisDrone - object detection VisDrone dataset - a large-scale drone-captured benchmark with 10 categories across diverse urban and rural scenes (~6500 train / ~550 val / ~1600 test-dev images). YOLO26 trained for 100 epochs, D-FINE for 75. YOLO26 confidence threshold - 0.25, D-FINE - 0.5. F1-score measured with IoU threshold 0.5. Preserved original dataset split (VisDrone2019-DET-train, VisDrone2019-DET-val, VisDrone2019-DET-test-dev). Metrics are reported on test-dev set. Latency measured end-to-end (preprocessing + forward pass + postprocessing) on RTX 5070 Ti with TensorRT FP16 at 640x640, batch size 1.
D-FINE outperforms YOLO26 in fine-tuning setting on VisDrone dataset in F1-score across every model size. D-FINE achieves ~7% higher mean relative F1-score with ~28% latency reduction. Notably, IoU is ~15% higher (mean relative improvement across all models).
TACO dataset (1500 images, 59 effective classes of waste in diverse environments, 86/14 train/val split by batch ID). The benchmarking environment is the same as for VisDrone.
Model Params (M) F1-score IoU Precision Recall Latency (ms) D-FINE-seg N 5.1 0.231 0.106 0.307 0.185 3.2 YOLO26-seg N 2.7 0.062 0.027 0.272 0.035 3.8 D-FINE-seg S 11.9 0.281 0.134 0.405 0.215 3.7 YOLO26-seg S 10.4 0.177 0.080 0.278 0.130 4.3 D-FINE-seg M 21.2 0.296 0.14 0.355 0.254 4.5 YOLO26-seg M 23.6 0.267 0.128 0.365 0.210 5.3 D-FINE-seg L 32.8 0.342 0.167 0.439 0.279 5.0 YOLO26-seg L 28.0 0.287 0.137 0.394 0.226 5.8 D-FINE
Read what's here, then head to the original whenever you're ready - never required.
Continue Reading on Hacker NewsMeasuring What Matters with Jules
Google Developers July 21, 2026