From 2b27c2c88872084123c77eceb5eea34a21290403 Mon Sep 17 00:00:00 2001 From: zhangmeng <775834166@qq.com> Date: 星期三, 15 一月 2020 11:10:42 +0800 Subject: [PATCH] zero copy face --- csrc/face.cpp | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 225 insertions(+), 0 deletions(-) diff --git a/csrc/face.cpp b/csrc/face.cpp new file mode 100644 index 0000000..328111a --- /dev/null +++ b/csrc/face.cpp @@ -0,0 +1,225 @@ +#include "face.h" + +#include <memory.h> + +#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 -- Gitblit v1.8.0