开源人脸检测库 libfacedetection,有如下特点:
- 深度模型仅有85K个参数。
- 采用AVX512/AVX2/NEON指令提速。
- 代码简短和简洁,只有一千多行代码。
- 代码不依赖任何其他第三方库,只要平台能编译C++则可使用。
- 项目License采用3-Clause BSD License,可以商业应用。
之前介绍过于老师的 libfacedetection 人脸检测开源库,并且基于 Ubuntu 和 Android 两个平台进行实践,效果还是很不错的。通过于老师的公众号得知最近 libfacedetection 有版本更新。作为不会算法,不会训练,只会使用的小白,实践出真知。
二、环境准备-
Windows 11
-
CLion 2021.2.2
-
OpenCV 4.5.3
-
CMake 3.20.2
-
MinGW w64.6.0
-
源码(https://github.com/ShiqiYu/libfacedetection)
3.1 创建工程实现效果:基于 libfacedetection 源码实现 图片人脸检测
File -> New Project -> C++ Executable
3.2 导入 libfacedetection 源码新建文件夹 libfacedetecion,并复制 src 目录下的 4 个文件即可。
为了避免编译错误和提高运行效率,做如下几点调整:
| 文件名 | 调整内容 |
|---|---|
| facedetectcnn.h | 注释掉 #include "facedetection_export.h" |
| facedetectcnn.h | 解除注释 #define _ENABLE_AVX2 //Please enable it if X64 CPU |
| facedetectcnn.h | 删除 FACEDETECTION_EXPORT |
#define _ENABLE_AVX2 或者 #define _ENABLE_AVX512 使能后,需要添加 add_compile_options(-march=native)
cmake_minimum_required(VERSION 3.20)
project(libFDSample)
set(CMAKE_CXX_STANDARD 14)
# #define _ENABLE_AVX2 打开后添加
add_compile_options(-march=native)
# openMP 配置
FIND_PACKAGE(OpenMP REQUIRED)
if (OPENMP_FOUND)
message("OPENMP FOUND")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif ()
aux_source_directory(libfacedetection lf)
add_executable(facedetect main.cpp ${lf})
set(OpenCV_DIR D:/05_Project/16_OpenCV/opencv-4.5.3/mbuild/install/x64/mingw/lib)
FIND_PACKAGE(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
link_directories(${OpenCV_LIBS})
TARGET_link_LIBRARIES(facedetect ${OpenCV_LIBS})
3.4 修改 main.cpp
对源码 example 目录下的 detect-image.cpp 示例代码,稍加调整:读取参数图像改为读取固定图像。
#include3.5 编译 Release 版本#include #include "libfacedetection/facedetectcnn.h" //define the buffer size. Do not change the size! #define DETECT_BUFFER_SIZE 0x20000 using namespace cv; int main(int argc, char* argv[]) { //load an image and convert it to gray (single-channel) Mat image = imread("../image/basketball.jpg"); if(image.empty()) { fprintf(stderr, "Can not load the image file %s.n", argv[1]); return -1; } int * pResults = NULL; //pBuffer is used in the detection functions. //If you call functions in multiple threads, please create one buffer for each thread! unsigned char * pBuffer = (unsigned char *)malloc(DETECT_BUFFER_SIZE); if(!pBuffer) { fprintf(stderr, "Can not alloc buffer.n"); return -1; } /// // CNN face detection // Best detection rate // //!!! The input image must be a BGR one (three-channel) instead of RGB //!!! DO NOT RELEASE pResults !!! TickMeter cvtm; cvtm.start(); pResults = facedetect_cnn(pBuffer, (unsigned char*)(image.ptr(0)), image.cols, image.rows, (int)image.step); cvtm.stop(); printf("time = %gmsn", cvtm.getTimeMilli()); printf("%d faces detected.n", (pResults ? *pResults : 0)); Mat result_image = image.clone(); //print the detection results for(int i = 0; i < (pResults ? *pResults : 0); i++) { short * p = ((short*)(pResults+1))+142*i; int confidence = p[0]; int x = p[1]; int y = p[2]; int w = p[3]; int h = p[4]; //show the score of the face. Its range is [0-100] char sScore[256]; snprintf(sScore, 256, "%d", confidence); cv::putText(result_image, sScore, cv::Point(x, y-3), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 1); //draw face rectangle rectangle(result_image, Rect(x, y, w, h), Scalar(0, 255, 0), 2); //draw five face landmarks in different colors cv::circle(result_image, cv::Point(p[5], p[5 + 1]), 1, cv::Scalar(255, 0, 0), 2); cv::circle(result_image, cv::Point(p[5 + 2], p[5 + 3]), 1, cv::Scalar(0, 0, 255), 2); cv::circle(result_image, cv::Point(p[5 + 4], p[5 + 5]), 1, cv::Scalar(0, 255, 0), 2); cv::circle(result_image, cv::Point(p[5 + 6], p[5 + 7]), 1, cv::Scalar(255, 0, 255), 2); cv::circle(result_image, cv::Point(p[5 + 8], p[5 + 9]), 1, cv::Scalar(0, 255, 255), 2); //print the result printf("face %d: confidence=%d, [%d, %d, %d, %d] (%d,%d) (%d,%d) (%d,%d) (%d,%d) (%d,%d)n", i, confidence, x, y, w, h, p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13],p[14]); } imshow("result", result_image); waitKey(); //release the buffer free(pBuffer); return 0; }
两种方式指定编译类型
- File -> Settings -> Build, Execution, Deployment -> CMake
- CMakeLists.txt 中指定CMAKE_BUILD_TYPE
set(CMAKE_BUILD_TYPE Release)3.6 运行



