Skip to content

Commit

Permalink
Add Background Subtractors.
Browse files Browse the repository at this point in the history
  • Loading branch information
yuvallanger committed Feb 23, 2019
1 parent 3259436 commit 5a8e12c
Show file tree
Hide file tree
Showing 4 changed files with 428 additions and 26 deletions.
116 changes: 95 additions & 21 deletions native/video.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,98 @@

extern "C" {

void* cv_term_criteria_new(int type, int count, double epsilon) {
return new cv::TermCriteria(type, count, epsilon);
}

void cv_term_criteria_drop(cv::TermCriteria* criteria) {
delete criteria;
criteria = nullptr;
}

RotatedRect cv_camshift(cv::Mat* bp_image, Rect crect, cv::TermCriteria* criteria) {
cv::Rect rect(crect.x, crect.y, crect.width, crect.height);
cv::RotatedRect rr = cv::CamShift(*bp_image, rect, *criteria);
RotatedRect c_rr;
c_rr.center.x = rr.center.x;
c_rr.center.y = rr.center.y;
c_rr.size.width = rr.size.width;
c_rr.size.height = rr.size.height;
c_rr.angle = rr.angle;
return c_rr;
}
}
void* cv_term_criteria_new(int type, int count, double epsilon) {
return new cv::TermCriteria(type, count, epsilon);
}

void cv_term_criteria_drop(cv::TermCriteria* criteria) {
delete criteria;
criteria = nullptr;
}

RotatedRect cv_camshift(cv::Mat* bp_image, Rect crect, cv::TermCriteria* criteria) {
cv::Rect rect(crect.x, crect.y, crect.width, crect.height);
cv::RotatedRect rr = cv::CamShift(*bp_image, rect, *criteria);
RotatedRect c_rr;
c_rr.center.x = rr.center.x;
c_rr.center.y = rr.center.y;
c_rr.size.width = rr.size.width;
c_rr.size.height = rr.size.height;
c_rr.angle = rr.angle;
return c_rr;
}

// BackgroundSubtractorKNN

void* cv_create_background_subtractor_knn(
int history,
double dist2Threshold,
bool detectShadows
) {
cv::Ptr<cv::BackgroundSubtractorKNN> background_subtractor = cv::createBackgroundSubtractorKNN(history, dist2Threshold, detectShadows);
return new cv::Ptr<cv::BackgroundSubtractorKNN>(background_subtractor);
};

void* cv_create_background_subtractor_knn_default() {
cv::Ptr<cv::BackgroundSubtractorKNN> background_subtractor = cv::createBackgroundSubtractorKNN();
return new cv::Ptr<cv::BackgroundSubtractorKNN>(background_subtractor);
};

void cv_background_subtractor_knn_drop(cv::Ptr<cv::BackgroundSubtractorKNN>* background_subtractor) {
delete background_subtractor;
background_subtractor = nullptr;
}

void cv_background_subtractor_knn_apply(
cv::Ptr<cv::BackgroundSubtractorKNN> background_subtractor,
cv::Mat* input_image,
cv::Mat* output_foreground,
double learning_rate
) {
background_subtractor->apply(*input_image, *output_foreground, learning_rate);
};

void cv_background_subtractor_knn_get_background_image(
cv::Ptr<cv::BackgroundSubtractorKNN> background_subtractor,
cv::Mat* output_background
) {
background_subtractor->getBackgroundImage(*output_background);
};

// BackgroundSubtractorMOG2

void* cv_create_background_subtractor_mog2(
int history,
double dist2Threshold,
bool detectShadows
) {
cv::Ptr<cv::BackgroundSubtractorMOG2> background_subtractor = cv::createBackgroundSubtractorMOG2(history, dist2Threshold, detectShadows);
return new cv::Ptr<cv::BackgroundSubtractorMOG2>(background_subtractor);
};

void* cv_create_background_subtractor_mog2_default() {
cv::Ptr<cv::BackgroundSubtractorMOG2> background_subtractor = cv::createBackgroundSubtractorMOG2();
return new cv::Ptr<cv::BackgroundSubtractorMOG2>(background_subtractor);
};

void cv_background_subtractor_mog2_drop(cv::Ptr<cv::BackgroundSubtractorMOG2>* background_subtractor) {
delete background_subtractor;
background_subtractor = nullptr;
}

void cv_background_subtractor_mog2_apply(
cv::Ptr<cv::BackgroundSubtractorMOG2> background_subtractor,
cv::Mat* input_image,
cv::Mat* output_foreground,
double learning_rate
) {
background_subtractor->apply(*input_image, *output_foreground, learning_rate);
};

void cv_background_subtractor_mog2_get_background_image(
cv::Ptr<cv::BackgroundSubtractorMOG2> background_subtractor,
cv::Mat* output_background
) {
background_subtractor->getBackgroundImage(*output_background);
};
}
55 changes: 52 additions & 3 deletions native/video.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,60 @@

#include "common.h"
#include <opencv2/video/tracking.hpp>
#include <opencv2/video/background_segm.hpp>

extern "C" {
void* cv_term_criteria_new(int type, int count, double epsilon);
void cv_term_criteria_drop(cv::TermCriteria* criteria);
RotatedRect cv_camshift(cv::Mat* back_project_image, Rect window, cv::TermCriteria* criteria);

// BackgroundSubtractorKNN

void* cv_create_background_subtractor_knn(
int history,
double dist2Threshold,
bool detectShadows
);

void* cv_create_background_subtractor_knn_default();

void cv_background_subtractor_knn_drop(cv::Ptr<cv::BackgroundSubtractorKNN>* background_subtractor);

void cv_background_subtractor_knn_apply(
cv::Ptr<cv::BackgroundSubtractorKNN> background_subtractor,
cv::Mat* input_image,
cv::Mat* output_foreground,
double learning_rate
);

void cv_background_subtractor_knn_get_background_image(
cv::Ptr<cv::BackgroundSubtractorKNN> background_subtractor,
cv::Mat* output_background
);

// BackgroundSubtractorMOG2

void* cv_create_background_subtractor_mog2(
int history,
double dist2Threshold,
bool detectShadows
);

void* cv_create_background_subtractor_mog2_default();

void cv_background_subtractor_mog2_drop(cv::Ptr<cv::BackgroundSubtractorMOG2>* background_subtractor);

void cv_background_subtractor_mog2_apply(
cv::Ptr<cv::BackgroundSubtractorMOG2> background_subtractor,
cv::Mat* input_image,
cv::Mat* output_foreground,
double learning_rate
);

void cv_background_subtractor_mog2_get_background_image(
cv::Ptr<cv::BackgroundSubtractorMOG2> background_subtractor,
cv::Mat* output_background
);

void* cv_term_criteria_new(int type, int count, double epsilon);
void cv_term_criteria_drop(cv::TermCriteria* criteria);
RotatedRect cv_camshift(cv::Mat* back_project_image, Rect window, cv::TermCriteria* criteria);
}
#endif // CV_RS_VIDEO_H
194 changes: 192 additions & 2 deletions src/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ pub mod tracking {
//! Object Tracking, see [OpenCV video
//! track](http://docs.opencv.org/3.1.0/dc/d6b/group__video__track.html)

use core::*;
use mat::*;
use core::{CTermCriteria, Rect, RotatedRect, TermCriteria};
use mat::{CMat, Mat};

// =========================================================================
// VideoTrack
Expand All @@ -29,4 +29,194 @@ pub mod tracking {
pub mod analysis {
//! Motion Analysis, see [OpenCV video
//! motion](http://docs.cv.org/3.1.0/de/de1/group__video__motion.html)

pub use self::background_subtractor_knn::BackgroundSubtractorKNN;
pub use self::background_subtractor_mog2::BackgroundSubtractorMOG2;

mod background_subtractor_knn {
use mat::{CMat, Mat};

extern "C" {
fn cv_create_background_subtractor_knn(
history: i64,
dist2threshold: f64,
detect_shadows: bool,
) -> *mut CPtrBackgroundSubtractorKNN;

fn cv_create_background_subtractor_knn_default() -> *mut CPtrBackgroundSubtractorKNN;

fn cv_background_subtractor_knn_drop(background_subtractor: *mut CPtrBackgroundSubtractorKNN);

fn cv_background_subtractor_knn_apply(
background_subtractor: *mut CPtrBackgroundSubtractorKNN,
input_image: *const CMat,
output_foreground: *mut CMat,
learning_rate: f64,
);

fn cv_background_subtractor_knn_get_background_image(
background_subtractor: *mut CPtrBackgroundSubtractorKNN,
output_background: *mut CMat,
);
}

pub(crate) enum CPtrBackgroundSubtractorKNN {}

#[derive(Clone, Debug)]
/// A KNN Background Subtractor algorithm.
pub struct BackgroundSubtractorKNN {
inner: *mut CPtrBackgroundSubtractorKNN,
exposed_to_image: bool,
}

impl BackgroundSubtractorKNN {
/// Makes a new BackgroundSubtractorKNN.
pub fn new(history: i64, dist2threshold: f64, detect_shadows: bool) -> Self {
let bgs = unsafe { cv_create_background_subtractor_knn(history, dist2threshold, detect_shadows) };

BackgroundSubtractorKNN {
inner: bgs,
exposed_to_image: false,
}
}

/// Computes the next foreground mask from input image.
pub fn apply(&mut self, image: &Mat, learning_rate: f64) -> Mat {
#[allow(unused_mut)]
let mut c_foreground = CMat::new();
unsafe {
cv_background_subtractor_knn_apply(self.inner, image.inner, c_foreground, learning_rate);
};
self.exposed_to_image = true;

Mat::from_raw(c_foreground)
}

/// Return the background image.
pub fn background_image(self) -> Option<Mat> {
if self.exposed_to_image {
#[allow(unused_mut)]
let mut c_background = CMat::new();

unsafe {
cv_background_subtractor_knn_get_background_image(self.inner, c_background);
};

Some(Mat::from_raw(c_background))
} else {
None
}
}
}

impl Default for BackgroundSubtractorKNN {
fn default() -> Self {
let bgs = unsafe { cv_create_background_subtractor_knn_default() };

BackgroundSubtractorKNN {
inner: bgs,
exposed_to_image: false,
}
}
}
impl Drop for BackgroundSubtractorKNN {
fn drop(&mut self) {
unsafe { cv_background_subtractor_knn_drop(self.inner) }
}
}
}

mod background_subtractor_mog2 {
use mat::{CMat, Mat};

extern "C" {
fn cv_create_background_subtractor_mog2(
history: i64,
dist2threshold: f64,
detect_shadows: bool,
) -> *mut CPtrBackgroundSubtractorMOG2;

fn cv_create_background_subtractor_mog2_default() -> *mut CPtrBackgroundSubtractorMOG2;

fn cv_background_subtractor_mog2_drop(background_subtractor: *mut CPtrBackgroundSubtractorMOG2);

fn cv_background_subtractor_mog2_apply(
background_subtractor: *mut CPtrBackgroundSubtractorMOG2,
input_image: *const CMat,
output_foreground: *mut CMat,
learning_rate: f64,
);

fn cv_background_subtractor_mog2_get_background_image(
background_subtractor: *mut CPtrBackgroundSubtractorMOG2,
output_background: *mut CMat,
);
}

pub(crate) enum CPtrBackgroundSubtractorMOG2 {}

#[derive(Clone, Debug)]
/// A MOG2 Background Subtractor algorithm.
pub struct BackgroundSubtractorMOG2 {
pub(crate) inner: *mut CPtrBackgroundSubtractorMOG2,
exposed_to_image: bool,
}

impl BackgroundSubtractorMOG2 {
/// Makes a new BackgroundSubtractorMOG2.
pub fn new(history: i64, dist2threshold: f64, detect_shadows: bool) -> Self {
let background_subtractor =
unsafe { cv_create_background_subtractor_mog2(history, dist2threshold, detect_shadows) };

BackgroundSubtractorMOG2 {
inner: background_subtractor,
exposed_to_image: false,
}
}

/// Computes the next foreground mask from input image.
pub fn apply(&mut self, image: &Mat, learning_rate: f64) -> Mat {
#[allow(unused_mut)]
let mut c_foreground = CMat::new();

unsafe {
cv_background_subtractor_mog2_apply(self.inner, image.inner, c_foreground, learning_rate);
}
self.exposed_to_image = true;

Mat::from_raw(c_foreground)
}

/// Return the background image.
pub fn background_image(self) -> Option<Mat> {
if self.exposed_to_image {
#[allow(unused_mut)]
let mut c_background = CMat::new();

unsafe {
cv_background_subtractor_mog2_get_background_image(self.inner, c_background);
}
Some(Mat::from_raw(c_background))
} else {
None
}
}
}

impl Default for BackgroundSubtractorMOG2 {
fn default() -> Self {
let background_subtractor = unsafe { cv_create_background_subtractor_mog2_default() };

BackgroundSubtractorMOG2 {
inner: background_subtractor,
exposed_to_image: false,
}
}
}
impl Drop for BackgroundSubtractorMOG2 {
fn drop(&mut self) {
unsafe { cv_background_subtractor_mog2_drop(self.inner) }
}
}
}
}
Loading

0 comments on commit 5a8e12c

Please sign in to comment.