-
Notifications
You must be signed in to change notification settings - Fork 1
/
HeadPoseDetectorMNN.cpp
106 lines (77 loc) · 3.11 KB
/
HeadPoseDetectorMNN.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include "HeadPoseDetectorMNN.h"
#include <MNN/ImageProcess.hpp>
#include <MNN/expr/ExprCreator.hpp>
#define kInputSize 224
#define kOutputSize 66
using namespace MNN::Express;
HeadPoseDetectorMNN::HeadPoseDetectorMNN()
{
//m_interpreter = std::shared_ptr<MNN::Interpreter>(MNN::Interpreter::createFromFile("hopenet_lite.mnn"));
m_interpreter = std::shared_ptr<MNN::Interpreter>(MNN::Interpreter::createFromFile("hopenet_lite_quantized.mnn"));
MNN::ScheduleConfig config;
config.numThread = 1;
config.type = MNN_FORWARD_METAL;
MNN::BackendConfig backendConfig;
backendConfig.precision = MNN::BackendConfig::PrecisionMode::Precision_Low;
config.backendConfig = &backendConfig;
m_session = m_interpreter->createSession(config);
m_tensor = m_interpreter->getSessionInput(m_session, nullptr);
}
HeadPoseDetectorMNN::~HeadPoseDetectorMNN()
{
m_interpreter->releaseModel();
m_interpreter->releaseSession(m_session);
}
bool HeadPoseDetectorMNN::detect(const cv::Mat &rgb, /*out*/double &yaw, /*out*/double &pitch, /*out*/double &roll)
{
if (rgb.empty())
return false;
m_interpreter->resizeTensor(m_tensor, {1, 3, kInputSize, kInputSize});
m_interpreter->resizeSession(m_session);
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 };
std::shared_ptr<MNN::CV::ImageProcess> pretreat(
MNN::CV::ImageProcess::create(MNN::CV::RGB, MNN::CV::RGB, mean_vals, 3, norm_vals, 3));
const int imgWidth = rgb.cols;
const int imgHeight = rgb.rows;
MNN::CV::Matrix trans;
trans.setIdentity();
trans.postScale(1.0f / imgWidth, 1.0f / imgHeight);
trans.postScale(kInputSize, kInputSize);
trans.invert(&trans);
pretreat->setMatrix(trans);
pretreat->convert(rgb.data, imgWidth, imgHeight, rgb.step[0], m_tensor);
m_interpreter->runSession(m_session);
const MNN::Tensor *yawTensor = m_interpreter->getSessionOutput(m_session, "616");
const MNN::Tensor *pitchTensor = m_interpreter->getSessionOutput(m_session, "617");
const MNN::Tensor *rollTensor = m_interpreter->getSessionOutput(m_session, "618");
yaw = calcPoseValue(yawTensor);
pitch = calcPoseValue(pitchTensor);
roll = calcPoseValue(rollTensor);
return true;
}
double HeadPoseDetectorMNN::calcPoseValue(const MNN::Tensor *tensor)
{
if (tensor == nullptr)
return 0;
tensor->getDimensionType();
MNN::Tensor tensorHost(tensor, tensor->getDimensionType());
tensor->copyToHostTensor(&tensorHost);
std::vector<float> vals;
for (int i = 0; i < kOutputSize; i++)
{
vals.push_back(tensorHost.host<float>()[i]);
}
auto input = _Input({1, 66}, NCHW);
auto inputPtr = input->writeMap<float>();
memcpy(inputPtr, vals.data(), vals.size() * sizeof(float));
input->unMap();
auto output = _Softmax(input);
auto predicted = output->readMap<float>();
double result = 0;
for (int i = 0; i < kOutputSize; i++)
{
result += (predicted[i] * i);
}
return result * 3 - 99;
}