Я использую OpenCV Cascade Classifier для обнаружения лиц. Я следовал руководству по веб-камере и смог использовать Detect MultiSale, чтобы найти и отследить свое лицо во время потокового видео с веб-камеры моего ноутбука.
Но когда я фотографирую себя с веб-камеры моего ноутбука, я загружаю это изображение в OpenCV и применяю на этом изображении detectMultiScale, и по какой-то причине Cascade Classifier не может обнаружить лица на этом статическом изображении!
Это статичное изображение определенно было бы обнаружено, если бы оно было одним кадром из потока моей веб-камеры, но когда я просто беру это одно отдельное изображение, ничего не обнаруживается.
Вот код, который я использую (только что выбрал соответствующие строки):
Общий код:
String face_cascade_name = "/path/to/data/haarcascades/haarcascade_frontalface_alt.xml";
CascadeClassifier face_cascade;
Mat imagePreprocessing(Mat frame) {
Mat processed_frame;
cvtColor( frame, processed_frame, COLOR_BGR2GRAY );
equalizeHist( processed_frame, processed_frame );
return processed_frame;
}
Для распознавания лиц с помощью веб-камеры:
int detectThroughWebCam() {
VideoCapture capture;
Mat frame;
if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading face cascade\n"); return -1; };//-- 2. Read the video stream
capture.open( -1 );
if ( ! capture.isOpened() ) { printf("--(!)Error opening video capture\n"); return -1; }
while ( capture.read(frame) )
{
if(frame.empty()) {
printf(" --(!) No captured frame -- Break!");
break;
}
//-- 3. Apply the classifier to the frame
Mat processed_image = imagePreprocessing( frame);
vector<Rect> faces;
face_cascade.detectMultiScale( processed_frame, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE|CV_HAAR_FIND_BIGGEST_OBJECT, Size(30, 30) );
if (faces.size() > 0) cout << "SUCCESS" << endl;
int c = waitKey(10);
if( (char)c == 27 ) { break; } // escape
}
return 0;
}
Для моего статического изображения лица:
void staticFaceDetection() {
Mat image = imread("path/to/jpg/image");
Mat processed_frame = imagePreprocessing(image);
std::vector<Rect> faces;
//-- Detect faces
face_cascade.detectMultiScale( processed_frame, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE|CV_HAAR_FIND_BIGGEST_OBJECT, Size(30, 30) );
if (faces.size() > 0) cout << "SUCCESS" << endl;
}
На мой взгляд, оба эти процесса идентичны (единственное отличие состоит в том, где я получаю исходное изображение), но версия видеопотока регулярно обнаруживает лица, в то время как статический метод, кажется, никогда не сможет найти лицо.
Я что-то здесь упускаю?
Есть несколько возможных причин для этого.
Вы сохраняете изображение в низком разрешении. Попробуйте сохранить его в оригинальном разрешении
Сжатие с потерями. Вы сохраняете изображения в формате .jpg? возможно, ваше сжатие слишком сильное. Попробуйте сохранить в виде файла BMP (он сохраняет исходное качество).
Формат изображения. Я не знаю что ты imagePreprocessing()
Метод делает, но вы могли бы представить следующие проблемы. Камера захватывает видео в определенном формате (большинство камер используют YUV). Обычно обнаружение лица выполняется в первой плоскости Y. Когда вы сохраняете изображение и считываете его с диска как RGB, вы не должны запускать обнаружение лица в первой плоскости. Это будет плоскость «B», а синий цвет хранит очень мало информации о лице. Убедитесь, что вы правильно преобразовали изображение в оттенки серого, прежде чем запускать распознавание лиц.
Диапазон изображения. Это распространенная ошибка. Убедитесь, что динамический диапазон изображения правильный. Иногда по ошибке вы можете умножить все значения на 255, фактически превратив все изображение в белое.
Возможно, распознавание лица на изображениях работает нормально, но вы как-то очищаете faces
вектор после обнаружения лица. Другая ошибка может заключаться в том, что вы читаете другой файл изображения. Например, вы сохраняете изображения в каталог «A», но случайно читаете из каталога «B»
Если ничего из вышеперечисленного не поможет. Сделайте следующую отладку.
Для видеокадра «я» — сохраните его в памяти. Затем сохраните его на диск и прочитайте обратно из файла в память. Теперь самая важная часть: сравнить изображения. Если они разные — это причина разных результатов обнаружения лиц. Если нет, то требуется дальнейшее расследование. Я уверен, что изображения не будут идентичны, и в этом проблема. Вы можете увидеть, где изображения не идентичны, взяв различия между значениями пикселей и отобразив разностное изображение. Вы можете сравнить изображения, используя memcmp()
функция, которая сравнивает 2 блока памяти.
Удачи
Решил это!
Действительно глупая ошибка. Я не вызывал facecascades.load для загрузки haarcascades для версии статического изображения, но я сделал это для версии видеокамеры.
Теперь все работает.