feat: ajout de parametrage dans l'interface

This commit is contained in:
Lapin Raving 2023-09-14 20:29:34 +02:00
parent edfdc46172
commit 3ceb80edc4
4 changed files with 322 additions and 107 deletions

View File

@ -6,25 +6,62 @@ const RADIUS: f32 = 2000.0;
const X_CENTER: f32 = 2047.0;
const Y_CENTER: f32 = 2047.0;
pub fn draw_line(
pub fn draw_line_dotted(
p1: &Point,
p2: &Point,
nb1: usize,
nb2: usize,
nb_all: usize,
nb_visible: usize,
) -> Result<Vec<Point>, Box<dyn std::error::Error>> {
let mut pl = vec![];
let black = Color { r: 0, g: 0, b: 0 };
for _ in 0..nb1 {
for _ in 0..nb_all {
pl.push(Point {
color: black,
..*p1
});
}
for _ in 0..nb2 {
for i in 0..nb_visible {
pl.push(Point {
color: if i % 2 == 0 { p2.color } else { black },
..*p2
});
}
if nb_visible > nb_all {
return Ok(pl);
}
for _ in 0..(nb_all - nb_visible) {
pl.push(Point {
color: black,
..*p2
});
}
Ok(pl)
}
pub fn draw_line(
p1: &Point,
p2: &Point,
nb_all: usize,
nb_visible: usize,
) -> Result<Vec<Point>, Box<dyn std::error::Error>> {
let mut pl = vec![];
let black = Color { r: 0, g: 0, b: 0 };
for _ in 0..nb_all {
pl.push(Point {
color: black,
..*p1
});
}
for _ in 0..nb_visible {
pl.push(*p2);
}
for _ in 0..(nb1 - nb2) {
if nb_visible > nb_all {
return Ok(pl);
}
for _ in 0..(nb_all - nb_visible) {
pl.push(Point {
color: black,
..*p2

View File

@ -8,21 +8,23 @@ mod framerate;
mod logs;
mod point;
mod utils;
mod qualibration;
mod utils;
use qualibration::{Qualibration, annalyse::adding_trackbar};
use qualibration::{annalyse::adding_trackbar, Qualibration};
use conf::Conf;
use log::{/*debug, warn, */ error, info};
use logs::init_logging;
use point::{Color, Point};
use redis::{Client, Commands, Connection};
use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use opencv::Result;
use opencv::highgui;
use opencv::Result;
opencv::opencv_branch_4! {
#[allow(unused_imports)]
@ -33,7 +35,6 @@ opencv::not_opencv_branch_4! {
use opencv::core::LINE_AA;
}
const DEFAULT_CONF_FILE: &str = "settings.toml";
pub fn main() {
@ -86,20 +87,20 @@ fn run_all() -> Result<(), Box<dyn std::error::Error>> {
)?;
while running.load(Ordering::SeqCst) {
let _t = framerate_handler.handle_time()?;
//let _t = framerate_handler.handle_time()?;
/////////////////
qualibration.run_step()?;
let key = highgui::wait_key(1)?;
if key != -1 {
qualibration.key = key;
}
if key == 27 { // esc in my case
if key == 27 {
// esc in my case
break;
}
let points_list: Vec<Point> = qualibration.draw_sequence()?; //draw::draw(_t)?;
//qualibration.id = next_id;
let v: Vec<(f32, f32, u32)> = points_list
//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();
@ -109,8 +110,10 @@ fn run_all() -> Result<(), Box<dyn std::error::Error>> {
format!("{:?}", v),
)?;
qualibration.run_step()?;
if qualibration.capture_mode {
let millis = std::time::Duration::from_millis(300); // TODO: find solution to know when change has been done
let millis = std::time::Duration::from_millis(1000); // TODO: find solution to know when change has been done
std::thread::sleep(millis);
}
}

View File

@ -13,7 +13,7 @@ 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};
use opencv::core::{bitwise_and, find_file, in_range, Point as OcvPoint, Scalar, Size_};
use opencv::core::{VecN, Vector};
use opencv::imgcodecs::imwrite;
use opencv::imgcodecs::{imread, IMREAD_COLOR};
@ -43,44 +43,48 @@ const DEBUG: bool = true;
#[derive(Debug, PartialEq, Seq, Copy, Clone)]
pub enum Sequence {
//TODO: avoir le meme nombre d'image en mode capture ET en mode replay
//TODO: avoir le meme nombre d'image en mode capture ET en mode replay
FirstState,
ReadDir,
ComputeArea,
WaitSpace,
Finish,
LinearConstSpeed, // [multiple test]
JumpFromTo,
AdaptLineSeg(u16), // [multiple test] find the correct distense
AdaptLineLum, // [multiple test] try minimu, medium, maximum.
//
TestRedSpeed,
TestGreenSpeed,
TestBlueSpeed,
SelectSpeedestColor, // on pourait mettre a jour les valeur a chaque passage
BackGround,
UpBorder,
LeftBorder,
DownBorder,
RightBorder,
ReadDir,
ComputeArea,
Finish,
WaitQ,
LinearConstSpeed, // [multiple test]
JumpFromTo,
AdaptLineSeg(u16), // [multiple test] find the correct distense
AdaptLineLum, // [multiple test] try minimu, medium, maximum.
//
SelectSpeedestColor, // on pourait mettre a jour les valeur a chaque passage
Vertical(u16),
Horizontal(u16),
SelectNbAll(u16),
ComputeSelectNbAll,
}
#[derive(Debug)]
pub struct Qualibration {
pub cam: VideoCapture,
pub r: i32,
pub g: i32,
pub b: i32,
pub capture_mode: bool,
pub frame: Mat,
pub frame_prev: Mat,
pub img: Vec<Mat>,
pub id: Option<Sequence>,
pub nb_pt_1: usize,
pub nb_pt_2: usize,
pub nb_all: i32,
pub nb_visible: i32,
pub nb_liss: i32,
pub tresh: Treshold,
pub dir_name: String,
@ -89,6 +93,8 @@ pub struct Qualibration {
pub canny_v2: i32,
pub hough_param: HoughLine,
pub border_pt: Vec<(f64, f64)>,
pub homography: Mat,
pub h_size: Size_<i32>,
}
impl Qualibration {
@ -109,13 +115,16 @@ impl Qualibration {
Ok(Qualibration {
cam,
r: 150,
g: 0,
b: 0,
capture_mode: dir_name.len() == 0,
img: vec![],
frame: Mat::default(), // TODO: init with frame from cam
frame_prev: Mat::default(),
id: Some(Sequence::FirstState),
nb_pt_1: 130,
nb_pt_2: 40,
nb_all: 120,
nb_visible: 40,
nb_liss: 10,
tresh: Treshold::new("histogram: 0", 0, 255)?,
dir_name: dir_name.clone(),
@ -130,18 +139,34 @@ impl Qualibration {
max_line_gap: 50000,
},
border_pt: vec![],
homography: Mat::default(),
h_size: Size::default(),
})
}
pub fn run_step(&mut self) -> Result<(), Box<dyn std::error::Error>> {
if self.capture_mode {
//println!("pouette: >{}<\n:self{:?}", self.dir_name, self);
//println!("capture");
self.cam.read(&mut self.frame)?;
highgui::imshow("camera", &self.frame)?;
}
//println!(
// "frame.size:{} \tframe_prev.size:{}",
// self.frame.size()?.width,
// self.frame_prev.size()?.width
//);
if self.frame.size()?.width > 0 && self.frame_prev.size()?.width > 0 || !self.capture_mode {
//println!("plif: {}", line!());
if self.id.is_some() {
self.id = if !self.capture_mode || is_same_frame(&self.frame, &self.frame_prev)? {
if self.id != Some(Sequence::WaitSpace) && self.capture_mode {
// println!("plif: {}", line!());
self.id = if true {
//self.capture_mode || self.id == Some(Sequence::WaitSpace) || is_same_frame(&self.frame, &self.frame_prev)? {
if self.id != Some(Sequence::WaitSpace)
&& self.id != Some(Sequence::FirstState)
&& self.capture_mode
{
self.img.push(self.frame.clone());
}
self.compute_sequence()?;
@ -157,10 +182,17 @@ impl Qualibration {
}
pub fn draw_sequence(&self) -> Result<Vec<Point>, Box<dyn std::error::Error>> {
if !self.capture_mode {
return Ok(vec![])
}
let seq = self.id;
let mut pl = vec![];
//let color = Color { r: 0, g: 30, b: 0 };
let color = Color { r: 60, g: 0, b: 0 };
let color = Color {
r: self.r as u8,
g: self.g as u8,
b: self.b as u8,
};
//let color = Color { r: 0, g: 0, b: 50 };
let p0 = Point {
x: 0.,
@ -182,33 +214,70 @@ impl Qualibration {
y: 4095.,
color,
};
let nb1 = self.nb_pt_1;
let nb2 = self.nb_pt_2;
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 nb_all = self.nb_all as usize;
let nb_visible = self.nb_visible as usize;
if seq.is_some() {
match seq.unwrap() {
Sequence::WaitSpace => {
////let l1 = draw::draw_line(&p0, &p1, nb1, nb2)?;
//let l0 = draw::draw_line(&p0, &p1, nb1, nb2)?;
//let l1 = draw::draw_line(&p1, &p2, nb1, nb2)?;
//let l2 = draw::draw_line(&p3, &p0, nb1, nb2)?;
//let l3 = draw::draw_line(&p2, &p3, nb1, nb2)?;
//pl.extend(l0);
//pl.extend(l1);
//pl.extend(l2);
//pl.extend(l3);
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.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)?);
}
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)?);
}
Sequence::UpBorder => {
pl = draw::draw_line(&p0, &p1, nb1, nb2)?;
pl = draw::draw_line(&p0, &p1, nb_all, nb_visible)?;
}
Sequence::RightBorder => {
pl = draw::draw_line(&p1, &p2, nb1, nb2)?;
pl = draw::draw_line(&p1, &p2, nb_all, nb_visible)?;
}
Sequence::DownBorder => {
pl = draw::draw_line(&p2, &p3, nb1, nb2)?;
pl = draw::draw_line(&p2, &p3, nb_all, nb_visible)?;
}
Sequence::LeftBorder => {
pl = draw::draw_line(&p3, &p0, nb1, nb2)?;
pl = draw::draw_line(&p3, &p0, nb_all, nb_visible)?;
}
Sequence::Vertical(n) => {
let p1 = Point {
@ -221,7 +290,7 @@ impl Qualibration {
y: 4095.,
color,
};
pl = draw::draw_line(&p1, &p2, nb1, nb2)?;
pl = draw::draw_line(&p1, &p2, nb_all, nb_visible)?;
}
Sequence::Horizontal(n) => {
let p1 = Point {
@ -234,7 +303,7 @@ impl Qualibration {
y: n as f32,
color,
};
pl = draw::draw_line(&p1, &p2, nb1, nb2)?;
pl = draw::draw_line(&p1, &p2, nb_all, nb_visible)?;
}
_ => (),
}
@ -251,9 +320,19 @@ impl Qualibration {
return None;
}
println!("Hey");
match self.id.unwrap() {
//Sequence::Finish => Some(Sequence::Finish),
Sequence::Finish => None,
Sequence::SelectNbAll(mut n) => {
if n == 0 {
Some(Sequence::SelectNbAll(2 - 1))
} else if (2 * n) > line_max as u16 {
next(&Sequence::SelectNbAll(u16::MAX))
} else {
next(&Sequence::SelectNbAll(n * 2 - 1))
}
}
Sequence::WaitSpace => {
//println!("key: {}", self.key);
if self.key == 32 {
@ -262,6 +341,14 @@ impl Qualibration {
Some(Sequence::WaitSpace)
}
}
Sequence::WaitQ => {
//println!("key: {}", self.key);
if self.key == 113 {
next(&Sequence::WaitQ)
} else {
Some(Sequence::WaitQ)
}
}
Sequence::Vertical(n) => {
let after = if n > line_max { u16::MAX } else { n + line_add };
next(&Sequence::Vertical(after))
@ -270,7 +357,7 @@ impl Qualibration {
let after = if n > line_max { u16::MAX } else { n + line_add };
next(&Sequence::Horizontal(after))
}
Sequence::ComputeArea => Some(Sequence::ComputeArea), //
//Sequence::ComputeArea => Some(Sequence::ComputeArea), //
id => next(&id),
}
}
@ -278,27 +365,54 @@ impl Qualibration {
pub fn compute_sequence(&mut self) -> Result<(), Box<dyn std::error::Error>> {
if self.id.is_some() {
match self.id.unwrap() {
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>;
// on recupere les image en fonction de mode: capture/dossier
if !self.capture_mode {
background = self.img[1].clone();
borders = self.img[2..6].into();
} else {
background = self.img[0].clone();
borders = self.img[1..].into();
}
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)?;
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);
@ -367,10 +481,12 @@ impl Qualibration {
// on fait un nom de dossier avec le temps
// on sauvgarde toutes les image
let now = std::time::Instant::now();
let mut name = "image/".to_owned();
let name = format!("image/");
create_dir(&name).unwrap_or(());
name.push_str(format!("testouille_{now:?}/").as_str());
let name = format!("testouille_{now:?}");
let name = format!("image/{:0>6?}_{:0>9?}/", now.elapsed().as_millis(), now.elapsed().as_nanos());
create_dir(&name).unwrap_or(());
//name.push_str(format!("image/{}_{}/", now.elapsed().as_secs(), now.elapsed().as_nanos()).as_str());
//let name = format!("image/{now:?}/");
//
for (i, img) in self.img.iter().enumerate() {
@ -391,7 +507,7 @@ impl Qualibration {
let dir = entry?;
let path = dir.path();
let a: Vec<_> = path.to_str().unwrap().to_string().chars().collect();
let b: String = a[21..(a.len() - 4)].iter().collect();
let b: String = a[27..(a.len() - 4)].iter().collect();
let img_id: i32 = b.parse()?;
let path = format!("{path:?}");
let path = path[1..(path.len() - 1)].to_owned();
@ -410,10 +526,17 @@ impl Qualibration {
}
});
for m in imgs {
self.img.push(m.1);
//println!("Youpi");
for (i, m) in imgs.iter().enumerate() {
self.img.push(m.1.clone());
//highgui::imshow(format!("img: {i}").as_str(), &m.1)?;
}
//loop {}
//prointln!("");
Ok(())
}
@ -423,22 +546,33 @@ impl Qualibration {
bord: &Mat,
id: usize,
) -> Result<((f64, f64), (f64, f64))> {
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 diff: Mat = image_diff(bord, background)?;
let _ = in_range(&diff, &min, &max, &mut color_selected);
//highgui::imshow(format!("mask: {id}").as_str(), &color_selected)?;
let mut bord_treshed = Mat::default();
bitwise_and(&diff, &diff, &mut bord_treshed, &color_selected)?;
//let (t1, s1, l1) = (
// self.tresh.min_0 as f64,
// self.tresh.min_1 as f64,
// self.tresh.min_2 as f64,
//);
//let (t2, s2, l2) = (
// self.tresh.max_0 as f64,
// self.tresh.max_1 as f64,
// self.tresh.max_2 as f64,
//);
//let min = Mat::from_slice(&[t1, s1, l1])?;
//let max = Mat::from_slice(&[t2, s2, l2])?;
//let mut color_selected = Mat::default();
//let _ = in_range(&diff, &min, &max, &mut color_selected);
////highgui::imshow(format!("mask: {id}").as_str(), &color_selected)?;
//let mut bord_treshed = Mat::default();
//bitwise_and(&diff, &diff, &mut bord_treshed, &color_selected)?;
////highgui::imshow(format!("diff & mask: {id}").as_str(), &bord_treshed)?;
// Pass the image to gray
let mut diff_gray = Mat::default();
cvt_color(&diff, &mut diff_gray, COLOR_BGR2GRAY, 0)?;
//cvt_color(&bord_treshed, &mut diff_gray, COLOR_BGR2GRAY, 0)?;
// Apply Canny edge detector
let mut edges = Mat::default();
canny(
@ -512,3 +646,31 @@ impl Treshold {
Ok(tresh)
}
}
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)
}

View File

@ -336,18 +336,23 @@ fn first_invert(histo: &Vec<f64>) -> ((usize, f64), (usize, f64)) {
)
}
pub fn adding_trackbar(mem: &mut Qualibration, winname: &str) -> Result<()> {
//println!("winname: {winname}");
pub fn trackbar_init_param(mem: &mut Qualibration, winname: &str) -> Result<()> {
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::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, 512, 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 Qualibration, winname: &str) -> Result<()> {
//highgui
let winname = format!("{}: {}", winname, 0); //"bord selected: 0";
named_window(winname.as_str(), WINDOW_AUTOSIZE)?;
@ -403,15 +408,23 @@ pub fn adding_trackbar(mem: &mut Qualibration, winname: &str) -> Result<()> {
500000,
None,
)?;
Ok(())
}
pub fn adding_trackbar(mem: &mut Qualibration, winname: &str) -> Result<()> {
//println!("winname: {winname}");
trackbar_init_param(mem, "init_param")?;
//named_window(winname, WINDOW_AUTOSIZE)?;
//associate_trackbar(winname, &mut mem.tresh)?;
//create_trackbar(
// "nb_liss",
// winname,
// Some(&mut mem.nb_liss),
// MAX_TRACKBAR,
// None,
//)?;
//trackbar_line_segment(mem, winname)?;
//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(())
}