feat: during IdCode implementation
The purpose is to include a en coded number in the image to be sure it's the right image.
This commit is contained in:
		
							parent
							
								
									6145b585f4
								
							
						
					
					
						commit
						910e340ec8
					
				| @ -11,10 +11,13 @@ pub fn draw_line_dotted( | ||||
|     p2: &Point, | ||||
|     nb_all: usize, | ||||
|     nb_visible: usize, | ||||
|     first_on: bool, | ||||
| ) -> Result<Vec<Point>, Box<dyn std::error::Error>> { | ||||
|     let mut pl = vec![]; | ||||
|     let black = Color { r: 0, g: 0, b: 0 }; | ||||
| 
 | ||||
|     let cmp = if first_on { 0 } else { 1 }; | ||||
| 
 | ||||
|     for _ in 0..nb_all { | ||||
|         pl.push(Point { | ||||
|             color: black, | ||||
| @ -23,7 +26,7 @@ pub fn draw_line_dotted( | ||||
|     } | ||||
|     for i in 0..nb_visible { | ||||
|         pl.push(Point { | ||||
|             color: if i % 2 == 0 { p2.color } else { black }, | ||||
|             color: if i % 2 == cmp { p2.color } else { black }, | ||||
|             ..*p2 | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| @ -1,15 +1,17 @@ | ||||
| pub mod annalyse; | ||||
| pub mod borders; | ||||
| pub mod compute_image; | ||||
| 
 | ||||
| use annalyse::{ | ||||
|     annalyse_segment, draw_histograme_bgr_tresh, get_vertical_segment, histogram_3d, image_diff, | ||||
|     image_mean, is_same_frame, | ||||
|     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; | ||||
| use crate::draw::{draw_line, draw_line_dotted}; | ||||
| use crate::point::{Color, Point}; | ||||
| 
 | ||||
| use enum_iterator::{next, Sequence as Seq}; | ||||
| @ -58,12 +60,14 @@ pub enum Sequence { | ||||
|     RightBorder, | ||||
|     ReadDir, | ||||
|     ComputeArea, | ||||
|     PlayLineDotted, | ||||
|     TakeMultiple(u16), | ||||
|     TakeMultipleEmpty(u16), | ||||
|     ComputeLineDotted, | ||||
|     IdCode1, | ||||
|     IdCode2, | ||||
|     Finish, | ||||
| 
 | ||||
|     PlayLineDotted, | ||||
|     EmptyFrame, | ||||
|     ComputeLineDotted, | ||||
| 
 | ||||
|     LinearConstSpeed, // [multiple test]
 | ||||
|     JumpFromTo, | ||||
| 
 | ||||
| @ -76,6 +80,8 @@ pub enum Sequence { | ||||
|     Horizontal(u16), | ||||
|     SelectNbAll(u16), | ||||
|     ComputeSelectNbAll, | ||||
|     TakeMultiple(u16), | ||||
|     TakeMultipleEmpty(u16), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| @ -105,6 +111,7 @@ pub struct Qualibration { | ||||
|     pub h_size: Size_<i32>, | ||||
|     pub line_pos: Vec<i32>, | ||||
|     pub multiple: u16, // le nombre de fois qu'une photo est prise pour certaine sequence
 | ||||
|     pub cnt: usize, | ||||
| } | ||||
| 
 | ||||
| impl Qualibration { | ||||
| @ -142,7 +149,7 @@ impl Qualibration { | ||||
|             tresh: Treshold::new("histogram: 0", 150, 255)?, | ||||
|             dir_name: dir_name.clone(), | ||||
|             key: 10, | ||||
|             canny_v1: 150, | ||||
|             canny_v1: 170, | ||||
|             canny_v2: 255, | ||||
|             hough_param: HoughLine { | ||||
|                 rho: 100, | ||||
| @ -156,6 +163,7 @@ impl Qualibration { | ||||
|             h_size: Size::default(), | ||||
|             line_pos: vec![4095; 34], | ||||
|             multiple: 20, | ||||
|             cnt: 0, | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
| @ -186,6 +194,7 @@ impl Qualibration { | ||||
|         } | ||||
|         //println!("sequence: {:?}", self.id);
 | ||||
|         self.frame_prev = self.frame.clone(); | ||||
|         self.cnt += 1; | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
| @ -202,81 +211,8 @@ impl Qualibration { | ||||
|             b: self.b as u8, | ||||
|         }; | ||||
|         //let color = Color { r: 0, g: 0, b: 50 };
 | ||||
|         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: self.r as u8, | ||||
|                 g: 0, | ||||
|                 b: 0, | ||||
|             }, | ||||
|         }; | ||||
|         let p5 = Point { | ||||
|             x: 4095., | ||||
|             y: 1000., | ||||
|             color: Color { | ||||
|                 r: self.r as u8, | ||||
|                 g: 0, | ||||
|                 b: 0, | ||||
|             }, | ||||
|         }; | ||||
|         let p6 = Point { | ||||
|             x: 0., | ||||
|             y: 2000., | ||||
|             color: Color { | ||||
|                 r: 0, | ||||
|                 g: self.g as u8, | ||||
|                 b: 0, | ||||
|             }, | ||||
|         }; | ||||
|         let p7 = Point { | ||||
|             x: 4095., | ||||
|             y: 2000., | ||||
|             color: Color { | ||||
|                 r: 0, | ||||
|                 g: self.g as u8, | ||||
|                 b: 0, | ||||
|             }, | ||||
|         }; | ||||
|         let p8 = Point { | ||||
|             x: 0., | ||||
|             y: 3000., | ||||
|             color: Color { | ||||
|                 r: 0, | ||||
|                 g: 0, | ||||
|                 b: self.b as u8, | ||||
|             }, | ||||
|         }; | ||||
|         let p9 = Point { | ||||
|             x: 4095., | ||||
|             y: 3000., | ||||
|             color: Color { | ||||
|                 r: 0, | ||||
|                 g: 0, | ||||
|                 b: self.b as u8, | ||||
|             }, | ||||
|         }; | ||||
| 
 | ||||
|         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
 | ||||
| @ -284,11 +220,20 @@ impl Qualibration { | ||||
| 
 | ||||
|         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
 | ||||
|                     pl = vec![]; | ||||
|                     let black = Color { r: 0, g: 0, b: 0 }; | ||||
|                     for _ in 0..nb_all { | ||||
|                         pl.push(Point { | ||||
| @ -321,32 +266,32 @@ impl Qualibration { | ||||
|                     } | ||||
|                 } | ||||
|                 Sequence::WaitSpace => { | ||||
|                     pl = draw::draw_line(&p0, &p1, nb_all, nb_visible)?; | ||||
|                     pl.extend(draw::draw_line(&p1, &p2, nb_all, nb_visible)?); | ||||
|                     pl.extend(draw::draw_line(&p3, &p0, nb_all, nb_visible)?); | ||||
|                     pl.extend(draw::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::draw_line_dotted(&p4, &p5, nb_all, nb_visible)?); | ||||
|                     pl.extend(draw::draw_line_dotted(&p6, &p7, nb_all, nb_visible)?); | ||||
|                     pl.extend(draw::draw_line_dotted(&p8, &p9, 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::draw_line(&p0, &p1, n as usize, n as usize)?; | ||||
|                     pl.extend(draw::draw_line(&p1, &p2, n as usize, n as usize)?); | ||||
|                     pl.extend(draw::draw_line(&p3, &p0, n as usize, n as usize)?); | ||||
|                     pl.extend(draw::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::draw_line(&p0, &p1, nb_all, nb_visible)?; | ||||
|                     pl = draw_line(&p0, &p1, nb_all, nb_visible)?; | ||||
|                 } | ||||
|                 Sequence::RightBorder => { | ||||
|                     pl = draw::draw_line(&p1, &p2, nb_all, nb_visible)?; | ||||
|                     pl = draw_line(&p1, &p2, nb_all, nb_visible)?; | ||||
|                 } | ||||
|                 Sequence::DownBorder => { | ||||
|                     pl = draw::draw_line(&p2, &p3, nb_all, nb_visible)?; | ||||
|                     pl = draw_line(&p2, &p3, nb_all, nb_visible)?; | ||||
|                 } | ||||
|                 Sequence::LeftBorder => { | ||||
|                     pl = draw::draw_line(&p3, &p0, nb_all, nb_visible)?; | ||||
|                     pl = draw_line(&p3, &p0, nb_all, nb_visible)?; | ||||
|                 } | ||||
|                 Sequence::Vertical(n) => { | ||||
|                     let p1 = Point { | ||||
| @ -359,7 +304,7 @@ impl Qualibration { | ||||
|                         y: 4095., | ||||
|                         color, | ||||
|                     }; | ||||
|                     pl = draw::draw_line(&p1, &p2, nb_all, nb_visible)?; | ||||
|                     pl = draw_line(&p1, &p2, nb_all, nb_visible)?; | ||||
|                 } | ||||
|                 Sequence::Horizontal(n) => { | ||||
|                     let p1 = Point { | ||||
| @ -372,7 +317,7 @@ impl Qualibration { | ||||
|                         y: n as f32, | ||||
|                         color, | ||||
|                     }; | ||||
|                     pl = draw::draw_line(&p1, &p2, nb_all, nb_visible)?; | ||||
|                     pl = draw_line(&p1, &p2, nb_all, nb_visible)?; | ||||
|                 } | ||||
|                 _ => (), | ||||
|             } | ||||
| @ -447,177 +392,264 @@ impl Qualibration { | ||||
|     } | ||||
| 
 | ||||
|     pub fn compute_sequence(&mut self) -> Result<(), Box<dyn std::error::Error>> { | ||||
|         if self.id.is_some() { | ||||
|             match self.id.unwrap() { | ||||
|                 Sequence::ComputeLineDotted => { | ||||
|                     let backgrounds = self.img[7..30].to_owned(); | ||||
|                     let lines_dots = self.img[30..52].to_owned(); | ||||
|         if self.id.is_none() { | ||||
|             return Ok(()); | ||||
|         } | ||||
|         match self.id.unwrap() { | ||||
|             Sequence::IdCode2 => { | ||||
|                 let mut id_code_1 = image_diff(&self.img[8], &self.img[1])?; | ||||
| 
 | ||||
|                     let background = image_mean(&backgrounds)?; | ||||
|                     let line_dot = image_mean(&lines_dots)?; | ||||
|                     let diff = image_diff(&background, &line_dot)?; | ||||
|                 id_code_1 = image_warp(&id_code_1, &self.homography, self.h_size)?; | ||||
|                 id_code_1 = image_treshold(&id_code_1, &self.tresh)?; | ||||
| 
 | ||||
|                     let mut warped_image = Mat::default(); | ||||
|                     imgproc::warp_perspective( | ||||
|                         &diff, | ||||
|                         &mut warped_image, | ||||
|                         &self.homography, | ||||
|                         self.h_size, | ||||
|                         imgproc::INTER_LINEAR, // I dont see difference with INTER_CUBIC
 | ||||
|                         core::BORDER_CONSTANT, | ||||
|                         Scalar::default(), | ||||
|                     )?; | ||||
|                     //highgui::imshow("Warped Image", &warped_image)?;
 | ||||
|                 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 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<f64, 4> = VecN::new(blue, 128., 0., 255.); | ||||
|                         let pa = VecN::from_array([*x0 as i32, *y0 as i32]); | ||||
|                         let pb = VecN::from_array([*x1 as i32, *y1 as i32]); | ||||
|                         let a = OcvPoint::from_vec2(pa); | ||||
|                         let b = OcvPoint::from_vec2(pb); | ||||
|                         line(&mut bord_treshed, a, b, color, 1, LINE_8, 0)?; | ||||
|                     } | ||||
|                     highgui::imshow("segemnt detector", &bord_treshed)?; | ||||
|                 } | ||||
|                 Sequence::ComputeSelectNbAll => { | ||||
|                     let background: Mat; | ||||
|                     let steps: Vec<Mat>; | ||||
| 
 | ||||
|                     background = self.img[1].clone(); | ||||
|                     steps = self.img[2..6].into(); | ||||
| 
 | ||||
|                     let mut angles: Vec<f64> = 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<Mat>; | ||||
| 
 | ||||
|                     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)?;
 | ||||
|                 //let blue = (i as f64 / code_seg_1.len() as f64) * 255.;
 | ||||
|                 let color_1: VecN<f64, 4> = 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)?;
 | ||||
|                     //}
 | ||||
|                 } | ||||
| 
 | ||||
|                     // on calcul le cadre
 | ||||
|                     let border_pt = get_intersection(&bords_pts); | ||||
|                     self.border_pt = bord_mult(border_pt, 1.1); | ||||
|                     let color: VecN<f64, 4> = 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 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<f64, 4> = 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)?;
 | ||||
|                     //}
 | ||||
|                 } | ||||
| 
 | ||||
|                     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<OcvPoint> = 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<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
 | ||||
|                     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()? | ||||
|                     } | ||||
|                 } | ||||
|                 _ => (), | ||||
|                 // 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<f64, 4> = VecN::new(blue, 128., 0., 255.); | ||||
|                     let pa = VecN::from_array([*x0 as i32, *y0 as i32]); | ||||
|                     let pb = VecN::from_array([*x1 as i32, *y1 as i32]); | ||||
|                     let a = OcvPoint::from_vec2(pa); | ||||
|                     let b = OcvPoint::from_vec2(pb); | ||||
|                     line(&mut bord_treshed, a, b, color, 1, LINE_8, 0)?; | ||||
|                 } | ||||
|                 highgui::imshow("segemnt detector", &bord_treshed)?; | ||||
|             } | ||||
|             Sequence::ComputeSelectNbAll => { | ||||
|                 let background: Mat; | ||||
|                 let steps: Vec<Mat>; | ||||
| 
 | ||||
|                 background = self.img[1].clone(); | ||||
|                 steps = self.img[2..6].into(); | ||||
| 
 | ||||
|                 let mut angles: Vec<f64> = 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<Mat>; | ||||
| 
 | ||||
|                 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<f64, 4> = 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<OcvPoint> = 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<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
 | ||||
|                 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(()) | ||||
|     } | ||||
| @ -743,6 +775,89 @@ impl Qualibration { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 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 { | ||||
|  | ||||
| @ -230,6 +230,151 @@ pub fn is_same_frame(frame: &Mat, frame_prev: &Mat) -> Result<bool> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // 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))>> { | ||||
| @ -251,7 +396,7 @@ pub fn get_vertical_segment(m: &Mat) -> Result<Vec<((f32, f32), (f32, f32))>> { | ||||
| 
 | ||||
|     // 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() { | ||||
|     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)); | ||||
|         } | ||||
| @ -266,7 +411,6 @@ pub fn get_vertical_segment(m: &Mat) -> Result<Vec<((f32, f32), (f32, f32))>> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     // on regroupe les point par illot.
 | ||||
|     let mut segment_iland = vec![vec![]; limits.len()]; | ||||
|     for (x, y) in seg_pt { | ||||
| @ -296,7 +440,7 @@ pub fn get_vertical_segment(m: &Mat) -> Result<Vec<((f32, f32), (f32, f32))>> { | ||||
|     //  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. 
 | ||||
|     //  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
 | ||||
| @ -309,28 +453,37 @@ pub fn get_vertical_segment(m: &Mat) -> Result<Vec<((f32, f32), (f32, f32))>> { | ||||
|     //          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.}; | ||||
|         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 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)}; | ||||
|                 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(){ | ||||
|                 if x_abs_max < p.x.abs() { | ||||
|                     x_abs_max = p.x.abs(); | ||||
|                 } | ||||
|             } | ||||
| @ -345,7 +498,7 @@ pub fn get_vertical_segment(m: &Mat) -> Result<Vec<((f32, f32), (f32, f32))>> { | ||||
|             //    iland_min = tmp_iland;
 | ||||
|             //}
 | ||||
|         } | ||||
|         iland_min.sort_by(|pta, ptb|{ | ||||
|         iland_min.sort_by(|pta, ptb| { | ||||
|             if pta.y < ptb.y { | ||||
|                 std::cmp::Ordering::Greater | ||||
|             } else if pta.y == ptb.y { | ||||
| @ -367,14 +520,23 @@ pub fn get_vertical_segment(m: &Mat) -> Result<Vec<((f32, f32), (f32, f32))>> { | ||||
|         //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 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))); | ||||
|         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) | ||||
|  | ||||
							
								
								
									
										43
									
								
								src/qualibration/compute_image.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/qualibration/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) | ||||
| } | ||||
| @ -3,11 +3,11 @@ 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::Div; | ||||
| use std::ops::DivAssign; | ||||
| //use std::ops::BitXor
 | ||||
| 
 | ||||
| impl Add for Pt { | ||||
| @ -28,7 +28,6 @@ impl AddAssign for Pt { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| impl Sub for Pt { | ||||
|     type Output = Self; | ||||
| 
 | ||||
| @ -110,7 +109,7 @@ impl Pt { | ||||
|     } | ||||
| 
 | ||||
|     pub fn mean(pts: &[Pt]) -> Pt { | ||||
|         let mut mean = Pt{x: 0., y: 0.}; | ||||
|         let mut mean = Pt { x: 0., y: 0. }; | ||||
|         for pt in pts { | ||||
|             mean += *pt; | ||||
|         } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user