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