javacvで顔検出+画像合成

やってみた。

package jp.ne.hatena.d.matasaburou;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

import com.googlecode.javacv.CanvasFrame;
import com.googlecode.javacv.OpenCVFrameGrabber;
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_objdetect.*;
import static com.googlecode.javacv.cpp.opencv_highgui.*;

public class Main {
	static CanvasFrame canvas;
	static BufferedImage bufImage;
	static OpenCVFrameGrabber grabber;
	public static void main(String[] args) {
		canvas = new CanvasFrame("Test");
		canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		try{
			bufImage = ImageIO.read(new File("C:\\image.jpg"));
		}catch(IOException e){
			e.printStackTrace();
		}
		grabber = new OpenCVFrameGrabber(0);
		new Main().loop();
	}

	private void loop() {
		try {
			grabber.start();
			double frameRate = grabber.getFrameRate();
			long wait = (long) (1000 / (frameRate == 0 ? 20 : frameRate));

			while (true) {
				Thread.sleep(wait);
				IplImage image = grabber.grab();
				if (image != null) {
					canvas.showImage(switchFace(image, bufImage));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private static final String XML = "C:\\opencv\\sources\\data\\haarcascades\\haarcascade_frontface_default.xml";
	private static CvHaarClassifierCascade cascade = new CvHaarClassifierCascade(cvLoad(XML));
	private static BufferedImage combinedImage;

	public BufferedImage switchFace(IplImage src, BufferedImage target){
		CvMemStorage storage = CvMemStorage.create();
		combinedImage = src.getBufferedImage();
		cvClearMemStorage(storage);
		CvSeq sign = cvHaarDetectObjects(
			src,
			cascade,
			storage,
			1.2,
			3,
			CV_HAAR_DO_CANNY_PRUNING
		);
		if(sign.total() > 0){
			CvRect r = new CvRect(cvGetSeqElem(sign, 0));
			combinedImage.getGraphics().drawImage(target, r.x(), r.y(), r.width(), r.height(), null);
		}
		return combinedImage;
	}
}

デフォルトの検出器では、横顔をうまく認識できない模様。
検出器をどこかから見つけてこよう。