admin 管理员组

文章数量: 1087649

(八)OpenCV

文章目录

  • 1. 简介
  • 2. Face Detector
  • 3. Age Detector
  • 4. Gender Detector
  • 5. 代码实现
  • 参考


1. 简介

本文介绍的内容是判断给定图像中人物的年龄和性别等信息。大致思路是首先使用人脸检测器定位人脸位置,然后分别使用年龄检测模型和性别检测模型得到最终的检测结果。


2. Face Detector

该项目的关键是首先准确定位人脸的位置,上图是所使用的人脸检测模型。


3. Age Detector


4. Gender Detector


5. 代码实现

#include<tuple>
#include<vector>
#include<iostream>#include<opencv2/dnn.hpp>
#include<opencv2/imgproc.hpp>
#include<opencv2/highgui.hpp>using namespace cv;
using namespace std;
using namespace cv::dnn;tuple<Mat, vector<vector<int>>> getFaceBox(Net net, Mat& frame, double conf_threshold) {Mat frameOpenCVDNN = frame.clone();// 输入图像高、宽int frameHeight = frameOpenCVDNN.rows;int frameWidth = frameOpenCVDNN.cols;// 缩放系数double inScaleFactor = 1.0;// 归一化后的图像大小Size size = Size(300, 300);// 归一化所使用的均值Scalar meanVal = Scalar{ 104, 117, 123 };// 获取输入图像并转换格式cv::Mat inputBlob;// 各参数含义(输入图像, 缩放系数, 输出图形尺寸, 均值, 是否交换RB两通道, 是否裁剪图像)inputBlob = cv::dnn::blobFromImage(frameOpenCVDNN, inScaleFactor, size, meanVal, true, false);// 模型输入,根据关键字"data"net.setInput(inputBlob, "data");// 模型输出,根据关键字"detection_out"cv::Mat detection = net.forward("detection_out");// 存放输出结果,并使用detection初始化cv::Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());// 存放检测框vector<vector<int>> bboxes;// 遍历检测结果for (int i = 0; i < detectionMat.rows; ++i) {// 置信度float confidence = detectionMat.at<float>(i, 2);if (confidence > conf_threshold) {// 获取边界框int x1 = static_cast<int>(detectionMat.at<float>(i, 3) * frameWidth);int y1 = static_cast<int>(detectionMat.at<float>(i, 4) * frameHeight);int x2 = static_cast<int>(detectionMat.at<float>(i, 5) * frameWidth);int y2 = static_cast<int>(detectionMat.at<float>(i, 6) * frameHeight);vector<int> box = { x1, y1, x2, y2 };bboxes.push_back(box);// 绘制用于标识人脸位置的矩形cv::rectangle(frameOpenCVDNN, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(0, 255, 0), 2, 4);}}return make_tuple(frameOpenCVDNN, bboxes);
}int main(int argc, char** argv) {// 各模型地址string faceProto = "assets/opencv_face_detector.pbtxt";string faceModel = "assets/opencv_face_detector_uint8.pb";string ageProto = "assets/age_deploy.prototxt";string ageModel = "assets/age_net.caffemodel";string genderProto = "assets/gender_deploy.prototxt";string genderModel = "assets/gender_net.caffemodel";Scalar MODEL_MEAN_VALUES = Scalar(78.4263377603, 87.7689143744, 114.895847746);// 年龄vector<string> ageList = { "(0-2)", "(4-6)", "(8-12)", "(15-20)", "(25-32)", "(38-43)", "(48-53)", "(60-100)" };// 性别vector<string> genderList = { "Male", "Female" };// 模型加载,readNet支持Caffe(.caffemodel), TensorFlow(.pb), Torch(.t7), DarkNet(.weights), DLDT(.bin), ONNX(.onnx)等模型// 不支持常用的PyTorch模型,需要首先将其转换为ONNX等格式Net faceNet = readNet(faceModel, faceProto);Net ageNet = readNet(ageModel, ageProto);Net genderNet = readNet(genderModel, genderProto);// 读取图像Mat image = imread("assets/face.jpg");// 人脸检测,并获取结果Mat img;vector<vector<int>> bboxes;tie(img, bboxes) = getFaceBox(faceNet, image, 0.7);// 如果没有检测到目标if (bboxes.size() == 0) {cout << "No face detected!" << endl;return -1;}// 处理结果int padding = 20;for (auto it = begin(bboxes); it != end(bboxes); ++it) {// 由(x1,y1,x2,y2)转换成(x,y,w,h),并增加填充Rect rec(it->at(0) - padding, it->at(1) - padding, it->at(2) - it->at(0) + 2 * padding, it->at(3) - it->at(1) + 2 * padding);// 设置RoIMat face = img(rec);// 处理输入图像Mat blob;blob = blobFromImage(face, 1, Size(227, 227), MODEL_MEAN_VALUES, false);// 设置模型输入genderNet.setInput(blob);// 预测年龄vector<float> genderPreds = genderNet.forward();// 得到结果对应的索引,使用std::distance返回结果要么为0要么为1int max_index_gender = std::distance(genderPreds.begin(), max_element(genderPreds.begin(), genderPreds.end()));// 性别string gender = genderList[max_index_gender];cout << "Gender: " << gender << endl;// 获得年龄预测输出ageNet.setInput(blob);vector<float> agePreds = ageNet.forward();// 得到结果对应的索引,同上int max_indice_age = std::distance(agePreds.begin(), max_element(agePreds.begin(), agePreds.end()));// 年龄string age = ageList[max_indice_age];cout << "Age: " << age << endl;// 显示内容string label = gender + ", " + age;// 显示结果cv::putText(img, label, Point(it->at(0), it->at(1) - 15), cv::FONT_HERSHEY_SIMPLEX, 0.9, Scalar(0, 255, 255), 2, cv::LINE_AA);imshow("Image", img);imwrite("assets/out.jpg", img);}return 0;
}

结果展示:


参考

  1. .


本文标签: (八)OpenCV