#include "sfe_toolkit/sfe_core.h"
#include "sfe_toolkit/sfe_face.h"
#include <regex>
#include <vector>
#include "solvers.h"
#include "utils.hpp"
#include <unordered_map>
std::string
gallery =
"./assets/face/entities/";
std::string
image_probe =
"assets/face/images/obiwan0.png";
size_t &recommended_width,
size_t &recommended_height) {
std::smatch width_height;
std::regex(".*w([0-9]+)h([0-9]+).*"))) {
recommended_width = std::stoi(width_height[1]);
recommended_height = std::stoi(width_height[2]);
} else {
utils::checkError(error);
recommended_width = input_size.width;
recommended_height = input_size.height;
};
}
{
utils::checkError(error);
size_t recommended_width{};
size_t recommended_height{};
recommended_height);
&resized_image);
utils::checkError(error);
}
size_t detection_count = 1;
{
&detected_face, &detection_count);
utils::checkError(error);
if (detection_count == 0) {
throw std::runtime_error("No face detected in the image.");
}
}
{
landmarks.data());
utils::checkError(error);
}
{
error =
landmarks.data(), &face_template);
utils::checkError(error);
}
return face_template;
}
std::cout << "Help: Usage of the program." << std::endl;
std::cout << "Options:" << std::endl;
std::cout << "-h: Display help." << std::endl;
std::cout << "-p: Probe image file." << std::endl;
std::cout << "-g: Path to folder with entities." << std::endl;
std::cout << "-d: Path to detector solver." << std::endl;
std::cout << "-l: Path to landmarks solver." << std::endl;
std::cout << "-e: Path to extraction solver." << std::endl;
std::cout << "-t: Detection threshold. <0,1>" << std::endl;
std::cout << "-i: Identification threshold. <0,1>" << std::endl;
std::cout << "-m: Minimal face size in pixels to detect." << std::endl;
std::cout << "-x: Max face size in pixels to detect." << std::endl;
}
int main(
int argc,
char *argv[]) {
{
std::unordered_map<std::string, std::string> args;
for (int i = 1; i < argc; ++i) {
std::string arg = argv[i];
if (arg[0] == '-') {
if (arg == "-h") {
return 0;
}
if (i + 1 < argc && argv[i + 1][0] != '-') {
args[arg] = argv[++i];
} else {
std::cerr << "Option " << arg << " requires a value." << std::endl;
return 1;
}
} else {
std::cerr << "Unknown option: " << arg << std::endl;
return 1;
}
}
if (args.count("-p"))
if (args.count("-g"))
if (args.count("-d"))
if (args.count("-l"))
if (args.count("-e"))
if (args.count("-t"))
if (args.count("-i"))
if (args.count("-m"))
if (args.count("-x"))
utils::printFormatted("EXAMPLE PARAMETERS");
std::cout <<
"Probe image: " <<
image_probe << std::endl;
std::cout <<
"Entities folder: " <<
gallery << std::endl;
<< std::endl;
std::cout <<
"Min face size [px]: " <<
face_size_min << std::endl;
std::cout <<
"Max face size [px]: " <<
face_size_max << std::endl;
<< std::endl;
}
utils::printToolkitInfo();
{
utils::checkError(error);
utils::checkError(error);
utils::checkError(error);
}
{
utils::printFormatted("PROBE TEMPLATE EXTRACTION");
landmarks_solver, template_solver);
std::cout << "Probe face template extracted." << std::endl;
}
std::vector<SFEFaceTemplate> gallery_face_templates = {};
std::vector<SFEEntity> enitity_pairs = {};
{
utils::printFormatted("ENTITIES TEMPLATE EXTRACTION");
auto folder_names = utils::getFiles(
gallery);
for (auto folder_name : folder_names) {
if (folder_name.find(".jpg") != std::string::npos ||
folder_name.find(".png") != std::string::npos) {
continue;
}
auto entity = utils::generateEntity();
auto entity_folder =
gallery + folder_name +
"/";
std::cout << "Folder: " << entity_folder << ", entity UUID: ["
<< static_cast<int>(entity.uuid[0]) << ", "
<< static_cast<int>(entity.uuid[1]) << "..."
<< static_cast<int>(entity.uuid[15]) << "]" << std::endl;
auto image_names = utils::getFiles(entity_folder);
for (auto image_name : image_names) {
image_path, detector_solver, landmarks_solver, template_solver);
gallery_face_templates.push_back(face_template);
enitity_pairs.push_back(entity);
}
}
}
size_t candidate_count = 1;
std::vector<SFEEntityIdentificationCandidate> results(candidate_count);
int best_candidate_index = -1;
{
utils::printFormatted("1:N IDENTIFICATION WITH ENTITIES");
&probe_face_template, gallery_face_templates.data(),
enitity_pairs.data(), gallery_face_templates.size(),
utils::checkError(error);
if (candidate_count == 0) {
std::cout << "No candidates found. Exiting.." << std::endl;
return 0;
}
std::cout << std::endl;
std::cout << "Found " << results.size() << " candidates " << std::endl;
for (int i = 0; i < results.size(); i++) {
std::cout << "Index: " << i << ", Score: " << results[i].score
<< std::endl;
std::cout << "Entity UUID: ["
<< static_cast<int>(results[i].entity.uuid[0]) << ", "
<< static_cast<int>(results[i].entity.uuid[1]) << "..."
<< static_cast<int>(results[i].entity.uuid[15]) << "]"
<< std::endl;
}
}
utils::printFormatted("FINISHED");
}
float identification_threshold
void getRecommendedImageSize(const std::string &solver_face_detect, SFEImage &image, const size_t face_size_min, const size_t face_size_max, size_t &recommended_width, size_t &recommended_height)
Get recommended image size for face detection.
std::string solver_face_detect
Solvers to use in example, the defaults are filled in by CMake.
float detection_threshold
const auto SOLVER_PARAMETERS
size_t face_size_min
Required size of the face to be detected.
std::string solver_face_landmarks
std::string solver_face_template
SFEFaceTemplate extractTemplate(std::string image_path, SFESolver &detector_solver, SFESolver &landmarks_solver, SFESolver &template_solver)
void sfeSolverFree(SFESolver solver)
Free memory associated with SFESolver.
SFEError sfeImageResize(SFEImageView image, size_t width, size_t height, SFEImage *out_image)
Resize image.
void * SFESolver
Solver provides an abstract interface over inference models and engines.
void * SFEError
Error type used to hold optional error message.
void sfeImageFree(SFEImage image)
Free memory associated with SFEImage.
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 sfeDetect(SFESolver solver, SFEImageView image, float threshold, SFEDetection *out_detections, size_t *in_out_detection_count)
Detect objects in the source image using unified detection API.
SFEError sfeFaceDetectInputSize(SFEImageView image, SFEFaceDetectionAccuracyType detection_mode, size_t min_face_size, size_t max_face_size, SFEDetectionInputSize *out_input_size)
Calculation of recommended input image width and height according to desired minimal and maximal size...
#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 sfeFaceEntityIdentify(SFEFaceTemplate *probe_face_template, SFEFaceTemplate *templates_gallery, SFEEntity *entities_gallery, size_t gallery_size, float matching_score_threshold, SFEEntityIdentificationCandidate *out_candidates, size_t *in_out_candidates_count, size_t thread_count)
Get an ordered array of SFEEntityIdentificationCandidate from tested template best matches of probe t...
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.
Core detection - tagged union containing all detection types.
Raw owned raster image representation, HWC|BGR order.