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