Skip to content

Commit

Permalink
Accumulation on contours for the ToS
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteesteban committed Jul 24, 2024
1 parent 75f9214 commit 0813006
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 17 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ Rust. My initial objective when starting to build this library was to learn the
Rust programming language by working on a project that would be useful for my
personal experiments. Its design is **strongly** inspired by the
[Pylene](https://gitlab.lre.epita.fr/olena/pylene) image processing library and
follows the same aims. **It has to be noted that this library is entirely developed during my free time, and its progress may be affected by my various other activities.**
follows the same aims. **It has to be noted that this library is entirely
developed during my free time, and its progress may be affected by my various
other activities.**

Currently, Olympus is not available on the [Rust community's crate
registry](https://crates.io) but it is intended to when it will be mature
Expand Down
102 changes: 92 additions & 10 deletions apps/tos/src/contours.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,89 @@
use std::fmt::Display;

use olympus::{
accu::{Accumulator, UntakeAccumulator},
accu::Accumulator,
morpho::Tree,
traits::Image,
Image2d, Point2d,
traits::{Domain, Image, Window},
Image2d, Point2d, C4,
};

use crate::{is_1h_face, is_1v_face};
use crate::is_2_face;

pub fn accumulate_on_contours_points<A, V>(t: &Tree<Image2d<i32>, u8>, _acc: A) -> Vec<V>
where
A: Accumulator<Input = Point2d, Output = V> + UntakeAccumulator + Clone,
V: Display,
A: Accumulator<Input = Point2d, Output = V> + Clone,
{
let mut contours_acc = vec![A::new(); t.num_nodes()];
let depth = t.depth();
let nbh = C4::new();

let domain = t.nodemap().domain();
for p in domain {
if is_2_face(&p) {
let np = *t.nodemap().at_point(&p);
for q in nbh.apply(&p) {
if domain.has(&q) {
let nq = *t.nodemap().at_point(&q);
let d = depth.get(nq as usize).unwrap();
let mut x = np as usize;
while depth.get(x).unwrap() > d {
contours_acc.get_mut(x).unwrap().take(q);
x = *t.parent(x as i32) as usize;
}
}
}
}
}

contours_acc.into_iter().map(|acc| acc.result()).collect()
}

pub fn accumulate_on_contours_values<A, V, O>(
t: &Tree<Image2d<i32>, u8>,
value_map: &Image2d<V>,
_acc: A,
) -> Vec<O>
where
A: Accumulator<Input = V, Output = O> + Clone,
V: Copy,
{
assert!(value_map.domain() == t.nodemap().domain());

let mut contours_acc = vec![A::new(); t.num_nodes()];
let depth = t.depth();
let nbh = C4::new();

let domain = t.nodemap().domain();
for p in domain {
if is_2_face(&p) {
let np = *t.nodemap().at_point(&p);
for q in nbh.apply(&p) {
if domain.has(&q) {
let nq = *t.nodemap().at_point(&q);
let d = depth.get(nq as usize).unwrap();
let mut x = np as usize;
while depth.get(x).unwrap() > d {
contours_acc
.get_mut(x)
.unwrap()
.take(*value_map.at_point(&q));
x = *t.parent(x as i32) as usize;
}
}
}
}
}

contours_acc.into_iter().map(|acc| acc.result()).collect()
}

#[cfg(test)]
mod tests {
use olympus::{accu::Accumulator, Image2d, Point2d};
use olympus::{
accu::Accumulator,
traits::{Image, ImageFromDomain},
Image2d, Point2d,
};

use crate::accumulate_on_contours_points;
use crate::{accumulate_on_contours_points, accumulate_on_contours_values};

#[test]
fn test_contours_length() {
Expand All @@ -41,4 +101,26 @@ mod tests {
assert_eq!(REF[i], *attr.get(i).unwrap());
}
}

#[test]
fn test_contours_length_using_values() {
let img = Image2d::<u8>::new_from_vec(
5,
5,
Vec::from([
2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 1, 4, 4, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 2,
]),
);
const REF: [usize; 4] = [0, 8, 10, 6];
let t = olympus::morpho::tos(&img, &Point2d::new(0, 0));
let value_map = Image2d::<u16>::new_from_domain_with_value(&t.nodemap().domain(), 1);
let attr = accumulate_on_contours_values(
&t,
&value_map,
olympus::accu::SumAccumulator::<u16, usize>::new(),
);
for i in 0..4 {
assert_eq!(REF[i], *attr.get(i).unwrap());
}
}
}
4 changes: 2 additions & 2 deletions apps/tos/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ mod border;
mod kprint;
mod lca;
//mod context_energy;
//mod contours;
mod contours;
mod cubical_complex_helper;
mod interpolation;
mod ksave;

pub use border::*;
pub use kprint::kprint;
//pub use context_energy;
//pub use contours::*;
pub use contours::*;
pub use cubical_complex_helper::*;
pub use interpolation::*;
pub use ksave::*;
Expand Down
1 change: 1 addition & 0 deletions src/accu/sum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::{

use super::{Accumulator, UntakeAccumulator};

#[derive(Clone)]
pub struct SumAccumulator<V, O> {
v: O,
_v: PhantomData<V>,
Expand Down
12 changes: 10 additions & 2 deletions src/core/neighborhoods/c4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,20 @@ impl C4 {
C4 {
offsets: [
Point2d::new(-1, 0),
Point2d::new(0, 1),
Point2d::new(1, 0),
Point2d::new(0, -1),
Point2d::new(1, 0),
Point2d::new(0, 1),
],
}
}

pub fn front(&self, p: &Point2d) -> Vec<Point2d> {
let mut res = Vec::<Point2d>::with_capacity(4);
for i in 0..2 {
res.push(*p + self.offsets[i]);
}
res
}
}

impl Window for C4 {
Expand Down
4 changes: 2 additions & 2 deletions src/tests/core/neighborhoods/c4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use crate::{traits::Window, Point2d, C4};
fn test_c4() {
let ref_values = Vec::<Point2d>::from([
Point2d::new(9, 12),
Point2d::new(10, 13),
Point2d::new(11, 12),
Point2d::new(10, 11),
Point2d::new(11, 12),
Point2d::new(10, 13),
]);
let p = Point2d::new(10, 12);
let c4 = C4::new();
Expand Down

0 comments on commit 0813006

Please sign in to comment.