import java.applet.Applet;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacpp.opencv_objdetect;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.javacv.OpenCVFrameGrabber;
import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_imgproc.*;
import static org.bytedeco.javacpp.opencv_objdetect.*;
/**
*
* @author Samuel Audet
*/
public class FaceApplet extends Applet implements Runnable {
private CvHaarClassifierCascade classifier = null;
private CvMemStorage storage = null;
private FrameGrabber grabber = null;
private IplImage grabbedImage = null, grayImage = null, smallImage = null;
private CvSeq faces = null;
private boolean stop = false;
private Exception exception = null;
OpenCVFrameConverter.ToIplImage grabberConverter = new OpenCVFrameConverter.ToIplImage();
Java2DFrameConverter paintConverter = new Java2DFrameConverter();
@Override public void init() {
try {
// Load the classifier file from Java resources.
String classiferName = "haarcascade_frontalface_alt.xml";
File classifierFile = Loader.extractResource(classiferName, null, "classifier", ".xml");
if (classifierFile == null || classifierFile.length() <= 0) {
throw new IOException("Could not extract \"" + classiferName + "\" from Java resources.");
}
// Preload the opencv_objdetect module to work around a known bug.
Loader.load(opencv_objdetect.class);
classifier = new CvHaarClassifierCascade(cvLoad(classifierFile.getAbsolutePath()));
classifierFile.delete();
if (classifier.isNull()) {
throw new IOException("Could not load the classifier file.");
}
storage = CvMemStorage.create();
} catch (Exception e) {
if (exception == null) {
exception = e;
repaint();
}
}
}
@Override public void start() {
try {
new Thread(this).start();
} catch (Exception e) {
if (exception == null) {
exception = e;
repaint();
}
}
}
public void run() {
try {
try {
grabber = FrameGrabber.createDefault(0);
grabber.setImageWidth(getWidth());
grabber.setImageHeight(getHeight());
grabber.start();
grabbedImage = grabberConverter.convert(grabber.grab());
} catch (Exception e) {
if (grabber != null) grabber.release();
grabber = new OpenCVFrameGrabber(0);
grabber.setImageWidth(getWidth());
grabber.setImageHeight(getHeight());
grabber.start();
grabbedImage = grabberConverter.convert(grabber.grab());
}
grayImage = IplImage.create(grabbedImage.width(), grabbedImage.height(), IPL_DEPTH_8U, 1);
smallImage = IplImage.create(grabbedImage.width()/4, grabbedImage.height()/4, IPL_DEPTH_8U, 1);
stop = false;
while (!stop && (grabbedImage = grabberConverter.convert(grabber.grab())) != null) {
if (faces == null) {
cvClearMemStorage(storage);
cvCvtColor(grabbedImage, grayImage, CV_BGR2GRAY);
cvResize(grayImage, smallImage, CV_INTER_AREA);
faces = cvHaarDetectObjects(smallImage, classifier, storage, 1.1, 3,
CV_HAAR_FIND_BIGGEST_OBJECT | CV_HAAR_DO_ROUGH_SEARCH);
repaint();
}
}
grabbedImage = grayImage = smallImage = null;
grabber.stop();
grabber.release();
grabber = null;
} catch (Exception e) {
if (exception == null) {
exception = e;
repaint();
}
}
}
@Override public void update(Graphics g) {
paint(g);
}
@Override public void paint(Graphics g) {
if (grabbedImage != null) {
Frame frame = grabberConverter.convert(grabbedImage);
BufferedImage image = paintConverter.getBufferedImage(frame, 2.2/grabber.getGamma());
Graphics2D g2 = image.createGraphics();
if (faces != null) {
g2.setColor(Color.RED);
g2.setStroke(new BasicStroke(2));
int total = faces.total();
for (int i = 0; i < total; i++) {
CvRect r = new CvRect(cvGetSeqElem(faces, i));
g2.drawRect(r.x()*4, r.y()*4, r.width()*4, r.height()*4);
}
faces = null;
}
g.drawImage(image, 0, 0, null);
}
if (exception != null) {
int y = 0, h = g.getFontMetrics().getHeight();
g.drawString(exception.toString(), 5, y += h);
for (StackTraceElement e : exception.getStackTrace()) {
g.drawString(" at " + e.toString(), 5, y += h);
}
}
}
@Override public void stop() {
stop = true;
}
@Override public void destroy() { }
}