feat(pose): add utralight posenet

This commit is contained in:
Syd Xu
2021-10-26 20:38:31 +08:00
parent 17ebe05f9c
commit 5d0fc1244f
34 changed files with 542 additions and 141 deletions

View File

@@ -3,7 +3,7 @@ package detecter
/*
#include <stdlib.h>
#include <stdbool.h>
#include "openvision/common/common.h"
#include "openvision/face/common.h"
#include "openvision/face/detecter.h"
*/
import "C"

View File

@@ -3,7 +3,7 @@ package face
/*
#include <stdlib.h>
#include <stdbool.h>
#include "openvision/common/common.h"
#include "openvision/face/common.h"
*/
import "C"
import (

View File

@@ -3,7 +3,7 @@ package face
/*
#include <stdlib.h>
#include <stdbool.h>
#include "openvision/common/common.h"
#include "openvision/face/common.h"
*/
import "C"

View File

@@ -3,7 +3,7 @@ package hopenet
/*
#include <stdlib.h>
#include <stdbool.h>
#include "openvision/common/common.h"
#include "openvision/face/common.h"
#include "openvision/face/hopenet.h"
*/
import "C"

View File

@@ -3,7 +3,7 @@ package face
/*
#include <stdlib.h>
#include <stdbool.h>
#include "openvision/common/common.h"
#include "openvision/face/common.h"
*/
import "C"
import (

View File

@@ -3,7 +3,7 @@ package tracker
/*
#include <stdlib.h>
#include <stdbool.h>
#include "openvision/common/common.h"
#include "openvision/face/common.h"
#include "openvision/face/tracker.h"
*/
import "C"

View File

@@ -131,14 +131,21 @@ file(COPY
DESTINATION ${INCLUDE_OUTPUT_PATH}/openvision/common
)
file(COPY
${CMAKE_CURRENT_SOURCE_DIR}/face/detecter/detecter.h
${CMAKE_CURRENT_SOURCE_DIR}/face/landmarker/landmarker.h
${CMAKE_CURRENT_SOURCE_DIR}/face/recognizer/recognizer.h
${CMAKE_CURRENT_SOURCE_DIR}/face/tracker/tracker.h
${CMAKE_CURRENT_SOURCE_DIR}/face/hopenet/hopenet.h
${CMAKE_CURRENT_SOURCE_DIR}/face/common.h
${CMAKE_CURRENT_SOURCE_DIR}/face/detecter.h
${CMAKE_CURRENT_SOURCE_DIR}/face/landmarker.h
${CMAKE_CURRENT_SOURCE_DIR}/face/recognizer.h
${CMAKE_CURRENT_SOURCE_DIR}/face/tracker.h
${CMAKE_CURRENT_SOURCE_DIR}/face/hopenet.h
DESTINATION ${INCLUDE_OUTPUT_PATH}/openvision/face
)
file(COPY
${CMAKE_CURRENT_SOURCE_DIR}/pose/common.h
${CMAKE_CURRENT_SOURCE_DIR}/pose/detecter.h
DESTINATION ${INCLUDE_OUTPUT_PATH}/openvision/pose
)
file(COPY
${CMAKE_CURRENT_SOURCE_DIR}/realesrgan/realesrgan.h
DESTINATION ${INCLUDE_OUTPUT_PATH}/openvision/realsr

View File

@@ -34,32 +34,6 @@ void FreePoint2fVector(Point2fVector* p) {
}
}
void FreeRectVector(RectVector *p) {
if (p->rects != NULL) {
free(p->rects);
p->rects = NULL;
}
}
void FreeFaceInfoVector(FaceInfoVector *p) {
if (p->faces != NULL) {
free(p->faces);
p->faces = NULL;
}
}
void NewFaceInfoVector(FaceInfoVector *v, int num) {
v->length = num;
v->faces = (FaceInfo*)(malloc(num * sizeof(FaceInfo)));
}
void FreeTrackedFaceInfoVector(TrackedFaceInfoVector *p) {
if (p->faces != NULL) {
free(p->faces);
p->faces = NULL;
}
}
void FreeFloatVector(FloatVector *p) {
if (p->values != NULL) {
free(p->values);
@@ -161,24 +135,6 @@ int ComputeIOU(const Rect & rect1,
return 0;
}
float CalculateSimilarity(const std::vector<float>&feature1, const std::vector<float>& feature2) {
if (feature1.size() != feature2.size()) {
std::cout << "feature size not match." << std::endl;
return 10003;
}
float inner_product = 0.0f;
float feature_norm1 = 0.0f;
float feature_norm2 = 0.0f;
#ifdef OV_OPENMP
#pragma omp parallel for num_threads(threads_num)
#endif
for(int i = 0; i < kFaceFeatureDim; ++i) {
inner_product += feature1[i] * feature2[i];
feature_norm1 += feature1[i] * feature1[i];
feature_norm2 += feature2[i] * feature2[i];
}
return inner_product / sqrt(feature_norm1) / sqrt(feature_norm2);
}
void EnlargeRect(const float& scale, Rect* rect) {
float offset_x = (scale - 1.f) / 2.f * rect->width;

View File

@@ -11,14 +11,8 @@ typedef ov::Size Size;
typedef ov::Point Point;
typedef ov::Point2f Point2f;
typedef ov::Rect Rect;
typedef ov::FaceInfo FaceInfo;
typedef ov::TrackedFaceInfo TrackedFaceInfo;
typedef ov::HeadPose HeadPose;
#else
#define kFaceFeatureDim 128
#define kFaceNameDim 256
// Wrapper for an individual cv::cvSize
typedef struct Size {
int width;
@@ -46,26 +40,6 @@ typedef struct Rect {
int height;
} Rect;
typedef struct FaceInfo {
Rect location_;
float score_;
float keypoints_[10];
bool mask_;
} FaceInfo;
typedef struct TrackedFaceInfo {
FaceInfo face_info_;
float iou_score_;
} TrackedFaceInfo;
typedef struct HeadPose
{
float roll;
float pitch;
float yaw;
} HeadPose;
#endif
int get_gpu_count();
@@ -86,21 +60,6 @@ typedef struct RectVector {
void FreeRectVector(RectVector *p);
typedef struct FaceInfoVector {
FaceInfo* faces;
int length;
} FaceInfoVector;
void FreeFaceInfoVector(FaceInfoVector *p);
void NewFaceInfoVector(FaceInfoVector *v, int num);
typedef struct TrackedFaceInfoVector {
TrackedFaceInfo* faces;
int length;
} TrackedFaceInfoVector;
void FreeTrackedFaceInfoVector(TrackedFaceInfoVector *p);
typedef struct FloatVector {
float* values;
int length;

View File

@@ -9,8 +9,6 @@
#endif
namespace ov {
#define kFaceFeatureDim 128
#define kFaceNameDim 256
const int threads_num = 2;
// Wrapper for an individual cv::cvSize
@@ -82,30 +80,6 @@ struct ObjectInfo {
std::string name_;
};
struct FaceInfo {
Rect location_;
float score_;
float keypoints_[10];
bool mask_;
};
struct TrackedFaceInfo {
FaceInfo face_info_;
float iou_score_;
};
struct HeadPose
{
float roll;
float pitch;
float yaw;
};
struct QueryResult {
std::string name_;
float sim_;
};
int RatioAnchors(const Rect & anchor,
const std::vector<float>& ratios, std::vector<Rect>* anchors);
@@ -160,7 +134,6 @@ int const NMS(const std::vector<T>& inputs, std::vector<T>* result,
return 0;
}
float CalculateSimilarity(const std::vector<float>&feature1, const std::vector<float>& feature2);
void EnlargeRect(const float& scale, Rect* rect);
void RectifyRect(Rect* rect);

50
src/face/common.h Normal file
View File

@@ -0,0 +1,50 @@
#ifndef _FACE_COMMON_C_H_
#define _FACE_COMMON_C_H_
#include "../common/common.h"
#ifdef __cplusplus
#include "common/common.hpp"
extern "C" {
#endif
#ifdef __cplusplus
typedef ov::FaceInfo FaceInfo;
typedef ov::TrackedFaceInfo TrackedFaceInfo;
typedef ov::HeadPose HeadPose;
#else
typedef struct FaceInfo {
Rect location_;
float score_;
float keypoints_[10];
bool mask_;
} FaceInfo;
typedef struct TrackedFaceInfo {
FaceInfo face_info_;
float iou_score_;
} TrackedFaceInfo;
typedef struct HeadPose {
float roll;
float pitch;
float yaw;
} HeadPose;
#endif
typedef struct FaceInfoVector {
FaceInfo* faces;
int length;
} FaceInfoVector;
typedef struct TrackedFaceInfoVector {
TrackedFaceInfo* faces;
int length;
} TrackedFaceInfoVector;
void FreeFaceInfoVector(FaceInfoVector *p);
void NewFaceInfoVector(FaceInfoVector *v, int num);
void FreeTrackedFaceInfoVector(TrackedFaceInfoVector *p);
#ifdef __cplusplus
}
#endif
#endif // !_FACE_COMMON_C_H_

View File

@@ -0,0 +1,54 @@
#include "../common.h"
#include <math.h>
#ifdef OV_VULKAN
#include "gpu.h"
#endif // OV_VULKAN
void FreeRectVector(RectVector *p) {
if (p->rects != NULL) {
free(p->rects);
p->rects = NULL;
}
}
void FreeFaceInfoVector(FaceInfoVector *p) {
if (p->faces != NULL) {
free(p->faces);
p->faces = NULL;
}
}
void NewFaceInfoVector(FaceInfoVector *v, int num) {
v->length = num;
v->faces = (FaceInfo*)(malloc(num * sizeof(FaceInfo)));
}
void FreeTrackedFaceInfoVector(TrackedFaceInfoVector *p) {
if (p->faces != NULL) {
free(p->faces);
p->faces = NULL;
}
}
namespace ov {
float CalculateSimilarity(const std::vector<float>&feature1, const std::vector<float>& feature2) {
if (feature1.size() != feature2.size()) {
return 10003;
}
float inner_product = 0.0f;
float feature_norm1 = 0.0f;
float feature_norm2 = 0.0f;
#ifdef OV_OPENMP
#pragma omp parallel for num_threads(threads_num)
#endif
for(int i = 0; i < kFaceFeatureDim; ++i) {
inner_product += feature1[i] * feature2[i];
feature_norm1 += feature1[i] * feature1[i];
feature_norm2 += feature2[i] * feature2[i];
}
return inner_product / sqrt(feature_norm1) / sqrt(feature_norm2);
}
}

View File

@@ -0,0 +1,31 @@
#ifndef _FACE_COMMON_H_
#define _FACE_COMMON_H_
#include "../../common/common.h"
#include <vector>
namespace ov {
#define kFaceFeatureDim 128
#define kFaceNameDim 256
struct FaceInfo {
Rect location_;
float score_;
float keypoints_[10];
bool mask_;
};
struct TrackedFaceInfo {
FaceInfo face_info_;
float iou_score_;
};
struct HeadPose
{
float roll;
float pitch;
float yaw;
};
}
float CalculateSimilarity(const std::vector<float>&feature1, const std::vector<float>& feature2);
#endif // !_FACE_COMMON_H_

View File

@@ -1,10 +1,10 @@
#ifndef _FACE_DETECTER_C_H_
#define _FACE_DETECTER_C_H_
#include "../common/common.h"
#include "common.h"
#ifdef __cplusplus
#include "detecter.hpp"
#include "detecter/detecter.hpp"
extern "C" {
#endif
typedef void* IDetecter;

View File

@@ -1,4 +1,4 @@
#include "detecter.h"
#include "../detecter.h"
#include "centerface/centerface.hpp"
#include "mtcnn/mtcnn.hpp"
#include "retinaface/retinaface.hpp"

View File

@@ -1,10 +1,10 @@
#ifndef _ROS_NCNN_HOPENET_C_H_
#define _ROS_NCNN_HOPENET_C_H_
#include "../common/common.h"
#include "common.h"
#ifdef __cplusplus
#include "hopenet.hpp"
#include "hopenet/hopenet.hpp"
extern "C" {
#endif
typedef void* IHopeNet;

View File

@@ -1,4 +1,4 @@
#include "hopenet.h"
#include "../hopenet.h"
#include <iostream>
#include <numeric>

View File

@@ -1,7 +1,7 @@
#ifndef _ROS_NCNN_HOPENET_H_
#define _ROS_NCNN_HOPENET_H_
#include "../../common/common.h"
#include "../common/common.hpp"
#include "net.h"
namespace ov {

View File

@@ -1,10 +1,10 @@
#ifndef _FACE_LANDMARKER_C_H_
#define _FACE_LANDMARKER_C_H_
#include "../common/common.h"
#include "common.h"
#ifdef __cplusplus
#include "landmarker.hpp"
#include "landmarker/landmarker.hpp"
extern "C" {
#endif
typedef void* ILandmarker;

View File

@@ -1,6 +1,5 @@
#include "insightface.hpp"
#include <string>
#include "../../common/common.hpp"
#ifdef OV_VULKAN
#include "gpu.h"

View File

@@ -1,4 +1,4 @@
#include "landmarker.h"
#include "../landmarker.h"
#include "zqlandmarker/zqlandmarker.hpp"
#include "insightface/insightface.hpp"

View File

@@ -1,9 +1,10 @@
#ifndef _FACE_RECOGNIZER_C_H_
#define _FACE_RECOGNIZER_C_H_
#include "../common/common.h"
#include "common.h"
#ifdef __cplusplus
#include "recognizer.hpp"
#include "recognizer/recognizer.hpp"
extern "C" {
#endif
typedef void* IRecognizer;

View File

@@ -1,4 +1,4 @@
#include "recognizer.h"
#include "../recognizer.h"
#include "./mobilefacenet/mobilefacenet.hpp"
IRecognizer new_mobilefacenet() {

View File

@@ -1,9 +1,9 @@
#ifndef _FACE_TRACKER_C_H_
#define _FACE_TRACKER_C_H_
#include "../common/common.h"
#include "common.h"
#ifdef __cplusplus
#include "tracker.hpp"
#include "tracker/tracker.hpp"
extern "C" {
#endif
typedef void* ITracker;

View File

@@ -1,4 +1,4 @@
#include "tracker.h"
#include "../tracker.h"
#include <queue>
ITracker new_tracker() {

View File

@@ -2,7 +2,7 @@
#define _FACE_TRACKER_H_
#include <vector>
#include "../common/common.h"
#include "../common/common.hpp"
namespace ov {
class Tracker {

40
src/pose/common.h Normal file
View File

@@ -0,0 +1,40 @@
#ifndef _POSE_COMMON_C_H_
#define _POSE_COMMON_C_H_
#include "../common/common.h"
#ifdef __cplusplus
#include "common/common.hpp"
extern "C" {
#endif
#ifdef __cplusplus
typedef ov::Keypoint Keypoint;
typedef ov::ROI ROI;
#else
typedef struct Keypoint {
Point2f p;
float prob;
} Keypoint;
typedef struct ROI {
Rect rect;
unsigned char *data;
float score;
} ROI;
#endif
typedef struct ROIVector {
ROI* items;
int length;
} ROIVector;
typedef struct KeypointVector {
Keypoint* points;
int length;
} KeypointVector;
void FreeKeypointVector(KeypointVector *p);
void FreeROIVector(ROIVector *p);
#ifdef __cplusplus
}
#endif
#endif // !_POSE_COMMON_C_H_

View File

@@ -0,0 +1,15 @@
#include "../common.h"
void FreeKeypointVector(KeypointVector *p) {
if (p->points != NULL) {
free(p->points);
p->points = NULL;
}
}
void FreeROIVector(ROIVector *p) {
if (p->items!= NULL) {
free(p->items);
p->items= NULL;
}
}

View File

@@ -0,0 +1,18 @@
#ifndef _POSE_COMMON_H_
#define _POSE_COMMON_H_
#include "../../common/common.h"
namespace ov {
struct Keypoint {
Point2f p;
float prob;
};
struct ROI {
Rect rect;
unsigned char *data;
float score;
};
}
#endif // !_POSE_COMMON_H_

21
src/pose/detecter.h Normal file
View File

@@ -0,0 +1,21 @@
#ifndef _POSE_DETECTER_C_H_
#define _POSE_DETECTER_C_H_
#include "common.h"
#ifdef __cplusplus
#include "detecter/detecter.hpp"
extern "C" {
#endif
typedef void* IDetecter;
IDetecter new_ultralight();
void destroy_detecter(IDetecter d);
int detecter_load_model(IDetecter d, const char* root_path);
int extract_rois(IDetecter d, const unsigned char* rgbdata,
int img_width, int img_height,
ROIVector* rois);
int extract_keypoints(IDetecter d, const ROI* roi,KeypointVector* keypoints);
#ifdef __cplusplus
}
#endif
#endif // !_POSE_DETECTER_C_H_

View File

@@ -0,0 +1,49 @@
#include "../detecter.h"
#include "utralight/utralight.hpp"
IDetecter new_utralight() {
return new ov::Utralight();
}
void destroy_detecter(IDetecter d) {
delete static_cast<ov::Detecter*>(d);
}
int detecter_load_model(IDetecter d, const char *root_path){
return static_cast<ov::Detecter*>(d)->LoadModel(root_path);
}
int extract_rois(IDetecter d, const unsigned char* rgbdata, int img_width, int img_height, ROIVector* rois) {
std::vector<ROI> detected;
int ret = static_cast<ov::Detecter*>(d)->ExtractROIs(rgbdata, img_width, img_height, &detected);
if (ret != 0) {
return ret;
}
rois->length = detected.size();
rois->items = (ROI*)malloc(rois->length * sizeof(ROI));
for (size_t i = 0; i < detected.size(); ++i) {
rois->items[i] = detected[i];
}
return 0;
}
int extract_keypoints(IDetecter d, const ROI* roi, KeypointVector* keypoints) {
std::vector<Keypoint> points;
int ret = static_cast<ov::Detecter*>(d)->ExtractKeypoints(*roi, &points);
if (ret != 0) {
return ret;
}
keypoints->length = points.size();
keypoints->points = (Keypoint*)malloc(keypoints->length * sizeof(Keypoint));
for (size_t i = 0; i < points.size(); ++i) {
keypoints->points[i] = points[i];
}
return 0;
}
namespace ov{
Detecter* UtralightFactory::CreateDetecter() {
return new Utralight();
}
}

View File

@@ -0,0 +1,31 @@
#ifndef _POSE_DETECTER_H_
#define _POSE_DETECTER_H_
#include "../common/common.hpp"
#include <vector>
namespace ov {
class Detecter {
public:
virtual ~Detecter(){};
virtual int LoadModel(const char* root_path) = 0;
virtual int ExtractROIs(const unsigned char* rgbadata,
int img_width, int img_height,
std::vector<ROI>* rois) = 0;
virtual int ExtractKeypoints(const ROI& roi, std::vector<Keypoint>* keypoints) = 0;
};
class DetecterFactory {
public:
virtual Detecter* CreateDetecter() = 0;
virtual ~DetecterFactory() {};
};
class UtralightFactory: public DetecterFactory {
public:
UtralightFactory() {}
~UtralightFactory() {}
Detecter* CreateDetecter();
};
}
#endif // !_POSE_DETECTER_H

View File

@@ -0,0 +1,166 @@
#include "utralight.hpp"
#include <string>
#ifdef OV_VULKAN
#include "gpu.h"
#endif // OV_VULKAN
namespace ov {
Utralight::Utralight() {
roi_net_ = new ncnn::Net();
pose_net_ = new ncnn::Net();
initialized_ = false;
#ifdef OV_VULKAN
roi_net_->opt.use_vulkan_compute = true;
pose_net_->opt.use_vulkan_compute = true;
#endif // OV_VULKAN
}
Utralight::~Utralight() {
roi_net_->clear();
pose_net_->clear();
}
int Utralight::LoadModel(const char * root_path) {
std::string roi_param_file = std::string(root_path) + "/roi.param";
std::string roi_bin_file = std::string(root_path) + "/roi.bin";
if (roi_net_->load_param(roi_param_file.c_str()) == -1 ||
roi_net_->load_model(roi_bin_file.c_str()) == -1) {
return 10000;
}
std::string pose_param_file = std::string(root_path) + "/pose.param";
std::string pose_bin_file = std::string(root_path) + "/pose.bin";
if (pose_net_->load_param(pose_param_file.c_str()) == -1 ||
pose_net_->load_model(pose_bin_file.c_str()) == -1) {
return 10000;
}
initialized_ = true;
return 0;
}
int Utralight::ExtractROIs(const unsigned char* rgbdata,
int img_width, int img_height,
std::vector<ROI>* rois) {
if (!initialized_) {
return 10000;
}
if (rgbdata == 0){
return 10001;
}
ncnn::Mat in = ncnn::Mat::from_pixels_resize(rgbdata,
ncnn::Mat::PIXEL_RGB, img_width, img_height, 320, 320);
//数据预处理
const float mean_vals[3] = {0.f, 0.f, 0.f};
const float norm_vals[3] = {1/255.f, 1/255.f, 1/255.f};
in.substract_mean_normalize(mean_vals, norm_vals);
ncnn::Extractor ex = roi_net_->create_extractor();
ex.set_num_threads(4);
ex.input("data", in);
ncnn::Mat out;
ex.extract("output", out);
for (int i = 0; i < out.h; i++)
{
printf("==================================\n");
float x1, y1, x2, y2, score, label;
float pw,ph,cx,cy;
const float* values = out.row(i);
x1 = values[2] * img_width;
y1 = values[3] * img_height;
x2 = values[4] * img_width;
y2 = values[5] * img_height;
pw = x2-x1;
ph = y2-y1;
cx = x1+0.5*pw;
cy = y1+0.5*ph;
x1 = cx - 0.7*pw;
y1 = cy - 0.6*ph;
x2 = cx + 0.7*pw;
y2 = cy + 0.6*ph;
score = values[1];
label = values[0];
//处理坐标越界问题
if(x1<0) x1=0;
if(y1<0) y1=0;
if(x2<0) x2=0;
if(y2<0) y2=0;
if(x1>img_width) x1=img_width;
if(y1>img_height) y1=img_height;
if(x2>img_width) x2=img_width;
if(y2>img_height) y2=img_height;
//截取人体ROI
//printf("x1:%f y1:%f x2:%f y2:%f\n",x1,y1,x2,y2);
Rect rect = Rect(x1, y1, x2-x1, y2-y1);
size_t total_size = rect.width * rect.height * 3 * sizeof(unsigned char);
unsigned char* cropdata = (unsigned char*)malloc(total_size);
const unsigned char *start_ptr = rgbdata;
for(size_t i = 0; i < rect.height; ++i) {
const unsigned char* srcCursor = start_ptr + ((i + rect.y) * img_width + rect.x) * 3;
unsigned char* dstCursor = cropdata + i * rect.width * 3;
memcpy(dstCursor, srcCursor, sizeof(unsigned char) * 3 * rect.width);
}
ROI roi;
roi.rect = rect;
roi.data = cropdata;
roi.score = score;
rois->push_back(roi);
free(cropdata);
}
return 0;
}
int Utralight::ExtractKeypoints(const ROI& roi, std::vector<Keypoint>* keypoints) {
keypoints->clear();
int w = roi.rect.width;
int h = roi.rect.height;
ncnn::Mat in = ncnn::Mat::from_pixels_resize(roi.data, ncnn::Mat::PIXEL_RGB, w, h, 192, 256);
//数据预处理
const float mean_vals[3] = {0.485f * 255.f, 0.456f * 255.f, 0.406f * 255.f};
const float norm_vals[3] = {1 / 0.229f / 255.f, 1 / 0.224f / 255.f, 1 / 0.225f / 255.f};
in.substract_mean_normalize(mean_vals, norm_vals);
ncnn::Extractor ex = pose_net_->create_extractor();
ex.set_num_threads(4);
ex.input("data", in);
ncnn::Mat out;
ex.extract("hybridsequential0_conv7_fwd", out);
for (int p = 0; p < out.c; p++)
{
const ncnn::Mat m = out.channel(p);
float max_prob = 0.f;
int max_x = 0;
int max_y = 0;
for (int y = 0; y < out.h; y++)
{
const float* ptr = m.row(y);
for (int x = 0; x < out.w; x++)
{
float prob = ptr[x];
if (prob > max_prob)
{
max_prob = prob;
max_x = x;
max_y = y;
}
}
}
Keypoint keypoint;
keypoint.p = Point2f(max_x * w / (float)out.w+roi.rect.x, max_y * h / (float)out.h+roi.rect.y);
keypoint.prob = max_prob;
keypoints->push_back(keypoint);
}
return 0;
}
}

View File

@@ -0,0 +1,31 @@
#ifndef _POSE_UTRALIGHT_H_
#define _POSE_UTRALIGHT_H_
#include "../detecter.hpp"
#include <vector>
#include "net.h"
namespace ov {
class Utralight : public Detecter {
public:
Utralight();
~Utralight();
int LoadModel(const char* root_path);
int ExtractROIs(const unsigned char* rgbadata,
int img_width, int img_height,
std::vector<ROI>* rois);
int ExtractKeypoints(const ROI& roi,
std::vector<Keypoint>* keypoints);
private:
ncnn::Net* roi_net_;
ncnn::Net* pose_net_;
bool initialized_;
};
}
#endif // !_POSE_MOBILEFACENET_H_