赞
踩
目录
最近项目中大量场景需要用到人脸检测和人脸关键点检测技术,因此经过一番查找,将相关资料进行了整理,最终的目的是希望能够将基于深度学习的人脸检测算法落地部署,方便未来直接嵌入到自己的项目中。
本文主要使用于士琪的人脸检测代码来操作,详细的训练(Pytorch版)过程和使用说明请参考官方代码:
libfacedetectionhttps://github.com/ShiqiYu/libfacedetection值得注意的是上述开源项目已经贡献到OpenCV里面了,因此,只需要安装最新的opencv即可方便的使用该人脸检测代码。
本文使用Windows10操作系统进行部署,只使用CPU,不依赖GPU。如果需要使用GPU,需要下载对应支持GPU CUDA版本的opencv。
本文完整代码链接:https://download.csdn.net/download/qianbin3200896/77986050
首选安装环境包:
- pip install numpy
- pip install "opencv-python>=4.5.4.58" -i https://mirror.baidu.com/pypi/simple
这里为了加速下载使用了百度镜像源。安装过程中如果opencv一直安装不上,可以尝试先更新下pip软件:
pip install --upgrade pip setuptools wheel
推理代码如下所示:
- import numpy as np
- import cv2 as cv
-
-
- def visualize(image, faces, print_flag=False):
- '''
- 可视化结果
- '''
- output = image.copy()
-
- for idx, face in enumerate(faces):
- if print_flag:
- print('Face {}, top-left coordinates: ({:.0f}, {:.0f}), box width: {:.0f}, box height {:.0f}, score: {:.2f}'.format(idx, face[0], face[1], face[2], face[3], face[-1]))
-
- coords = face[:-1].astype(np.int32)
- # 画人脸框
- cv.rectangle(output, (coords[0], coords[1]), (coords[0]+coords[2], coords[1]+coords[3]), (0, 255, 0), 2)
- # 画关键点
- cv.circle(output, (coords[4], coords[5]), 2, (255, 0, 0), 2)
- cv.circle(output, (coords[6], coords[7]), 2, (0, 0, 255), 2)
- cv.circle(output, (coords[8], coords[9]), 2, (0, 255, 0), 2)
- cv.circle(output, (coords[10], coords[11]), 2, (255, 0, 255), 2)
- cv.circle(output, (coords[12], coords[13]), 2, (0, 255, 255), 2)
- # 画置信度
- cv.putText(output, '{:.4f}'.format(face[-1]), (coords[0], coords[1]+15), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0))
-
- return output
-
-
- def main():
- '''
- 主函数
- '''
- # 初始化模型
- yunet = cv.FaceDetectorYN.create(
- model='./yunet.onnx',
- config='',
- input_size=(320, 320),
- score_threshold=0.6,
- nms_threshold=0.3,
- top_k=5000,
- backend_id=cv.dnn.DNN_BACKEND_DEFAULT,
- target_id=cv.dnn.DNN_TARGET_CPU
- )
-
- # 读入图像
- image = cv.imread('test.jpg')
-
- # 重新设置模型输入尺寸
- yunet.setInputSize((image.shape[1], image.shape[0]))
-
- # 执行检测
- _, faces = yunet.detect(image)
-
- # 画检测框和关键点
- vis_image = visualize(image, faces)
-
- # 保存图像
- cv.imwrite('new.jpg', vis_image)
-
- print('完成')
-
-
- if __name__ == '__main__':
- main()
效果图如下所示:
从效果上来看检测精度是比较高的,满足实用需求。
测试结果如下所示:
图像尺寸 | CPU型号 | CPU单次推理时间 |
1280 X 960 | CPU型号 Intel(R) Core(TM) CPU i7-6700 @ 3.40GHz | 102毫秒 |
如果想要达到实时性检测要求,把图像分辨率降低1倍,即控制在512x512的尺寸,那么就可以满足该指标。如果想要在嵌入式设备上跑该代码,那还需要再进一步优化。
本节使用VS2019在windows平台上通过C++实现人脸检测和人脸关键点检测。
首先从官网下载最新版opencv:Releases - OpenCVhttps://opencv.org/releases/
本文下载使用对应windows版本的opencv4.5.5。
接下来用VS2019创建一个控制台项目:
创建完成后切换成64位Release平台:
然后进行项目配置如下:
(1)属性配置——VC++目录
(2)属性配置——库目录
(3)链接器——输入
添加lib文件如下:
接下来将opencv对应的dll文件(opencv_world455.dll)和模型文件yunet.onnx拷贝到项目根目录下即可。如下图所示:
完整推理代码如下:
- #include <iostream>
-
- //导入opencv库
- #include <opencv2/dnn.hpp>
- #include <opencv2/imgproc.hpp>
- #include <opencv2/highgui.hpp>
- #include <opencv2/objdetect.hpp>
-
- //定义命名空间
- using namespace std;
- using namespace cv;
-
-
- Mat visualize(cv::Mat input, cv::Mat faces, bool print_flag = false, int thickness = 2)
- {
- cv::Mat output = input.clone();
-
- for (int i = 0; i < faces.rows; i++)
- {
- if (print_flag) {
- cout << "Face " << i
- << ", top-left coordinates: (" << faces.at<float>(i, 0) << ", " << faces.at<float>(i, 1) << "), "
- << "box width: " << faces.at<float>(i, 2) << ", box height: " << faces.at<float>(i, 3) << ", "
- << "score: " << faces.at<float>(i, 14) << "\n";
- }
-
- // 画人脸框
- cv::rectangle(output, cv::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))), cv::Scalar(0, 255, 0), thickness);
- // 画关键点
- cv::circle(output, cv::Point2i(int(faces.at<float>(i, 4)), int(faces.at<float>(i, 5))), 2, cv::Scalar(255, 0, 0), thickness);
- cv::circle(output, cv::Point2i(int(faces.at<float>(i, 6)), int(faces.at<float>(i, 7))), 2, cv::Scalar(0, 0, 255), thickness);
- cv::circle(output, cv::Point2i(int(faces.at<float>(i, 8)), int(faces.at<float>(i, 9))), 2, cv::Scalar(0, 255, 0), thickness);
- cv::circle(output, cv::Point2i(int(faces.at<float>(i, 10)), int(faces.at<float>(i, 11))), 2, cv::Scalar(255, 0, 255), thickness);
- cv::circle(output, cv::Point2i(int(faces.at<float>(i, 12)), int(faces.at<float>(i, 13))), 2, cv::Scalar(0, 255, 255), thickness);
- // 画置信度
- cv::putText(output, cv::format("%.4f", faces.at<float>(i, 14)), cv::Point2i(int(faces.at<float>(i, 0)), int(faces.at<float>(i, 1)) + 15), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0));
- }
- return output;
- }
-
- int main(int argc, char** argv)
- {
- //参数设置
- cv::String modelPath = "yunet.onnx";
- int backendId = 0; //0: default, 1: Halide, 2: Intel's Inference Engine, 3: OpenCV, 4: VKCOM, 5: CUDA
- int targetId = 0; //0: CPU, 1: OpenCL, 2: OpenCL FP16, 3: Myriad, 4: Vulkan, 5: FPGA, 6: CUDA, 7: CUDA FP16, 8: HDDL
-
- float scoreThreshold = 0.9;
- float nmsThreshold = 0.3;
- int topK = 5000;
-
- // 初始化人脸检测器FaceDetectorYN
- cv::Ptr<cv::FaceDetectorYN> detector = cv::FaceDetectorYN::create(modelPath, "", cv::Size(320, 320), scoreThreshold, nmsThreshold, topK, backendId, targetId);
-
- // 加载图像
- cv::Mat image = cv::imread("test.jpg");
-
- // 重新设置尺寸
- detector->setInputSize(image.size());
-
- //检测
- cv::Mat faces;
- detector->detect(image, faces);
-
- //可视化结果
- cv::Mat vis_image = visualize(image, faces, true);
- cout << "执行完成.\n";
-
- //保存结果
- cv::imwrite("result.jpg", vis_image);
- }
Java推理部分请参考另一篇博文。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。