基于 DNN 的人脸检测和识别
基于 DNN 的人脸检测和识别
介绍
在本节中,我们将介绍用于人脸检测的 cv::FaceDetectorYN 类和用于人脸识别的 cv::FaceRecognizerSF 类。
模型
本模块需要预训练两个模型(ONNX 格式):
数据库 | 准确性 | 阈值 (normL2) | 阈值(余弦) |
---|---|---|---|
LFW(英语:LFW) | 99.60% | 1.128 | 0.363 |
小牛 | 93.95% | 1.149 | 0.340 |
CPLFW系列 | 91.05% | 1.204 | 0.275 |
年龄DB-30 | 94.90% | 1.202 | 0.277 |
CFP-FP型 | 94.80% | 1.253 | 0.212 |
法典
C++蟒
- 可下载代码: 点击这里
- 代码一目了然:
#include < opencv2/dnn.hpp>#include < opencv2/imgproc.hpp>#include < opencv2/highgui.hpp>#include < opencv2/objdetect.hpp>#include < iostream>使用命名空间 CV;使用命名空间 std;静态的{std::string fpsString = cv::format(“FPS : %.2f”, (float)fps);if(帧 >= 0)cout << “帧 ” << 帧 << “, ”;cout << “FPS: ” << fpsString << endl;for (int i = 0; i <面。行;i++){打印结果cout << “Face ” << i<< “score: ” << cv::format(“%.2f”, faces.at<float>(i, 14))<< endl;绘制边界框rectangle(input, Rect2i(int(faces.at<float>(i, 0)), int(faces.at<float>(i, 1)), int(faces.at<float>(i, 2)), int(faces.at<float>(i, 3))), 标量(0, 255, 0), 厚度);绘制地标circle(input, Point2i(int(faces.at<float>(i, 4)), int(faces.at<float>(i, 5))), 2, 标量(255, 0, 0), 厚度);circle(input, Point2i(int(faces.at<float>(i, 6)), int(faces.at<float>(i, 7))), 2, 标量(0, 0, 255), 厚度);circle(input, Point2i(int(faces.at<float>(i, 8)), int(faces.at<float>(i, 9))), 2, 标量(0, 255, 0), 厚度);circle(input, Point2i(int(faces.at<float>(i, 10)), int(faces.at<float>(i, 11))), 2, 标量(255, 0, 255), 厚度);circle(input, Point2i(int(faces.at<float>(i, 12)), int(faces.at<float>(i, 13))), 2, 标量(0, 255, 255), 厚度);}putText(input, fpsString, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 2);}int main(int argc, char** argv){CommandLineParser 解析器(argc, argv,“{帮助 h | |打印此消息}”“{image1 i1 | |输入 image1 的路径。省略通过VideoCapture进行检测}”“{image2 i2 | |输入图像的路径2。当给出 image1 和 image2 参数时,程序会尝试在两张图像上找到一张人脸并运行人脸识别算法}”“{视频 v |0 |输入视频路径}”“{scale sc |1.0 |用于调整输入视频帧大小的比例因子}”“{fd_model fd |face_detection_yunet_2021dec.onnx|模型的路径。下载 yunet.onnx 在 https://github.com/opencv/opencv_zoo/tree/master/models/face_detection_yunet}”“{fr_model fr |face_recognition_sface_2021dec.onnx |人脸识别模型的路径。在 https://github.com/opencv/opencv_zoo/tree/master/models/face_recognition_sface}下载模型”“{score_threshold |0.9 |过滤掉分数< score_threshold}”“{nms_threshold |0.3 |禁止 iou >= nms_threshold}“ 的边界框“{top_k |5000 |在 NMS 之前保留top_k边界框}”“{保存 |假 |设置为 true 以保存结果。使用相机时,此标志无效}”);if (parser.has(“帮助”)){解析器.printMessage();返回 0;}float scoreThreshold = 解析器.get<float>(“score_threshold”);浮点 nmsThreshold = parser.get<float>(“nms_threshold”);int topK = 解析器.get<int>(“top_k”);bool save = parser.get<bool>(“保存”);浮点比例 = parser.get<float>(“scale”);双cosine_similar_thresh = 0.363;双l2norm_similar_thresh = 1.128;初始化 FaceDetectorYNPtr<FaceDetectorYN> detector = FaceDetectorYN::create(fd_modelPath, “”, Size(320, 320), scoreThreshold, nmsThreshold, topK);滴答计 tm;如果输入是图像if (parser.has(“image1”)){垫子 image1 = imread(samples::findFile(input1));如果 (image1.empty()){std::cerr << “无法读取图像:” << input1 << std::endl;返回 2;}int imageWidth = int(image1.cols * 比例);int imageHeight = int(image1.rows * 比例);tm。开始();在推理之前设置输入大小探测器->setInputSize(image1.size());垫面1;检测器->detect(image1, faces1);如果(faces1.行 < 1){std::cerr << “在 ” << input1 << std::endl;返回 1;}tm。停();在输入图像上绘制结果可视化(image1, -1, faces1, tm.获取FPS());如果 save 为 true,则保存结果if(保存){cout << “保存结果.jpg...\n”;imwrite(“结果.jpg”, image1);}可视化结果imshow(“图像1”, 图像1);pollKey();处理 UI 事件以显示内容if (parser.has(“image2”)){垫子 image2 = imread(samples::findFile(input2));如果 (image2.empty()){std::cerr << “无法读取 image2:” << input2 << std::endl;返回 2;}tm。重置();tm。开始();探测器->setInputSize(image2.size());垫面2;检测器->检测(图像2,人脸2);如果 (faces2.行 < 1){std::cerr << “在 ” << input2 << std::endl;返回 1;}tm。停();visualize(image2, -1, faces2, tm.获取FPS());if(保存){cout << “保存结果 2.jpg...\n”;imwrite(“结果2.jpg”, image2);}imshow(“图像2”, 图像2);初始化 FaceRecognizerSFPtr<FaceRecognizerSF> faceRecognizer = FaceRecognizerSF::create(fr_modelPath,"");通过检测到的第一张面孔对齐和裁剪面部图像。Mat aligned_face1,aligned_face2;faceRecognizer->alignCrop(image1, faces1.row(0), aligned_face1);faceRecognizer->alignCrop(image2, faces2.row(0), aligned_face2);使用给定aligned_face运行特征提取垫子特征1,特征2;faceRecognizer->feature(aligned_face1, feature1);feature1 = feature1。克隆();faceRecognizer->feature(aligned_face2, feature2);特征 2 = 特征 2。克隆();double cos_score = faceRecognizer->match(feature1, feature2, FaceRecognizerSF::D isType::FR_COSINE);双L2_score = faceRecognizer->match(feature1, feature2, FaceRecognizerSF::D isType::FR_NORM_L2);如果 (cos_score >= cosine_similar_thresh){std::cout << “他们具有相同的身份;”;}还{std::cout << “他们有不同的身份;”;}std::cout << “余弦相似度:”<< cos_score <<“,阈值:”<< cosine_similar_thresh <<”。(值越高表示相似度越高,最大值为 1.0)\n”;如果 (L2_score <= l2norm_similar_thresh){std::cout << “他们具有相同的身份;”;}还{std::cout << “他们有不同的身份。”;}std::cout << “ NormL2 距离:” << L2_score << “,阈值:” << l2norm_similar_thresh << ”。(值越低表示相似度越高,最小值为0.0)\n”;}cout << “按任意键退出...” << endl;waitKey(0);}还{int frameWidth, frameHeight;VideoCapture 捕获;std::string video = 解析器。get<string>(“视频”);if (video.size() == 1 && isdigit(video[0]))捕获。open(parser.get<int>(“视频”));还捕获。open(samples::findFileOrKeep(video));保留 GStreamer 流水线if(捕获。is已打开()){frameWidth = int(capture.get(CAP_PROP_FRAME_WIDTH) * 比例);frameHeight = int(capture.get(CAP_PROP_FRAME_HEIGHT) * 缩放);cout << “Video ” << video<< “: width=” << frameWidth<< “, height=” << frameHeight<< endl;}还{cout << “无法初始化视频捕获:”<<视频<<“\n”;返回 1;}detector->setInputSize(Size(frameWidth, frameHeight));cout << “按'空格'保存帧,任何其他键退出......” << endl;int nFrame = 0;为 (;;){获取框架垫子框架;if (!capture.读取(帧)){cerr << “抓不住框架!停止\n”;破;}推理垫面;tm。开始();detector->detect(帧,人脸);tm。停();在输入图像上绘制结果visualize(result, nFrame, faces, tm.获取FPS());可视化结果imshow(“Live”, 结果);int 键 = waitKey(1);bool saveFrame = 保存;如果(键 ==' '){saveFrame = 真;键 = 0;//处理}如果 (saveFrame){std::string frame_name = cv::format(“frame_%05d.png”, nFrame);std::string result_name = cv::format(“result_%05d.jpg”, nFrame);cout << “保存 '” << frame_name << “' 和 '” << result_name << “' ...\n” ;imwrite(frame_name, 帧);imwrite(result_name, 结果);}++n框架;if(密钥> 0)破;}cout << “已处理 ” << nFrame << “frames” << endl;}cout << “完成。” << endl;返回 0;}
解释
初始化 FaceDetectorYNPtr<FaceDetectorYN> detector = FaceDetectorYN::create(fd_modelPath, “”, Size(320, 320), scoreThreshold, nmsThreshold, topK);在推理之前设置输入大小探测器->setInputSize(image1.size());垫面1;检测器->detect(image1, faces1);如果 (faces1.rows < 1){std::cerr << “在 ” << input1 << std::endl;返回 1;}
检测输出是 CV_32F 类型的二维数组,其行是检测到的人脸实例,列是人脸的位置和 5 个人脸特征点。每行的格式如下:faces
,其中是左上角坐标,人脸边界框的宽度和高度,分别代表右眼、左眼、鼻尖、右嘴角和左嘴角的坐标。x1, y1, w, h
{x, y}_{re, le, nt, rcm, lcm}
人脸识别
C++蟒
在人脸检测之后,运行下面的代码以从人脸图像中提取人脸特征。
初始化 FaceRecognizerSFPtr<FaceRecognizerSF> faceRecognizer = FaceRecognizerSF::create(fr_modelPath,"");通过检测到的第一张面孔对齐和裁剪面部图像。Mat aligned_face1,aligned_face2;faceRecognizer->alignCrop(image1, faces1.row(0), aligned_face1);faceRecognizer->alignCrop(image2, faces2.row(0), aligned_face2);使用给定aligned_face运行特征提取垫子特征1,特征2;faceRecognizer->feature(aligned_face1, feature1);feature1 = feature1。克隆();faceRecognizer->feature(aligned_face2, feature2);特征 2 = 特征 2。克隆();
获取两张人脸图像的人脸特征特征 1 和特征 2 后,运行下面的代码来计算两人脸之间的同一性差异。
double cos_score = faceRecognizer->match(feature1, feature2, FaceRecognizerSF::D isType::FR_COSINE);双L2_score = faceRecognizer->match(feature1, feature2, FaceRecognizerSF::D isType::FR_NORM_L2);
例如,如果余弦距离大于或等于 0.363,或者 normL2 距离小于或等于 1.128,则两个面具有相同的标识。
在线教程
- 麻省理工学院人工智能视频教程 – 麻省理工人工智能课程
- 人工智能入门 – 人工智能基础学习。Peter Norvig举办的课程
- EdX 人工智能 – 此课程讲授人工智能计算机系统设计的基本概念和技术。
- 人工智能中的计划 – 计划是人工智能系统的基础部分之一。在这个课程中,你将会学习到让机器人执行一系列动作所需要的基本算法。
- 机器人人工智能 – 这个课程将会教授你实现人工智能的基本方法,包括:概率推算,计划和搜索,本地化,跟踪和控制,全部都是围绕有关机器人设计。
- 机器学习 – 有指导和无指导情况下的基本机器学习算法
- 机器学习中的神经网络 – 智能神经网络上的算法和实践经验
- 斯坦福统计学习
有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓
人工智能书籍
- OpenCV(中文版).(布拉德斯基等)
- OpenCV+3计算机视觉++Python语言实现+第二版
- OpenCV3编程入门 毛星云编著
- 数字图像处理_第三版
- 人工智能:一种现代的方法
- 深度学习面试宝典
- 深度学习之PyTorch物体检测实战
- 吴恩达DeepLearning.ai中文版笔记
- 计算机视觉中的多视图几何
- PyTorch-官方推荐教程-英文版
- 《神经网络与深度学习》(邱锡鹏-20191121)
- …
第一阶段:零基础入门(3-6个月)
新手应首先通过少而精的学习,看到全景图,建立大局观。 通过完成小实验,建立信心,才能避免“从入门到放弃”的尴尬。因此,第一阶段只推荐4本最必要的书(而且这些书到了第二、三阶段也能继续用),入门以后,在后续学习中再“哪里不会补哪里”即可。
第二阶段:基础进阶(3-6个月)
熟读《机器学习算法的数学解析与Python实现》并动手实践后,你已经对机器学习有了基本的了解,不再是小白了。这时可以开始触类旁通,学习热门技术,加强实践水平。在深入学习的同时,也可以探索自己感兴趣的方向,为求职面试打好基础。
第三阶段:工作应用
这一阶段你已经不再需要引导,只需要一些推荐书目。如果你从入门时就确认了未来的工作方向,可以在第二阶段就提前阅读相关入门书籍(对应“商业落地五大方向”中的前两本),然后再“哪里不会补哪里”。
有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓
更多推荐
所有评论(0)