派生自 libgowrapper/face

zhangmeng
2020-01-15 2b27c2c88872084123c77eceb5eea34a21290403
zero copy face
10个文件已删除
2个文件已添加
1 文件已重命名
3个文件已修改
924 ■■■■ 已修改文件
cface.cpp 137 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cface.h 64 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/all.hpp 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/base.hpp 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/face/detector.cpp 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/face/detector.h 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/face/extractor.cpp 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/face/extractor.h 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/face/property.cpp 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/face/property.h 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/face/tracker.cpp 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/face/tracker.h 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/face.cpp 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/face.h 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/struct.h 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
goface.go 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cface.cpp
@@ -1,85 +1,86 @@
#ifdef __cplusplus
extern "C"{
#endif
#include <stdio.h>
#include "cface.h"
#ifdef __cplusplus
}
#endif
#include "csrc/all.hpp"
using namespace csdk_wrap;
static VecFunc dtors_;
int c_api_face_detector_init(const int tm, const int gi, const int minFaces, const int rollAngle){
    return init_face_detector(tm, gi, minFaces, rollAngle, dtors_);
#include "csrc/face.h"
#include "csrc/struct.h"
#include "csrc/face.cpp"
using namespace cppface;
void *create_sdkface(){
    return new sdkface();
}
int c_api_face_property_init(const int tm){
    return init_face_property(tm, dtors_);
}
int c_api_face_extractor_init(const int tm, const int gi){
    return init_face_extractor(tm, gi, dtors_);
}
int c_api_face_tracker_init(const int tm, const int gi, const int wid, const int hei,
                              const int maxFaces, const int detinterval, const int sampleSize){
   return init_face_tracker(tm, gi, wid, hei, maxFaces, detinterval, sampleSize, dtors_);
}
int c_api_face_track_resize(const int chan, const int wid, const int hei){
    return face_track_resize(chan, wid, hei);
}
void c_api_release(){
    for(auto &i : dtors_){
        i();
void release(void *handle){
    if (handle){
        sdkface *s = (sdkface*)handle;
        delete s;
    }
    dtors_.clear();
}
////////////////////////////////////////////////
cFacePos* c_api_face_detect(int *faceCount, uchar*data, const int w, const int h, const int channel){
    const cIMAGE img{data, w, h, 3};
    return face_detect(faceCount, &img, channel);
int init_detector(void *handle, const int min_faces, const int roll_angles,
                    const int threads_max, const int gpu){
    sdkface *s = (sdkface*)handle;
    return s->detector(min_faces, roll_angles, threads_max, gpu);
}
cThftResult c_api_face_property(const cFacePos* pos, uchar*data, const int w, const int h, const int channel){
    const cIMAGE img{data, w, h, 3};
    return face_property(*pos, &img, channel);
int init_extractor(void *handle, const int threads_max, const int gpu){
    sdkface *s = (sdkface*)handle;
    return s->extractor(threads_max, gpu);
}
uchar* c_api_face_extract(int *featLen, const cFacePos* pos, uchar*data, const int w, const int h, const int channel){
    const cIMAGE img{data, w, h, 3};
    return face_extract_feature(featLen, *pos, &img, channel);
int init_propertizer(void *handle, const int threads_max){
    sdkface *s = (sdkface*)handle;
    return s->propertizer(threads_max);
}
float c_api_face_compare(uchar *feat1, uchar *feat2){
    return face_compare(feat1, feat2);
int init_tracker(void *handle, const int width, const int height,
            const int max_faces, const int interval, const int sample_size,
            const int threads_max, const int gpu){
    sdkface *s = (sdkface*)handle;
    return s->tracker(width, height, max_faces, interval, sample_size, threads_max, gpu);
}
cRECT* c_api_face_track_only(int *fCount, uchar *data, const int wid, const int hei, const int channel){
    const cIMAGE img{data, wid, hei, 3};
    return face_track_only(fCount, &img, channel);
int detect(void *handle, const void *data, const int w, const int h, const int c, const int chan, void **fpos, int *fcnt){
    sdkface *s = (sdkface*)handle;
    cIMAGE img{(unsigned char*)data, w, h, c};
    return s->detect(&img, chan, fpos, fcnt);
}
cFaceInfo* c_api_face_track_detect(int *fCount, uchar *data, const int wid, const int hei, const int channel){
    const cIMAGE img{data, wid, hei, 3};
    return face_track_detect(fCount, &img, channel);
int extract(void *handle, const cFacePos *pos, const void*data, const int w, const int h, const int c, const int chan, void **feat, int *featLen){
    sdkface *s = (sdkface*)handle;
    cIMAGE img{(unsigned char*)data, w, h, c};
    return s->extract(*pos, &img, chan, feat, featLen);
}
cFaceInfo* c_api_face_track(int *fCount, uchar *data, const int wid, const int hei, const int channel){
    const cIMAGE img{data, wid, hei, 3};
    return face_track(fCount, &img, channel);
float compare(void *handle, unsigned char *feat1, unsigned char *feat2){
    sdkface *s = (sdkface*)handle;
    return s->compare(feat1, feat2);
}
int propertize(void *handle, const cFacePos *pos, const void *data, const int w, const int h, const int c, const int chan, void **res){
    sdkface *s = (sdkface*)handle;
    cIMAGE img{(unsigned char*)data, w, h, c};
    return s->propertize(*pos, &img, chan, res);
}
int track(void *handle, const void *data, const int w, const int h, const int c, const int chan, void **fInfo, int *fcnt){
    sdkface *s = (sdkface*)handle;
    cIMAGE img{(unsigned char*)data, w, h, c};
    return s->track(&img, chan, fInfo, fcnt);
}
int track_resize(void *handle, const int w, const int h, const int chan){
    sdkface *s = (sdkface*)handle;
    return s->track_resize(w, h, chan);
}
cface.h
@@ -1,40 +1,36 @@
#ifndef _c_wrapper_sdk_h_
#define _c_wrapper_sdk_h_
#ifndef _c_face_h_
#define _c_face_h_
#ifdef __cplusplus
extern "C"{
#endif
#include "csdk_struct.h"
#ifndef uchar
typedef unsigned char uchar;
#endif
typedef void* YoloHandle;
int c_api_face_detector_init(const int tm, const int gi, const int minFaces, const int rollAngle);
int c_api_face_property_init(const int tm);
int c_api_face_extractor_init(const int tm, const int gi);
int c_api_face_tracker_init(const int tm, const int gi, const int wid, const int hei,
                              const int maxFaces, const int detinterval, const int sampleSize);
int c_api_face_track_resize(const int chan, const int w, const int h);
void c_api_release();
///////////////////////////////////////////
/// face api
cFacePos* c_api_face_detect(int *faceCount, uchar*data, const int w, const int h, const int channel);
cThftResult c_api_face_property(const cFacePos* pos, uchar*data, const int w, const int h, const int channel);
uchar* c_api_face_extract(int *featLen, const cFacePos* pos, uchar*data, const int w, const int h, const int channel);
float c_api_face_compare(uchar *feat1, uchar *feat2);
cRECT* c_api_face_track_only(int *fCount, uchar *data, const int wid, const int hei, const int channel);
cFaceInfo* c_api_face_track_detect(int *fCount, uchar *data, const int wid, const int hei, const int channel);
cFaceInfo* c_api_face_track(int *fCount, uchar *data, const int wid, const int hei, const int channel);
#include "csrc/struct.h"
void *create_sdkface();
void release(void *handle);
int init_detector(void *handle, const int min_faces, const int roll_angles,
                    const int threads_max, const int gpu);
int init_extractor(void *handle, const int threads_max, const int gpu);
int init_propertizer(void *handle, const int threads_max);
int init_tracker(void *handle, const int width, const int height,
            const int max_faces, const int interval, const int sample_size,
            const int threads_max, const int gpu);
int detect(void *handle, const void *data, const int w, const int h, const int c, const int chan, void **fpos, int *fcnt);
int extract(void *handle, const cFacePos *pos, const void*data, const int w, const int h, const int c, const int chan, void **feat, int *featLen);
float compare(void *handle, unsigned char *feat1, unsigned char *feat2);
int propertize(void *handle, const cFacePos *pos, const void *data, const int w, const int h, const int c, const int chan, void **res);
int track(void *handle, const void *data, const int w, const int h, const int c, const int chan, void **fInfo, int *fcnt);
int track_resize(void *handle, const int w, const int h, const int chan);
#ifdef __cplusplus
}
#endif
#endif
#endif
csrc/all.hpp
File was deleted
csrc/buz/base.hpp
File was deleted
csrc/buz/face/detector.cpp
File was deleted
csrc/buz/face/detector.h
File was deleted
csrc/buz/face/extractor.cpp
File was deleted
csrc/buz/face/extractor.h
File was deleted
csrc/buz/face/property.cpp
File was deleted
csrc/buz/face/property.h
File was deleted
csrc/buz/face/tracker.cpp
File was deleted
csrc/buz/face/tracker.h
File was deleted
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
csrc/face.h
New file
@@ -0,0 +1,51 @@
#ifndef _cpp_face_hpp_
#define _cpp_face_hpp_
#include <vector>
#include <functional>
using VecFunc = std::vector<std::function<void()> >;
#include "struct.h"
namespace cppface
{
    class sdkface{
    public:
        sdkface();
        ~sdkface();
    public:
        int detector(const int min_faces, const int roll_angles,
                    const int threads_max, const int gpu);
        int extractor(const int threads_max, const int gpu);
        int propertizer(const int threads_max);
        int 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);
    public:
        int detect(const cIMAGE *img, const int chan, void **fpos, int *fcnt);
        int extract(const cFacePos &pos, const cIMAGE *img, const int chan, void **feat, int *featLen);
        float compare(unsigned char *feat1, unsigned char *feat2);
        int propertize(const cFacePos &pos, const cIMAGE *img, const int chan, void **res);
        int track(const cIMAGE *img, const int chan, void **fInfo, int *fcnt);
        int track_resize(const int w, const int h, const int chan);
    private:
        VecFunc dtors_;
        cFacePos *fpos_;
        int feature_size_;
        unsigned char *feature_;
        cFaceInfo *finfos_;
    };
} // namespace cppface
#endif
csrc/struct.h
File was renamed from csdk_struct.h
@@ -1,34 +1,32 @@
#ifndef _c_wrapper_c_structure_h_
#define _c_wrapper_c_structure_h_
#include <string.h>
#ifndef _face_struct_h_
#define _face_struct_h_
typedef struct _cPOINT {
    int x;
    int y;
} cPOINT;
typedef struct _cRECT {
    int left;
    int top;
    int right;
    int bottom;
} cRECT;
typedef struct _cIMAGE{
    unsigned char *data;
    int width;
    int height;
    int channel;
} cIMAGE;
typedef struct _cFaceAngle {
    int yaw;
    int pitch;
    int roll;
    float confidence;
} cFaceAngle;
typedef struct _cThftResult {
    int gender;//1-male,0-female
    int age;//range[0-100]
@@ -36,7 +34,7 @@
    int beauty_level;//range[0-100]
    int smile_level;//range[0-100]
} cThftResult;
typedef struct _cFacePos {
    cRECT rcFace;
    cPOINT ptLeftEye;
@@ -48,7 +46,7 @@
    
    unsigned char pFacialData[512];
} cFacePos;
typedef struct _cFaceInfo{
    cRECT rcFace;
    cPOINT ptLeftEye;
@@ -61,6 +59,5 @@
    unsigned char pFacialData[8*1024];
    long        nFaceID;//face tracking id
} cFaceInfo;
#endif
goface.go
@@ -22,6 +22,7 @@
// SDKFace sdk
type SDKFace struct {
    handle      unsafe.Pointer
    detector    bool
    extractor   bool
    propertizer bool
@@ -31,8 +32,13 @@
// NewSDK sdk
func NewSDK(fn func(...interface{})) *SDKFace {
    h := C.create_sdkface()
    if h == nil {
        return nil
    }
    return &SDKFace{
        handle:      h,
        detector:    false,
        extractor:   false,
        propertizer: false,
@@ -43,7 +49,9 @@
// Free free
func (s *SDKFace) Free() {
    C.c_api_release()
    if s != nil && s.handle != nil {
        C.release(s.handle)
    }
}
func (s *SDKFace) printLog(l ...interface{}) {
@@ -53,14 +61,12 @@
}
// Detector detector
func (s *SDKFace) Detector(minFaces, rollAngle, threadMax, gpu int) bool {
func (s *SDKFace) Detector(minFaces, rollAngles, threadMax, gpu int) bool {
    if s.detector {
        return true
    }
    ret := C.c_api_face_detector_init(C.int(threadMax), C.int(gpu), C.int(minFaces), C.int(rollAngle))
    ret := C.init_detector(s.handle, C.int(minFaces), C.int(rollAngles), C.int(threadMax), C.int(gpu))
    if ret <= 0 {
        s.printLog("->face--> CREATE Detector ERROR: ", ret)
        return false
@@ -75,7 +81,7 @@
    if s.extractor {
        return true
    }
    ret := C.c_api_face_extractor_init(C.int(threadMax), C.int(gpu))
    ret := C.init_extractor(s.handle, C.int(threadMax), C.int(gpu))
    if ret <= 0 {
        s.printLog("->face--> CREATE Extractor ERROR: ", ret)
        return false
@@ -90,7 +96,7 @@
    if s.propertizer {
        return true
    }
    ret := C.c_api_face_property_init(C.int(threadMax))
    ret := C.init_propertizer(s.handle, C.int(threadMax))
    if ret <= 0 {
        s.printLog("->face--> CREATE Propertizer ERROR: ", ret)
        return false
@@ -103,9 +109,10 @@
func (s *SDKFace) Tracker(w, h, maxFaces, interval, sampleSize, threadMax, gpu int) bool {
    if s.tracker {
        return true
        return s.tracker
    }
    ret := C.c_api_face_tracker_init(C.int(threadMax), C.int(gpu), C.int(w), C.int(h), C.int(maxFaces), C.int(interval), C.int(sampleSize))
    ret := C.init_tracker(s.handle, C.int(w), C.int(h), C.int(maxFaces), C.int(interval), C.int(sampleSize), C.int(threadMax), C.int(gpu))
    if ret <= 0 {
        s.printLog("->face--> CREATE Tracker ERROR: ", ret)
        return false
@@ -134,32 +141,29 @@
        return nil
    }
    var cfpos unsafe.Pointer
    var count C.int
    cfpos := C.c_api_face_detect(&count, (*C.uchar)(unsafe.Pointer(&data[0])), C.int(w), C.int(h), C.int(ch))
    if cfpos != nil {
        defer C.free(unsafe.Pointer(cfpos))
        return CFacePosArrayToGoArray(unsafe.Pointer(cfpos), int(count))
    ret := C.detect(s.handle, unsafe.Pointer(&data[0]), C.int(w), C.int(h), C.int(c), C.int(ch), &cfpos, &count)
    if ret > 0 {
        return CFacePosArrayToGoArray(cfpos, int(count))
    }
    s.printLog("->face--> Detect No One")
    s.printLog("->face--> Detect No One, Ret: ", ret)
    return nil
}
// Extract extract
func (s *SDKFace) Extract(fpos sdkstruct.CFacePos, data []byte, w, h, c int, ch int) []byte {
    if !s.extractor {
        return nil
    }
    var featLen C.int
    pos := (*C.cFacePos)(unsafe.Pointer(&fpos))
    p := C.c_api_face_extract(&featLen, pos, (*C.uchar)(unsafe.Pointer(&data[0])), C.int(w), C.int(h), C.int(ch))
    if p != nil {
        defer C.free(unsafe.Pointer(p))
        return C.GoBytes(unsafe.Pointer(p), featLen)
    //(void *handle, const cFacePos *pos, const void*data, const int w, const int h, const int c, const int chan, void **feat, int *featLen);
    var feat unsafe.Pointer
    var featLen C.int
    ret := C.extract(s.handle, pos, unsafe.Pointer(&data[0]), C.int(w), C.int(h), C.int(c), C.int(ch), &feat, &featLen)
    if ret > 0 {
        return C.GoBytes(feat, featLen)
    }
    s.printLog("->face--> Extract Nothing")
    s.printLog("->face--> Extract Nothing, Ret: ", ret)
    return nil
}
@@ -170,20 +174,27 @@
        return 0
    }
    res := C.c_api_face_compare((*C.uchar)(unsafe.Pointer(&feat1[0])), (*C.uchar)(unsafe.Pointer(&feat2[0])))
    res := C.compare(s.handle, (*C.uchar)(unsafe.Pointer(&feat1[0])), (*C.uchar)(unsafe.Pointer(&feat2[0])))
    return float32(res)
}
// Propertize prop
func (s *SDKFace) Propertize(fpos sdkstruct.CFacePos, data []byte, w, h, c int, ch int) sdkstruct.CThftResult {
func (s *SDKFace) Propertize(fpos sdkstruct.CFacePos, data []byte, w, h, c int, ch int) *sdkstruct.CThftResult {
    if !s.propertizer {
        return sdkstruct.CThftResult{Age: 0}
        return nil
    }
    pos := (*C.cFacePos)(unsafe.Pointer(&fpos))
    result := C.c_api_face_property(pos, (*C.uchar)(unsafe.Pointer(&data[0])), C.int(w), C.int(h), C.int(ch))
    s.printLog("->face--> Propertize")
    return *(*sdkstruct.CThftResult)(unsafe.Pointer(&result))
    var thft unsafe.Pointer
    ret := C.propertize(s.handle, pos, unsafe.Pointer(&data[0]), C.int(w), C.int(h), C.int(c), C.int(ch), &thft)
    if ret == 0 {
        gothft := *(*sdkstruct.CThftResult)(thft)
        C.free(thft)
        return &gothft
    }
    s.printLog("->face--> Propertize Nothing, Ret: ", ret)
    return nil
}
// CFaceInfoArrayToGoArray convert cFaceInfo array to go
@@ -207,14 +218,17 @@
    //img, const int chan, void **fInfo, int *fcnt);
    var fCount C.int
    cFinfo := C.c_api_face_track(&fCount, (*C.uchar)(unsafe.Pointer(&data[0])), C.int(w), C.int(h), C.int(ch))
    // fmt.Println("cFinfo detected:", cFinfo)
    if cFinfo == nil {
        return nil
    var finfos unsafe.Pointer
    ret := C.track(s.handle, unsafe.Pointer(&data[0]), C.int(w), C.int(h), C.int(c), C.int(ch), &finfos, &fCount)
    if ret > 0 {
        faces := CFaceInfoArrayToGoArray(finfos, int(fCount))
        //if len(faces) > 0{
        // fmt.Println("faces detected:", len(faces))
        //}
        return faces
    }
    defer C.free(unsafe.Pointer(cFinfo))
    faces := CFaceInfoArrayToGoArray(unsafe.Pointer(cFinfo), int(fCount))
    return faces
    return nil
}
// FaceInfo2FacePos info -> pos
@@ -235,13 +249,18 @@
}
// TrackerResize init face tracker
func (s *SDKFace) TrackerResize(w, h, ch int) int {
func (s *SDKFace) TrackerResize(w, h, ch int) bool {
    if !s.tracker {
        s.printLog("->face--> TrackerResize Failed, No Tracker Init")
        return -1
        return false
    }
    return int(C.c_api_face_track_resize(C.int(ch), C.int(w), C.int(h)))
    ret := C.track_resize(s.handle, C.int(w), C.int(h), C.int(ch))
    if ret == 1 {
        return true
    }
    s.printLog("->face--> TrackerResize Failed, Ret: ", ret, " SDK Channel: ", ch, " Size: ", w, "x", h)
    return false
}
// Run run
@@ -272,7 +291,7 @@
        //运行sd
        dec := FaceInfo2FacePos(d)
        p := s.Propertize(dec, data, w, h, c, dchan)
        p := s.Propertize(dec, data, w, h, c, 0)
        feat := s.Extract(dec, data, w, h, c, dchan)
        /// filter rules
@@ -280,7 +299,7 @@
        // size := (d.RcFace.Right - d.RcFace.Left) * (d.RcFace.Bottom - d.RcFace.Top)
        // angle := d.FAngle
        // if !filter(rMsg.Msg.Tasklab.Taskid, sdkid, angle.Confidence, float32(angle.Yaw), int(size)) {
        //     continue
        //     continue
        // }
        /// filter rules