use super::core::*;
use super::errors::*;
use super::*;
use failure::Error;
use std::ffi::CString;
use std::os::raw::{c_char, c_double, c_int};
use std::path::Path;
use std::vec::Vec;
enum CCascadeClassifier {}
extern "C" {
fn cv_cascade_classifier_new() -> *mut CCascadeClassifier;
fn cv_cascade_classifier_load(cc: *mut CCascadeClassifier, p: *const c_char) -> bool;
fn cv_cascade_classifier_drop(p: *mut CCascadeClassifier);
fn cv_cascade_classifier_detect(
cc: *mut CCascadeClassifier,
cmat: *mut CMat,
vec_of_rect: *mut CVec<Rect>,
scale_factor: c_double,
min_neighbors: c_int,
flags: c_int,
min_size: Size2i,
max_size: Size2i,
);
}
unsafe impl Send for CascadeClassifier {}
pub trait ObjectDetect {
fn detect(&self, image: &Mat) -> Vec<(Rect, f64)>;
}
#[derive(Debug)]
pub struct CascadeClassifier {
inner: *mut CCascadeClassifier,
}
impl ObjectDetect for CascadeClassifier {
fn detect(&self, image: &Mat) -> Vec<(Rect, f64)> {
self.detect_multiscale(image)
.into_iter()
.map(|r| (r, 0f64))
.collect::<Vec<_>>()
}
}
impl CascadeClassifier {
pub fn new() -> CascadeClassifier {
CascadeClassifier {
inner: unsafe { cv_cascade_classifier_new() },
}
}
pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
let cc = CascadeClassifier::new();
cc.load(path)?;
Ok(cc)
}
pub fn load<P: AsRef<Path>>(&self, path: P) -> Result<(), Error> {
if let Some(p) = path.as_ref().to_str() {
let s = CString::new(p)?;
if unsafe { cv_cascade_classifier_load(self.inner, (&s).as_ptr()) } {
return Ok(());
}
}
Err(CvError::InvalidPath(path.as_ref().to_path_buf()).into())
}
pub fn detect_multiscale(&self, mat: &Mat) -> Vec<Rect> {
self.detect_with_params(mat, 1.1, 3, Size2i::default(), Size2i::default())
}
pub fn detect_with_params(
&self,
mat: &Mat,
scale_factor: f32,
min_neighbors: c_int,
min_size: Size2i,
max_size: Size2i,
) -> Vec<Rect> {
let mut c_result = CVec::<Rect>::default();
unsafe {
cv_cascade_classifier_detect(
self.inner,
mat.inner,
&mut c_result,
scale_factor as c_double,
min_neighbors,
0,
min_size,
max_size,
)
}
c_result.unpack()
}
}
impl Drop for CascadeClassifier {
fn drop(&mut self) {
unsafe {
cv_cascade_classifier_drop(self.inner);
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum CSvmDetector {}
#[derive(Debug)]
pub struct SvmDetector {
pub(crate) inner: *mut CSvmDetector,
}
extern "C" {
fn cv_hog_default_people_detector() -> *mut CSvmDetector;
fn cv_hog_daimler_people_detector() -> *mut CSvmDetector;
fn cv_hog_detector_drop(d: *mut CSvmDetector);
}
impl SvmDetector {
pub fn default_people_detector() -> SvmDetector {
SvmDetector {
inner: unsafe { cv_hog_default_people_detector() },
}
}
pub fn daimler_people_detector() -> SvmDetector {
SvmDetector {
inner: unsafe { cv_hog_daimler_people_detector() },
}
}
}
impl Drop for SvmDetector {
fn drop(&mut self) {
unsafe {
cv_hog_detector_drop(self.inner);
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct HogParams {
pub win_size: Size2i,
pub block_size: Size2i,
pub block_stride: Size2i,
pub cell_size: Size2i,
pub nbins: c_int,
pub win_sigma: f64,
pub l2hys_threshold: f64,
pub gamma_correction: bool,
pub nlevels: usize,
pub hit_threshold: f64,
pub win_stride: Size2i,
pub padding: Size2i,
pub scale: f64,
pub group_threshold: c_int,
pub use_meanshift_grouping: bool,
pub final_threshold: f64,
}
const DEFAULT_WIN_SIGMA: f64 = -1f64;
const DEFAULT_NLEVELS: usize = 64;
impl Default for HogParams {
fn default() -> HogParams {
let win_sigma = {
if cfg!(feature = "cuda") {
4.0
} else {
DEFAULT_WIN_SIGMA
}
};
HogParams {
win_size: Size2i::new(64, 128),
block_size: Size2i::new(16, 16),
block_stride: Size2i::new(8, 8),
cell_size: Size2i::new(8, 8),
nbins: 9,
win_sigma: win_sigma,
l2hys_threshold: 0.2,
gamma_correction: false,
nlevels: DEFAULT_NLEVELS,
hit_threshold: 0f64,
win_stride: Size2i::new(8, 8),
padding: Size2i::default(),
scale: 1.05,
group_threshold: 2,
final_threshold: 2.0,
use_meanshift_grouping: false,
}
}
}
enum CHogDescriptor {}
#[derive(Debug)]
pub struct HogDescriptor {
inner: *mut CHogDescriptor,
pub params: HogParams,
}
unsafe impl Send for HogDescriptor {}
extern "C" {
fn cv_hog_new() -> *mut CHogDescriptor;
fn cv_hog_drop(hog: *mut CHogDescriptor);
fn cv_hog_set_svm_detector(hog: *mut CHogDescriptor, svm: *mut CSvmDetector);
fn cv_hog_detect(
hog: *mut CHogDescriptor,
image: *mut CMat,
objs: *mut CVec<Rect>,
weights: *mut CVec<c_double>,
win_stride: Size2i,
padding: Size2i,
scale: c_double,
final_threshold: c_double,
use_means_shift: bool,
);
}
impl Default for HogDescriptor {
fn default() -> HogDescriptor {
HogDescriptor {
inner: unsafe { cv_hog_new() },
params: HogParams::default(),
}
}
}
impl ObjectDetect for HogDescriptor {
fn detect(&self, image: &Mat) -> Vec<(Rect, f64)> {
let mut detected = CVec::<Rect>::default();
let mut weights = CVec::<c_double>::default();
unsafe {
cv_hog_detect(
self.inner,
image.inner,
&mut detected,
&mut weights,
self.params.win_stride,
self.params.padding,
self.params.scale,
self.params.final_threshold,
self.params.use_meanshift_grouping,
)
}
let results = detected.unpack();
let weights = weights.unpack();
results.into_iter().zip(weights).collect::<Vec<_>>()
}
}
impl HogDescriptor {
pub fn with_params(params: HogParams) -> HogDescriptor {
HogDescriptor {
inner: unsafe { cv_hog_new() },
params: params,
}
}
pub fn set_svm_detector(&mut self, detector: SvmDetector) {
unsafe { cv_hog_set_svm_detector(self.inner, detector.inner) }
}
}
impl Drop for HogDescriptor {
fn drop(&mut self) {
unsafe { cv_hog_drop(self.inner) }
}
}