libfacedetection 让人脸检测如此简单

一、前言

开源人脸检测库 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)

三、工程实践

实现效果:基于 libfacedetection 源码实现 图片人脸检测

3.1 创建工程

File -> New Project -> C++ Executable

New Project

3.2 导入 libfacedetection 源码

新建文件夹 libfacedetecion,并复制 src 目录下的 4 个文件即可。

libfacedetection

为了避免编译错误和提高运行效率,做如下几点调整:

文件名调整内容
facedetectcnn.h注释掉 #include "facedetection_export.h"
facedetectcnn.h解除注释 #define _ENABLE_AVX2 //Please enable it if X64 CPU
facedetectcnn.h删除 FACEDETECTION_EXPORT

3.3 修改 CMakeLists.txt

#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 示例代码,稍加调整:读取参数图像改为读取固定图像。

#include <stdio.h>
#include <opencv2/opencv.hpp>
#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 = %gms\n", 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;
}

3.5 编译 Release 版本

两种方式指定编译类型

  • File -> Settings -> Build, Execution, Deployment -> CMake

Build Type

  • CMakeLists.txt 中指定CMAKE_BUILD_TYPE
set(CMAKE_BUILD_TYPE Release)

3.6 运行

运行结果

检测数据

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AndroidKt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值