use super::Qualibration; use super::DEBUG; //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; 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; fn draw_histograme_dbg( window_name: &str, histo: &Vec, (from, to): (usize, usize), ) -> Result<()> { let v: VecN = VecN::new(0., 0., 0., 255.); let c1: VecN = VecN::new(128., 128., 128., 255.); let c2: VecN = VecN::new(255., 255., 255., 255.); //let color: VecN = 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(()) } fn draw_histograme(window_name: &str, histo: &Vec) -> Result<()> { let v: VecN = VecN::new(0., 0., 0., 255.); let color: VecN = VecN::new(255., 255., 255., 255.); 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 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(()) } fn draw_histograme_bgr(window_name: &str, histo: &Vec>) -> Result<()> { let v: VecN = VecN::new(0., 0., 0., 255.); let b: VecN = VecN::new(255., 0., 0., 255.); let g: VecN = VecN::new(0., 255., 0., 255.); let r: VecN = 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(()) } fn draw_histograme_bgr_tresh( window_name: &str, histo: &Vec>, tresh: &Treshold, ) -> Result<()> { let v: VecN = VecN::new(0., 0., 0., 255.); let b: VecN = VecN::new(255., 0., 0., 255.); let g: VecN = VecN::new(0., 255., 0., 255.); let r: VecN = 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 = [tresh.max_0 as f64, tresh.max_1 as f64, tresh.max_2 as f64].into(); let min: Vec = [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 { 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) } } pub fn image_diff(frame: &Mat, frame_prev: &Mat) -> Result { 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 = 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) } fn histogram_3d(m: &Mat, nb_liss: i32) -> Result>> { 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_ = 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) } fn histogram_1d(m: &Mat, nb_liss: i32) -> Result> { 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 = 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) } fn first_invert(histo: &Vec) -> ((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 adding_trackbar(mem: &mut Qualibration, winname: &str) -> Result<()> { //println!("winname: {winname}"); named_window(winname, WINDOW_AUTOSIZE)?; associate_trackbar(winname, &mut mem.tresh)?; create_trackbar( "nb_liss", winname, Some(&mut mem.nb_liss), MAX_TRACKBAR, None, )?; //highgui let winname = format!("{}: {}", winname, 0); //"bord selected: 0"; named_window(winname.as_str(), WINDOW_AUTOSIZE)?; highgui::move_window(winname.as_str(), 20, 20)?; // 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), 500000, None, )?; //let winname = "bord selected: 0"; //create_trackbar("scale : ", winname, Some(&mut mem.lsd_param.scale ), 1000, None)?; //create_trackbar("sigma_scal", winname, Some(&mut mem.lsd_param.sigma_scale), 1000, None)?; //create_trackbar("quant : ", winname, Some(&mut mem.lsd_param.quant ), 1000, None)?; //create_trackbar("ang_th : ", winname, Some(&mut mem.lsd_param.ang_th ), 1000, None)?; //create_trackbar("log_eps : ", winname, Some(&mut mem.lsd_param.log_eps ), 1000, None)?; //create_trackbar("density_th", winname, Some(&mut mem.lsd_param.density_th ), 1000, None)?; //create_trackbar("n_bins : ", winname, Some(&mut mem.lsd_param.n_bins ), 1000, None)?; Ok(()) } 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(()) }