slight speedup by passing x,y offset instead of slicing the windows
This commit is contained in:
parent
7c7ae29bf9
commit
f9b066a166
2 changed files with 20 additions and 15 deletions
|
@ -22,7 +22,7 @@ fn main() {
|
||||||
|
|
||||||
|
|
||||||
warn!("test");
|
warn!("test");
|
||||||
let haar = visualhaar::HaarClassifier::from_xml("haarcascade_frontalface_alt2.xml").unwrap();
|
let haar = visualhaar::HaarClassifier::from_xml("../haarcascade_frontalface_alt2.xml").unwrap();
|
||||||
// println!("Haar: {:?}", haar);
|
// println!("Haar: {:?}", haar);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,19 +52,19 @@ pub struct HaarClassifierFeature {
|
||||||
|
|
||||||
|
|
||||||
impl HaarClassifierFeature{
|
impl HaarClassifierFeature{
|
||||||
fn compute_feature(&self, image_window: &nd::ArrayView2<u32>, scale: &f64) -> f64 {
|
fn compute_feature(&self, image_window: &nd::ArrayView2<u32>, scale: &f64, x: usize, y: usize, scan_window_size: usize) -> f64 {
|
||||||
let mut score = 0.;
|
let mut score = 0.;
|
||||||
|
|
||||||
for rect in &self.rects{
|
for rect in &self.rects{
|
||||||
score += rect.compute_rect(image_window, scale);
|
score += rect.compute_rect(image_window, scale, x, y, scan_window_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
score
|
score
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&self, draw_window: &mut nd::ArrayViewMut2<i16>, scale: &f64) {
|
fn draw(&self, draw_window: &mut nd::ArrayViewMut2<i16>, scale: &f64, x: usize, y: usize, scan_window_size: usize) {
|
||||||
for rect in &self.rects{
|
for rect in &self.rects{
|
||||||
rect.draw(draw_window, scale);
|
rect.draw(draw_window, scale, x, y, scan_window_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,23 +92,25 @@ impl HaarClassifierFeatureRect{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The feature sum is finally calculated by first summing all values of the pixels inside the rectangle and then multiplying it with the weight factor. Finally, those weighted sums are combined together to yield as a final feature value. Keep in mind that all the coordinates retrieved for a single feature are in relation to the window/model size and not the complete image which is processed.
|
/// The feature sum is finally calculated by first summing all values of the pixels inside the rectangle and then multiplying it with the weight factor. Finally, those weighted sums are combined together to yield as a final feature value. Keep in mind that all the coordinates retrieved for a single feature are in relation to the window/model size and not the complete image which is processed.
|
||||||
fn compute_rect(&self, image_window: &nd::ArrayView2<u32>, scale: &f64) -> f64 {
|
fn compute_rect(&self, image_window: &nd::ArrayView2<u32>, scale: &f64, x: usize, y: usize, scan_window_size: usize) -> f64 {
|
||||||
let (x1, y1, x2, y2) = self.get_coordinates_for_scale(scale);
|
let (x1, y1, x2, y2) = self.get_coordinates_for_scale(scale);
|
||||||
|
|
||||||
let sum = (image_window[[y2,x2]] + image_window[[y1,x1]] - image_window[[y1, x2]] - image_window[[y2, x1]]) as f64;
|
let sum = (image_window[[y+y2,x+x2]] + image_window[[y+y1,x+x1]] - image_window[[y+y1, x+x2]] - image_window[[y+y2, x+x1]]) as f64;
|
||||||
let sum = (sum/(scale*scale)) * self.weight as f64; // normalise: when the window grows, all values of the integral image become bigger by a factor scale-squared
|
let sum = (sum/(scale*scale)) * self.weight as f64; // normalise: when the window grows, all values of the integral image become bigger by a factor scale-squared
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn draw(&self, draw_window: &mut nd::ArrayViewMut2<i16>, scale: &f64) {
|
fn draw(&self, draw_window: &mut nd::ArrayViewMut2<i16>, scale: &f64, x: usize, y: usize, scan_window_size: usize) {
|
||||||
let (x1, y1, x2, y2) = self.get_coordinates_for_scale(scale);
|
let (x1, y1, x2, y2) = self.get_coordinates_for_scale(scale);
|
||||||
|
|
||||||
// TODO how to speed this up?
|
// TODO how to speed this up?
|
||||||
|
|
||||||
// info!("Draw {} {} {} {} ({:?}),", x1, y1, x2, y2,self);
|
// info!("Draw {} {} {} {} ({:?}),", x1, y1, x2, y2,self);
|
||||||
let mut rect = draw_window.slice_mut(s![y1..y2, x1..x2]); // semi slow (initially 500ms)
|
let mut rect = draw_window.slice_mut(s![y+y1..y+y2, x+x1..x+x2]); // semi slow (initially 500ms)
|
||||||
|
|
||||||
rect += self.weight; // super slow (initially 10.000 ms)
|
rect += self.weight; // super slow (initially 10.000 ms)
|
||||||
|
|
||||||
// info!("add")
|
// info!("add")
|
||||||
// for x in x1..x2{
|
// for x in x1..x2{
|
||||||
// for y in y1..y2{
|
// for y in y1..y2{
|
||||||
|
@ -342,6 +344,9 @@ impl HaarClassifier {
|
||||||
img_bw.dimensions().0 as usize,
|
img_bw.dimensions().0 as usize,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
let mut integral_view = integral.view();
|
||||||
|
let mut output_draw_frame = output_frame.view_mut();
|
||||||
|
|
||||||
// info!("Frame: {:?} {:?}", integral[[0,0]], integral[[integral.dim().0-1,integral.dim().1-1]]);
|
// info!("Frame: {:?} {:?}", integral[[0,0]], integral[[integral.dim().0-1,integral.dim().1-1]]);
|
||||||
|
|
||||||
// let rect = integral.slice(s![3..5, 2..4]);
|
// let rect = integral.slice(s![3..5, 2..4]);
|
||||||
|
@ -364,9 +369,9 @@ impl HaarClassifier {
|
||||||
// step by scale.ceil() as this is 1px in the model's size. (small is probably unnecesarily fine-grained)
|
// step by scale.ceil() as this is 1px in the model's size. (small is probably unnecesarily fine-grained)
|
||||||
for x in (0..(img_bw.dimensions().0 as usize - scan_window_size)).step_by((scale * 1.0).ceil() as usize) {
|
for x in (0..(img_bw.dimensions().0 as usize - scan_window_size)).step_by((scale * 1.0).ceil() as usize) {
|
||||||
for y in (0..(img_bw.dimensions().1 as usize - scan_window_size)).step_by((scale * 1.0).ceil() as usize) {
|
for y in (0..(img_bw.dimensions().1 as usize - scan_window_size)).step_by((scale * 1.0).ceil() as usize) {
|
||||||
let window = integral.slice(s![y..y+scan_window_size, x..x+scan_window_size]);
|
// let window = integral.slice(s![y..y+scan_window_size, x..x+scan_window_size]);
|
||||||
let mut output_window = output_frame.slice_mut(s![y..y+scan_window_size, x..x+scan_window_size]);
|
// let mut output_window = output_frame.slice_mut(s![y..y+scan_window_size, x..x+scan_window_size]);
|
||||||
if self.scan_window(window, scale, &mut output_window) {
|
if self.scan_window(integral_view, scale, &mut output_draw_frame, x, y, window_size) {
|
||||||
count_faces += 1;
|
count_faces += 1;
|
||||||
} else {
|
} else {
|
||||||
count_not_faces += 1;
|
count_not_faces += 1;
|
||||||
|
@ -429,14 +434,14 @@ impl HaarClassifier {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scan_window(&self, integral_window: nd::ArrayView2<u32>, scale: f64, output_window: &mut nd::ArrayViewMut2<i16>) -> bool{
|
fn scan_window(&self, integral_window: nd::ArrayView2<u32>, scale: f64, output_window: &mut nd::ArrayViewMut2<i16>, x: usize, y: usize, scan_window_size: usize) -> bool{
|
||||||
let mut failed = false; // let's assume the cascade will work
|
let mut failed = false; // let's assume the cascade will work
|
||||||
for stage in &self.stages{
|
for stage in &self.stages{
|
||||||
let mut stage_sum = 0.;
|
let mut stage_sum = 0.;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
for classifier in &stage.weak_classifiers{
|
for classifier in &stage.weak_classifiers{
|
||||||
// or 'stumps'
|
// or 'stumps'
|
||||||
let feature = classifier.feature.compute_feature(&integral_window, &scale);
|
let feature = classifier.feature.compute_feature(&integral_window, &scale, x, y, scan_window_size);
|
||||||
let stddev = 1.; // TODO what should we use here?
|
let stddev = 1.; // TODO what should we use here?
|
||||||
let threshold = classifier.threshold * stddev;
|
let threshold = classifier.threshold * stddev;
|
||||||
let idx = if feature < threshold {
|
let idx = if feature < threshold {
|
||||||
|
@ -445,7 +450,7 @@ impl HaarClassifier {
|
||||||
} else {
|
} else {
|
||||||
stage_sum += classifier.leaf_values[1];
|
stage_sum += classifier.leaf_values[1];
|
||||||
// weak classifier bigger then threshold... draw it!
|
// weak classifier bigger then threshold... draw it!
|
||||||
classifier.feature.draw(output_window, &scale);
|
classifier.feature.draw(output_window, &scale, x, y, scan_window_size);
|
||||||
i+=1;
|
i+=1;
|
||||||
classifier.right
|
classifier.right
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue