diff options
Diffstat (limited to 'src/embedders.rs')
-rw-r--r-- | src/embedders.rs | 59 |
1 files changed, 48 insertions, 11 deletions
diff --git a/src/embedders.rs b/src/embedders.rs index 7310a58..94fc122 100644 --- a/src/embedders.rs +++ b/src/embedders.rs @@ -1,3 +1,4 @@ +use rayon::prelude::*; use std::path::PathBuf; pub trait MetricElem { @@ -22,7 +23,7 @@ impl EmbedderT for BrightnessEmbedder { fn embed(&mut self, paths: &[PathBuf]) -> Result<Vec<f64>, String> { paths - .iter() + .par_iter() .map(|p| { let im = image::open(p).map_err(|e| e.to_string())?; let num_bytes = 3 * (im.height() * im.width()); @@ -36,11 +37,14 @@ impl EmbedderT for BrightnessEmbedder { .map(|e| *e as u64) .sum::<u64>() as f64 / num_bytes as f64) }) + .collect::<Vec<_>>() + .into_iter() .try_collect() } } -struct Hue (f64); +#[repr(transparent)] +pub struct Hue (f64); impl MetricElem for Hue { fn dist(&self, b: &Hue) -> f64 { let d = self.0.dist(&b.0); @@ -50,11 +54,11 @@ impl MetricElem for Hue { pub struct HueEmbedder; impl EmbedderT for HueEmbedder { - type Embedding = f64; // TODO anderes Ding was Winkel vergleicht + type Embedding = Hue; - fn embed(&mut self, paths: &[PathBuf]) -> Result<Vec<f64>, String> { + fn embed(&mut self, paths: &[PathBuf]) -> Result<Vec<Hue>, String> { paths - .iter() + .par_iter() .map(|p| { let im = image::open(p).map_err(|e| e.to_string())?; let num_pixels = im.height() * im.width(); @@ -67,7 +71,7 @@ impl EmbedderT for HueEmbedder { }) .map(|e| e as f64 / 255. / num_pixels as f64); - let mut hue = + let hue = if sr >= sg && sr >= sb { (sg - sb) / (sr - sg.min(sb)) } @@ -78,16 +82,49 @@ impl EmbedderT for HueEmbedder { 4. + (sr - sg) / (sb - sr.min(sg)) }; - if hue < 0. { - hue += 6.; - } - if hue.is_nan() { Err("Encountered NaN hue, possibly because of a colorless or empty image")?; } - Ok(hue) + Ok(Hue(hue)) + }) + .collect::<Vec<_>>() + .into_iter() + .try_collect() + } +} + +impl MetricElem for (f64, f64, f64) { + fn dist(&self, o: &(f64, f64, f64)) -> f64 { + let (dr, dg, db) = + ((self.0 - o.0), (self.1 - o.1), (self.2 - o.2)); + (dr*dr + dg*dg + db*db).sqrt() + } +} + +pub struct ColorEmbedder; +impl EmbedderT for ColorEmbedder { + type Embedding = (f64, f64, f64); + + fn embed(&mut self, paths: &[PathBuf]) -> Result<Vec<(f64, f64, f64)>, String> { + paths + .par_iter() + .map(|p| { + let im = image::open(p).map_err(|e| e.to_string())?; + let num_pixels = im.height() * im.width(); + let [sr, sg, sb] = im + .to_rgb8() + .pixels() + .fold([0, 0, 0], |[or, og, ob], n| { + let [nr, ng, nb] = n.0; + [or + nr as u64, og + ng as u64, ob + nb as u64] + }) + .map(|e| e as f64 / num_pixels as f64); + + Ok((sr, sg, sb)) }) + .collect::<Vec<_>>() + .into_iter() .try_collect() } } |