Java и haarcascade распознавание лица и рта - рот как нос
Сегодня я начинаю тестировать проект, который обнаруживает улыбку в Java и OpenCv. Для распознавания лица и рта проект haarcascade_frontalface_alt и haarcascade_mcs_mouth Но я не понимаю, почему по каким-то причинам проект обнаруживает нос как рот.
У меня есть два метода:
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;
}
и обнаружите
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");
}
}
}
Примеры:
Для этого изображения
![введите описание изображения здесь]()
правильно определяет это место:
![введите описание изображения здесь]()
но на другом рисунке
![введите описание изображения здесь]()
обнаружен нос
![введите описание изображения здесь]()
Какая проблема на ваш взгляд?
Ответы
Ответ 1
Скорее всего, он обнаруживает это неправильно на вашей фотографии из-за доли лица (слишком большое расстояние от глаз до рта по сравнению с расстоянием между глазами). Обнаружение рта и носа с помощью хара-детектора не очень стабильно, поэтому алгоритмы обычно используют геометрическую модель лица, чтобы выбрать лучшую комбинацию кандидатов на объекты для каждой лицевой функции. Некоторые реализации могут даже попытаться предсказать положение рта на основе глаз, если не было найдено никаких кандидатов на рот.
Датчик Haar не является самым новым и самым известным в настоящее время для обнаружения признаков. Попытайтесь использовать реализации модели деформируемых частей. Попробуйте это, у них есть код matlab с эффективными оптимизированными функциями С++:
https://www.ics.uci.edu/~xzhu/face/