DX-APP Python Usage Guide
This guide explains how to navigate and use the refactored Python example tree in DX-APP.
Overview
The Python examples are located under src/python_example/ and are organized by:
- task
- model family
- execution and post-processing variant
All examples share a common runtime layer under src/python_example/common/ that provides base interfaces, processors, runners, input sources, visualizers, and utilities. This is the Python counterpart of src/cpp_example/common/ — both languages implement the same 7-module factory-based architecture. Each model directory contains only thin entry-point scripts and a factory that wires shared components together.
Representative task directories include:
classification/— EfficientNet, AlexNet, ResNet, MobileNet, etc.object_detection/— YOLOv3/v5/v7/v8/v9/v10/v11/v12, YOLO26, YOLOX, NanoDet, DAMOYOLO, SSDface_detection/— SCRFD, YOLOv5Face, YOLOv7Face, RetinaFacepose_estimation/— YOLOv8-Posesemantic_segmentation/— BiSeNet, DeepLabV3+, SegFormerinstance_segmentation/— YOLOv8Seg, YOLOv26Segdepth_estimation/— FastDepth, SCDepthV3embedding/— ArcFaceobb_detection/— YOLOv26OBBimage_denoising/,image_enhancement/,super_resolution/hand_landmark/— Hand landmark estimationppu/— PPU-accelerated variants (YOLOv5/v7/v8/v9/v10/v11/v12/SCRFD/Pose)attribute_recognition/— Attribute recognition (DeepMAR)reid/— Person re-identification (CasViT)face_alignment/— Face alignment / 3D landmark (3DDFA v2)
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 Python examples:
| Module | Role |
|---|---|
common/base/ | Abstract interfaces: IFactory, IProcessor, IVisualizer, IInputSource |
common/config/ | ModelConfig — loads config.json (input size, labels, thresholds) |
common/processors/ | 35 shared post-processors covering all model families |
common/runner/ | SyncRunner, AsyncRunner, run_dir, verify_serialize, args — generic execution engines with built-in profiling |
common/inputs/ | Input source abstraction: image, video, camera, RTSP |
common/visualizers/ | 10 task-specific visualizers (detection, segmentation, pose, etc.) |
common/utility/ | Labels, preprocessing, profiling, drawing helpers |
Factory Pattern & Model Registry
Each model directory has a factory/{model}_factory.py that implements IFactory:
from common.processors import YOLOv5Postprocessor
from common.visualizers import DetectionVisualizer
class Yolov9sFactory(IFactory):
def create_processor(self):
return YOLOv5Postprocessor(self.config)
def create_visualizer(self):
return DetectionVisualizer(self.config)
The entry-point script simply delegates to the runner:
from common.runner import SyncRunner
runner = SyncRunner(factory)
runner.run()
Model Registry (config/model_registry.json)
A JSON registry stores per-model metadata (task, postprocessor type, input dimensions, thresholds). The scripts/add_model.sh tool reads this registry to auto-generate factory files, config.json, and all entry-point scripts — enabling zero-code model onboarding.
Directory & File Pattern
Each model family has its own directory with a consistent structure:
src/python_example/object_detection/yolov9s/
├── config.json # Model-specific runtime settings
├── factory/
│ └── yolov9s_factory.py # Wires shared processor + visualizer
├── yolov9s_sync.py # Pure Python synchronous
├── yolov9s_async.py # Pure Python asynchronous
├── yolov9s_sync_cpp_postprocess.py # Synchronous + C++ binding
└── yolov9s_async_cpp_postprocess.py # Asynchronous + C++ binding
Execution Framework
Execution Variants
Pure Python Flow (*_sync.py, *_async.py)
Use these when you want:
- easier logic inspection — post-processing is readable Python in
common/processors/ - Python-first experimentation
- simpler debugging during algorithm development
C++ Post-process Flow (*_cpp_postprocess.py)
Use these when you want:
- faster post-processing — uses C++ via pybind11 (
dx_postprocess) - better alignment with shared C++ decode logic
- more realistic performance validation
CLI Interface
All Python examples use argparse via common/runner/args.py and share a consistent interface:
| Flag | Short | Type | Description |
|---|---|---|---|
--model | -m | string | Path to .dxnn model file (auto-downloaded if missing) |
--image | -i | string | Input image file or directory |
--video | -v | string | Input video file |
--camera | -c | int | Camera device index |
--rtsp | -r | string | RTSP stream URL |
--save | -s | flag | Save rendered output to a run directory |
--save-dir | — | string | Base output directory (default: artifacts/python_example/) |
--dump-tensors | — | flag | Dump input/output tensors to .npy files |
--loop | -l | int | Inference repeat count (default: 1; bare --loop = 2) |
--no-display | — | flag | Disable visualization window |
--show-log | — | flag | Enable verbose log output (default: quiet) |
--config | — | string | Model config JSON path (auto-detected if omitted) |
--fast-postprocess | — | flag | Opt-in faster postprocessing variant where available (standard path is the default) |
--output | -o | string | Output file path (restoration/depth/SR only) |
--help | -h | — | Show usage |
- Input source:
--image,--video,--camera, and--rtspform a mutually exclusive group. If none is specified, a default sample image is automatically selected based on the task type.
Image-only tasks: embedding, reid, and attribute_recognition tasks accept --image input only. --video, --camera, and --rtsp 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. Passing a video/camera source to these tasks exits with an error.
Getting Started (Workflow)
Step 1. Prepare assets
./setup.sh
Step 2. Build shared libraries
./build.sh
Step 3. Run a Python example
python src/python_example/object_detection/yolov9s/yolov9s_sync.py --model assets/models/yolov9-s_640x640.dxnn --image sample/img/sample_kitchen.jpg
python src/python_example/object_detection/yolov9s/yolov9s_async_cpp_postprocess.py --model assets/models/yolov9-s_640x640.dxnn --video 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:
[DXAPP] [INFO] No input specified. Using default sample: sample/img/sample_street.jpg
Signal Handling
Both SyncRunner and AsyncRunner use stop_event (threading.Event) for graceful Ctrl+C shutdown. The async pipeline uses a SENTINEL chain to propagate stop signals through all queues.
Output Management (--save)
When --save is enabled, a timestamped directory is created (e.g., artifacts/python_example/{model}-image-{name}-{timestamp}/) containing run_info.txt, saved images/video, and optional tensor dumps.
Headless Mode
When DISPLAY/WAYLAND_DISPLAY environment variables are absent, cv2.imshow() is automatically skipped. Use --no-display for explicit headless operation.
Model Configuration (--config)
Runtime parameters (thresholds, top-k, etc.) are loaded via _FactoryConfigMixin with alias normalization (score_threshold → conf_threshold). If omitted, config.json is auto-detected adjacent to the model or script.
Fast Postprocessing (--fast-postprocess)
An opt-in, performance-oriented postprocessing path. By default the runner always uses the standard postprocessor; passing --fast-postprocess selects a faster variant only for the model families that provide one — other models silently keep the standard path, so the flag is always safe to add. The optimization skips work the standard path performs before thresholding (e.g. running sigmoid over the full anchor grid, taking argmax over every anchor, or upsampling each mask to the full input resolution).
There are two accuracy tiers:
| Tier | Output vs. standard path | Model families |
|---|---|---|
| Exact | Byte-identical (verified by parity unit tests) | Object detection — YOLOv5 / YOLOv7, EfficientDet |
| Approximate | Differs only at sub-pixel mask boundaries (binary masks agree at high IoU) | Instance segmentation (YOLOv8-seg), YOLACT, SegFormer semantic segmentation |
- Exact tier (detection): the fast path gates anchors before the expensive decode. Because objectness/score gating is monotonic and the survivors are decoded with the same formulas, the detections are bit-for-bit identical to the standard path — it can be enabled with no accuracy cost.
- Approximate tier (segmentation): the fast path crops and resizes masks at prototype (or output) resolution instead of upsampling each mask to the full input resolution first. This changes only sub-pixel boundary interpolation; on the profiled workloads the measured speedup is roughly 2.3x for instance segmentation and 4.9x for SegFormer-style semantic segmentation (the exact figure depends on the model, resolution, and host CPU).
When to enable. The benefit is largest when postprocessing dominates end-to-end latency — typically high-resolution feature grids or large anchor×class counts (dense detection heads, many-class detectors, high-resolution segmentation). Profile your own workload rather than assuming a fixed factor.
When to keep the default. The standard path is always the default and remains the accuracy reference. For the approximate (segmentation) tier, keep the standard path when exact mask boundaries matter.
# Object detection (exact tier) — identical results, faster decode
python src/python_example/object_detection/yolov7/yolov7_sync.py \
--model assets/models/yolov7_640x640.dxnn --image sample/img/sample_street.jpg --fast-postprocess
Verification & Diagnostics
Numerical Verification (DXAPP_VERIFY)
Set DXAPP_VERIFY=1 to serialize all post-processing results to logs/verify/{model}.json for inspection and debugging.
Tensor Dump for Debugging (--dump-tensors)
Dumps raw input/output tensors as .npy files. On exception, tensors and a reason.txt are auto-dumped for debugging.
Model Validation (optional)
# Run NPU inference for all supported models
bash scripts/validate_models.sh --lang py
Environment Variables Reference
| Variable | Description |
|---|---|
DXAPP_SAVE_IMAGE | Save visualization to the specified file path (no --save required) |
DXAPP_VERIFY | When 1, dump JSON verification data |
Supplementary Information
Component Relationships
The *_cpp_postprocess.py variants depend on the shared Python binding exposed from src/bindings/python/dx_postprocess/.
See also: DX-APP Pybind PostProcess Overview
Developer Resources
- For contributor workflows, use DX Tool Guide
- For test execution, use DX-APP Python Example Tests
- For repository layout details, use DX-APP Example Source Structure