现在开源的人脸检测、识别算法也越来越多,同时有些算法厂商也开始将他们的产品免费提供给用户。前些天,下了虹软的人脸检测算法,与开源的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()
-
对比测试
使用同一张照片,原图如下:
(1) Dlib算法检测结果:
(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)