Fully handle inner/outer determination and nesting in contour tracing
This commit is contained in:
1 parent
a7372d05c2
commit
7f29c5abbb
2 files changed
+59
-18
No files matched your search
+15
-8
@@ -15,22 +15,29 @@ const INNER: image::SRGBA = image::SRGBA {
|
||||
a: 1.0,
|
||||
};
|
||||
|
||||
fn main() -> std::process::ExitCode {
|
||||
common::process_image(|mut img| {
|
||||
let greyscale = img.map(|p| image::Luminance::from(p));
|
||||
let thresholded = filter::threshold_auto(greyscale);
|
||||
let contours = contour::find(thresholded);
|
||||
for contour in contours {
|
||||
fn draw(contour: &contour::Contour, img: &mut image::Image<image::SRGBA>) {
|
||||
let n = contour.vertices.len();
|
||||
for i in 0..n {
|
||||
let (x0, y0) = contour.vertices[i];
|
||||
let (x1, y1) = contour.vertices[(i + 1) % n];
|
||||
draw::line(x0, y0, x1, y1, &mut img, match contour.kind {
|
||||
let colour = match contour.kind {
|
||||
contour::Kind::Outer => OUTER,
|
||||
contour::Kind::Inner => INNER,
|
||||
});
|
||||
};
|
||||
draw::line(x0, y0, x1, y1, img, colour);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> std::process::ExitCode {
|
||||
common::process_image(|mut img| {
|
||||
let greyscale = img.map(|p| image::Luminance::from(p));
|
||||
let thresholded = filter::threshold_auto(greyscale);
|
||||
|
||||
let contours = contour::find(thresholded);
|
||||
for contour in contours {
|
||||
draw(&contour, &mut img);
|
||||
}
|
||||
|
||||
img
|
||||
})
|
||||
}
|
||||
+44
-10
@@ -18,7 +18,8 @@ pub struct Contour {
|
||||
enum Pixel {
|
||||
Foreground,
|
||||
Background,
|
||||
Traced(usize),
|
||||
TracedUp(usize),
|
||||
TracedDown(usize),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
@@ -60,17 +61,17 @@ pub fn find(img: image::Image<image::Luminance>) -> Vec<Contour> {
|
||||
let q = (x, y);
|
||||
if foreground(&map, q) && background(&map, q.prev_x()) {
|
||||
add(q, Kind::Outer, parent, &mut contours, &mut map);
|
||||
} else if foreground(&map, q) && background(&map, q.next_x()) {
|
||||
} else if (foreground(&map, q) || traced_up(&map, q).is_some())
|
||||
&& background(&map, q.next_x())
|
||||
{
|
||||
add(q, Kind::Inner, parent, &mut contours, &mut map);
|
||||
} else if let Some(label) = traced(&map, q) {
|
||||
if background(&map, q.prev_x()) {
|
||||
} else if let Some(label) = traced_up(&map, q) {
|
||||
parent = Some(label);
|
||||
} else if background(&map, q.next_x()) {
|
||||
} else if let Some(label) = traced_down(&map, q) {
|
||||
parent = contours[label].parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
contours
|
||||
}
|
||||
|
||||
@@ -103,7 +104,9 @@ fn trace(
|
||||
|
||||
let mut vertices = Vec::new();
|
||||
loop {
|
||||
q.set(img, Pixel::Traced(label));
|
||||
if foreground(img, q) {
|
||||
q.set(img, Pixel::TracedUp(label));
|
||||
}
|
||||
|
||||
let prev_dir = dir;
|
||||
dir = dir.flip().next();
|
||||
@@ -115,6 +118,9 @@ fn trace(
|
||||
}
|
||||
break qp;
|
||||
}
|
||||
if dir == Dir::E {
|
||||
q.set(img, Pixel::TracedDown(label));
|
||||
}
|
||||
dir = dir.next();
|
||||
};
|
||||
|
||||
@@ -122,9 +128,27 @@ fn trace(
|
||||
if dir != start_dir {
|
||||
vertices.push(q);
|
||||
}
|
||||
break vertices;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// println!();
|
||||
// for y in 0..img.extent.y {
|
||||
// for x in 0..img.extent.x {
|
||||
// if let Some(label) = traced_up(img, (x, y)) {
|
||||
// print!("{:1}", label);
|
||||
// } else if let Some(label) = traced_down(img, (x, y)) {
|
||||
// print!("-")
|
||||
// } else if foreground(img, (x, y)) {
|
||||
// print!(".");
|
||||
// } else if background(img, (x, y)) {
|
||||
// print!(" ");
|
||||
// }
|
||||
// }
|
||||
// println!();
|
||||
// }
|
||||
|
||||
vertices
|
||||
}
|
||||
|
||||
fn foreground(img: &image::Image<Pixel>, q: (usize, usize)) -> bool {
|
||||
@@ -141,9 +165,19 @@ fn background(img: &image::Image<Pixel>, q: (usize, usize)) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn traced(img: &image::Image<Pixel>, q: (usize, usize)) -> Option<usize> {
|
||||
fn traced_up(img: &image::Image<Pixel>, q: (usize, usize)) -> Option<usize> {
|
||||
match q.get(img) {
|
||||
Some(Pixel::Traced(label)) => Some(label),
|
||||
Some(Pixel::TracedUp(label)) => Some(label),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn traced_down(
|
||||
img: &image::Image<Pixel>,
|
||||
q: (usize, usize),
|
||||
) -> Option<usize> {
|
||||
match q.get(img) {
|
||||
Some(Pixel::TracedDown(label)) => Some(label),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user