mx.iteso.desi.vision.WebCamStream.java Source code

Java tutorial

Introduction

Here is the source code for mx.iteso.desi.vision.WebCamStream.java

Source

/*
 * Copyright 2017 Mario Contreras <marioc@nazul.net>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package mx.iteso.desi.vision;

import javax.swing.JPanel;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.objdetect.Objdetect;
import org.opencv.videoio.VideoCapture;

public class WebCamStream {

    private Mat frame;
    private Mat processedFrame;
    private VideoCapture webSource;
    private WebCamThread webcamTh;
    private JPanel photoPanel;
    private int webCamNumber;
    // Face size
    private int absoluteFaceSize;
    // OpenCV classifier for face detection
    private final CascadeClassifier faceCascade;

    private class WebCamThread implements Runnable {

        protected volatile boolean runnable = false;

        public void run() {
            synchronized (this) {
                while (runnable) {
                    if (webSource.grab()) {
                        try {
                            webSource.retrieve(frame);
                            // compute minimum face size
                            if (absoluteFaceSize == 0) {
                                int height = frame.rows();
                                if (Math.round(height * 0.15f) > 0) {
                                    absoluteFaceSize = Math.round(height * 0.15f);
                                }
                            }
                            detectFaces();
                        } catch (Exception e) {
                            continue;
                        }
                        if (frame != null) {
                            showPhotoAtFrame(processedFrame.clone());
                        }
                    }
                }
            }
        }

        private void showPhotoAtFrame(Mat photo) {
            synchronized (this) {
                if (runnable) {
                    Size actualSize = photo.size();

                    double hfactor = (actualSize.height > photoPanel.getHeight())
                            ? (photoPanel.getHeight() / actualSize.height)
                            : 1;
                    double wfactor = (actualSize.width > photoPanel.getWidth())
                            ? (photoPanel.getWidth() / actualSize.width)
                            : 1;

                    double factor = (hfactor < wfactor) ? hfactor : wfactor;
                    if (factor < 1) {
                        Imgproc.resize(photo, photo,
                                new Size(actualSize.width * factor, actualSize.height * factor));
                    }

                    if (!photo.empty()) {
                        photoPanel.removeAll();
                        photoPanel.add(ImagesMatUtils.MatToJLabel(photo));
                        photoPanel.revalidate();
                    }

                }
            }
        }
    }

    public WebCamStream(int webCamNumber) {
        this.webCamNumber = webCamNumber;
        // Initialize cascade classifier
        this.faceCascade = new CascadeClassifier(
                getClass().getResource("/mx/iteso/desi/vision/resources/lbpcascade_frontalface.xml").getFile()
                        .substring(1).replace("/", "\\").replace("%20", " "));
    }

    public void startStream(JPanel dst) {
        this.photoPanel = dst;
        this.webSource = new VideoCapture(webCamNumber);
        this.frame = new Mat();
        this.webcamTh = new WebCamThread();
        Thread t = new Thread(webcamTh);
        t.setDaemon(true);
        t.start();
        webcamTh.runnable = true;
    }

    public Mat stopStream() {
        if (webcamTh != null) {
            webcamTh.runnable = false;
        }
        if (this.webSource != null) {
            this.webSource.release();
        }
        if (this.webSource != null) {
            return frame.clone();
        }
        return null;
    }

    private void detectFaces() {
        MatOfRect faces = new MatOfRect();
        Mat grayFrame = new Mat();

        processedFrame = frame.clone();

        // convert the frame in gray scale
        Imgproc.cvtColor(processedFrame, grayFrame, Imgproc.COLOR_BGR2GRAY);
        // equalize the frame histogram to improve the result
        Imgproc.equalizeHist(grayFrame, grayFrame);

        // detect faces
        this.faceCascade.detectMultiScale(grayFrame, faces, 1.1, 2, Objdetect.CASCADE_SCALE_IMAGE,
                new Size(this.absoluteFaceSize, this.absoluteFaceSize), new Size());

        // each rectangle in faces is a face: draw them!
        Rect[] facesArray = faces.toArray();
        for (Rect face : facesArray) {
            Imgproc.rectangle(processedFrame, face.tl(), face.br(), new Scalar(0, 255, 0, 255), 3);
        }
    }
}

// EOF