Face and eyes detection with OpenCV and Java


Before you start you can check out Compiling/Building OpenCV under Ubuntu/Debian

Haarcascade profiles

Profiles can be found in the OpenCV’s GitHub

When you are using Maven you must place them in resources directory.

Create a package called detector and inside create class FaceEyesDetector:

package detector;

import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.Videoio;

import javax.swing.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;

public class FaceEyesDetector {

    // initializing and assigning the detectors
    private CascadeClassifier faceDetector = new CascadeClassifier(getClass().getClassLoader().getResource("haarcascade_frontalface_alt.xml").getPath().substring(1));
    private CascadeClassifier eyeDetector = new CascadeClassifier(getClass().getClassLoader().getResource("haarcascade_eye.xml").getPath().substring(1));

    // initializing and assigning the "containers" which will hold information about detected faces/eyes
    private MatOfRect detectedFaces = new MatOfRect();
    private MatOfRect detectedEyes = new MatOfRect();

    public static void main(String[] args) {
        // load the OpenCV library
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        // initialize and assign the detector
        FaceEyesDetector detector = new FaceEyesDetector();
        // start detecting
        detector.detect();
    }

    private void detect() {
        // initialize and assign the basic image container
        Mat mat = new Mat();
        // initialize and assign which camera to use, on most laptops index - 0 is the main laptop camera
        VideoCapture camera = new VideoCapture(0);
        // get the resolution of the the camera
        final Size frameSize = new Size(camera.get(Videoio.CAP_PROP_FRAME_WIDTH), camera.get(Videoio.CAP_PROP_FRAME_HEIGHT));

        JFrame frame = new JFrame();
        // Make X close the window
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        JLabel panel = new JLabel();
        frame.setContentPane(panel);
        frame.setSize((int) frameSize.width, (int) frameSize.height);
        frame.setVisible(true);

        // when the program stops (Pressed X button, closed from the IDE and etc) makes sure that the image container and the video capture are released
        Runtime.getRuntime().addShutdownHook(new ShutdownThread(mat, camera));

        // while the camera is opened and is "reading" video
        while (camera.isOpened() && camera.read(mat)) {
            // detect the faces
            faceDetector.detectMultiScale(mat, detectedFaces);
            // detect the eyes
            eyeDetector.detectMultiScale(mat, detectedEyes);
            // place a green rectangle over each face
            for (Rect face : detectedFaces.toArray()) {
                if(face.height == 0 && face.width == 0){
                    continue;
                }
                Imgproc.rectangle(mat, new Point(face.x, face.y), new Point(face.x + face.width, face.y + face.height),
                        new Scalar(0, 255,0), 3);
            }
            // place a blue rectangle over each eye
            for (Rect eye : detectedEyes.toArray()) {
                if(eye.height == 0 && eye.width == 0){
                    continue;
                }
                Imgproc.rectangle(mat, new Point(eye.x, eye.y), new Point(eye.x + eye.width, eye.y + eye.height),
                        new Scalar(255, 12, 0), 3);
            }

            // converts the basic image container to image
            ImageIcon image = new ImageIcon(mat2BufferedImage(mat));
            // sets the image
            panel.setIcon(image);
            // refreshes the panel in the frame
            panel.repaint();
        }
    }

    private BufferedImage mat2BufferedImage(Mat m) {
        int type = BufferedImage.TYPE_BYTE_GRAY;
        if (m.channels() > 1) {
            type = BufferedImage.TYPE_3BYTE_BGR;
        }
        int bufferSize = m.channels() * m.cols() * m.rows();
        byte[] b = new byte[bufferSize];
        m.get(0, 0, b); // get all the pixels
        BufferedImage img = new BufferedImage(m.cols(), m.rows(), type);
        final byte[] targetPixels = ((DataBufferByte) img.getRaster().getDataBuffer()).getData();
        System.arraycopy(b, 0, targetPixels, 0, b.length);
        return img;
    }

    private class ShutdownThread extends Thread {

        private Mat mat;
        private VideoCapture videoCapture;

        public ShutdownThread(Mat mat, VideoCapture videoCapture) {
            this.mat = mat;
            this.videoCapture = videoCapture;
        }

        @Override
        public void run() {
            super.run();
            mat.release();
            videoCapture.release();
        }
    }
}

With this eye profile many times your nose or mouth may be detected as an eye



If you have any questions or suggestions, feel free to leave a comment.