#include "face.h"
|
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <string.h>
|
|
#include "THFaceImage_i.h"
|
#include "THFeature_i.h"
|
#include "THFaceProperty_i.h"
|
#include "THFaceTracking_i.h"
|
|
#include "csdk_struct.h"
|
|
namespace csdk_wrap{
|
sdkface::sdkface()
|
:fpos_(NULL)
|
,featLen_(0)
|
,feat_(NULL)
|
,finfo_(NULL)
|
{}
|
|
sdkface::~sdkface(){
|
for(auto &i : dtors_){
|
i();
|
}
|
|
if (fpos_) free(fpos_);
|
if (feat_) free(feat_);
|
if (finfo_) free(finfo_);
|
}
|
|
int sdkface::init_face_detector(const int tm, const int gi, const int minFaces, const int rollAngle){
|
int ret = 0;
|
if (gi < 0) {
|
THFI_Param *param = new THFI_Param[tm];
|
ret = THFI_Create(tm, param);
|
delete[] param;
|
} else {
|
THFI_Param_Ex *param = new THFI_Param_Ex[tm];
|
THFI_Param detParam;
|
detParam.nMinFaceSize = minFaces;
|
detParam.nRollAngle = rollAngle;
|
for (int i = 0; i < tm; i++) {
|
param[i].tp = detParam;
|
param[i].nDeviceID = gi;
|
}
|
ret = THFI_Create_Ex(tm, param);
|
delete[] param;
|
}
|
if(ret != tm){
|
printf("create face detector failed!\n");
|
}else{
|
dtors_.emplace_back([]{THFI_Release();});
|
}
|
|
return ret;
|
}
|
|
static const int maxFacePos = 30;
|
|
int sdkface::face_detect(const cIMAGE *img, const int chan, void **fpos, int *fcnt){
|
if(chan < 0 || !img || !img->data || img->width <= 0 || img->height <= 0){
|
return -1;
|
}
|
|
if (fpos_ == NULL){
|
fpos_ = (cFacePos*)malloc(maxFacePos * sizeof(cFacePos));
|
}
|
|
// ::THFI_FacePos facesPos[maxFacePos];
|
int faceNum = THFI_DetectFace(chan, (BYTE*)(img->data), 24, img->width, img->height,
|
(::THFI_FacePos*)fpos_, maxFacePos);
|
|
if (faceNum > 0) {
|
// memcpy(fpos_, facesPos, sizeof(THFI_FacePos) * faceNum);
|
*fcnt = faceNum;
|
*fpos = fpos_;
|
}
|
return faceNum;
|
}
|
///////////////////////////////////////////////////
|
int sdkface::init_face_extractor(const int tm, const int gi){
|
int ret = 0;
|
if (gi < 0) {
|
ret = EF_Init(tm);
|
} else {
|
EF_Param *param = new EF_Param[tm];
|
for (int i = 0; i < tm; i++) {
|
param[i].nDeviceID = gi;
|
}
|
ret = EF_Init_Ex(tm, param);
|
delete[] param;
|
}
|
if(ret != tm){
|
printf("create face extractor failed!\n");;
|
}else{
|
dtors_.emplace_back([]{EF_Release();});
|
}
|
return ret;
|
}
|
|
int sdkface::face_extract_feature(const cFacePos &pos, const cIMAGE *img, const int chan,
|
void **feat, int *featLen){
|
if(chan < 0 || !img || !img->data || img->width <= 0 || img->height <= 0){
|
printf("face extract error, image or pos null\n");
|
return -1;
|
}
|
*featLen = EF_Size();
|
if (featLen_ < *featLen){
|
free(feat_);
|
feat_ = (unsigned char*)malloc(*featLen);
|
featLen_ = *featLen;
|
}
|
|
auto ret = EF_Extract(chan, (BYTE*)(img->data), img->width, img->height, 3,
|
(THFI_FacePos*)(&pos), feat_);
|
|
if(ret != 1){
|
printf("face extract error %d\n", ret);
|
return ret;
|
}
|
|
*feat = feat_;
|
|
return *featLen;
|
}
|
|
float sdkface::face_compare(unsigned char *feat1, unsigned char *feat2){
|
if (!feat1 || !feat2){
|
return 0.0f;
|
}
|
|
return EF_Compare(feat1, feat2);
|
}
|
|
////////////////////////////////////////////
|
int sdkface::init_face_property(const int tm){
|
auto ret = THFP_Create(tm);
|
if(ret != tm){
|
printf("create face property error\n");
|
}else{
|
dtors_.emplace_back([]{THFP_Release();});
|
}
|
return ret;
|
}
|
|
cThftResult sdkface::face_property(const cFacePos &pos, const cIMAGE *img, const int chan){
|
cThftResult result;
|
result.gender = result.age = result.race = -1;
|
|
auto ret = THFP_Execute_V2(chan, (BYTE*)(img->data), img->width, img->height,
|
(THFI_FacePos*)(&pos), (THFP_Result_V2*)(&result));
|
if(ret == 0){
|
// printf("property face gender %s, age %d, race %s, beauty level %d, smile_level %d\n",
|
// result.gender ?"male":"female",
|
// result.age,
|
// result.race==2?"yello":"other",
|
// result.beauty_level, result.smile_level);
|
}
|
return result;
|
}
|
/////////////////////////////////////////////////////
|
static THFT_Param param;
|
int sdkface::init_face_tracker(const int tm, const int gi,const int w, const int h,
|
const int maxFaces, const int detinterval, const int sampleSize){
|
param.nDeviceID = gi;
|
param.nImageWidth = w;
|
param.nImageHeight = h;
|
param.nMaxFaceNum = maxFaces;
|
param.nSampleSize = sampleSize > 0 ? sampleSize : w/2;
|
param.nDetectionIntervalFrame = detinterval;
|
|
printf("threads %d gi: %d size: %dx%d maxface: %d, sample: %d, interval: %d\n",
|
tm, gi, w, h, maxFaces, sampleSize, detinterval);
|
|
auto nNum = THFT_Create(tm, ¶m);
|
if(nNum != tm){
|
printf("create face detector failed!\n");
|
}else{
|
dtors_.emplace_back([]{THFT_Release();});
|
}
|
return nNum;
|
}
|
|
int sdkface::face_track(const cIMAGE *img, const int chan, void **fInfo, int *fcnt){
|
|
if (!finfo_){
|
finfo_ = (cFaceInfo*)malloc(param.nMaxFaceNum * sizeof(cFaceInfo));
|
}
|
|
*fcnt = 0;
|
|
auto nNum = THFT_FaceTracking(chan, img->data, (THFT_FaceInfo*)finfo_);
|
if (nNum > 0){
|
*fcnt = nNum;
|
*fInfo = finfo_;
|
}else{
|
*fInfo = NULL;
|
}
|
return nNum;
|
}
|
|
//THFACETRACKING_API int THFT_Reset(short nChannelID, THFT_Param* pParam);
|
int sdkface::face_track_resize(const int chan, const int w, const int h){
|
THFT_Param tmpParam;
|
tmpParam.nDeviceID = param.nDeviceID;
|
tmpParam.nImageWidth = w;
|
tmpParam.nImageHeight = h;
|
tmpParam.nMaxFaceNum = param.nMaxFaceNum;
|
tmpParam.nSampleSize = param.nSampleSize;
|
tmpParam.nDetectionIntervalFrame = param.nDetectionIntervalFrame;
|
|
printf("chan %d size: %dx%d", chan, w, h);
|
|
auto flag = THFT_Reset(chan, &tmpParam);
|
|
return flag;
|
}
|
}
|