feat: adding segment detection for the laser
The feature need to be better but it's usable.
This commit is contained in:
parent
550021a014
commit
6145b585f4
11
src/main.rs
11
src/main.rs
@ -112,7 +112,16 @@ fn run_all() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
qualibration.run_step()?;
|
qualibration.run_step()?;
|
||||||
|
|
||||||
if qualibration.capture_mode && (qualibration.id != Some(Sequence::WaitSpace) || qualibration.id != Some(Sequence::PlayLineDotted)) {
|
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
|
let millis = std::time::Duration::from_millis(400); // TODO: find solution to know when change has been done
|
||||||
std::thread::sleep(millis);
|
std::thread::sleep(millis);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
pub mod annalyse;
|
pub mod annalyse;
|
||||||
pub mod borders;
|
pub mod borders;
|
||||||
|
|
||||||
use std::time::Instant;
|
use annalyse::{
|
||||||
use annalyse::{image_diff, is_same_frame};
|
annalyse_segment, draw_histograme_bgr_tresh, get_vertical_segment, histogram_3d, image_diff,
|
||||||
|
image_mean, is_same_frame,
|
||||||
|
}; // mean dans le sans moyenne des image
|
||||||
use borders::{bord_mult, get_extermities, get_intersection, mix_borders, probabilistic_hough};
|
use borders::{bord_mult, get_extermities, get_intersection, mix_borders, probabilistic_hough};
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
use crate::draw;
|
use crate::draw;
|
||||||
use crate::point::{Color, Point};
|
use crate::point::{Color, Point};
|
||||||
@ -35,6 +38,7 @@ use opencv::{
|
|||||||
|
|
||||||
opencv::opencv_branch_4! {
|
opencv::opencv_branch_4! {
|
||||||
use opencv::imgproc::LINE_AA;
|
use opencv::imgproc::LINE_AA;
|
||||||
|
use opencv::imgproc::LINE_8;
|
||||||
}
|
}
|
||||||
opencv::not_opencv_branch_4! {
|
opencv::not_opencv_branch_4! {
|
||||||
use opencv::core::LINE_AA;
|
use opencv::core::LINE_AA;
|
||||||
@ -55,10 +59,11 @@ pub enum Sequence {
|
|||||||
ReadDir,
|
ReadDir,
|
||||||
ComputeArea,
|
ComputeArea,
|
||||||
PlayLineDotted,
|
PlayLineDotted,
|
||||||
|
TakeMultiple(u16),
|
||||||
|
TakeMultipleEmpty(u16),
|
||||||
|
ComputeLineDotted,
|
||||||
Finish,
|
Finish,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LinearConstSpeed, // [multiple test]
|
LinearConstSpeed, // [multiple test]
|
||||||
JumpFromTo,
|
JumpFromTo,
|
||||||
|
|
||||||
@ -76,6 +81,7 @@ pub enum Sequence {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Qualibration {
|
pub struct Qualibration {
|
||||||
pub begin: Instant,
|
pub begin: Instant,
|
||||||
|
pub dst_size: i32,
|
||||||
pub cam: VideoCapture,
|
pub cam: VideoCapture,
|
||||||
pub r: i32,
|
pub r: i32,
|
||||||
pub g: i32,
|
pub g: i32,
|
||||||
@ -98,6 +104,7 @@ pub struct Qualibration {
|
|||||||
pub homography: Mat,
|
pub homography: Mat,
|
||||||
pub h_size: Size_<i32>,
|
pub h_size: Size_<i32>,
|
||||||
pub line_pos: Vec<i32>,
|
pub line_pos: Vec<i32>,
|
||||||
|
pub multiple: u16, // le nombre de fois qu'une photo est prise pour certaine sequence
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Qualibration {
|
impl Qualibration {
|
||||||
@ -119,6 +126,7 @@ impl Qualibration {
|
|||||||
//let now = std::time::Instant::now();
|
//let now = std::time::Instant::now();
|
||||||
Ok(Qualibration {
|
Ok(Qualibration {
|
||||||
begin: std::time::Instant::now(),
|
begin: std::time::Instant::now(),
|
||||||
|
dst_size: 900,
|
||||||
cam,
|
cam,
|
||||||
r: 150,
|
r: 150,
|
||||||
g: 0,
|
g: 0,
|
||||||
@ -131,7 +139,7 @@ impl Qualibration {
|
|||||||
nb_all: 120,
|
nb_all: 120,
|
||||||
nb_visible: 40,
|
nb_visible: 40,
|
||||||
nb_liss: 10,
|
nb_liss: 10,
|
||||||
tresh: Treshold::new("histogram: 0", 0, 255)?,
|
tresh: Treshold::new("histogram: 0", 150, 255)?,
|
||||||
dir_name: dir_name.clone(),
|
dir_name: dir_name.clone(),
|
||||||
key: 10,
|
key: 10,
|
||||||
canny_v1: 150,
|
canny_v1: 150,
|
||||||
@ -147,6 +155,7 @@ impl Qualibration {
|
|||||||
homography: Mat::default(),
|
homography: Mat::default(),
|
||||||
h_size: Size::default(),
|
h_size: Size::default(),
|
||||||
line_pos: vec![4095; 34],
|
line_pos: vec![4095; 34],
|
||||||
|
multiple: 20,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +191,7 @@ impl Qualibration {
|
|||||||
|
|
||||||
pub fn draw_sequence(&self) -> Result<Vec<Point>, Box<dyn std::error::Error>> {
|
pub fn draw_sequence(&self) -> Result<Vec<Point>, Box<dyn std::error::Error>> {
|
||||||
if !self.capture_mode {
|
if !self.capture_mode {
|
||||||
return Ok(vec![])
|
return Ok(vec![]);
|
||||||
}
|
}
|
||||||
let seq = self.id;
|
let seq = self.id;
|
||||||
let mut pl = vec![];
|
let mut pl = vec![];
|
||||||
@ -213,62 +222,103 @@ impl Qualibration {
|
|||||||
y: 4095.,
|
y: 4095.,
|
||||||
color,
|
color,
|
||||||
};
|
};
|
||||||
|
|
||||||
let p4 = Point {
|
let p4 = Point {
|
||||||
x: 0.,
|
x: 0.,
|
||||||
y: 1000.,
|
y: 1000.,
|
||||||
color: Color {r: self.r as u8, g:0, b:0},
|
color: Color {
|
||||||
|
r: self.r as u8,
|
||||||
|
g: 0,
|
||||||
|
b: 0,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let p5 = Point {
|
let p5 = Point {
|
||||||
x: 4095.,
|
x: 4095.,
|
||||||
y: 1000.,
|
y: 1000.,
|
||||||
color: Color {r: self.r as u8, g:0, b:0},
|
color: Color {
|
||||||
|
r: self.r as u8,
|
||||||
|
g: 0,
|
||||||
|
b: 0,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let p6 = Point {
|
let p6 = Point {
|
||||||
x: 0.,
|
x: 0.,
|
||||||
y: 2000.,
|
y: 2000.,
|
||||||
color: Color {r: 0, g:self.g as u8, b:0},
|
color: Color {
|
||||||
|
r: 0,
|
||||||
|
g: self.g as u8,
|
||||||
|
b: 0,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let p7 = Point {
|
let p7 = Point {
|
||||||
x: 4095.,
|
x: 4095.,
|
||||||
y: 2000.,
|
y: 2000.,
|
||||||
color: Color {r: 0, g:self.g as u8, b:0},
|
color: Color {
|
||||||
|
r: 0,
|
||||||
|
g: self.g as u8,
|
||||||
|
b: 0,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let p8 = Point {
|
let p8 = Point {
|
||||||
x: 0.,
|
x: 0.,
|
||||||
y: 3000.,
|
y: 3000.,
|
||||||
color: Color {r: 0, g:0, b:self.b as u8},
|
color: Color {
|
||||||
|
r: 0,
|
||||||
|
g: 0,
|
||||||
|
b: self.b as u8,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let p9 = Point {
|
let p9 = Point {
|
||||||
x: 4095.,
|
x: 4095.,
|
||||||
y: 3000.,
|
y: 3000.,
|
||||||
color: Color {r: 0, g:0, b:self.b as u8},
|
color: Color {
|
||||||
|
r: 0,
|
||||||
|
g: 0,
|
||||||
|
b: self.b as u8,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let nb_all = self.nb_all as usize;
|
let nb_all = self.nb_all as usize;
|
||||||
let nb_visible = self.nb_visible as usize;
|
let nb_visible = self.nb_visible as usize;
|
||||||
let nb_wait = 20;
|
let nb_wait = 30; // ca permet de prendre de la vitess en y. Et donc ca permet de
|
||||||
|
// mieux voir les segment qui bouge peut au debut.
|
||||||
|
|
||||||
if seq.is_some() {
|
if seq.is_some() {
|
||||||
match seq.unwrap() {
|
match seq.unwrap() {
|
||||||
Sequence::PlayLineDotted => {
|
Sequence::PlayLineDotted
|
||||||
|
| Sequence::TakeMultiple(_)
|
||||||
|
| Sequence::ComputeLineDotted => {
|
||||||
// la on va faire une ligne qu'on peut observer
|
// la on va faire une ligne qu'on peut observer
|
||||||
pl = vec![];
|
pl = vec![];
|
||||||
let black = Color{r: 0, g: 0, b: 0};
|
let black = Color { r: 0, g: 0, b: 0 };
|
||||||
for _ in 0..nb_all {
|
for _ in 0..nb_all {
|
||||||
pl.push(Point{x: 0., y: 0., color: black});
|
pl.push(Point {
|
||||||
|
x: 0.,
|
||||||
|
y: 0.,
|
||||||
|
color: black,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
let len = (2*self.line_pos.len() + nb_wait) as f32;
|
let len = (2 * self.line_pos.len() + nb_wait) as f32;
|
||||||
for i in 0..nb_wait {
|
for i in 0..nb_wait {
|
||||||
let y = i as f32 * 4095. / len;
|
let y = i as f32 * 4095. / len;
|
||||||
pl.push(Point{x: 0., y, color: black});
|
pl.push(Point {
|
||||||
|
x: 0.,
|
||||||
|
y,
|
||||||
|
color: black,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
for i in 0..(self.line_pos.len() * 2) {
|
for i in 0..(self.line_pos.len() * 2) {
|
||||||
let y = (i + nb_wait) as f32 * 4095. / len;
|
let y = (i + nb_wait) as f32 * 4095. / len;
|
||||||
let c = if (i + nb_wait) % 2 == 0 && i < nb_visible {color} else {black};
|
let c = if (i + nb_wait) % 2 == 0 && i < nb_visible {
|
||||||
pl.push(Point{x: self.line_pos[i/2] as f32, y, color: c});
|
color
|
||||||
|
} else {
|
||||||
|
black
|
||||||
|
};
|
||||||
|
pl.push(Point {
|
||||||
|
x: self.line_pos[i / 2] as f32,
|
||||||
|
y,
|
||||||
|
color: c,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Sequence::WaitSpace => {
|
Sequence::WaitSpace => {
|
||||||
pl = draw::draw_line(&p0, &p1, nb_all, nb_visible)?;
|
pl = draw::draw_line(&p0, &p1, nb_all, nb_visible)?;
|
||||||
@ -343,6 +393,21 @@ impl Qualibration {
|
|||||||
match self.id.unwrap() {
|
match self.id.unwrap() {
|
||||||
//Sequence::Finish => Some(Sequence::Finish),
|
//Sequence::Finish => Some(Sequence::Finish),
|
||||||
Sequence::Finish => None,
|
Sequence::Finish => None,
|
||||||
|
Sequence::ComputeLineDotted => Some(Sequence::ComputeLineDotted),
|
||||||
|
Sequence::TakeMultiple(n) => {
|
||||||
|
if n > self.multiple {
|
||||||
|
next(&Sequence::TakeMultiple(u16::MAX))
|
||||||
|
} else {
|
||||||
|
next(&Sequence::TakeMultiple(n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Sequence::TakeMultipleEmpty(n) => {
|
||||||
|
if n > self.multiple {
|
||||||
|
next(&Sequence::TakeMultipleEmpty(u16::MAX))
|
||||||
|
} else {
|
||||||
|
next(&Sequence::TakeMultipleEmpty(n))
|
||||||
|
}
|
||||||
|
}
|
||||||
Sequence::SelectNbAll(n) => {
|
Sequence::SelectNbAll(n) => {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
Some(Sequence::SelectNbAll(2 - 1))
|
Some(Sequence::SelectNbAll(2 - 1))
|
||||||
@ -354,7 +419,7 @@ impl Qualibration {
|
|||||||
}
|
}
|
||||||
Sequence::WaitSpace => {
|
Sequence::WaitSpace => {
|
||||||
//println!("key: {}", self.key);
|
//println!("key: {}", self.key);
|
||||||
if self.key == 32 || !self.capture_mode{
|
if self.key == 32 || !self.capture_mode {
|
||||||
next(&Sequence::WaitSpace)
|
next(&Sequence::WaitSpace)
|
||||||
} else {
|
} else {
|
||||||
Some(Sequence::WaitSpace)
|
Some(Sequence::WaitSpace)
|
||||||
@ -362,7 +427,7 @@ impl Qualibration {
|
|||||||
}
|
}
|
||||||
Sequence::PlayLineDotted => {
|
Sequence::PlayLineDotted => {
|
||||||
//println!("key: {}", self.key);
|
//println!("key: {}", self.key);
|
||||||
if self.key == 32 {
|
if self.key == 32 || !self.capture_mode {
|
||||||
next(&Sequence::PlayLineDotted)
|
next(&Sequence::PlayLineDotted)
|
||||||
} else {
|
} else {
|
||||||
Some(Sequence::PlayLineDotted)
|
Some(Sequence::PlayLineDotted)
|
||||||
@ -384,6 +449,64 @@ impl Qualibration {
|
|||||||
pub fn compute_sequence(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn compute_sequence(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if self.id.is_some() {
|
if self.id.is_some() {
|
||||||
match self.id.unwrap() {
|
match self.id.unwrap() {
|
||||||
|
Sequence::ComputeLineDotted => {
|
||||||
|
let backgrounds = self.img[7..30].to_owned();
|
||||||
|
let lines_dots = self.img[30..52].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_LINEAR, // 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 => {
|
Sequence::ComputeSelectNbAll => {
|
||||||
let background: Mat;
|
let background: Mat;
|
||||||
let steps: Vec<Mat>;
|
let steps: Vec<Mat>;
|
||||||
@ -448,14 +571,16 @@ impl Qualibration {
|
|||||||
}
|
}
|
||||||
highgui::imshow("mixed bored", &mixed)?;
|
highgui::imshow("mixed bored", &mixed)?;
|
||||||
|
|
||||||
|
let size = self.dst_size;
|
||||||
// ici on va requadrer la partie de la projection laser de l'image
|
// ici on va requadrer la partie de la projection laser de l'image
|
||||||
let warped_image_size = Size::new(1024, 1024);
|
let warped_image_size = Size::new(size, size);
|
||||||
let roi_corners: Vec<OcvPoint> = self
|
let roi_corners: Vec<OcvPoint> = self
|
||||||
.border_pt
|
.border_pt
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(x, y)| OcvPoint::new(*x as i32, *y as i32))
|
.map(|(x, y)| OcvPoint::new(*x as i32, *y as i32))
|
||||||
.collect();
|
.collect();
|
||||||
let dst = [(0, 0), (0, 1024), (1024, 1024), (1024, 0)];
|
//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> =
|
let dst_corners: Vec<OcvPoint> =
|
||||||
dst.iter().map(|(x, y)| OcvPoint::new(*x, *y)).collect();
|
dst.iter().map(|(x, y)| OcvPoint::new(*x, *y)).collect();
|
||||||
let roi_corners_mat = Mat::from_slice(&roi_corners[..])?;
|
let roi_corners_mat = Mat::from_slice(&roi_corners[..])?;
|
||||||
@ -468,12 +593,14 @@ impl Qualibration {
|
|||||||
3.,
|
3.,
|
||||||
)?; //get homography
|
)?; //get homography
|
||||||
let mut warped_image = Mat::default();
|
let mut warped_image = Mat::default();
|
||||||
|
self.homography = h.clone();
|
||||||
|
self.h_size = warped_image_size.clone();
|
||||||
imgproc::warp_perspective(
|
imgproc::warp_perspective(
|
||||||
&mixed,
|
&mixed,
|
||||||
&mut warped_image,
|
&mut warped_image,
|
||||||
&h,
|
&h,
|
||||||
warped_image_size,
|
warped_image_size,
|
||||||
imgproc::INTER_LINEAR, // I dont see difference with INTER_CUBIC
|
imgproc::INTER_CUBIC, // I dont see difference with INTER_CUBIC
|
||||||
core::BORDER_CONSTANT,
|
core::BORDER_CONSTANT,
|
||||||
Scalar::default(),
|
Scalar::default(),
|
||||||
)?; // do perspective transformation
|
)?; // do perspective transformation
|
||||||
@ -502,7 +629,11 @@ impl Qualibration {
|
|||||||
let now = self.begin;
|
let now = self.begin;
|
||||||
let name = format!("image/");
|
let name = format!("image/");
|
||||||
create_dir(&name).unwrap_or(());
|
create_dir(&name).unwrap_or(());
|
||||||
let name = format!("image/{:0>6?}_{:0>9?}/", now.elapsed().as_secs(), now.elapsed().as_nanos());
|
let name = format!(
|
||||||
|
"image/{:0>6?}_{:0>9?}/",
|
||||||
|
now.elapsed().as_secs(),
|
||||||
|
now.elapsed().as_nanos()
|
||||||
|
);
|
||||||
create_dir(&name).unwrap_or(());
|
create_dir(&name).unwrap_or(());
|
||||||
//name.push_str(format!("image/{}_{}/", now.elapsed().as_secs(), now.elapsed().as_nanos()).as_str());
|
//name.push_str(format!("image/{}_{}/", now.elapsed().as_secs(), now.elapsed().as_nanos()).as_str());
|
||||||
//let name = format!("image/{now:?}/");
|
//let name = format!("image/{now:?}/");
|
||||||
@ -526,8 +657,8 @@ impl Qualibration {
|
|||||||
let dir = entry?;
|
let dir = entry?;
|
||||||
let path = dir.path();
|
let path = dir.path();
|
||||||
let c: Vec<&str> = path.to_str().unwrap().split("/").collect();
|
let c: Vec<&str> = path.to_str().unwrap().split("/").collect();
|
||||||
let d: Vec<_> = c[c.len()-1].chars().collect();
|
let d: Vec<_> = c[c.len() - 1].chars().collect();
|
||||||
let e: String = d[4..d.len()-4].iter().collect();
|
let e: String = d[4..d.len() - 4].iter().collect();
|
||||||
let img_id: i32 = e.parse()?;
|
let img_id: i32 = e.parse()?;
|
||||||
//println!("c: {c:?}");
|
//println!("c: {c:?}");
|
||||||
//let a: Vec<_> = path.to_str().unwrap().to_string().chars().collect();
|
//let a: Vec<_> = path.to_str().unwrap().to_string().chars().collect();
|
||||||
@ -572,7 +703,6 @@ impl Qualibration {
|
|||||||
) -> Result<((f64, f64), (f64, f64))> {
|
) -> Result<((f64, f64), (f64, f64))> {
|
||||||
let diff: Mat = image_diff(bord, background)?;
|
let diff: Mat = image_diff(bord, background)?;
|
||||||
|
|
||||||
|
|
||||||
//let (t1, s1, l1) = (
|
//let (t1, s1, l1) = (
|
||||||
// self.tresh.min_0 as f64,
|
// self.tresh.min_0 as f64,
|
||||||
// self.tresh.min_1 as f64,
|
// self.tresh.min_1 as f64,
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
use std::f64::consts::PI;
|
||||||
|
|
||||||
use super::Qualibration;
|
use super::Qualibration;
|
||||||
use super::DEBUG;
|
use super::DEBUG;
|
||||||
|
use crate::utils::Pt;
|
||||||
//use opencv::prelude::MatTraitConst;
|
//use opencv::prelude::MatTraitConst;
|
||||||
use opencv::prelude::*; //MatTraitConst;
|
use opencv::prelude::*; //MatTraitConst;
|
||||||
|
|
||||||
@ -8,6 +12,12 @@ use opencv::highgui::{self, create_trackbar, named_window, WINDOW_AUTOSIZE};
|
|||||||
use opencv::imgproc::{cvt_color, line, COLOR_BGR2GRAY};
|
use opencv::imgproc::{cvt_color, line, COLOR_BGR2GRAY};
|
||||||
use opencv::Result;
|
use opencv::Result;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
enum Cnt {
|
||||||
|
Beg(usize),
|
||||||
|
End(usize),
|
||||||
|
}
|
||||||
|
|
||||||
opencv::opencv_branch_4! {
|
opencv::opencv_branch_4! {
|
||||||
use opencv::imgproc::LINE_AA;
|
use opencv::imgproc::LINE_AA;
|
||||||
}
|
}
|
||||||
@ -18,7 +28,7 @@ opencv::not_opencv_branch_4! {
|
|||||||
use super::Treshold;
|
use super::Treshold;
|
||||||
const MAX_TRACKBAR: i32 = 255;
|
const MAX_TRACKBAR: i32 = 255;
|
||||||
|
|
||||||
fn draw_histograme_dbg(
|
pub fn draw_histograme_dbg(
|
||||||
window_name: &str,
|
window_name: &str,
|
||||||
histo: &Vec<f64>,
|
histo: &Vec<f64>,
|
||||||
(from, to): (usize, usize),
|
(from, to): (usize, usize),
|
||||||
@ -56,13 +66,18 @@ fn draw_histograme_dbg(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_histograme(window_name: &str, histo: &Vec<f64>) -> Result<()> {
|
pub fn draw_histograme(window_name: &str, histo: &Vec<f64>) -> Result<()> {
|
||||||
let v: VecN<f64, 4> = VecN::new(0., 0., 0., 255.);
|
let v: VecN<f64, 4> = VecN::new(0., 0., 0., 255.);
|
||||||
let color: 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 img = Mat::new_rows_cols_with_default(
|
||||||
|
histo.len() as i32 * 2,
|
||||||
|
histo.len() as i32 * 2,
|
||||||
|
CV_8UC3,
|
||||||
|
v,
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut max = 0.;
|
let mut max = 0.;
|
||||||
for i in 0..256 {
|
for i in 0..(histo.len() - 1) {
|
||||||
if histo[i] > max {
|
if histo[i] > max {
|
||||||
max = histo[i];
|
max = histo[i];
|
||||||
}
|
}
|
||||||
@ -70,13 +85,15 @@ fn draw_histograme(window_name: &str, histo: &Vec<f64>) -> Result<()> {
|
|||||||
|
|
||||||
let v_log = 10.;
|
let v_log = 10.;
|
||||||
|
|
||||||
for i in 0..255 {
|
for i in 0..(histo.len() - 1) {
|
||||||
let x1 = ((i + 0) * 2) as i32;
|
let x1 = ((i + 0) * 2) as i32;
|
||||||
let x2 = ((i + 1) * 2) as i32;
|
let x2 = ((i + 1) * 2) as i32;
|
||||||
let y1 =
|
let y1 = ((histo[i + 0] as f64 + 1.).log(v_log) / (max as f64).log(v_log)
|
||||||
((histo[i + 0] as f64 + 1.).log(v_log) / (max as f64).log(v_log) * 2. * 256.) as i32;
|
* 2.
|
||||||
let y2 =
|
* histo.len() as f64) as i32;
|
||||||
((histo[i + 1] 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.
|
||||||
|
* histo.len() as f64) as i32;
|
||||||
let pt1 = OcvPoint::new(x1, y1);
|
let pt1 = OcvPoint::new(x1, y1);
|
||||||
let pt2 = OcvPoint::new(x2, y2);
|
let pt2 = OcvPoint::new(x2, y2);
|
||||||
line(&mut img, pt1, pt2, color, 1, LINE_AA, 0)?;
|
line(&mut img, pt1, pt2, color, 1, LINE_AA, 0)?;
|
||||||
@ -87,7 +104,7 @@ fn draw_histograme(window_name: &str, histo: &Vec<f64>) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_histograme_bgr(window_name: &str, histo: &Vec<Vec<f64>>) -> Result<()> {
|
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 v: VecN<f64, 4> = VecN::new(0., 0., 0., 255.);
|
||||||
let b: VecN<f64, 4> = VecN::new(255., 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 g: VecN<f64, 4> = VecN::new(0., 255., 0., 255.);
|
||||||
@ -126,7 +143,7 @@ fn draw_histograme_bgr(window_name: &str, histo: &Vec<Vec<f64>>) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_histograme_bgr_tresh(
|
pub fn draw_histograme_bgr_tresh(
|
||||||
window_name: &str,
|
window_name: &str,
|
||||||
histo: &Vec<Vec<f64>>,
|
histo: &Vec<Vec<f64>>,
|
||||||
tresh: &Treshold,
|
tresh: &Treshold,
|
||||||
@ -213,6 +230,290 @@ 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_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> {
|
pub fn image_diff(frame: &Mat, frame_prev: &Mat) -> Result<Mat> {
|
||||||
let mut diff_bgr = Mat::default();
|
let mut diff_bgr = Mat::default();
|
||||||
let mut diff_bgr_2 = Mat::default();
|
let mut diff_bgr_2 = Mat::default();
|
||||||
@ -233,7 +534,7 @@ pub fn image_diff(frame: &Mat, frame_prev: &Mat) -> Result<Mat> {
|
|||||||
Ok(d_bgr)
|
Ok(d_bgr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn histogram_3d(m: &Mat, nb_liss: i32) -> Result<Vec<Vec<f64>>> {
|
pub fn histogram_3d(m: &Mat, nb_liss: i32) -> Result<Vec<Vec<f64>>> {
|
||||||
let (cols, rows) = (m.cols(), m.rows());
|
let (cols, rows) = (m.cols(), m.rows());
|
||||||
let mut histo = vec![vec![0.; 256]; 3];
|
let mut histo = vec![vec![0.; 256]; 3];
|
||||||
|
|
||||||
@ -262,7 +563,7 @@ fn histogram_3d(m: &Mat, nb_liss: i32) -> Result<Vec<Vec<f64>>> {
|
|||||||
Ok(histo)
|
Ok(histo)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn histogram_1d(m: &Mat, nb_liss: i32) -> Result<Vec<f64>> {
|
pub fn histogram_1d(m: &Mat, nb_liss: i32) -> Result<Vec<f64>> {
|
||||||
let (cols, rows) = (m.cols(), m.rows());
|
let (cols, rows) = (m.cols(), m.rows());
|
||||||
let mut histo = vec![0; 256];
|
let mut histo = vec![0; 256];
|
||||||
let mut m_gray = Mat::default();
|
let mut m_gray = Mat::default();
|
||||||
@ -291,7 +592,7 @@ fn histogram_1d(m: &Mat, nb_liss: i32) -> Result<Vec<f64>> {
|
|||||||
Ok(histo)
|
Ok(histo)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn first_invert(histo: &Vec<f64>) -> ((usize, f64), (usize, f64)) {
|
pub fn first_invert(histo: &Vec<f64>) -> ((usize, f64), (usize, f64)) {
|
||||||
// on applique un log puis on normalise mar le log du max
|
// on applique un log puis on normalise mar le log du max
|
||||||
let mut normalised = vec![0.; histo.len()];
|
let mut normalised = vec![0.; histo.len()];
|
||||||
let mut p1 = vec![0.; histo.len() / 2];
|
let mut p1 = vec![0.; histo.len() / 2];
|
||||||
@ -356,7 +657,11 @@ pub fn trackbar_line_segment(mem: &mut Qualibration, winname: &str) -> Result<()
|
|||||||
//highgui
|
//highgui
|
||||||
let winname = format!("{}: {}", winname, 0); //"bord selected: 0";
|
let winname = format!("{}: {}", winname, 0); //"bord selected: 0";
|
||||||
named_window(winname.as_str(), WINDOW_AUTOSIZE)?;
|
named_window(winname.as_str(), WINDOW_AUTOSIZE)?;
|
||||||
highgui::move_window(winname.as_str(), 20, 20)?;
|
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(
|
create_trackbar(
|
||||||
"canny min",
|
"canny min",
|
||||||
@ -405,7 +710,7 @@ pub fn trackbar_line_segment(mem: &mut Qualibration, winname: &str) -> Result<()
|
|||||||
"max_gap : ",
|
"max_gap : ",
|
||||||
winname.as_str(),
|
winname.as_str(),
|
||||||
Some(&mut mem.hough_param.max_line_gap),
|
Some(&mut mem.hough_param.max_line_gap),
|
||||||
500000,
|
50000,
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -433,23 +738,25 @@ pub fn line_pos(mem: &mut Qualibration, winname: &str) -> Result<()> {
|
|||||||
|
|
||||||
pub fn adding_trackbar(mut mem: &mut Qualibration, winname: &str) -> Result<()> {
|
pub fn adding_trackbar(mut mem: &mut Qualibration, winname: &str) -> Result<()> {
|
||||||
//println!("winname: {winname}");
|
//println!("winname: {winname}");
|
||||||
line_pos(&mut mem , "Play Line")?;
|
//line_pos(&mut mem, "Play Line")?;
|
||||||
trackbar_init_param(mem, "init_param")?;
|
//trackbar_init_param(mem, "init_param")?;
|
||||||
//named_window(winname, WINDOW_AUTOSIZE)?;
|
|
||||||
//associate_trackbar(winname, &mut mem.tresh)?;
|
named_window("histo bgr", WINDOW_AUTOSIZE)?;
|
||||||
//create_trackbar(
|
associate_trackbar("histo bgr", &mut mem.tresh)?;
|
||||||
// "nb_liss",
|
create_trackbar(
|
||||||
// winname,
|
"nb_liss",
|
||||||
// Some(&mut mem.nb_liss),
|
"histo bgr",
|
||||||
// MAX_TRACKBAR,
|
Some(&mut mem.nb_liss),
|
||||||
// None,
|
MAX_TRACKBAR,
|
||||||
//)?;
|
None,
|
||||||
//trackbar_line_segment(mem, winname)?;
|
)?;
|
||||||
|
|
||||||
|
//trackbar_line_segment(mem, "line detector")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn associate_trackbar(winname: &str, tresh: &mut Treshold) -> Result<()> {
|
pub fn associate_trackbar(winname: &str, tresh: &mut Treshold) -> Result<()> {
|
||||||
create_trackbar(
|
create_trackbar(
|
||||||
"blue min: ",
|
"blue min: ",
|
||||||
winname,
|
winname,
|
||||||
|
43
src/utils.rs
43
src/utils.rs
@ -2,9 +2,13 @@ use crate::point::Point;
|
|||||||
static NEAR_ZERO: f64 = 0.000001;
|
static NEAR_ZERO: f64 = 0.000001;
|
||||||
|
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
use std::ops::AddAssign;
|
||||||
use std::ops::Mul;
|
use std::ops::Mul;
|
||||||
use std::ops::MulAssign;
|
use std::ops::MulAssign;
|
||||||
use std::ops::Sub;
|
use std::ops::Sub;
|
||||||
|
use std::ops::Div;
|
||||||
|
use std::ops::DivAssign;
|
||||||
|
//use std::ops::BitXor
|
||||||
|
|
||||||
impl Add for Pt {
|
impl Add for Pt {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
@ -17,6 +21,14 @@ impl Add for Pt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AddAssign for Pt {
|
||||||
|
fn add_assign(&mut self, other: Self) {
|
||||||
|
self.x += other.x;
|
||||||
|
self.y += other.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Sub for Pt {
|
impl Sub for Pt {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
@ -46,6 +58,24 @@ impl Mul<f64> for Pt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Div<f64> for Pt {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn div(self, rhs: f64) -> Self {
|
||||||
|
Pt {
|
||||||
|
x: self.x / rhs,
|
||||||
|
y: self.y / rhs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DivAssign<f64> for Pt {
|
||||||
|
fn div_assign(&mut self, rhs: f64) {
|
||||||
|
self.x /= rhs;
|
||||||
|
self.y /= rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
|
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
|
||||||
pub struct Pt {
|
pub struct Pt {
|
||||||
pub x: f64,
|
pub x: f64,
|
||||||
@ -75,9 +105,16 @@ impl Pt {
|
|||||||
Self { x, y }
|
Self { x, y }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mul_assign(&mut self, rhs: f64) {
|
pub fn cross(&self, other: &Pt) -> f64 {
|
||||||
self.x *= rhs;
|
self.x * other.x + self.y * other.y
|
||||||
self.y *= rhs;
|
}
|
||||||
|
|
||||||
|
pub fn mean(pts: &[Pt]) -> Pt {
|
||||||
|
let mut mean = Pt{x: 0., y: 0.};
|
||||||
|
for pt in pts {
|
||||||
|
mean += *pt;
|
||||||
|
}
|
||||||
|
mean / (pts.len() as f64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user