feat: dering refacto Qualibration and Sequence
This commit is contained in:
		
							parent
							
								
									910e340ec8
								
							
						
					
					
						commit
						392455e903
					
				
							
								
								
									
										37
									
								
								src/draw.rs
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								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<Vec<Point>, Box<dyn std::error::Error>> { | ||||
| ) -> Vec<Point> { | ||||
|     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<Vec<Point>, Box<dyn std::error::Error>> { | ||||
| pub fn draw_line(p0: &Point, p1: &Point, nb_all: usize, nb_visible: usize) -> Vec<Point> { | ||||
|     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<Vec<Point>, Box<dyn std::error::Error>> { | ||||
| pub fn draw(_time: f64) -> Vec<Point> { | ||||
|     let mut v: Vec<Point> = 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<Vec<Point>, Box<dyn std::error::Error>> { | ||||
|             }, | ||||
|         }); | ||||
|     } | ||||
|     Ok(v) | ||||
|     v | ||||
| } | ||||
|  | ||||
							
								
								
									
										68
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								src/main.rs
									
									
									
									
									
								
							| @ -1,3 +1,7 @@ | ||||
| //mod qualib_refacto;
 | ||||
| //use qualib_refacto;
 | ||||
| //use qualib_refacto::{self, Qualibration as Qualib};
 | ||||
| 
 | ||||
| ///
 | ||||
| /// Configure udev:
 | ||||
| /// https://github.com/Grix/helios_dac/blob/master/docs/udev_rules_for_linux.md
 | ||||
| @ -8,10 +12,10 @@ mod framerate; | ||||
| mod logs; | ||||
| mod point; | ||||
| 
 | ||||
| mod qualibration; | ||||
| mod qualib_refacto; | ||||
| mod utils; | ||||
| 
 | ||||
| use qualibration::{annalyse::adding_trackbar, Qualibration, Sequence}; | ||||
| use qualib_refacto::{annalyse::adding_trackbar, Qualibration, Sequence}; | ||||
| 
 | ||||
| use conf::Conf; | ||||
| use log::{/*debug,  warn, */ error, info}; | ||||
| @ -78,7 +82,7 @@ fn run_all() -> Result<(), Box<dyn std::error::Error>> { | ||||
|     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( | ||||
| @ -90,41 +94,43 @@ fn run_all() -> Result<(), Box<dyn std::error::Error>> { | ||||
|         //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( | ||||
|  | ||||
							
								
								
									
										313
									
								
								src/qualib_refacto.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								src/qualib_refacto.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,313 @@ | ||||
| //use opencv::Result;
 | ||||
| //use opencv::core::{self, Mat};
 | ||||
| 
 | ||||
| static DEBUG: bool = true; | ||||
| 
 | ||||
| pub mod annalyse; | ||||
| pub mod borders; | ||||
| pub mod compute_image; | ||||
| 
 | ||||
| use std::env::args; | ||||
| use std::time::Instant; | ||||
| 
 | ||||
| use crate::draw::{draw_line, draw_line_dotted}; | ||||
| use crate::point::{Color, Point}; | ||||
| 
 | ||||
| use enum_iterator::{next, Sequence as Seq}; | ||||
| use opencv::core::Mat; | ||||
| use opencv::Result; | ||||
| use std::f64::consts::PI; | ||||
| 
 | ||||
| use opencv::core::{bitwise_and, find_file, in_range, Point as OcvPoint, Scalar, Size, 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; | ||||
| 
 | ||||
| mod init_border; | ||||
| mod load_image; | ||||
| mod save_image; | ||||
| mod wait_space; | ||||
| use init_border::InitBorder; | ||||
| use load_image::LoadImage; | ||||
| use save_image::SaveImage; | ||||
| use wait_space::WaitSpace; | ||||
| 
 | ||||
| //impl Clone for dyn Sequence {
 | ||||
| //    fn clone() {
 | ||||
| //    }
 | ||||
| //}
 | ||||
| 
 | ||||
| #[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<Self> { | ||||
|         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) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| //impl
 | ||||
| 
 | ||||
| //#[derive(Copy)]
 | ||||
| pub trait Sequence { | ||||
|     fn draw(&self, mem: &Param) -> Option<Vec<Point>>; | ||||
|     fn compute_sequence(&mut self, mem: &mut Param) -> Result<(), Box<dyn std::error::Error>>; | ||||
|     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:?}") | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct Param { | ||||
|     seq_id: usize, | ||||
|     imgs: Vec<Vec<Mat>>, | ||||
|     dst_size: i32, | ||||
|     r: i32, | ||||
|     g: i32, | ||||
|     b: i32, | ||||
|     nb_all: i32, | ||||
|     nb_visible: i32, | ||||
|     nb_liss: i32, | ||||
|     tresh: Treshold, | ||||
|     canny_v1: i32, | ||||
|     canny_v2: i32, | ||||
|     hough_param: HoughLine, | ||||
|     border_pt: Vec<(f64, f64)>, | ||||
|     homography: Mat, | ||||
|     h_size: Size_<i32>, | ||||
|     line_pos: Vec<i32>, | ||||
|     multiple: u16, // le nombre de fois qu'une photo est prise pour certaine sequence
 | ||||
|     pub key: i32, | ||||
|     dir_name: String, | ||||
|     begin: Instant, | ||||
|     pub capture_mode: bool, | ||||
| } | ||||
| 
 | ||||
| impl Param { | ||||
|     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(()) | ||||
|     } | ||||
| 
 | ||||
|     fn load_image(&mut self) -> Result<(), Box<dyn std::error::Error>> { | ||||
|         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)] | ||||
| pub struct Qualibration { | ||||
|     seq: Vec<Box<dyn Sequence>>, | ||||
|     cam: VideoCapture, | ||||
|     cnt: usize, | ||||
| 
 | ||||
|     pub param: Param, | ||||
| } | ||||
| 
 | ||||
| impl Qualibration { | ||||
|     pub fn new() -> Result<Self> { | ||||
|         //let v: Vec<Box<dyn Sequence>> = 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; | ||||
|         } | ||||
| 
 | ||||
|         let mut cam = videoio::VideoCapture::new(0, videoio::CAP_ANY)?; // 0 is the default camera                   ;
 | ||||
|         let opened_cam = videoio::VideoCapture::is_opened(&cam)?; | ||||
|         if !opened_cam { | ||||
|             panic!("Unable to open default camera!"); | ||||
|         } | ||||
| 
 | ||||
|         let mut frame = Mat::default(); | ||||
|         cam.read(&mut frame)?; | ||||
| 
 | ||||
|         let beg = Point::from((0., 0., 38400)); // r:150, v:0, b:0
 | ||||
|         let end = Point::from((4095., 4095., 38400)); // r:150, v:0, b:0
 | ||||
|         let seq: Vec<Box<dyn Sequence>> = vec![ | ||||
|             Box::new(LoadImage::new()), | ||||
|             Box::new(WaitSpace::new()), | ||||
|             Box::new(InitBorder::new(beg, end)), | ||||
|             Box::new(SaveImage::new()), | ||||
|         ]; | ||||
|         //let now = std::time::Instant::now();
 | ||||
|         Ok(Qualibration { | ||||
|             seq, | ||||
|             cam, | ||||
|             cnt: 0, | ||||
|             param: Param { | ||||
|                 begin: std::time::Instant::now(), | ||||
|                 dir_name: dir_name.clone(), | ||||
|                 capture_mode: dir_name.len() == 0, | ||||
|                 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, | ||||
|                 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 draw_sequence(&mut self) -> Option<Vec<Point>> { | ||||
|         if self.param.seq_id >= self.seq.len() { | ||||
|             return None; | ||||
|         } | ||||
| 
 | ||||
|         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![]); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         pl | ||||
|     } | ||||
| 
 | ||||
|     pub fn run_step(self: &mut Self) -> Result<(), Box<dyn std::error::Error>> { | ||||
|         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()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if frame.size()?.width > 0 || !self.param.capture_mode { | ||||
|             self.seq[self.param.seq_id].compute_sequence(&mut self.param)?; | ||||
|         } | ||||
| 
 | ||||
|         self.cnt += 1; | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
							
								
								
									
										968
									
								
								src/qualib_refacto/annalyse.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										968
									
								
								src/qualib_refacto/annalyse.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,968 @@ | ||||
| use std::collections::HashSet; | ||||
| use std::f64::consts::PI; | ||||
| 
 | ||||
| use super::Param; | ||||
| use super::DEBUG; | ||||
| use crate::utils::Pt; | ||||
| //use opencv::prelude::MatTraitConst;
 | ||||
| use opencv::prelude::*; //MatTraitConst;
 | ||||
| 
 | ||||
| use opencv::core::{add, subtract, Mat, Point as OcvPoint, Point3_, VecN, CV_8UC3}; | ||||
| use opencv::highgui::{self, create_trackbar, named_window, WINDOW_AUTOSIZE}; | ||||
| use opencv::imgproc::{cvt_color, line, COLOR_BGR2GRAY}; | ||||
| use opencv::Result; | ||||
| 
 | ||||
| #[derive(Clone, Copy)] | ||||
| enum Cnt { | ||||
|     Beg(usize), | ||||
|     End(usize), | ||||
| } | ||||
| 
 | ||||
| opencv::opencv_branch_4! { | ||||
|     use opencv::imgproc::LINE_AA; | ||||
| } | ||||
| opencv::not_opencv_branch_4! { | ||||
|     use opencv::core::LINE_AA; | ||||
| } | ||||
| 
 | ||||
| use super::Treshold; | ||||
| const MAX_TRACKBAR: i32 = 255; | ||||
| 
 | ||||
| pub fn draw_histograme_dbg( | ||||
|     window_name: &str, | ||||
|     histo: &Vec<f64>, | ||||
|     (from, to): (usize, usize), | ||||
| ) -> Result<()> { | ||||
|     let v: VecN<f64, 4> = VecN::new(0., 0., 0., 255.); | ||||
|     let c1: VecN<f64, 4> = VecN::new(128., 128., 128., 255.); | ||||
|     let c2: VecN<f64, 4> = VecN::new(255., 255., 255., 255.); | ||||
|     //let color: VecN<f64, 4> = VecN::new(255., 255., 255., 255.);
 | ||||
|     let mut img = Mat::new_rows_cols_with_default(256 * 2, 256 * 2, CV_8UC3, v)?; | ||||
| 
 | ||||
|     let mut max = 0.; | ||||
|     for i in 0..256 { | ||||
|         if histo[i] > max { | ||||
|             max = histo[i]; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     let v_log = 10.; | ||||
| 
 | ||||
|     for i in 0..255 { | ||||
|         let x1 = ((i + 0) * 2) as i32; | ||||
|         let x2 = ((i + 1) * 2) as i32; | ||||
|         let y1 = | ||||
|             ((histo[i + 0] as f64 + 1.).log(v_log) / (max as f64).log(v_log) * 2. * 256.) as i32; | ||||
|         let y2 = | ||||
|             ((histo[i + 1] as f64 + 1.).log(v_log) / (max as f64).log(v_log) * 2. * 256.) as i32; | ||||
|         let color = if i >= from && i <= to { c2 } else { c1 }; | ||||
|         let pt1 = OcvPoint::new(x1, y1); | ||||
|         let pt2 = OcvPoint::new(x2, y2); | ||||
|         line(&mut img, pt1, pt2, color, 1, LINE_AA, 0)?; | ||||
|     } | ||||
| 
 | ||||
|     highgui::imshow(window_name, &img)?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| pub fn draw_histograme(window_name: &str, histo: &Vec<f64>) -> Result<()> { | ||||
|     let v: VecN<f64, 4> = VecN::new(0., 0., 0., 255.); | ||||
|     let color: VecN<f64, 4> = VecN::new(255., 255., 255., 255.); | ||||
|     let mut img = Mat::new_rows_cols_with_default( | ||||
|         histo.len() as i32 * 2, | ||||
|         histo.len() as i32 * 2, | ||||
|         CV_8UC3, | ||||
|         v, | ||||
|     )?; | ||||
| 
 | ||||
|     let mut max = 0.; | ||||
|     for i in 0..(histo.len() - 1) { | ||||
|         if histo[i] > max { | ||||
|             max = histo[i]; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     let v_log = 10.; | ||||
| 
 | ||||
|     for i in 0..(histo.len() - 1) { | ||||
|         let x1 = ((i + 0) * 2) as i32; | ||||
|         let x2 = ((i + 1) * 2) as i32; | ||||
|         let y1 = ((histo[i + 0] as f64 + 1.).log(v_log) / (max as f64).log(v_log) | ||||
|             * 2. | ||||
|             * histo.len() as f64) as i32; | ||||
|         let y2 = ((histo[i + 1] as f64 + 1.).log(v_log) / (max as f64).log(v_log) | ||||
|             * 2. | ||||
|             * histo.len() as f64) as i32; | ||||
|         let pt1 = OcvPoint::new(x1, y1); | ||||
|         let pt2 = OcvPoint::new(x2, y2); | ||||
|         line(&mut img, pt1, pt2, color, 1, LINE_AA, 0)?; | ||||
|     } | ||||
| 
 | ||||
|     highgui::imshow(window_name, &img)?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| pub fn draw_histograme_bgr(window_name: &str, histo: &Vec<Vec<f64>>) -> Result<()> { | ||||
|     let v: VecN<f64, 4> = VecN::new(0., 0., 0., 255.); | ||||
|     let b: VecN<f64, 4> = VecN::new(255., 0., 0., 255.); | ||||
|     let g: VecN<f64, 4> = VecN::new(0., 255., 0., 255.); | ||||
|     let r: VecN<f64, 4> = VecN::new(0., 0., 255., 255.); | ||||
|     let color = vec![b, g, r]; | ||||
|     let mut img = Mat::new_rows_cols_with_default(256 * 2, 256 * 2, CV_8UC3, v)?; | ||||
| 
 | ||||
|     let mut range = vec![vec![f64::MAX, f64::MIN]; 3]; | ||||
|     for j in 0..3 { | ||||
|         for i in 0..256 { | ||||
|             if histo[j][i] > range[j][1] { | ||||
|                 range[j][1] = histo[j][i]; | ||||
|             } | ||||
|             if histo[j][i] < range[j][0] { | ||||
|                 range[j][0] = histo[j][i]; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     //let v_log = 10.;
 | ||||
| 
 | ||||
|     for j in 0..3 { | ||||
|         for i in 0..255 { | ||||
|             let x1 = ((i + 0) * 2) as i32; | ||||
|             let x2 = ((i + 1) * 2) as i32; | ||||
|             let y1 = ((histo[j][i + 0] + 1.).log10() / range[j][1].log10() * 2. * 256.) as i32; | ||||
|             let y2 = ((histo[j][i + 1] + 1.).log10() / range[j][1].log10() * 2. * 256.) as i32; | ||||
|             let pt1 = OcvPoint::new(x1, y1); | ||||
|             let pt2 = OcvPoint::new(x2, y2); | ||||
|             line(&mut img, pt1, pt2, color[j], 1, LINE_AA, 0)?; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     highgui::imshow(window_name, &img)?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| pub fn draw_histograme_bgr_tresh( | ||||
|     window_name: &str, | ||||
|     histo: &Vec<Vec<f64>>, | ||||
|     tresh: &Treshold, | ||||
| ) -> Result<()> { | ||||
|     let v: VecN<f64, 4> = VecN::new(0., 0., 0., 255.); | ||||
|     let b: VecN<f64, 4> = VecN::new(255., 0., 0., 255.); | ||||
|     let g: VecN<f64, 4> = VecN::new(0., 255., 0., 255.); | ||||
|     let r: VecN<f64, 4> = VecN::new(0., 0., 255., 255.); | ||||
|     let color1 = vec![b, g, r]; | ||||
|     let color2 = vec![b / 2., g / 2., r / 2.]; | ||||
|     let mut img = Mat::new_rows_cols_with_default(256 * 2, 256 * 2, CV_8UC3, v)?; | ||||
| 
 | ||||
|     let mut vmax = vec![f64::MIN; 3]; | ||||
|     for j in 0..histo.len() { | ||||
|         for i in 0..histo[j].len() { | ||||
|             if histo[j][i] > vmax[j] { | ||||
|                 vmax[j] = histo[j][i]; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     //let v_log = 10.;
 | ||||
|     let max: Vec<f64> = [tresh.max_0 as f64, tresh.max_1 as f64, tresh.max_2 as f64].into(); | ||||
|     let min: Vec<f64> = [tresh.min_0 as f64, tresh.min_1 as f64, tresh.min_2 as f64].into(); | ||||
| 
 | ||||
|     //println!("min: {min:?}\tmax: {max:?}");
 | ||||
| 
 | ||||
|     for j in 0..3 { | ||||
|         for i in 0..255 { | ||||
|             let x1 = ((i + 0) * 2) as i32; | ||||
|             let x2 = ((i + 1) * 2) as i32; | ||||
|             let y1 = ((histo[j][i + 0] + 1.).log10() / vmax[j].log10() * 2. * 256.) as i32; | ||||
|             let y2 = ((histo[j][i + 1] + 1.).log10() / vmax[j].log10() * 2. * 256.) as i32; | ||||
|             let pt1 = OcvPoint::new(x1, y1); | ||||
|             let pt2 = OcvPoint::new(x2, y2); | ||||
| 
 | ||||
|             //let val = (histo[j][i] + 1.).log10() / max[j].log10();
 | ||||
|             let (color, thickness) = if i as f64 >= min[j] && i as f64 <= max[j] { | ||||
|                 (color1[j], 2) | ||||
|             } else { | ||||
|                 (color2[j], 1) | ||||
|             }; | ||||
|             line(&mut img, pt1, pt2, color, thickness, LINE_AA, 0)?; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     highgui::imshow(window_name, &img)?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| // limit = 0.35 c'est bien
 | ||||
| pub fn is_same_frame(frame: &Mat, frame_prev: &Mat) -> Result<bool> { | ||||
|     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
 | ||||
| 
 | ||||
|     let d_bgr = image_diff(frame, frame_prev)?; | ||||
|     let histo = histogram_1d(&d_bgr, nb_liss)?; | ||||
|     let ((_id1, v1), (_id2, v2)) = first_invert(&histo); | ||||
| 
 | ||||
|     if DEBUG { | ||||
|         // on affiche l'image de la cam
 | ||||
|         highgui::imshow("cam image", frame)?; | ||||
|         // on affiche l'image de la cam
 | ||||
|         highgui::imshow("prev image", frame_prev)?; | ||||
|         // on affiche la difference
 | ||||
|         highgui::imshow("diff image", &d_bgr)?; | ||||
|         // on affiche l'histograme
 | ||||
|         let ids = ((128 - _id2), (128 + _id1)); | ||||
|         draw_histograme_dbg("histograme", &histo, ids)?; | ||||
|         // -- pour chaque image enregistrer on l'affiche ma ca se fait autre part
 | ||||
|     } | ||||
| 
 | ||||
|     if DEBUG { | ||||
|         println!("v1[{_id1}]:{v1}\tv2[{_id1}:{v2}"); | ||||
|     } | ||||
| 
 | ||||
|     if v1 >= limit || v2 >= limit { | ||||
|         println!("\t XXX DIFFERENT XXX"); | ||||
|         Ok(false) | ||||
|     } else { | ||||
|         println!("\t  :)   Same    (: "); | ||||
|         Ok(true) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // On cherche des segment regourper par ilot de point. chaque illot a une plage de valeur en y qui
 | ||||
| // lui est propre, aucun autre ilot aura des point dans une plage de valeurs d'un autre illot.
 | ||||
| pub fn get_horizontal_segment(m: &Mat) -> Result<Vec<(((f32, f32), (f32, f32)), f32)>> { | ||||
|     // 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
 | ||||
|     let mut seg_pt = HashSet::from([]); | ||||
|     let (cols, rows) = (m.cols(), m.rows()); | ||||
|     let mut histo_x = vec![0.; cols.max(rows) as usize]; | ||||
|     for j in 0..rows { | ||||
|         for i in 0..cols { | ||||
|             let v: &Point3_<u8> = m.at_2d(j, i)?; | ||||
|             if v.x != 0 && v.y != 0 && v.z != 0 { | ||||
|                 seg_pt.insert((i, j)); | ||||
|                 histo_x[i as usize] += 1.; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // on determine le debut et la fin de ces plage de valeur en x
 | ||||
|     let mut histo_limit = vec![]; | ||||
|     for i in (0..(histo_x.len() - 1)).rev() { | ||||
|         if histo_x[i] != 0. && histo_x[i + 1] == 0. { | ||||
|             histo_limit.push(Cnt::End(i)); | ||||
|         } | ||||
|         if histo_x[i] == 0. && histo_x[i + 1] != 0. { | ||||
|             histo_limit.push(Cnt::Beg(i + 1)); | ||||
|         } | ||||
|     } | ||||
|     let mut limits = vec![]; | ||||
|     for k in 0..(histo_limit.len() / 2) { | ||||
|         if let (Cnt::Beg(a), Cnt::End(b)) = (histo_limit[2 * k + 1], histo_limit[2 * k]) { | ||||
|             limits.push((a, b)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // on regroupe les point par illot.
 | ||||
|     let mut segment_iland = vec![vec![]; limits.len()]; | ||||
|     for (x, y) in seg_pt { | ||||
|         let id = get_id_groups(&limits, x as usize).unwrap(); | ||||
|         segment_iland[id].push((x, y)); | ||||
|     } | ||||
| 
 | ||||
|     // on transforme chaque point en pt: (f32, f32) -> Pt
 | ||||
|     // toujours avec la meme structure d'ilot.
 | ||||
|     let segment_iland_pt: Vec<Vec<Pt>> = segment_iland | ||||
|         .iter() | ||||
|         .map(|iland| { | ||||
|             iland | ||||
|                 .iter() | ||||
|                 .map(|(x, y)| Pt { | ||||
|                     x: *x as f64, | ||||
|                     y: *y as f64, | ||||
|                 }) | ||||
|                 .collect() | ||||
|         }) | ||||
|         .collect(); | ||||
| 
 | ||||
|     let mut segments = vec![]; | ||||
|     for (i, iland) in segment_iland_pt.iter().enumerate() { | ||||
|         let mut center = Pt { x: 0., y: 0. }; | ||||
|         for p in iland { | ||||
|             center += *p; | ||||
|         } | ||||
|         center /= iland.len() as f64; | ||||
| 
 | ||||
|         let max_deg = 360; | ||||
|         let (mut rad_min, mut y_min) = (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.; | ||||
|             let y_axis = Pt { | ||||
|                 x: rad.sin(), | ||||
|                 y: rad.cos(), | ||||
|             }; | ||||
|             let x_axis = Pt { | ||||
|                 x: -y_axis.y, | ||||
|                 y: y_axis.x, | ||||
|             }; | ||||
|             let mut tmp_iland = vec![]; | ||||
|             let mut y_abs_max = f64::MIN; | ||||
|             for pt in iland { | ||||
|                 let mut p = *pt - center; | ||||
|                 p = Pt { | ||||
|                     x: p.cross(&x_axis), | ||||
|                     y: p.cross(&y_axis), | ||||
|                 }; | ||||
|                 tmp_iland.push(p); | ||||
|                 if y_abs_max < p.y.abs() { | ||||
|                     y_abs_max = p.y.abs(); | ||||
|                 } | ||||
|             } | ||||
|             if y_abs_max < y_min { | ||||
|                 y_min = y_abs_max; | ||||
|                 rad_min = rad; | ||||
|                 iland_min = tmp_iland; | ||||
|             } | ||||
|         } | ||||
|         iland_min.sort_by(|pta, ptb| { | ||||
|             if pta.y < ptb.y { | ||||
|                 std::cmp::Ordering::Greater | ||||
|             } else if pta.y == ptb.y { | ||||
|                 if pta.x.abs() < ptb.x.abs() { | ||||
|                     std::cmp::Ordering::Greater | ||||
|                 } else if pta.x.abs() == ptb.x.abs() { | ||||
|                     std::cmp::Ordering::Equal | ||||
|                 } else { | ||||
|                     std::cmp::Ordering::Less | ||||
|                 } | ||||
|             } else { | ||||
|                 std::cmp::Ordering::Less | ||||
|             } | ||||
|         }); | ||||
|         let id1 = iland_min.len() / 2; | ||||
|         let id2 = iland_min.len() - id1; | ||||
|         let mean_r = Pt::mean(&iland_min[..id1]); | ||||
|         let mean_l = Pt::mean(&iland_min[id2..]); | ||||
|         //let mean_r = iland_min[0];
 | ||||
|         //let mean_l = iland_min.last().unwrap();
 | ||||
| 
 | ||||
|         let y_axis = Pt { | ||||
|             x: rad_min.sin(), | ||||
|             y: rad_min.cos(), | ||||
|         }; | ||||
|         let x_axis = Pt { | ||||
|             x: -y_axis.y, | ||||
|             y: y_axis.x, | ||||
|         }; | ||||
|         let pt_r = center + (y_axis * mean_r.y) + (x_axis * mean_r.x); | ||||
|         let pt_l = center + (y_axis * mean_l.y) + (x_axis * mean_l.x); | ||||
|         //segments.push(((pt_l.x as f32, pt_l.y as f32), (pt_r.x as f32, pt_r.y as f32)));
 | ||||
|         let pt_r_2 = pt_l + (pt_r - pt_l) * 1.5; | ||||
|         let pt_l_2 = pt_r + (pt_l - pt_r) * 1.5; | ||||
|         segments.push(( | ||||
|             ( | ||||
|                 ((pt_l_2.x as f32, pt_l_2.y as f32)), | ||||
|                 ((pt_r_2.x as f32, pt_r_2.y as f32)), | ||||
|             ), | ||||
|             y_min as f32, | ||||
|         )); | ||||
|     } | ||||
| 
 | ||||
|     Ok(segments) | ||||
| } | ||||
| 
 | ||||
| // On cherche des segment regourper par ilot de point. chaque illot a une plage de valeur en y qui
 | ||||
| // lui est propre, aucun autre ilot aura des point dans une plage de valeurs d'un autre illot.
 | ||||
| pub fn get_vertical_segment(m: &Mat) -> Result<Vec<((f32, f32), (f32, f32))>> { | ||||
|     // 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
 | ||||
|     let mut seg_pt = HashSet::from([]); | ||||
|     let (cols, rows) = (m.cols(), m.rows()); | ||||
|     let mut histo_y = vec![0.; cols.max(rows) as usize]; | ||||
|     for j in 0..rows { | ||||
|         for i in 0..cols { | ||||
|             let v: &Point3_<u8> = m.at_2d(j, i)?; | ||||
|             if v.x != 0 && v.y != 0 && v.z != 0 { | ||||
|                 seg_pt.insert((i, j)); | ||||
|                 histo_y[j as usize] += 1.; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // on determine le debut et la fin de ces palge de l=valeur en y
 | ||||
|     let mut histo_limit = vec![]; | ||||
|     for i in (0..(histo_y.len() - 1)).rev() { | ||||
|         if histo_y[i] != 0. && histo_y[i + 1] == 0. { | ||||
|             histo_limit.push(Cnt::End(i)); | ||||
|         } | ||||
|         if histo_y[i] == 0. && histo_y[i + 1] != 0. { | ||||
|             histo_limit.push(Cnt::Beg(i + 1)); | ||||
|         } | ||||
|     } | ||||
|     let mut limits = vec![]; | ||||
|     for k in 0..(histo_limit.len() / 2) { | ||||
|         if let (Cnt::Beg(a), Cnt::End(b)) = (histo_limit[2 * k + 1], histo_limit[2 * k]) { | ||||
|             limits.push((a, b)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // on regroupe les point par illot.
 | ||||
|     let mut segment_iland = vec![vec![]; limits.len()]; | ||||
|     for (x, y) in seg_pt { | ||||
|         let id = get_id_groups(&limits, y as usize).unwrap(); | ||||
|         segment_iland[id].push((x, y)); | ||||
|     } | ||||
| 
 | ||||
|     // on transforme chaque point en pt: (f32, f32) -> Pt
 | ||||
|     // toujours avec la meme structure d'ilot.
 | ||||
|     let segment_iland_pt: Vec<Vec<Pt>> = segment_iland | ||||
|         .iter() | ||||
|         .map(|iland| { | ||||
|             iland | ||||
|                 .iter() | ||||
|                 .map(|(x, y)| Pt { | ||||
|                     x: *x as f64, | ||||
|                     y: *y as f64, | ||||
|                 }) | ||||
|                 .collect() | ||||
|         }) | ||||
|         .collect(); | ||||
| 
 | ||||
|     //  Pour chaque ilot de pixel: on prend le centre, on cherche l'axe qui passe le plus au centre
 | ||||
|     //  de l'illot. Pour trouver cet axe, pour chaque pixel de l'ilot, on va calculer l'eccart au
 | ||||
|     //  carree avec cet axe. On selectionne l'axe qui a l'erreur la plus faible
 | ||||
|     //      TODO: peut etre un meileur algo de recheche de l'axe (dicotomie en partie)
 | ||||
|     //  En suite on tris ces pixel et on prend la moiter la plus haute et la moiter la plus basse
 | ||||
|     //  part raport a l'axe. On fait la mayenne des ces 2 groupe et on a les extremiter haute et
 | ||||
|     //  basse pour cet ilot de pixel. En suite on multiplie par 2 ce segement pour qui soit de la
 | ||||
|     //  taille de l'ilots.
 | ||||
|     //
 | ||||
|     //  TODO: La selection de l'axe qui passe au centre de l'ilot pourrauiut aussi etre meilleur
 | ||||
|     //          au lieux d'utiliser l'arreur, on pourrait regarder la valeur absolue de la coordoner x la plus petit
 | ||||
|     //          DONE=> j'ai tester une autre methode mais il y a plus d'erreur... mais
 | ||||
|     //          l'orientation des segment est pas mal. En gros l'orientation de l'axe n'est pas
 | ||||
|     //          toujours la meme. C'est du a la fonction de tris. La fonction ne s'execute pas dans
 | ||||
|     //          le meme ordre sur les valeur, Et quand 2 valeurs sont identique, elle peuvent etre
 | ||||
|     //          inter changer.
 | ||||
|     //  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() { | ||||
|         let mut center = Pt { x: 0., y: 0. }; | ||||
|         for p in iland { | ||||
|             center += *p; | ||||
|         } | ||||
|         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 iland_min = vec![]; | ||||
|         for deg in 0..max_deg { | ||||
|             let rad = (deg as f64) / (max_deg as f64) * PI * 2.; | ||||
|             let y_axis = Pt { | ||||
|                 x: rad.sin(), | ||||
|                 y: rad.cos(), | ||||
|             }; | ||||
|             let x_axis = Pt { | ||||
|                 x: -y_axis.y, | ||||
|                 y: y_axis.x, | ||||
|             }; | ||||
|             let mut err = 0.; | ||||
|             let mut tmp_iland = vec![]; | ||||
|             let mut x_abs_max = f64::MIN; | ||||
|             for pt in iland { | ||||
|                 let mut p = *pt - center; | ||||
|                 p = Pt { | ||||
|                     x: p.cross(&x_axis), | ||||
|                     y: p.cross(&y_axis), | ||||
|                 }; | ||||
|                 err += p.x * p.x; | ||||
|                 tmp_iland.push(p); | ||||
|                 if x_abs_max < p.x.abs() { | ||||
|                     x_abs_max = p.x.abs(); | ||||
|                 } | ||||
|             } | ||||
|             if x_abs_max < x_min { | ||||
|                 x_min = x_abs_max; | ||||
|                 rad_min = rad; | ||||
|                 iland_min = tmp_iland; | ||||
|             } | ||||
|             //if err < err_min {
 | ||||
|             //    err_min = err;
 | ||||
|             //    rad_min = rad;
 | ||||
|             //    iland_min = tmp_iland;
 | ||||
|             //}
 | ||||
|         } | ||||
|         iland_min.sort_by(|pta, ptb| { | ||||
|             if pta.y < ptb.y { | ||||
|                 std::cmp::Ordering::Greater | ||||
|             } else if pta.y == ptb.y { | ||||
|                 if pta.x.abs() < ptb.x.abs() { | ||||
|                     std::cmp::Ordering::Greater | ||||
|                 } else if pta.x.abs() == ptb.x.abs() { | ||||
|                     std::cmp::Ordering::Equal | ||||
|                 } else { | ||||
|                     std::cmp::Ordering::Less | ||||
|                 } | ||||
|             } else { | ||||
|                 std::cmp::Ordering::Less | ||||
|             } | ||||
|         }); | ||||
|         let id1 = iland_min.len() / 2; | ||||
|         let id2 = iland_min.len() - id1; | ||||
|         let mean_up = Pt::mean(&iland_min[..id1]); | ||||
|         let mean_down = Pt::mean(&iland_min[id2..]); | ||||
|         //let mean_up = iland_min[0];
 | ||||
|         //let mean_down = iland_min.last().unwrap();
 | ||||
| 
 | ||||
|         let y_axis = Pt { | ||||
|             x: rad_min.sin(), | ||||
|             y: rad_min.cos(), | ||||
|         }; | ||||
|         let x_axis = Pt { | ||||
|             x: -y_axis.y, | ||||
|             y: y_axis.x, | ||||
|         }; | ||||
|         let pt_up = center + (y_axis * mean_up.y) + (x_axis * mean_up.x); | ||||
|         let pt_down = center + (y_axis * mean_down.y) + (x_axis * mean_down.x); | ||||
|         //segments.push(((pt_down.x as f32, pt_down.y as f32), (pt_up.x as f32, pt_up.y as f32)));
 | ||||
|         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), | ||||
|         )); | ||||
|     } | ||||
| 
 | ||||
|     Ok(segments) | ||||
| } | ||||
| 
 | ||||
| fn average_pt_i32(vals: &[(i32, i32)]) -> (f32, f32) { | ||||
|     let (mut mean_x, mut mean_y) = (0., 0.); | ||||
|     let len = vals.len() as f32; | ||||
| 
 | ||||
|     for (x, y) in vals { | ||||
|         mean_x += *x as f32; | ||||
|         mean_y += *y as f32; | ||||
|     } | ||||
|     (mean_x / len, mean_y / len) | ||||
| } | ||||
| 
 | ||||
| fn get_id_groups(limits: &Vec<(usize, usize)>, id: usize) -> Option<usize> { | ||||
|     for (id_seg, (min, max)) in limits.iter().enumerate() { | ||||
|         if id >= *min && id <= *max { | ||||
|             return Some(id_seg); | ||||
|         } | ||||
|     } | ||||
|     None | ||||
|     //return usize::MAX; // im lazy to have Option return...
 | ||||
| } | ||||
| 
 | ||||
| pub fn annalyse_segment(m: &Mat) -> Result<Vec<Vec<(i32, i32)>>> { | ||||
|     // on recupere les coordoner des point selectioner
 | ||||
|     let mut seg_pt = HashSet::from([]); | ||||
|     let (cols, rows) = (m.cols(), m.rows()); | ||||
|     for j in 0..rows { | ||||
|         for i in 0..cols { | ||||
|             let v: &Point3_<u8> = m.at_2d(j, i)?; | ||||
|             if v.x != 0 && v.y != 0 && v.z != 0 { | ||||
|                 seg_pt.insert((i, j)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // on garde que ceux qui sont frontiere
 | ||||
|     //let around_all = [(-1, -1), (-1, 0), (-1, 1), (0, 1), (1, 1), (1, 0), (1, -1), (0, -1)];
 | ||||
|     let around_all = [(-1, 0), (0, 1), (1, 0), (0, -1)]; | ||||
|     let mut selected: HashSet<(i32, i32)> = seg_pt | ||||
|         .iter() | ||||
|         .filter_map(|(x, y)| { | ||||
|             for (k, (i, j)) in around_all.iter().enumerate() { | ||||
|                 if seg_pt.get(&(*x + i, *y + j)).is_none() { | ||||
|                     return Some((*x, *y)); | ||||
|                 } | ||||
|             } | ||||
|             None | ||||
|         }) | ||||
|         .collect(); | ||||
| 
 | ||||
|     //let around = [(-1, 0), (0, -1), (1, 0), (0, 1), (-1, -1), (1, -1), (1, 1), (-1, 1)];
 | ||||
|     let around = [ | ||||
|         (-1, 1), | ||||
|         (0, 1), | ||||
|         (1, 1), | ||||
|         (1, 0), | ||||
|         (1, -1), | ||||
|         (0, -1), | ||||
|         (-1, -1), | ||||
|         (-1, 0), | ||||
|     ]; | ||||
|     let mut lines = vec![]; | ||||
|     while selected.len() > 0 { | ||||
|         let mut outed: HashSet<(i32, i32)> = HashSet::from([]); | ||||
|         let (x, y) = selected.iter().next().unwrap(); | ||||
|         let mut line = vec![(*x, *y)]; | ||||
| 
 | ||||
|         outed.insert((*x, *y)); | ||||
|         let mut last = 0; | ||||
|         'line: loop { | ||||
|             let (x, y) = line[line.len() - 1]; | ||||
|             for k in 0..around.len() { | ||||
|                 let (i, j) = around[(k + last) % around.len()]; | ||||
|                 if seg_pt.get(&(x + i, y + j)).is_some() && outed.get(&(x + i, y + j)).is_none() { | ||||
|                     line.push((x + i, y + j)); | ||||
|                     outed.insert((x + i, y + j)); | ||||
|                     last = k + last + around.len() - 2; | ||||
|                     // ici on pourrait cleaner le rest
 | ||||
|                     //for l in (k+1)..around.len() {
 | ||||
|                     //    let (i, j) = around[(l+last)%around.len()];
 | ||||
|                     //    outed.insert((x+i, y+j));
 | ||||
|                     //    //
 | ||||
|                     //}
 | ||||
|                     continue 'line; | ||||
|                 } | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         lines.push(line); | ||||
|         for (x, y) in outed { | ||||
|             selected.remove(&(x, y)); | ||||
|         } | ||||
|     } | ||||
|     println!("\nseg: {}", lines.len()); | ||||
|     Ok(lines) | ||||
| } | ||||
| 
 | ||||
| pub fn image_mean(frames: &[Mat]) -> Result<Mat> { | ||||
|     /* | ||||
|      * Il faudrait pouvoir changer les matrice de type pour avoir des valeur plus grande | ||||
|      * */ | ||||
|     let mut frames_big: Vec<Mat> = vec![]; | ||||
|     let len = frames.len() as i16; | ||||
| 
 | ||||
|     for frame in frames { | ||||
|         let mut tmp = Mat::default(); | ||||
|         frame.convert_to(&mut tmp, 19, 1., 0.)?; // 19 is for: CV_16SC3
 | ||||
|         frames_big.push(tmp); | ||||
|     } | ||||
| 
 | ||||
|     let mut img_sum: Mat = frames_big[0].clone(); | ||||
|     let mask = Mat::default(); | ||||
|     for frame in frames_big[1..].iter() { | ||||
|         let mut tmp = Mat::default(); | ||||
|         add(&img_sum, &frame, &mut tmp, &mask, -1)?; | ||||
|         img_sum = tmp; | ||||
|     } | ||||
| 
 | ||||
|     let (cols, rows) = (img_sum.cols(), img_sum.rows()); | ||||
|     for j in 0..rows { | ||||
|         for i in 0..cols { | ||||
|             let v: &mut Point3_<i16> = img_sum.at_2d_mut(j, i)?; | ||||
|             v.x /= len; | ||||
|             v.y /= len; | ||||
|             v.z /= len; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     let mut mean = Mat::default(); | ||||
|     img_sum.convert_to(&mut mean, 16, 1., 0.)?; // 16 is for: CV_8UC3
 | ||||
| 
 | ||||
|     Ok(mean) | ||||
| } | ||||
| 
 | ||||
| pub fn image_diff(frame: &Mat, frame_prev: &Mat) -> Result<Mat> { | ||||
|     let mut diff_bgr = Mat::default(); | ||||
|     let mut diff_bgr_2 = Mat::default(); | ||||
|     let mut d_bgr = Mat::default(); | ||||
|     let (row, col) = (frame.rows(), frame.cols()); | ||||
|     let mask = Mat::default(); | ||||
|     let v: VecN<f64, 4> = VecN::new(128., 128., 128., 128.); | ||||
|     let mid: Mat = Mat::new_rows_cols_with_default(row, col, CV_8UC3, v)?; | ||||
| 
 | ||||
|     // ca parait etonant d'enlever la difference dans l'autre sens mais paradoxalement, ca permet
 | ||||
|     // d'avoir toutes les valeur, pck a chaque fois les valeur negative sont mise a 0 dans
 | ||||
|     // l'operation de soustraction
 | ||||
|     subtract(frame, frame_prev, &mut diff_bgr, &mask, -1)?; | ||||
|     add(&diff_bgr, &mid, &mut diff_bgr_2, &mask, -1)?; | ||||
|     subtract(frame_prev, frame, &mut diff_bgr, &mask, -1)?; | ||||
|     subtract(&diff_bgr_2, &diff_bgr, &mut d_bgr, &mask, -1)?; | ||||
| 
 | ||||
|     Ok(d_bgr) | ||||
| } | ||||
| 
 | ||||
| pub fn histogram_3d(m: &Mat, nb_liss: i32) -> Result<Vec<Vec<f64>>> { | ||||
|     let (cols, rows) = (m.cols(), m.rows()); | ||||
|     let mut histo = vec![vec![0.; 256]; 3]; | ||||
| 
 | ||||
|     // on calcule l'histograme
 | ||||
|     for j in 0..rows { | ||||
|         for i in 0..cols { | ||||
|             let v: &Point3_<u8> = m.at_2d(j, i)?; | ||||
|             let (b, g, r) = (v.x as usize, v.y as usize, v.z as usize); | ||||
|             histo[2][r] += 1.; | ||||
|             histo[1][g] += 1.; | ||||
|             histo[0][b] += 1.; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // on lisse l'histograme
 | ||||
|     for j in 0..3 { | ||||
|         let mut tmp = histo[j].clone(); | ||||
|         for _ in 0..nb_liss { | ||||
|             for i in 1..(tmp.len() - 1) { | ||||
|                 histo[j][i] = (tmp[i - 1] + 1. * tmp[i] + tmp[i + 1]) / 3.; | ||||
|             } | ||||
|             tmp = histo[j].clone(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     Ok(histo) | ||||
| } | ||||
| 
 | ||||
| pub fn histogram_1d(m: &Mat, nb_liss: i32) -> Result<Vec<f64>> { | ||||
|     let (cols, rows) = (m.cols(), m.rows()); | ||||
|     let mut histo = vec![0; 256]; | ||||
|     let mut m_gray = Mat::default(); | ||||
| 
 | ||||
|     // on convertie en gris
 | ||||
|     cvt_color(m, &mut m_gray, COLOR_BGR2GRAY, 0)?; | ||||
|     // on calcule l'histograme
 | ||||
|     for j in 0..rows { | ||||
|         for i in 0..cols { | ||||
|             let v: &u8 = m_gray.at_2d(j, i)?; | ||||
|             let id = *v as usize; | ||||
|             histo[id] += 1; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // on lisse l'histograme
 | ||||
|     let mut histo: Vec<f64> = histo.iter().map(|x| *x as f64).collect(); | ||||
|     let mut tmp = histo.clone(); | ||||
|     for _ in 0..nb_liss { | ||||
|         for i in 1..(histo.len() - 1) { | ||||
|             histo[i] = (tmp[i - 1] + 2. * tmp[i] + tmp[i + 1]) / 4.; | ||||
|         } | ||||
|         tmp = histo.clone(); | ||||
|     } | ||||
| 
 | ||||
|     Ok(histo) | ||||
| } | ||||
| 
 | ||||
| pub fn first_invert(histo: &Vec<f64>) -> ((usize, f64), (usize, f64)) { | ||||
|     // on applique un log puis on normalise mar le log du max
 | ||||
|     let mut normalised = vec![0.; histo.len()]; | ||||
|     let mut p1 = vec![0.; histo.len() / 2]; | ||||
|     let mut p2 = vec![0.; histo.len() / 2]; | ||||
|     let mut dp1 = vec![0.; histo.len() / 2]; | ||||
|     let mut dp2 = vec![0.; histo.len() / 2]; | ||||
|     let mid = (histo.len() + 1) / 2; | ||||
|     let max = (histo[mid] as f64).log10(); // on par du principe que le max est au centre
 | ||||
| 
 | ||||
|     for i in 0..histo.len() { | ||||
|         normalised[i] = (histo[i] as f64 + 1.).log10() / max; | ||||
|     } | ||||
|     for i in (mid)..(histo.len() - 1) { | ||||
|         p1[i - mid] = mid as f64 * ((normalised[mid] - normalised[i + 1]) / (i - mid + 2) as f64); | ||||
|     } | ||||
|     for i in (1..mid).rev() { | ||||
|         p2[mid - i - 1] = mid as f64 * ((normalised[mid] - normalised[i]) / (mid - i) as f64); | ||||
|     } | ||||
|     for i in 0..(mid - 1) { | ||||
|         dp1[i] = p1[i + 1] - p1[i]; | ||||
|         dp2[i] = p2[i + 1] - p2[i]; | ||||
|     } | ||||
| 
 | ||||
|     let mut dist_1 = 0; | ||||
|     for (i, v) in dp1.iter().enumerate() { | ||||
|         if v < &0. { | ||||
|             dist_1 = i; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     let mut dist_2 = 0; | ||||
|     for (i, v) in dp2.iter().enumerate() { | ||||
|         if v < &0. { | ||||
|             dist_2 = i; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     ( | ||||
|         (dist_1, normalised[mid + dist_1]), | ||||
|         (dist_2, normalised[mid - dist_2]), | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| 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<f64, 4> = VecN::new(0., 0., 0., 255.); | ||||
|     let m = Mat::new_rows_cols_with_default(1, 1024, CV_8UC3, v)?; | ||||
|     highgui::imshow(winname, &m)?; | ||||
| 
 | ||||
|     create_trackbar("nb_all", winname, Some(&mut mem.nb_all), 400, None)?; | ||||
|     create_trackbar("nb_visible", winname, Some(&mut mem.nb_visible), 400, None)?; | ||||
|     create_trackbar("r", winname, Some(&mut mem.r), MAX_TRACKBAR, None)?; | ||||
|     create_trackbar("g", winname, Some(&mut mem.g), MAX_TRACKBAR, None)?; | ||||
|     create_trackbar("b", winname, Some(&mut mem.b), MAX_TRACKBAR, None)?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| 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)?; | ||||
|     highgui::move_window(winname.as_str(), 20, 520)?; | ||||
|     //highgui::move_window(winname, 20, 20)?;
 | ||||
|     let v: VecN<f64, 4> = VecN::new(0., 0., 0., 255.); | ||||
|     let m = Mat::new_rows_cols_with_default(1, 1800, CV_8UC3, v)?; | ||||
|     highgui::imshow(winname.as_str(), &m)?; | ||||
|     //
 | ||||
|     create_trackbar( | ||||
|         "canny min", | ||||
|         winname.as_str(), | ||||
|         Some(&mut mem.canny_v1), | ||||
|         MAX_TRACKBAR, | ||||
|         None, | ||||
|     )?; | ||||
|     create_trackbar( | ||||
|         "canny max", | ||||
|         winname.as_str(), | ||||
|         Some(&mut mem.canny_v2), | ||||
|         MAX_TRACKBAR, | ||||
|         None, | ||||
|     )?; | ||||
| 
 | ||||
|     create_trackbar( | ||||
|         "rho     : ", | ||||
|         winname.as_str(), | ||||
|         Some(&mut mem.hough_param.rho), | ||||
|         1000, | ||||
|         None, | ||||
|     )?; | ||||
|     create_trackbar( | ||||
|         "theta   : ", | ||||
|         winname.as_str(), | ||||
|         Some(&mut mem.hough_param.theta), | ||||
|         1000, | ||||
|         None, | ||||
|     )?; | ||||
|     create_trackbar( | ||||
|         "treshold: ", | ||||
|         winname.as_str(), | ||||
|         Some(&mut mem.hough_param.treshold), | ||||
|         255, | ||||
|         None, | ||||
|     )?; | ||||
|     create_trackbar( | ||||
|         "min_leng: ", | ||||
|         winname.as_str(), | ||||
|         Some(&mut mem.hough_param.min_length), | ||||
|         1000, | ||||
|         None, | ||||
|     )?; | ||||
|     create_trackbar( | ||||
|         "max_gap : ", | ||||
|         winname.as_str(), | ||||
|         Some(&mut mem.hough_param.max_line_gap), | ||||
|         50000, | ||||
|         None, | ||||
|     )?; | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| pub fn line_pos(mem: &mut Param, winname: &str) -> Result<()> { | ||||
|     named_window(winname, WINDOW_AUTOSIZE)?; | ||||
|     highgui::move_window(winname, 20, 20)?; | ||||
|     let v: VecN<f64, 4> = VecN::new(0., 0., 0., 255.); | ||||
|     let m = Mat::new_rows_cols_with_default(1, 1024, CV_8UC3, v)?; | ||||
|     highgui::imshow(winname, &m)?; | ||||
| 
 | ||||
|     for i in 0..mem.line_pos.len() { | ||||
|         create_trackbar( | ||||
|             format!("pt[{i}]:\t").as_str(), | ||||
|             winname, | ||||
|             Some(&mut mem.line_pos[i]), | ||||
|             4095, | ||||
|             None, | ||||
|         )?; | ||||
|     } | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| pub fn adding_trackbar(mut mem: &mut Param, winname: &str) -> Result<()> { | ||||
|     //println!("winname: {winname}");
 | ||||
|     //line_pos(&mut mem, "Play Line")?;
 | ||||
|     //trackbar_init_param(mem, "init_param")?;
 | ||||
| 
 | ||||
|     named_window("histo bgr", WINDOW_AUTOSIZE)?; | ||||
|     associate_trackbar("histo bgr", &mut mem.tresh)?; | ||||
|     create_trackbar( | ||||
|         "nb_liss", | ||||
|         "histo bgr", | ||||
|         Some(&mut mem.nb_liss), | ||||
|         MAX_TRACKBAR, | ||||
|         None, | ||||
|     )?; | ||||
| 
 | ||||
|     //trackbar_line_segment(mem, "line detector")?;
 | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| pub fn associate_trackbar(winname: &str, tresh: &mut Treshold) -> Result<()> { | ||||
|     create_trackbar( | ||||
|         "blue min: ", | ||||
|         winname, | ||||
|         Some(&mut tresh.min_0), | ||||
|         MAX_TRACKBAR, | ||||
|         None, | ||||
|     )?; | ||||
|     create_trackbar( | ||||
|         "blue max: ", | ||||
|         winname, | ||||
|         Some(&mut tresh.max_0), | ||||
|         MAX_TRACKBAR, | ||||
|         None, | ||||
|     )?; | ||||
| 
 | ||||
|     create_trackbar( | ||||
|         "green min: ", | ||||
|         winname, | ||||
|         Some(&mut tresh.min_1), | ||||
|         MAX_TRACKBAR, | ||||
|         None, | ||||
|     )?; | ||||
|     create_trackbar( | ||||
|         "green max: ", | ||||
|         winname, | ||||
|         Some(&mut tresh.max_1), | ||||
|         MAX_TRACKBAR, | ||||
|         None, | ||||
|     )?; | ||||
| 
 | ||||
|     create_trackbar( | ||||
|         "red min: ", | ||||
|         winname, | ||||
|         Some(&mut tresh.min_2), | ||||
|         MAX_TRACKBAR, | ||||
|         None, | ||||
|     )?; | ||||
|     create_trackbar( | ||||
|         "red max: ", | ||||
|         winname, | ||||
|         Some(&mut tresh.max_2), | ||||
|         MAX_TRACKBAR, | ||||
|         None, | ||||
|     )?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
							
								
								
									
										182
									
								
								src/qualib_refacto/borders.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								src/qualib_refacto/borders.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,182 @@ | ||||
| use super::HoughLine; | ||||
| use crate::utils::{CartesianEquation, EqAffine, Pt}; | ||||
| use opencv::core::{add, subtract, Mat, VecN, Vector, CV_8UC3}; | ||||
| //use opencv::prelude::MatTraitConst;
 | ||||
| use opencv::imgproc::{cvt_color, hough_lines_p, COLOR_GRAY2BGR}; | ||||
| use opencv::prelude::*; //MatTraitConst;
 | ||||
| use opencv::types::VectorOfVec4i; | ||||
| use opencv::Result; | ||||
| 
 | ||||
| pub fn mix_borders(background: &Mat, borders: Vec<Mat>) -> Result<Mat> { | ||||
|     let (row, col) = (background.rows(), background.cols()); | ||||
|     //let mask = Mat::default();
 | ||||
|     let v: VecN<f64, 4> = VecN::new(0., 0., 0., 0.); | ||||
|     let mut sum_diff_0 = Mat::new_rows_cols_with_default(row, col, CV_8UC3, v)?; | ||||
|     let mut sum_diff_1 = Mat::new_rows_cols_with_default(row, col, CV_8UC3, v)?; | ||||
|     let mask = Mat::default(); | ||||
|     let mut tmp = Mat::default(); | ||||
| 
 | ||||
|     // on va faire la somme des difference
 | ||||
|     // on va les ajouter a l'image du fond
 | ||||
|     for bord in borders { | ||||
|         //let diff = image_diff(&bord, background)?;
 | ||||
|         //add(&diff, &mid, &mut diff_bgr_2, &mask, -1)?;
 | ||||
|         let mut diff = Mat::default(); | ||||
|         subtract(&bord, background, &mut diff, &mask, -1)?; | ||||
|         add(&diff, &sum_diff_0, &mut tmp, &mask, -1)?; | ||||
|         sum_diff_0 = tmp.clone(); | ||||
| 
 | ||||
|         subtract(background, &bord, &mut diff, &mask, -1)?; | ||||
|         add(&diff, &sum_diff_1, &mut tmp, &mask, -1)?; | ||||
|         sum_diff_1 = tmp.clone(); | ||||
|     } | ||||
|     //let v: VecN<f64, 4> = VecN::new(128., 128., 128., 128.);
 | ||||
|     //let mid = Mat::new_rows_cols_with_default(row, col, CV_8UC3, v)?;
 | ||||
|     let mut tmp = Mat::default(); | ||||
|     //let mut tmp2 = Mat::default();
 | ||||
|     let mut mix = Mat::default(); | ||||
|     add(&sum_diff_0, &background, &mut tmp, &mask, -1)?; | ||||
|     subtract(&tmp, &sum_diff_1, &mut mix, &mask, -1)?; | ||||
| 
 | ||||
|     Ok(mix) | ||||
| } | ||||
| 
 | ||||
| //impl Add for (f64, f64) {
 | ||||
| //}
 | ||||
| pub fn bord_mult(pt: Vec<(f64, f64)>, factor: f64) -> Vec<(f64, f64)> { | ||||
|     let pt: Vec<Pt> = pt.iter().map(|p| Pt::from(p)).collect(); | ||||
| 
 | ||||
|     let mut pa = vec![]; | ||||
|     let mut pb = vec![]; | ||||
|     for i in 0..pt.len() { | ||||
|         let k = (i + pt.len() - 1) % pt.len(); | ||||
|         let j = (i + 1) % pt.len(); | ||||
|         pa.push((pt[i] - pt[j]) * factor + pt[j]); | ||||
|         pb.push((pt[i] - pt[k]) * factor + pt[k]); | ||||
|     } | ||||
| 
 | ||||
|     let mut eq = vec![]; | ||||
|     for i in 0..pt.len() { | ||||
|         let j = (i + 1) % pt.len(); | ||||
|         eq.push(CartesianEquation::new_from_pt(&pb[i], &pa[j])); | ||||
|     } | ||||
| 
 | ||||
|     let mut p_out = vec![]; | ||||
|     for i in 0..pt.len() { | ||||
|         let k = (i + pt.len() - 1) % pt.len(); | ||||
|         p_out.push(eq[i].intersection(&eq[k]).unwrap()); // TODO: faire un truc pour le unwrap...
 | ||||
|                                                          // normalement c'est un gars sur ta
 | ||||
|                                                          // compris ;)... mais bon... un alignement
 | ||||
|                                                          // malencontreux ca arrive vite
 | ||||
|     } | ||||
| 
 | ||||
|     p_out.iter().map(|p| (p.x, p.y)).collect() | ||||
| } | ||||
| 
 | ||||
| // en fait ca marche pas dutout...next time
 | ||||
| pub fn bord_mult_v2(pt: Vec<(f64, f64)>, factor: f64) -> Vec<(f64, f64)> { | ||||
|     let mut pt: Vec<Pt> = pt.iter().map(|p| Pt::from(p)).collect(); | ||||
| 
 | ||||
|     let mut pn = vec![]; | ||||
|     for i in 0..pt.len() { | ||||
|         let j = (i + 2) % pt.len(); | ||||
|         pn.push((pt[i] - pt[j]) * factor + pt[j]); | ||||
|     } | ||||
| 
 | ||||
|     pn.iter().map(|p| (p.x, p.y)).collect() | ||||
| } | ||||
| 
 | ||||
| pub fn get_intersection(pts: &[((f64, f64), (f64, f64))]) -> Vec<(f64, f64)> { | ||||
|     let mut eq_cart = vec![]; | ||||
|     for i in 0..pts.len() { | ||||
|         eq_cart.push(CartesianEquation::new_from_tuple(pts[i])); | ||||
|     } | ||||
| 
 | ||||
|     let mut points = vec![]; | ||||
|     for i in 0..eq_cart.len() { | ||||
|         let id_next = (i + 1) % eq_cart.len(); | ||||
|         let pt = eq_cart[i].intersection(&eq_cart[id_next]).unwrap(); // TODO verifier quand meme la sortie au lieu de unwrap salement... xD
 | ||||
|         points.push((pt.x, pt.y)); | ||||
|     } | ||||
| 
 | ||||
|     points | ||||
| } | ||||
| 
 | ||||
| pub fn get_extermities(lines: &Vector<VecN<i32, 4>>, id: usize) -> ((f64, f64), (f64, f64)) { | ||||
|     let mut p0: (f64, f64) = (0., 0.); | ||||
|     let mut p1: (f64, f64) = (0., 0.); | ||||
|     let (mut min, mut max): (f64, f64) = (f64::MAX, f64::MIN); | ||||
|     //let mut eq: (f64, f64, f64) = (0., 0., 0.);
 | ||||
|     let mut dst_sum = 0.; | ||||
|     let mut v_eq = vec![]; | ||||
| 
 | ||||
|     // on cherche les extremite
 | ||||
|     for l in lines { | ||||
|         // rename value and switch x and y if necessery
 | ||||
|         let (mut a0, mut b0, mut a1, mut b1) = if id % 2 == 0 { | ||||
|             (l[0] as f64, l[1] as f64, l[2] as f64, l[3] as f64) | ||||
|         } else { | ||||
|             (l[1] as f64, l[0] as f64, l[3] as f64, l[2] as f64) // switch x <-> y
 | ||||
|         }; | ||||
| 
 | ||||
|         // reorder if not
 | ||||
|         if a0 > a1 { | ||||
|             (a0, b0, a1, b1) = (a1, b1, a0, b0); | ||||
|         } | ||||
| 
 | ||||
|         // update min/max
 | ||||
|         min = min.min(a0).min(a1); | ||||
|         max = max.max(a0).max(a1); | ||||
| 
 | ||||
|         // cancel computation if devide by zero
 | ||||
|         if a1 - a0 == 0. { | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         let eq = EqAffine::new(a0, b0, a1, b1); | ||||
|         dst_sum += eq.dst; | ||||
|         v_eq.push(eq); | ||||
|     } | ||||
| 
 | ||||
|     p0.0 = min; | ||||
|     p1.0 = max; | ||||
|     for eq in v_eq { | ||||
|         p0.1 += eq.get_val_dst(min); | ||||
|         p1.1 += eq.get_val_dst(max); | ||||
|     } | ||||
|     p0.1 /= dst_sum; | ||||
|     p1.1 /= dst_sum; | ||||
| 
 | ||||
|     // revert x-y if already reverted previously
 | ||||
|     if id % 2 != 0 { | ||||
|         p0 = (p0.1, p0.0); | ||||
|         p1 = (p1.1, p1.0); | ||||
|     } | ||||
| 
 | ||||
|     (p0, p1) | ||||
| } | ||||
| 
 | ||||
| pub fn probabilistic_hough( | ||||
|     edges: &Mat, | ||||
|     hough_param: &HoughLine, | ||||
|     id: usize, | ||||
| ) -> Result<Vector<VecN<i32, 4>>> { | ||||
|     let mut p_lines = VectorOfVec4i::new(); | ||||
|     let mut probabalistic_hough = Mat::default(); | ||||
| 
 | ||||
|     cvt_color(edges, &mut probabalistic_hough, COLOR_GRAY2BGR, 0)?; | ||||
| 
 | ||||
|     // 2. Use Probabilistic Hough Transform
 | ||||
|     let p = hough_param.get_param(); | ||||
|     hough_lines_p( | ||||
|         edges, | ||||
|         &mut p_lines, | ||||
|         p.rho, | ||||
|         p.theta, | ||||
|         p.treshold, | ||||
|         p.min_length, | ||||
|         p.max_line_gap, | ||||
|     )?; | ||||
| 
 | ||||
|     Ok(p_lines) | ||||
| } | ||||
							
								
								
									
										43
									
								
								src/qualib_refacto/compute_image.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/qualib_refacto/compute_image.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| use super::Treshold; | ||||
| use opencv::core::{self, bitwise_and, in_range, Mat, Scalar, Size_}; | ||||
| use opencv::imgproc; | ||||
| use opencv::Result; | ||||
| 
 | ||||
| pub fn image_warp(img: &Mat, homography: &Mat, h_size: Size_<i32>) -> Result<Mat> { | ||||
|     let mut warped_image = Mat::default(); | ||||
|     imgproc::warp_perspective( | ||||
|         &img, | ||||
|         &mut warped_image, | ||||
|         homography, | ||||
|         h_size, | ||||
|         imgproc::INTER_CUBIC, // I dont see difference with INTER_CUBIC
 | ||||
|         core::BORDER_CONSTANT, | ||||
|         Scalar::default(), | ||||
|     )?; | ||||
| 
 | ||||
|     Ok(warped_image) | ||||
| } | ||||
| 
 | ||||
| pub fn image_treshold(img: &Mat, tresh: &Treshold) -> Result<Mat> { | ||||
|     let (t1, s1, l1) = (tresh.min_0 as f64, tresh.min_1 as f64, tresh.min_2 as f64); | ||||
|     let (t2, s2, l2) = (tresh.max_0 as f64, tresh.max_1 as f64, 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(img, &min, &max, &mut color_selected); | ||||
|     let mut bord_treshed = Mat::default(); | ||||
|     bitwise_and(&img, &img, &mut bord_treshed, &color_selected)?; | ||||
| 
 | ||||
|     Ok(bord_treshed) | ||||
| } | ||||
| 
 | ||||
| pub fn image_warp_treshold( | ||||
|     img: &Mat, | ||||
|     homography: &Mat, | ||||
|     h_size: Size_<i32>, | ||||
|     tresh: &Treshold, | ||||
| ) -> Result<Mat> { | ||||
|     let warped = image_warp(img, homography, h_size)?; | ||||
|     let treshed = image_treshold(&warped, tresh)?; | ||||
|     Ok(treshed) | ||||
| } | ||||
							
								
								
									
										204
									
								
								src/qualib_refacto/init_border.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								src/qualib_refacto/init_border.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,204 @@ | ||||
| use crate::draw::draw_line; | ||||
| use crate::point::{Color, Point}; | ||||
| use crate::qualib_refacto::{HoughLine, Param, Sequence}; | ||||
| 
 | ||||
| use crate::qualib_refacto::annalyse::image_diff; | ||||
| use crate::qualib_refacto::borders::{ | ||||
|     bord_mult, get_extermities, get_intersection, mix_borders, probabilistic_hough, | ||||
| }; | ||||
| 
 | ||||
| use opencv::{ | ||||
|     calib3d, | ||||
|     core::{self, Mat, Point as OcvPoint, Scalar, Size, VecN, Vector}, | ||||
|     imgproc::{self, canny, cvt_color, line, COLOR_BGR2GRAY}, | ||||
|     Result, | ||||
| }; | ||||
| 
 | ||||
| opencv::opencv_branch_4! { | ||||
|     use opencv::imgproc::LINE_AA; | ||||
| } | ||||
| opencv::not_opencv_branch_4! { | ||||
|     use opencv::core::LINE_AA; | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone, Copy)] | ||||
| pub struct InitBorder { | ||||
|     borders: [Point; 4], | ||||
|     cnt: usize, | ||||
| } | ||||
| 
 | ||||
| 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, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Sequence for InitBorder { | ||||
|     //type Obj = Self;
 | ||||
| 
 | ||||
|     fn draw(&self, mem: &Param) -> Option<Vec<Point>> { | ||||
|         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<dyn std::error::Error>> { | ||||
|         if self.cnt < self.borders.len() { | ||||
|             return Ok(()); | ||||
|         } | ||||
| 
 | ||||
|         let len = self.borders.len(); | ||||
|         let imgs = mem.imgs[mem.seq_id].clone(); | ||||
|         let background = imgs[len].clone(); | ||||
|         let borders: Vec<Mat> = imgs[..=len].into(); | ||||
| 
 | ||||
|         // 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<f64, 4> = 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<OcvPoint> = 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<OcvPoint> = 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)?;
 | ||||
|         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<Vector<VecN<i32, 4>>> { | ||||
|     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) | ||||
| } | ||||
							
								
								
									
										33
									
								
								src/qualib_refacto/load_image.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/qualib_refacto/load_image.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| use super::{Param, Sequence}; | ||||
| use crate::point::Point; | ||||
| use opencv::{core::Mat, Result}; | ||||
| 
 | ||||
| #[derive(Debug, Clone, Copy)] | ||||
| pub struct LoadImage { | ||||
|     finished: bool, | ||||
| } | ||||
| 
 | ||||
| impl LoadImage { | ||||
|     pub fn new() -> LoadImage { | ||||
|         LoadImage { finished: true } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Sequence for LoadImage { | ||||
|     fn draw(&self, _mem: &Param) -> Option<Vec<Point>> { | ||||
|         if self.finished { | ||||
|             return None; | ||||
|         } | ||||
|         Some(vec![]) | ||||
|     } | ||||
|     fn compute_sequence(&mut self, mem: &mut Param) -> Result<(), Box<dyn std::error::Error>> { | ||||
|         if !mem.capture_mode { | ||||
|             mem.load_image()?; | ||||
|         } | ||||
|         self.finished = true; | ||||
|         Ok(()) | ||||
|     } | ||||
|     fn is_capture(&self) -> bool { | ||||
|         false | ||||
|     } | ||||
| } | ||||
							
								
								
									
										31
									
								
								src/qualib_refacto/save_image.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/qualib_refacto/save_image.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| use super::{Param, Sequence}; | ||||
| use crate::point::Point; | ||||
| use opencv::{core::Mat, Result}; | ||||
| 
 | ||||
| #[derive(Debug, Clone, Copy)] | ||||
| pub struct SaveImage { | ||||
|     finished: bool, | ||||
| } | ||||
| 
 | ||||
| impl SaveImage { | ||||
|     pub fn new() -> SaveImage { | ||||
|         SaveImage { finished: true } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Sequence for SaveImage { | ||||
|     fn draw(&self, _mem: &Param) -> Option<Vec<Point>> { | ||||
|         if self.finished { | ||||
|             return None; | ||||
|         } | ||||
|         Some(vec![]) | ||||
|     } | ||||
|     fn compute_sequence(&mut self, mem: &mut Param) -> Result<(), Box<dyn std::error::Error>> { | ||||
|         mem.save_image()?; | ||||
|         self.finished = true; | ||||
|         Ok(()) | ||||
|     } | ||||
|     fn is_capture(&self) -> bool { | ||||
|         false | ||||
|     } | ||||
| } | ||||
							
								
								
									
										29
									
								
								src/qualib_refacto/wait_space.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/qualib_refacto/wait_space.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| use super::{Param, Sequence}; | ||||
| use crate::point::Point; | ||||
| use opencv::{core::Mat, Result}; | ||||
| 
 | ||||
| #[derive(Debug, Clone, Copy)] | ||||
| pub struct WaitSpace {} | ||||
| 
 | ||||
| impl WaitSpace { | ||||
|     pub fn new() -> Self { | ||||
|         Self {} | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Sequence for WaitSpace { | ||||
|     //type Obj = Self;
 | ||||
| 
 | ||||
|     fn draw(&self, mem: &Param) -> Option<Vec<Point>> { | ||||
|         if mem.key == 32 { | ||||
|             return None; | ||||
|         } | ||||
|         Some(vec![]) | ||||
|     } | ||||
|     fn compute_sequence(&mut self, _mem: &mut Param) -> Result<(), Box<dyn std::error::Error>> { | ||||
|         Ok(()) | ||||
|     } | ||||
|     fn is_capture(&self) -> bool { | ||||
|         false | ||||
|     } | ||||
| } | ||||
| @ -223,12 +223,12 @@ impl Qualibration { | ||||
|                 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)?); | ||||
|                     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)?); | ||||
|                     pl.extend(draw_line_dotted(&pa, &pb, nb_all, nb_visible, false)); | ||||
|                 } | ||||
|                 Sequence::PlayLineDotted | ||||
|                 | Sequence::TakeMultiple(_) | ||||
| @ -266,32 +266,32 @@ impl Qualibration { | ||||
|                     } | ||||
|                 } | ||||
|                 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 = 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)?); | ||||
|                     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)?); | ||||
|                     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)?; | ||||
|                     pl = draw_line(&p0, &p1, nb_all, nb_visible); | ||||
|                 } | ||||
|                 Sequence::RightBorder => { | ||||
|                     pl = draw_line(&p1, &p2, nb_all, nb_visible)?; | ||||
|                     pl = draw_line(&p1, &p2, nb_all, nb_visible); | ||||
|                 } | ||||
|                 Sequence::DownBorder => { | ||||
|                     pl = draw_line(&p2, &p3, nb_all, nb_visible)?; | ||||
|                     pl = draw_line(&p2, &p3, nb_all, nb_visible); | ||||
|                 } | ||||
|                 Sequence::LeftBorder => { | ||||
|                     pl = draw_line(&p3, &p0, nb_all, nb_visible)?; | ||||
|                     pl = draw_line(&p3, &p0, nb_all, nb_visible); | ||||
|                 } | ||||
|                 Sequence::Vertical(n) => { | ||||
|                     let p1 = Point { | ||||
| @ -304,7 +304,7 @@ impl Qualibration { | ||||
|                         y: 4095., | ||||
|                         color, | ||||
|                     }; | ||||
|                     pl = draw_line(&p1, &p2, nb_all, nb_visible)?; | ||||
|                     pl = draw_line(&p1, &p2, nb_all, nb_visible); | ||||
|                 } | ||||
|                 Sequence::Horizontal(n) => { | ||||
|                     let p1 = Point { | ||||
| @ -317,7 +317,7 @@ impl Qualibration { | ||||
|                         y: n as f32, | ||||
|                         color, | ||||
|                     }; | ||||
|                     pl = draw_line(&p1, &p2, nb_all, nb_visible)?; | ||||
|                     pl = draw_line(&p1, &p2, nb_all, nb_visible); | ||||
|                 } | ||||
|                 _ => (), | ||||
|             } | ||||
| @ -504,7 +504,7 @@ impl Qualibration { | ||||
|                 //highgui::imshow("Warped Image", &warped_image)?;
 | ||||
| 
 | ||||
|                 let histo = histogram_3d(&warped_image, self.nb_liss)?; | ||||
|                 draw_histograme_bgr_tresh("histo bgr", &histo, &self.tresh)?; | ||||
|                 draw_histograme_bgr_tresh("histo bgr", &histo, &self.tresh); | ||||
| 
 | ||||
|                 let (t1, s1, l1) = ( | ||||
|                     self.tresh.min_0 as f64, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user