实现嵌入式设备中的人脸检测

原文地址

原文链接

前言

在前文交叉编译armv7运行环境以及嵌入式opencv的编译示例,我们已经构建了对应运行环境的交叉编译链,以及编译了opencv作为用例。现在我们需要简单实现一个人脸检测程序,本着拒绝重复造轮子的思想我们使用开源库libfacedetection实现

实现

编译

和前文相同,我们这里的构建环境是CentOS Stream release 8 x86_64 GNU/Linux以及Ubuntu 18.04.6 LTS x86_64 GNU/Linux,运行环境为armv7l GNU/Linux

首先拉取libfacedetection源码

mkdir /usr/local/facedetect && cd /usr/local/facedetect && git clone https://github.com/ShiqiYu/libfacedetection.git

然后根据写下交叉编译工具链的引用

cd libfacedetection && vim arm-gnueabi.toolchain.cmake

这里给出armv7l GNU/Linux运行环境的参考

set(GCC_COMPILER_VERSION "" CACHE STRING "GCC Compiler version")
set(GNU_MACHINE "arm-linux-gnueabi" CACHE STRING "GNU compiler triple")

#指定工具链
set(CMAKE_C_COMPILER /usr/local/arm/arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER /usr/local/arm/arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-g++)

#生成静态库
set(BUILD_SHARED_LIBS OFF)
#构建详细输出
set(CMAKE_VERBOSE_MAKEFILE ON)
#生成Release版本
set(CMAKE_BUILD_TYPE Release)

#libdetect选项
option(DEMO "" OFF)
option(ENABLE_AVX2 "" OFF)
option(ENABLE_NEON "" ON)
option(USE_OPENMP "" ON)

然后生成Makefile

mkdir build && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=../arm-gnueabi.toolchain.cmake -DCMAKE_INSTALL_PREFIX=/usr/local/facedetect/install   ..

最后构建安装,分别生成库文件和头文件到/usr/local/facedetect/install/lib/usr/local/facedetect/install/include

make && make install 

测试

mkdir /usr/local/facedetect/sample && cd /usr/local/facedetect/sample && vim main.cpp

稍微改动下源码提供的测试用例

#include <iostream>
#include <opencv2/opencv.hpp>
#include <facedetection/facedetectcnn.h>

#define DETECT_BUFFER_SIZE 0x9000

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
    //param check
    if(argc != 2)
    {
        cout << "need img" << endl;
        return -1;
    }
    //load file
    Mat image = imread(argv[1]); 
    if(image.empty())
    {
        cout << "load img fail" << endl;
        return -1;

    }
    int * pResults = NULL; 
    unsigned char * pBuffer = (unsigned char *)malloc(DETECT_BUFFER_SIZE);
    if(!pBuffer)
    {
        cout << "no buffer" << endl;
        return -1;
    }

    //resize
    cv::resize(image, image, cv::Size(200, 200));

        
    TickMeter cvtm;
    cvtm.start();

    pResults = facedetect_cnn(pBuffer, (unsigned char*)(image.ptr(0)), image.cols, image.rows, (int)image.step);
    
    cvtm.stop();    
    cout << "detect time : " <<  cvtm.getTimeMilli() << endl;
    
    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)) + 16*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]);

        }
        cv::imwrite("/test/detect.jpg", result_image);
        //imshow("result", result_image);
        //waitKey();

    //release the buffer
    free(pBuffer);
        return 0;
}

然后编译arm-none-linux-gnueabihf-g++ -O3 main.cpp -o testface -static -std=c++11 -I/usr/local/facedetect/install/include -L/usr/local/facedetect/install/lib -lfacedetection -fopenmp $(pkg-config --cflags --libs --static opencv4)

最后将应用程序到传入运行机器,运行

获取结果

armv7l单线程跑200*200图片120毫秒左右,也算是差强人意吧,但是如果希望速度更快,可以参考benchmark,启用OpenMP来达到更好的性能

原文地址

原文链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值