本文へスキップ
SDK Version: 2.3.3

DX-APP C++ Usage Guide

# DX-APP C++ Usage Guide

This guide explains how to navigate and use the refactored C++ example tree in DX-APP.


Overview

The C++ examples are located under src/cpp_example/ and are organized by:

  • task
  • model family
  • execution variant

All examples share a common runtime layer under src/cpp_example/common/ that provides base interfaces, processors, runners, input sources, visualizers, and utilities. This is the C++ counterpart of src/python_example/common/ — both languages implement the same 7-module factory-based architecture. Each model directory contains thin entry-point source files and a factory that wires shared components together.

Representative task directories include:

  • classification/
  • object_detection/
  • face_detection/
  • pose_estimation/
  • semantic_segmentation/
  • instance_segmentation/
  • depth_estimation/
  • embedding/
  • image_denoising/
  • image_enhancement/
  • super_resolution/
  • hand_landmark/
  • obb_detection/
  • ppu/
  • attribute_recognition/
  • reid/
  • face_alignment/

For the full repository-level structure, refer to DX-APP Example Source Structure.


Architecture & Design Pattern

Architecture Strategy

Shared Runtime Layer (common/)

The common/ directory is the engine behind all C++ examples:

ModuleContentsRole
common/base/4 interfaces (.hpp)IFactory, IProcessor, IVisualizer, IInputSource
common/config/model_config.hppLoads config.json (input size, labels, thresholds)
common/processors/44 processorsShared decode logic for all model families
common/runner/24 runner headers12 sync + 12 async task-specific runner pairs
common/inputs/5 source headersImage, Video, Camera, RTSP input abstraction
common/visualizers/12 visualizersTask-specific result rendering
common/utility/8 utility headersLabels, preprocessing, profiling, run_dir, signal_handler, verify_serialize

Unlike Python's generic SyncRunner/AsyncRunner, C++ runners are task-specific: each task type has a dedicated sync/async pair (e.g., sync_detection_runner.hpp, async_detection_runner.hpp).

Factory Pattern Implementation

Each model directory has a factory/{model}_factory.hpp that implements IFactory:

// factory/yolov9s_factory.hpp
#include "common/processors/yolov8_postprocessor.hpp"
#include "common/visualizers/detection_visualizer.hpp"

class YOLOv9sFactory : public IFactory {
IProcessor* createProcessor() override { return new YOLOv8Postprocessor(config); }
IVisualizer* createVisualizer() override { return new DetectionVisualizer(); }
};

The entry-point delegates to a task-specific runner:

// yolov9s_sync.cpp
auto factory = YOLOv9sFactory(config);
SyncDetectionRunner runner(factory);
runner.run();

Directory Pattern & File Pattern

Each model family usually has its own directory.

Example:

src/cpp_example/object_detection/yolov9s/
├── config.json
├── factory/
│ └── yolov9s_factory.hpp # Assembles processor + visualizer from common/
├── yolov9s_sync.cpp # Entry point → sync_detection_runner
└── yolov9s_async.cpp # Entry point → async_detection_runner

Common files:

  • config.json: model-specific runtime settings
  • factory/: factory header wiring shared common/ components
  • *_sync.cpp: synchronous execution example (via task-specific sync runner)
  • *_async.cpp: asynchronous execution example (via task-specific async runner)

Execution Framework

Execution Variants

Synchronous Flow (*_sync.cpp)

Use this variant when you want:

  • simpler control flow
  • easier step-by-step debugging
  • single-image or low-complexity usage examples

Asynchronous Flow (*_async.cpp)

Use this variant when you want:

  • higher throughput
  • better overlap of pipeline stages
  • real-time image/video processing patterns

CLI Interface

All C++ examples use cxxopts for argument parsing and share a consistent interface:

FlagShortTypeDescription
--model_path-mstringPath to .dxnn model file (auto-downloaded if missing)
--image_path-istringInput image file or directory
--video_path-vstringInput video file
--camera_index-cintCamera device index
--rtsp_url-rstringRTSP stream URL
--save-sboolSave rendered output to a run directory
--save-dirstringBase output directory (default: artifacts/cpp_example)
--dump-tensorsboolDump input/output tensors to .bin files
--loop-lintInference repeat count (default: auto)
--no-displayboolDisable visualization window, output FPS only
--show-logboolEnable verbose log output (default: quiet)
--configstringModel config JSON path (auto-detected if omitted)
--help-hShow usage
  • Input source: --image_path, --video_path, --camera_index, and --rtsp_url form a mutually exclusive group. If none is specified, a default sample image is automatically selected based on the task type.
NOTE

Image-only tasks: embedding, reid, and attribute_recognition tasks accept --image_path input only. --video_path, --camera_index, and --rtsp_url are not supported for these tasks because meaningful inference requires a crop of a pre-detected subject (face or person). Running a single embedding model on a raw video stream without a preceding detector would not produce valid results.


Getting Started (Workflow)

Step 1. Prepare assets

./setup.sh

Step 2. Build the repository

./build.sh

Step 3. Run a C++ example

./bin/yolov9s_sync -m assets/models/YoloV9S.dxnn -i sample/img/sample_kitchen.jpg
./bin/yolov9s_async -m assets/models/YoloV9S.dxnn -v assets/videos/dance-group.mov

Advanced Operations & Debugging

Runtime Features

Auto-Download

When a specified model file is not found locally, the runner automatically attempts to download it via setup_sample_models.sh. If a --video file is missing, setup_sample_videos.sh is invoked. If the download fails, a clear error message with manual download instructions is displayed.

Default Input Fallback

If no input source is provided, the runner automatically selects a default sample image appropriate for the task type (e.g., sample/img/sample_street.jpg for object detection). A log message indicates which default was applied.

Signal Handling

All runners install SIGINT/SIGTERM handlers (installSignalHandlers()). Pressing Ctrl+C triggers a graceful shutdown with clean resource release.

Output Management (--save)

When --save is enabled, a timestamped directory is created (e.g., artifacts/cpp_example/{model}-image-{name}-{timestamp}/) containing run_info.txt, saved images/video, and optional tensor dumps.

Configuration Management (--config)

Runtime parameters (thresholds, top-k, etc.) can be customized per-model via config.json. If omitted, auto-detected adjacent to the model file.

Verification & Diagnostics

Numerical Verification (DXAPP_VERIFY)

Set DXAPP_VERIFY=1 to serialize all post-processing results to logs/verify/{model}.json. Use scripts/verify_inference_output.py to validate correctness.

Tensor Dump for Debugging (--dump-tensors)

Dumps raw input/output tensors as .bin files. On exception, tensors and a reason.txt are auto-dumped for debugging.

Environment Variables Reference

VariableDescription
DXAPP_SAVE_IMAGESave visualization to the specified file path
DXAPP_VERIFYWhen 1, dump JSON verification data

Supplementary Information

Component Relationships

src/postprocess/ contains C++ post-processing implementations that are not used by cpp_example/common/processors/ directly. Instead, they are consumed by the pybind11 bindings (src/bindings/python/dx_postprocess/) to enable *_cpp_postprocess.py variants in Python.

The C++ examples rely on their own shared processors in src/cpp_example/common/processors/.

See also: DX-APP C++ Post-processing Overview

Developer Resources