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, &param);
+        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