Skip to content

Commit

Permalink
Draw segments in line detection overlay (HULKs#1319)
Browse files Browse the repository at this point in the history
  • Loading branch information
h3ndrk authored Jul 18, 2024
1 parent a7e38a4 commit 1cac67f
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 57 deletions.
34 changes: 33 additions & 1 deletion crates/types/src/image_segments.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use coordinate_systems::Pixel;
use linear_algebra::{point, Point2};
use path_serde::{PathDeserialize, PathIntrospect, PathSerialize};
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -44,7 +46,18 @@ impl Segment {
}
}

#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[derive(
Clone,
Copy,
Debug,
Deserialize,
Eq,
PartialEq,
Serialize,
PathSerialize,
PathDeserialize,
PathIntrospect,
)]
pub enum EdgeType {
Rising,
Falling,
Expand All @@ -57,3 +70,22 @@ pub enum Direction {
Horizontal,
Vertical,
}

#[derive(
Clone, Copy, Debug, Deserialize, Serialize, PathSerialize, PathDeserialize, PathIntrospect,
)]
pub struct GenericSegment {
pub start: Point2<Pixel, u16>,
pub end: Point2<Pixel, u16>,
pub start_edge_type: EdgeType,
pub end_edge_type: EdgeType,
}

impl GenericSegment {
pub fn center(&self) -> Point2<Pixel, u16> {
point![
self.start.x() + (self.end.x() - self.start.x()) / 2,
self.start.y() + (self.end.y() - self.start.y()) / 2,
]
}
}
20 changes: 10 additions & 10 deletions crates/vision/src/line_detection.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
mod checks;
mod iter_if;
mod map_segments;
mod segment;
mod segment_merger;

use std::{collections::HashSet, ops::Range};
Expand All @@ -24,6 +23,7 @@ use projection::{camera_matrix::CameraMatrix, Projection};
use ransac::{Ransac, RansacResult};
use types::{
filtered_segments::FilteredSegments,
image_segments::GenericSegment,
line_data::{LineData, LineDiscardReason},
ycbcr422_image::YCbCr422Image,
};
Expand All @@ -41,7 +41,8 @@ pub struct CycleContext {
lines_in_image: AdditionalOutput<Vec<LineSegment<Pixel>>, "lines_in_image">,
discarded_lines:
AdditionalOutput<Vec<(LineSegment<Pixel>, LineDiscardReason)>, "discarded_lines">,
ransac_input: AdditionalOutput<Vec<Point2<Pixel>>, "ransac_input">,
filtered_segments_output:
AdditionalOutput<Vec<GenericSegment>, "line_detection.filtered_segments">,

use_horizontal_segments:
Parameter<bool, "line_detection.$cycler_instance.use_horizontal_segments">,
Expand Down Expand Up @@ -138,10 +139,16 @@ impl LineDetection {
*context.gradient_alignment,
*context.gradient_sobel_stride,
)
});
})
.collect::<Vec<_>>();

context
.filtered_segments_output
.fill_if_subscribed(|| filtered_segments.clone());

let (line_points, used_segments): (Vec<Point2<Ground>>, HashSet<Point2<Pixel, u16>>) =
filtered_segments
.into_iter()
.filter_map(|segment| {
Some((
context
Expand All @@ -153,13 +160,6 @@ impl LineDetection {
})
.unzip();

context.ransac_input.fill_if_subscribed(|| {
line_points
.iter()
.map(|point| context.camera_matrix.ground_to_pixel(*point).unwrap())
.collect()
});

let mut ransac = Ransac::new(line_points);
let mut lines_in_ground = Vec::new();
for _ in 0..*context.maximum_number_of_lines {
Expand Down
17 changes: 9 additions & 8 deletions crates/vision/src/line_detection/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ use std::ops::Range;
use coordinate_systems::Pixel;
use linear_algebra::{distance, vector, Point2, Vector2};
use projection::{camera_matrix::CameraMatrix, Projection};
use types::{image_segments::EdgeType, ycbcr422_image::YCbCr422Image};
use types::{
image_segments::{EdgeType, GenericSegment},
ycbcr422_image::YCbCr422Image,
};

use super::segment::Segment;

pub fn is_non_field_segment(segment: &Segment) -> bool {
pub fn is_non_field_segment(segment: &GenericSegment) -> bool {
segment.start_edge_type == EdgeType::Rising && segment.end_edge_type == EdgeType::Falling
}

pub fn is_in_length_range(
segment: &Segment,
segment: &GenericSegment,
camera_matrix: &CameraMatrix,
allowed_projected_segment_length: &Range<f32>,
) -> bool {
Expand All @@ -26,7 +27,7 @@ pub fn is_in_length_range(
}

pub fn has_opposite_gradients(
segment: &Segment,
segment: &GenericSegment,
image: &YCbCr422Image,
gradient_alignment: f32,
gradient_sobel_stride: u32,
Expand Down Expand Up @@ -129,15 +130,15 @@ mod tests {
Isometry3::identity().framed_transform(),
);

let segment = Segment {
let segment = GenericSegment {
start: point![40, 2],
end: point![40, 202],
start_edge_type: EdgeType::ImageBorder,
end_edge_type: EdgeType::ImageBorder,
};
assert!(!is_in_length_range(&segment, &camera_matrix, &(0.0..0.3)));

let segment = Segment {
let segment = GenericSegment {
start: point![40, 364],
end: point![40, 366],
start_edge_type: EdgeType::ImageBorder,
Expand Down
8 changes: 4 additions & 4 deletions crates/vision/src/line_detection/map_segments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ use std::slice::Iter;

use coordinate_systems::Pixel;
use linear_algebra::{point, Point2};
use types::image_segments::ScanLine;
use types::image_segments::{GenericSegment, ScanLine};

use super::{segment::Segment, segment_merger::SegmentMerger};
use super::segment_merger::SegmentMerger;

pub fn map_segments<Mapping: PositionMapping>(
scan_lines: Iter<'_, ScanLine>,
maximum_merge_gap: u16,
) -> impl Iterator<Item = Segment> + '_ {
) -> impl Iterator<Item = GenericSegment> + '_ {
scan_lines.flat_map(move |scan_line| {
SegmentMerger::new(
scan_line.segments.iter().map(|segment| Segment {
scan_line.segments.iter().map(|segment| GenericSegment {
start: Mapping::map(scan_line.position, segment.start),
end: Mapping::map(scan_line.position, segment.end),
start_edge_type: segment.start_edge_type,
Expand Down
20 changes: 0 additions & 20 deletions crates/vision/src/line_detection/segment.rs

This file was deleted.

12 changes: 6 additions & 6 deletions crates/vision/src/line_detection/segment_merger.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use std::iter::Peekable;

use super::segment::Segment;
use types::image_segments::GenericSegment;

pub struct SegmentMerger<T: Iterator<Item = Segment>> {
pub struct SegmentMerger<T: Iterator<Item = GenericSegment>> {
iterator: Peekable<T>,
maximum_merge_gap: u16,
}

impl<T> SegmentMerger<T>
where
T: Iterator<Item = Segment>,
T: Iterator<Item = GenericSegment>,
{
pub fn new(iterator: T, maximum_merge_gap: u16) -> Self {
Self {
Expand All @@ -21,9 +21,9 @@ where

impl<T> Iterator for SegmentMerger<T>
where
T: Iterator<Item = Segment>,
T: Iterator<Item = GenericSegment>,
{
type Item = Segment;
type Item = GenericSegment;

fn next(&mut self) -> Option<Self::Item> {
let mut current = self.iterator.next()?;
Expand All @@ -42,6 +42,6 @@ where
}
}

fn distance_between_segments(first: Segment, second: Segment) -> u16 {
fn distance_between_segments(first: GenericSegment, second: GenericSegment) -> u16 {
(second.start.x() - first.end.x()) + (second.start.y() - first.end.y())
}
18 changes: 10 additions & 8 deletions tools/twix/src/panels/image/overlays/line_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ use eframe::epaint::{Color32, Stroke};

use coordinate_systems::Pixel;
use geometry::line_segment::LineSegment;
use linear_algebra::Point2;
use types::line_data::LineDiscardReason;
use types::{image_segments::GenericSegment, line_data::LineDiscardReason};

use crate::{
panels::image::{cycler_selector::VisionCycler, overlay::Overlay},
Expand All @@ -17,7 +16,7 @@ type DiscardedLines = Vec<(LineSegment<Pixel>, LineDiscardReason)>;
pub struct LineDetection {
lines_in_image: BufferHandle<Option<Vec<LineSegment<Pixel>>>>,
discarded_lines: BufferHandle<Option<DiscardedLines>>,
ransac_input: BufferHandle<Option<Vec<Point2<Pixel>>>>,
filtered_segments: BufferHandle<Option<Vec<GenericSegment>>>,
}

impl Overlay for LineDetection {
Expand All @@ -30,8 +29,9 @@ impl Overlay for LineDetection {
.subscribe_value(format!("{cycler_path}.additional_outputs.lines_in_image")),
discarded_lines: nao
.subscribe_value(format!("{cycler_path}.additional_outputs.discarded_lines")),
ransac_input: nao
.subscribe_value(format!("{cycler_path}.additional_outputs.ransac_input")),
filtered_segments: nao.subscribe_value(format!(
"{cycler_path}.additional_outputs.line_detection.filtered_segments"
)),
}
}

Expand All @@ -42,11 +42,13 @@ impl Overlay for LineDetection {
let Some(discarded_lines) = self.discarded_lines.get_last_value()?.flatten() else {
return Ok(());
};
let Some(ransac_input) = self.ransac_input.get_last_value()?.flatten() else {
let Some(filtered_segments) = self.filtered_segments.get_last_value()?.flatten() else {
return Ok(());
};
for point in ransac_input {
painter.circle_stroke(point, 3.0, Stroke::new(1.0, Color32::RED))
for segment in filtered_segments {
let stroke = Stroke::new(1.0, Color32::RED);
painter.line_segment(segment.start.cast(), segment.end.cast(), stroke);
painter.circle_stroke(segment.center().cast(), 3.0, stroke);
}
for (line, reason) in discarded_lines {
let color = match reason {
Expand Down

0 comments on commit 1cac67f

Please sign in to comment.