diff --git a/.gitignore b/.gitignore index b2706ed..5ea1abc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.png image target +settings.toml diff --git a/src/draw.rs b/src/draw.rs index 84165bf..f904f30 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -7,12 +7,12 @@ const X_CENTER: f32 = 2047.0; const Y_CENTER: f32 = 2047.0; pub fn draw_line_dotted( + p0: &Point, p1: &Point, - p2: &Point, nb_all: usize, nb_visible: usize, first_on: bool, -) -> Result, Box> { +) -> Vec { let mut pl = vec![]; let black = Color { r: 0, g: 0, b: 0 }; @@ -21,61 +21,56 @@ pub fn draw_line_dotted( for _ in 0..nb_all { pl.push(Point { color: black, - ..*p1 + ..*p0 }); } for i in 0..nb_visible { pl.push(Point { - color: if i % 2 == cmp { p2.color } else { black }, - ..*p2 + color: if i % 2 == cmp { p1.color } else { black }, + ..*p1 }); } if nb_visible > nb_all { - return Ok(pl); + return pl; } for _ in 0..(nb_all - nb_visible) { pl.push(Point { color: black, - ..*p2 + ..*p1 }); } - Ok(pl) + pl } -pub fn draw_line( - p1: &Point, - p2: &Point, - nb_all: usize, - nb_visible: usize, -) -> Result, Box> { +pub fn draw_line(p0: &Point, p1: &Point, nb_all: usize, nb_visible: usize) -> Vec { let mut pl = vec![]; let black = Color { r: 0, g: 0, b: 0 }; for _ in 0..nb_all { pl.push(Point { color: black, - ..*p1 + ..*p0 }); } for _ in 0..nb_visible { - pl.push(*p2); + pl.push(*p1); } if nb_visible > nb_all { - return Ok(pl); + return pl; } for _ in 0..(nb_all - nb_visible) { pl.push(Point { color: black, - ..*p2 + ..*p1 }); } - Ok(pl) + pl } #[allow(dead_code)] -pub fn draw(_time: f64) -> Result, Box> { +pub fn draw(_time: f64) -> Vec { let mut v: Vec = vec![]; for i in 0..128 { let a = i as f32 / 128.0 * std::f32::consts::PI * 2.0; @@ -89,5 +84,5 @@ pub fn draw(_time: f64) -> Result, Box> { }, }); } - Ok(v) + v } diff --git a/src/framerate.rs b/src/framerate.rs index cfca9f6..5b55ebe 100644 --- a/src/framerate.rs +++ b/src/framerate.rs @@ -1,8 +1,10 @@ +#[allow(unused)] use log::{debug, warn}; use std::thread; use std::time::{Duration, Instant}; /// Converts helios Geometry to Helios +#[allow(dead_code)] #[derive(Debug, Clone, Copy)] pub struct Framerate { start: Instant, @@ -10,6 +12,7 @@ pub struct Framerate { framerate: u8, } +#[allow(dead_code)] impl Framerate { pub fn new(framerate: u8) -> Result> { Ok(Framerate { @@ -18,7 +21,7 @@ impl Framerate { framerate, }) } - pub fn handle_time(&mut self) -> Result<(f64), Box> { + pub fn handle_time(&mut self) -> Result> { let frame_time = 1000000000 / self.framerate as u128; let now = Instant::now(); // How long since last loop ? diff --git a/src/main.rs b/src/main.rs index 011300e..c9e6f12 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ mod point; mod qualibration; mod utils; -use qualibration::{annalyse::adding_trackbar, Qualibration, Sequence}; +use qualibration::{annalyse::adding_trackbar, Qualibration}; use conf::Conf; use log::{/*debug, warn, */ error, info}; @@ -57,7 +57,7 @@ fn run_all() -> Result<(), Box> { let client = Client::open(config.redis_url.clone())?; let mut con: Connection = client.get_connection()?; - let mut framerate_handler = framerate::Framerate::new(config.framerate)?; + let mut _framerate_handler = framerate::Framerate::new(config.framerate)?; // Setup handler for interrupt Signals let running = Arc::new(AtomicBool::new(true)); @@ -78,7 +78,7 @@ fn run_all() -> Result<(), Box> { info!("{:?}", config); let mut qualibration = Qualibration::new()?; - adding_trackbar(&mut qualibration, "histogram: 0")?; + adding_trackbar(&mut qualibration.param, "histogram: 0")?; let _a: () = con.set(format!("/kpps/{}", conf2.laser_id), 65535)?; let _a: () = con.set( @@ -87,44 +87,46 @@ fn run_all() -> Result<(), Box> { )?; while running.load(Ordering::SeqCst) { - //let _t = framerate_handler.handle_time()?; + //let _t = _framerate_handler.handle_time()?; ///////////////// let key = highgui::wait_key(1)?; - //if key != -1 { - qualibration.key = key; - //} + qualibration.param.key = key; if key == 27 { - // esc in my case break; } - //qualibration.id = next_id; - let v: Vec<(f32, f32, u32)> = qualibration - .draw_sequence()? - .iter() - .map(|pt| (pt.x, pt.y, u32::from(pt.color))) - .collect(); - // println!("{:?}", v); - let _ = con.set( - format!("/pl/{}/{}", config.client_id, config.laser_id), - format!("{:?}", v), - )?; + let v = qualibration.draw_sequence(); + if v.is_some() { + if qualibration.param.capture_mode { + let pl: Vec<(f32, f32, u32)> = v + .unwrap() + .iter() + .map(|pt| (pt.x, pt.y, u32::from(pt.color))) + .collect(); - qualibration.run_step()?; + let _ = con.set( + format!("/pl/{}/{}", config.client_id, config.laser_id), + format!("{:?}", pl), + )?; + } - let q_id = qualibration.id.clone(); - let mut n = 65534; - if let Sequence::TakeMultiple(m) = q_id.clone().unwrap_or(Sequence::Finish) { - n = m; - }; - if qualibration.capture_mode - && (q_id != Some(Sequence::WaitSpace) - || q_id != Some(Sequence::PlayLineDotted) - || n != 65534) - { - let millis = std::time::Duration::from_millis(400); // TODO: find solution to know when change has been done - std::thread::sleep(millis); + qualibration.run_step()?; } + //qualibration.id = next_id; + + //let q_id = qualibration.id.clone(); + //let mut n = 65534; + //if let Sequence::TakeMultiple(m) = q_id.clone().unwrap_or(Sequence::Finish) { + // n = m; + //}; + //if qualibration.capture_mode + // && (q_id != Some(Sequence::WaitSpace) + // || q_id != Some(Sequence::PlayLineDotted) + // || n != 65534) + //{ + // let millis = std::time::Duration::from_millis(400); // TODO: find solution to know when change has been done + // std::thread::sleep(millis); + //} } let _ = con.set( diff --git a/src/point.rs b/src/point.rs index 36f13b8..c720627 100644 --- a/src/point.rs +++ b/src/point.rs @@ -1,3 +1,4 @@ +#[allow(dead_code)] pub type Line = Vec<(f32, f32, u32)>; #[derive(Debug, Clone, Copy, Default, PartialEq)] diff --git a/src/qualibration.rs b/src/qualibration.rs index 562a1a4..1737b67 100644 --- a/src/qualibration.rs +++ b/src/qualibration.rs @@ -1,121 +1,45 @@ +//use opencv::Result; +//use opencv::core::{self, Mat}; + +#[allow(dead_code)] +static DEBUG: bool = true; + pub mod annalyse; pub mod borders; pub mod compute_image; -use annalyse::{ - draw_histograme_bgr_tresh, get_horizontal_segment, get_vertical_segment, histogram_3d, - image_diff, image_mean, -}; // mean dans le sans moyenne des image -use borders::{bord_mult, get_extermities, get_intersection, mix_borders, probabilistic_hough}; -use compute_image::{image_treshold, image_warp, image_warp_treshold}; use std::env::args; -use std::time::Instant; -use crate::draw::{draw_line, draw_line_dotted}; -use crate::point::{Color, Point}; +use crate::point::Point; -use enum_iterator::{next, Sequence as Seq}; use opencv::core::Mat; use opencv::Result; -use std::f64::consts::PI; +//use std::f64::consts::PI; -use opencv::core::{bitwise_and, find_file, in_range, Point as OcvPoint, Scalar, Size_}; -use opencv::core::{VecN, Vector}; -use opencv::imgcodecs::imwrite; -use opencv::imgcodecs::{imread, IMREAD_COLOR}; -use opencv::imgproc::{canny, cvt_color, line, COLOR_BGR2GRAY}; use opencv::prelude::*; use opencv::{ highgui, videoio::{self, VideoCapture}, }; -use std::fs::create_dir; -use std::fs::read_dir; -use opencv::{ - calib3d, - core::{self, Size}, - imgproc, -}; +mod param; +use param::Param; -opencv::opencv_branch_4! { - use opencv::imgproc::LINE_AA; - use opencv::imgproc::LINE_8; -} -opencv::not_opencv_branch_4! { - use opencv::core::LINE_AA; -} - -const DEBUG: bool = true; - -#[derive(Debug, PartialEq, Seq, Copy, Clone)] -pub enum Sequence { - //TODO: avoir le meme nombre d'image en mode capture ET en mode replay - FirstState, - WaitSpace, - BackGround, - UpBorder, - LeftBorder, - DownBorder, - RightBorder, - ReadDir, - ComputeArea, - IdCode1, - IdCode2, - Finish, - - PlayLineDotted, - EmptyFrame, - ComputeLineDotted, - - LinearConstSpeed, // [multiple test] - JumpFromTo, - - AdaptLineSeg(u16), // [multiple test] find the correct distense - AdaptLineLum, // [multiple test] try minimu, medium, maximum. - // - SelectSpeedestColor, // on pourait mettre a jour les valeur a chaque passage - - Vertical(u16), - Horizontal(u16), - SelectNbAll(u16), - ComputeSelectNbAll, - TakeMultiple(u16), - TakeMultipleEmpty(u16), -} +mod sequence; +pub use sequence::{InitBorder, InitIdcode, LineDotted, LoadImage, SaveImage, Sequence, WaitSpace}; #[derive(Debug)] pub struct Qualibration { - pub begin: Instant, - pub dst_size: i32, - pub cam: VideoCapture, - pub r: i32, - pub g: i32, - pub b: i32, - pub capture_mode: bool, - pub frame: Mat, - pub frame_prev: Mat, - pub img: Vec, - pub id: Option, - pub nb_all: i32, - pub nb_visible: i32, - pub nb_liss: i32, - pub tresh: Treshold, - pub dir_name: String, - pub key: i32, - pub canny_v1: i32, - pub canny_v2: i32, - pub hough_param: HoughLine, - pub border_pt: Vec<(f64, f64)>, - pub homography: Mat, - pub h_size: Size_, - pub line_pos: Vec, - pub multiple: u16, // le nombre de fois qu'une photo est prise pour certaine sequence - pub cnt: usize, + seq: Vec>, + cam: VideoCapture, + + pub param: Param, } impl Qualibration { pub fn new() -> Result { + //let v: Vec> = vec![]; + let mut dir_name = "".to_string(); //"building.jpg".to_string(); // by default if let Some(dir_name_arg) = args().nth(1) { dir_name = dir_name_arg; @@ -130,816 +54,58 @@ impl Qualibration { let mut frame = Mat::default(); cam.read(&mut frame)?; + // 38400 -> r:150, v:0, b:0 + let beg = Point::from((0., 0., 38400)); + let beg2 = Point::from((4095., 0., 38400)); + let end = Point::from((4095., 4095., 38400)); + let seq: Vec> = vec![ + Box::new(LoadImage::new()), + Box::new(WaitSpace::new(beg, end)), + Box::new(InitBorder::new(beg, end)), + Box::new(LineDotted::new(beg, end, true, false)), + Box::new(InitIdcode::new(beg2, end)), + Box::new(SaveImage::new()), + ]; //let now = std::time::Instant::now(); Ok(Qualibration { - begin: std::time::Instant::now(), - dst_size: 900, + seq, cam, - r: 150, - g: 0, - b: 0, - capture_mode: dir_name.len() == 0, - img: vec![], - frame: Mat::default(), // TODO: init with frame from cam - frame_prev: Mat::default(), - id: Some(Sequence::FirstState), - nb_all: 120, - nb_visible: 40, - nb_liss: 10, - tresh: Treshold::new("histogram: 0", 150, 255)?, - dir_name: dir_name.clone(), - key: 10, - canny_v1: 170, - canny_v2: 255, - hough_param: HoughLine { - rho: 100, - theta: 100, - treshold: 30, - min_length: 0, - max_line_gap: 50000, - }, - border_pt: vec![], - homography: Mat::default(), - h_size: Size::default(), - line_pos: vec![4095; 34], - multiple: 20, - cnt: 0, + param: Param::new(dir_name.to_owned())?, }) } - pub fn run_step(&mut self) -> Result<(), Box> { - if self.capture_mode && self.id != Some(Sequence::PlayLineDotted) { - //println!("capture"); - self.cam.read(&mut self.frame)?; - highgui::imshow("camera", &self.frame)?; - } - - if self.frame.size()?.width > 0 && self.frame_prev.size()?.width > 0 || !self.capture_mode { - if self.id.is_some() { - self.id = if true { - //self.capture_mode || self.id == Some(Sequence::WaitSpace) || is_same_frame(&self.frame, &self.frame_prev)? { - if self.id != Some(Sequence::WaitSpace) - && self.id != Some(Sequence::FirstState) - && self.id != Some(Sequence::PlayLineDotted) - && self.capture_mode - { - self.img.push(self.frame.clone()); - } - self.compute_sequence()?; - self.get_next_id_seq() - } else { - self.id - }; - } - } - //println!("sequence: {:?}", self.id); - self.frame_prev = self.frame.clone(); - self.cnt += 1; - Ok(()) - } - - pub fn draw_sequence(&self) -> Result, Box> { - if !self.capture_mode { - return Ok(vec![]); - } - let seq = self.id; - let mut pl = vec![]; - //let color = Color { r: 0, g: 30, b: 0 }; - let color = Color { - r: self.r as u8, - g: self.g as u8, - b: self.b as u8, - }; - //let color = Color { r: 0, g: 0, b: 50 }; - let (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pa, pb) = - get_point_to_draw(self.r as u8, self.g as u8, self.b as u8, color.clone()); - let nb_all = self.nb_all as usize; - let nb_visible = self.nb_visible as usize; - let nb_wait = 30; // ca permet de prendre de la vitess en y. Et donc ca permet de - // mieux voir les segment qui bouge peut au debut. - - if seq.is_some() { - match seq.unwrap() { - Sequence::IdCode1 => { - // on va en haut a gauche - // on va a droite en clognotant sur les nombre pair - pl.extend(draw_line_dotted(&pa, &pb, nb_all, nb_visible, true)?); - } - Sequence::IdCode2 => { - // on va en haut a gauche - // on va a droite en clognotant sur les nombre impair - pl.extend(draw_line_dotted(&pa, &pb, nb_all, nb_visible, false)?); - } - Sequence::PlayLineDotted - | Sequence::TakeMultiple(_) - | Sequence::ComputeLineDotted => { - // la on va faire une ligne qu'on peut observer - let black = Color { r: 0, g: 0, b: 0 }; - for _ in 0..nb_all { - pl.push(Point { - x: 0., - y: 0., - color: black, - }); - } - let len = (2 * self.line_pos.len() + nb_wait) as f32; - for i in 0..nb_wait { - let y = i as f32 * 4095. / len; - pl.push(Point { - x: 0., - y, - color: black, - }); - } - for i in 0..(self.line_pos.len() * 2) { - let y = (i + nb_wait) as f32 * 4095. / len; - let c = if (i + nb_wait) % 2 == 0 && i < nb_visible { - color - } else { - black - }; - pl.push(Point { - x: self.line_pos[i / 2] as f32, - y, - color: c, - }); - } - } - Sequence::WaitSpace => { - pl = draw_line(&p0, &p1, nb_all, nb_visible)?; - pl.extend(draw_line(&p1, &p2, nb_all, nb_visible)?); - pl.extend(draw_line(&p3, &p0, nb_all, nb_visible)?); - pl.extend(draw_line(&p2, &p3, nb_all, nb_visible)?); - - pl.extend(draw_line_dotted(&p4, &p5, nb_all, nb_visible, true)?); - pl.extend(draw_line_dotted(&p6, &p7, nb_all, nb_visible, true)?); - pl.extend(draw_line_dotted(&p8, &p9, nb_all, nb_visible, true)?); - } - Sequence::SelectNbAll(n) => { - pl = draw_line(&p0, &p1, n as usize, n as usize)?; - pl.extend(draw_line(&p1, &p2, n as usize, n as usize)?); - pl.extend(draw_line(&p3, &p0, n as usize, n as usize)?); - pl.extend(draw_line(&p2, &p3, n as usize, n as usize)?); - } - Sequence::UpBorder => { - pl = draw_line(&p0, &p1, nb_all, nb_visible)?; - } - Sequence::RightBorder => { - pl = draw_line(&p1, &p2, nb_all, nb_visible)?; - } - Sequence::DownBorder => { - pl = draw_line(&p2, &p3, nb_all, nb_visible)?; - } - Sequence::LeftBorder => { - pl = draw_line(&p3, &p0, nb_all, nb_visible)?; - } - Sequence::Vertical(n) => { - let p1 = Point { - x: n as f32, - y: 0., - color, - }; - let p2 = Point { - x: n as f32, - y: 4095., - color, - }; - pl = draw_line(&p1, &p2, nb_all, nb_visible)?; - } - Sequence::Horizontal(n) => { - let p1 = Point { - x: 0., - y: n as f32, - color, - }; - let p2 = Point { - x: 4095., - y: n as f32, - color, - }; - pl = draw_line(&p1, &p2, nb_all, nb_visible)?; - } - _ => (), - } - } - - Ok(pl) - } - - pub fn get_next_id_seq(&self) -> Option { - let line_max = 4095; - let line_add = 100; - - if self.id.is_none() { + pub fn draw_sequence(&mut self) -> Option> { + if self.param.seq_id >= self.seq.len() { return None; } - //println!("Hey"); - match self.id.unwrap() { - //Sequence::Finish => Some(Sequence::Finish), - Sequence::Finish => None, - Sequence::ComputeLineDotted => Some(Sequence::ComputeLineDotted), - Sequence::TakeMultiple(n) => { - if n > self.multiple { - next(&Sequence::TakeMultiple(u16::MAX)) - } else { - next(&Sequence::TakeMultiple(n)) - } + let pl = self.seq[self.param.seq_id].draw(&self.param); + + if pl.is_none() { + self.param.seq_id += 1; + if self.param.capture_mode { + self.param.imgs.push(vec![]); } - Sequence::TakeMultipleEmpty(n) => { - if n > self.multiple { - next(&Sequence::TakeMultipleEmpty(u16::MAX)) - } else { - next(&Sequence::TakeMultipleEmpty(n)) - } - } - Sequence::SelectNbAll(n) => { - if n == 0 { - Some(Sequence::SelectNbAll(2 - 1)) - } else if (2 * n) > line_max as u16 { - next(&Sequence::SelectNbAll(u16::MAX)) - } else { - next(&Sequence::SelectNbAll(n * 2 - 1)) - } - } - Sequence::WaitSpace => { - //println!("key: {}", self.key); - if self.key == 32 || !self.capture_mode { - next(&Sequence::WaitSpace) - } else { - Some(Sequence::WaitSpace) - } - } - Sequence::PlayLineDotted => { - //println!("key: {}", self.key); - if self.key == 32 || !self.capture_mode { - next(&Sequence::PlayLineDotted) - } else { - Some(Sequence::PlayLineDotted) - } - } - Sequence::Vertical(n) => { - let after = if n > line_max { u16::MAX } else { n + line_add }; - next(&Sequence::Vertical(after)) - } - Sequence::Horizontal(n) => { - let after = if n > line_max { u16::MAX } else { n + line_add }; - next(&Sequence::Horizontal(after)) - } - //Sequence::ComputeArea => Some(Sequence::ComputeArea), // - id => next(&id), } + + pl } - pub fn compute_sequence(&mut self) -> Result<(), Box> { - if self.id.is_none() { - return Ok(()); + pub fn run_step(self: &mut Self) -> Result<(), Box> { + let mut frame = Mat::default(); + if self.param.capture_mode { + self.cam.read(&mut frame)?; + highgui::imshow("camera", &frame)?; + + if frame.size()?.width > 0 && self.seq[self.param.seq_id].is_capture() { + self.param.imgs[self.param.seq_id].push(frame.clone()); + } } - match self.id.unwrap() { - Sequence::IdCode2 => { - let mut id_code_1 = image_diff(&self.img[8], &self.img[1])?; - id_code_1 = image_warp(&id_code_1, &self.homography, self.h_size)?; - id_code_1 = image_treshold(&id_code_1, &self.tresh)?; - - let code_seg_1 = get_horizontal_segment(&id_code_1)?; - let code_seg_1 = code_seg_1[1..(code_seg_1.len() - 1)].to_owned(); - //let l = code_seg_1.len(); - //let code_seg_1 = code_seg_1[(l-16)..(l-1)].to_owned(); - - //let blue = (i as f64 / code_seg_1.len() as f64) * 255.; - let color_1: VecN = VecN::new(255., 0., 0., 255.); - // on dessine - for i in 0..code_seg_1.len() { - let (((x0, y0), (x1, y1)), size) = code_seg_1[i]; - //line(&mut id_code_1, ); - let s = size as i32; - let x = ((x0 + x1) / 2.) as i32; - let y = ((y0 + y1) / 2.) as i32; - let a = OcvPoint::from_vec2(VecN::from_array([x, y - s])); - let b = OcvPoint::from_vec2(VecN::from_array([x, y + s])); - line(&mut id_code_1, a, b, color_1, 1, LINE_8, 0)?; - //if i < (code_seg_1.len() - 1) { - // let (((x2, y2), _), size) = code_seg_1[i + 1]; - // let x = ((x1 + x2) / 2.) as i32; - // let y = ((y0 + y1) / 2.) as i32; - // let a = OcvPoint::from_vec2(VecN::from_array([x, y - s])); - // let b = OcvPoint::from_vec2(VecN::from_array([x, y + s])); - // line(&mut id_code_1, a, b, color_1, 1, LINE_8, 0)?; - //} - } - - let mut id_code_2 = image_diff(&self.img[9], &self.img[1])?; - id_code_2 = image_warp(&id_code_2, &self.homography, self.h_size)?; - id_code_2 = image_treshold(&id_code_2, &self.tresh)?; - let code_seg_2 = get_horizontal_segment(&id_code_2)?; - let l = code_seg_2.len(); - let code_seg_2 = code_seg_2[(l - 16)..(l - 1)].to_owned(); - //highgui::imshow("code 2", &id_code_2)?; - let color_2: VecN = VecN::new(0., 255., 0., 255.); - // on dessine - for i in 0..code_seg_2.len() { - let (((x0, y0), (x1, y1)), size) = code_seg_2[i]; - //line(&mut id_code_2, ); - let s = size as i32; - let x = ((x0 + x1) / 2.) as i32; - let y = ((y0 + y1) / 2.) as i32; - let a = OcvPoint::from_vec2(VecN::from_array([x, y - s])); - let b = OcvPoint::from_vec2(VecN::from_array([x, y + s])); - line(&mut id_code_1, a, b, color_2, 1, LINE_8, 0)?; - //if i < (code_seg_2.len() - 1) { - // let (((x2, y2), _), size) = code_seg_2[i + 1]; - // let x = ((x1 + x2) / 2.) as i32; - // let y = ((y0 + y1) / 2.) as i32; - // let a = OcvPoint::from_vec2(VecN::from_array([x, y - s])); - // let b = OcvPoint::from_vec2(VecN::from_array([x, y + s])); - // line(&mut id_code_2, a, b, color_2, 1, LINE_8, 0)?; - //} - } - - // on va faire des ligne sur les endroit de scanne - - highgui::imshow("code 1", &id_code_1)?; - - // si on garde les [(len-16)..(len-1)] - - //let mean = image_mean(&[id_code_1, id_code_2])?; - //highgui::imshow("image mean", &mean)?; - - // la on pourrait aussi mettre les segment - - // On va regarder au milieux de code_2 pour voir si on voi un truc sur code_1 - - // fonction warp image - // fonction select thresh - // BOUUUUUH !!! ... t'as eut peur? - // - //let mut id_code_2 = image_diff(&self.img[9], &self.img[1])?; - //id_code_2 = image_warp(&id_code_2, &self.homography, self.h_size)?; - //id_code_2 = image_treshold(&id_code_2, &self.tresh)?; - //highgui::imshow("code 2", &id_code_2)?; - } - Sequence::ComputeLineDotted => { - let id1 = 7 + (self.cnt % 22); - let id2 = 30 + (self.cnt % 22); - //let backgrounds = self.img[7..30].to_owned(); - //let lines_dots = self.img[30..52].to_owned(); - let backgrounds = self.img[id1..(id1 + 1)].to_owned(); - let lines_dots = self.img[id2..(id2 + 1)].to_owned(); - - let background = image_mean(&backgrounds)?; - let line_dot = image_mean(&lines_dots)?; - let diff = image_diff(&background, &line_dot)?; - - let mut warped_image = Mat::default(); - imgproc::warp_perspective( - &diff, - &mut warped_image, - &self.homography, - self.h_size, - imgproc::INTER_CUBIC, // I dont see difference with INTER_CUBIC - core::BORDER_CONSTANT, - Scalar::default(), - )?; - //highgui::imshow("Warped Image", &warped_image)?; - - let histo = histogram_3d(&warped_image, self.nb_liss)?; - draw_histograme_bgr_tresh("histo bgr", &histo, &self.tresh)?; - - let (t1, s1, l1) = ( - self.tresh.min_0 as f64, - self.tresh.min_1 as f64, - self.tresh.min_2 as f64, - ); - let (t2, s2, l2) = ( - self.tresh.max_0 as f64, - self.tresh.max_1 as f64, - self.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 = get_vertical_segment(&bord_treshed)?; - for (i, ((x0, y0), (x1, y1))) in segments.iter().enumerate() { - let blue = (i as f64 / segments.len() as f64) * 255.; - let color: VecN = 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)?; - } - Sequence::ComputeSelectNbAll => { - let background: Mat; - let steps: Vec; - - background = self.img[1].clone(); - steps = self.img[2..6].into(); - - let mut angles: Vec = vec![]; - for (id, step) in steps.iter().enumerate() { - let lines = get_lines( - &background, - step, - id, - self.canny_v1, - self.canny_v2, - &self.hough_param, - )?; - - for l in lines { - let (x0, y0, x1, y1) = (l[0] as f64, l[1] as f64, l[2] as f64, l[3] as f64); - - let ang = (y1 - y0).atan2(x1 - x0); - angles.push(ang); - } - println!("ang: {angles:?}"); - } - - // on compare ce qui doit l'etre - } - Sequence::ComputeArea => { - let background: Mat; - let borders: Vec; - - background = self.img[1].clone(); - borders = self.img[2..6].into(); - - // on recupere chaqu'un des 4 bord - let mut bords_pts = vec![]; - for (i, bord) in borders.iter().enumerate() { - let bord_pt = self.get_one_border(&background, &bord, i)?; - bords_pts.push(bord_pt); - } - - //for (i, m) in self.img.iter().enumerate() { - // highgui::imshow(format!("img[{i}]").as_str(), m)?; - //} - - // on calcul le cadre - let border_pt = get_intersection(&bords_pts); - self.border_pt = bord_mult(border_pt, 1.1); - let color: VecN = VecN::new(255., 128., 0., 255.); - let mut mixed = mix_borders(&background, borders)?; - let b = &self.border_pt; - for i in 0..b.len() { - let j = (i + 1) % self.border_pt.len(); - let pa = VecN::from_array([b[i].0 as i32, b[i].1 as i32]); - let pb = VecN::from_array([b[j].0 as i32, b[j].1 as i32]); - let a = OcvPoint::from_vec2(pa); - let b = OcvPoint::from_vec2(pb); - line(&mut mixed, a, b, color, 1, LINE_AA, 0)?; - } - //highgui::imshow("mixed bored", &mixed)?; - - let size = self.dst_size; - // ici on va requadrer la partie de la projection laser de l'image - let warped_image_size = Size::new(size, size); - let roi_corners: Vec = self - .border_pt - .iter() - .map(|(x, y)| OcvPoint::new(*x as i32, *y as i32)) - .collect(); - //let dst = [(0, 0), (0, size), (size, size), (size, 0)]; // in: laser repere - let dst = [(0, size), (0, 0), (size, 0), (size, size)]; - let dst_corners: Vec = - dst.iter().map(|(x, y)| OcvPoint::new(*x, *y)).collect(); - let roi_corners_mat = Mat::from_slice(&roi_corners[..])?; - let dst_corners_mat = Mat::from_slice(&dst_corners)?; - let h = calib3d::find_homography( - &roi_corners_mat, - &dst_corners_mat, - &mut Mat::default(), - 0, - 3., - )?; //get homography - let mut warped_image = Mat::default(); - self.homography = h.clone(); - self.h_size = warped_image_size.clone(); - imgproc::warp_perspective( - &mixed, - &mut warped_image, - &h, - warped_image_size, - imgproc::INTER_CUBIC, // I dont see difference with INTER_CUBIC - core::BORDER_CONSTANT, - Scalar::default(), - )?; // do perspective transformation - //highgui::imshow("Warped Image", &warped_image)?; - } - Sequence::ReadDir => { - if !self.capture_mode { - self.load_image()?; - } - } - Sequence::Finish => { - if self.capture_mode { - self.save_image()? - } - } - _ => (), - } - Ok(()) - } - - fn save_image(&self) -> Result<()> { - // on fait le nom de dossier general au cas ou - // on fait un nom de dossier avec le temps - // on sauvgarde toutes les image - let now = self.begin; - let name = format!("image/"); - create_dir(&name).unwrap_or(()); - let name = format!( - "image/{:0>6?}_{:0>9?}/", - now.elapsed().as_secs(), - now.elapsed().as_nanos() - ); - create_dir(&name).unwrap_or(()); - //name.push_str(format!("image/{}_{}/", now.elapsed().as_secs(), now.elapsed().as_nanos()).as_str()); - //let name = format!("image/{now:?}/"); - - // - for (i, img) in self.img.iter().enumerate() { - let mut name_img = name.clone(); - name_img.push_str(&format!("img_{i}.png")); - imwrite(&name_img, img, &Vector::from_slice(&[6, 6, 6, 0]))?; + if frame.size()?.width > 0 || !self.param.capture_mode { + self.seq[self.param.seq_id].compute_sequence(&mut self.param)?; } Ok(()) } - - //use std::cmp::Ordering; - fn load_image(&mut self) -> Result<(), Box> { - let mut imgs = vec![]; - let paths = read_dir(&self.dir_name)?; - //let len = paths.size_hint(); - for entry in paths { - let dir = entry?; - let path = dir.path(); - let c: Vec<&str> = path.to_str().unwrap().split("/").collect(); - let d: Vec<_> = c[c.len() - 1].chars().collect(); - let e: String = d[4..d.len() - 4].iter().collect(); - let img_id: i32 = e.parse()?; - //println!("c: {c:?}"); - //let a: Vec<_> = path.to_str().unwrap().to_string().chars().collect(); - //let b: String = a[27..(a.len() - 4)].iter().collect(); - //let img_id: i32 = b.parse()?; - let path = format!("{path:?}"); - let path = path[1..(path.len() - 1)].to_owned(); - let img: Mat = imread(&find_file(&path, false, false)?, IMREAD_COLOR)?; - // highgui::imshow(&path, &img)?; - imgs.push((img_id, img)); - } - - imgs.sort_by(|v1, v2| { - if v1.0 > v2.0 { - std::cmp::Ordering::Greater - } else if v1.0 == v2.0 { - std::cmp::Ordering::Equal - } else { - std::cmp::Ordering::Less - } - }); - - //println!("Youpi"); - - for (i, m) in imgs.iter().enumerate() { - self.img.push(m.1.clone()); - //highgui::imshow(format!("img: {i}").as_str(), &m.1)?; - } - - //loop {} - - //prointln!(""); - - Ok(()) - } - - pub fn get_one_border( - &self, - background: &Mat, - bord: &Mat, - id: usize, - ) -> Result<((f64, f64), (f64, f64))> { - let diff: Mat = image_diff(bord, background)?; - - //let (t1, s1, l1) = ( - // self.tresh.min_0 as f64, - // self.tresh.min_1 as f64, - // self.tresh.min_2 as f64, - //); - //let (t2, s2, l2) = ( - // self.tresh.max_0 as f64, - // self.tresh.max_1 as f64, - // self.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(&diff, &min, &max, &mut color_selected); - ////highgui::imshow(format!("mask: {id}").as_str(), &color_selected)?; - //let mut bord_treshed = Mat::default(); - //bitwise_and(&diff, &diff, &mut bord_treshed, &color_selected)?; - ////highgui::imshow(format!("diff & mask: {id}").as_str(), &bord_treshed)?; - - // Pass the image to gray - let mut diff_gray = Mat::default(); - cvt_color(&diff, &mut diff_gray, COLOR_BGR2GRAY, 0)?; - //cvt_color(&bord_treshed, &mut diff_gray, COLOR_BGR2GRAY, 0)?; - - // Apply Canny edge detector - let mut edges = Mat::default(); - canny( - &diff_gray, - &mut edges, - self.canny_v1 as f64, - self.canny_v2 as f64, - 3, - false, - )?; - let lines = probabilistic_hough(&edges, &self.hough_param, id)?; - //let ((x1, y1), (x2, y2)) = get_extermities(&lines, id); - Ok(get_extermities(&lines, id)) - } -} - -fn get_point_to_draw( - r: u8, - g: u8, - b: u8, - color: Color, -) -> ( - Point, - Point, - Point, - Point, - Point, - Point, - Point, - Point, - Point, - Point, - Point, - Point, -) { - let p0 = Point { - x: 0., - y: 0., - color, - }; - let p1 = Point { - x: 4095., - y: 0., - color, - }; - let p2 = Point { - x: 4095., - y: 4095., - color, - }; - let p3 = Point { - x: 0., - y: 4095., - color, - }; - let p4 = Point { - x: 0., - y: 1000., - color: Color { r, g: 0, b: 0 }, - }; - let p5 = Point { - x: 4095., - y: 1000., - color: Color { r, g: 0, b: 0 }, - }; - let p6 = Point { - x: 0., - y: 2000., - color: Color { r: 0, g, b: 0 }, - }; - let p7 = Point { - x: 4095., - y: 2000., - color: Color { r: 0, g, b: 0 }, - }; - let p8 = Point { - x: 0., - y: 3000., - color: Color { r: 0, g: 0, b }, - }; - let p9 = Point { - x: 4095., - y: 3000., - color: Color { r: 0, g: 0, b }, - }; - - let pa = Point { - x: 0., - y: 4095., - color, - }; - let pb = Point { - x: 4095., - y: 4095., - color, - }; - (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pa, pb) -} - -// ca c'est les donner manipuler par les slider -#[derive(Debug, Clone)] -pub struct HoughLine { - pub rho: i32, - pub theta: i32, - pub treshold: i32, - pub min_length: i32, - pub max_line_gap: i32, -} - -// ca c'est les donner qu'on envoie a la fonction -pub struct HoughLineValue { - pub rho: f64, - pub theta: f64, - pub treshold: i32, - pub min_length: f64, - pub max_line_gap: f64, -} - -impl HoughLine { - pub fn get_param(&self) -> HoughLineValue { - HoughLineValue { - rho: self.rho as f64 / 100., - theta: self.theta as f64 / 100. * PI / 180., - treshold: self.treshold, - min_length: self.min_length as f64 / 100., - max_line_gap: self.max_line_gap as f64 / 100., - } - } -} - -#[derive(Clone, Debug)] -pub struct Treshold { - pub win_name: String, - pub min_0: i32, - pub min_1: i32, - pub min_2: i32, - pub max_0: i32, - pub max_1: i32, - pub max_2: i32, -} - -impl Treshold { - pub fn new(name: &str, min: i32, max: i32) -> Result { - let tresh = Treshold { - win_name: name.to_owned(), - min_0: min, - min_1: min, - min_2: min, - max_0: max, - max_1: max, - max_2: max, - }; - - Ok(tresh) - } -} - -pub fn get_lines( - background: &Mat, - bord: &Mat, - id: usize, - canny_v1: i32, - canny_v2: i32, - hough_param: &HoughLine, -) -> Result>> { - let diff: Mat = image_diff(bord, background)?; - - // Pass the image to gray - let mut diff_gray = Mat::default(); - cvt_color(&diff, &mut diff_gray, COLOR_BGR2GRAY, 0)?; - // Apply Canny edge detector - let mut edges = Mat::default(); - canny( - &diff_gray, - &mut edges, - canny_v1 as f64, - canny_v2 as f64, - 3, - false, - )?; - let lines = probabilistic_hough(&edges, hough_param, id)?; - //let ((x1, y1), (x2, y2)) = get_extermities(&lines, id); - Ok(lines) } diff --git a/src/qualibration/annalyse.rs b/src/qualibration/annalyse.rs index 4e82325..05e2e37 100644 --- a/src/qualibration/annalyse.rs +++ b/src/qualibration/annalyse.rs @@ -1,7 +1,7 @@ use std::collections::HashSet; use std::f64::consts::PI; -use super::Qualibration; +use super::Param; use super::DEBUG; use crate::utils::Pt; //use opencv::prelude::MatTraitConst; @@ -25,9 +25,10 @@ opencv::not_opencv_branch_4! { use opencv::core::LINE_AA; } -use super::Treshold; +use super::param::Treshold; const MAX_TRACKBAR: i32 = 255; +#[allow(dead_code)] pub fn draw_histograme_dbg( window_name: &str, histo: &Vec, @@ -66,6 +67,7 @@ pub fn draw_histograme_dbg( Ok(()) } +#[allow(dead_code)] pub fn draw_histograme(window_name: &str, histo: &Vec) -> Result<()> { let v: VecN = VecN::new(0., 0., 0., 255.); let color: VecN = VecN::new(255., 255., 255., 255.); @@ -104,6 +106,7 @@ pub fn draw_histograme(window_name: &str, histo: &Vec) -> Result<()> { Ok(()) } +#[allow(dead_code)] pub fn draw_histograme_bgr(window_name: &str, histo: &Vec>) -> Result<()> { let v: VecN = VecN::new(0., 0., 0., 255.); let b: VecN = VecN::new(255., 0., 0., 255.); @@ -196,6 +199,7 @@ pub fn draw_histograme_bgr_tresh( } // limit = 0.35 c'est bien +#[allow(dead_code)] pub fn is_same_frame(frame: &Mat, frame_prev: &Mat) -> Result { let nb_liss: i32 = 50; // plus on lisse la courbe plus on attein la limite facilement let limit = 0.45; // plus c'est haut, plus on tolere de changement entre 2 image @@ -289,7 +293,7 @@ pub fn get_horizontal_segment(m: &Mat) -> Result Result Result> { +pub fn get_vertical_segment(m: &Mat) -> Result> { // on va faire un histogram des point selon leur position en y // ca permetera des les differencier // on fait cette histo gramme pour connaitre ces plage de valeur en y @@ -452,7 +456,7 @@ pub fn get_vertical_segment(m: &Mat) -> Result> { // TODO: La selection des pixel pour chaque illot pourrait etre ameliorer // En fait elle me va bien. C'est vrai que il ne sont pas ouf mais bon... let mut segments = vec![]; - for (i, iland) in segment_iland_pt.iter().enumerate() { + for (_i, iland) in segment_iland_pt.iter().enumerate() { let mut center = Pt { x: 0., y: 0. }; for p in iland { center += *p; @@ -460,7 +464,7 @@ pub fn get_vertical_segment(m: &Mat) -> Result> { center /= iland.len() as f64; let max_deg = 360; - let (mut err_min, mut rad_min, mut x_min) = (f64::MAX, 0., f64::MAX); + let (mut _err_min, mut rad_min, mut x_min) = (f64::MAX, 0., f64::MAX); let mut iland_min = vec![]; for deg in 0..max_deg { let rad = (deg as f64) / (max_deg as f64) * PI * 2.; @@ -472,7 +476,7 @@ pub fn get_vertical_segment(m: &Mat) -> Result> { x: -y_axis.y, y: y_axis.x, }; - let mut err = 0.; + let mut _err = 0.; let mut tmp_iland = vec![]; let mut x_abs_max = f64::MIN; for pt in iland { @@ -481,7 +485,7 @@ pub fn get_vertical_segment(m: &Mat) -> Result> { x: p.cross(&x_axis), y: p.cross(&y_axis), }; - err += p.x * p.x; + _err += p.x * p.x; tmp_iland.push(p); if x_abs_max < p.x.abs() { x_abs_max = p.x.abs(); @@ -492,8 +496,8 @@ pub fn get_vertical_segment(m: &Mat) -> Result> { rad_min = rad; iland_min = tmp_iland; } - //if err < err_min { - // err_min = err; + //if _err < _err_min { + // err_min = _err; // rad_min = rad; // iland_min = tmp_iland; //} @@ -534,14 +538,18 @@ pub fn get_vertical_segment(m: &Mat) -> Result> { let pt_up_2 = pt_down + (pt_up - pt_down) * 1.5; let pt_down_2 = pt_up + (pt_down - pt_up) * 1.5; segments.push(( - (pt_down_2.x as f32, pt_down_2.y as f32), - (pt_up_2.x as f32, pt_up_2.y as f32), + ( + (pt_down_2.x as f32, pt_down_2.y as f32), + (pt_up_2.x as f32, pt_up_2.y as f32), + ), + x_min as f32, )); } Ok(segments) } +#[allow(dead_code)] fn average_pt_i32(vals: &[(i32, i32)]) -> (f32, f32) { let (mut mean_x, mut mean_y) = (0., 0.); let len = vals.len() as f32; @@ -563,6 +571,7 @@ fn get_id_groups(limits: &Vec<(usize, usize)>, id: usize) -> Option { //return usize::MAX; // im lazy to have Option return... } +#[allow(dead_code)] pub fn annalyse_segment(m: &Mat) -> Result>> { // on recupere les coordoner des point selectioner let mut seg_pt = HashSet::from([]); @@ -582,7 +591,7 @@ pub fn annalyse_segment(m: &Mat) -> Result>> { let mut selected: HashSet<(i32, i32)> = seg_pt .iter() .filter_map(|(x, y)| { - for (k, (i, j)) in around_all.iter().enumerate() { + for (_k, (i, j)) in around_all.iter().enumerate() { if seg_pt.get(&(*x + i, *y + j)).is_none() { return Some((*x, *y)); } @@ -639,6 +648,7 @@ pub fn annalyse_segment(m: &Mat) -> Result>> { Ok(lines) } +#[allow(dead_code)] pub fn image_mean(frames: &[Mat]) -> Result { /* * Il faudrait pouvoir changer les matrice de type pour avoir des valeur plus grande @@ -799,7 +809,8 @@ pub fn first_invert(histo: &Vec) -> ((usize, f64), (usize, f64)) { ) } -pub fn trackbar_init_param(mem: &mut Qualibration, winname: &str) -> Result<()> { +#[allow(dead_code)] +pub fn trackbar_init_param(mem: &mut Param, winname: &str) -> Result<()> { named_window(winname, WINDOW_AUTOSIZE)?; highgui::move_window(winname, 20, 20)?; let v: VecN = VecN::new(0., 0., 0., 255.); @@ -815,7 +826,8 @@ pub fn trackbar_init_param(mem: &mut Qualibration, winname: &str) -> Result<()> Ok(()) } -pub fn trackbar_line_segment(mem: &mut Qualibration, winname: &str) -> Result<()> { +#[allow(dead_code)] +pub fn trackbar_line_segment(mem: &mut Param, winname: &str) -> Result<()> { //highgui let winname = format!("{}: {}", winname, 0); //"bord selected: 0"; named_window(winname.as_str(), WINDOW_AUTOSIZE)?; @@ -878,7 +890,8 @@ pub fn trackbar_line_segment(mem: &mut Qualibration, winname: &str) -> Result<() Ok(()) } -pub fn line_pos(mem: &mut Qualibration, winname: &str) -> Result<()> { +#[allow(dead_code)] +pub fn line_pos(mem: &mut Param, winname: &str) -> Result<()> { named_window(winname, WINDOW_AUTOSIZE)?; highgui::move_window(winname, 20, 20)?; let v: VecN = VecN::new(0., 0., 0., 255.); @@ -898,7 +911,7 @@ pub fn line_pos(mem: &mut Qualibration, winname: &str) -> Result<()> { Ok(()) } -pub fn adding_trackbar(mut mem: &mut Qualibration, winname: &str) -> Result<()> { +pub fn adding_trackbar(mem: &mut Param, _winname: &str) -> Result<()> { //println!("winname: {winname}"); //line_pos(&mut mem, "Play Line")?; //trackbar_init_param(mem, "init_param")?; diff --git a/src/qualibration/borders.rs b/src/qualibration/borders.rs index 1302317..78543b2 100644 --- a/src/qualibration/borders.rs +++ b/src/qualibration/borders.rs @@ -1,4 +1,4 @@ -use super::HoughLine; +use super::param::HoughLine; use crate::utils::{CartesianEquation, EqAffine, Pt}; use opencv::core::{add, subtract, Mat, VecN, Vector, CV_8UC3}; //use opencv::prelude::MatTraitConst; @@ -7,6 +7,7 @@ use opencv::prelude::*; //MatTraitConst; use opencv::types::VectorOfVec4i; use opencv::Result; +#[allow(dead_code)] pub fn mix_borders(background: &Mat, borders: Vec) -> Result { let (row, col) = (background.rows(), background.cols()); //let mask = Mat::default(); @@ -74,8 +75,9 @@ pub fn bord_mult(pt: Vec<(f64, f64)>, factor: f64) -> Vec<(f64, f64)> { } // en fait ca marche pas dutout...next time +#[allow(dead_code)] pub fn bord_mult_v2(pt: Vec<(f64, f64)>, factor: f64) -> Vec<(f64, f64)> { - let mut pt: Vec = pt.iter().map(|p| Pt::from(p)).collect(); + let pt: Vec = pt.iter().map(|p| Pt::from(p)).collect(); let mut pn = vec![]; for i in 0..pt.len() { @@ -159,7 +161,7 @@ pub fn get_extermities(lines: &Vector>, id: usize) -> ((f64, f64), pub fn probabilistic_hough( edges: &Mat, hough_param: &HoughLine, - id: usize, + _id: usize, ) -> Result>> { let mut p_lines = VectorOfVec4i::new(); let mut probabalistic_hough = Mat::default(); diff --git a/src/qualibration/compute_image.rs b/src/qualibration/compute_image.rs index 910047b..ebee19b 100644 --- a/src/qualibration/compute_image.rs +++ b/src/qualibration/compute_image.rs @@ -1,4 +1,4 @@ -use super::Treshold; +use super::param::Treshold; use opencv::core::{self, bitwise_and, in_range, Mat, Scalar, Size_}; use opencv::imgproc; use opencv::Result; @@ -31,6 +31,7 @@ pub fn image_treshold(img: &Mat, tresh: &Treshold) -> Result { Ok(bord_treshed) } +#[allow(dead_code)] pub fn image_warp_treshold( img: &Mat, homography: &Mat, diff --git a/src/qualibration/param.rs b/src/qualibration/param.rs new file mode 100644 index 0000000..52f4487 --- /dev/null +++ b/src/qualibration/param.rs @@ -0,0 +1,185 @@ +use opencv::imgcodecs::{imread, imwrite, IMREAD_COLOR}; +use opencv::{ + core::{find_file, Mat, Size, Size_, Vector}, + Result, +}; +use std::f64::consts::PI; +use std::fs::{create_dir, read_dir}; +use std::time::Instant; + +#[derive(Clone, Debug)] +pub struct Param { + pub seq_id: usize, + pub imgs: Vec>, + pub dst_size: i32, + pub r: i32, + pub g: i32, + pub b: i32, + pub nb_all: i32, + pub nb_visible: i32, + pub nb_wait: i32, + pub nb_liss: i32, + pub tresh: Treshold, + pub canny_v1: i32, + pub canny_v2: i32, + pub hough_param: HoughLine, + pub border_pt: Vec<(f64, f64)>, + pub homography: Mat, + pub h_size: Size_, + pub line_pos: Vec, + pub multiple: u16, // le nombre de fois qu'une photo est prise pour certaine sequence + pub key: i32, + pub dir_name: String, + pub begin: Instant, + pub capture_mode: bool, +} + +impl Param { + pub fn new(dir_name: String) -> Result { + Ok(Self { + begin: std::time::Instant::now(), + capture_mode: dir_name.len() == 0, + dir_name, + key: -1, + imgs: vec![vec![]], + seq_id: 0, + dst_size: 900, + r: 150, + g: 0, + b: 0, + nb_all: 120, + nb_visible: 40, + nb_liss: 10, + nb_wait: 30, + tresh: Treshold::new("histogram", 160, 255)?, + canny_v1: 170, + canny_v2: 255, + hough_param: HoughLine { + rho: 100, + theta: 100, + treshold: 30, + min_length: 0, + max_line_gap: 50000, + }, + border_pt: vec![], + homography: Mat::default(), + h_size: Size::default(), + line_pos: vec![4095; 34], + multiple: 20, + }) + } + + pub fn save_image(&self) -> Result<()> { + let now = self.begin; + let img_root = format!("image"); + create_dir(&img_root).unwrap_or(()); + let new_dir = format!( + "{img_root}/{:0>6?}_{:0>9?}", + now.elapsed().as_millis(), + now.elapsed().as_nanos() + ); + create_dir(&new_dir).unwrap_or(()); + for (i, img_seq) in self.imgs.iter().enumerate() { + let seq_dir_name = format!("{new_dir}/{i}"); + create_dir(&seq_dir_name).unwrap_or(()); + for img in img_seq { + let mut name_img = format!("{seq_dir_name}/"); + name_img.push_str(&format!("img_{i}.png")); + imwrite(&name_img, img, &Vector::from_slice(&[6, 6, 6, 0]))?; + } + } + + Ok(()) + } + + pub fn load_image(&mut self) -> Result<(), Box> { + let mut imgs = vec![]; + let paths = read_dir(&self.dir_name)?; + for entry in paths { + let mut seq_img = vec![]; + let dir = entry?; + let path = dir.path(); // sequence directory + let names: Vec<&str> = path.to_str().unwrap().split("/").collect(); + let seq_id: usize = names[names.len() - 1].parse()?; + for entry in read_dir(&path)? { + let sub_path = entry?.path(); + let names: Vec<&str> = path.to_str().unwrap().split("/").collect(); + let img_name = names[names.len() - 1]; + let img_id: usize = img_name[4..img_name.len() - 4].parse()?; + let img: Mat = imread( + &find_file(&sub_path.to_str().unwrap(), false, false)?, + IMREAD_COLOR, + )?; + seq_img.push((img_id, img)); + } + imgs.push((seq_id, seq_img)); + } + + self.imgs = vec![vec![]; imgs.len()]; + for (seq_id, seq_img) in imgs { + self.imgs[seq_id] = vec![Mat::default(); seq_img.len()]; + for (img_id, img) in seq_img { + self.imgs[seq_id][img_id] = img; + } + } + + Ok(()) + } +} + +#[derive(Debug, Clone)] +pub struct HoughLine { + pub rho: i32, + pub theta: i32, + pub treshold: i32, + pub min_length: i32, + pub max_line_gap: i32, +} + +// ca c'est les donner qu'on envoie a la fonction +pub struct HoughLineValue { + pub rho: f64, + pub theta: f64, + pub treshold: i32, + pub min_length: f64, + pub max_line_gap: f64, +} + +impl HoughLine { + pub fn get_param(&self) -> HoughLineValue { + HoughLineValue { + rho: self.rho as f64 / 100., + theta: self.theta as f64 / 100. * PI / 180., + treshold: self.treshold, + min_length: self.min_length as f64 / 100., + max_line_gap: self.max_line_gap as f64 / 100., + } + } +} + +#[derive(Clone, Debug)] +pub struct Treshold { + pub win_name: String, + pub min_0: i32, + pub min_1: i32, + pub min_2: i32, + pub max_0: i32, + pub max_1: i32, + pub max_2: i32, +} + +impl Treshold { + pub fn new(name: &str, min: i32, max: i32) -> Result { + let tresh = Treshold { + win_name: name.to_owned(), + min_0: min, + min_1: min, + min_2: min, + max_0: max, + max_1: max, + max_2: max, + }; + + Ok(tresh) + } +} diff --git a/src/qualibration/sequence.rs b/src/qualibration/sequence.rs new file mode 100644 index 0000000..4d543be --- /dev/null +++ b/src/qualibration/sequence.rs @@ -0,0 +1,27 @@ +use super::Param; +use crate::point::Point; + +mod init_border; +mod init_idcode; +mod line_dotted; +mod load_image; +mod save_image; +mod wait_space; +pub use init_border::InitBorder; +pub use init_idcode::InitIdcode; +pub use line_dotted::LineDotted; +pub use load_image::LoadImage; +pub use save_image::SaveImage; +pub use wait_space::WaitSpace; + +pub trait Sequence { + fn draw(&self, mem: &Param) -> Option>; + fn compute_sequence(&mut self, mem: &mut Param) -> Result<(), Box>; + fn is_capture(&self) -> bool; +} + +impl std::fmt::Debug for dyn Sequence { + fn fmt(self: &Self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{self:?}") + } +} diff --git a/src/qualibration/sequence/init_border.rs b/src/qualibration/sequence/init_border.rs new file mode 100644 index 0000000..bcdd4e6 --- /dev/null +++ b/src/qualibration/sequence/init_border.rs @@ -0,0 +1,212 @@ +use crate::draw::draw_line; +use crate::point::{Color, Point}; +use crate::qualibration::{ + param::{HoughLine, Param}, + Sequence, +}; + +use crate::qualibration::annalyse::image_diff; +use crate::qualibration::borders::{ + bord_mult, get_extermities, get_intersection, probabilistic_hough, +}; + +use opencv::{ + calib3d, + core::{Mat, Point as OcvPoint, Size, VecN, Vector}, + imgproc::{canny, cvt_color, COLOR_BGR2GRAY}, + Result, +}; + +opencv::opencv_branch_4! { + #[allow(unused)] + use opencv::imgproc::LINE_AA; +} +opencv::not_opencv_branch_4! { + use opencv::core::LINE_AA; +} + +#[derive(Debug, Clone, Copy)] +pub struct InitBorder { + finished: bool, + cnt: usize, + borders: [Point; 4], +} + +impl InitBorder { + pub fn new(beg: Point, end: Point) -> Self { + InitBorder { + borders: [ + Point { + x: beg.x, + y: beg.y, + color: end.color, + }, + Point { + x: end.x, + y: beg.y, + color: end.color, + }, + Point { + x: end.x, + y: end.y, + color: end.color, + }, + Point { + x: beg.x, + y: end.y, + color: end.color, + }, + ], + cnt: 0, + finished: false, + } + } +} + +impl Sequence for InitBorder { + //type Obj = Self; + + fn draw(&self, mem: &Param) -> Option> { + if self.cnt > self.borders.len() { + return None; + } + if self.cnt == self.borders.len() { + return Some(vec![]); + } + + let color = Color { + r: mem.r as u8, + g: mem.g as u8, + b: mem.b as u8, + }; + let id1 = (self.cnt + 1) % self.borders.len(); + let p0 = Point { + color, + ..self.borders[self.cnt] + }; + let p1 = Point { + color, + ..self.borders[id1] + }; + Some(draw_line( + &p0, + &p1, + mem.nb_all as usize, + mem.nb_visible as usize, + )) + } + + fn compute_sequence(&mut self, mem: &mut Param) -> Result<(), Box> { + if self.cnt < self.borders.len() { + self.cnt += 1; + return Ok(()); + } + + let len = self.borders.len(); + let imgs = mem.imgs[mem.seq_id].clone(); + let borders: Vec = imgs[..len].into(); + let background = imgs[len].clone(); + + // on recupere chaqu'un des 4 bord + let mut bords_pts = vec![]; + for (id, bord) in borders.iter().enumerate() { + let lines = get_lines( + &background, + &bord, + id, + mem.canny_v1, + mem.canny_v2, + &mem.hough_param, + )?; + let bord_pt = get_extermities(&lines, id); + bords_pts.push(bord_pt); + } + + // on calcul le cadre + let border_pt = get_intersection(&bords_pts); + mem.border_pt = bord_mult(border_pt, 1.1); + + //// on dessine le cadre + //let color: VecN = VecN::new(255., 128., 0., 255.); + //let mut mixed = mix_borders(&background, borders)?; + //let b = &mem.border_pt; + //for i in 0..b.len() { + // let j = (i + 1) % mem.border_pt.len(); + // let pa = VecN::from_array([b[i].0 as i32, b[i].1 as i32]); + // let pb = VecN::from_array([b[j].0 as i32, b[j].1 as i32]); + // let a = OcvPoint::from_vec2(pa); + // let b = OcvPoint::from_vec2(pb); + // line(&mut mixed, a, b, color, 1, LINE_AA, 0)?; + //} + //highgui::imshow("mixed bored", &mixed)?; + + // on calcule l'homography + let size = mem.dst_size; + // ici on va requadrer la partie de la projection laser de l'image + let warped_image_size = Size::new(size, size); + let roi_corners: Vec = mem + .border_pt + .iter() + .map(|(x, y)| OcvPoint::new(*x as i32, *y as i32)) + .collect(); + //let dst = [(0, 0), (0, size), (size, size), (size, 0)]; // in: laser repere + let dst = [(0, size), (0, 0), (size, 0), (size, size)]; + let dst_corners: Vec = dst.iter().map(|(x, y)| OcvPoint::new(*x, *y)).collect(); + let roi_corners_mat = Mat::from_slice(&roi_corners[..])?; + let dst_corners_mat = Mat::from_slice(&dst_corners)?; + let h = calib3d::find_homography( + &roi_corners_mat, + &dst_corners_mat, + &mut Mat::default(), + 0, + 3., + )?; //get homography + mem.homography = h.clone(); + mem.h_size = warped_image_size.clone(); + //let mut warped_image = Mat::default(); + //imgproc::warp_perspective( + // &mixed, + // &mut warped_image, + // &h, + // warped_image_size, + // imgproc::INTER_CUBIC, // I dont see difference with INTER_CUBIC + // core::BORDER_CONSTANT, + // Scalar::default(), + //)?; // do perspective transformation + //highgui::imshow("Warped Image", &warped_image)?; + self.finished = true; + Ok(()) + } + + fn is_capture(&self) -> bool { + true + } +} + +pub fn get_lines( + background: &Mat, + bord: &Mat, + id: usize, + canny_v1: i32, + canny_v2: i32, + hough_param: &HoughLine, +) -> Result>> { + let diff: Mat = image_diff(bord, background)?; + + // Pass the image to gray + let mut diff_gray = Mat::default(); + cvt_color(&diff, &mut diff_gray, COLOR_BGR2GRAY, 0)?; + // Apply Canny edge detector + let mut edges = Mat::default(); + canny( + &diff_gray, + &mut edges, + canny_v1 as f64, + canny_v2 as f64, + 3, + false, + )?; + let lines = probabilistic_hough(&edges, hough_param, id)?; + //let ((x1, y1), (x2, y2)) = get_extermities(&lines, id); + Ok(lines) +} diff --git a/src/qualibration/sequence/init_idcode.rs b/src/qualibration/sequence/init_idcode.rs new file mode 100644 index 0000000..1fbd900 --- /dev/null +++ b/src/qualibration/sequence/init_idcode.rs @@ -0,0 +1,105 @@ +use crate::{ + draw::draw_line_dotted, + point::Point, + qualibration::{ + annalyse::{get_horizontal_segment, image_diff}, + compute_image::{image_treshold, image_warp}, + param::Param, + Sequence, + }, +}; + +use opencv::{ + core::{Point as OcvPoint, VecN}, + highgui, + imgproc::line, + Result, +}; + +opencv::opencv_branch_4! { + use opencv::imgproc::LINE_8; +} +opencv::not_opencv_branch_4! { + use opencv::core::LINE_AA; +} + +#[derive(Debug, Clone, Copy)] +pub struct InitIdcode { + finished: bool, + cnt: usize, + beg: Point, + end: Point, +} + +impl InitIdcode { + pub fn new(beg: Point, end: Point) -> InitIdcode { + InitIdcode { + finished: false, + cnt: 0, + beg, + end, + } + } +} + +impl Sequence for InitIdcode { + fn draw(&self, mem: &Param) -> Option> { + if self.finished { + return None; + } + if self.cnt == 0 { + return Some(vec![]); + } + let mut pl = vec![]; + pl.extend(draw_line_dotted( + &self.beg, + &self.end, + mem.nb_all as usize, + mem.nb_visible as usize, + true, + )); + Some(pl) + } + fn compute_sequence(&mut self, mem: &mut Param) -> Result<(), Box> { + if self.cnt == 0 { + self.cnt += 1; + return Ok(()); + } + let id = mem.seq_id; + let mut id_code_1 = image_diff(&mem.imgs[id][1], &mem.imgs[id][0])?; + + id_code_1 = image_warp(&id_code_1, &mem.homography, mem.h_size)?; + id_code_1 = image_treshold(&id_code_1, &mem.tresh)?; + + let code_seg_1 = get_horizontal_segment(&id_code_1)?; + let code_seg_1 = code_seg_1[1..(code_seg_1.len() - 1)].to_owned(); + + // on dessine + let color_1: VecN = VecN::new(255., 0., 0., 255.); + for i in 0..code_seg_1.len() { + let (((x0, y0), (x1, y1)), size) = code_seg_1[i]; + //line(&mut id_code_1, ); + let s = size as i32; + let x = ((x0 + x1) / 2.) as i32; + let y = ((y0 + y1) / 2.) as i32; + let a = OcvPoint::from_vec2(VecN::from_array([x, y - s])); + let b = OcvPoint::from_vec2(VecN::from_array([x, y + s])); + line(&mut id_code_1, a, b, color_1, 1, LINE_8, 0)?; + if i < (code_seg_1.len() - 1) { + let (((x2, _), _), _) = code_seg_1[i + 1]; + let x = ((x1 + x2) / 2.) as i32; + let y = ((y0 + y1) / 2.) as i32; + let a = OcvPoint::from_vec2(VecN::from_array([x, y - s])); + let b = OcvPoint::from_vec2(VecN::from_array([x, y + s])); + line(&mut id_code_1, a, b, color_1, 1, LINE_8, 0)?; + } + } + + highgui::imshow("code 1", &id_code_1)?; + self.finished = true; + Ok(()) + } + fn is_capture(&self) -> bool { + true + } +} diff --git a/src/qualibration/sequence/line_dotted.rs b/src/qualibration/sequence/line_dotted.rs new file mode 100644 index 0000000..b35a403 --- /dev/null +++ b/src/qualibration/sequence/line_dotted.rs @@ -0,0 +1,167 @@ +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> { + 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> { + 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 = 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 + } +} diff --git a/src/qualibration/sequence/load_image.rs b/src/qualibration/sequence/load_image.rs new file mode 100644 index 0000000..c723241 --- /dev/null +++ b/src/qualibration/sequence/load_image.rs @@ -0,0 +1,33 @@ +use super::{super::Param, Sequence}; +use crate::point::Point; +use opencv::Result; + +#[derive(Debug, Clone, Copy)] +pub struct LoadImage { + finished: bool, +} + +impl LoadImage { + pub fn new() -> LoadImage { + LoadImage { finished: false } + } +} + +impl Sequence for LoadImage { + fn draw(&self, _mem: &Param) -> Option> { + if self.finished { + return None; + } + Some(vec![]) + } + fn compute_sequence(&mut self, mem: &mut Param) -> Result<(), Box> { + if !mem.capture_mode { + mem.load_image()?; + } + self.finished = true; + Ok(()) + } + fn is_capture(&self) -> bool { + false + } +} diff --git a/src/qualibration/sequence/save_image.rs b/src/qualibration/sequence/save_image.rs new file mode 100644 index 0000000..1ddfec3 --- /dev/null +++ b/src/qualibration/sequence/save_image.rs @@ -0,0 +1,31 @@ +use super::{super::Param, Sequence}; +use crate::point::Point; +use opencv::Result; + +#[derive(Debug, Clone, Copy)] +pub struct SaveImage { + finished: bool, +} + +impl SaveImage { + pub fn new() -> SaveImage { + SaveImage { finished: false } + } +} + +impl Sequence for SaveImage { + fn draw(&self, _mem: &Param) -> Option> { + if self.finished { + return None; + } + Some(vec![]) + } + fn compute_sequence(&mut self, mem: &mut Param) -> Result<(), Box> { + mem.save_image()?; + self.finished = true; + Ok(()) + } + fn is_capture(&self) -> bool { + false + } +} diff --git a/src/qualibration/sequence/wait_space.rs b/src/qualibration/sequence/wait_space.rs new file mode 100644 index 0000000..db26bcf --- /dev/null +++ b/src/qualibration/sequence/wait_space.rs @@ -0,0 +1,176 @@ +use super::{super::Param, Sequence}; +use crate::{ + draw::{draw_line, draw_line_dotted}, + point::{Color, Point}, +}; + +use opencv::Result; + +#[derive(Debug, Clone, Copy)] +pub struct WaitSpace { + borders: [Point; 4], + red: [Point; 2], + green: [Point; 2], + blue: [Point; 2], +} + +impl WaitSpace { + pub fn new(beg: Point, end: Point) -> Self { + let red_y = (end.y - beg.y) * 1./5. + beg.y; + let green_y = (end.y - beg.y) * 2./5. + beg.y; + let blue_y = (end.y - beg.y) * 3./5. + beg.y; + Self { + borders: [ + Point { + x: beg.x, + y: beg.y, + color: end.color, + }, + Point { + x: end.x, + y: beg.y, + color: end.color, + }, + Point { + x: end.x, + y: end.y, + color: end.color, + }, + Point { + x: beg.x, + y: end.y, + color: end.color, + }, + ], + red: [ + Point { + x: beg.x, + y: red_y, + color: end.color, + }, + Point { + x: end.x, + y: red_y, + color: end.color, + }, + ], + blue: [ + Point { + x: beg.x, + y: blue_y, + color: end.color, + }, + Point { + x: end.x, + y: blue_y, + color: end.color, + }, + ], + green: [ + Point { + x: beg.x, + y: green_y, + color: end.color, + }, + Point { + x: end.x, + y: green_y, + color: end.color, + }, + ], + } + } +} + +impl Sequence for WaitSpace { + fn draw(&self, mem: &Param) -> Option> { + if mem.key == 32 || !mem.capture_mode { + return None; + } + + let mut pl = vec![]; + let color = Color { + r: mem.r as u8, + g: mem.g as u8, + b: mem.b as u8, + }; + let red = Color { + r: mem.r as u8, + g: 0, + b: 0, + }; + let green = Color { + r: 0, + g: mem.g as u8, + b: 0, + }; + let blue = Color { + r: 0, + g: 0, + b: mem.b as u8, + }; + for i in 0..self.borders.len() { + let id1 = (i + 1) % self.borders.len(); + let p0 = Point { + color, + ..self.borders[i] + }; + let p1 = Point { + color, + ..self.borders[id1] + }; + pl.extend(draw_line( + &p0, + &p1, + mem.nb_all as usize, + mem.nb_visible as usize, + )); + pl.extend(draw_line_dotted( + &Point{ + color: blue, + ..self.blue[0] + }, + &Point{ + color: blue, + ..self.blue[1] + }, + mem.nb_all as usize, + mem.nb_visible as usize, + true, + )); + pl.extend(draw_line_dotted( + &Point{ + color: green, + ..self.green[0] + }, + &Point{ + color: green, + ..self.green[1] + }, + mem.nb_all as usize, + mem.nb_visible as usize, + true, + )); + pl.extend(draw_line_dotted( + &Point{ + color: red, + ..self.red[0] + }, + &Point{ + color: red, + ..self.red[1] + }, + mem.nb_all as usize, + mem.nb_visible as usize, + true, + )); + } + Some(pl) + } + fn compute_sequence(&mut self, _mem: &mut Param) -> Result<(), Box> { + Ok(()) + } + fn is_capture(&self) -> bool { + false + } +} diff --git a/src/utils.rs b/src/utils.rs index b55aa46..1223c49 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,13 +1,7 @@ use crate::point::Point; static NEAR_ZERO: f64 = 0.000001; -use std::ops::Add; -use std::ops::AddAssign; -use std::ops::Div; -use std::ops::DivAssign; -use std::ops::Mul; -use std::ops::MulAssign; -use std::ops::Sub; +use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub}; //use std::ops::BitXor impl Add for Pt {