forked from IntelRealSense/RealSenseID
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhost-mode.cc
214 lines (176 loc) · 8.49 KB
/
host-mode.cc
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2020-2021 Intel Corporation. All Rights Reserved.
#include "RealSenseID/FaceAuthenticator.h"
#include <iostream>
#include <string>
#include <map>
#include <memory>
#include <string.h>
#include <stdio.h>
// map of user-id->faceprint_pair to demonstrate faceprints feature.
static std::map<std::string, RealSenseID::Faceprints> s_user_faceprint_db;
// Create FaceAuthenticator (after successfully connecting it to the device).
// If failed to connect, exit(1)
std::unique_ptr<RealSenseID::FaceAuthenticator> CreateAuthenticator(const RealSenseID::SerialConfig& serial_config)
{
auto authenticator = std::make_unique<RealSenseID::FaceAuthenticator>();
auto connect_status = authenticator->Connect(serial_config);
if (connect_status != RealSenseID::Status::Ok)
{
std::cout << "Failed connecting to port " << serial_config.port << " status:" << connect_status << std::endl;
std::exit(1);
}
std::cout << "Connected to device" << std::endl;
return authenticator;
}
// extract faceprints for new enrolled user
class EnrollClbk : public RealSenseID::EnrollFaceprintsExtractionCallback
{
std::string _user_id;
public:
EnrollClbk(const char* user_id) : _user_id(user_id)
{
}
void OnResult(const RealSenseID::EnrollStatus status, const RealSenseID::ExtractedFaceprints* faceprints) override
{
std::cout << "on_result: status: " << status << std::endl;
if (status == RealSenseID::EnrollStatus::Success)
{
s_user_faceprint_db[_user_id].data.version = faceprints->data.version;
s_user_faceprint_db[_user_id].data.flags = faceprints->data.flags;
s_user_faceprint_db[_user_id].data.featuresType = faceprints->data.featuresType;
// handle with/without mask vectors properly (if needed).
// set the full data for the enrolled object:
size_t copySize = sizeof(faceprints->data.featuresVector);
static_assert(sizeof(s_user_faceprint_db[_user_id].data.adaptiveDescriptorWithoutMask) == sizeof(faceprints->data.featuresVector), "faceprints sizes does not match");
::memcpy(s_user_faceprint_db[_user_id].data.adaptiveDescriptorWithoutMask, faceprints->data.featuresVector, copySize);
static_assert(sizeof(s_user_faceprint_db[_user_id].data.enrollmentDescriptor) == sizeof(faceprints->data.featuresVector), "faceprints sizes does not match");
::memcpy(s_user_faceprint_db[_user_id].data.enrollmentDescriptor, faceprints->data.featuresVector, copySize);
// mark the withMask vector as not-set because its not yet set!
s_user_faceprint_db[_user_id].data.adaptiveDescriptorWithMask[RSID_INDEX_IN_FEATURES_VECTOR_TO_FLAGS] = RealSenseID::FaVectorFlagsEnum::VecFlagNotSet;
}
}
void OnProgress(const RealSenseID::FacePose pose) override
{
std::cout << "on_progress: pose: " << pose << std::endl;
}
void OnHint(const RealSenseID::EnrollStatus hint) override
{
std::cout << "on_hint: hint: " << hint << std::endl;
}
};
void enroll_faceprints(const RealSenseID::SerialConfig& serial_config, const char* user_id)
{
auto authenticator = CreateAuthenticator(serial_config);
EnrollClbk enroll_clbk {user_id};
auto status = authenticator->ExtractFaceprintsForEnroll(enroll_clbk);
std::cout << "Status: " << status << std::endl << std::endl;
}
// authenticate with faceprints
class FaceprintsAuthClbk : public RealSenseID::AuthFaceprintsExtractionCallback
{
RealSenseID::FaceAuthenticator* _authenticator;
public:
FaceprintsAuthClbk(RealSenseID::FaceAuthenticator* authenticator) : _authenticator(authenticator)
{
}
void OnResult(const RealSenseID::AuthenticateStatus status, const RealSenseID::ExtractedFaceprints* faceprints) override
{
std::cout << "on_result: status: " << status << std::endl;
if (status != RealSenseID::AuthenticateStatus::Success)
{
std::cout << "ExtractFaceprints failed with status " << status << std::endl;
return;
}
RealSenseID::MatchElement scanned_faceprint;
scanned_faceprint.data.version = faceprints->data.version;
scanned_faceprint.data.featuresType = faceprints->data.featuresType;
int32_t vecFlags = (int32_t)faceprints->data.featuresVector[RSID_INDEX_IN_FEATURES_VECTOR_TO_FLAGS];
int32_t opFlags = RealSenseID::FaOperationFlagsEnum::OpFlagAuthWithoutMask;
if(vecFlags == RealSenseID::FaVectorFlagsEnum::VecFlagValidWithMask)
{
opFlags = RealSenseID::FaOperationFlagsEnum::OpFlagAuthWithMask;
}
scanned_faceprint.data.flags = opFlags;
static_assert(sizeof(scanned_faceprint.data.featuresVector) == sizeof(faceprints->data.featuresVector), "faceprints without mask sizes does not match");
::memcpy(scanned_faceprint.data.featuresVector, faceprints->data.featuresVector, sizeof(faceprints->data.featuresVector));
// try to match the resulting faceprint to one of the faceprints stored in the db
RealSenseID::Faceprints updated_faceprint;
std::cout << "\nSearching " << s_user_faceprint_db.size() << " faceprints" << std::endl;
int save_max_score = -1;
int winning_index = -1;
std::string winning_id_str = "";
RealSenseID::MatchResultHost winning_match_result;
RealSenseID::Faceprints winning_updated_faceprints;
// use High by default.
// should be taken from DeviceConfig.
RealSenseID::ThresholdsConfidenceEnum matcher_confidence_level = RealSenseID::ThresholdsConfidenceEnum::ThresholdsConfidenceLevel_High;
int users_index = 0;
for (auto& iter : s_user_faceprint_db)
{
auto& user_id = iter.first;
auto& existing_faceprint = iter.second; // faceprints at the DB
auto& updated_faceprint = existing_faceprint; // updated faceprints
auto match = _authenticator->MatchFaceprints(scanned_faceprint, existing_faceprint, updated_faceprint, matcher_confidence_level);
int current_score = (int)match.score;
// save the best winner that matched.
if (match.success)
{
if(current_score > save_max_score)
{
save_max_score = current_score;
winning_match_result = match;
winning_index = users_index;
winning_id_str = user_id;
winning_updated_faceprints = updated_faceprint;
}
}
users_index++;
} // end of for() loop
if(winning_index >= 0) // we have a winner so declare success!
{
std::cout << "\n******* Match success. user_id: " << winning_id_str << " *******\n" << std::endl;
// apply adaptive-update on the db.
if (winning_match_result.should_update)
{
// apply adaptive update
s_user_faceprint_db[winning_id_str] = winning_updated_faceprints;
std::cout << "DB adaptive apdate applied to user = " << winning_id_str << "." << std::endl;
}
}
else // no winner, declare authentication failed!
{
std::cout << "\n******* Forbidden (no faceprint matched) *******\n" << std::endl;
}
}
void OnHint(const RealSenseID::AuthenticateStatus hint) override
{
std::cout << "on_hint: hint: " << hint << std::endl;
}
void OnFaceDetected(const std::vector<RealSenseID::FaceRect>& faces, const unsigned int ts) override
{
for (auto& face : faces)
{
printf("** Detected face %u,%u %ux%u (timestamp %u)\n", face.x, face.y, face.w, face.h, ts);
}
}
};
void authenticate_faceprints(const RealSenseID::SerialConfig& serial_config)
{
auto authenticator = CreateAuthenticator(serial_config);
FaceprintsAuthClbk clbk(authenticator.get());
// extract faceprints of the user in front of the device
auto status = authenticator->ExtractFaceprintsForAuth(clbk);
if (status != RealSenseID::Status::Ok)
std::cout << "Status: " << status << std::endl << std::endl;
}
int main()
{
#ifdef _WIN32
RealSenseID::SerialConfig config {"COM9"};
#elif LINUX
RealSenseID::SerialConfig config {"/dev/ttyACM0"};
#endif
enroll_faceprints(config, "my-username");
authenticate_faceprints(config);
}