117 lines
4.4 KiB
C++
117 lines
4.4 KiB
C++
|
|
#include "face_pipeline.h"
|
|||
|
|
#include <iostream> // 用于日志
|
|||
|
|
|
|||
|
|
// 构造函数:初始化ORT环境、会话选项,并加载模型
|
|||
|
|
FacePipeline::FacePipeline(const std::string& model_dir)
|
|||
|
|
: m_env(ORT_LOGGING_LEVEL_WARNING, "FaceSDK") // 初始化ORT环境
|
|||
|
|
{
|
|||
|
|
// 配置会话选项
|
|||
|
|
m_session_options.SetIntraOpNumThreads(1); // 移动端通常设置为1
|
|||
|
|
m_session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_ALL);
|
|||
|
|
|
|||
|
|
// 立即加载模型
|
|||
|
|
m_initialized = LoadModels(model_dir);
|
|||
|
|
|
|||
|
|
if (m_initialized) {
|
|||
|
|
std::cout << "FacePipeline initialized successfully." << std::endl;
|
|||
|
|
} else {
|
|||
|
|
std::cerr << "FacePipeline initialization failed." << std::endl;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 析构函数 (由于使用unique_ptr, 资源会自动释放)
|
|||
|
|
FacePipeline::~FacePipeline() {}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// (私有) 加载所有模型
|
|||
|
|
bool FacePipeline::LoadModels(const std::string& model_dir) {
|
|||
|
|
try {
|
|||
|
|
// 【【修正点】】:
|
|||
|
|
// 我们不再使用 to_wstring()。
|
|||
|
|
// 我们直接使用 .c_str(),因为Android API需要 const char*
|
|||
|
|
|
|||
|
|
// 1. 人脸检测
|
|||
|
|
std::string detector_path = model_dir + "/faceboxesv2-640x640.onnx";
|
|||
|
|
m_session_detector = std::make_unique<Ort::Session>(m_env, detector_path.c_str(), m_session_options);
|
|||
|
|
std::cout << "Loaded model: " << detector_path << std::endl;
|
|||
|
|
|
|||
|
|
// 2. 关键点 (Net1)
|
|||
|
|
std::string lm1_path = model_dir + "/face_landmarker_pts5_net1.onnx";
|
|||
|
|
m_session_landmarker1 = std::make_unique<Ort::Session>(m_env, lm1_path.c_str(), m_session_options);
|
|||
|
|
std::cout << "Loaded model: " << lm1_path << std::endl;
|
|||
|
|
|
|||
|
|
// 3. 关键点 (Net2)
|
|||
|
|
std::string lm2_path = model_dir + "/face_landmarker_pts5_net2.onnx";
|
|||
|
|
m_session_landmarker2 = std::make_unique<Ort::Session>(m_env, lm2_path.c_str(), m_session_options);
|
|||
|
|
std::cout << "Loaded model: " << lm2_path << std::endl;
|
|||
|
|
|
|||
|
|
// 4. 人脸识别
|
|||
|
|
std::string rec_path = model_dir + "/face_recognizer.onnx";
|
|||
|
|
m_session_recognizer = std::make_unique<Ort::Session>(m_env, rec_path.c_str(), m_session_options);
|
|||
|
|
std::cout << "Loaded model: " << rec_path << std::endl;
|
|||
|
|
|
|||
|
|
// 5. 旋转分类
|
|||
|
|
std::string rot_path = model_dir + "/model_gray_mobilenetv2_rotcls.onnx";
|
|||
|
|
m_session_rotator = std::make_unique<Ort::Session>(m_env, rot_path.c_str(), m_session_options);
|
|||
|
|
std::cout << "Loaded model: " << rot_path << std::endl;
|
|||
|
|
|
|||
|
|
// 6. 姿态估计 (VAR)
|
|||
|
|
std::string pose_var_path = model_dir + "/fsanet-var.onnx";
|
|||
|
|
m_session_pose_var = std::make_unique<Ort::Session>(m_env, pose_var_path.c_str(), m_session_options);
|
|||
|
|
std::cout << "Loaded model: " << pose_var_path << std::endl;
|
|||
|
|
|
|||
|
|
// 7. 姿态估计 (CONV)
|
|||
|
|
std::string pose_conv_path = model_dir + "/fsanet-conv.onnx";
|
|||
|
|
m_session_pose_conv = std::make_unique<Ort::Session>(m_env, pose_conv_path.c_str(), m_session_options);
|
|||
|
|
std::cout << "Loaded model: " << pose_conv_path << std::endl;
|
|||
|
|
|
|||
|
|
} catch (const Ort::Exception& e) {
|
|||
|
|
// 如果任何模型加载失败,捕获异常
|
|||
|
|
std::cerr << "Error loading models: " << e.what() << std::endl;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
std::cout << "All 7 models loaded successfully." << std::endl;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// L2 归一化 (将在Extract中使用)
|
|||
|
|
void FacePipeline::normalize_l2(std::vector<float>& v) {
|
|||
|
|
double norm = 0.0;
|
|||
|
|
for (float val : v) {
|
|||
|
|
norm += val * val;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (norm > 1e-6) { // 避免除以零
|
|||
|
|
norm = std::sqrt(norm);
|
|||
|
|
for (float& val : v) {
|
|||
|
|
val = static_cast<float>(val / norm);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Extract 方法的桩函数 (我们将在下一步实现)
|
|||
|
|
bool FacePipeline::Extract(const cv::Mat& image, std::vector<float>& feature) {
|
|||
|
|
if (!m_initialized) {
|
|||
|
|
std::cerr << "Pipeline is not initialized." << std::endl;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (image.empty()) {
|
|||
|
|
std::cerr << "Input image is empty." << std::endl;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// --------------------------------------------------
|
|||
|
|
// TODO: 在这里实现完整的 7 模型推理管线
|
|||
|
|
// --------------------------------------------------
|
|||
|
|
|
|||
|
|
// std::cout << "Extract method is not implemented yet." << std::endl;
|
|||
|
|
|
|||
|
|
// 临时填充一个假的特征向量
|
|||
|
|
feature.assign(512, 0.5f);
|
|||
|
|
normalize_l2(feature);
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|