API Reference
All public classes live in the yolos namespace. Task-specific classes are in sub-namespaces (yolos::det, yolos::seg, yolos::pose, yolos::obb, yolos::cls). Include the top-level header to pull everything in:
#include "yolos/yolos.hpp"
Core Types
Defined in yolos/core/types.hpp — shared across all tasks.
yolos::BoundingBox
Axis-aligned bounding box (top-left origin).
struct BoundingBox {
int x, y; // top-left corner
int width, height; // box dimensions
float area() const noexcept;
float iou(const BoundingBox& other) const noexcept;
};
yolos::OrientedBoundingBox
Rotated bounding box used by the OBB detector.
struct OrientedBoundingBox {
float x, y; // center point
float width, height; // box dimensions
float angle; // rotation in radians
float area() const noexcept;
};
yolos::KeyPoint
Single keypoint for pose estimation.
struct KeyPoint {
float x, y; // image coordinates
float confidence; // per-keypoint score [0, 1]
};
Object Detection — yolos::det
Defined in yolos/tasks/detection.hpp.
yolos::det::Detection
struct Detection {
BoundingBox box;
float conf; // confidence [0, 1]
int classId;
};
yolos::det::YOLODetector
Main detector — supports YOLO v7, v8, v10, v11, v26, and NAS via runtime auto-detection.
YOLODetector(
const std::string& modelPath, // path to .onnx model
const std::string& labelsPath, // path to class-names .txt file
bool useGPU = false,
YOLOVersion version = YOLOVersion::Auto
);
// Load the model from memory instead of a file (see In-Memory Model Loading)
YOLODetector(
const void* modelData,
size_t modelSize,
const std::vector<std::string>& classNames, // empty = read ONNX metadata
bool useGPU = false,
YOLOVersion version = YOLOVersion::Auto
);
// Run detection on a BGR image
std::vector<Detection> detect(
const cv::Mat& image,
float confThreshold = 0.4f,
float iouThreshold = 0.45f
);
// Run detection on many images in one ONNX Runtime call (see Batch Inference)
std::vector<std::vector<Detection>> batchDetect(
const std::vector<cv::Mat>& images,
float confThreshold = 0.4f,
float iouThreshold = 0.45f
);
// Draw boxes + labels onto the image
void drawDetections(cv::Mat& image, const std::vector<Detection>& detections) const;
// Draw boxes with a semi-transparent filled mask
void drawDetectionsWithMask(cv::Mat& image, const std::vector<Detection>& detections,
float alpha = 0.4f) const;
const std::vector<std::string>& getClassNames() const;
const std::vector<cv::Scalar>& getClassColors() const;
Version-pinned convenience classes (same API as YOLODetector):
| Class | YOLO version |
|---|---|
yolos::det::YOLOv7Detector |
v7 |
yolos::det::YOLOv8Detector |
v8 |
yolos::det::YOLOv10Detector |
v10 |
yolos::det::YOLOv11Detector |
v11 |
yolos::det::YOLO26Detector |
v26 |
yolos::det::YOLONASDetector |
NAS |
Factory functions:
std::unique_ptr<YOLODetector> yolos::det::createDetector(
const std::string& modelPath,
const std::string& labelsPath,
YOLOVersion version = YOLOVersion::Auto,
bool useGPU = false
);
std::unique_ptr<YOLODetector> yolos::det::createDetectorFromMemory(
const void* modelData,
size_t modelSize,
const std::vector<std::string>& classNames,
YOLOVersion version = YOLOVersion::Auto,
bool useGPU = false
);
Example:
yolos::det::YOLODetector detector("yolo11n.onnx", "coco.names");
auto results = detector.detect(frame);
detector.drawDetections(frame, results);
Instance Segmentation — yolos::seg
Defined in yolos/tasks/segmentation.hpp.
yolos::seg::Segmentation
struct Segmentation {
BoundingBox box;
float conf;
int classId;
cv::Mat mask; // binary mask (CV_8UC1), original image coords
};
yolos::seg::YOLOSegDetector
Supports YOLOv8-seg, YOLOv11-seg, and YOLO26-seg.
YOLOSegDetector(
const std::string& modelPath,
const std::string& labelsPath,
bool useGPU = false
);
// Load the model from memory instead of a file (see In-Memory Model Loading)
YOLOSegDetector(
const void* modelData,
size_t modelSize,
const std::vector<std::string>& classNames, // empty = read ONNX metadata
bool useGPU = false
);
// Returns detections with per-instance binary masks
std::vector<Segmentation> segment(
const cv::Mat& image,
float confThreshold = 0.4f,
float iouThreshold = 0.45f
);
// Segment many images in one ONNX Runtime call (see Batch Inference)
std::vector<std::vector<Segmentation>> batchSegment(
const std::vector<cv::Mat>& images,
float confThreshold = 0.4f,
float iouThreshold = 0.45f
);
// Draw masks + boxes onto the image
void drawSegmentations(cv::Mat& image, const std::vector<Segmentation>& results,
float maskAlpha = 0.5f) const;
void drawMasksOnly(cv::Mat& image, const std::vector<Segmentation>& results,
float maskAlpha = 0.5f) const;
Example:
yolos::seg::YOLOSegDetector detector("yolo11n-seg.onnx", "coco.names");
auto results = detector.segment(frame);
detector.drawSegmentations(frame, results);
Pose Estimation — yolos::pose
Defined in yolos/tasks/pose.hpp.
yolos::pose::PoseResult
struct PoseResult {
BoundingBox box;
float conf;
int classId; // 0 = person
std::vector<KeyPoint> keypoints; // 17 keypoints (COCO format)
};
yolos::pose::YOLOPoseDetector
Supports YOLOv8-pose, YOLOv11-pose, and YOLO26-pose.
YOLOPoseDetector(
const std::string& modelPath,
const std::string& labelsPath = "", // optional; defaults to "person"
bool useGPU = false
);
// Load the model from memory instead of a file (see In-Memory Model Loading)
YOLOPoseDetector(
const void* modelData,
size_t modelSize,
const std::vector<std::string>& classNames = {}, // empty = metadata, then "person"
bool useGPU = false
);
std::vector<PoseResult> detect(
const cv::Mat& image,
float confThreshold = 0.4f,
float iouThreshold = 0.5f
);
// Detect on many images in one ONNX Runtime call (see Batch Inference)
std::vector<std::vector<PoseResult>> batchDetect(
const std::vector<cv::Mat>& images,
float confThreshold = 0.4f,
float iouThreshold = 0.5f
);
// Draw bounding boxes + skeleton keypoints
void drawPoses(cv::Mat& image, const std::vector<PoseResult>& results,
int kptRadius = 4, float kptThreshold = 0.5f, int lineThickness = 2) const;
// Draw skeleton only (no boxes)
void drawSkeletonsOnly(cv::Mat& image, const std::vector<PoseResult>& results,
int kptRadius = 4, float kptThreshold = 0.5f, int lineThickness = 2) const;
Example:
yolos::pose::YOLOPoseDetector detector("yolo11n-pose.onnx");
auto results = detector.detect(frame);
detector.drawPoses(frame, results);
Oriented Bounding Box Detection — yolos::obb
Defined in yolos/tasks/obb.hpp.
yolos::obb::OBBResult
struct OBBResult {
OrientedBoundingBox box;
float conf;
int classId;
};
yolos::obb::YOLOOBBDetector
Supports YOLOv8-obb, YOLOv11-obb, and YOLO26-obb.
YOLOOBBDetector(
const std::string& modelPath,
const std::string& labelsPath,
bool useGPU = false
);
// Load the model from memory instead of a file (see In-Memory Model Loading)
YOLOOBBDetector(
const void* modelData,
size_t modelSize,
const std::vector<std::string>& classNames, // empty = read ONNX metadata
bool useGPU = false
);
std::vector<OBBResult> detect(
const cv::Mat& image,
float confThreshold = 0.25f,
float iouThreshold = 0.45f,
int maxDet = 300
);
// Detect on many images in one ONNX Runtime call (see Batch Inference)
std::vector<std::vector<OBBResult>> batchDetect(
const std::vector<cv::Mat>& images,
float confThreshold = 0.25f,
float iouThreshold = 0.45f,
int maxDet = 300
);
void drawDetections(cv::Mat& image, const std::vector<OBBResult>& results,
int thickness = 2) const;
Example:
yolos::obb::YOLOOBBDetector detector("yolo11n-obb.onnx", "dota.names");
auto results = detector.detect(frame);
detector.drawDetections(frame, results);
Image Classification — yolos::cls
Defined in yolos/tasks/classification.hpp.
yolos::cls::ClassificationResult
struct ClassificationResult {
int classId;
float confidence;
std::string className;
};
yolos::cls::YOLOClassifier
Supports YOLOv11-cls, YOLOv12-cls, and YOLO26-cls.
YOLOClassifier(
const std::string& modelPath,
const std::string& labelsPath,
bool useGPU = false,
const cv::Size& targetInputShape = cv::Size(224, 224)
);
// Load the model from memory instead of a file (see In-Memory Model Loading)
YOLOClassifier(
const void* modelData,
size_t modelSize,
const std::vector<std::string>& classNames,
bool useGPU = false,
const cv::Size& targetInputShape = cv::Size(224, 224)
);
ClassificationResult classify(const cv::Mat& image);
// Classify many images in one ONNX Runtime call (see Batch Inference)
std::vector<ClassificationResult> batchClassify(const std::vector<cv::Mat>& images);
void drawResult(cv::Mat& image, const ClassificationResult& result,
const cv::Point& position = cv::Point(10, 30)) const;
const std::vector<std::string>& getClassNames() const;
Version-pinned convenience classes:
| Class | YOLO version |
|---|---|
yolos::cls::YOLO11Classifier |
v11 |
yolos::cls::YOLO12Classifier |
v12 |
yolos::cls::YOLO26Classifier |
v26 |
Factory functions:
std::unique_ptr<YOLOClassifier> yolos::cls::createClassifier(
const std::string& modelPath,
const std::string& labelsPath,
YOLOVersion version = YOLOVersion::V11,
bool useGPU = false
);
std::unique_ptr<YOLOClassifier> yolos::cls::createClassifierFromMemory(
const void* modelData,
size_t modelSize,
const std::vector<std::string>& classNames,
YOLOVersion version = YOLOVersion::V11,
bool useGPU = false
);
Example:
yolos::cls::YOLOClassifier classifier("yolo11n-cls.onnx", "imagenet.names");
auto result = classifier.classify(frame);
classifier.drawResult(frame, result);
Preprocessing. classify() reproduces ultralytics.data.augment.classify_transforms():
resize the shortest edge to the model input size, centre-crop to a square, scale to
[0, 1]. Ultralytics resizes through PIL, whose bilinear filter is antialiased, so
YOLOs-CPP uses preprocessing::resizeAntialiasBilinear() rather than
cv::resize(INTER_LINEAR). Using a plain bilinear resize here inflates confidences and
can change the top-1 class on downscaled images.
This differs from the other tasks on purpose: Ultralytics' LetterBox (detection,
segmentation, pose, OBB) really does use cv2.INTER_LINEAR, so those paths keep it.
Depth Estimation — yolos::depth
Defined in yolos/tasks/depth.hpp. Requires a YOLO26 -depth model.
yolos::depth::YOLODepthEstimator
YOLODepthEstimator(
const std::string& modelPath,
bool useGPU = false
);
// Per-pixel metric depth in meters, CV_32FC1, sized to `image`
cv::Mat estimate(const cv::Mat& image);
// Blend a colorized depth map over the image
void drawDepth(cv::Mat& image, const cv::Mat& depth, float alpha = 0.6f,
drawing::DepthColormap cmap = drawing::DepthColormap::Jet,
drawing::DepthNorm mode = drawing::DepthNorm::Disparity) const;
No labelsPath, no confidence and no IoU threshold: depth models emit a single dense
map and have no classes. The constructor throws std::runtime_error if the model's
output is not shaped [1, 1, H, W], so pointing it at a detection export fails
immediately rather than producing meaningless depth.
Factory function:
std::unique_ptr<YOLODepthEstimator> yolos::depth::createDepthEstimator(
const std::string& modelPath,
bool useGPU = false
);
Example:
yolos::depth::YOLODepthEstimator estimator("yolo26n-depth.onnx");
cv::Mat depth = estimator.estimate(frame); // CV_32FC1, meters
float metres = depth.at<float>(y, x);
double lo, hi;
cv::minMaxLoc(depth, &lo, &hi);
estimator.drawDepth(frame, depth);
Units. Values are metric depth in meters, straight from the model. The exported
graph already applies the clamp/exp, the log-affine calibration and the 4× upsample
from Ultralytics' Depth head, so nothing needs undoing on this side. The library never
normalizes depth — only the visualization helpers do.
Depth visualization — yolos::drawing
enum class DepthColormap { Jet, Inferno };
enum class DepthNorm { Disparity, Metric };
cv::Mat colorizeDepth(const cv::Mat& depth,
DepthColormap cmap = DepthColormap::Jet,
DepthNorm mode = DepthNorm::Disparity,
float vmin = NaN, float vmax = NaN);
void drawDepthMap(cv::Mat& image, const cv::Mat& depth, float alpha = 0.6f,
DepthColormap cmap = DepthColormap::Jet,
DepthNorm mode = DepthNorm::Disparity,
float vmin = NaN, float vmax = NaN);
Defaults match Ultralytics: disparity (1/d) normalization between the 2nd and 98th
percentile, JET colormap, non-positive pixels black, alpha = 0.6.
For video, pass explicit vmin/vmax. Recomputing percentiles per frame makes the
overlay flicker; the video and camera examples derive the range from the first frame and
reuse it. Ultralytics' third colormap, spectral, is a custom matplotlib LUT with no
OpenCV equivalent and is not supported.
Exporting a depth model:
from ultralytics import YOLO
YOLO("yolo26n-depth.pt").export(format="onnx")
Base Session — yolos::OrtSessionBase
Defined in yolos/core/session_base.hpp. All detectors inherit from this — you normally don't need to use it directly.
cv::Size getInputShape() const noexcept;
bool isDynamicInputShape() const noexcept;
bool isDynamicBatchSize() const noexcept; // true if the ONNX batch dim is dynamic
int getModelBatchSize() const noexcept; // fixed batch size, or -1 if dynamic
bool supportsBatchSize(size_t count) const noexcept; // can one call take `count` images?
std::string getDevice() const noexcept; // "cpu" or "gpu"
size_t getNumInputNodes() const noexcept;
size_t getNumOutputNodes() const noexcept;
In-Memory Model Loading
Every task class has a constructor that takes the serialized ONNX bytes instead of a
file path, for encrypted stores, network streams and resources embedded in the binary.
Class names are passed as a std::vector<std::string> in class-id order, so no labels
file is needed either.
// Whatever produces the bytes — decryption, download, embedded array — only the
// buffer reaches the detector.
std::vector<uint8_t> bytes = yolos::utils::readFileBytes("yolo11n.onnx");
yolos::det::YOLODetector detector(
bytes.data(), bytes.size(),
{"person", "bicycle", "car" /* ... */});
auto results = detector.detect(frame);
Notes:
- ONNX Runtime copies the buffer while creating the session, so the caller may free or wipe it as soon as the constructor returns.
- Passing an empty
classNamesfalls back to the Ultralyticsnamesentry in the ONNX metadata, when the export carries one. - A null pointer or zero size throws
std::invalid_argument. yolos::utils::readFileBytes(path)is a convenience helper for testing this path; production callers normally supply their own bytes.
Constructors and matching create*FromMemory() factories exist for detection,
segmentation, pose, OBB, classification and YOLOE.
Batch Inference
batchDetect / batchSegment / batchClassify pack several images into a single
N × C × H × W tensor and run one ONNX Runtime call, which is what improves GPU
throughput over calling the single-image method in a loop.
std::vector<cv::Mat> images = {cv::imread("a.jpg"), cv::imread("b.jpg"), cv::imread("c.jpg")};
yolos::det::YOLODetector detector("yolo11n.onnx", "coco.names", /*useGPU=*/true);
// One result vector per input image, in input order
std::vector<std::vector<yolos::det::Detection>> results = detector.batchDetect(images);
| Task | Method | Returns |
|---|---|---|
| Detection | batchDetect(images, conf, iou) |
std::vector<std::vector<Detection>> |
| Segmentation | batchSegment(images, conf, iou) |
std::vector<std::vector<Segmentation>> |
| Pose | batchDetect(images, conf, iou) |
std::vector<std::vector<PoseResult>> |
| OBB | batchDetect(images, conf, iou, maxDet) |
std::vector<std::vector<OBBResult>> |
| Classification | batchClassify(images) |
std::vector<ClassificationResult> |
Automatic fallback. True batching needs a model whose batch dimension accepts the
batch size — either a dynamic batch dim, or a fixed one equal to images.size(). When
it does not, the batch methods loop over the single-image path instead, so the call
still returns one result per image with any export. The same recovery covers exports
that declare a dynamic batch dimension the graph cannot actually run (hard-coded
Reshape targets, for example): the failure is reported as a warning and the per-image
loop takes over. Check up front with:
detector.isDynamicBatchSize(); // was the model exported with dynamic=True?
detector.getModelBatchSize(); // fixed batch size, or -1 when dynamic
detector.supportsBatchSize(images.size()); // will this call actually batch?
Export a dynamic-batch model from Ultralytics with:
model.export(format="onnx", dynamic=True)
Behavioral note. A batched tensor requires one shared letterbox target, so batched runs letterbox every image to the model input shape. For a model with a dynamic input shape, the single-image methods instead pick a per-image stride-aligned shape, so the two paths can differ slightly for such models. Fixed-input-shape models — the common case — produce identical results either way.
Runnable demo: src/batch_image_inference.cpp (--in-memory also exercises the
in-memory loader).
YOLO Version Enum
enum class YOLOVersion {
Auto, // runtime detection (default)
V7, V8, V10, V11, V12, V26, NAS
};