SmartFace Embedded Toolkit  4.2.1
Loading...
Searching...
No Matches
example_palm_liveness.cpp File Reference
#include "sfe_toolkit/sfe_core.h"
#include "sfe_toolkit/sfe_palm.h"
#include <iomanip>
#include <regex>
#include <sstream>
#include <vector>
#include "annotate.hpp"
#include "solvers.h"
#include "utils.hpp"
#include <unordered_map>

Go to the source code of this file.

Functions

void printPalmDetectionInfo (SFEDetection &detected_palm)
 
void printHelp ()
 
int main (int argc, char *argv[])
 Main fuction is used to parse command line arguments.
 

Variables

std::string image_probe = "assets/palm/palm_id1_r1.jpg"
 
std::string solver_palm_detect = SOLVER_PALM_DETECT
 Solvers to use in example, the defaults are filled in by CMake.
 
const auto SOLVER_PARAMETERS = std::vector<SFESolverParameter>{}
 
float detection_threshold = 0.1f
 

Function Documentation

◆ main()

int main ( int  argc,
char *  argv[] 
)

Main fuction is used to parse command line arguments.

[Image Load]

[Image Load]

[Palm Detect]

[Palm Detect]

[Palm Liveness]

[Palm Liveness]

Definition at line 53 of file example_palm_liveness.cpp.

53 {
54
55 { // STAGE: 0 Parse command line arguments
56 // Map to store argument values
57 std::unordered_map<std::string, std::string> args;
58
59 // Parse command line arguments
60 for (int i = 1; i < argc; ++i) {
61 std::string arg = argv[i];
62 if (arg[0] == '-') {
63 if (arg == "-h") {
64 printHelp();
65 return 0;
66 }
67 // Check if there's a next argument and it isn't another option
68 if (i + 1 < argc && argv[i + 1][0] != '-') {
69 args[arg] = argv[++i];
70 } else {
71 std::cerr << "Option " << arg << " requires a value." << std::endl;
72 return 1;
73 }
74 } else {
75 std::cerr << "Unknown option: " << arg << std::endl;
76 return 1;
77 }
78 }
79
80 // Assign values to variables based on parsed arguments
81 if (args.count("-p"))
82 image_probe = args["-p"];
83 if (args.count("-d"))
84 solver_palm_detect = args["-d"];
85 if (args.count("-i"))
86 solver_palm_liveness = args["-i"];
87 if (args.count("-t"))
88 detection_threshold = std::stof(args["-t"]);
89
90 utils::printFormatted("PARAMETERS");
91 // Print resource names
92 std::cout << "Probe image: " << image_probe << std::endl;
93
94 // Print solver names
95 std::cout << "Palm detection solver: " << solver_palm_detect << std::endl;
96 std::cout << "Palm liveness solver: " << solver_palm_liveness << std::endl;
97
98 // Print other options
99 std::cout << "Detection threshold: " << detection_threshold << std::endl;
100 }
101
102 utils::printToolkitInfo();
103
104 SFEError error{};
105
106 SFESolver detector_solver{};
107 DEFER(sfeSolverFree(detector_solver));
108 SFESolver liveness_solver{};
109 DEFER(sfeSolverFree(liveness_solver));
110 { // STAGE 1: loading solvers
111 utils::printFormatted("LOADING solvers");
112 // Initialize palm detection solver
113 error = sfeSolverCreate(
115 SOLVER_PARAMETERS.size(), &detector_solver);
116 utils::checkError(error);
117
118 // Initialize palm liveness solver
119 error = sfeSolverCreate(
120 solver_palm_liveness.c_str(), SOLVER_PARAMETERS.data(),
121 SOLVER_PARAMETERS.size(), &liveness_solver);
122 utils::checkError(error);
123 }
124
125 SFEImage image{};
126 DEFER(sfeImageFree(image));
127 { // STAGE 2: Load image
128
129 utils::printFormatted("PALM DETECTION");
131 // Load image data from file
132 auto image_data = utils::readFile(image_probe);
133
134 // Decode image from data
135 error = sfeImageDecode(image_data.data(), image_data.size(), &image);
136 utils::checkError(error);
138 }
140 SFEDetection detected_palm = {};
141 { // STAGE 3: Detect palm in the image
142 size_t detection_count = 1;
143 // Detect palm in the image
144 error = sfeDetect(detector_solver, image, detection_threshold,
145 &detected_palm, &detection_count);
146 utils::checkError(error);
147
148 if (detection_count == 0) {
149 std::cout << "No palm detected in the probe image." << std::endl;
150 return 0;
151 } else {
152 std::cout << "Found " << detection_count
153 << " palm(s) in the probe image. Using the palm with highest "
154 "confidence."
155 << std::endl;
156 }
157 }
159
160 printPalmDetectionInfo(detected_palm);
161
163 float liveness_score = 0.0f;
164 { // STAGE 4: Liveness check
165 utils::printFormatted("LIVENESS CHECK");
166 error = sfePalmLivenessPassive(liveness_solver, image, &detected_palm,
167 &liveness_score);
168 utils::checkError(error);
169 }
171 { // STAGE 5: Print the liveness score
172 std::cout << "Liveness score is " << liveness_score;
173 // Recommended threshold for liveness score, see EER threshold for palm liveness in the documentation
174 static const float LIVENESS_THRESHOLD = 0.8189f;
175 if (liveness_score < LIVENESS_THRESHOLD) {
176 std::cout << " which is below " << LIVENESS_THRESHOLD
177 << " threshold. Palm is spoof." << std::endl;
178 } else {
179 std::cout << " which is above " << LIVENESS_THRESHOLD
180 << " threshold. Palm is genuine." << std::endl;
181 }
182 }
183
184 { // STAGE 6: Annotate the image
185 // Render bounding box
186 std::stringstream label;
187 label << "Palm" << std::fixed << std::setprecision(2)
188 << " d:" << detected_palm.confidence << " l:" << liveness_score;
189
190 annotate::labelBox(image, label.str(), detected_palm.bounding_box,
191 annotate::WHITE, annotate::GREEN);
192
193 // Save annotated image
194 size_t size = image.width * image.height * 3;
195 auto png_file = std::vector<unsigned char>(size);
196 error = sfeImageEncode(image, SFE_IMAGE_FORMAT_PNG, png_file.data(), &size);
197 utils::checkError(error);
198 png_file.resize(size);
199 utils::saveFile("palm_liveness.png", png_file);
200
201 std::cout << std::endl;
202 std::cout << "Annotated image saved to palm_liveness.png" << std::endl;
203 }
204 utils::printFormatted("FINISHED");
205}
void printHelp()
std::string image_probe
float detection_threshold
const auto SOLVER_PARAMETERS
std::string solver_palm_detect
Solvers to use in example, the defaults are filled in by CMake.
void printPalmDetectionInfo(SFEDetection &detected_palm)
void sfeSolverFree(SFESolver solver)
Free memory associated with SFESolver.
void * SFESolver
Solver provides an abstract interface over inference models and engines.
Definition sfe_core.h:102
void * SFEError
Error type used to hold optional error message.
Definition sfe_core.h:97
void sfeImageFree(SFEImage image)
Free memory associated with SFEImage.
@ SFE_IMAGE_FORMAT_PNG
Portable Network Graphics format.
Definition sfe_core.h:53
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 sfePalmLivenessPassive(SFESolver solver, SFEImageView image, const SFEDetection *detection, float *out_liveness_score)
Passive liveness score calculation.
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)
Raw owned raster image representation, HWC|BGR order.
Definition sfe_core.h:70

◆ printHelp()

void printHelp ( )

Definition at line 42 of file example_palm_liveness.cpp.

42 {
43 std::cout << "Help: Usage of the program." << std::endl;
44 std::cout << "Options:" << std::endl;
45 std::cout << "-h: Display help." << std::endl;
46 std::cout << "-p: Probe image file." << std::endl;
47 std::cout << "-d: Path to detector solver." << std::endl;
48 std::cout << "-i: Path to liveness solver." << std::endl;
49 std::cout << "-t: Palm detection threshold. <0,1>" << std::endl;
50}

◆ printPalmDetectionInfo()

void printPalmDetectionInfo ( SFEDetection &  detected_palm)
inline
Examples
example_palm_attributes.cpp, and example_palm_liveness.cpp.

Definition at line 29 of file example_palm_liveness.cpp.

29 {
30 std::cout << "SFEDetection{ " << std::endl;
31 std::cout << " confidence: " << detected_palm.confidence << std::endl;
32 std::cout << " SFEBoundingBox{ " << std::endl;
33 std::cout << " x: " << detected_palm.bounding_box.x << std::endl;
34 std::cout << " y: " << detected_palm.bounding_box.y << std::endl;
35 std::cout << " width: " << detected_palm.bounding_box.width << std::endl;
36 std::cout << " height: " << detected_palm.bounding_box.height << std::endl;
37 std::cout << " }" << std::endl;
38 std::cout << " }" << std::endl;
39 std::cout << std::endl;
40}
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>

Variable Documentation

◆ detection_threshold

float detection_threshold = 0.1f

Definition at line 27 of file example_palm_liveness.cpp.

◆ image_probe

std::string image_probe = "assets/palm/palm_id1_r1.jpg"

Definition at line 17 of file example_palm_liveness.cpp.

◆ solver_palm_detect

std::string solver_palm_detect = SOLVER_PALM_DETECT

Solvers to use in example, the defaults are filled in by CMake.

Definition at line 20 of file example_palm_liveness.cpp.

◆ SOLVER_PARAMETERS

const auto SOLVER_PARAMETERS = std::vector<SFESolverParameter>{}

Definition at line 25 of file example_palm_liveness.cpp.