本教程基于虹軟免費(fèi)的人臉認(rèn)知引擎界酒,介紹了人臉檢測(cè)和人臉識(shí)別如何應(yīng)用于實(shí)踐。
此為小白教程岳掐,高手可略過(guò)。
第一步:
先從虹軟官網(wǎng)下載Windows版SDK执解。
附鏈接:http://www.arcsoft.com.cn/ai/arcface.html
簡(jiǎn)單注冊(cè)衰腌,并下載對(duì)應(yīng)版本后觅赊,會(huì)提供如下APP Id和SDK key.(開(kāi)發(fā)的時(shí)候會(huì)用到)
第二步:
下載后解壓饶囚,我們發(fā)現(xiàn)壓縮包內(nèi)容如下:
有三個(gè)包萝风,分別是Detection(人臉檢測(cè))紫岩,Recognition(人臉識(shí)別)泉蝌,Tracking(人臉跟蹤)
簡(jiǎn)單介紹下這三個(gè)包的區(qū)別——
Detection(人臉檢測(cè))——用于圖片的人臉檢測(cè)梨与,獲取的人臉坐標(biāo)可用于人臉識(shí)別
Recognition(人臉識(shí)別)——用于比對(duì)目標(biāo)圖像和提前注冊(cè)好的圖片間的相似度
Tracking(人臉跟蹤)——用于視頻類粥鞋,如攝像頭場(chǎng)景時(shí)人臉檢測(cè)效率高于Detection
第三部:
創(chuàng)建Visual Studio的C++工程(我用的是vs2012):
這里我選擇了控制臺(tái)程序缘挽。
由于習(xí)慣用Multi-Byte的方式開(kāi)發(fā),可以在工程右鍵屬性中按如下方式配置Character Set.
第三步:
在工程目錄下創(chuàng)建inc文件夾呻粹,將三個(gè)壓縮包中的頭文件壕曼,放在該目錄中,
另外創(chuàng)建lib文件夾等浊,將壓縮包中的lib庫(kù)放入該目錄中腮郊。
Dll放入生成可執(zhí)行文件的路徑下(因?yàn)槲椰F(xiàn)在用的是Debug版本,因此放在了Debug下面)
第四步:
在工程里包含需要的頭文件和lib庫(kù)筹燕。
如下我這里只用了Detection和Recognition轧飞。
#include "stdafx.h"
#include "inc/amcomdef.h"
#include "inc/ammem.h"
#include "inc/asvloffscreen.h"
#include "inc\merror.h"
#include "inc\arcsoft_fsdk_face_detection.h"
#include "inc\arcsoft_fsdk_face_recognition.h"
#pragma comment(lib,"libarcsoft_fsdk_face_detection.lib")
#pragma comment(lib,"libarcsoft_fsdk_face_recognition.lib")
#define SafeFree(p){if((p)) free(p);(p)=NULL;}
第五步:
實(shí)現(xiàn)照片注冊(cè)。
需要用到人臉檢測(cè)和人臉識(shí)別过咬。
注意:虹軟用到的圖像數(shù)據(jù)格式并非Jpeg等格式大渤,而是解碼后的格式,如RGB格式掸绞,官方給的是(ASVL_PAF_RGB24_B8G8R8)
所謂注冊(cè)泵三,即通過(guò)人臉識(shí)別算法將人臉特征信息提取出來(lái),并保存到數(shù)據(jù)庫(kù)衔掸,用于后續(xù)的人臉特征比對(duì)烫幕。
附注冊(cè)代碼如下:
int RegisterFace(ASVLOFFSCREEN *imginfo,TCHAR * regName)
{
//FD
MByte* pfd_Mem = (MByte*)malloc(FD_MEMSIZE);
MHandle hfd_Engine = NULL;
MRESULT res = AFD_FSDK_InitialFaceEngine(APP_ID,FD_SDK_KEY, pfd_Mem, FD_MEMSIZE, &hfd_Engine,
AFD_FSDK_OPF_0_HIGHER_EXT,16,10);
if(res != MOK)
{
SafeFree(pfd_Mem);
return res;
}
LPAFD_FSDK_FACERES faces;
res = AFD_FSDK_StillImageFaceDetection(hfd_Engine, imginfo, &faces);
if(res != MOK)
printf("FD Detect Failed\r\n");
if (faces->nFace == 0)
{
printf("No faces detected\r\n");
SafeFree(pfd_Mem);
return -1;
}
//FR
MByte* pfr_Mem = (MByte*)malloc(FR_MEMSIZE);
MHandle hfr_Engine = NULL;
res = AFR_FSDK_InitialEngine(APP_ID,
FR_SDK_KEY, pfr_Mem, FR_MEMSIZE, &hfr_Engine);
if(res != MOK)
{
SafeFree(pfd_Mem);
SafeFree(pfr_Mem);
return res;
}
AFR_FSDK_FACEMODEL faceModel = { 0 };
AFR_FSDK_FACEINPUT faceInput = { 0 };
faceInput.lOrient = (AFR_FSDK_OrientCode)*faces->lfaceOrient;
//memcpy(&faceInput.rcFace , &faces->rcFace[0],sizeof(MRECT));
int leffff = faces->rcFace[0].left;
faceInput.rcFace.left = faces->rcFace[0].left;
faceInput.rcFace.bottom = faces->rcFace[0].bottom;
faceInput.rcFace.right = faces->rcFace[0].right;
faceInput.rcFace.top = faces->rcFace[0].top;
res = AFR_FSDK_ExtractFRFeature(hfr_Engine, imginfo, &faceInput,&faceModel);
if (res == MOK && faceModel.lFeatureSize > 0 && faceModel.pbFeature)
{
SaveFeature(&faceModel,regName);//保存特征
printf("注冊(cè)成功!");
}
else
{
printf("注冊(cè)(提取特征)失敗");
return MERR_BASIC_BASE;
}
res = AFD_FSDK_UninitialFaceEngine(hfd_Engine);
res = AFR_FSDK_UninitialEngine(hfr_Engine);
SafeFree(pfd_Mem);
SafeFree(pfr_Mem);
return MOK;
}
Void Regist()
{
ASVLOFFSCREEN imageInfo = {0};
char * filepath = argv[2];
IplImage * img = cvLoadImage(filepath,1);
imageInfo.i32Width = img->width;
imageInfo.i32Height = img->height;
imageInfo.u32PixelArrayFormat = ASVL_PAF_RGB24_B8G8R8;
imageInfo.pi32Pitch[0] = imageInfo.i32Width*3;
imageInfo.ppu8Plane[0] = (MUInt8*)malloc(imageInfo.i32Height*imageInfo.pi32Pitch[0]);
memcpy(imageInfo.ppu8Plane[0],img->imageData,imageInfo.i32Height*imageInfo.pi32Pitch[0]);
RegisterFace(&imageInfo,"Leo");
}
第六步:
識(shí)別比對(duì)人臉。
所謂識(shí)別敞映,即通過(guò)人臉識(shí)別算法將人臉特征信息提取出來(lái)较曼,與之前的保存的特征進(jìn)行比較,獲取相似度值驱显。
以下為單人臉識(shí)別比對(duì)示例诗芜,將已經(jīng)保存的特征值進(jìn)行逐一比對(duì),即可找到注冊(cè)人群中最相似的人埃疫,即1:N場(chǎng)景伏恐。如果是1:1場(chǎng)景的話,只需把當(dāng)前的需要識(shí)別的圖像和指定的特征值進(jìn)行比較即可栓霜。
//faceModels2 為已保存(注冊(cè))的人臉特征
int RecoginizeFace(ASVLOFFSCREEN *imginfo, char **regName)
{
//FD
MByte* pfd_Mem = (MByte*)malloc(FD_MEMSIZE);
MHandle hfd_Engine = NULL;
MRESULT res = AFD_FSDK_InitialFaceEngine(APP_ID,FD_SDK_KEY, pfd_Mem, FD_MEMSIZE, &hfd_Engine,
AFD_FSDK_OPF_0_HIGHER_EXT,16,10);
if(res != MOK)
{
SafeFree(pfd_Mem);
return res;
}
LPAFD_FSDK_FACERES faces;
res = AFD_FSDK_StillImageFaceDetection(hfd_Engine, imginfo, &faces);
if(res != MOK)
printf("FD Detect Failed\r\n");
res = AFD_FSDK_UninitialFaceEngine(hfd_Engine);
if (faces->nFace == 0)
{
printf("No faces detected\r\n");
SafeFree(pfd_Mem);
return -1;
}
//FR
MByte* pfr_Mem = (MByte*)malloc(FR_MEMSIZE);
MHandle hfr_Engine = NULL;
res = AFR_FSDK_InitialEngine(APP_ID,
FR_SDK_KEY, pfr_Mem, FR_MEMSIZE, &hfr_Engine);
if(res != MOK)
SafeFree(pfd_Mem);
SafeFree(pfr_Mem);
return res;
AFR_FSDK_FACEMODEL faceModel = { 0 };
AFR_FSDK_FACEINPUT faceInput = { 0 };
faceInput.lOrient = (AFR_FSDK_OrientCode)faces->lfaceOrient;
res = AFR_FSDK_ExtractFRFeature(hfr_Engine, imginfo, &faceInput,&faceModel);
if (res == MOK && faceModel.lFeatureSize > 0 && faceModel.pbFeature)
{
MFloat fSimilScore = 0.0f;
//在這里和原來(lái)保存的Feature進(jìn)行對(duì)比
//loadFeatures();
//MRESULT ret = AFR_FSDK_FacePairMatching(hfr_Engine, &faceModel, &faceModels2, &fSimilScore);
//fsimilScore 該值即獲得
}
else
{
printf("注冊(cè)(提取特征)失敗");
return MERR_BASIC_BASE;
}
res = AFR_FSDK_UninitialEngine(hfr_Engine);
SafeFree(pfd_Mem);
SafeFree(pfr_Mem);
return MOK;
return 0;
}
測(cè)試了下翠桦,常規(guī)情況下0.63左右的相似度作為閾值,基本可以區(qū)分是否查找比對(duì)成功胳蛮。即高于0.63應(yīng)該是查找匹配成功销凑。實(shí)際的相似度可能還需和使用場(chǎng)景掛鉤,在0.5-0.7的范圍內(nèi)選擇適合所在場(chǎng)景的值作為分界線仅炊。