Modify contour finding to return path vertices instead of trace
This commit is contained in:
1 parent
d550a7e71e
commit
a7372d05c2
2 files changed
+63
-44
No files matched your search
@@ -21,11 +21,14 @@ fn main() -> std::process::ExitCode {
|
||||
let thresholded = filter::threshold_auto(greyscale);
|
||||
let contours = contour::find(thresholded);
|
||||
for contour in contours {
|
||||
for (x, y) in contour.trace {
|
||||
*img.at_mut(x, y) = match contour.kind {
|
||||
contour::Kind::Inner => INNER,
|
||||
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 {
|
||||
contour::Kind::Outer => OUTER,
|
||||
};
|
||||
contour::Kind::Inner => INNER,
|
||||
});
|
||||
}
|
||||
}
|
||||
img
|
||||
|
||||
+56
-40
@@ -8,7 +8,7 @@ pub enum Kind {
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Contour {
|
||||
pub trace: Vec<(usize, usize)>,
|
||||
pub vertices: Vec<(usize, usize)>,
|
||||
pub children: Vec<usize>,
|
||||
pub parent: Option<usize>,
|
||||
pub kind: Kind,
|
||||
@@ -58,22 +58,10 @@ pub fn find(img: image::Image<image::Luminance>) -> Vec<Contour> {
|
||||
let mut parent = None;
|
||||
for x in 0..map.extent.x {
|
||||
let q = (x, y);
|
||||
if foreground(&map, q) {
|
||||
let prev_bg = background(&map, q.prev_x());
|
||||
let next_bg = background(&map, q.next_x());
|
||||
if prev_bg || next_bg {
|
||||
let (dir, kind) = if prev_bg {
|
||||
(Dir::W, Kind::Outer)
|
||||
} else {
|
||||
(Dir::E, Kind::Inner)
|
||||
};
|
||||
let label = contours.len();
|
||||
let trace = trace(&mut map, q, dir, label);
|
||||
contours.push(Contour::new(parent, kind, trace));
|
||||
if let Some(index) = parent {
|
||||
contours[index].add_child(label);
|
||||
}
|
||||
}
|
||||
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()) {
|
||||
add(q, Kind::Inner, parent, &mut contours, &mut map);
|
||||
} else if let Some(label) = traced(&map, q) {
|
||||
if background(&map, q.prev_x()) {
|
||||
parent = Some(label);
|
||||
@@ -86,38 +74,57 @@ pub fn find(img: image::Image<image::Luminance>) -> Vec<Contour> {
|
||||
contours
|
||||
}
|
||||
|
||||
fn add(
|
||||
start: (usize, usize),
|
||||
kind: Kind,
|
||||
parent: Option<usize>,
|
||||
contours: &mut Vec<Contour>,
|
||||
map: &mut image::Image<Pixel>,
|
||||
) {
|
||||
let label = contours.len();
|
||||
let vertices = trace(map, start, kind.start_dir(), label);
|
||||
contours.push(Contour::new(parent, kind, vertices));
|
||||
if let Some(index) = parent {
|
||||
contours[index].add_child(label);
|
||||
}
|
||||
}
|
||||
|
||||
fn trace(
|
||||
img: &mut image::Image<Pixel>,
|
||||
start_q: (usize, usize),
|
||||
mut dir: Dir,
|
||||
start_dir: Dir,
|
||||
label: usize,
|
||||
) -> Vec<(usize, usize)> {
|
||||
let mut q = start_q;
|
||||
dir = dir.next();
|
||||
|
||||
let mut path = Vec::new();
|
||||
'outer: loop {
|
||||
if !q.in_bounds(img.extent) {
|
||||
break;
|
||||
}
|
||||
q.set(img, Pixel::Traced(label));
|
||||
path.push(q);
|
||||
|
||||
let start = dir;
|
||||
let mut dir = start_dir;
|
||||
while background(img, dir.from(q)) {
|
||||
dir = dir.next();
|
||||
if dir == start {
|
||||
break 'outer;
|
||||
dir.next();
|
||||
}
|
||||
}
|
||||
q = dir.from(q);
|
||||
dir = dir.flip().next();
|
||||
|
||||
if q == start_q {
|
||||
break;
|
||||
let mut vertices = Vec::new();
|
||||
loop {
|
||||
q.set(img, Pixel::Traced(label));
|
||||
|
||||
let prev_dir = dir;
|
||||
dir = dir.flip().next();
|
||||
q = loop {
|
||||
let qp = dir.from(q);
|
||||
if !background(img, qp) {
|
||||
if dir != prev_dir {
|
||||
vertices.push(q)
|
||||
}
|
||||
break qp;
|
||||
}
|
||||
dir = dir.next();
|
||||
};
|
||||
|
||||
if q == start_q || !q.in_bounds(img.extent) {
|
||||
if dir != start_dir {
|
||||
vertices.push(q);
|
||||
}
|
||||
break vertices;
|
||||
}
|
||||
}
|
||||
path
|
||||
}
|
||||
|
||||
fn foreground(img: &image::Image<Pixel>, q: (usize, usize)) -> bool {
|
||||
@@ -141,6 +148,15 @@ fn traced(img: &image::Image<Pixel>, q: (usize, usize)) -> Option<usize> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Kind {
|
||||
fn start_dir(self) -> Dir {
|
||||
match self {
|
||||
Kind::Outer => Dir::E,
|
||||
Kind::Inner => Dir::W,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dir {
|
||||
fn next(self) -> Self {
|
||||
match self {
|
||||
@@ -222,10 +238,10 @@ impl Contour {
|
||||
fn new(
|
||||
parent: Option<usize>,
|
||||
kind: Kind,
|
||||
trace: Vec<(usize, usize)>,
|
||||
vertices: Vec<(usize, usize)>,
|
||||
) -> Self {
|
||||
Self {
|
||||
trace,
|
||||
vertices,
|
||||
children: Vec::new(),
|
||||
parent,
|
||||
kind,
|
||||
|
||||
Reference in new issue
Block a user