SmartFace Embedded Toolkit  4.2.1
Loading...
Searching...
No Matches
example_person_attributes.cpp
Go to the documentation of this file.
1#include <sstream>
2#include <iomanip>
3#include <vector>
4#include <algorithm>
5
6#include <sfe_toolkit/sfe_core.h>
7#include <sfe_toolkit/sfe_object.h>
8#include <sfe_toolkit/sfe_person.h>
9
10#include "utils.hpp"
11#include "solvers.h"
12#include "annotate.hpp"
13#include "strings.hpp"
14
15// Solver parameters, we are using ONNX Runtime CPU backend
16const auto SOLVER_PARAMETERS = std::vector<SFESolverParameter>{
17 SFESolverParameter { "intra_threads", "4" },
18};
19
20std::string image_path = "assets/person/person_attributes.jpg";
21std::string solver_object_detect = SOLVER_OBJECT_DETECT;
22std::string solver_person_attributes = SOLVER_PERSON_ATTRIBUTES;
23std::string solver_person_pose = SOLVER_PERSON_POSE;
24
25int main() {
26 SFEError error;
27
28 SFEImage image{};
29 DEFER(sfeImageFree(image));
30 { // STAGE 1: Load Image
31 auto encoded_image = utils::readFile(image_path);
32 error = sfeImageDecode(encoded_image.data(), encoded_image.size(), &image);
33 utils::checkError(error);
34
35 std::cout << "Image size: " << image.width << "x" << image.height << std::endl;
36 }
37
38 std::vector<SFEDetection> detections(10);
39 { // STAGE 2: Run object detection
40 // Initialize detection solver
41 SFESolver detection_solver{};
42 DEFER(sfeSolverFree(detection_solver));
43 error = sfeSolverCreate(solver_object_detect.c_str(), SOLVER_PARAMETERS.data(), SOLVER_PARAMETERS.size(), &detection_solver);
44 utils::checkError(error);
45
46 // Run detection for up to 10 objects
47 size_t detection_count = detections.size();
48 float detection_threshold = 0.3;
49 error = sfeDetect(detection_solver,
50 image,
52 detections.data(), &detection_count);
53 utils::checkError(error);
54 detections.resize(detection_count);
55
56 std::cout << "Detected " << detection_count << " objects" << std::endl;
57 }
58
59 std::vector<size_t> detection_classes;
60 { // STAGE 3: Check for best detection classes
61 for (size_t i = 0; i < detections.size(); i++) {
62 auto& detection = detections[i];
63 size_t best_class_index = 0;
64 for (size_t c = 0; c < SFE_OBJECT_DETECT; c++) {
65 auto object = detection.modality_data.object.objects[c];
66 if (object.confidence < 0.01) continue;
67 if (object.confidence > detection.modality_data.object.objects[best_class_index].confidence) {
68 best_class_index = c;
69 }
70
71 std::cout << "Detection " << i << " : " << OBJECT_CLASS_NAMES[c] << " confidence: " << std::fixed << std::setprecision(2) << detection.modality_data.object.objects[c].confidence << std::endl;
72 }
73 detection_classes.push_back(best_class_index);
74 }
75 }
76
77 size_t person_index;
78 { // STAGE 4: Find first person in detections
79 auto person_iter = std::find(detection_classes.begin(), detection_classes.end(), SFE_OBJECT_TYPE_PERSON);
80 if (person_iter == detection_classes.end()) {
81 std::cout << "No person detected" << std::endl;
82 return 0;
83 }
84 person_index = std::distance(detection_classes.begin(), person_iter);
85
86 std::cout << "Person detected at index " << person_index << std::endl;
87 }
88
89 std::array<SFEPersonAttribute, SFE_PERSON_ATTRIBUTE_COUNT> person_attributes;
90 { // STAGE 5: Extract person attributes
91 SFESolver attribute_solver{};
92 DEFER(sfeSolverFree(attribute_solver));
93 error = sfeSolverCreate(solver_person_attributes.c_str(), SOLVER_PARAMETERS.data(), SOLVER_PARAMETERS.size(), &attribute_solver);
94 utils::checkError(error);
95
96 // Extract attributes for the detected person
97 error = sfePersonAttributes(attribute_solver, image, &detections[person_index], person_attributes.data());
98 utils::checkError(error);
99
100 for (auto& attribute : person_attributes) {
101 if (attribute.confidence < 0.1) continue;
102 std::cout << "Attribute " << PERSON_ATTRIBUTE_TYPE[attribute.attribute_type] << " confidence: " << std::fixed << std::setprecision(2) << attribute.confidence << std::endl;
103 }
104 }
105
106 std::array<SFEPersonPoseKeypoint, SFE_PERSON_POSE_KEYPOINT_COUNT> person_pose;
107 { // STAGE 6: Person pose estimation
108 SFESolver pose_solver;
109 DEFER(sfeSolverFree(pose_solver));
110 error = sfeSolverCreate(solver_person_pose.c_str(), SOLVER_PARAMETERS.data(), SOLVER_PARAMETERS.size(), &pose_solver);
111 utils::checkError(error);
112
113 // Estimate pose for the detected person
114 error = sfePersonPose(pose_solver, image, &detections[person_index], person_pose.data());
115 utils::checkError(error);
116
117 for (auto& keypoint : person_pose) {
118 if (keypoint.confidence < 0.1) continue;
119 std::cout << "Keypoint " << keypoint.keypoint_type << " confidence: " << std::fixed << std::setprecision(2) << keypoint.confidence << std::endl;
120 }
121 }
122
123 { // END STAGE: Display results
124 for (size_t i = 0; i < detections.size(); i++) {
125 auto& detection = detections[i];
126 auto& class_index = detection_classes[i];
127 auto color = i == person_index ? annotate::GREEN : annotate::RED;
128 // Render bounding box
129 std::stringstream label;
130 label << i << ": " << OBJECT_CLASS_NAMES[class_index] << std::fixed << std::setprecision(2)
131 << " c=" << detection.modality_data.object.objects[class_index].confidence
132 << " d=" << detection.confidence;
133
134 annotate::labelBox(image, label.str(), detection.bounding_box, annotate::WHITE, color);
135 }
136
137 // Render pose points
138 for (auto& keypoint : person_pose) {
139 annotate::circle(image, keypoint.x * image.width, keypoint.y * image.height, 3, annotate::YELLOW);
140 }
141
142 // Save annotated image
143 size_t size = image.width * image.height * 3;
144 auto png_file = std::vector<unsigned char>(size);
145 error = sfeImageEncode(image, SFE_IMAGE_FORMAT_PNG, png_file.data(), &size);
146 utils::checkError(error);
147 png_file.resize(size);
148 utils::saveFile("person_attributes.png", png_file);
149 }
150}
float detection_threshold
std::string solver_person_pose
std::string solver_object_detect
std::string solver_person_attributes
const auto SOLVER_PARAMETERS
std::string image_path
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.
#define SFE_OBJECT_DETECT
Object detection count.
@ SFE_OBJECT_TYPE_PERSON
Raw owned raster image representation, HWC|BGR order.
Definition sfe_core.h:70
Solver parameter used to configure solvers.
Definition sfe_core.h:105