#include "face.h" #include #include "THFaceImage_i.h" #include "THFeature_i.h" #include "THFaceProperty_i.h" #include "THFaceTracking_i.h" namespace cppface { sdkface::sdkface() :fpos_(NULL) ,feature_size_(0) ,feature_(NULL) ,finfos_(NULL) {} sdkface::~sdkface() { for (auto i : dtors_){ i(); } if (fpos_) free(fpos_); if (feature_) free(feature_); if (finfos_) free(finfos_); } int sdkface::detector(const int min_faces, const int roll_angles, const int threads_max, const int gpu){ int ret = 0; if (gpu < 0) { THFI_Param *param = new THFI_Param[threads_max]; ret = THFI_Create(threads_max, param); delete[] param; } else { THFI_Param_Ex *param = new THFI_Param_Ex[threads_max]; THFI_Param detParam; detParam.nMinFaceSize = min_faces; detParam.nRollAngle = roll_angles; for (int i = 0; i < threads_max; i++) { param[i].tp = detParam; param[i].nDeviceID = gpu; } ret = THFI_Create_Ex(threads_max, param); delete[] param; } if(ret != threads_max){ printf("create face detector failed!\n"); }else{ dtors_.emplace_back([]{THFI_Release();}); } return ret; } int sdkface::extractor(const int threads_max, const int gpu){ int ret = 0; if (gpu < 0) { ret = EF_Init(threads_max); } else { EF_Param *param = new EF_Param[threads_max]; for (int i = 0; i < threads_max; i++) { param[i].nDeviceID = gpu; } ret = EF_Init_Ex(threads_max, param); delete[] param; } if(ret != threads_max){ printf("create face extractor failed!\n");; }else{ dtors_.emplace_back([]{EF_Release();}); } return ret; } int sdkface::propertizer(const int threads_max){ auto ret = THFP_Create(threads_max); if(ret != threads_max){ printf("create face property error\n"); }else{ dtors_.emplace_back([]{THFP_Release();}); } return ret; } static const int maxFacePos = 30; int sdkface::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::extract(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 (feature_size_ < *featLen){ free(feature_); feature_ = (unsigned char*)malloc(*featLen); feature_size_ = *featLen; } auto ret = EF_Extract(chan, (BYTE*)(img->data), img->width, img->height, 3, (THFI_FacePos*)(&pos), feature_); if(ret != 1){ printf("face extract error %d\n", ret); return ret; } *feat = feature_; return *featLen; } float sdkface::compare(unsigned char *feat1, unsigned char *feat2){ if (!feat1 || !feat2){ return 0.0f; } return EF_Compare(feat1, feat2); } int sdkface::propertize(const cFacePos &pos, const cIMAGE *img, const int chan, void **res){ if(chan < 0 || !img || !img->data || img->width <= 0 || img->height <= 0){ printf("face propertize error, image or pos null\n"); return -1; } cThftResult *thft = (cThftResult*)malloc(sizeof(cThftResult)); *res = NULL; auto ret = THFP_Execute_V2(chan, (BYTE*)(img->data), img->width, img->height, (THFI_FacePos*)(&pos), (THFP_Result_V2*)thft); if(ret == 0){ *res = thft; // printf("property face gender %s, age %d, race %s, beauty level %d, smile_level %d\n", // res.gender ?"male":"female", // res.age, // res.race==2?"yello":"other", // res.beauty_level, res.smile_level); } return ret; } static THFT_Param param; int sdkface::tracker(const int width, const int height, const int max_faces, const int interval, const int sample_size, const int threads_max, const int gpu){ param.nDeviceID = gpu; param.nImageWidth = width; param.nImageHeight = height; param.nMaxFaceNum = max_faces; param.nSampleSize = sample_size > 0 ? sample_size : width/2; param.nDetectionIntervalFrame = interval; printf("##########start threads: %d gi: %d size: %dx%d maxface: %d, sample: %d, interval: %d\n", threads_max, gpu, width, height, max_faces, sample_size, interval); auto nNum = THFT_Create(threads_max, ¶m); if(nNum != threads_max){ printf("create face detector failed!\n"); }else{ dtors_.emplace_back([]{THFT_Release();}); } printf("##########end threads: %d gi: %d size: %dx%d maxface: %d, sample: %d, interval: %d\n", threads_max, gpu, width, height, max_faces, sample_size, interval); return nNum; } int sdkface::track(const cIMAGE *img, const int chan, void **fInfo, int *fcnt){ if (!finfos_){ finfos_ = (cFaceInfo*)malloc(param.nMaxFaceNum * sizeof(cFaceInfo)); } *fcnt = 0; auto nNum = THFT_FaceTracking(chan, img->data, (THFT_FaceInfo*)finfos_); if (nNum > 0){ *fcnt = nNum; *fInfo = finfos_; }else{ *fInfo = NULL; } return nNum; } int sdkface::track_resize(const int w, const int h, const int chan){ 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("##########resize track\n"); return THFT_Reset(chan, &tmpParam); } } // namespace cppface