use std::{ path::PathBuf, sync::{Arc, Mutex}, }; use clap::Parser; use indicatif::{ParallelProgressIterator, ProgressStyle}; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use kornia_rs::io::functional as F; #[derive(Parser, Debug)] struct Args { #[arg(short, long)] images_dir: PathBuf, #[arg(short, long, default_value = "8")] num_threads: usize, } fn main() -> Result<(), Box> { let args = Args::parse(); rayon::ThreadPoolBuilder::new() .num_threads(args.num_threads) .build_global() .expect("Failed to build thread pool"); // Walk through the images directory and collect the paths of the images let images_paths: Vec = walkdir::WalkDir::new(&args.images_dir) .into_iter() .filter_map(|entry| entry.ok()) .filter(|entry| { entry.file_type().is_file() && entry .path() .extension() .map(|ext| ext == "jpeg") .unwrap_or(false) }) .map(|entry| entry.path().to_path_buf()) .collect(); if images_paths.is_empty() { println!("No images found in the directory"); return Ok(()); } println!( "🚀 Found {} images. Starting to compute the std and mean !!!", images_paths.len() ); // Create a progress bar let pb = indicatif::ProgressBar::new(images_paths.len() as u64); pb.set_style(ProgressStyle::default_bar().template( "{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos:>7}/{len:7} ({eta}) {msg} {per_sec}", )?.progress_chars("##>-")); // compute the std and mean of the images let total_std = Arc::new(Mutex::new(vec![0.0; 3])); let total_mean = Arc::new(Mutex::new(vec![0.0; 3])); let num_samples = images_paths.len() as f64; images_paths .into_par_iter() .progress_with(pb) .for_each(|image_path| { // read the image let image = F::read_image_any(&image_path).expect("Failed to read image"); // compute the std and mean let (std, mean) = kornia_rs::core::std_mean(&image); // update the total std and mean total_std .lock() .expect("Failed to lock total std") .iter_mut() .zip(std.iter()) .for_each(|(t, s)| *t += s); total_mean .lock() .expect("Failed to lock total mean") .iter_mut() .zip(mean.iter()) .for_each(|(t, m)| *t += m); }); // average the measurements let total_std = total_std .lock() .expect("Failed to lock total std") .iter() .map(|&s| s / num_samples) .collect::>(); let total_mean = total_mean .lock() .expect("Failed to lock total mean") .iter() .map(|&m| m / num_samples) .collect::>(); println!("🔥Total std: {:?}", total_std); println!("🔥Total mean: {:?}", total_mean); Ok(()) }