Main fuction is used to parse command line arguments.
144 {
145
146 {
147
148 std::unordered_map<std::string, std::string> args;
149
150
151 for (int i = 1; i < argc; ++i) {
152 std::string arg = argv[i];
153 if (arg[0] == '-') {
154 if (arg == "-h") {
156 return 0;
157 }
158
159 if (i + 1 < argc && argv[i + 1][0] != '-') {
160 args[arg] = argv[++i];
161 } else {
162 std::cerr << "Option " << arg << " requires a value." << std::endl;
163 return 1;
164 }
165 } else {
166 std::cerr << "Unknown option: " << arg << std::endl;
167 return 1;
168 }
169 }
170
171
172 if (args.count("-p"))
174 if (args.count("-g"))
176 if (args.count("-d"))
178 if (args.count("-l"))
180 if (args.count("-e"))
182 if (args.count("-t"))
184 if (args.count("-i"))
186 if (args.count("-m"))
188 if (args.count("-x"))
190
191 utils::printFormatted("EXAMPLE PARAMETERS");
192
193 std::cout <<
"Probe image: " <<
image_probe << std::endl;
194 std::cout <<
"Gallery image: " <<
image_gallery << std::endl;
195
196
199 << std::endl;
201
202
203 std::cout <<
"Min face size [px]: " <<
face_size_min << std::endl;
204 std::cout <<
"Max face size [px]: " <<
face_size_max << std::endl;
207 << std::endl;
208 }
209
210 utils::printToolkitInfo();
211
213
220 {
221 utils::printFormatted("LOADING SOLVERS");
222
226 utils::checkError(error);
227
228
232 utils::checkError(error);
233
234
238 utils::checkError(error);
239 }
240
242 {
243 utils::printFormatted("PROBE TEMPLATE EXTRACTION");
244
247 {
248
250
251
252 error =
sfeImageDecode(image_data.data(), image_data.size(), &image);
253 utils::checkError(error);
254 }
255
257 {
258
259 detectFace(image, detector_solver, detected_face);
260 }
261
263 {
264
265
267 landmarks.data());
268 utils::checkError(error);
269 }
270
272 {
273
274
276 landmarks.data(), &probe_face_template);
277 utils::checkError(error);
278 }
280
281 {
282 utils::printFormatted("PROBE TEMPLATE ATTRIBUTES");
283
287 utils::checkError(error);
288
290 std::cout <<
"Version of the probe template: " << version.
version_major
291 << '.' << version_minor << std::endl;
293 }
294
296 {
297 std::vector<uint8_t> buf(1024);
298 size_t size = buf.size();
300 if (error && size > buf.size()) {
301 buf.resize(size);
302 size = buf.size();
304 }
305 utils::checkError(error);
306
309 utils::checkError(error);
310
311 float roundtrip_score = 0.f;
313 &roundtrip_score);
314 utils::checkError(error);
315 std::cout << "Export/import round-trip match score: " << roundtrip_score
316 << std::endl;
317 }
319 }
320
321 std::vector<std::string> image_paths{};
322 {
323
325
326 for (auto folder_name : folder_names) {
328
329
330 auto image_names = utils::getFiles(gallery_folder);
331
332
333 for (auto image_name : image_names) {
334
335 auto image_path = gallery_folder + image_name;
336
338 }
339 }
340 }
341
342 std::vector<SFEFaceTemplate> gallery_face_templates(image_paths.size());
343 std::vector<SFEDetection> detected_faces(image_paths.size());
344 std::vector<std::array<SFEFaceLandmarks, SFE_FACE_LANDMARK_COUNT>> landmarks(
345 image_paths.size());
346 {
347
348 utils::printFormatted("GALLERY TEMPLATE EXTRACTION");
349
350 for (size_t i = 0; i < image_paths.size(); i++) {
351 std::cout << "Processing image #" << i << ", path: " << image_paths[i]
352 << std::endl;
355 {
356
357 auto image_data = utils::readFile(image_paths[i]);
358
359
360 error =
sfeImageDecode(image_data.data(), image_data.size(), &image);
361 utils::checkError(error);
362 }
363
364 {
365
366 detectFace(image, detector_solver, detected_faces[i]);
367 }
368
369 {
370
371
373 landmarks[i].data());
374 utils::checkError(error);
375 }
376
377 {
378
380 template_solver, image, &detected_faces[i], landmarks[i].data(),
381 &gallery_face_templates[i]);
382 utils::checkError(error);
383 std::cout << "Extracted face template." << std::endl;
384 }
385 std::cout << std::endl;
386 }
387 }
388
390 size_t candidate_count = 1;
391 int best_candidate_index = -1;
392 std::vector<SFETemplateIdentificationCandidate> identification_results(
393 image_paths.size());
394 {
395 utils::printFormatted("1:N IDENTIFICATION");
396
398 &probe_face_template, gallery_face_templates.data(),
400 identification_results.data(), &candidate_count, 4);
401 utils::checkError(error);
402
403
404
405 identification_results.resize(candidate_count);
406
407 std::cout << "Found " << identification_results.size()
408 << " candidates above identification threshold "
410 for (auto &result : identification_results)
411 std::cout << "Template index: #" << result.index
412 << ", score: " << result.score << std::endl;
413
414
415 best_candidate_index = identification_results[0].index;
416 }
418
420 {
421
422 utils::printFormatted("1:1 MATCHING WITH TOP CANDIDATE");
423
424 if (identification_results.size() == 0) {
425 std::cout << "No candidates found above identification threshold "
427 return 0;
428 }
429
430 auto best_candidate_template = gallery_face_templates[best_candidate_index];
431
432 float match_confidence;
434 &match_confidence);
435 utils::checkError(error);
436
437 std::cout << "Matching score of probe template with template index #"
438 << best_candidate_index << ", score: " << match_confidence
439 << std::endl;
440 }
442
443 {
444
445 utils::printFormatted("SAVE FACE CROP AND ANNOTATED IMAGE");
446
447 auto best_face_index = identification_results[0].index;
448
451 {
452
453 auto image_data = utils::readFile(image_paths[best_face_index]);
454
455
456 error =
sfeImageDecode(image_data.data(), image_data.size(), &image);
457 utils::checkError(error);
458 }
459
463 {
464
465
466 float face_size_extension = 2.0f;
468 sfeFaceCrop(image, landmarks[best_face_index].data(),
470 utils::checkError(error);
471
474 << "px, height of cropped image: "
476 }
478
479 {
480 auto png_file = std::vector<unsigned char>();
481 size_t size =
483 png_file.resize(size);
485 png_file.data(), &size);
486 utils::checkError(error2);
487
488 std::cout << "Face crop saved as crop_identified_person.png" << std::endl;
489 utils::saveFile("crop_identified_person.png", png_file);
490 }
491
492 {
493
494 std::stringstream label;
495 label << " D:" << std::fixed << std::setprecision(2)
496 << detected_faces[best_face_index].confidence
497 << " M:" << identification_results[0].score;
498
499 auto color = annotate::RED;
500
501 annotate::labelBox(image, label.str(),
502 detected_faces[best_candidate_index].bounding_box,
503 annotate::WHITE, color);
504
505
506 for (auto &landmark : landmarks[best_face_index]) {
507 auto x = landmark.x * image.width;
508 auto y = landmark.y * image.height;
509 annotate::circle(image, x, y, 3, annotate::YELLOW);
510 }
511
512
513 size_t size = image.width * image.height * 3;
514 auto png_file = std::vector<unsigned char>(size);
516 utils::checkError(error);
517 png_file.resize(size);
518 utils::saveFile("face_identify.png", png_file);
519
520 std::cout << std::endl;
521 std::cout << "Annotated image saved as face_identify.png" << std::endl;
522 }
523 }
524
525 utils::printFormatted("FINISHED");
526}
float identification_threshold
void detectFace(SFEImage &image, SFESolver &detector_solver, SFEDetection &detected_face)
const auto SOLVER_PARAMETERS
std::string solver_face_landmarks
std::string solver_face_template
std::string image_gallery
void sfeSolverFree(SFESolver solver)
Free memory associated with SFESolver.
void * SFESolver
Solver provides an abstract interface over inference models and engines.
@ SFE_IMAGE_FORMAT_PNG
Portable Network Graphics format.
SFEError sfeImageEncode(SFEImageView image, SFEImageFormat image_format, unsigned char *out_data, size_t *in_out_data_len)
Encode SFEImage into a buffer with specified image_format.
SFEError sfeSolverCreate(const char *solver_file, const SFESolverParameter *solver_parameters, size_t solver_parameters_count, SFESolver *out_solver)
Create new solver from solver file.
SFEError sfeImageDecode(const unsigned char *data, size_t data_len, SFEImage *out_image)
Decode SFEImage from raw image data of various formats. Eg. PNG, JPEG ..
SFEError sfeFaceTemplateIdentify(SFEFaceTemplate *probe_face_template, SFEFaceTemplate *templates_gallery, size_t gallery_size, float matching_score_threshold, SFETemplateIdentificationCandidate *out_candidates, size_t *in_out_candidates_count, size_t thread_count)
Get an ordered array of SFETemplateIdentificationCandidate from tested template best matches of probe...
SFEError sfeFaceTemplateMatch(SFEFaceTemplate *template1, SFEFaceTemplate *template2, float *out_matching_score)
Match two face templates.
#define SFE_FACE_LANDMARK_COUNT
SFEError sfeFaceLandmarks(SFESolver solver, SFEImageView image, const SFEDetection *detection, SFEFaceLandmarks out_face_landmarks[SFE_FACE_LANDMARK_COUNT])
Detect 23 landmarks of the face detected in the area of source image marked with detection.
SFEError sfeFaceCrop(SFEImageView image, SFEFaceLandmarks face_landmarks[SFE_FACE_LANDMARK_COUNT], float face_size_extension, float max_face_size, SFEFaceCrop *out_crop)
Crop the face according the given landmarks, the face size extension and the maximal face size....
SFEError sfeFaceTemplateExport(const SFEFaceTemplate *face_template, uint8_t *bytes, size_t *size)
Export face template to bytes that can be shared between Innovatrics components.
SFEError sfeFaceTemplateImport(const uint8_t *bytes, size_t size, SFEFaceTemplate *out_face_template)
Import face template from bytes; format is auto-detected (iface-template protobuf or raw ICF 522-byte...
SFEError sfeFaceTemplateExtract(SFESolver solver, SFEImageView image, const SFEDetection *detection, const SFEFaceLandmarks face_landmarks[SFE_FACE_LANDMARK_COUNT], SFEFaceTemplate *out_face_template)
Extract template from source image and given face landmarks.
SFEError sfeFaceTemplateVersion(SFEFaceTemplate *face_template, SFEFaceTemplateVersion *out_face_template_version)
Get face template version.
Core detection - tagged union containing all detection types.
SFEImage crop_image
Image of face cropped according the crop_box.
float face_size_extension
Defines the size of the crop as an extension of the detection bounding box.
Face template version struct.
uint8_t version_major
major template version
uint8_t version_minor
minor template version
size_t width
Width of the image in pixels.
size_t height
Height of the image in pixels.