ZQCNN快速人脸检测
ZQCNN亦是一款开源人脸检测、特征点定位的优秀代码库,其基于MTCNN算法构建。
cpu 25ms,侧脸,低头都能检测到,精度不是很高,人脸框不是特别稳。
以下内容主要来自:
https://github.com/zuoqing1988/ZQCNN-MTCNN-vs-libfacedetection
ZQCNN-MTCNN-vs-libfacedetection
依赖库:
windows:mkl, opencv3.4.2
arm-linux: openblas, opencv3.4.2
libfacedetection:下载时间2019-03-25 09:00
该库无任何依赖。点赞~
mtcnn测试代码:
MKL 拷贝dll即可运行。
200多ms,人脸框不稳定,关键点也不是特别准。
#include "ZQ_CNN_Net.h"
#include "ZQ_CNN_MTCNN_old.h"
#include "ZQ_CNN_MTCNN.h"
#include <vector>
#include <iostream>
#include "opencv2/opencv.hpp"
#include "ZQ_CNN_CompileConfig.h"
#include <opencv2\imgproc\types_c.h>
#if ZQ_CNN_USE_BLAS_GEMM
#if __ARM_NEON
#include <openblas/cblas.h>
#else
#include <openblas/cblas.h>
#pragma comment(lib,"libopenblas.lib")
#endif
#elif ZQ_CNN_USE_MKL_GEMM
#include "mkl/mkl.h"
#pragma comment(lib,"mklml.lib")
#else
#pragma comment(lib,"ZQ_GEMM.lib")
#endif
using namespace ZQ;
using namespace std;
using namespace cv;static void Draw(cv::Mat &image, const std::vector<ZQ_CNN_BBox>& thirdBbox)
{std::vector<ZQ_CNN_BBox>::const_iterator it = thirdBbox.begin();for (; it != thirdBbox.end(); it++){if ((*it).exist){if (it->score > 0.7){cv::rectangle(image, cv::Point((*it).col1, (*it).row1), cv::Point((*it).col2, (*it).row2), cv::Scalar(0, 0, 255), 2, 8, 0);}else{cv::rectangle(image, cv::Point((*it).col1, (*it).row1), cv::Point((*it).col2, (*it).row2), cv::Scalar(0, 255, 0), 2, 8, 0);}for (int num = 0; num < 5; num++)circle(image, cv::Point(*(it->ppoint + num) + 0.5f, *(it->ppoint + num + 5) + 0.5f), 1, cv::Scalar(0, 255, 255), -1);}else{printf("not exist!\n");}}
}static void Draw(cv::Mat &image, const std::vector<ZQ_CNN_BBox106>& thirdBbox)
{std::vector<ZQ_CNN_BBox106>::const_iterator it = thirdBbox.begin();for (; it != thirdBbox.end(); it++){if ((*it).exist){if (it->score > 0.7){cv::rectangle(image, cv::Point((*it).col1, (*it).row1), cv::Point((*it).col2, (*it).row2), cv::Scalar(0, 0, 255), 2, 8, 0);}else{cv::rectangle(image, cv::Point((*it).col1, (*it).row1), cv::Point((*it).col2, (*it).row2), cv::Scalar(0, 255, 0), 2, 8, 0);}for (int num = 0; num < 106; num++)circle(image, cv::Point(*(it->ppoint + num * 2) + 0.5f, *(it->ppoint + num * 2 + 1) + 0.5f), 1, cv::Scalar(0, 255, 255), -1);}else{printf("not exist!\n");}}
}int main()
{int num_threads = 1;
#if ZQ_CNN_USE_BLAS_GEMMprintf("set openblas thread_num = %d\n",num_threads);openblas_set_num_threads(num_threads);
#elif ZQ_CNN_USE_MKL_GEMMmkl_set_num_threads(num_threads);
#endifVideoCapture cap = VideoCapture(0);if (!cap.isOpened())//如果视频不能正常打开则返回return 1;Mat image0;while (1){cap >> image0;//等价于cap.read(frame);if (image0.empty())//如果某帧为空则退出循环break;//cv::resize(image0, image0, cv::Size(), 2, 2);if (image0.channels() == 1)cv::cvtColor(image0, image0, CV_GRAY2BGR);//cv::convertScaleAbs(image0, image0, 2.0);/* TIPS: when finding tiny faces for very big image, gaussian blur is very useful for Pnet*/bool run_blur = true;int kernel_size = 3, sigma = 2;if (image0.cols * image0.rows >= 2500 * 1600){run_blur = false;kernel_size = 5;sigma = 3;}else if (image0.cols * image0.rows >= 1920 * 1080){run_blur = false;kernel_size = 3;sigma = 2;}else{run_blur = false;}if (run_blur){cv::Mat blur_image0;int nBlurIters = 1000;double t00 = omp_get_wtime();for (int i = 0; i < nBlurIters; i++)cv::GaussianBlur(image0, blur_image0, cv::Size(kernel_size, kernel_size), sigma, sigma);double t01 = omp_get_wtime();printf("[%d] blur cost %.3f secs, 1 blur costs %.3f ms\n", nBlurIters, t01 - t00, 1000 * (t01 - t00) / nBlurIters);cv::GaussianBlur(image0, image0, cv::Size(kernel_size, kernel_size), sigma, sigma);}std::vector<ZQ_CNN_BBox> thirdBbox;std::vector<ZQ_CNN_BBox106> thirdBbox106;ZQ_CNN_MTCNN mtcnn;std::string result_name;mtcnn.TurnOnShowDebugInfo();//mtcnn.SetLimit(300, 50, 20);const int use_pnet20 = true;bool landmark106 = true;int thread_num = 0;bool special_handle_very_big_face = false;result_name = "resultdet.jpg";if (use_pnet20){if (landmark106){
#if defined(_WIN32)if (!mtcnn.Init("model/det1-dw20-fast.zqparams", "model/det1-dw20-fast.nchwbin","model/det2-dw24-fast.zqparams", "model/det2-dw24-fast.nchwbin",//"model/det2.zqparams", "model/det2_bgr.nchwbin","model/det3-dw48-fast.zqparams", "model/det3-dw48-fast.nchwbin", thread_num, true,"model/det5-dw64-v3s.zqparams", "model/det5-dw64-v3s.nchwbin"//"model/det3.zqparams", "model/det3_bgr.nchwbin"
#elseif (!mtcnn.Init("../../model/det1-dw20-fast.zqparams", "../../model/det1-dw20-fast.nchwbin","../../model/det2-dw24-fast.zqparams", "../../model/det2-dw24-fast.nchwbin",//"../../model/det2.zqparams", "../../model/det2_bgr.nchwbin","../../model/det3-dw48-fast.zqparams", "../../model/det3-dw48-fast.nchwbin",thread_num, true,"../../model/det5-dw64-v3s.zqparams", "../../model/det5-dw64-v3s.nchwbin"//"../../model/det3.zqparams", "../../model/det3_bgr.nchwbin"
#endif)){cout << "failed to init!\n";return EXIT_FAILURE;}}else{
#if defined(_WIN32)if (!mtcnn.Init("model/det1-dw20-fast.zqparams", "model/det1-dw20-fast.nchwbin","model/det2-dw24-fast.zqparams", "model/det2-dw24-fast.nchwbin",//"model\\det2.zqparams", "model\\det2_bgr.nchwbin","model/det3-dw48-fast.zqparams", "model/det3-dw48-fast.nchwbin",//"model/det3.zqparams", "model/det3_bgr.nchwbin",thread_num, false,"model/det4-dw48-v2n.zqparams", "model/det4-dw48-v2n.nchwbin"//"model/det3.zqparams", "model/det3_bgr.nchwbin"
#elseif (!mtcnn.Init("../../model/det1-dw20-fast.zqparams", "../../model/det1-dw20-fast.nchwbin","../../model/det2-dw24-fast.zqparams", "../../model/det2-dw24-fast.nchwbin",//"model/det2.zqparams", "model/det2_bgr.nchwbin","../../model/det3-dw48-fast.zqparams", "../../model/det3-dw48-fast.nchwbin", thread_num, false,"model/det4-dw48-v2s.zqparams", "model/det4-dw48-v2s.nchwbin"//"../../model/det3.zqparams", "../../model/det3_bgr.nchwbin"
#endif)){cout << "failed to init!\n";return EXIT_FAILURE;}}mtcnn.SetPara(image0.cols, image0.rows, 80, 0.5, 0.6, 0.8, 0.4, 0.5, 0.5, 0.709, 3, 20, 4, special_handle_very_big_face);}else{
#if defined(_WIN32)if (!mtcnn.Init("model/det1.zqparams", "model/det1_bgr.nchwbin","model/det2.zqparams", "model/det2_bgr.nchwbin","model/det3.zqparams", "model/det3_bgr.nchwbin", thread_num))
#elseif (!mtcnn.Init("../../model/det1.zqparams", "../../model/det1_bgr.nchwbin","../../model/det2.zqparams", "../../model/det2_bgr.nchwbin","../../model/det3.zqparams", "../../model/det3_bgr.nchwbin", thread_num))
#endif{cout << "failed to init!\n";return EXIT_FAILURE;}mtcnn.SetPara(image0.cols, image0.rows, 20, 0.6, 0.7, 0.7, 0.4, 0.5, 0.5, 0.709, 4, 12, 2, special_handle_very_big_face);}mtcnn.TurnOffShowDebugInfo();//mtcnn.TurnOnShowDebugInfo();int iters = 100;double t1 = omp_get_wtime();for (int i = 0; i < iters; i++){if (i == iters / 2)mtcnn.TurnOnShowDebugInfo();elsemtcnn.TurnOffShowDebugInfo();if (landmark106 && use_pnet20){if (!mtcnn.Find106(image0.data, image0.cols, image0.rows, image0.step[0], thirdBbox106)){cout << "failed to find face!\n";//return EXIT_FAILURE;continue;}}else{if (!mtcnn.Find(image0.data, image0.cols, image0.rows, image0.step[0], thirdBbox)){cout << "failed to find face!\n";//return EXIT_FAILURE;continue;}}}double t2 = omp_get_wtime();printf("total %.3f s / %d = %.3f ms\n", t2 - t1, iters, 1000 * (t2 - t1) / iters);namedWindow("result");if (landmark106 && use_pnet20)Draw(image0, thirdBbox106);elseDraw(image0, thirdBbox);imwrite(result_name, image0);imshow("result", image0);waitKey(1);}return EXIT_SUCCESS;
}
(一) WINDOWS下对比
(测试机器为E5-1650V4 3.6GHz)
编译方式:
ZQCNN用.sln打开
libfacedetection用cmake-gui配置,勾选avx2和DEMO,不勾选int8和neon,配置之后用vs打开,注意在facedetection、facedetection_shared、fdt_demo三个项目的项目属性->C++->代码生成里开启AVX2和快速浮点。
(1)对比keliamoniz1.jpg
结果比较:
(2)对比4.jpg
结果比较:
(3)对比其他图片
结果比较:
(二)ARM-LINUX下对比
(测试机器为firefly rk3399)
编译方式:
ZQCNN: 先编译OpenBLAS, OpenCV3.4.2, 然后编译ZQCNN, 使用命令cmake .. -DSIMD_ARCH_TYPE=arm64 -DBLAS_TYPE=openblas_zq_gemm 具体参见ZQCNN项目的README
libfacedetection: 命令cmake .. -DENABLE_NEON=ON -DCMAKE_BUILD_TYPE=RELEASE
(1)对比keliamoniz1.jpg
结果比较:
(2)对比4.jpg
结果比较:
(3)对比其他图片
结果比较:
总结
根据以上比较结果可知,按照上述编译方式,在上述图像集中,ZQCNN-MTCNN在速度和精度上都优于libfacedetection。
不过要声明一点,该比较中使用的图像数量过少,感兴趣的读者可自行下载编译测试。
ZQCNN使用了mkl、openblas,这些基础加速库可能是其速度占优的原因。
libfacedetection追求无依赖库,在实际项目中,应用可以更广泛。
代码数据下载
作者已经把上述代码及测试图像开源了,在OpenCV中文网公众号对话界面回复“facepk”,即可收到下载地址。
ZQCNN快速人脸检测相关推荐
- 一种改进的快速人脸检测算法
人脸检测是计算机视觉及相关领域的关键技术,在智能人机交互.视频会议.安全监控等方面都有着广阔的应用前景.目前人脸检测方法主要有基于知识的方法和基于统计学习的方法[1].其中,基于知识的检测算法首先抽取 ...
- matlab rgb 到 ycgcr,基于混合肤色模型的快速人脸检测算法
摘 要: 提出了一种基于混合肤色模型" title="肤色模型">肤色模型" title="肤色模型">肤色模型" ...
- java人脸对比开源_重磅!最快人脸检测开源库对比:ZQCNN-MTCNN vs libfacedetection
前言 CVer 前段时间分享了一个很棒的开源人脸检测库:libfacedetection,详见:重磅!最快人脸检测库开源 2019年3月25日,Amusi 在github上发现 follow很久的左庆 ...
- 人脸检测识别文献代码
https://github.com/ChanChiChoi/awesome-Face_Recognition 人脸检测 PyramidBox: A Context-assisted Single S ...
- 人脸检测识别文献阅读总结
1 在人脸检测的时候需要结合人脸特征点对齐来综合考虑人脸检测问题,因为人脸特征点对齐有助于提高人脸检测性能 下面的文献都论证了这个思想: Joint cascade face detection an ...
- AI学习笔记(十三)CNN之人脸检测
AI学习笔记之CNN之人脸检测 人脸检测 人脸检测概念 人脸检测的难点 人脸检测的主要用途 mtcnn 主要步骤 构建图像金字塔 P-Net(Proposal Network) R-Net(Refin ...
- 快速多尺度人脸检测2--Multi-Scale Fully Convolutional Network for Face Detection in the Wild
Multi-Scale Fully Convolutional Network for Face Detection in the Wild CVPRW2017 上一篇文献的姊妹篇吧,如何能够快速的实 ...
- 快速多尺度人脸检测--Multi-Scale Fully Convolutional Network for Fast Face Detection
Multi-Scale Fully Convolutional Network for Fast Face Detection BMVC 2016 如何能够快速的实现多尺度人脸检测了? 本文的思路是 ...
- [Python图像处理] 二十八.OpenCV快速实现人脸检测及视频中的人脸
该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...
最新文章
- php微信公众号获取天气预报,【微信公众平台开发】封装获取天气预报功能
- Android开发入门教程--Android应用程序结构分析
- leetcode 46. 全排列 思考分析
- 飞鸽传书:HTML界面也有它欠缺的方面
- 关于设计秒杀系统的几个问题
- java 怎么控制暂停5秒钟_java – libGDX暂停运行几秒钟
- 庆祝喜提13337000编号,我悄悄把老板的Windows命令行设置成了这样
- Shell脚本实现SSH免密登录及批量配置管理
- make的时候会报错g++: Command not found
- WPF中的TreeView入门
- Spring Boot实战笔记(四)-- Spring常用配置(事件Application Event)
- 目前web渗透的思路
- mysql directx repair_[MySQL]快速解决is marked as crashed and should be repaired故障
- html5svg在线编辑器,五款超实用的开源SVG工具
- 精伦iDR210读卡器驱动安装教程
- JAVA 接口签名sign生成 工具类
- 知识共享许可 cc 协议
- 云服务器ECS的简介
- 懂得选择,学会放弃!
- Splunk机器学习应用(Machine Learning Toolkit)
热门文章
- 解析Shell编程中的-----“去重“
- php168齐博,php168整站系统(齐博CMS)下载
- 服务器一拷贝文件就死机,u盘拷贝文件时导致电脑死机怎么办【解决方法】
- nginx 正则匹配优化(一)
- html 滚动条_数十种自定义多彩多样滚动条样式
- 年会抽奖程序准备好了吗?没有的话,直接来取!
- 2022年最新限量红包封面,炸裂的不要不要的!速度领取!
- 皮一皮:考试了,全国统一舔狗学校招生考试!
- 战争升级!Elasticsearch 从客户端向 AWS 开了一炮!
- 公司用了 6 年的分布式锁,很是牛逼啊!