-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
50 changed files
with
1,420 additions
and
680 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[package] | ||
name = "YOLO-ONNXRuntime-Rust" | ||
version = "0.1.0" | ||
edition = "2021" | ||
authors = ["Jamjamjon <[email protected]>"] | ||
|
||
[dependencies] | ||
anyhow = "1.0.92" | ||
clap = "4.5.20" | ||
tracing = "0.1.40" | ||
tracing-subscriber = "0.3.18" | ||
usls = { version = "0.0.19", features = ["auto"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
# YOLO-Series ONNXRuntime Rust Demo for Core YOLO Tasks | ||
|
||
This repository provides a Rust demo for key YOLO-Series tasks such as `Classification`, `Segmentation`, `Detection`, `Pose Detection`, and `OBB` using ONNXRuntime. It supports various YOLO models (v5 - 11) across multiple vision tasks. | ||
|
||
## Introduction | ||
|
||
- This example leverages the latest versions of both ONNXRuntime and YOLO models. | ||
- We utilize the [usls](https://github.com/jamjamjon/usls/tree/main) crate to streamline YOLO model inference, providing efficient data loading, visualization, and optimized inference performance. | ||
|
||
## Features | ||
|
||
- **Extensive Model Compatibility**: Supports `YOLOv5`, `YOLOv6`, `YOLOv7`, `YOLOv8`, `YOLOv9`, `YOLOv10`, `YOLO11`, `YOLO-world`, `RTDETR`, and others, covering a wide range of YOLO versions. | ||
- **Versatile Task Coverage**: Includes `Classification`, `Segmentation`, `Detection`, `Pose`, and `OBB`. | ||
- **Precision Flexibility**: Works with `FP16` and `FP32` ONNX models. | ||
- **Execution Providers**: Accelerated support for `CPU`, `CUDA`, `CoreML`, and `TensorRT`. | ||
- **Dynamic Input Shapes**: Dynamically adjusts to variable `batch`, `width`, and `height` dimensions for flexible model input. | ||
- **Flexible Data Loading**: The `DataLoader` handles images, folders, videos, and video streams. | ||
- **Real-Time Display and Video Export**: `Viewer` provides real-time frame visualization and video export functions, similar to OpenCV’s `imshow()` and `imwrite()`. | ||
- **Enhanced Annotation and Visualization**: The `Annotator` facilitates comprehensive result rendering, with support for bounding boxes (HBB), oriented bounding boxes (OBB), polygons, masks, keypoints, and text labels. | ||
|
||
## Setup Instructions | ||
|
||
### 1. ONNXRuntime Linking | ||
|
||
<details> | ||
<summary>You have two options to link the ONNXRuntime library:</summary> | ||
|
||
- **Option 1: Manual Linking** | ||
|
||
- For detailed setup, consult the [ONNX Runtime linking documentation](https://ort.pyke.io/setup/linking). | ||
- **Linux or macOS**: | ||
1. Download the ONNX Runtime package from the [Releases page](https://github.com/microsoft/onnxruntime/releases). | ||
2. Set up the library path by exporting the `ORT_DYLIB_PATH` environment variable: | ||
```shell | ||
export ORT_DYLIB_PATH=/path/to/onnxruntime/lib/libonnxruntime.so.1.19.0 | ||
``` | ||
|
||
- **Option 2: Automatic Download** | ||
- Use the `--features auto` flag to handle downloading automatically: | ||
```shell | ||
cargo run -r --example yolo --features auto | ||
``` | ||
|
||
</details> | ||
|
||
### 2. \[Optional\] Install CUDA, CuDNN, and TensorRT | ||
|
||
- The CUDA execution provider requires CUDA version `12.x`. | ||
- The TensorRT execution provider requires both CUDA `12.x` and TensorRT `10.x`. | ||
|
||
### 3. \[Optional\] Install ffmpeg | ||
|
||
To view video frames and save video inferences, install `rust-ffmpeg`. For instructions, see: | ||
[https://github.com/zmwangx/rust-ffmpeg/wiki/Notes-on-building#dependencies](https://github.com/zmwangx/rust-ffmpeg/wiki/Notes-on-building#dependencies) | ||
|
||
## Get Started | ||
|
||
```Shell | ||
# customized | ||
cargo run -r -- --task detect --ver v8 --nc 6 --model xxx.onnx # YOLOv8 | ||
# Classify | ||
cargo run -r -- --task classify --ver v5 --scale s --width 224 --height 224 --nc 1000 # YOLOv5 | ||
cargo run -r -- --task classify --ver v8 --scale n --width 224 --height 224 --nc 1000 # YOLOv8 | ||
cargo run -r -- --task classify --ver v11 --scale n --width 224 --height 224 --nc 1000 # YOLOv11 | ||
# Detect | ||
cargo run -r -- --task detect --ver v5 --scale n # YOLOv5 | ||
cargo run -r -- --task detect --ver v6 --scale n # YOLOv6 | ||
cargo run -r -- --task detect --ver v7 --scale t # YOLOv7 | ||
cargo run -r -- --task detect --ver v8 --scale n # YOLOv8 | ||
cargo run -r -- --task detect --ver v9 --scale t # YOLOv9 | ||
cargo run -r -- --task detect --ver v10 --scale n # YOLOv10 | ||
cargo run -r -- --task detect --ver v11 --scale n # YOLOv11 | ||
cargo run -r -- --task detect --ver rtdetr --scale l # RTDETR | ||
# Pose | ||
cargo run -r -- --task pose --ver v8 --scale n # YOLOv8-Pose | ||
cargo run -r -- --task pose --ver v11 --scale n # YOLOv11-Pose | ||
# Segment | ||
cargo run -r -- --task segment --ver v5 --scale n # YOLOv5-Segment | ||
cargo run -r -- --task segment --ver v8 --scale n # YOLOv8-Segment | ||
cargo run -r -- --task segment --ver v11 --scale n # YOLOv8-Segment | ||
cargo run -r -- --task segment --ver v8 --model yolo/FastSAM-s-dyn-f16.onnx # FastSAM | ||
# OBB | ||
cargo run -r -- --ver v8 --task obb --scale n --width 1024 --height 1024 --source images/dota.png # YOLOv8-Obb | ||
cargo run -r -- --ver v11 --task obb --scale n --width 1024 --height 1024 --source images/dota.png # YOLOv11-Obb | ||
``` | ||
|
||
**`cargo run -- --help` for more options** | ||
|
||
For more details, please refer to [usls-yolo](https://github.com/jamjamjon/usls/tree/main/examples/yolo). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
use anyhow::Result; | ||
use clap::Parser; | ||
|
||
use usls::{ | ||
models::YOLO, Annotator, DataLoader, Device, Options, Viewer, Vision, YOLOScale, YOLOTask, | ||
YOLOVersion, COCO_SKELETONS_16, | ||
}; | ||
|
||
#[derive(Parser, Clone)] | ||
#[command(author, version, about, long_about = None)] | ||
pub struct Args { | ||
/// Path to the ONNX model | ||
#[arg(long)] | ||
pub model: Option<String>, | ||
|
||
/// Input source path | ||
#[arg(long, default_value_t = String::from("../../ultralytics/assets/bus.jpg"))] | ||
pub source: String, | ||
|
||
/// YOLO Task | ||
#[arg(long, value_enum, default_value_t = YOLOTask::Detect)] | ||
pub task: YOLOTask, | ||
|
||
/// YOLO Version | ||
#[arg(long, value_enum, default_value_t = YOLOVersion::V8)] | ||
pub ver: YOLOVersion, | ||
|
||
/// YOLO Scale | ||
#[arg(long, value_enum, default_value_t = YOLOScale::N)] | ||
pub scale: YOLOScale, | ||
|
||
/// Batch size | ||
#[arg(long, default_value_t = 1)] | ||
pub batch_size: usize, | ||
|
||
/// Minimum input width | ||
#[arg(long, default_value_t = 224)] | ||
pub width_min: isize, | ||
|
||
/// Input width | ||
#[arg(long, default_value_t = 640)] | ||
pub width: isize, | ||
|
||
/// Maximum input width | ||
#[arg(long, default_value_t = 1024)] | ||
pub width_max: isize, | ||
|
||
/// Minimum input height | ||
#[arg(long, default_value_t = 224)] | ||
pub height_min: isize, | ||
|
||
/// Input height | ||
#[arg(long, default_value_t = 640)] | ||
pub height: isize, | ||
|
||
/// Maximum input height | ||
#[arg(long, default_value_t = 1024)] | ||
pub height_max: isize, | ||
|
||
/// Number of classes | ||
#[arg(long, default_value_t = 80)] | ||
pub nc: usize, | ||
|
||
/// Class confidence | ||
#[arg(long)] | ||
pub confs: Vec<f32>, | ||
|
||
/// Enable TensorRT support | ||
#[arg(long)] | ||
pub trt: bool, | ||
|
||
/// Enable CUDA support | ||
#[arg(long)] | ||
pub cuda: bool, | ||
|
||
/// Enable CoreML support | ||
#[arg(long)] | ||
pub coreml: bool, | ||
|
||
/// Use TensorRT half precision | ||
#[arg(long)] | ||
pub half: bool, | ||
|
||
/// Device ID to use | ||
#[arg(long, default_value_t = 0)] | ||
pub device_id: usize, | ||
|
||
/// Enable performance profiling | ||
#[arg(long)] | ||
pub profile: bool, | ||
|
||
/// Disable contour drawing, for saving time | ||
#[arg(long)] | ||
pub no_contours: bool, | ||
|
||
/// Show result | ||
#[arg(long)] | ||
pub view: bool, | ||
|
||
/// Do not save output | ||
#[arg(long)] | ||
pub nosave: bool, | ||
} | ||
|
||
fn main() -> Result<()> { | ||
let args = Args::parse(); | ||
|
||
// logger | ||
if args.profile { | ||
tracing_subscriber::fmt() | ||
.with_max_level(tracing::Level::INFO) | ||
.init(); | ||
} | ||
|
||
// model path | ||
let path = match &args.model { | ||
None => format!( | ||
"yolo/{}-{}-{}.onnx", | ||
args.ver.name(), | ||
args.scale.name(), | ||
args.task.name() | ||
), | ||
Some(x) => x.to_string(), | ||
}; | ||
|
||
// saveout | ||
let saveout = match &args.model { | ||
None => format!( | ||
"{}-{}-{}", | ||
args.ver.name(), | ||
args.scale.name(), | ||
args.task.name() | ||
), | ||
Some(x) => { | ||
let p = std::path::PathBuf::from(&x); | ||
p.file_stem().unwrap().to_str().unwrap().to_string() | ||
} | ||
}; | ||
|
||
// device | ||
let device = if args.cuda { | ||
Device::Cuda(args.device_id) | ||
} else if args.trt { | ||
Device::Trt(args.device_id) | ||
} else if args.coreml { | ||
Device::CoreML(args.device_id) | ||
} else { | ||
Device::Cpu(args.device_id) | ||
}; | ||
|
||
// build options | ||
let options = Options::new() | ||
.with_model(&path)? | ||
.with_yolo_version(args.ver) | ||
.with_yolo_task(args.task) | ||
.with_device(device) | ||
.with_trt_fp16(args.half) | ||
.with_ixx(0, 0, (1, args.batch_size as _, 4).into()) | ||
.with_ixx(0, 2, (args.height_min, args.height, args.height_max).into()) | ||
.with_ixx(0, 3, (args.width_min, args.width, args.width_max).into()) | ||
.with_confs(if args.confs.is_empty() { | ||
&[0.2, 0.15] | ||
} else { | ||
&args.confs | ||
}) | ||
.with_nc(args.nc) | ||
.with_find_contours(!args.no_contours) // find contours or not | ||
// .with_names(&COCO_CLASS_NAMES_80) // detection class names | ||
// .with_names2(&COCO_KEYPOINTS_17) // keypoints class names | ||
// .exclude_classes(&[0]) | ||
// .retain_classes(&[0, 5]) | ||
.with_profile(args.profile); | ||
|
||
// build model | ||
let mut model = YOLO::new(options)?; | ||
|
||
// build dataloader | ||
let dl = DataLoader::new(&args.source)? | ||
.with_batch(model.batch() as _) | ||
.build()?; | ||
|
||
// build annotator | ||
let annotator = Annotator::default() | ||
.with_skeletons(&COCO_SKELETONS_16) | ||
.without_masks(true) // no masks plotting when doing segment task | ||
.with_bboxes_thickness(3) | ||
.with_keypoints_name(false) // enable keypoints names | ||
.with_saveout_subs(&["YOLO"]) | ||
.with_saveout(&saveout); | ||
|
||
// build viewer | ||
let mut viewer = if args.view { | ||
Some(Viewer::new().with_delay(5).with_scale(1.).resizable(true)) | ||
} else { | ||
None | ||
}; | ||
|
||
// run & annotate | ||
for (xs, _paths) in dl { | ||
let ys = model.forward(&xs, args.profile)?; | ||
let images_plotted = annotator.plot(&xs, &ys, !args.nosave)?; | ||
|
||
// show image | ||
match &mut viewer { | ||
Some(viewer) => viewer.imshow(&images_plotted)?, | ||
None => continue, | ||
} | ||
|
||
// check out window and key event | ||
match &mut viewer { | ||
Some(viewer) => { | ||
if !viewer.is_open() || viewer.is_key_pressed(usls::Key::Escape) { | ||
break; | ||
} | ||
} | ||
None => continue, | ||
} | ||
|
||
// write video | ||
if !args.nosave { | ||
match &mut viewer { | ||
Some(viewer) => viewer.write_batch(&images_plotted)?, | ||
None => continue, | ||
} | ||
} | ||
} | ||
|
||
// finish video write | ||
if !args.nosave { | ||
if let Some(viewer) = &mut viewer { | ||
viewer.finish_write()?; | ||
} | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.