frclib.FrcFaceDetector.java Source code

Java tutorial

Introduction

Here is the source code for frclib.FrcFaceDetector.java

Source

/*
 * Copyright (c) 2017 Titan Robotics Club (http://www.titanrobotics.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package frclib;

import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.objdetect.CascadeClassifier;

import edu.wpi.cscore.CvSink;
import edu.wpi.cscore.CvSource;
import trclib.TrcDbgTrace;

/**
 * This class implements an OpenCV face detector using the provided classifier.
 */
public class FrcFaceDetector extends FrcOpenCVDetector<MatOfRect> {
    private static final String moduleName = "FrcFaceDetector";
    private static final boolean debugEnabled = false;
    private static final boolean tracingEnabled = false;
    private static final TrcDbgTrace.TraceLevel traceLevel = TrcDbgTrace.TraceLevel.API;
    private static final TrcDbgTrace.MsgLevel msgLevel = TrcDbgTrace.MsgLevel.INFO;
    private TrcDbgTrace dbgTrace = null;

    private static final int NUM_IMAGE_BUFFERS = 2;
    private static final int NUM_OBJECT_BUFFERS = 2;

    private static volatile MatOfRect[] detectedFacesBuffers = new MatOfRect[NUM_OBJECT_BUFFERS];
    private CascadeClassifier faceDetector;
    private volatile Rect[] faceRects = null;
    private volatile Mat currImage = null;
    private boolean videoOutEnabled = false;

    /**
     * Constructor: Create an instance of the object.
     *
     * @param instanceName specifies the instance name.
     * @param classifierPath specifies the file path for the classifier.
     * @param videoIn specifies the video input stream.
     * @param videoOut specifies the video output stream.
     */
    public FrcFaceDetector(final String instanceName, final String classifierPath, CvSink videoIn,
            CvSource videoOut) {
        super(instanceName, videoIn, videoOut, NUM_IMAGE_BUFFERS, detectedFacesBuffers);

        if (debugEnabled) {
            dbgTrace = new TrcDbgTrace(moduleName, tracingEnabled, traceLevel, msgLevel);
        }
        //
        // Preallocate two MatOfRects for ping pong processing.
        //
        for (int i = 0; i < detectedFacesBuffers.length; i++) {
            detectedFacesBuffers[i] = new MatOfRect();
        }

        faceDetector = new CascadeClassifier(classifierPath);
        if (faceDetector.empty()) {
            throw new RuntimeException("Failed to load Cascade Classifier <" + classifierPath + ">");
        }
    } //FrcFaceDetector

    /**
     * This method returns an array of rectangles of last detected faces.
     *
     * @return array of rectangle of last detected faces.
     */
    public Rect[] getFaceRects() {
        final String funcName = "getFaceRects";

        if (debugEnabled) {
            dbgTrace.traceEnter(funcName, TrcDbgTrace.TraceLevel.API);
            dbgTrace.traceExit(funcName, TrcDbgTrace.TraceLevel.API);
        }

        return faceRects;
    } //getFaceRects

    /**
     * This method update the video stream with the detected faces overlay on the image as rectangles.
     *
     * @param color specifies the color of the rectangle outline overlay onto the detected faces.
     * @param thickness specifies the thickness of the rectangle outline.
     */
    public void putFrame(Scalar color, int thickness) {
        if (currImage != null) {
            super.putFrame(currImage, faceRects, color, thickness);
        }
    } //putFrame

    /**
     * This method update the video stream with the detected faces overlay on the image as rectangles.
     */
    public void putFrame() {
        if (currImage != null) {
            super.putFrame(currImage, faceRects, new Scalar(0, 255, 0), 0);
        }
    } //putFrame

    /**
     * This method enables/disables the video out stream.
     *
     * @param enabled specifies true to enable video out stream, false to disable.
     */
    public void setVideoOutEnabled(boolean enabled) {
        final String funcName = "setVideoOutEnabled";

        if (debugEnabled) {
            dbgTrace.traceEnter(funcName, TrcDbgTrace.TraceLevel.API, "enabled=%s", Boolean.toString(enabled));
            dbgTrace.traceExit(funcName, TrcDbgTrace.TraceLevel.API);
        }

        videoOutEnabled = enabled;
    } //setVideoOutEnabled

    //
    // Implements the TrcVisionTask.VisionProcesor interface.
    //

    /**
     * This method is called to detect objects in the image frame.
     *
     * @param image specifies the image to be processed.
     * @param detectedTargets specifies the preallocated buffer to hold the detected targets.
     * @param detectedObjects specifies the object rectangle array to hold the detected objects.
     * @return detected objects, null if none detected.
     */
    @Override
    public MatOfRect detectObjects(Mat image, MatOfRect detectedObjects) {
        final String funcName = "detectedObjects";

        if (debugEnabled) {
            dbgTrace.traceEnter(funcName, TrcDbgTrace.TraceLevel.CALLBK, "image=%s,objRects=%s", image.toString(),
                    detectedObjects.toString());
        }

        faceDetector.detectMultiScale(image, detectedObjects);
        if (!detectedObjects.empty()) {
            faceRects = detectedObjects.toArray();
        } else {
            faceRects = null;
            detectedObjects = null;
        }

        if (videoOutEnabled) {
            putFrame();
        }

        currImage = image;

        if (debugEnabled) {
            dbgTrace.traceExit(funcName, TrcDbgTrace.TraceLevel.CALLBK, "=%s",
                    Boolean.toString(detectedObjects != null));
        }

        return detectedObjects;
    } //detectedObjects

} //class FrcFaceDetector