mod args;
use anyhow::Result;
use args::Args;
#[allow(warnings)]
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use serde_derive::*;
use flir_rs::cli::{process_paths_par, GenericImage};
use flir_rs::{image::ThermalImage, stats::Stats};
fn main() -> Result<()> {
let args = Args::from_cmd_line()?;
use rayon::prelude::*;
let Args {
paths,
distance,
is_json,
} = args;
let (stats, cumulative) = process_paths_par(paths, is_json)
.into_par_iter()
.map(|try_img| -> Result<_> {
let img = try_img?;
Ok(ImageStats::from_thermal_image(
&img.image,
distance,
img.filename,
))
})
.try_fold(
|| (vec![], Stats::default()),
|mut acc, try_img| -> Result<_> {
let item = try_img?;
acc.0.push(item);
acc.1 += &acc.0.last().unwrap().stats;
Ok(acc)
},
)
.try_reduce(
|| (vec![], Stats::default()),
|mut acc1, acc2| -> Result<_> {
acc1.0.extend(acc2.0);
acc1.1 += &acc2.1;
Ok(acc1)
},
)?;
use serde_derive::*;
#[derive(Debug, Serialize)]
struct OutputJson {
pub image_stats: Vec<ImageStats>,
pub cumulative: Stats,
}
serde_json::to_writer(
std::io::stdout().lock(),
&OutputJson {
image_stats: stats,
cumulative,
},
)?;
Ok(())
}
#[derive(Serialize, Debug)]
pub struct ImageStats {
pub path: String,
pub width: usize,
pub height: usize,
pub stats: Stats,
}
impl ImageStats {
pub fn from_thermal_image(flir_rs: &GenericImage, distance: f64, path: String) -> Self {
Self::from_flir_image(flir_rs, distance, path)
}
pub fn from_flir_image(flir_rs: &ThermalImage, distance: f64, path: String) -> Self {
let temp_t = flir_rs.settings.temperature_transform(distance);
let (ht, wid) = flir_rs.image.dim();
let mut stats = Stats::default();
for row in 0..ht {
for col in 0..wid {
let raw = flir_rs.image[(row, col)] as f64;
let temp = temp_t(raw);
stats += temp;
}
}
ImageStats {
width: wid,
height: ht,
path,
stats,
}
}
}