本次笔记要整理记录的内容是关于三个caffe模型的联合调用,分别是人脸检测模型、性别检测模型和年龄检测模型。基于这三个模型来实现实时的性别年龄检测效果。
这个效果实现的思路如下:
(1)加载预先下载好的三个caffe网络模型;
(2)打开摄像头加载视频流;
(3)对从摄像头中获取每一帧图像进行人脸检测;
(4)对检测到的人脸进行性别与年龄检测;
(5)解析检测结果;
(6)显示检测结果。
下面通过代码来逐步整理。
首先,我们需要加载这三个模型,并设置计算后台和目标设备,由于是对视频流进行实时处理,所以我们对运算速度有更快的要求,在这里使用openVINO作为计算后台,用来进行CPU加速。
//加载人脸检测模型
string face_model_path = "D:\\opencv_c++\\opencv_tutorial\\data\\models\\face_detector\\res10_300x300_ssd_iter_140000_fp16.caffemodel";
string face_config_path = "D:\\opencv_c++\\opencv_tutorial\\data\\models\\face_detector\\deploy.prototxt";
Net face_net = readNetFromCaffe(face_config_path, face_model_path);
face_net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
face_net.setPreferableTarget(DNN_TARGET_CPU);
//加载年龄预测模型
string age_model_path = "D:/opencv_c++/opencv_tutorial/data/models/cnn_age_gender_models/age_net.caffemodel";
string age_config_path = "D:/opencv_c++/opencv_tutorial/data/models/cnn_age_gender_models/age_deploy.prototxt";
Net age_net = readNetFromCaffe(age_config_path, age_model_path);
age_net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
age_net.setPreferableTarget(DNN_TARGET_CPU);
//加载性别预测模型
string gender_model_path = "D:\\opencv_c++\\opencv_tutorial\\data\\models\\cnn_age_gender_models\\gender_net.caffemodel";
string gender_config_path = "D:\\opencv_c++\\opencv_tutorial\\data\\models\\cnn_age_gender_models\\gender_deploy.prototxt";
Net gender_net = readNetFromCaffe(gender_config_path, gender_model_path);
gender_net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
gender_net.setPreferableTarget(DNN_TARGET_CPU);
然后我们需要分别定义性别检测模型和年龄检测模型各自的标签集,使得检测结果能够索引到正确的标签。这里的年龄检测模型将检测年龄段分为了8个区间,每次检测将会得到其中一个区间值,可能是因为太精确的年龄检测起来很困难,所以才采取了分区间的方法把。至于性别检测模型就不用多说了,分为“男”、“女”两类。
//定义年龄、性别标签
string age_labels[8] = {
"0-2","4-6","8-12","15-20","25-32","38-43","48-53","60-100" };
string gender_labels[2] = {
"Man","Woman" };
然后调用摄像头,并判断是否能够正常打开摄像头
//调用摄像头
VideoCapture capture;
capture.open(0,CAP_DSHOW);
if (!capture.isOpened())
{
cout << "can't open camera" << endl;
exit(-1);
}
当我们对某一帧图像进行检测的时候,首先需要通过人脸检测模型来定位到人脸区域,并且获取这个人脸区域。这里可以设置一个阈值,用来判断检测到的对象是人脸的置信度有多高。
而且由于后续对人脸进行性别年龄检测的时候,我们需要把人脸区域给截出来,所以在定位人脸的时候我们必须注意到人脸检测框不可以超出图像的范围,一旦截取的人脸检测框超出了图像范围就会导致访问越界,显示内存出错。
所以我们在进行人脸区域截取之前,必须先对检测框进行限制,避免它出现越界。
flip(frame, frame, 1);
Mat inputBlob = blobFromImage(frame, 1, Size(300, 300), Scalar(104, 117, 123), true, false);
face_net.setInput(inputBlob);
Mat face_prob = face_net.forward();
Mat face_detection = Mat(face_prob.size[2], face_prob.size[3], CV_32F, face_prob.ptr<float>());
float confidence_thresh = 0.6;
for (int row = 0;row < face_detection.rows;row++)
{
float confidence = face_detection.at<float>(row, 2);
if (confidence