rostro - Detección de la cara y la boca de Java y Haarcascade: la boca como la nariz
reconocimiento de rostros opencv (1)
Lo más probable es que detecte que está mal en su imagen, debido a la proporción de la cara (distancia demasiado larga de los ojos a la boca en comparación con la distancia entre los ojos). La detección de la boca y la nariz utilizando el detector de cabellos no es muy estable, por lo que los algoritmos generalmente usan el modelo geométrico de la cara, para elegir la mejor combinación de características candidatas para cada característica facial. Algunas implementaciones incluso pueden intentar predecir la posición de la boca en función de los ojos, si no se encontraron candidatos para la boca.
El detector Haar no es el más nuevo y mejor conocido en este momento para la detección de características. Intente utilizar implementaciones de modelo de piezas deformables. Pruebe esto, tienen un código matlab con funciones eficientes optimizadas para c ++: https://www.ics.uci.edu/~xzhu/face/
Hoy comienzo a probar el proyecto que detecta una sonrisa en Java y OpenCv. Para el reconocimiento de cara y boca proyecto utilizado haarcascade_frontalface_alt y haarcascade_mcs_mouth Pero no entiendo por qué en algunas ocasiones el proyecto detecta la nariz como una boca. Tengo dos métodos:
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;
}
y detectar sonrisa
private void detectSmile(ArrayList<Mat> 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");
}
}
}
Ejemplos:
Para esa foto
detecta correctamente esta montaña:
pero en otra imagen
¿Cuál es el problema en tu opinión?