虹软人脸检测算法评测

现在开源的人脸检测、识别算法也越来越多,同时有些算法厂商也开始将他们的产品免费提供给用户。前些天,下了虹软的人脸检测算法,与开源的Dlib人脸检测算法进行了一个对比,过程和结果如下:

  • 虹软人脸检测算法

(1)从虹软官网上下载评测版本,我下来的zip包是:ARCSOFT_FSDK_FACE_DETECTION_1.1.0.197_LINUX64_05212018.zip

(2)编译测试代码,这里不得不吐槽一下,虹软提供的测试代码真是相当简单,没有编译说明文档不说,连测试输入也在代码中写死成YUV格式的某个固定文件。所以我对测试代码进行了修改,输入改成任意的JPG格式的文件,输出是检测到人脸的位置坐标信息。
#cat arcsoft_afd_samplecode.cpp

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <string.h>

#include "arcsoft_fsdk_face_detection.h"
#include "merror.h"

#define APPID     "86aGodkxpbeC3CM11sV85H6ByLFjAmsdU3qBiWnwXoJX"
#define SDKKEY    "3wFJQRRSBSjc6Q9F1uX97pTFeXXUd6DSgu6XWKbcXxVF"


#define INPUT_IMAGE_FORMAT  ASVL_PAF_RGB24_B8G8R8

#define WORKBUF_SIZE        (40*1024*1024)
#define MAX_FACE_NUM        (50)

using namespace std;
using namespace cv;

int main(int argc, char* argv[]) {

    Mat img;

    img = imread(argv[1]);


    MByte *pWorkMem = (MByte *)malloc(WORKBUF_SIZE);
    if(pWorkMem == nullptr){
        fprintf(stderr, "fail to malloc workbuf\r\n");
        exit(0);
    }

    MHandle hEngine = nullptr;

    int ret = AFD_FSDK_InitialFaceEngine((MPChar)APPID, (MPChar)SDKKEY, pWorkMem, WORKBUF_SIZE, 
                                         &hEngine, AFD_FSDK_OPF_0_HIGHER_EXT, 16, MAX_FACE_NUM);
    if (ret != 0) {
        fprintf(stderr, "fail to AFD_FSDK_InitialFaceEngine(): 0x%x\r\n", ret);
        free(pWorkMem);
        exit(0);
    }

    const AFD_FSDK_Version*pVersionInfo = AFD_FSDK_GetVersion(hEngine);
    printf("%d %d %d %d\r\n", pVersionInfo->lCodebase, pVersionInfo->lMajor,
                                 pVersionInfo->lMinor, pVersionInfo->lBuild);
    printf("%s\r\n", pVersionInfo->Version);
    printf("%s\r\n", pVersionInfo->BuildDate);
    printf("%s\r\n", pVersionInfo->CopyRight);

    ASVLOFFSCREEN inputImg = { 0 };
    inputImg.u32PixelArrayFormat = INPUT_IMAGE_FORMAT;
#if 0
    inputImg.i32Width = INPUT_IMAGE_WIDTH;
    inputImg.i32Height = INPUT_IMAGE_HEIGHT;
#else
    inputImg.i32Width = img.size().width;
    inputImg.i32Height = img.size().height;
#endif

#if 0
    inputImg.ppu8Plane[0] = nullptr;
    fu_ReadFile(INPUT_IMAGE_PATH, (uint8_t**)&inputImg.ppu8Plane[0], nullptr);
     if (!inputImg.ppu8Plane[0]) {
        fprintf(stderr, "fail to fu_ReadFile(%s): %s\r\n", INPUT_IMAGE_PATH, strerror(errno));
                AFD_FSDK_UninitialFaceEngine(hEngine);
        free(pWorkMem);
        exit(0);
    }
#else
     inputImg.ppu8Plane[0] = (MUInt8*)malloc(inputImg.i32Width * inputImg.i32Height * 3);
     memcpy(inputImg.ppu8Plane[0], img.data, inputImg.i32Width * inputImg.i32Height * 3);
#endif

    if (ASVL_PAF_I420 == inputImg.u32PixelArrayFormat) {
        inputImg.pi32Pitch[0] = inputImg.i32Width;
        inputImg.pi32Pitch[1] = inputImg.i32Width/2;
        inputImg.pi32Pitch[2] = inputImg.i32Width/2;
        inputImg.ppu8Plane[1] = inputImg.ppu8Plane[0] + inputImg.pi32Pitch[0] * inputImg.i32Height;
        inputImg.ppu8Plane[2] = inputImg.ppu8Plane[1] + inputImg.pi32Pitch[1] * inputImg.i32Height/2;
    } else if (ASVL_PAF_NV12 == inputImg.u32PixelArrayFormat) {
        inputImg.pi32Pitch[0] = inputImg.i32Width;
        inputImg.pi32Pitch[1] = inputImg.i32Width;
        inputImg.ppu8Plane[1] = inputImg.ppu8Plane[0] + (inputImg.pi32Pitch[0] * inputImg.i32Height);
    } else if (ASVL_PAF_NV21 == inputImg.u32PixelArrayFormat) {
        inputImg.pi32Pitch[0] = inputImg.i32Width;
        inputImg.pi32Pitch[1] = inputImg.i32Width;
        inputImg.ppu8Plane[1] = inputImg.ppu8Plane[0] + (inputImg.pi32Pitch[0] * inputImg.i32Height);
    } else if (ASVL_PAF_YUYV == inputImg.u32PixelArrayFormat) {
        inputImg.pi32Pitch[0] = inputImg.i32Width*2;
    } else if (ASVL_PAF_I422H == inputImg.u32PixelArrayFormat) {
        inputImg.pi32Pitch[0] = inputImg.i32Width;
        inputImg.pi32Pitch[1] = inputImg.i32Width / 2;
        inputImg.pi32Pitch[2] = inputImg.i32Width / 2;
        inputImg.ppu8Plane[1] = inputImg.ppu8Plane[0] + inputImg.pi32Pitch[0] * inputImg.i32Height;
        inputImg.ppu8Plane[2] = inputImg.ppu8Plane[1] + inputImg.pi32Pitch[1] * inputImg.i32Height;
    } else if (ASVL_PAF_LPI422H == inputImg.u32PixelArrayFormat) {
        inputImg.pi32Pitch[0] = inputImg.i32Width;
        inputImg.pi32Pitch[1] = inputImg.i32Width;
        inputImg.ppu8Plane[1] = inputImg.ppu8Plane[0] + (inputImg.pi32Pitch[0] * inputImg.i32Height);
    } else if (ASVL_PAF_RGB24_B8G8R8 == inputImg.u32PixelArrayFormat) {
        inputImg.pi32Pitch[0] = inputImg.i32Width*3;
    } else {
        fprintf(stderr, "unsupported Image format: 0x%x\r\n",inputImg.u32PixelArrayFormat);
        free(inputImg.ppu8Plane[0]);
        AFD_FSDK_UninitialFaceEngine(hEngine);
        free(pWorkMem);
        exit(0);
    }
    LPAFD_FSDK_FACERES faceResult;
    ret = AFD_FSDK_StillImageFaceDetection(hEngine, &inputImg, &faceResult);
    if (ret != 0) {
        fprintf(stderr, "fail to AFD_FSDK_StillImageFaceDetection(): 0x%x\r\n", ret);
        free(inputImg.ppu8Plane[0]);
                AFD_FSDK_UninitialFaceEngine(hEngine);
        free(pWorkMem);
        exit(0);
    }

    printf("faceResult->nFace = %d\n", faceResult->nFace);
    for (int i = 0; i < faceResult->nFace; i++) {
        printf("face %d:(%d,%d,%d,%d)\n", i, 
               faceResult->rcFace[i].left, faceResult->rcFace[i].top,
               faceResult->rcFace[i].right, faceResult->rcFace[i].bottom);

    }

    
    free(inputImg.ppu8Plane[0]);
        AFD_FSDK_UninitialFaceEngine(hEngine);
    free(pWorkMem);

    return 0;
}

修改后的测试代码中使用了opencv库,编译命令如下:
#g++ -std=c++11 -I../inc/ -L ../lib/linux_x64 -o arcsoft_fd ./arcsoft_afd_samplecode.cpp -larcsoft_fsdk_face_detection -lopencv_core -lopencv_imgproc -lopencv_highgui

  • DLib开源算法

(1) 使用了开源的face_recognition python库,这个库底层就是基于Dlib的,写了一个测试程序,代码如下:

# -*- coding: utf-8 -*-
# 

# 检测人脸
import face_recognition
import cv2
import sys

# 读取图片并识别人脸
img = face_recognition.load_image_file(sys.argv[1])
face_locations = face_recognition.face_locations(img)
print face_locations

# 调用opencv函数显示图片
img = cv2.imread(sys.argv[1])
cv2.namedWindow("原图")
cv2.imshow("原图", img)
#size = cv2.GetSize(img)
#print size

sp = img.shape
print sp

# 遍历每个人脸,并标注
faceNum = len(face_locations)
for i in range(0, faceNum):
    top =  face_locations[i][0]
    right =  face_locations[i][1]
    bottom = face_locations[i][2]
    left = face_locations[i][3]

    start = (left, top)
    end = (right, bottom)

    color = (55,255,155)
    thickness = 1
    cv2.rectangle(img, start, end, color, thickness)



# 显示识别结果

cv2.namedWindow("识别")

cv2.imshow("识别", img)

cv2.waitKey(0)
cv2.destroyAllWindows()
  • 对比测试

使用同一张照片,原图如下:


image.png

(1) Dlib算法检测结果:


image.png

(2) 虹软算法检测结果:

$ LD_LIBRARY_PATH=../lib/linux_x64/ ./test ../test3.jpg
0 1 1 197
ArcSoft_FreeSDK_Face_Detection_1.1.0.197
May 21 2018
Copyright 2017 ArcSoft, Inc. All rights reserved.
faceResult->nFace = 1
face 0:(63,142,113,191)

 import cv2
 img = cv2.imread("./test3.jpg")
 start = (63,142)
 end = (113,191)
 color = (55,255,155)
 thickness = 1
 cv2.rectangle(img, start, end, color, thickness)
 cv2.imshow("ArcSoft", img)
cv2.waitKey(0)
image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容