Skip to content

feat: add YOLO auto-labeling with ONNX Runtime - #110

Merged
developer0hye merged 11 commits into
masterfrom
feat/auto-label-onnx
Feb 16, 2026
Merged

feat: add YOLO auto-labeling with ONNX Runtime#110
developer0hye merged 11 commits into
masterfrom
feat/auto-label-onnx

Conversation

@developer0hye

@developer0hye developer0hye commented Feb 16, 2026

Copy link
Copy Markdown
Owner

Summary

Add auto-labeling capability using ONNX Runtime (CPU only) for Ultralytics YOLO models (.onnx). Users can load a pre-trained model and auto-detect objects on the current image or batch-process all images, then review and correct results using the existing manual annotation tools.

Key Changes

  • New YoloDetector class (yolo_detector.h/cpp): Encapsulates ONNX Runtime inference with letterbox preprocessing, NMS postprocessing, and auto-detection of YOLOv5 ([B,N,C+5]) vs YOLOv8/11/12/26 ([B,C+4,N]) output formats. Reads ONNX metadata (class names, input size, task, end-to-end flag) for zero-config model loading.
  • Auto-label toolbar in MainWindow: Load Model button, confidence threshold slider (1-99%), Auto Label (current image), Auto Label All (batch with progress dialog)
  • Keyboard shortcut: R key for quick auto-labeling of the current image
  • Undo support: Auto-label results can be undone with Ctrl+Z
  • Class list mismatch warning: When the model's class list differs from the loaded label list, auto-label is disabled with a warning dialog explaining the mismatch
  • Conditional compilation: #ifdef ONNXRUNTIME_AVAILABLE — app still builds and works without ONNX Runtime
  • CI/CD: Downloads and bundles ONNX Runtime v1.24.1 pre-built binaries for Windows, Linux, and macOS
  • CI accuracy test (Linux only): Validates C++ inference matches Ultralytics Python inference for YOLOv5n, YOLOv8n, YOLO11n, and YOLO26n using IoU-based detection matching
  • Helper script: scripts/download_onnxruntime.sh for local development setup

Bug Fixes

  • Fix out-of-bounds read in preprocess: constScanLine(y) already returns a pointer to row y, so the pixel offset should be x*3, not y*bytesPerLine + x*3. The old code doubled the y offset, reading past the image buffer for large images.
  • Fix dynamic-shape ONNX models: Models with dynamic output dimensions (-1) are now handled correctly using runtime output shape instead of load-time shape.

Supported Models

Any Ultralytics model exported with model.export(format="onnx"):

  • YOLOv5 (anchor-based, objectness score)
  • YOLOv8, YOLO11, YOLO12, YOLO26 (anchor-free, same output format)
  • End-to-end models (NMS baked in, [1, maxDet, 6] output)

CI Accuracy Test Results

All 4 model series pass with 100% detection match rate:

Model Python C++ Match Result
YOLOv5n 2 dets 2 dets 100% PASS
YOLOv8n 2 dets 2 dets 100% PASS
YOLO11n 2 dets 2 dets 100% PASS
YOLO26n 1 det 1 det 100% PASS

How to Use

  1. Open images and class list as usual
  2. Click Load Model → select a .onnx file
  3. Adjust confidence threshold with the slider
  4. Click Auto Label (or press R) to detect objects on the current image
  5. Click Auto Label All to batch-process all images
  6. Review and correct results using existing annotation tools

🤖 Generated with Claude Code

developer0hye and others added 8 commits February 16, 2026 19:00
Add auto-labeling capability using ONNX Runtime (CPU) for Ultralytics
YOLO models. Users can load a .onnx model exported from Ultralytics
and auto-detect objects on the current image or all images in batch.

Key changes:
- New YoloDetector class (yolo_detector.h/cpp) encapsulating ONNX
  Runtime inference, letterbox preprocessing, and NMS postprocessing
- Auto-detect YOLOv5 ([B,N,C+5]) vs YOLOv8+ ([B,C+4,N]) output format
- Auto-label toolbar in MainWindow with Load Model, confidence slider,
  Auto Label (current), and Auto Label All (batch) buttons
- Keyboard shortcut: R key for auto-labeling current image
- Conditional compilation (#ifdef ONNXRUNTIME_AVAILABLE) so the app
  still builds without ONNX Runtime
- CI workflow downloads and bundles ONNX Runtime for all 3 platforms
- Helper script (scripts/download_onnxruntime.sh) for local development

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: developer0hye <developer.0hye@gmail.com>
- Read model metadata (names, task, stride, imgsz, end2end, author, description) from ONNX files
- Auto-populate class names from model metadata when no .names file is loaded
- Support end-to-end models (NMS baked in, output [1, maxDet, 6])
- Validate task type: reject non-detection models with clear error messages
- Detect specific YOLO version (V5, V8, V11, V12, V26) from metadata description
- Use metadata imgsz for dynamic input shapes instead of hardcoded 640

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: developer0hye <developer.0hye@gmail.com>
Document the auto-label feature covering supported Ultralytics models,
ONNX metadata usage, inference pipeline, and conditional build setup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: developer0hye <developer.0hye@gmail.com>
Point to specific Ultralytics source files (exporter.py, autobackend.py,
ops.py) as reference for ONNX metadata schema and output formats.
Instruct future maintainers to check upstream before modifying rather
than relying solely on hardcoded model lists.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: developer0hye <developer.0hye@gmail.com>
- Use actual runtime output shape (not load-time m_version) to choose
  postprocess path in detect(), fixing dynamic-shape models where
  output dims are -1 at load time but concrete after inference
- Consolidate input dimension resolution: fixed shape > metadata imgsz > 640
- Reorder loadModel() to read metadata before resolving input dimensions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: developer0hye <developer.0hye@gmail.com>
When both the user's class file and the model's metadata class names
exist but don't match (different count or different names), show a
warning dialog and disable the auto-label buttons to prevent silently
producing incorrect labels.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: developer0hye <developer.0hye@gmail.com>
constScanLine(y) returns a pointer to the start of row y, so the
pixel offset within the row is just x*3. The old code used
y*bytesPerLine + x*3 as the offset from the row pointer, doubling
the y component and reading past the image buffer for y >= newH/2.

Signed-off-by: developer0hye <developer.0hye@gmail.com>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: developer0hye <developer.0hye@gmail.com>
Add a CI step (Linux only) that validates our C++ ONNX inference
produces results matching Ultralytics Python inference. For each
model series (YOLOv5n, YOLOv8n, YOLO11n, YOLO26n), the test
exports to ONNX, runs both engines on the same image, and compares
detections using IoU matching with defined tolerances.

New files:
- tests/test_inference.pro: qmake project for CLI test binary
- tests/test_inference.cpp: loads ONNX model, runs detect(), outputs JSON
- tests/run_accuracy_test.py: orchestrates export, inference, comparison

Signed-off-by: developer0hye <developer.0hye@gmail.com>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: developer0hye <developer.0hye@gmail.com>
developer0hye and others added 3 commits February 16, 2026 20:34
Allow passing an ONNX model path as a CLI argument to launch with
auto-labeling ready. Arguments are detected by extension — .onnx files
load as YOLO models, other files load as class name lists. This enables
flexible invocation patterns:
  ./YoloLabel <dir> <classes> <model.onnx>
  ./YoloLabel <dir> <model.onnx>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: developer0hye <developer.0hye@gmail.com>
Add Q_UNUSED(onnxModelPath) in the #else branch to suppress unused
variable warnings when building without ONNX Runtime. Document that
`open YoloLabel.app --args` on macOS sets cwd to / so absolute paths
are required for CLI arguments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: developer0hye <developer.0hye@gmail.com>
@developer0hye
developer0hye merged commit 2da54cf into master Feb 16, 2026
5 checks passed
@developer0hye
developer0hye deleted the feat/auto-label-onnx branch February 16, 2026 11:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant