本教程基于虹軟免費的人臉認知引擎,介紹了人臉檢測和人臉識別如何應用于實踐。
此為小白教程,高手可略過。
第一步:
先從虹軟官網下載Windows版SDK。
附鏈接:http://www.arcsoft.com.cn/ai/arcface.html
簡單注冊,并下載對應版本后,會提供如下APP Id和SDK key.(開發的時候會用到)
第二步:
下載后解壓,我們發現壓縮包內容如下:
有三個包,分別是Detection(人臉檢測),Recognition(人臉識別),Tracking(人臉跟蹤)
簡單介紹下這三個包的區別——
Detection(人臉檢測)——用于圖片的人臉檢測,獲取的人臉坐標可用于人臉識別
Recognition(人臉識別)——用于比對目標圖像和提前注冊好的圖片間的相似度
Tracking(人臉跟蹤)——用于視頻類,如攝像頭場景時人臉檢測效率高于Detection
第三部:
創建Visual Studio的C++工程(我用的是vs2012):
這里我選擇了控制臺程序。
由于習慣用Multi-Byte的方式開發,可以在工程右鍵屬性中按如下方式配置Character Set.
第三步:
在工程目錄下創建inc文件夾,將三個壓縮包中的頭文件,放在該目錄中,
另外創建lib文件夾,將壓縮包中的lib庫放入該目錄中。
Dll放入生成可執行文件的路徑下(因為我現在用的是Debug版本,因此放在了Debug下面)
第四步:
在工程里包含需要的頭文件和lib庫。
如下我這里只用了Detection和Recognition。
第五步:
實現照片注冊。
需要用到人臉檢測和人臉識別。
注意:虹軟用到的圖像數據格式并非Jpeg等格式,而是解碼后的格式,如RGB格式,官方給的是(ASVL_PAF_RGB24_B8G8R8)
所謂注冊,即通過人臉識別算法將人臉特征信息提取出來,并保存到數據庫,用于后續的人臉特征比對。
附注冊代碼如下:
intRegisterFace(ASVLOFFSCREEN*imginfo,TCHAR*regName)
{
//FD
MByte* pfd_Mem = (MByte*)malloc(FD_MEMSIZE);
MHandlehfd_Engine =NULL;
MRESULTres = 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);
returnres;
}
LPAFD_FSDK_FACERESfaces;
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);
MHandlehfr_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);
returnres;
}
AFR_FSDK_FACEMODELfaceModel = { 0 };
AFR_FSDK_FACEINPUTfaceInput = { 0 };
faceInput.lOrient = (AFR_FSDK_OrientCode)*faces->lfaceOrient;
//memcpy(&faceInput.rcFace ,
&faces->rcFace[0],sizeof(MRECT));
intleffff = 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("注冊成功!");
}
else
{
printf("注冊(提取特征)失敗");
returnMERR_BASIC_BASE;
}
res =AFD_FSDK_UninitialFaceEngine(hfd_Engine);
res = AFR_FSDK_UninitialEngine(hfr_Engine);
SafeFree(pfd_Mem);
SafeFree(pfr_Mem);
returnMOK;
}
VoidRegist()
{
ASVLOFFSCREENimageInfo = {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");
}
第六步:
識別比對人臉。
所謂識別,即通過人臉識別算法將人臉特征信息提取出來,與之前的保存的特征進行比較,獲取相似度值。
以下為單人臉識別比對示例,將已經保存的特征值進行逐一比對,即可找到注冊人群中最相似的人,即1:N場景。如果是1:1場景的話,只需把當前的需要識別的圖像和指定的特征值進行比較即可。
//faceModels2為已保存(注冊)的人臉特征
intRecoginizeFace(ASVLOFFSCREEN*imginfo,char**regName)
{
//FD
MByte* pfd_Mem = (MByte*)malloc(FD_MEMSIZE);
MHandlehfd_Engine =NULL;
MRESULTres = 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);
returnres;
}
LPAFD_FSDK_FACERESfaces;
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);
MHandlehfr_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);
returnres;
AFR_FSDK_FACEMODELfaceModel = { 0 };
AFR_FSDK_FACEINPUTfaceInput = { 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)
{
MFloatfSimilScore = 0.0f;
//在這里和原來保存的Feature進行對比
//loadFeatures();
//MRESULT ret =
AFR_FSDK_FacePairMatching(hfr_Engine, &faceModel, &faceModels2,
&fSimilScore);
//fsimilScore該值即獲得
}
else
{
printf("注冊(提取特征)失敗");
returnMERR_BASIC_BASE;
}
res =AFR_FSDK_UninitialEngine(hfr_Engine);
SafeFree(pfd_Mem);
SafeFree(pfr_Mem);
returnMOK;
return0;
}
測試了下,常規情況下0.63左右的相似度作為閾值,基本可以區分是否查找比對成功。即高于0.63應該是查找匹配成功。實際的相似度可能還需和使用場景掛鉤,在0.5-0.7的范圍內選擇適合所在場景的值作為分界線。