v0.0.16: Add Viewer for image show

* Add `Viewer` for image-show

* Add .`with_ixx()` to simplify model building with `Options`

* Update `MinOptMax`
This commit is contained in:
Jamjamjon
2024-09-28 09:51:33 +08:00
committed by GitHub
parent f0fd4936e8
commit 6ace97f09f
42 changed files with 891 additions and 1752 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "usls"
version = "0.0.15"
version = "0.0.16"
edition = "2021"
description = "A Rust library integrated with ONNXRuntime, providing a collection of ML models."
repository = "https://github.com/jamjamjon/usls"
@ -38,6 +38,7 @@ video-rs = { version = "0.9.0", features = ["ndarray"] }
natord = "1.0.9"
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
minifb = "0.27.0"
[features]

View File

@ -56,9 +56,8 @@ pub fn benchmark_cuda(c: &mut Criterion, h: isize, w: isize) -> Result<()> {
.with_cuda(0)
// .with_cpu()
.with_dry_run(0)
.with_i00((1, 1, 4).into())
.with_i02((320, h, 1280).into())
.with_i03((320, w, 1280).into())
.with_ixx(0, 2, (320, h, 1280).into())
.with_ixx(0, 3, (320, w, 1280).into())
.with_confs(&[0.2, 0.15]);
let mut model = YOLO::new(options)?;

View File

@ -4,19 +4,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// visual
let options_visual = Options::default()
.with_model("blip/visual-base.onnx")?
.with_i00((1, 1, 4).into())
// .with_ixx(0, 2, 384.into())
// .with_ixx(0, 3, 384.into())
.with_profile(false);
// textual
let options_textual = Options::default()
.with_model("blip/textual-base.onnx")?
.with_tokenizer("blip/tokenizer.json")?
.with_i00((1, 1, 4).into()) // input_id: batch
.with_i01((1, 1, 4).into()) // input_id: seq_len
.with_i10((1, 1, 4).into()) // attention_mask: batch
.with_i11((1, 1, 4).into()) // attention_mask: seq_len
.with_i20((1, 1, 4).into()) // encoder_hidden_states: batch
.with_i30((1, 1, 4).into()) // encoder_attention_mask: batch
.with_profile(false);
// build model

View File

@ -2,17 +2,12 @@ use usls::{models::Clip, DataLoader, Options};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// visual
let options_visual = Options::default()
.with_model("clip/visual-base-dyn.onnx")?
.with_i00((1, 1, 4).into())
.with_profile(false);
let options_visual = Options::default().with_model("clip/visual-base-dyn.onnx")?;
// textual
let options_textual = Options::default()
.with_model("clip/textual-base-dyn.onnx")?
.with_tokenizer("clip/tokenizer.json")?
.with_i00((1, 1, 4).into())
.with_profile(false);
.with_tokenizer("clip/tokenizer.json")?;
// build model
let mut model = Clip::new(options_visual, options_textual)?;

View File

@ -1,4 +1,6 @@
use usls::{models::YOLO, Annotator, DataLoader, Options, Vision, YOLOTask, YOLOVersion};
use usls::{
models::YOLO, Annotator, DataLoader, Device, Options, Viewer, Vision, YOLOTask, YOLOVersion,
};
fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt()
@ -6,40 +8,57 @@ fn main() -> anyhow::Result<()> {
.init();
let options = Options::new()
.with_cuda(0)
.with_device(Device::Cuda(0))
.with_model("yolo/v8-m-dyn.onnx")?
.with_yolo_version(YOLOVersion::V8)
.with_yolo_task(YOLOTask::Detect)
.with_i00((1, 1, 4).into())
.with_i02((0, 640, 640).into())
.with_i03((0, 640, 640).into())
.with_batch(2)
.with_ixx(0, 2, (416, 640, 800).into())
.with_ixx(0, 3, (416, 640, 800).into())
.with_confs(&[0.2]);
let mut model = YOLO::new(options)?;
// build dataloader
let dl = DataLoader::new(
// "images/bus.jpg", // remote image
// "../images", // image folder
// "../demo.mp4", // local video
// "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4", // remote video
// "rtsp://admin:xyz@192.168.2.217:554/h265/ch1/", // rtsp h264 stream
"./assets/bus.jpg", // local image
)?
.with_batch(1)
.build()?;
// build annotator
let annotator = Annotator::new()
.with_bboxes_thickness(4)
.with_saveout("YOLO-DataLoader");
// run
// build dataloader
let dl = DataLoader::new(
// "images/bus.jpg", // remote image
// "../images", // image folder
// "../demo.mp4", // local video
// "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4", // remote video
// "rtsp://admin:xyz@192.168.2.217:554/h265/ch1/", // rtsp h264 stream
// "./assets/bus.jpg", // local image
"../7.mp4",
)?
.with_batch(1)
.build()?;
let mut viewer = Viewer::new().with_delay(10).with_scale(1.).resizable(true);
// iteration
for (xs, _) in dl {
// std::thread::sleep(std::time::Duration::from_millis(100));
let ys = model.forward(&xs, false)?;
annotator.annotate(&xs, &ys);
// inference & annotate
let ys = model.run(&xs)?;
let images_plotted = annotator.plot(&xs, &ys, false)?;
// show image
viewer.imshow(&images_plotted)?;
// check out window and key event
if !viewer.is_open() || viewer.is_key_pressed(usls::Key::Escape) {
break;
}
// write video
viewer.write_batch(&images_plotted)?;
}
// finish video write
viewer.finish_write()?;
// images -> video
// DataLoader::is2v("runs/YOLO-DataLoader", &["runs", "is2v"], 24)?;

View File

@ -3,9 +3,9 @@ use usls::{models::DB, Annotator, DataLoader, Options};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// build model
let options = Options::default()
.with_i00((1, 4, 8).into())
.with_i02((608, 960, 1280).into())
.with_i03((608, 960, 1280).into())
.with_ixx(0, 0, (1, 4, 8).into())
.with_ixx(0, 2, (608, 960, 1280).into())
.with_ixx(0, 3, (608, 960, 1280).into())
// .with_trt(0)
.with_confs(&[0.4])
.with_min_width(5.0)

View File

@ -5,13 +5,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let options = Options::default()
// .with_model("depth-anything/v1-s-dyn.onnx")?
.with_model("depth-anything/v2-s.onnx")?
.with_i00((1, 1, 8).into())
.with_i02((384, 512, 1024).into())
.with_i03((384, 512, 1024).into());
.with_ixx(0, 2, (384, 512, 1024).into())
.with_ixx(0, 3, (384, 512, 1024).into());
let mut model = DepthAnything::new(options)?;
// load
let x = [DataLoader::try_read("images/2.jpg")?];
let x = [DataLoader::try_read("images/street.jpg")?];
// run
let y = model.run(&x)?;

View File

@ -4,9 +4,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// build model
let options = Options::default()
.with_model("dinov2/s-dyn.onnx")?
.with_i00((1, 1, 1).into())
.with_i02((224, 224, 224).into())
.with_i03((224, 224, 224).into());
.with_ixx(0, 2, 224.into())
.with_ixx(0, 3, 224.into());
let mut model = Dinov2::new(options)?;
let x = [DataLoader::try_read("images/bus.jpg")?];
let y = model.run(&x)?;

View File

@ -1,130 +1,35 @@
use usls::{models::Florence2, Annotator, DataLoader, Options, Task};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let batch_size = 3;
// vision encoder
let options_vision_encoder = Options::default()
.with_model("florence2/base-vision-encoder.onnx")?
.with_i00((1, 2, 4).into())
.with_i02((512, 768, 800).into())
.with_i03((512, 768, 800).into())
.with_profile(false)
.with_cuda(0);
.with_model("florence2/base-vision-encoder-f16.onnx")?
.with_ixx(0, 2, (512, 768, 800).into())
.with_ixx(0, 3, 768.into())
.with_ixx(0, 0, (1, batch_size as _, 8).into());
// text embed
let options_text_embed = Options::default()
.with_model("florence2/base-embed-tokens.onnx")?
.with_i00((1, 2, 4).into())
.with_i01((1, 2, 20).into()) // seq_length
.with_model("florence2/base-embed-tokens-f16.onnx")?
.with_tokenizer("florence2/tokenizer.json")?
.with_profile(false);
.with_batch(batch_size);
// transformer encoder
let options_encoder = Options::default()
.with_model("florence2/base-encoder.onnx")?
.with_i00((1, 2, 4).into())
.with_i01((1, 2, 300).into()) // encoder_sequence_length
.with_i10((1, 2, 4).into())
.with_i11((1, 2, 300).into()) // encoder_sequence_length
.with_profile(false);
.with_model("florence2/base-encoder-f16.onnx")?
.with_batch(batch_size);
// transformer decoder
let options_decoder = Options::default()
.with_model("florence2/base-decoder.onnx")?
.with_i00((1, 2, 4).into())
.with_i01((1, 2, 300).into()) // encoder_sequence_length
.with_i10((1, 2, 4).into())
.with_i11((1, 2, 300).into()) // encoder_sequence_length
.with_i20((1, 2, 4).into())
.with_i21((1, 2, 300).into()) // encoder_sequence_length
.with_profile(false);
.with_model("florence2/base-decoder-f16.onnx")?
.with_batch(batch_size);
// transformer decoder merged
let options_decoder_merged = Options::default()
.with_model("florence2/base-decoder-merged.onnx")?
// encoder_attention_mask
.with_i00((1, 2, 4).into())
.with_i01((1, 2, 300).into()) // encoder_sequence_length
// encoder_hidden_states
.with_i10((1, 2, 4).into())
.with_i11((1, 2, 300).into()) // encoder_sequence_length
// inputs_embeds
.with_i20((1, 2, 4).into())
.with_i21((1, 2, 300).into()) // encoder_sequence_length
// past_key_values.0.decoder.key
.with_i30((1, 2, 4).into())
.with_i32_((1, 2, 1).into())
// past_key_values.0.decoder.value
.with_i40((1, 2, 4).into())
.with_i42((1, 2, 1).into())
// past_key_values.0.encoder.key
.with_i50((1, 2, 4).into())
.with_i52((1, 2, 1).into())
// past_key_values.0.decoder.value
.with_i60((1, 2, 4).into())
.with_i62((1, 2, 1).into())
// past_key_values.1.decoder.key
.with_i70((1, 2, 4).into())
.with_i72((1, 2, 1).into())
// past_key_values.1.decoder.value
.with_i80((1, 2, 4).into())
.with_i82((1, 2, 1).into())
// past_key_values.1.encoder.key
.with_i90((1, 2, 4).into())
.with_i92((1, 2, 1).into())
// past_key_values.1.decoder.value
.with_i100((1, 2, 4).into())
.with_i102((1, 2, 1).into())
// past_key_values.2.decoder.key
.with_i110((1, 2, 4).into())
.with_i112((1, 2, 1).into())
// past_key_values.2.decoder.value
.with_i120((1, 2, 4).into())
.with_i122((1, 2, 1).into())
// past_key_values.2.encoder.key
.with_i130((1, 2, 4).into())
.with_i132((1, 2, 1).into())
// past_key_values.2.decoder.value
.with_i140((1, 2, 4).into())
.with_i142((1, 2, 1).into())
// past_key_values.3.decoder.key
.with_i150((1, 2, 4).into())
.with_i152((1, 2, 1).into())
// past_key_values.3.decoder.value
.with_i160((1, 2, 4).into())
.with_i162((1, 2, 1).into())
// past_key_values.3.encoder.key
.with_i170((1, 2, 4).into())
.with_i172((1, 2, 1).into())
// past_key_values.3.decoder.value
.with_i180((1, 2, 4).into())
.with_i182((1, 2, 1).into())
// past_key_values.4.decoder.key
.with_i190((1, 2, 4).into())
.with_i192((1, 2, 1).into())
// past_key_values.4.decoder.value
.with_i200((1, 2, 4).into())
.with_i202((1, 2, 1).into())
// past_key_values.4.encoder.key
.with_i210((1, 2, 4).into())
.with_i212((1, 2, 1).into())
// past_key_values.4.decoder.value
.with_i220((1, 2, 4).into())
.with_i222((1, 2, 1).into())
// past_key_values.5.decoder.key
.with_i230((1, 2, 4).into())
.with_i232((1, 2, 1).into())
// past_key_values.5.decoder.value
.with_i240((1, 2, 4).into())
.with_i242((1, 2, 1).into())
// past_key_values.5.encoder.key
.with_i250((1, 2, 4).into())
.with_i252((1, 2, 1).into())
// past_key_values.5.decoder.value
.with_i260((1, 2, 4).into())
.with_i262((1, 2, 1).into())
//use_cache_branch
.with_i270((1, 2, 1).into())
.with_profile(false);
.with_model("florence2/base-decoder-merged-f16.onnx")?
.with_batch(batch_size);
// build model
let mut model = Florence2::new(

View File

@ -2,20 +2,20 @@ use usls::{models::GroundingDINO, Annotator, DataLoader, Options};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let opts = Options::default()
.with_i00((1, 1, 4).into())
.with_i02((640, 800, 1200).into())
.with_i03((640, 1200, 1200).into())
.with_i10((1, 1, 4).into())
.with_i11((256, 256, 512).into())
.with_i20((1, 1, 4).into())
.with_i21((256, 256, 512).into())
.with_i30((1, 1, 4).into())
.with_i31((256, 256, 512).into())
.with_i40((1, 1, 4).into())
.with_i41((256, 256, 512).into())
.with_i50((1, 1, 4).into())
.with_i51((256, 256, 512).into())
.with_i52((256, 256, 512).into())
.with_ixx(0, 0, (1, 1, 4).into())
.with_ixx(0, 2, (640, 800, 1200).into())
.with_ixx(0, 3, (640, 1200, 1200).into())
// .with_i10((1, 1, 4).into())
// .with_i11((256, 256, 512).into())
// .with_i20((1, 1, 4).into())
// .with_i21((256, 256, 512).into())
// .with_i30((1, 1, 4).into())
// .with_i31((256, 256, 512).into())
// .with_i40((1, 1, 4).into())
// .with_i41((256, 256, 512).into())
// .with_i50((1, 1, 4).into())
// .with_i51((256, 256, 512).into())
// .with_i52((256, 256, 512).into())
.with_model("grounding-dino/swint-ogc-dyn-u8.onnx")? // TODO: current onnx model does not support bs > 1
// .with_model("grounding-dino/swint-ogc-dyn-f32.onnx")?
.with_tokenizer("grounding-dino/tokenizer.json")?

View File

@ -4,9 +4,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// build model
let options = Options::default()
.with_model("modnet/dyn-f32.onnx")?
.with_i00((1, 1, 4).into())
.with_i02((416, 512, 800).into())
.with_i03((416, 512, 800).into());
.with_ixx(0, 2, (416, 512, 800).into())
.with_ixx(0, 3, (416, 512, 800).into());
let mut model = MODNet::new(options)?;
// load image

View File

@ -4,7 +4,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// build model
let options = Options::default()
.with_model("rtmo/s-dyn.onnx")?
.with_i00((1, 1, 8).into())
.with_nk(17)
.with_confs(&[0.3])
.with_kconfs(&[0.5]);

View File

@ -29,9 +29,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.with_model("sam/sam-vit-b-encoder-u8.onnx")?;
let options_decoder = Options::default()
.with_i00((1, 1, 1).into())
.with_i11((1, 1, 1).into())
.with_i21((1, 1, 1).into())
.with_sam_kind(SamKind::Sam)
// .with_model("sam/sam-vit-b-decoder.onnx")?;
// .with_model("sam/sam-vit-b-decoder-singlemask.onnx")?;
@ -44,8 +41,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// .with_model("sam/sam2-hiera-small-encoder.onnx")?;
.with_model("sam/sam2-hiera-base-plus-encoder.onnx")?;
let options_decoder = Options::default()
.with_i31((1, 1, 1).into())
.with_i41((1, 1, 1).into())
.with_sam_kind(SamKind::Sam2)
// .with_model("sam/sam2-hiera-tiny-decoder.onnx")?;
// .with_model("sam/sam2-hiera-small-decoder.onnx")?;
@ -57,9 +52,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
Options::default().with_model("sam/mobile-sam-vit-t-encoder.onnx")?;
let options_decoder = Options::default()
.with_i00((1, 1, 1).into())
.with_i11((1, 1, 1).into())
.with_i21((1, 1, 1).into())
.with_sam_kind(SamKind::MobileSam)
.with_model("sam/mobile-sam-vit-t-decoder.onnx")?;
(options_encoder, options_decoder, "Mobile-SAM")
@ -68,9 +60,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let options_encoder = Options::default().with_model("sam/sam-hq-vit-t-encoder.onnx")?;
let options_decoder = Options::default()
.with_i00((1, 1, 1).into())
.with_i21((1, 1, 1).into())
.with_i31((1, 1, 1).into())
.with_sam_kind(SamKind::SamHq)
.with_model("sam/sam-hq-vit-t-decoder.onnx")?;
(options_encoder, options_decoder, "SAM-HQ")
@ -78,9 +67,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
SamKind::EdgeSam => {
let options_encoder = Options::default().with_model("sam/edge-sam-3x-encoder.onnx")?;
let options_decoder = Options::default()
.with_i00((1, 1, 1).into())
.with_i11((1, 1, 1).into())
.with_i21((1, 1, 1).into())
.with_sam_kind(SamKind::EdgeSam)
.with_model("sam/edge-sam-3x-decoder.onnx")?;
(options_encoder, options_decoder, "Edge-SAM")
@ -88,9 +74,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
};
let options_encoder = options_encoder
.with_cuda(args.device_id)
.with_i00((1, 1, 1).into())
.with_i02((800, 1024, 1024).into())
.with_i03((800, 1024, 1024).into());
.with_ixx(0, 2, (800, 1024, 1024).into())
.with_ixx(0, 3, (800, 1024, 1024).into());
let options_decoder = options_decoder
.with_cuda(args.device_id)
.use_low_res_mask(args.use_low_res_mask)

View File

@ -8,9 +8,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let options = Options::default()
.with_model("sapiens/seg-0.3b-dyn.onnx")?
.with_sapiens_task(SapiensTask::Seg)
.with_names(&BODY_PARTS_28)
.with_profile(false)
.with_i00((1, 1, 8).into());
.with_names(&BODY_PARTS_28);
let mut model = Sapiens::new(options)?;
// load

View File

@ -3,8 +3,9 @@ use usls::{models::SVTR, DataLoader, Options};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// build model
let options = Options::default()
.with_i00((1, 2, 8).into())
.with_i03((320, 960, 1600).into())
.with_ixx(0, 0, (1, 2, 8).into())
.with_ixx(0, 2, (320, 960, 1600).into())
.with_ixx(0, 3, (320, 960, 1600).into())
.with_confs(&[0.2])
.with_vocab("svtr/ppocr_rec_vocab.txt")?
.with_model("svtr/ppocr-v4-svtr-ch-dyn.onnx")?;

View File

@ -5,12 +5,8 @@ use usls::{
fn main() -> Result<(), Box<dyn std::error::Error>> {
// build SAM
let options_encoder = Options::default()
.with_i00((1, 1, 1).into())
.with_model("sam/mobile-sam-vit-t-encoder.onnx")?;
let options_encoder = Options::default().with_model("sam/mobile-sam-vit-t-encoder.onnx")?;
let options_decoder = Options::default()
.with_i11((1, 1, 1).into())
.with_i21((1, 1, 1).into())
.with_find_contours(true)
.with_sam_kind(SamKind::Sam)
.with_model("sam/mobile-sam-vit-t-decoder.onnx")?;
@ -22,9 +18,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.with_yolo_task(YOLOTask::Detect)
.with_model("yolo/v8-m-dyn.onnx")?
.with_cuda(0)
.with_i00((1, 1, 4).into())
.with_i02((416, 640, 800).into())
.with_i03((416, 640, 800).into())
.with_ixx(0, 2, (416, 640, 800).into())
.with_ixx(0, 3, (416, 640, 800).into())
.with_find_contours(false)
.with_confs(&[0.45]);
let mut yolo = YOLO::new(options_yolo)?;

View File

@ -21,6 +21,9 @@ pub struct Args {
#[arg(long, value_enum, default_value_t = YOLOVersion::V8)]
pub ver: YOLOVersion,
#[arg(long, default_value_t = 1)]
pub batch_size: usize,
#[arg(long, default_value_t = 224)]
pub width_min: isize,
@ -163,7 +166,7 @@ fn main() -> Result<()> {
} else if args.trt {
let options = options.with_trt(args.device_id);
if args.half {
options.with_fp16(true)
options.with_trt_fp16(true)
} else {
options
}
@ -173,9 +176,9 @@ fn main() -> Result<()> {
options.with_cpu()
};
let options = options
.with_i00((1, 1, 4).into())
.with_i02((args.height_min, args.height, args.height_max).into())
.with_i03((args.width_min, args.width, args.width_max).into())
.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(&[0.2, 0.15]) // class_0: 0.4, others: 0.15
// .with_names(&COCO_CLASS_NAMES_80)
.with_names2(&COCO_KEYPOINTS_17)

View File

@ -4,7 +4,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// build model
let options = Options::default()
.with_model("yolop/v2-dyn-480x800.onnx")?
.with_i00((1, 1, 8).into())
.with_confs(&[0.3]);
let mut model = YOLOPv2::new(options)?;

View File

@ -358,17 +358,17 @@ impl Annotator {
Dir::Currnet.raw_path_with_subs(&subs)
}
/// Annotate images, and no return
/// Annotate images, save, and no return
pub fn annotate(&self, imgs: &[DynamicImage], ys: &[Y]) {
let _ = self.plot(imgs, ys);
let _ = self.plot(imgs, ys, true);
}
/// Plot images and return plotted images(RGBA8)
pub fn plot(&self, imgs: &[DynamicImage], ys: &[Y]) -> Result<Vec<RgbaImage>> {
/// Plot images and return plotted images
pub fn plot(&self, imgs: &[DynamicImage], ys: &[Y], save: bool) -> Result<Vec<DynamicImage>> {
let span = tracing::span!(tracing::Level::INFO, "Annotator-plot");
let _guard = span.enter();
let mut vs: Vec<RgbaImage> = Vec::new();
let mut vs: Vec<DynamicImage> = Vec::new();
// annotate
for (img, y) in imgs.iter().zip(ys.iter()) {
@ -414,16 +414,19 @@ impl Annotator {
self.plot_probs(&mut img_rgba, xs);
}
// save
let saveout = self.saveout()?.join(format!("{}.png", string_now("-")));
match img_rgba.save(&saveout) {
Err(err) => tracing::error!("{} Saving failed: {:?}", CROSS_MARK, err),
Ok(_) => {
tracing::info!("{} Annotated image saved to: {:?}", CHECK_MARK, saveout);
// save or not
if save {
let saveout = self.saveout()?.join(format!("{}.png", string_now("-")));
match img_rgba.save(&saveout) {
Err(err) => tracing::error!("{} Saving failed: {:?}", CROSS_MARK, err),
Ok(_) => {
tracing::info!("{} Annotated image saved to: {:?}", CHECK_MARK, saveout);
}
}
}
vs.push(img_rgba);
// RgbaImage -> DynamicImage
vs.push(image::DynamicImage::from(img_rgba));
}
Ok(vs)
}

View File

@ -19,6 +19,7 @@ type TempReturnType = (Vec<DynamicImage>, Vec<PathBuf>);
pub struct DataLoaderIterator {
receiver: mpsc::Receiver<TempReturnType>,
progress_bar: Option<ProgressBar>,
batch_size: u64,
}
impl Iterator for DataLoaderIterator {
@ -29,7 +30,7 @@ impl Iterator for DataLoaderIterator {
None => self.receiver.recv().ok(),
Some(progress_bar) => match self.receiver.recv().ok() {
Some(item) => {
progress_bar.inc(1);
progress_bar.inc(self.batch_size);
Some(item)
}
None => {
@ -53,7 +54,7 @@ impl IntoIterator for DataLoader {
fn into_iter(self) -> Self::IntoIter {
let progress_bar = if self.with_pb {
build_progress_bar(
self.nf / self.batch_size as u64,
self.nf,
" Iterating",
Some(&format!("{:?}", self.media_type)),
crate::PROGRESS_BAR_STYLE_CYAN_2,
@ -66,6 +67,7 @@ impl IntoIterator for DataLoader {
DataLoaderIterator {
receiver: self.receiver,
progress_bar,
batch_size: self.batch_size as _,
}
}
}
@ -164,7 +166,7 @@ impl DataLoader {
}
// summary
tracing::info!("{} Found {:?} x{}", CHECK_MARK, media_type, nf,);
tracing::info!("{} Found {:?} x{}", CHECK_MARK, media_type, nf);
Ok(DataLoader {
paths,

View File

@ -1,6 +1,6 @@
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Device {
Auto(usize), // TODO
Auto(usize),
Cpu(usize),
Cuda(usize),
Trt(usize),

View File

@ -14,6 +14,10 @@ pub enum Dir {
}
impl Dir {
pub fn saveout(subs: &[&str]) -> anyhow::Result<std::path::PathBuf> {
Self::Currnet.raw_path_with_subs(subs)
}
/// Retrieves the base path for the specified directory type, optionally appending the `usls` subdirectory.
///
/// # Arguments

View File

@ -1,63 +1,421 @@
/// A value composed of Min-Opt-Max
#[derive(Clone)]
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
pub struct MinOptMax {
pub min: isize,
pub opt: isize,
pub max: isize,
min: usize,
opt: usize,
max: usize,
}
impl Default for MinOptMax {
fn default() -> Self {
Self {
min: -1,
opt: -1,
max: -1,
min: 1,
opt: 1,
max: 1,
}
}
}
impl std::fmt::Debug for MinOptMax {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("")
.field("Min", &self.min)
.field("Opt", &self.opt)
.field("Max", &self.max)
.finish()
}
}
impl From<(isize, isize, isize)> for MinOptMax {
fn from((min, opt, max): (isize, isize, isize)) -> Self {
let min = min.min(opt);
let max = max.max(opt);
Self { min, opt, max }
}
}
impl From<[isize; 3]> for MinOptMax {
fn from([min, opt, max]: [isize; 3]) -> Self {
let min = min.min(opt);
let max = max.max(opt);
Self { min, opt, max }
}
}
impl MinOptMax {
pub fn new(opt: isize) -> Self {
pub fn min(&self) -> usize {
self.min
}
pub fn opt(&self) -> usize {
self.opt
}
pub fn max(&self) -> usize {
self.max
}
pub fn ones() -> Self {
Default::default()
}
pub fn zeros() -> Self {
Self {
min: opt,
opt,
max: opt,
min: 0,
opt: 0,
max: 0,
}
}
pub fn update(&mut self, opt: isize) {
pub fn update_opt(&mut self, opt: usize) {
// `opt` can be any valid usize number, even if it is smaller than `self.min` or greater than `self.max`.
self.opt = opt;
if self.min > opt {
self.min = opt;
}
if self.max < opt {
self.max = opt;
self.auto_tune();
}
pub fn try_update_min(&mut self, x: usize) -> anyhow::Result<()> {
if x > self.opt {
anyhow::bail!(
"Newly assigned `min`: {} must be smaller than the current `self.opt`: {}",
x,
self.opt
);
} else {
self.min = x;
Ok(())
}
}
pub fn try_update_max(&mut self, x: usize) -> anyhow::Result<()> {
if x < self.opt {
anyhow::bail!(
"Newly assigned `max`: {} must be greater than the current `self.opt`: {}",
x,
self.opt
);
} else {
self.max = x;
Ok(())
}
}
pub fn auto_tune(&mut self) {
// Rule 1: min <= opt <= max
// Rule 2: opt is unchangeable here
self.min = self.min.min(self.opt);
self.max = self.max.max(self.opt);
}
pub fn auto_tuned(mut self) -> Self {
self.auto_tune();
self
}
pub fn is_dyn(&self) -> bool {
self.min + self.max + self.opt == 0
}
}
impl From<i32> for MinOptMax {
fn from(opt: i32) -> Self {
let opt = opt.max(0) as usize;
let min = opt;
let max = opt;
Self { min, opt, max }
}
}
impl From<i64> for MinOptMax {
fn from(opt: i64) -> Self {
let opt = opt.max(0) as usize;
let min = opt;
let max = opt;
Self { min, opt, max }
}
}
impl From<u32> for MinOptMax {
fn from(opt: u32) -> Self {
let opt = opt as usize;
let min = opt;
let max = opt;
Self { min, opt, max }
}
}
impl From<u64> for MinOptMax {
fn from(opt: u64) -> Self {
let opt = opt as usize;
let min = opt;
let max = opt;
Self { min, opt, max }
}
}
impl From<usize> for MinOptMax {
fn from(opt: usize) -> Self {
let min = opt;
let max = opt;
Self { min, opt, max }
}
}
impl From<isize> for MinOptMax {
fn from(opt: isize) -> Self {
let opt = opt.max(0) as usize;
let min = opt;
let max = opt;
Self { min, opt, max }
}
}
impl From<f32> for MinOptMax {
fn from(opt: f32) -> Self {
let opt = opt.max(0.).round() as usize;
let min = opt;
let max = opt;
Self { min, opt, max }
}
}
impl From<f64> for MinOptMax {
fn from(opt: f64) -> Self {
let opt = opt.max(0.).round() as usize;
let min = opt;
let max = opt;
Self { min, opt, max }
}
}
impl<T> From<(T, T, T)> for MinOptMax
where
T: Into<MinOptMax>,
{
fn from((min, opt, max): (T, T, T)) -> Self {
let min = min.into().min;
let opt = opt.into().opt;
let max = max.into().max;
Self { min, opt, max }.auto_tuned()
}
}
impl<T> From<[T; 3]> for MinOptMax
where
T: Into<MinOptMax>,
{
fn from([min, opt, max]: [T; 3]) -> Self {
Self::from((min, opt, max))
}
}
#[cfg(test)]
mod tests_minoptmax {
use super::MinOptMax;
#[test]
fn test_default() {
let default_mom = MinOptMax::default();
assert_eq!(default_mom.min, 1);
assert_eq!(default_mom.opt, 1);
assert_eq!(default_mom.max, 1);
}
#[test]
fn test_ones() {
let ones_mom = MinOptMax::ones();
assert_eq!(ones_mom.min, 1);
assert_eq!(ones_mom.opt, 1);
assert_eq!(ones_mom.max, 1);
}
#[test]
fn test_zeros() {
let zeros_mom = MinOptMax::zeros();
assert_eq!(zeros_mom.min, 0);
assert_eq!(zeros_mom.opt, 0);
assert_eq!(zeros_mom.max, 0);
}
#[test]
fn test_update_opt() {
let mut mom = MinOptMax::default();
mom.update_opt(5);
assert_eq!(mom.opt, 5);
assert_eq!(mom.min, 1);
assert_eq!(mom.max, 5);
let mut mom = MinOptMax::from((5, 6, 7));
mom.update_opt(2);
assert_eq!(mom.opt, 2);
assert_eq!(mom.min, 2);
assert_eq!(mom.max, 7);
}
#[test]
fn test_try_update_min_success() {
let mut mom = MinOptMax::default();
let result = mom.try_update_min(0);
assert!(result.is_ok());
assert_eq!(mom.min, 0);
let result = mom.try_update_min(1);
assert!(result.is_ok());
assert_eq!(mom.min, 1);
}
#[test]
fn test_try_update_min_failure() {
let mut mom = MinOptMax::default(); // 1
let result = mom.try_update_min(6);
assert!(result.is_err());
assert_eq!(mom.min, 1);
assert_eq!(mom.opt, 1);
assert_eq!(mom.max, 1);
}
#[test]
fn test_try_update_max_success() {
let mut mom = MinOptMax::default();
let result = mom.try_update_max(20);
assert!(result.is_ok());
assert_eq!(mom.max, 20);
assert_eq!(mom.opt, 1);
assert_eq!(mom.min, 1);
}
#[test]
fn test_try_update_max_failure() {
let mut mom = MinOptMax::default();
mom.update_opt(5);
let result = mom.try_update_max(4);
assert!(result.is_err());
assert_eq!(mom.max, 5);
assert_eq!(mom.opt, 5);
assert_eq!(mom.min, 1);
}
#[test]
fn test_combined_updates() {
let mut mom = MinOptMax::default();
mom.update_opt(5);
assert_eq!(mom.max, 5);
assert_eq!(mom.opt, 5);
assert_eq!(mom.min, 1);
assert!(mom.try_update_min(3).is_ok());
assert_eq!(mom.min, 3);
assert_eq!(mom.opt, 5);
assert_eq!(mom.max, 5);
assert!(mom.try_update_max(6).is_ok());
assert_eq!(mom.max, 6);
assert_eq!(mom.opt, 5);
assert_eq!(mom.min, 3);
// unchanged
assert!(mom.try_update_min(7).is_err());
assert_eq!(mom.max, 6);
assert_eq!(mom.opt, 5);
assert_eq!(mom.min, 3);
// unchanged
assert!(mom.try_update_max(4).is_err());
assert_eq!(mom.max, 6);
assert_eq!(mom.opt, 5);
assert_eq!(mom.min, 3);
}
#[test]
fn test_auto_tune() {
let mut mom = MinOptMax {
min: 5,
opt: 3,
max: 7,
};
mom.auto_tune();
assert_eq!(mom.min, 3);
assert_eq!(mom.max, 7);
assert_eq!(mom.opt, 3);
}
#[test]
fn test_auto_tuned() {
let mom = MinOptMax {
min: 5,
opt: 3,
max: 7,
}
.auto_tuned();
assert_eq!(mom.min, 3);
assert_eq!(mom.max, 7);
assert_eq!(mom.opt, 3);
}
#[test]
fn test_is_dyn() {
let dyn_mom = MinOptMax::zeros();
assert!(dyn_mom.is_dyn());
let non_dyn_mom = MinOptMax {
min: 1,
opt: 1,
max: 1,
};
assert!(!non_dyn_mom.is_dyn());
}
#[test]
fn test_from_integer_types() {
let from_i32: MinOptMax = MinOptMax::from(-5);
assert_eq!(from_i32, MinOptMax::zeros());
let from_i64: MinOptMax = MinOptMax::from(-3);
assert_eq!(from_i64, MinOptMax::zeros());
let from_u32: MinOptMax = MinOptMax::from(4u32);
assert_eq!(
from_u32,
MinOptMax {
min: 4,
opt: 4,
max: 4
}
);
let from_u64: MinOptMax = MinOptMax::from(7u64);
assert_eq!(
from_u64,
MinOptMax {
min: 7,
opt: 7,
max: 7
}
);
let from_usize: MinOptMax = MinOptMax::from(10);
assert_eq!(
from_usize,
MinOptMax {
min: 10,
opt: 10,
max: 10
}
);
let from_isize: MinOptMax = MinOptMax::from(-1isize);
assert_eq!(from_isize, MinOptMax::zeros());
let from_f32: MinOptMax = MinOptMax::from(-2.0);
assert_eq!(from_f32, MinOptMax::zeros());
let from_f64: MinOptMax = MinOptMax::from(3.9);
assert_eq!(
from_f64,
MinOptMax {
min: 4,
opt: 4,
max: 4
}
);
}
#[test]
fn test_from_tuple() {
let tuple_mom: MinOptMax = MinOptMax::from((1, 2, 3));
assert_eq!(
tuple_mom,
MinOptMax {
min: 1,
opt: 2,
max: 3
}
);
}
#[test]
fn test_from_array() {
let array_mom: MinOptMax = [1, 2, 3].into();
assert_eq!(
array_mom,
MinOptMax {
min: 1,
opt: 2,
max: 3
}
);
}
}

View File

@ -15,6 +15,7 @@ mod ort_engine;
mod task;
mod tokenizer_stream;
mod ts;
mod viewer;
mod vision;
mod x;
mod xs;
@ -31,10 +32,14 @@ pub use metric::Metric;
pub use min_opt_max::MinOptMax;
pub use ops::Ops;
pub use options::Options;
pub use ort_engine::OrtEngine;
pub use ort_engine::*;
pub use task::Task;
pub use tokenizer_stream::TokenizerStream;
pub use ts::Ts;
pub use viewer::Viewer;
pub use vision::Vision;
pub use x::X;
pub use xs::Xs;
// re-export
pub use minifb::Key;

File diff suppressed because it is too large Load Diff

View File

@ -12,12 +12,26 @@ use crate::{
CHECK_MARK, CROSS_MARK, X,
};
/// Ort Tensor Attrs: name, data_type, dims
/// A struct for input composed of the i-th input, the ii-th dimension, and the value.
#[derive(Clone, Debug, Default)]
pub struct Iiix {
pub i: usize,
pub ii: usize,
pub x: MinOptMax,
}
impl From<(usize, usize, MinOptMax)> for Iiix {
fn from((i, ii, x): (usize, usize, MinOptMax)) -> Self {
Self { i, ii, x }
}
}
/// A struct for tensor attrs composed of the names, the dtypes, and the dimensions.
#[derive(Debug)]
pub struct OrtTensorAttr {
pub names: Vec<String>,
pub dtypes: Vec<ort::TensorElementType>,
pub dimss: Vec<Vec<isize>>,
pub dtypes: Vec<TensorElementType>,
pub dimss: Vec<Vec<usize>>,
}
/// ONNXRuntime Backend
@ -69,193 +83,8 @@ impl OrtEngine {
// inputs & outputs
let inputs_attrs = Self::io_from_onnx_value_info(&initializer_names, &graph.input)?;
let outputs_attrs = Self::io_from_onnx_value_info(&initializer_names, &graph.output)?;
// inputs minoptmax
let mut inputs_minoptmax: Vec<Vec<MinOptMax>> = Vec::new();
for (i, dims) in inputs_attrs.dimss.iter().enumerate() {
let mut v_: Vec<MinOptMax> = Vec::new();
for (ii, &x) in dims.iter().enumerate() {
let x_default: MinOptMax = (
inputs_attrs.dimss[i][ii],
inputs_attrs.dimss[i][ii],
inputs_attrs.dimss[i][ii],
)
.into();
let x: MinOptMax = match (i, ii) {
(0, 0) => Self::_set_ixx(x, &config.i00, i, ii).unwrap_or(x_default),
(0, 1) => Self::_set_ixx(x, &config.i01, i, ii).unwrap_or(x_default),
(0, 2) => Self::_set_ixx(x, &config.i02, i, ii).unwrap_or(x_default),
(0, 3) => Self::_set_ixx(x, &config.i03, i, ii).unwrap_or(x_default),
(0, 4) => Self::_set_ixx(x, &config.i04, i, ii).unwrap_or(x_default),
(0, 5) => Self::_set_ixx(x, &config.i05, i, ii).unwrap_or(x_default),
(1, 0) => Self::_set_ixx(x, &config.i10, i, ii).unwrap_or(x_default),
(1, 1) => Self::_set_ixx(x, &config.i11, i, ii).unwrap_or(x_default),
(1, 2) => Self::_set_ixx(x, &config.i12, i, ii).unwrap_or(x_default),
(1, 3) => Self::_set_ixx(x, &config.i13, i, ii).unwrap_or(x_default),
(1, 4) => Self::_set_ixx(x, &config.i14, i, ii).unwrap_or(x_default),
(1, 5) => Self::_set_ixx(x, &config.i15, i, ii).unwrap_or(x_default),
(2, 0) => Self::_set_ixx(x, &config.i20, i, ii).unwrap_or(x_default),
(2, 1) => Self::_set_ixx(x, &config.i21, i, ii).unwrap_or(x_default),
(2, 2) => Self::_set_ixx(x, &config.i22, i, ii).unwrap_or(x_default),
(2, 3) => Self::_set_ixx(x, &config.i23, i, ii).unwrap_or(x_default),
(2, 4) => Self::_set_ixx(x, &config.i24, i, ii).unwrap_or(x_default),
(2, 5) => Self::_set_ixx(x, &config.i25, i, ii).unwrap_or(x_default),
(3, 0) => Self::_set_ixx(x, &config.i30, i, ii).unwrap_or(x_default),
(3, 1) => Self::_set_ixx(x, &config.i31, i, ii).unwrap_or(x_default),
(3, 2) => Self::_set_ixx(x, &config.i32_, i, ii).unwrap_or(x_default),
(3, 3) => Self::_set_ixx(x, &config.i33, i, ii).unwrap_or(x_default),
(3, 4) => Self::_set_ixx(x, &config.i34, i, ii).unwrap_or(x_default),
(3, 5) => Self::_set_ixx(x, &config.i35, i, ii).unwrap_or(x_default),
(4, 0) => Self::_set_ixx(x, &config.i40, i, ii).unwrap_or(x_default),
(4, 1) => Self::_set_ixx(x, &config.i41, i, ii).unwrap_or(x_default),
(4, 2) => Self::_set_ixx(x, &config.i42, i, ii).unwrap_or(x_default),
(4, 3) => Self::_set_ixx(x, &config.i43, i, ii).unwrap_or(x_default),
(4, 4) => Self::_set_ixx(x, &config.i44, i, ii).unwrap_or(x_default),
(4, 5) => Self::_set_ixx(x, &config.i45, i, ii).unwrap_or(x_default),
(5, 0) => Self::_set_ixx(x, &config.i50, i, ii).unwrap_or(x_default),
(5, 1) => Self::_set_ixx(x, &config.i51, i, ii).unwrap_or(x_default),
(5, 2) => Self::_set_ixx(x, &config.i52, i, ii).unwrap_or(x_default),
(5, 3) => Self::_set_ixx(x, &config.i53, i, ii).unwrap_or(x_default),
(5, 4) => Self::_set_ixx(x, &config.i54, i, ii).unwrap_or(x_default),
(5, 5) => Self::_set_ixx(x, &config.i55, i, ii).unwrap_or(x_default),
(6, 0) => Self::_set_ixx(x, &config.i60, i, ii).unwrap_or(x_default),
(6, 1) => Self::_set_ixx(x, &config.i61, i, ii).unwrap_or(x_default),
(6, 2) => Self::_set_ixx(x, &config.i62, i, ii).unwrap_or(x_default),
(6, 3) => Self::_set_ixx(x, &config.i63, i, ii).unwrap_or(x_default),
(6, 4) => Self::_set_ixx(x, &config.i64_, i, ii).unwrap_or(x_default),
(6, 5) => Self::_set_ixx(x, &config.i65, i, ii).unwrap_or(x_default),
(7, 0) => Self::_set_ixx(x, &config.i70, i, ii).unwrap_or(x_default),
(7, 1) => Self::_set_ixx(x, &config.i71, i, ii).unwrap_or(x_default),
(7, 2) => Self::_set_ixx(x, &config.i72, i, ii).unwrap_or(x_default),
(7, 3) => Self::_set_ixx(x, &config.i73, i, ii).unwrap_or(x_default),
(7, 4) => Self::_set_ixx(x, &config.i74, i, ii).unwrap_or(x_default),
(7, 5) => Self::_set_ixx(x, &config.i75, i, ii).unwrap_or(x_default),
(8, 0) => Self::_set_ixx(x, &config.i80, i, ii).unwrap_or(x_default),
(8, 1) => Self::_set_ixx(x, &config.i81, i, ii).unwrap_or(x_default),
(8, 2) => Self::_set_ixx(x, &config.i82, i, ii).unwrap_or(x_default),
(8, 3) => Self::_set_ixx(x, &config.i83, i, ii).unwrap_or(x_default),
(8, 4) => Self::_set_ixx(x, &config.i84, i, ii).unwrap_or(x_default),
(8, 5) => Self::_set_ixx(x, &config.i85, i, ii).unwrap_or(x_default),
(9, 0) => Self::_set_ixx(x, &config.i90, i, ii).unwrap_or(x_default),
(9, 1) => Self::_set_ixx(x, &config.i91, i, ii).unwrap_or(x_default),
(9, 2) => Self::_set_ixx(x, &config.i92, i, ii).unwrap_or(x_default),
(9, 3) => Self::_set_ixx(x, &config.i93, i, ii).unwrap_or(x_default),
(9, 4) => Self::_set_ixx(x, &config.i94, i, ii).unwrap_or(x_default),
(9, 5) => Self::_set_ixx(x, &config.i95, i, ii).unwrap_or(x_default),
(10, 0) => Self::_set_ixx(x, &config.i100, i, ii).unwrap_or(x_default),
(10, 1) => Self::_set_ixx(x, &config.i101, i, ii).unwrap_or(x_default),
(10, 2) => Self::_set_ixx(x, &config.i102, i, ii).unwrap_or(x_default),
(10, 3) => Self::_set_ixx(x, &config.i103, i, ii).unwrap_or(x_default),
(10, 4) => Self::_set_ixx(x, &config.i104, i, ii).unwrap_or(x_default),
(10, 5) => Self::_set_ixx(x, &config.i105, i, ii).unwrap_or(x_default),
(11, 0) => Self::_set_ixx(x, &config.i110, i, ii).unwrap_or(x_default),
(11, 1) => Self::_set_ixx(x, &config.i111, i, ii).unwrap_or(x_default),
(11, 2) => Self::_set_ixx(x, &config.i112, i, ii).unwrap_or(x_default),
(11, 3) => Self::_set_ixx(x, &config.i113, i, ii).unwrap_or(x_default),
(11, 4) => Self::_set_ixx(x, &config.i114, i, ii).unwrap_or(x_default),
(11, 5) => Self::_set_ixx(x, &config.i115, i, ii).unwrap_or(x_default),
(12, 0) => Self::_set_ixx(x, &config.i120, i, ii).unwrap_or(x_default),
(12, 1) => Self::_set_ixx(x, &config.i121, i, ii).unwrap_or(x_default),
(12, 2) => Self::_set_ixx(x, &config.i122, i, ii).unwrap_or(x_default),
(12, 3) => Self::_set_ixx(x, &config.i123, i, ii).unwrap_or(x_default),
(12, 4) => Self::_set_ixx(x, &config.i124, i, ii).unwrap_or(x_default),
(12, 5) => Self::_set_ixx(x, &config.i125, i, ii).unwrap_or(x_default),
(13, 0) => Self::_set_ixx(x, &config.i130, i, ii).unwrap_or(x_default),
(13, 1) => Self::_set_ixx(x, &config.i131, i, ii).unwrap_or(x_default),
(13, 2) => Self::_set_ixx(x, &config.i132, i, ii).unwrap_or(x_default),
(13, 3) => Self::_set_ixx(x, &config.i133, i, ii).unwrap_or(x_default),
(13, 4) => Self::_set_ixx(x, &config.i134, i, ii).unwrap_or(x_default),
(13, 5) => Self::_set_ixx(x, &config.i135, i, ii).unwrap_or(x_default),
(14, 0) => Self::_set_ixx(x, &config.i140, i, ii).unwrap_or(x_default),
(14, 1) => Self::_set_ixx(x, &config.i141, i, ii).unwrap_or(x_default),
(14, 2) => Self::_set_ixx(x, &config.i142, i, ii).unwrap_or(x_default),
(14, 3) => Self::_set_ixx(x, &config.i143, i, ii).unwrap_or(x_default),
(14, 4) => Self::_set_ixx(x, &config.i144, i, ii).unwrap_or(x_default),
(14, 5) => Self::_set_ixx(x, &config.i145, i, ii).unwrap_or(x_default),
(15, 0) => Self::_set_ixx(x, &config.i150, i, ii).unwrap_or(x_default),
(15, 1) => Self::_set_ixx(x, &config.i151, i, ii).unwrap_or(x_default),
(15, 2) => Self::_set_ixx(x, &config.i152, i, ii).unwrap_or(x_default),
(15, 3) => Self::_set_ixx(x, &config.i153, i, ii).unwrap_or(x_default),
(15, 4) => Self::_set_ixx(x, &config.i154, i, ii).unwrap_or(x_default),
(15, 5) => Self::_set_ixx(x, &config.i155, i, ii).unwrap_or(x_default),
(16, 0) => Self::_set_ixx(x, &config.i160, i, ii).unwrap_or(x_default),
(16, 1) => Self::_set_ixx(x, &config.i161, i, ii).unwrap_or(x_default),
(16, 2) => Self::_set_ixx(x, &config.i162, i, ii).unwrap_or(x_default),
(16, 3) => Self::_set_ixx(x, &config.i163, i, ii).unwrap_or(x_default),
(16, 4) => Self::_set_ixx(x, &config.i164, i, ii).unwrap_or(x_default),
(16, 5) => Self::_set_ixx(x, &config.i165, i, ii).unwrap_or(x_default),
(17, 0) => Self::_set_ixx(x, &config.i170, i, ii).unwrap_or(x_default),
(17, 1) => Self::_set_ixx(x, &config.i171, i, ii).unwrap_or(x_default),
(17, 2) => Self::_set_ixx(x, &config.i172, i, ii).unwrap_or(x_default),
(17, 3) => Self::_set_ixx(x, &config.i173, i, ii).unwrap_or(x_default),
(17, 4) => Self::_set_ixx(x, &config.i174, i, ii).unwrap_or(x_default),
(17, 5) => Self::_set_ixx(x, &config.i175, i, ii).unwrap_or(x_default),
(18, 0) => Self::_set_ixx(x, &config.i180, i, ii).unwrap_or(x_default),
(18, 1) => Self::_set_ixx(x, &config.i181, i, ii).unwrap_or(x_default),
(18, 2) => Self::_set_ixx(x, &config.i182, i, ii).unwrap_or(x_default),
(18, 3) => Self::_set_ixx(x, &config.i183, i, ii).unwrap_or(x_default),
(18, 4) => Self::_set_ixx(x, &config.i184, i, ii).unwrap_or(x_default),
(18, 5) => Self::_set_ixx(x, &config.i185, i, ii).unwrap_or(x_default),
(19, 0) => Self::_set_ixx(x, &config.i190, i, ii).unwrap_or(x_default),
(19, 1) => Self::_set_ixx(x, &config.i191, i, ii).unwrap_or(x_default),
(19, 2) => Self::_set_ixx(x, &config.i192, i, ii).unwrap_or(x_default),
(19, 3) => Self::_set_ixx(x, &config.i193, i, ii).unwrap_or(x_default),
(19, 4) => Self::_set_ixx(x, &config.i194, i, ii).unwrap_or(x_default),
(19, 5) => Self::_set_ixx(x, &config.i195, i, ii).unwrap_or(x_default),
(20, 0) => Self::_set_ixx(x, &config.i200, i, ii).unwrap_or(x_default),
(20, 1) => Self::_set_ixx(x, &config.i201, i, ii).unwrap_or(x_default),
(20, 2) => Self::_set_ixx(x, &config.i202, i, ii).unwrap_or(x_default),
(20, 3) => Self::_set_ixx(x, &config.i203, i, ii).unwrap_or(x_default),
(20, 4) => Self::_set_ixx(x, &config.i204, i, ii).unwrap_or(x_default),
(20, 5) => Self::_set_ixx(x, &config.i205, i, ii).unwrap_or(x_default),
(21, 0) => Self::_set_ixx(x, &config.i210, i, ii).unwrap_or(x_default),
(21, 1) => Self::_set_ixx(x, &config.i211, i, ii).unwrap_or(x_default),
(21, 2) => Self::_set_ixx(x, &config.i212, i, ii).unwrap_or(x_default),
(21, 3) => Self::_set_ixx(x, &config.i213, i, ii).unwrap_or(x_default),
(21, 4) => Self::_set_ixx(x, &config.i214, i, ii).unwrap_or(x_default),
(21, 5) => Self::_set_ixx(x, &config.i215, i, ii).unwrap_or(x_default),
(22, 0) => Self::_set_ixx(x, &config.i220, i, ii).unwrap_or(x_default),
(22, 1) => Self::_set_ixx(x, &config.i221, i, ii).unwrap_or(x_default),
(22, 2) => Self::_set_ixx(x, &config.i222, i, ii).unwrap_or(x_default),
(22, 3) => Self::_set_ixx(x, &config.i223, i, ii).unwrap_or(x_default),
(22, 4) => Self::_set_ixx(x, &config.i224, i, ii).unwrap_or(x_default),
(22, 5) => Self::_set_ixx(x, &config.i225, i, ii).unwrap_or(x_default),
(23, 0) => Self::_set_ixx(x, &config.i230, i, ii).unwrap_or(x_default),
(23, 1) => Self::_set_ixx(x, &config.i231, i, ii).unwrap_or(x_default),
(23, 2) => Self::_set_ixx(x, &config.i232, i, ii).unwrap_or(x_default),
(23, 3) => Self::_set_ixx(x, &config.i233, i, ii).unwrap_or(x_default),
(23, 4) => Self::_set_ixx(x, &config.i234, i, ii).unwrap_or(x_default),
(23, 5) => Self::_set_ixx(x, &config.i235, i, ii).unwrap_or(x_default),
(24, 0) => Self::_set_ixx(x, &config.i240, i, ii).unwrap_or(x_default),
(24, 1) => Self::_set_ixx(x, &config.i241, i, ii).unwrap_or(x_default),
(24, 2) => Self::_set_ixx(x, &config.i242, i, ii).unwrap_or(x_default),
(24, 3) => Self::_set_ixx(x, &config.i243, i, ii).unwrap_or(x_default),
(24, 4) => Self::_set_ixx(x, &config.i244, i, ii).unwrap_or(x_default),
(24, 5) => Self::_set_ixx(x, &config.i245, i, ii).unwrap_or(x_default),
(25, 0) => Self::_set_ixx(x, &config.i250, i, ii).unwrap_or(x_default),
(25, 1) => Self::_set_ixx(x, &config.i251, i, ii).unwrap_or(x_default),
(25, 2) => Self::_set_ixx(x, &config.i252, i, ii).unwrap_or(x_default),
(25, 3) => Self::_set_ixx(x, &config.i253, i, ii).unwrap_or(x_default),
(25, 4) => Self::_set_ixx(x, &config.i254, i, ii).unwrap_or(x_default),
(25, 5) => Self::_set_ixx(x, &config.i255, i, ii).unwrap_or(x_default),
(26, 0) => Self::_set_ixx(x, &config.i260, i, ii).unwrap_or(x_default),
(26, 1) => Self::_set_ixx(x, &config.i261, i, ii).unwrap_or(x_default),
(26, 2) => Self::_set_ixx(x, &config.i262, i, ii).unwrap_or(x_default),
(26, 3) => Self::_set_ixx(x, &config.i263, i, ii).unwrap_or(x_default),
(26, 4) => Self::_set_ixx(x, &config.i264, i, ii).unwrap_or(x_default),
(26, 5) => Self::_set_ixx(x, &config.i265, i, ii).unwrap_or(x_default),
(27, 0) => Self::_set_ixx(x, &config.i270, i, ii).unwrap_or(x_default),
(27, 1) => Self::_set_ixx(x, &config.i271, i, ii).unwrap_or(x_default),
(27, 2) => Self::_set_ixx(x, &config.i272, i, ii).unwrap_or(x_default),
(27, 3) => Self::_set_ixx(x, &config.i273, i, ii).unwrap_or(x_default),
(27, 4) => Self::_set_ixx(x, &config.i274, i, ii).unwrap_or(x_default),
(27, 5) => Self::_set_ixx(x, &config.i275, i, ii).unwrap_or(x_default),
_ => todo!(),
};
v_.push(x);
}
inputs_minoptmax.push(v_);
}
let inputs_minoptmax =
Self::build_inputs_minoptmax(&inputs_attrs, &config.iiixs, config.batch_size)?;
// build
ort::init().commit()?;
@ -343,9 +172,9 @@ impl OrtEngine {
let mut s_opt = format!("{}:", name);
let mut s_max = format!("{}:", name);
for d in inputs_minoptmax[i].iter() {
let min_ = &format!("{}x", d.min);
let opt_ = &format!("{}x", d.opt);
let max_ = &format!("{}x", d.max);
let min_ = &format!("{}x", d.min());
let opt_ = &format!("{}x", d.opt());
let max_ = &format!("{}x", d.max());
s_min += min_;
s_opt += opt_;
s_max += max_;
@ -423,7 +252,7 @@ impl OrtEngine {
for i in self.inputs_minoptmax.iter() {
let mut x: Vec<usize> = Vec::new();
for i_ in i.iter() {
x.push(i_.opt as usize);
x.push(i_.opt());
}
let x: Array<f32, IxDyn> = Array::ones(x).into_dyn();
xs.push(X::from(x));
@ -555,20 +384,58 @@ impl OrtEngine {
Ok(ys)
}
fn _set_ixx(x: isize, ixx: &Option<MinOptMax>, i: usize, ii: usize) -> Option<MinOptMax> {
match x {
-1 => {
match ixx {
None => panic!(
"{CROSS_MARK} Using dynamic shapes in inputs without specifying it: the {}-th input, the {}-th dimension.",
i + 1,
ii + 1
),
Some(ixx) => Some(ixx.to_owned()), // customized
fn build_inputs_minoptmax(
inputs_attrs: &OrtTensorAttr,
iiixs: &[Iiix],
batch_size: usize,
) -> Result<Vec<Vec<MinOptMax>>> {
let span = tracing::span!(tracing::Level::INFO, "OrtEngine-build_inputs_minoptmax");
let _guard = span.enter();
// init
let mut ys: Vec<Vec<MinOptMax>> = inputs_attrs
.dimss
.iter()
.map(|dims| dims.iter().map(|&x| MinOptMax::from(x)).collect())
.collect();
// update from customized
for iiix in iiixs.iter() {
if let Some(x) = inputs_attrs
.dimss
.get(iiix.i)
.and_then(|dims| dims.get(iiix.ii))
{
// dynamic
if *x == 0 {
ys[iiix.i][iiix.ii] = iiix.x.clone();
}
} else {
anyhow::bail!(
"Cannot retrieve the {}-th dimension of the {}-th input.",
iiix.ii,
iiix.i,
);
}
_ => Some((x, x, x).into()), // customized, but not dynamic
}
// deal with the dynamic axis
ys.iter_mut().enumerate().for_each(|(i, xs)| {
xs.iter_mut().enumerate().for_each(|(ii, x)| {
if x.is_dyn() {
let n = if ii == 0 { batch_size } else { 1 };
let y = MinOptMax::from(n);
tracing::warn!(
"Using dynamic shapes in inputs without specifying it: the {}-th input, the {}-th dimension. \
Using {:?} by default. You should make it clear when using TensorRT.",
i + 1, ii + 1, y
);
*x = y;
}
});
});
Ok(ys)
}
#[allow(dead_code)]
@ -627,57 +494,11 @@ impl OrtEngine {
}
}
#[allow(dead_code)]
fn i_from_session(session: &ort::Session) -> Result<OrtTensorAttr> {
let mut dimss = Vec::new();
let mut dtypes = Vec::new();
let mut names = Vec::new();
for x in session.inputs.iter() {
names.push(x.name.to_owned());
if let ort::ValueType::Tensor { ty, dimensions } = &x.input_type {
dimss.push(dimensions.iter().map(|x| *x as isize).collect::<Vec<_>>());
dtypes.push(*ty);
} else {
dimss.push(vec![-1_isize]);
dtypes.push(ort::TensorElementType::Float32);
}
}
Ok(OrtTensorAttr {
names,
dimss,
dtypes,
})
}
#[allow(dead_code)]
fn o_from_session(session: &ort::Session) -> Result<OrtTensorAttr> {
let mut dimss = Vec::new();
let mut dtypes = Vec::new();
let mut names = Vec::new();
for x in session.outputs.iter() {
names.push(x.name.to_owned());
if let ort::ValueType::Tensor { ty, dimensions } = &x.output_type {
dimss.push(dimensions.iter().map(|x| *x as isize).collect::<Vec<_>>());
dtypes.push(*ty);
} else {
dimss.push(vec![-1_isize]);
dtypes.push(ort::TensorElementType::Float32);
}
}
Ok(OrtTensorAttr {
names,
dimss,
dtypes,
})
}
fn io_from_onnx_value_info(
initializer_names: &HashSet<&str>,
value_info: &[onnx::ValueInfoProto],
) -> Result<OrtTensorAttr> {
let mut dimss: Vec<Vec<isize>> = Vec::new();
let mut dimss: Vec<Vec<usize>> = Vec::new();
let mut dtypes: Vec<ort::TensorElementType> = Vec::new();
let mut names: Vec<String> = Vec::new();
for v in value_info.iter() {
@ -708,16 +529,16 @@ impl OrtEngine {
Some(shapes) => shapes,
None => continue,
};
let mut shape_: Vec<isize> = Vec::new();
let mut shape_: Vec<usize> = Vec::new();
for shape in shapes.dim.iter() {
match &shape.value {
None => continue,
Some(value) => match value {
onnx::tensor_shape_proto::dimension::Value::DimValue(x) => {
shape_.push(*x as isize);
shape_.push(*x as _);
}
onnx::tensor_shape_proto::dimension::Value::DimParam(_) => {
shape_.push(-1isize);
shape_.push(0);
}
},
}
@ -736,11 +557,11 @@ impl OrtEngine {
Ok(onnx::ModelProto::decode(f.as_slice())?)
}
pub fn oshapes(&self) -> &Vec<Vec<isize>> {
pub fn oshapes(&self) -> &Vec<Vec<usize>> {
&self.outputs_attrs.dimss
}
pub fn odimss(&self) -> &Vec<Vec<isize>> {
pub fn odimss(&self) -> &Vec<Vec<usize>> {
&self.outputs_attrs.dimss
}
@ -752,11 +573,11 @@ impl OrtEngine {
&self.outputs_attrs.dtypes
}
pub fn ishapes(&self) -> &Vec<Vec<isize>> {
pub fn ishapes(&self) -> &Vec<Vec<usize>> {
&self.inputs_attrs.dimss
}
pub fn idimss(&self) -> &Vec<Vec<isize>> {
pub fn idimss(&self) -> &Vec<Vec<usize>> {
&self.inputs_attrs.dimss
}
@ -780,6 +601,14 @@ impl OrtEngine {
&self.inputs_minoptmax[0][0]
}
pub fn try_height(&self) -> Option<&MinOptMax> {
self.inputs_minoptmax.first().and_then(|x| x.get(2))
}
pub fn try_width(&self) -> Option<&MinOptMax> {
self.inputs_minoptmax.first().and_then(|x| x.get(3))
}
pub fn height(&self) -> &MinOptMax {
&self.inputs_minoptmax[0][2]
}
@ -789,7 +618,7 @@ impl OrtEngine {
}
pub fn is_batch_dyn(&self) -> bool {
self.ishapes()[0][0] == -1
self.ishapes()[0][0] == 0
}
pub fn try_fetch(&self, key: &str) -> Option<String> {

195
src/core/viewer.rs Normal file
View File

@ -0,0 +1,195 @@
use anyhow::Result;
use image::DynamicImage;
use minifb::{Window, WindowOptions};
use video_rs::{
encode::{Encoder, Settings},
time::Time,
};
use crate::{string_now, Dir, Key};
pub struct Viewer<'a> {
name: &'a str,
window: Option<Window>,
window_scale: f32,
window_resizable: bool,
fps_poll: usize,
fps: usize,
writer: Option<Encoder>,
position: Time,
}
impl Default for Viewer<'_> {
fn default() -> Self {
Self {
name: "usls-viewer",
window: None,
window_scale: 0.5,
window_resizable: true,
fps_poll: 100,
fps: 25,
writer: None,
position: Time::zero(),
}
}
}
impl Viewer<'_> {
pub fn new() -> Self {
Default::default()
}
pub fn imshow(&mut self, xs: &[DynamicImage]) -> Result<()> {
for x in xs.iter() {
let rgb = x.to_rgb8();
let (w, h) = (rgb.width() as usize, rgb.height() as usize);
let (w_scale, h_scale) = (
(w as f32 * self.window_scale) as usize,
(h as f32 * self.window_scale) as usize,
);
// should reload?
let should_reload = match &self.window {
None => true,
Some(window) => {
if self.window_resizable {
false
} else {
window.get_size() != (w_scale, h_scale)
}
}
};
// create window
if should_reload {
self.window = Window::new(
self.name,
w_scale,
h_scale,
WindowOptions {
resize: true,
topmost: true,
borderless: false,
scale: minifb::Scale::X1,
..WindowOptions::default()
},
)
.ok()
.map(|mut x| {
x.set_target_fps(self.fps_poll);
x
});
}
// build buffer
let mut buffer: Vec<u32> = Vec::with_capacity(w * h);
for pixel in rgb.pixels() {
let r = pixel[0];
let g = pixel[1];
let b = pixel[2];
let p = Self::rgb8_to_u32(r, g, b);
buffer.push(p);
}
// update buffer
self.window
.as_mut()
.unwrap()
.update_with_buffer(&buffer, w, h)?;
}
Ok(())
}
pub fn write(&mut self, frame: &image::DynamicImage) -> Result<()> {
// build writer at the 1st time
let frame = frame.to_rgb8();
let (w, h) = frame.dimensions();
if self.writer.is_none() {
let settings = Settings::preset_h264_yuv420p(w as _, h as _, false);
let saveout = Dir::saveout(&["runs"])?.join(format!("{}.mp4", string_now("-")));
tracing::info!("Video will be save to: {:?}", saveout);
self.writer = Some(Encoder::new(saveout, settings)?);
}
// write video
if let Some(writer) = self.writer.as_mut() {
let raw_data = frame.to_vec();
let frame = ndarray::Array3::from_shape_vec((h as usize, w as usize, 3), raw_data)?;
// encode and update
writer.encode(&frame, self.position)?;
self.position = self
.position
.aligned_with(Time::from_nth_of_a_second(self.fps))
.add();
}
Ok(())
}
pub fn write_batch(&mut self, frames: &[image::DynamicImage]) -> Result<()> {
for frame in frames.iter() {
self.write(frame)?
}
Ok(())
}
pub fn finish_write(&mut self) -> Result<()> {
match &mut self.writer {
Some(writer) => writer.finish()?,
None => {
tracing::info!("Found no video writer. No need to release.");
}
}
Ok(())
}
pub fn is_open(&self) -> bool {
if let Some(window) = &self.window {
window.is_open()
} else {
false
}
}
pub fn is_key_pressed(&self, key: Key) -> bool {
if let Some(window) = &self.window {
window.is_key_down(key)
} else {
false
}
}
pub fn is_esc_pressed(&self) -> bool {
self.is_key_pressed(Key::Escape)
}
pub fn resizable(mut self, x: bool) -> Self {
self.window_resizable = x;
self
}
pub fn with_scale(mut self, x: f32) -> Self {
self.window_scale = x;
self
}
pub fn with_fps(mut self, x: usize) -> Self {
self.fps = x;
self
}
pub fn with_delay(mut self, x: usize) -> Self {
self.fps_poll = 1000 / x;
self
}
pub fn wh(&self) -> Option<(usize, usize)> {
self.window.as_ref().map(|x| x.get_size())
}
fn rgb8_to_u32(r: u8, g: u8, b: u8) -> u32 {
let (r, g, b) = (r as u32, g as u32, b as u32);
(r << 16) | (g << 8) | b
}
}

View File

@ -56,8 +56,8 @@ impl Blip {
let xs_ = X::apply(&[
Ops::Resize(
xs,
self.height.opt as u32,
self.width.opt as u32,
self.height.opt() as u32,
self.width.opt() as u32,
"Bilinear",
),
Ops::Normalize(0., 255.),
@ -146,10 +146,10 @@ impl Blip {
}
pub fn batch_visual(&self) -> usize {
self.batch_visual.opt as usize
self.batch_visual.opt()
}
pub fn batch_textual(&self) -> usize {
self.batch_textual.opt as usize
self.batch_textual.opt()
}
}

View File

@ -66,8 +66,8 @@ impl Clip {
let xs_ = X::apply(&[
Ops::Resize(
xs,
self.height.opt as u32,
self.width.opt as u32,
self.height.opt() as u32,
self.width.opt() as u32,
"Bilinear",
),
Ops::Normalize(0., 255.),
@ -98,10 +98,10 @@ impl Clip {
}
pub fn batch_visual(&self) -> usize {
self.batch_visual.opt as usize
self.batch_visual.opt()
}
pub fn batch_textual(&self) -> usize {
self.batch_textual.opt as usize
self.batch_textual.opt()
}
}

View File

@ -162,14 +162,14 @@ impl DB {
}
pub fn batch(&self) -> isize {
self.batch.opt
self.batch.opt() as _
}
pub fn width(&self) -> isize {
self.width.opt
self.width.opt() as _
}
pub fn height(&self) -> isize {
self.height.opt
self.height.opt() as _
}
}

View File

@ -33,8 +33,8 @@ impl DepthAnything {
let xs_ = X::apply(&[
Ops::Resize(
xs,
self.height.opt as u32,
self.width.opt as u32,
self.height.opt() as u32,
self.width.opt() as u32,
"Lanczos3",
),
Ops::Normalize(0., 255.),
@ -77,14 +77,14 @@ impl DepthAnything {
}
pub fn batch(&self) -> isize {
self.batch.opt
self.batch.opt() as _
}
pub fn width(&self) -> isize {
self.width.opt
self.width.opt() as _
}
pub fn height(&self) -> isize {
self.height.opt
self.height.opt() as _
}
}

View File

@ -51,8 +51,8 @@ impl Dinov2 {
let xs_ = X::apply(&[
Ops::Resize(
xs,
self.height.opt as u32,
self.width.opt as u32,
self.height.opt() as u32,
self.width.opt() as u32,
"Lanczos3",
),
Ops::Normalize(0., 255.),

View File

@ -80,8 +80,8 @@ impl Florence2 {
let xs_ = X::apply(&[
Ops::Resize(
xs,
self.height.opt as u32,
self.width.opt as u32,
self.height.opt() as u32,
self.width.opt() as u32,
"Bilinear",
),
Ops::Normalize(0., 255.),
@ -103,7 +103,7 @@ impl Florence2 {
let image_embeddings = self.encode_images(xs)?;
// note: the length of xs is not always equal to batch size
self.batch.update(xs.len() as isize);
self.batch.update_opt(xs.len() as _);
// build pb
let pb = build_progress_bar(
@ -454,6 +454,6 @@ impl Florence2 {
}
pub fn batch(&self) -> usize {
self.batch.opt as usize
self.batch.opt()
}
}

View File

@ -232,14 +232,14 @@ impl GroundingDINO {
}
pub fn batch(&self) -> isize {
self.batch.opt
self.batch.opt() as _
}
pub fn width(&self) -> isize {
self.width.opt
self.width.opt() as _
}
pub fn height(&self) -> isize {
self.height.opt
self.height.opt() as _
}
}

View File

@ -34,8 +34,8 @@ impl MODNet {
let xs_ = X::apply(&[
Ops::Resize(
xs,
self.height.opt as u32,
self.width.opt as u32,
self.height.opt() as u32,
self.width.opt() as u32,
"Lanczos3",
),
Ops::Normalize(0., 255.),
@ -71,14 +71,14 @@ impl MODNet {
}
pub fn batch(&self) -> isize {
self.batch.opt
self.batch.opt() as _
}
pub fn width(&self) -> isize {
self.width.opt
self.width.opt() as _
}
pub fn height(&self) -> isize {
self.height.opt
self.height.opt() as _
}
}

View File

@ -128,14 +128,14 @@ impl RTMO {
}
pub fn batch(&self) -> isize {
self.batch.opt
self.batch.opt() as _
}
pub fn width(&self) -> isize {
self.width.opt
self.width.opt() as _
}
pub fn height(&self) -> isize {
self.height.opt
self.height.opt() as _
}
}

View File

@ -322,14 +322,14 @@ impl SAM {
}
pub fn batch(&self) -> isize {
self.batch.opt
self.batch.opt() as _
}
pub fn width(&self) -> isize {
self.width.opt
self.width.opt() as _
}
pub fn height(&self) -> isize {
self.height.opt
self.height.opt() as _
}
}

View File

@ -146,14 +146,14 @@ impl Sapiens {
}
pub fn batch(&self) -> isize {
self.batch.opt
self.batch.opt() as _
}
pub fn width(&self) -> isize {
self.width.opt
self.width.opt() as _
}
pub fn height(&self) -> isize {
self.height.opt
self.height.opt() as _
}
}

View File

@ -46,8 +46,8 @@ impl SVTR {
let xs_ = X::apply(&[
Ops::Letterbox(
xs,
self.height.opt as u32,
self.width.opt as u32,
self.height.opt() as u32,
self.width.opt() as u32,
"Bilinear",
0,
"auto",

View File

@ -506,15 +506,15 @@ impl Vision for YOLO {
impl YOLO {
pub fn batch(&self) -> isize {
self.batch.opt
self.batch.opt() as _
}
pub fn width(&self) -> isize {
self.width.opt
self.width.opt() as _
}
pub fn height(&self) -> isize {
self.height.opt
self.height.opt() as _
}
pub fn version(&self) -> Option<&YOLOVersion> {

View File

@ -172,15 +172,15 @@ impl YOLOPv2 {
}
pub fn batch(&self) -> isize {
self.batch.opt
self.batch.opt() as _
}
pub fn width(&self) -> isize {
self.width.opt
self.width.opt() as _
}
pub fn height(&self) -> isize {
self.height.opt
self.height.opt() as _
}
fn get_contours_from_mask(

View File

@ -15,6 +15,7 @@ pub struct Bbox {
name: Option<String>,
id_born: isize,
}
impl Nms for Bbox {
/// Returns the confidence score of the bounding box.
fn confidence(&self) -> f32 {