OpenCV реализует обнаружение лиц на основе остаточной сети
Версия OpenCV3.3 впервые представила модуль Deep Neural Network (DNN) в официальной версии выпуска.Модуль DNN в последней версии OpenCV3.4 выпустил две нирваны, одна из которых поддерживает более быстрое обнаружение объектов R-CNN, что быстрее, чем SSD.По сравнению с YOLO, эти модели имеют более высокую точность обнаружения и возможности обнаружения мелких объектов.Другой является поддержка обнаружения лиц на основе модели SSD + Resnet.Хотя скорость не может достичь производительности каскадного детектора HAAR в реальном времени, точность и модель Способность к обобщению можно назвать алгоритмом обнаружения лиц метода каскадного детектора HAAR. Как разработчик OpenCV, которому нужна функция обнаружения лиц, есть более надежный выбор.Здесь мы сначала кратко представим, что такое остаточная сеть, а затем продемонстрируем ее модель обнаружения лиц, основанную на обнаружении лиц камерой в реальном времени в OpenCV.
Один: Остаточная сеть (Resnet)
Исходная сеть CNN LeNet и AlexNet имеет относительно мало сверточных слоев.VGG достигает значительного увеличения глубины сети за счет небольшого ядра свертки, но когда количество слоев чрезмерно увеличивается, обнаруживается, что как ошибки обучения, так и ошибки тестирования увеличиваются. , как показано ниже:
Сначала люди думали, что это вызвано исчезновением градиента или взрывом градиента, но благодаря всем усилиям это не проблема переобучения, а явление затухания сети, поэтому в ответ на эту ситуацию команда MSRA He Kaiming предложила метод. Идея новой сетевой модели - Остаточные сети заключается в использовании остаточной структуры для обучения сети Остаточная структура выглядит следующим образом:
Автор считает, что F(x) = H(x)-x, поэтому получается тождественное отображение, такое как H(x) = F(x) + x, а затем автор устанавливает 34-слойную простую сеть и 34-слойную сеть. -слойная остаточная сеть в качестве сравнения. Крайняя левая сеть VGG-19 используется в качестве эталона, и вся структура сети показана следующим образом:
--- Картинка слишком большая! ! !
После того, как модель была создана, автор провел обучение и тестирование на различных наборах данных и заметил, что эффект остаточной сети был значительно лучше, чем у простой 34-слойной сети, и обнаружил, что чем глубже слой сети, основанный на остаточная структура, тем лучше эффект Ну, 34-слойная обычная сеть имеет очевидное явление затухания по сравнению с 18-слойной простой сетью. Результаты сравнительного обучения следующие:
До появления остаточной сети немногие сети имели более 100 слоев, но остаточная сеть могла достигать тысяч слоев.Нет никаких сомнений в том, что команда Хэ Кайминга также использовала модель остаточной сети в конкурсе классификации изображений ImageNet в 2015 году. чемпионат с использованием 152-слойной остаточной сети. Остаточная сетевая модель распознавания лиц в OpenCV основана на SSD, поэтому скорость по-прежнему довольно высока, а эффект особенно хорош. Не так много глупостей, позвольте мне посмотреть, как использовать его для обнаружения лиц в OpenCV.
Второе: реализация кода распознавания лиц
Модель генерируется на основе обучения сети Caffe, поэтому первое, что нужно сделать перед тем, как приступить к написанию программы, это скачать файл модели и файл описания, я уже скачал это, так что вам не нужно переходить на мой адрес github. файл модели
GitHub.com/gloomyfish1…
Скачав модель, поместите ее в локальную папку, после чего можно приступать к программированию.
Сначала нужно загрузить модель в сеть:
String modelDesc = "D:/vcprojects/images/dnn/face/deploy.prototxt";
String modelBinary = "D:/vcprojects/images/dnn/face/res10_300x300_ssd_iter_140000.caffemodel";
// 初始化网络
dnn::Net net = readNetFromCaffe(modelDesc, modelBinary);
if (net.empty())
{
printf("could not load net...\n");
return -1;
}
Затем, чтобы открыть локальную камеру или видеофайл, используйте объект VideoCapture, код выглядит следующим образом:
// 打开摄像头
VideoCapture capture(0);
if (!capture.isOpened()) {
printf("could not load camera...\n");
return -1;
}
После того, как камера успешно открыта, каждый кадр изображения может быть прочитан и записан, а затем преобразован в тип данных, приемлемый для сети.Код выглядит следующим образом:
// 输入数据调整
Mat inputBlob = blobFromImage(frame, inScaleFactor,
Size(inWidth, inHeight), meanVal, false, false);
net.setInput(inputBlob, "data");
Затем в OpenCV, вызвав net.forward для обнаружения, извлеките показатель достоверности (0 ~ 1) для результата и извлеките позицию BOX выше порогового значения (при условии, что 0,5), вы можете нарисовать прямоугольную рамку для отображения, код этой части выглядит следующим образом:
// 人脸检测
Mat detection = net.forward("detection_out");
vector<double> layersTimings;
double freq = getTickFrequency() / 1000;
double time = net.getPerfProfile(layersTimings) / freq;
Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());
ostringstream ss;
ss << "FPS: " << 1000 / time << " ; time: " << time << " ms";
putText(frame, ss.str(), Point(20, 20), 0, 0.5, Scalar(0, 0, 255));
for (int i = 0; i < detectionMat.rows; i++)
{
float confidence = detectionMat.at<float>(i, 2);
if (confidence > confidenceThreshold)
{
int xLeftBottom = static_cast<int>(detectionMat.at<float>(i, 3) * frame.cols);
int yLeftBottom = static_cast<int>(detectionMat.at<float>(i, 4) * frame.rows);
int xRightTop = static_cast<int>(detectionMat.at<float>(i, 5) * frame.cols);
int yRightTop = static_cast<int>(detectionMat.at<float>(i, 6) * frame.rows);
Rect object((int)xLeftBottom, (int)yLeftBottom,
(int)(xRightTop - xLeftBottom),
(int)(yRightTop - yLeftBottom));
rectangle(frame, object, Scalar(0, 255, 0));
ss.str("");
ss << confidence;
String conf(ss.str());
String label = "Face: " + conf;
int baseLine = 0;
Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
rectangle(frame, Rect(Point(xLeftBottom, yLeftBottom - labelSize.height),
Size(labelSize.width, labelSize.height + baseLine)),
Scalar(255, 255, 255), CV_FILLED);
putText(frame, label, Point(xLeftBottom, yLeftBottom),
FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0));
}
}
Окончательные результаты бегущего дисплея следующие, при нормальных обстоятельствах лицо не заблокировано:
С открытым лицом и наклоненной головой:
Когда лицо закрыто:
Больше в различных ситуациях, таких как наклон, боковая грань, размытие и т. д.:
Видно, насколько мощна модель остаточной сети.Не пора ли заказать песню «Лян Лян» и отправить ее на каскадный детектор HAAR. Полный исходный код приведенной выше демонстрации можно загрузить на GITHUB.
GitHub.com/gloomyfish1…