Post date: Jun 13, 2013 2:22:05 PM
processingで顔の認識をしたい場合には、javaCVなんて使わなくてもprocessing用のOpenCVやjavaCVProとかを使えば良いが、
今回は勉強ということでjavaCVを無理やり引っ張ってきて使った。
使っているのはHaar-like特徴分類器を使用したもの。
ライブラリの導入とかはこっちをみてね。
今回のコードはこちら。
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import static com.googlecode.javacv.cpp.opencv_highgui.*;
import static com.googlecode.javacv.cpp.opencv_objdetect.*;
CvCapture cam;
CvHaarClassifierCascade cascade;
CvMemStorage storage;
void setup ()
{
size(640, 480);
cascade=new CvHaarClassifierCascade(cvLoad("[pdeファイルの有るところまでの絶対パス]\\data\\haarcascade_frontalface_default.xml"));
println(cascade);
if (cascade==null) {
println("特徴ファイルが読めません");
exit();
while (true);
}
storage=cvCreateMemStorage(0);
println("storageの準備完了");
cam=cvCreateCameraCapture(1);
if (cam==null) {
println("カメラ取得失敗");
exit();
while (true);
}
println("準備OK!");
}
void draw() {
IplImage frame = cvQueryFrame(cam);
// 取ってきた画像を画面に表示
if (frame == null)return;
cvClearMemStorage(storage);//メモリ領域の初期化
//Haar-like特徴分類器による顔検出
CvSeq objects = cvHaarDetectObjects(frame, cascade, storage, 1.1, 3, 0);
int total=objects.total();
for (int i=0;i<total;i++) {
CvRect r=new CvRect(cvGetSeqElem(objects, i));
cvRectangle(frame, cvPoint(r.x(), r.y()), cvPoint(r.x()+r.width(), r.y()+r.height()), CV_RGB(0, 255, 0), 3,8,0);
}
image(cvtPImage(frame), 0, 0);
}
PImage cvtPImage ( IplImage iplImg ) {
java.awt.image.BufferedImage bImg = iplImg.getBufferedImage();
PImage img = new PImage( bImg.getWidth(), bImg.getHeight(), ARGB );
bImg.getRGB( 0, 0, img.width, img.height, img.pixels, 0, img.width );
img.updatePixels();
return img;
}
void exit() {
cvReleaseCapture( cam );
cvReleaseMemStorage(storage);
cvReleaseHaarClassifierCascade(cascade);
super.exit();
}
今回はちょっとづつ解説を。
CvMemStorageは、動的に拡張されるメモリ領域を表現するもの、らしい。今回コンストラクタで引数0をとっているので64kBが確保されている。
cvHaarDetectObjects( 「対象画像」 , 「CvHaarClassifierCascadeクラス」 , 「計算用メモリ領域(CvMemStorage)」 , 「引数1」 , 「引数2」 , 「引数3」 );
引数1: Haar特徴をマッピングさせる時の拡大縮小率
大きくすると高速だが特定のサイズの検出漏れを起こす 今回は低速だが正確な1.1を使用
引数2: 近傍にある検出した領域をまとめる際の「近傍」を指定する デフォルト3
最低でもn個の領域が存在しているところを「顔」と見る
引数3: 未使用??
CvSeqはArrayListみたいなもの?