Development Guide
Architecture overview, extending YOLOs-CPP, and debugging.
Architecture
include/yolos/
├── core/ # Shared utilities
│ ├── types.hpp # Detection, Segmentation types
│ ├── preprocessing.hpp # Letterbox, normalization
│ ├── nms.hpp # Non-maximum suppression
│ ├── drawing.hpp # Visualization
│ ├── version.hpp # YOLO version detection
│ ├── utils.hpp # Helper functions
│ └── session_base.hpp # ONNX session wrapper
├── tasks/ # Task implementations
│ ├── detection.hpp # YOLODetector
│ ├── segmentation.hpp # YOLOSegDetector
│ ├── pose.hpp # YOLOPoseDetector
│ ├── obb.hpp # YOLOOBBDetector
│ ├── classification.hpp # YOLOClassifier
│ └── yoloe.hpp # YOLOEDetector, YOLOESegDetector (open-vocabulary)
└── yolos.hpp # Master include
Core Components
Preprocessing (preprocessing.hpp)
// Letterbox with padding
cv::Mat blob = yolos::preprocessing::letterBoxToBlob(
image,
cv::Size(640, 640),
scalePad // Returns scale and padding info
);
NMS (nms.hpp)
// Class-aware batched NMS
std::vector<int> indices;
yolos::nms::NMSBoxesFBatched(
boxes, scores, classIds,
confThreshold, iouThreshold,
indices
);
Drawing (drawing.hpp)
yolos::drawing::drawBoundingBox(image, box, label, color);
yolos::drawing::drawMask(image, mask, color, alpha);
yolos::drawing::drawKeypoints(image, keypoints);
Adding a New YOLO Version
Step 1: Update Version Enum
// include/yolos/core/version.hpp
enum class YOLOVersion {
V5, V6, V7, V8, V9, V10, V11, V12, V26,
VNew // Add your version
};
Step 2: Implement Postprocessing
// include/yolos/tasks/detection.hpp
void postprocessVNew(/* params */) {
// Parse model output
// Apply NMS
// Return detections
}
Step 3: Update Factory
switch (version) {
case YOLOVersion::VNew:
return postprocessVNew(...);
// ...
}
Step 4: Add Tests
// tests/detection/compare_results.cpp
// Add model to test suite
Open-Vocabulary (YOLOE)
YOLOE is not a new output-tensor layout: exports match the same postprocessing as the backbone
(YOLO11 → standard detection/seg; YOLO26 → end-to-end seg). Integration lives in
include/yolos/tasks/yoloe.hpp as thin wrappers over
YOLODetector / YOLOSegDetector with inline class names, setClasses(), and agnostic NMS defaults.
- ONNX semantics: Ultralytics documents
set_classes()beforeexport(format="onnx")for text-prompt models; that bakes the vocabulary into the graph. C++ supplies matching strings for labeling—see Model Guide — YOLOE and ONNX runtime. Prompt-free*-pfmodels use a large fixed vocabulary; the.namesfile line count must match the export. - Export:
scripts/export_yoloe_onnx.py(UltralyticsYOLOE,set_classes,export(..., nms=False)). - Parity tests:
tests/test_yoloe.sh— UltralyticsYOLOEvs C++YOLOESegDetector(JSON + mask comparison, same workflow as segmentation tests). ONNX for CI is produced bytests/yoloe/models/export_yoloe_test_onnx.py; class names live intests/yoloe/inference_config.json. - Docs / benchmarks: Model Guide,
benchmarks/README.md.
ONNX Runtime Integration
Session Management
Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "YOLOs-CPP");
Ort::SessionOptions options;
// CPU optimization
options.SetIntraOpNumThreads(4);
options.SetGraphOptimizationLevel(ORT_ENABLE_ALL);
// GPU (CUDA)
OrtCUDAProviderOptions cuda_options{};
options.AppendExecutionProvider_CUDA(cuda_options);
Ort::Session session(env, "model.onnx", options);
Memory Efficiency
// Pre-allocate buffers
std::vector<float> inputBuffer(3 * 640 * 640);
// Create tensor from existing memory
Ort::Value::CreateTensor<float>(
memoryInfo,
inputBuffer.data(),
inputBuffer.size(),
inputShape.data(),
inputShape.size()
);
Debugging
Enable Verbose Output
Ort::Env env(ORT_LOGGING_LEVEL_VERBOSE, "Debug");
Profile Inference
#include <chrono>
auto start = std::chrono::high_resolution_clock::now();
auto detections = detector.detect(frame);
auto end = std::chrono::high_resolution_clock::now();
auto ms = std::chrono::duration<double, std::milli>(end - start).count();
std::cout << "Inference: " << ms << " ms" << std::endl;
Validate Against Python
# Run comparison tests
cd tests
./test_detection.sh
Code Style
- C++17 standard
- snake_case for variables and functions
- PascalCase for classes and types
- UPPER_CASE for constants
- Use
constand[[nodiscard]]where appropriate
Building Tests
cd tests
./build_test.sh 0 # Detection
./build_test.sh 1 # Classification
./build_test.sh 2 # Segmentation
./build_test.sh 3 # Pose
./build_test.sh 4 # OBB
Benchmarking
cd benchmarks
./auto_bench.sh 1.20.1 0 yolo11n,yolov8n
Next Steps
- Contributing — Submit changes
- Model Guide — Model compatibility