lj_qualibration/src/qualibration/sequence/line_dotted.rs

168 lines
5.3 KiB
Rust

use crate::point::{Color, Point};
use crate::qualibration::{
annalyse::{
draw_histograme_bgr_tresh, get_horizontal_segment, get_vertical_segment, histogram_3d,
image_diff,
},
param::Param,
Sequence,
};
use opencv::{
core::{bitwise_and, in_range, Mat, Point as OcvPoint, Scalar, VecN, BORDER_CONSTANT},
highgui,
imgproc::{self, line},
Result,
};
opencv::opencv_branch_4! {
use opencv::imgproc::LINE_8;
}
opencv::not_opencv_branch_4! {
use opencv::core::LINE_AA;
}
#[derive(Debug, Clone)]
pub struct LineDotted {
finished: bool,
cnt: usize,
beg: Point,
end: Point,
continuous_y: bool,
continuous_x: bool,
}
impl LineDotted {
pub fn new(beg: Point, end: Point, continuous_y: bool, continuous_x: bool) -> Self {
Self {
finished: false,
cnt: 0,
beg,
end,
continuous_x,
continuous_y,
}
}
}
impl Sequence for LineDotted {
fn draw(&self, mem: &Param) -> Option<Vec<Point>> {
if self.finished {
return None;
}
if self.cnt == 0 {
return Some(vec![]);
}
let nb_all = mem.nb_all;
let nb_wait = mem.nb_wait as usize;
let nb_visible = mem.nb_visible as usize;
let mut pl = vec![];
let color = Color {
r: mem.r as u8,
g: mem.g as u8,
b: mem.b as u8,
};
let black = Color { r: 0, g: 0, b: 0 };
for _ in 0..nb_all {
pl.push(Point {
color: black,
..self.beg
});
}
let len = (2 * mem.line_pos.len() + nb_wait) as f32;
for i in 0..nb_wait {
let val_x = i as f32 / len * (self.end.x - self.beg.x) + self.beg.x;
let val_y = i as f32 / len * (self.end.y - self.beg.y) + self.beg.y;
pl.push(Point {
x: if self.continuous_x { val_x } else { self.beg.x },
y: if self.continuous_y { val_y } else { self.beg.y },
color: black,
});
}
for i in 0..(mem.line_pos.len() * 2) {
let val_cont_x = (i + nb_wait) as f32 / len * (self.end.x - self.beg.x) + self.beg.x;
let val_cont_y = (i + nb_wait) as f32 / len * (self.end.y - self.beg.y) + self.beg.y;
let val_x = mem.line_pos[i / 2] as f32 + self.beg.x;
let val_y = mem.line_pos[i / 2] as f32 + self.beg.y;
let is_visible = (i + nb_wait) % 2 == 0 && i < nb_visible;
let c = if is_visible { color } else { black };
pl.push(Point {
x: if self.continuous_x { val_cont_x } else { val_x },
y: if self.continuous_y { val_cont_y } else { val_y },
color: c,
});
}
Some(pl)
}
fn compute_sequence(&mut self, mem: &mut Param) -> Result<(), Box<dyn std::error::Error>> {
if self.cnt < 1 {
self.cnt += 1;
}
let ids = mem.seq_id;
let background = mem.imgs[ids][0].to_owned();
let line_dot = mem.imgs[ids][1].to_owned();
let diff = image_diff(&background, &line_dot)?;
let mut warped_image = Mat::default();
imgproc::warp_perspective(
&diff,
&mut warped_image,
&mem.homography,
mem.h_size,
imgproc::INTER_CUBIC, // I dont see difference with INTER_CUBIC
BORDER_CONSTANT,
Scalar::default(),
)?;
//highgui::imshow("Warped Image", &warped_image)?;
let histo = histogram_3d(&warped_image, mem.nb_liss)?;
draw_histograme_bgr_tresh("histo bgr", &histo, &mem.tresh)?;
let (t1, s1, l1) = (
mem.tresh.min_0 as f64,
mem.tresh.min_1 as f64,
mem.tresh.min_2 as f64,
);
let (t2, s2, l2) = (
mem.tresh.max_0 as f64,
mem.tresh.max_1 as f64,
mem.tresh.max_2 as f64,
);
let min = Mat::from_slice(&[t1, s1, l1])?;
let max = Mat::from_slice(&[t2, s2, l2])?;
let mut color_selected = Mat::default();
let _ = in_range(&warped_image, &min, &max, &mut color_selected);
let mut bord_treshed = Mat::default();
bitwise_and(
&warped_image,
&warped_image,
&mut bord_treshed,
&color_selected,
)?;
//highgui::imshow(format!("warped_image & mask").as_str(), &bord_treshed)?;
let segments = if self.continuous_y {
get_vertical_segment(&bord_treshed)?
} else {
get_horizontal_segment(&bord_treshed)?
};
for (i, (((x0, y0), (x1, y1)), _size)) in segments.iter().enumerate() {
let blue = (i as f64 / segments.len() as f64) * 255.;
let color: VecN<f64, 4> = VecN::new(blue, 128., 0., 255.);
let pa = VecN::from_array([*x0 as i32, *y0 as i32]);
let pb = VecN::from_array([*x1 as i32, *y1 as i32]);
let a = OcvPoint::from_vec2(pa);
let b = OcvPoint::from_vec2(pb);
line(&mut bord_treshed, a, b, color, 1, LINE_8, 0)?;
}
highgui::imshow("segemnt detector", &bord_treshed)?;
self.finished = true;
Ok(())
}
fn is_capture(&self) -> bool {
true
}
}