简体   繁体   English

OpenCV Java微笑检测

[英]OpenCV Java Smile Detection

I've tried to create a smile detector with source code that I've found on the Internet. 我试图用我在Internet上找到的源代码创建一个微笑探测器。 It detects face and works pretty well. 它可以检测人脸并且效果很好。 It uses Haar classifiers, I've found the Haar classifiers for smile recognition and tried it, however it doesn't work. 它使用Haar分类器,我已经找到了Haar分类器用于微笑识别并尝试过,但是它不起作用。 I've tried to use it in the same way that was used to recognize face. 我试图以与识别面部相同的方式使用它。 Tried the same with eye classifier - and it worked. 使用眼睛分类器进行了相同的尝试-并且有效。 All classifiers I've found in opencv/data folder, could somebody give me a tip, what could I do more with given code? 我在opencv / data文件夹中找到的所有分类器,有人可以给我一个提示,给定的代码我还能做些什么?

import java.io.File;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.highgui.Highgui;
import org.opencv.objdetect.CascadeClassifier;

public class SmileDetector {

public void detectSmile(String filename) {
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    System.out.println("\nRunning SmileDetector");

    CascadeClassifier faceDetector = new CascadeClassifier(new File(
            "src/main/resources/haarcascade_frontalface_alt.xml").getAbsolutePath());
    CascadeClassifier smileDetector = new CascadeClassifier(
            new File("src/main/resources/haarcascade_smile.xml").getAbsolutePath());
    Mat image = Highgui.imread(filename);
    MatOfRect faceDetections = new MatOfRect();
    MatOfRect smileDetections = new MatOfRect();
    faceDetector.detectMultiScale(image, faceDetections);

    System.out.println(String.format("Detected %s faces", faceDetections.toArray().length));

    for (Rect rect : faceDetections.toArray()) {
        Core.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),
                new Scalar(0, 255, 0));
    }
    Mat face = image.submat(faceDetections.toArray()[0]);
    smileDetector.detectMultiScale(face, smileDetections);

    for (Rect rect : smileDetections.toArray()) {
        Core.rectangle(face, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),
                new Scalar(0, 255, 0));
    }

    String outputFilename = "ouput.png";
    System.out.println(String.format("Writing %s", outputFilename));
    Highgui.imwrite(outputFilename, image);
    Highgui.imwrite("ee.png", face);
}
}

To answer Vi Matviichuk comment: Yes I was partially able to fix the problem. 回答Vi Matviichuk的评论:是的,我部分能够解决问题。 I've used mouth classifier instead of smile, the name of mouth classifier from opencv samples is haarcascade_mcs_mouth.xml ; 我使用嘴部分类器代替了微笑,opencv示例中的嘴部分类器的名称为haarcascade_mcs_mouth.xml; then you look for faces, crop them and look for mouths on faces. 然后您寻找面孔,修剪它们并寻找嘴巴。 However it will give you a lot of mouths, so you have to filter them by: 但是,这会给您带来很多麻烦,因此您必须使用以下方法进行过滤:

/**
 * Detects face(s) and then for each detects and crops mouth
 * 
 * @param filename path to file on which smile(s) will be detected
 * @return List of Mat objects with cropped mouth pictures.
 */
private ArrayList<Mat> detectMouth(String filename) {
    int i = 0;
    ArrayList<Mat> mouths = new ArrayList<Mat>();
    // reading image in grayscale from the given path
    image = Highgui.imread(filename, Highgui.CV_LOAD_IMAGE_GRAYSCALE);
    MatOfRect faceDetections = new MatOfRect();
    // detecting face(s) on given image and saving them to MatofRect object
    faceDetector.detectMultiScale(image, faceDetections);
    System.out.println(String.format("Detected %s faces", faceDetections.toArray().length));
    MatOfRect mouthDetections = new MatOfRect();
    // detecting mouth(s) on given image and saving them to MatOfRect object
    mouthDetector.detectMultiScale(image, mouthDetections);
    System.out.println(String.format("Detected %s mouths", mouthDetections.toArray().length));
    for (Rect face : faceDetections.toArray()) {
        Mat outFace = image.submat(face);
        // saving cropped face to picture
        Highgui.imwrite("face" + i + ".png", outFace);
        for (Rect mouth : mouthDetections.toArray()) {
            // trying to find right mouth
            // if the mouth is in the lower 2/5 of the face
            // and the lower edge of mouth is above of the face
            // and the horizontal center of the mouth is the enter of the face
            if (mouth.y > face.y + face.height * 3 / 5 && mouth.y + mouth.height < face.y + face.height
                    && Math.abs((mouth.x + mouth.width / 2)) - (face.x + face.width / 2) < face.width / 10) {
                Mat outMouth = image.submat(mouth);
                // resizing mouth to the unified size of trainSize
                Imgproc.resize(outMouth, outMouth, trainSize);
                mouths.add(outMouth);
                // saving mouth to picture 
                Highgui.imwrite("mouth" + i + ".png", outMouth);
                i++;
            }
        }
    }
    return mouths;
}

Then you have to find a smile, I tried to do this with SVM training machine, but I hadn't got enough samples so it wasn't perfect. 然后您必须找到一个微笑,我尝试使用SVM训练机进行此操作,但是我没有足够的样本,因此效果并不理想。 However, whole code I got can be found here: https://bitbucket.org/cybuch/smile-detector/src/ac8a309454c3467ffd8bc1c34ad95879cb059328/src/main/java/org/cybuch/smiledetector/SmileDetector.java?at=master 但是,可以在这里找到我得到的完整代码: https : //bitbucket.org/cybuch/smile-detector/src/ac8a309454c3467ffd8bc1c34ad95879cb059328/src/main/java/org/cybuch/smiledetector/SmileDetector.java?at=master

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM