RustでFaceTime HDカメラやWebカメラを使う
はじめに
node-webkitや、Atom ShellでWebRTCを使えば、Facetime HDカメラを簡単に使えるが、Rustだとどういうやり方があるのかと調べて、試してみた。
OpenCV使うと簡単に出来た。
Rustは言語レベルでFFIがサポートされているので、これを使ってOpenCVを叩ける。
#[allow(dead_code)]
pub mod cv {
extern crate libc;
use self::libc::{ c_char, c_double, c_int, c_schar, c_void }
;
pub struct Capture;
pub struct IplImage;
#[link(name = "opencv_highgui")]
extern"C" {
fn cvDestroyAllWindows() -> c_void;
fn cvNamedWindow(title: * const c_char) -> c_int;
fn cvShowImage(name: * const c_char, image: * const IplImage) -> c_void;
fn cvWaitKey(delay: c_int) -> c_int;
fn cvCreateCameraCapture(index: c_int) -> * mut Capture;
fn cvQueryFrame(capture: * mut Capture) -> * mut IplImage;
fn cvSaveImage(filename: * const c_char, image: * const IplImage, params: *const c_int) -> c_int;
}
pub fn destroy_all_windows() -> () {
unsafe {
cvDestroyAllWindows();
}
}
pub fn named_window(title: &str) -> () {
title.with_c_str(| title | unsafe {
cvNamedWindow(title);
}
);
}
pub fn create_camera_capture(index: int) -> * mut Capture {
unsafe {
cvCreateCameraCapture(index.to_i32().unwrap())
}
}
pub fn query_frame(capture: * mut Capture) -> * mut IplImage {
unsafe {
cvQueryFrame(capture)
}
}
pub fn show_image(name: &str, image: * const IplImage) -> () {
name.with_c_str(| name | unsafe {
cvShowImage(name, image);
}
)
}
pub fn wait_key(delay: int) -> int {
unsafe {
cvWaitKey(delay.to_i32().unwrap()).to_int().unwrap()
}
}
pub fn save_image(name: &str, image: * const IplImage) -> int {
name.with_c_str(| name | unsafe {
cvSaveImage(name, image,0 as * const i32).to_int().unwrap()
}
)
}
}
fn main() {
let name = "WebCam test";
let capture = cv::create_camera_capture(0);
cv::named_window(name);
while true {
let frame = cv::query_frame(capture);
cv::show_image(name, frame as * const cv::IplImage);
let c = cv::wait_key(2);
if c == 0x1b {
break;
}
if c == 0x20 {
cv::save_image("snap.jpg",frame as * const cv::IplImage);
break;
}
}
cv::destroy_all_windows();
}
まとめ
OpenCVは自分が学生やってたころに、インテルから作るよというアナウンスがあったくらいから知っているが、JavaScriptで顔検出するまで、使ったことがなかった。
今どきはC++のAPIは今回のRustで使っているCのAPIよりずっと洗練されたAPIを持っているようで、どうりで、皆C++で書いているのだと分かった。
Link
関連記事