New file |
| | |
| | | #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 |