#include "sfe_toolkit/sfe_core.h"
#include "sfe_toolkit/sfe_face.h"
#include <ostream>
#include <regex>
#include <vector>
#include <iomanip>
#include <sstream>
#include "annotate.hpp"
#include "solvers.h"
#include "utils.hpp"
#include <unordered_map>
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 {
image,
SFEFaceDetectionAccuracyType::SFE_FACE_DETECT_ACCURACY_TYPE_ACCURATE,
utils::checkError(error);
recommended_width = input_size.width;
recommended_height = input_size.height;
};
}
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 << "-d: Path to detector solver." << std::endl;
std::cout << "-t: Detection 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;
}
{
size_t recommended_width{};
size_t recommended_height{};
recommended_height);
&resized_image);
utils::checkError(error);
}
size_t detection_count = 10;
std::vector<SFEDetection> detected_faces(detection_count);
{
detected_faces.data(), &detection_count);
utils::checkError(error);
if (detection_count == 0) {
std::ostringstream oss;
oss << "Error: No face detected in the image ";
throw std::runtime_error(oss.str());
}
detected_faces.resize(detection_count);
std::cout << "Detected " << detection_count << " faces in the image."
<< std::endl;
}
return detected_faces;
}
for (size_t i = 0; i < 16; ++i) {
os << std::hex << std::setw(2) << std::setfill('0')
<<
static_cast<int>(entity.
uuid[i]);
if (i == 3 || i == 5 || i == 7 || i == 9) {
os << '-';
}
}
os << std::dec;
return os;
}
switch (state) {
os << "NEW";
break;
os << "TRACKED";
break;
os << "LOST";
break;
os << "REMOVED";
break;
default:
os << "UNKNOWN";
break;
}
return os;
}
os <<
"Face ID: " << tracked.
id <<
" UUID: " << tracked.
uuid
<<
" State: " << tracked.
state;
return os;
}
template <typename T>
std::ostream &
operator<<(std::ostream &os,
const std::vector<T> &vec) {
for (auto &item : vec) {
os << item << std::endl;
}
return os;
}
size_t reserved_size = 10;
size_t tracked_faces_count = reserved_size;
size_t lost_faces_count = reserved_size;
size_t removed_faces_count = reserved_size;
std::vector<SFETracked> tracked_faces(tracked_faces_count);
std::vector<SFEEntity> lost_faces(lost_faces_count);
std::vector<SFEEntity> removed_faces(removed_faces_count);
tracked_faces.data(), &tracked_faces_count);
utils::checkError(error);
tracked_faces.resize(tracked_faces_count);
utils::checkError(error);
lost_faces.resize(lost_faces_count);
&removed_faces_count);
utils::checkError(error);
removed_faces.resize(removed_faces_count);
std::cout << "Tracked" << std::endl;
std::cout << tracked_faces;
std::cout << "Lost" << std::endl;
std::cout << lost_faces;
std::cout << "Removed" << std::endl;
std::cout << removed_faces;
}
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("-d"))
if (args.count("-t"))
if (args.count("-m"))
if (args.count("-x"))
utils::printFormatted("EXAMPLE PARAMETERS");
std::cout <<
"Probe image: " <<
image_probe << std::endl;
std::cout <<
"Min face size [px]: " <<
face_size_min << std::endl;
std::cout <<
"Max face size [px]: " <<
face_size_max << std::endl;
}
utils::printToolkitInfo();
{
utils::printFormatted("LOADING SOLVERS");
utils::checkError(error);
}
std::vector<SFEDetection> detected_faces;
{
utils::printFormatted("DETECT FACES");
{
utils::checkError(error);
}
{
}
}
{
utils::printFormatted("TRACK FACES");
utils::checkError(error);
utils::printFormatted("FRAME 1");
frame(detected_faces, tracker);
utils::printFormatted("FRAME 2");
frame(detected_faces, tracker);
detected_faces.clear();
utils::printFormatted("FRAME 3");
frame(detected_faces, tracker);
utils::printFormatted("FRAME 4");
frame(detected_faces, tracker);
}
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::vector< SFEDetection > detectFaces(SFEImage &image, SFESolver &detector_solver)
Detect faces in the image.
void frame(std::vector< SFEDetection > &detections, SFETracker tracker)
Print out the results of the face tracking.
std::ostream & operator<<(std::ostream &os, const SFEEntity &entity)
Print UUID.
void sfeSolverFree(SFESolver solver)
Free memory associated with SFESolver.
SFEError sfeDetectionTrackerCreate(float new_track_threshold, float track_high_threshold, float track_low_threshold, float match_threshold, uint64_t max_time_lost, SFETracker *out_tracker)
Create a new tracker.
SFEError sfeImageResize(SFEImageView image, size_t width, size_t height, SFEImage *out_image)
Resize image.
SFEError sfeDetectionTrackerUpdate(SFETracker tracker, const SFEDetection *detections, size_t detections_count, SFETracked *out_tracked, size_t *in_out_tracked_count)
Update the tracker.
SFEError sfeDetectionTrackerRemoved(SFETracker tracker, SFEEntity *out_entities, size_t *in_out_entities_count)
Get removed entities after update.
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.
void sfeDetectionTrackerFree(SFETracker tracker)
Free the tracker.
SFETrackedState
Tracked state.
@ SFE_TRACKED_STATE_REMOVED
@ SFE_TRACKED_STATE_TRACKED
SFEError sfeDetectionTrackerLost(SFETracker tracker, SFEEntity *out_entities, size_t *in_out_entities_count)
Get lost entities after update.
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.
void * SFETracker
Tracker is a ByteTrack implementation for multi-modal tracking across multiple frames.
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...
Core detection - tagged union containing all detection types.
Entity type, used to group templates for entity identification. This type is compatible with uuid_v4 ...
Raw owned raster image representation, HWC|BGR order.
enum SFETrackedState state
Tracking state.