Skip to content

Instantly share code, notes, and snippets.

@woxtu
Last active March 4, 2019 05:37
Show Gist options
  • Save woxtu/c186b173be3a53171533 to your computer and use it in GitHub Desktop.
Save woxtu/c186b173be3a53171533 to your computer and use it in GitHub Desktop.
Face detection in Rust
pub mod cv {
extern crate libc;
use self::libc::{c_char, c_double, c_int, c_schar, c_void};
#[repr(C)]
pub struct HaarClassifierCascade;
#[repr(C)]
pub struct MemStorage;
#[repr(C)]
pub struct Mat {
_type_: c_int,
_step: c_int,
_refcount: *const c_int,
_hdr_refcount: c_int,
_data: *const c_void,
pub rows: c_int,
pub cols: c_int,
}
#[repr(C)]
pub struct Point {
pub x: c_int,
pub y: c_int,
}
#[repr(C)]
pub struct Rect {
pub x: c_int,
pub y: c_int,
pub width: c_int,
pub height: c_int,
}
#[repr(C)]
pub type Scalar = [c_double, ..4];
#[repr(C)]
pub struct Seq {
tree_node_fields: [c_int, ..10],
pub total: c_int,
}
#[repr(C)]
pub struct Size {
pub width: c_int,
pub height: c_int,
}
#[link(name = "opencv_core.2.4.9")]
extern "C" {
fn cvCreateMat(rows: c_int, cols: c_int, type_: c_int) -> *const Mat;
fn cvCreateMemStorage(block_size: c_int) -> *const MemStorage;
fn cvGetSeqElem(seq: *const Seq, index: c_int) -> *const c_schar;
fn cvLoad(filename: *const c_char) -> *const c_void;
fn cvRectangle(image: *const Mat,
pt1: Point,
pt2: Point,
color: Scalar,
thickness: c_int,
line_type: c_int,
shift: c_int);
fn cvReleaseMemStorage(storage: *const *const MemStorage);
}
pub fn create_mat(rows: c_int, cols: c_int, type_: c_int) -> *const Mat {
unsafe { cvCreateMat(rows, cols, type_) }
}
pub fn create_mem_storage(block_size: int) -> *const MemStorage {
unsafe { cvCreateMemStorage(block_size as i32) }
}
pub fn get_seq_elem_as_rect(seq: *const Seq, index: int) -> *const Rect {
unsafe { cvGetSeqElem(seq, index as i32) as *const Rect }
}
pub fn load_haar_classifier_cascade(filename: &str) -> *const HaarClassifierCascade {
unsafe { cvLoad(filename.to_string().to_c_str().unwrap()) as *const HaarClassifierCascade } // ??
}
pub fn rectangle(image: *const Mat, pt1: Point, pt2: Point, color: Scalar, thickness: int) {
unsafe { cvRectangle(image, pt1, pt2, color, thickness as i32, 16i32, 0i32); }
}
pub fn release_mem_storage(storage: *const *const MemStorage) {
unsafe { cvReleaseMemStorage(storage); }
}
#[link(name = "opencv_highgui.2.4.9")]
extern "C" {
fn cvDestroyAllWindows();
fn cvLoadImageM(filename: *const c_char, iscolor: c_int) -> *const Mat;
fn cvNamedWindow(title: *const c_char) -> c_int;
fn cvShowImage(name: *const c_char, image: *const Mat);
fn cvWaitKey(delay: c_int) -> c_int;
}
pub fn destroy_all_windows() {
unsafe { cvDestroyAllWindows(); }
}
pub fn load_image(filename: &str) -> *const Mat {
filename.with_c_str(|filename| unsafe {
cvLoadImageM(filename, 1i32)
})
}
pub fn named_window(title: &str) {
title.with_c_str(|title| unsafe {
cvNamedWindow(title);
});
}
pub fn show_image(name: &str, image: *const Mat) {
name.with_c_str(|name| unsafe {
cvShowImage(name, image);
})
}
pub fn wait_key(delay: int) -> int {
unsafe { cvWaitKey(delay as i32) as int }
}
#[link(name = "opencv_imgproc.2.4.9")]
extern "C" {
fn cvCvtColor(src: *const Mat, dst: *const Mat, code: c_int);
fn cvEqualizeHist(src: *const Mat, dst: *const Mat);
}
pub fn cvt_color(src: *const Mat, dst: *const Mat, code: int) {
unsafe { cvCvtColor(src, dst, code as i32); }
}
pub fn equalize_hist(src: *const Mat, dst: *const Mat) {
unsafe { cvEqualizeHist(src, dst); }
}
#[link(name = "opencv_objdetect.2.4.9")]
extern "C" {
fn cvHaarDetectObjects(image: *const Mat,
cascade: *const HaarClassifierCascade,
storage: *const MemStorage,
scale_factor: c_double,
min_neighbors: c_int,
flags: c_int,
min_size: Size,
max_size: Size) -> *const Seq;
fn cvReleaseHaarClassifierCascade(cascade: *const *const HaarClassifierCascade);
}
pub fn haar_detect_objects(image: *const Mat, cascade: *const HaarClassifierCascade, storage: *const MemStorage) -> *const Seq {
unsafe {
let zero = Size { width: 0i32, height: 0i32 };
cvHaarDetectObjects(image, cascade, storage, 1.1f64, 3, 0, zero, zero)
}
}
pub fn release_haar_classifier_cascade(cascade: *const *const HaarClassifierCascade) {
unsafe { cvReleaseHaarClassifierCascade(cascade); }
}
}
fn main() {
let name = "Face detection";
cv::named_window(name);
let image0 = cv::load_image(std::os::args()[1].as_slice());
let image1 = unsafe { cv::create_mat((*image0).rows, (*image0).cols, 0i32) }; // CV_8UC1 = 0
let cascade = cv::load_haar_classifier_cascade("haarcascade_frontalface_alt.xml");
let storage = cv::create_mem_storage(0i);
cv::cvt_color(image0, image1, 6i); // CV_BGR2GRAY = 6
cv::equalize_hist(image1, image1);
let seq = cv::haar_detect_objects(image1, cascade, storage);
unsafe {
for n in range(0i, (*seq).total as int) {
let rect = *cv::get_seq_elem_as_rect(seq, n);
let src = cv::Point { x: rect.x, y: rect.y };
let dst = cv::Point { x: rect.x + rect.width, y: rect.y + rect.height };
cv::rectangle(image0, src, dst, [144.0f64, 48.0f64, 255.0f64, 0.0f64], 1i);
}
}
cv::show_image(name, image0);
cv::wait_key(0);
cv::release_mem_storage(&storage);
cv::release_haar_classifier_cascade(&cascade);
cv::destroy_all_windows();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment