派生自 libgowrapper/face

zhangmeng
2020-01-15 2b27c2c88872084123c77eceb5eea34a21290403
csrc/face.cpp
New file
@@ -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