-
Notifications
You must be signed in to change notification settings - Fork 202
Expand file tree
/
Copy pathhuman_face_recognition.cpp
More file actions
165 lines (151 loc) · 5.53 KB
/
human_face_recognition.cpp
File metadata and controls
165 lines (151 loc) · 5.53 KB
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include "human_face_recognition.hpp"
#include <filesystem>
#if CONFIG_HUMAN_FACE_FEAT_MODEL_IN_FLASH_RODATA
extern const uint8_t human_face_feat_espdl[] asm("_binary_human_face_feat_espdl_start");
static const char *path = (const char *)human_face_feat_espdl;
#elif CONFIG_HUMAN_FACE_FEAT_MODEL_IN_FLASH_PARTITION
static const char *path = "human_face_feat";
#else
#if !defined(CONFIG_BSP_SD_MOUNT_POINT)
#define CONFIG_BSP_SD_MOUNT_POINT "/sdcard"
#endif
#endif
namespace human_face_recognition {
MFN::MFN(const char *model_name)
{
#if !CONFIG_HUMAN_FACE_FEAT_MODEL_IN_SDCARD
m_model =
new dl::Model(path, model_name, static_cast<fbs::model_location_type_t>(CONFIG_HUMAN_FACE_FEAT_MODEL_LOCATION));
#else
auto sd_path =
std::filesystem::path(CONFIG_BSP_SD_MOUNT_POINT) / CONFIG_HUMAN_FACE_FEAT_MODEL_SDCARD_DIR / model_name;
m_model = new dl::Model(sd_path.c_str(), fbs::MODEL_LOCATION_IN_SDCARD);
#endif
m_model->minimize();
m_image_preprocessor =
new dl::image::FeatImagePreprocessor(m_model, {127.5, 127.5, 127.5}, {127.5, 127.5, 127.5}, true);
m_postprocessor = new dl::feat::FeatPostprocessor(m_model);
}
} // namespace human_face_recognition
HumanFaceFeat::HumanFaceFeat(model_type_t model_type, bool lazy_load) : m_model_type(model_type)
{
if (lazy_load) {
m_model = nullptr;
} else {
load_model();
}
}
void HumanFaceFeat::load_model()
{
switch (m_model_type) {
case model_type_t::MFN_S8_V1:
#if CONFIG_FLASH_HUMAN_FACE_FEAT_MFN_S8_V1 || CONFIG_HUMAN_FACE_FEAT_MODEL_IN_SDCARD
m_model = new human_face_recognition::MFN("human_face_feat_mfn_s8_v1.espdl");
#else
ESP_LOGE("human_face_feat", "human_face_feat_mfn_s8_v1 is not selected in menuconfig.");
#endif
break;
case model_type_t::MBF_S8_V1:
#if CONFIG_FLASH_HUMAN_FACE_FEAT_MBF_S8_V1 || CONFIG_HUMAN_FACE_FEAT_MODEL_IN_SDCARD
m_model = new human_face_recognition::MBF("human_face_feat_mbf_s8_v1.espdl");
#else
ESP_LOGE("human_face_feat", "human_face_feat_mbf_s8_v1 is not selected in menuconfig.");
#endif
break;
default:
ESP_LOGE("human_face_feat", "Unknown model type.");
}
}
HumanFaceRecognizer::HumanFaceRecognizer(const std::string &db_path,
HumanFaceFeat::model_type_t model_type,
bool lazy_load) :
m_feat(model_type, lazy_load), m_db_path(db_path), m_thr(0.5), m_top_k(1)
{
if (lazy_load) {
m_db = nullptr;
} else {
m_db = new dl::recognition::DataBase(m_db_path, m_feat.get_feat_len());
}
}
HumanFaceRecognizer::~HumanFaceRecognizer()
{
delete m_db;
}
std::vector<dl::recognition::result_t> HumanFaceRecognizer::recognize(const dl::image::img_t &img,
const std::list<dl::detect::result_t> &detect_res)
{
if (!m_db) {
m_db = new dl::recognition::DataBase(m_db_path, m_feat.get_feat_len());
}
std::vector<std::vector<dl::recognition::result_t>> res;
if (detect_res.empty()) {
ESP_LOGW("HumanFaceRecognizer", "Failed to recognize. No face detected.");
return {};
} else if (detect_res.size() == 1) {
auto feat = m_feat.run(img, detect_res.back().keypoint);
return m_db->query_feat(feat, m_thr, m_top_k);
} else {
auto max_detect_res =
std::max_element(detect_res.begin(),
detect_res.end(),
[](const dl::detect::result_t &a, const dl::detect::result_t &b) -> bool {
return a.box_area() > b.box_area();
});
auto feat = m_feat.run(img, max_detect_res->keypoint);
return m_db->query_feat(feat, m_thr, m_top_k);
}
}
esp_err_t HumanFaceRecognizer::enroll(const dl::image::img_t &img, const std::list<dl::detect::result_t> &detect_res)
{
if (!m_db) {
m_db = new dl::recognition::DataBase(m_db_path, m_feat.get_feat_len());
}
if (detect_res.empty()) {
ESP_LOGW("HumanFaceRecognizer", "Failed to enroll. No face detected.");
return ESP_FAIL;
} else if (detect_res.size() == 1) {
auto feat = m_feat.run(img, detect_res.back().keypoint);
return m_db->enroll_feat(feat);
} else {
auto max_detect_res =
std::max_element(detect_res.begin(),
detect_res.end(),
[](const dl::detect::result_t &a, const dl::detect::result_t &b) -> bool {
return a.box_area() > b.box_area();
});
auto feat = m_feat.run(img, max_detect_res->keypoint);
return m_db->enroll_feat(feat);
}
}
esp_err_t HumanFaceRecognizer::clear_all_feats()
{
if (!m_db) {
m_db = new dl::recognition::DataBase(m_db_path, m_feat.get_feat_len());
}
return m_db->clear_all_feats();
}
esp_err_t HumanFaceRecognizer::delete_feat(uint16_t id)
{
if (!m_db) {
m_db = new dl::recognition::DataBase(m_db_path, m_feat.get_feat_len());
}
return m_db->delete_feat(id);
}
esp_err_t HumanFaceRecognizer::delete_last_feat()
{
if (!m_db) {
m_db = new dl::recognition::DataBase(m_db_path, m_feat.get_feat_len());
}
return m_db->delete_last_feat();
}
int HumanFaceRecognizer::get_num_feats()
{
if (!m_db) {
m_db = new dl::recognition::DataBase(m_db_path, m_feat.get_feat_len());
}
return m_db->get_num_feats();
}
HumanFaceFeat *HumanFaceRecognizer::get_feat_model()
{
return &m_feat;
}