Java和haarcascade面部和嘴部检测 – 嘴巴作为鼻子

今天我开始测试在Java和OpenCv中检测微笑的项目。 用于识别面部和嘴部项目使用haarcascade_frontalface_alt和haarcascade_mcs_mouth但我不明白为什么在某些原因项目检测鼻子为嘴。 我有两种方法:

private ArrayList detectMouth(String filename) { int i = 0; ArrayList mouths = new ArrayList(); // 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; } 

并检测微笑

 private void detectSmile(ArrayList mouths) { trainSVM(); CvSVMParams params = new CvSVMParams(); // set linear kernel (no mapping, regression is done in the original feature space) params.set_kernel_type(CvSVM.LINEAR); // train SVM with images in trainingImages, labels in trainingLabels, given params with empty samples clasificador = new CvSVM(trainingImages, trainingLabels, new Mat(), new Mat(), params); // save generated SVM to file, so we can see what it generated clasificador.save("svm.xml"); // loading previously saved file clasificador.load("svm.xml"); // returnin, if there aren't any samples if (mouths.isEmpty()) { System.out.println("No mouth detected"); return; } for (Mat mouth : mouths) { Mat out = new Mat(); // converting to 32 bit floating point in gray scale mouth.convertTo(out, CvType.CV_32FC1); if (clasificador.predict(out.reshape(1, 1)) == 1.0) { System.out.println("Detected happy face"); } else { System.out.println("Detected not a happy face"); } } } 

例子:

对于那张照片

在此处输入图像描述

正确检测到这个mounth:

在此处输入图像描述

但在其他情况下

在此处输入图像描述

检测到鼻子 在此处输入图像描述

你认为有什么问题?

由于脸部的比例(眼睛与嘴之间的距离与眼睛之间的距离相比太长),因此很可能它会在您的照片上检测到错误。 使用haar检测器检测口鼻不是很稳定,因此算法通常使用脸部的几何模型,为每个脸部特征选择候选特征的最佳组合。 如果没有找到口腔候选者,一些实施甚至可以尝试基于眼睛预测口腔位置。

Haar探测器不是目前用于特征检测的最新和最知名的。 尝试使用可变形零件模型实现。 试试这个,他们有matlab代码和高效的c ++优化函数: https : //www.ics.uci.edu/~xzhu/face/

Interesting Posts