5#include "sfe_toolkit/sfe_core.h"
6#include "sfe_toolkit/sfe_face.h"
12#include "annotate.hpp"
15#include <unordered_map>
41 size_t &recommended_width,
42 size_t &recommended_height) {
51 std::smatch width_height;
53 std::regex(
".*w([0-9]+)h([0-9]+).*"))) {
54 recommended_width = std::stoi(width_height[1]);
55 recommended_height = std::stoi(width_height[2]);
67 SFEFaceDetectionAccuracyType::SFE_FACE_DETECT_ACCURACY_TYPE_ACCURATE,
69 utils::checkError(error);
70 recommended_width = input_size.width;
71 recommended_height = input_size.height;
77 std::cout <<
"SFEDetection{ " << std::endl;
78 std::cout <<
" confidence: " << detected_face.
confidence << std::endl;
79 std::cout <<
" SFEBoundingBox{ " << std::endl;
80 std::cout <<
" x: " << detected_face.
bounding_box.
x << std::endl;
81 std::cout <<
" y: " << detected_face.
bounding_box.
y << std::endl;
84 std::cout <<
" }" << std::endl;
85 std::cout <<
" } " << std::endl;
86 std::cout << std::endl;
90 std::cout <<
"SFEFaceArea{ " << std::endl;
91 std::cout <<
" size: " << face_area.
size <<
" [px]" << std::endl;
92 std::cout <<
" area: " << face_area.
area << std::endl;
93 std::cout <<
" area_in_image: " << face_area.
area_in_image << std::endl;
94 std::cout <<
"}" << std::endl;
95 std::cout << std::endl;
99 std::cout <<
"SFEFaceHeadPose{" << std::endl;
100 std::cout <<
" pitch: " << head_pose.
pitch << std::endl;
101 std::cout <<
" yaw: " << head_pose.
yaw << std::endl;
102 std::cout <<
" roll: " << head_pose.
roll << std::endl;
103 std::cout <<
"} " << std::endl;
104 std::cout << std::endl;
108 std::cout <<
"Face size: " << face_size <<
" [px]" << std::endl;
109 std::cout << std::endl;
113 std::cout <<
"Mask confidence: " << mask_confidence << std::endl;
114 std::cout << std::endl;
119 std::cout <<
"SFEFaceQualityAttributes{" << std::endl;
120 std::cout <<
" sharpness: " << quality_attributes.
sharpness << std::endl;
121 std::cout <<
" brightness: " << quality_attributes.
brightness << std::endl;
122 std::cout <<
" contrast: " << quality_attributes.
contrast << std::endl;
123 std::cout <<
" unique_intensity_levels: "
125 std::cout <<
"} " << std::endl;
126 std::cout << std::endl;
130 std::cout <<
"Help: Usage of the program." << std::endl;
131 std::cout <<
"Options:" << std::endl;
132 std::cout <<
"-h: Display help." << std::endl;
133 std::cout <<
"-p: Probe image file." << std::endl;
134 std::cout <<
"-d: Path to detector solver." << std::endl;
135 std::cout <<
"-l: Path to landmarks solver." << std::endl;
136 std::cout <<
"-i: Path to liveness solver." << std::endl;
137 std::cout <<
"-t: Face detection threshold. <0,1>" << std::endl;
138 std::cout <<
"-m: Minimal face size in pixels to detect." << std::endl;
139 std::cout <<
"-x: Max face size in pixels to detect." << std::endl;
143int main(
int argc,
char *argv[]) {
147 std::unordered_map<std::string, std::string> args;
150 for (
int i = 1; i < argc; ++i) {
151 std::string arg = argv[i];
158 if (i + 1 < argc && argv[i + 1][0] !=
'-') {
159 args[arg] = argv[++i];
161 std::cerr <<
"Option " << arg <<
" requires a value." << std::endl;
165 std::cerr <<
"Unknown option: " << arg << std::endl;
171 if (args.count(
"-p"))
173 if (args.count(
"-d"))
175 if (args.count(
"-l"))
177 if (args.count(
"-i"))
179 if (args.count(
"-t"))
181 if (args.count(
"-m"))
183 if (args.count(
"-x"))
186 utils::printFormatted(
"PARAMETERS");
188 std::cout <<
"Probe image: " <<
image_probe << std::endl;
197 std::cout <<
"Min face size [px]: " <<
face_size_min << std::endl;
198 std::cout <<
"Max face size [px]: " <<
face_size_max << std::endl;
202 utils::printToolkitInfo();
213 utils::printFormatted(
"LOADING solvers");
218 utils::checkError(error);
224 utils::checkError(error);
230 utils::checkError(error);
239 utils::printFormatted(
"FACE DETECTION");
245 error =
sfeImageDecode(image_data.data(), image_data.size(), &image);
246 utils::checkError(error);
249 size_t recommended_width{};
250 size_t recommended_height{};
262 error =
sfeImageResize(image, recommended_width, recommended_height,
264 utils::checkError(error);
270 size_t detection_count = 1;
273 &detected_face, &detection_count);
274 utils::checkError(error);
276 if (detection_count == 0) {
277 std::cout <<
"No face detected in the probe image." << std::endl;
280 std::cout <<
"Found " << detection_count
281 <<
" face(s) in the probe image. Using the face with highest "
296 utils::checkError(error);
303 utils::printFormatted(
"LIVENESS CHECK");
306 utils::checkError(error);
311 std::cout <<
"Liveness score is " << liveness.
score;
313 static const float LIVENESS_THRESHOLD = 0.81f;
314 if (liveness.
score < LIVENESS_THRESHOLD) {
315 std::cout <<
" which is below " << LIVENESS_THRESHOLD
316 <<
" threshold. Face is spoof." << std::endl;
318 std::cout <<
" which is above " << LIVENESS_THRESHOLD
319 <<
" threshold. Face is genuine." << std::endl;
326 float mask_confidence;
331 utils::printFormatted(
"FACE ATTRIBUTES");
334 error =
sfeFaceSize(image, landmarks.data(), &face_size);
335 utils::checkError(error);
340 utils::checkError(error);
344 error =
sfeFaceArea(image, landmarks.data(), &face_area);
345 utils::checkError(error);
350 utils::checkError(error);
356 utils::checkError(error);
371 std::stringstream label;
372 label <<
"Face" << std::fixed << std::setprecision(2)
373 <<
" d:" << detected_face.
confidence <<
" m:" << mask_confidence
374 <<
" l:" << liveness.
score;
376 annotate::labelBox(image, label.str(), detected_face.
bounding_box, annotate::WHITE,
380 for (
auto &landmark : landmarks) {
381 auto x = landmark.x * image.width;
382 auto y = landmark.y * image.height;
383 annotate::circle(image, x, y, 3, annotate::YELLOW);
387 size_t size = image.width * image.height * 3;
388 auto png_file = std::vector<unsigned char>(size);
390 utils::checkError(error);
391 png_file.resize(size);
392 utils::saveFile(
"face_liveness.png", png_file);
394 std::cout << std::endl;
395 std::cout <<
"Annotated image saved to face_liveness.png" << std::endl;
398 utils::printFormatted(
"FINISHED");
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
void printMaskConfidence(float mask_confidence)
std::string solver_face_liveness
void printFaceSize(size_t face_size)
void printFaceHeadPose(SFEFaceHeadPose &head_pose)
void prinFaceAreaInfo(SFEFaceArea &face_area)
void printFaceQualityAttributes(SFEFaceQualityAttributes &quality_attributes)
void printFaceDetectionInfo(SFEDetection &detected_face)
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.
@ 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 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 sfeFaceArea(SFEImageView image, SFEFaceLandmarks face_landmarks[SFE_FACE_LANDMARK_COUNT], SFEFaceArea *out_area)
Get face area.
SFEError sfeFaceSize(SFEImageView image, SFEFaceLandmarks face_landmarks[SFE_FACE_LANDMARK_COUNT], float *face_size)
Get the face size in pixels from the face landmarks and the source image. Face size is defined as a m...
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...
SFEError sfeFaceMaskConfidence(const SFEFaceLandmarks face_landmarks[SFE_FACE_LANDMARK_COUNT], float *out_mask_confidence)
Get confidence from given landmarks if the face is wearing a face mask.
#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 sfeFaceLivenessPassive(SFESolver solver, SFEImageView image, SFEFaceLandmarks face_landmarks[SFE_FACE_LANDMARK_COUNT], SFEFaceLiveness *out_liveness)
Passive liveness score calculation.
SFEError sfeFaceHeadPose(SFEImageView image, SFEFaceLandmarks face_landmarks[SFE_FACE_LANDMARK_COUNT], SFEFaceHeadPose *out_head_pose)
Calculate angle rotations of head towards camera reference frame from given landmarks.
SFEError sfeFaceQualityAttributes(SFEImageView image, SFEFaceLandmarks face_landmarks[SFE_FACE_LANDMARK_COUNT], SFEFaceQualityAttributes *out_quality_attributes)
Calculate face image quality attributes from given source image and landmarks data.
float y
Y coordinate of the top left corner of the bounding box relative to source image size - range <0,...
float width
Width of the bounding box relative to source image size - range <0,1>
float x
X coordinate of the top left corner of the bounding box relative to source image size - range <0,...
float height
Height of the bounding box relative to source image size - range <0,1>
Core detection - tagged union containing all detection types.
SFEBoundingBox bounding_box
Bounding box (common for all detection types)
float confidence
Detection confidence - range <0,1> (common for all detection types)
float area_in_image
size of face area intersected with the whole image and relative to the whole image; value in range <0...
float area
size of face area relative to the whole image; value in range <0,1>
float size
absolute face size
Face head pose struct containing angle rotations of head.
float yaw
Face attribute representing angle rotation of head towards camera reference frame around Y-axis as pe...
float pitch
Face attribute representing angle rotation of head towards camera reference frame around X-axis as pe...
float roll
Face attribute representing angle rotation of head towards camera reference frame around Z-axis as pe...
float score
Normalized passive liveness score - range <0,1>
Face quality attributes struct.
float unique_intensity_levels
Normalized face attribute for evaluating whether an area of face has appropriate number of unique int...
float sharpness
Normalized face attribute for evaluating whether an area of face image is not blurred....
float brightness
Normalized face attribute for evaluating whether an area of face is correctly exposed....
float contrast
Normalized face attribute for evaluating whether an area of face is contrast enough....
Raw owned raster image representation, HWC|BGR order.