254 lines
4.7 KiB
C++
254 lines
4.7 KiB
C++
#include <cmath>
|
|
#include <cstddef>
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "face_engine.h"
|
|
#include "face_config.h"
|
|
|
|
static constexpr std::size_t EMBEDDING_SIZE = 128;
|
|
|
|
static void write_json_string(const std::string& value)
|
|
{
|
|
std::cout << '"';
|
|
|
|
for (unsigned char ch : value) {
|
|
switch (ch) {
|
|
case '"':
|
|
std::cout << "\\\"";
|
|
break;
|
|
|
|
case '\\':
|
|
std::cout << "\\\\";
|
|
break;
|
|
|
|
case '\b':
|
|
std::cout << "\\b";
|
|
break;
|
|
|
|
case '\f':
|
|
std::cout << "\\f";
|
|
break;
|
|
|
|
case '\n':
|
|
std::cout << "\\n";
|
|
break;
|
|
|
|
case '\r':
|
|
std::cout << "\\r";
|
|
break;
|
|
|
|
case '\t':
|
|
std::cout << "\\t";
|
|
break;
|
|
|
|
default:
|
|
if (ch < 0x20) {
|
|
const char* hex = "0123456789abcdef";
|
|
|
|
std::cout
|
|
<< "\\u00"
|
|
<< hex[(ch >> 4) & 0x0f]
|
|
<< hex[ch & 0x0f];
|
|
} else {
|
|
std::cout << static_cast<char>(ch);
|
|
}
|
|
}
|
|
}
|
|
|
|
std::cout << '"';
|
|
}
|
|
|
|
static bool finite_face(const Face& face)
|
|
{
|
|
if (!std::isfinite(face.score) ||
|
|
!std::isfinite(face.x1) ||
|
|
!std::isfinite(face.y1) ||
|
|
!std::isfinite(face.x2) ||
|
|
!std::isfinite(face.y2)) {
|
|
return false;
|
|
}
|
|
|
|
for (const Point& point : face.kps) {
|
|
if (!std::isfinite(point.x) ||
|
|
!std::isfinite(point.y)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (face.embedding.size() != EMBEDDING_SIZE)
|
|
return false;
|
|
|
|
for (float value : face.embedding) {
|
|
if (!std::isfinite(value))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static void write_face_json(
|
|
const Face& face,
|
|
std::size_t face_index)
|
|
{
|
|
const float width = face.x2 - face.x1;
|
|
const float height = face.y2 - face.y1;
|
|
|
|
std::cout << "{";
|
|
|
|
std::cout
|
|
<< "\"face_index\":"
|
|
<< face_index
|
|
<< ",";
|
|
|
|
std::cout
|
|
<< "\"score\":"
|
|
<< face.score
|
|
<< ",";
|
|
|
|
std::cout << "\"bbox\":{";
|
|
|
|
std::cout
|
|
<< "\"x\":"
|
|
<< face.x1
|
|
<< ",";
|
|
|
|
std::cout
|
|
<< "\"y\":"
|
|
<< face.y1
|
|
<< ",";
|
|
|
|
std::cout
|
|
<< "\"width\":"
|
|
<< width
|
|
<< ",";
|
|
|
|
std::cout
|
|
<< "\"height\":"
|
|
<< height;
|
|
|
|
std::cout << "},";
|
|
|
|
std::cout << "\"landmarks\":[";
|
|
|
|
for (int i = 0; i < 5; ++i) {
|
|
if (i != 0)
|
|
std::cout << ",";
|
|
|
|
std::cout
|
|
<< "["
|
|
<< face.kps[i].x
|
|
<< ","
|
|
<< face.kps[i].y
|
|
<< "]";
|
|
}
|
|
|
|
std::cout << "],";
|
|
|
|
std::cout << "\"embedding\":[";
|
|
|
|
for (std::size_t i = 0;
|
|
i < face.embedding.size();
|
|
++i) {
|
|
if (i != 0)
|
|
std::cout << ",";
|
|
|
|
std::cout << face.embedding[i];
|
|
}
|
|
|
|
std::cout << "]";
|
|
|
|
std::cout << "}";
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
if (argc != 2) {
|
|
std::cerr
|
|
<< "Uso: "
|
|
<< argv[0]
|
|
<< " image.jpg\n";
|
|
|
|
return 2;
|
|
}
|
|
|
|
const std::string root =
|
|
FACE_CLUSTERING_ROOT;
|
|
|
|
const std::string scrfd_model =
|
|
root + "/models/SCRFD_500M_KPS_640.rknn";
|
|
|
|
const std::string sface_model =
|
|
root + "/models/face_recognition_sface_2021dec.rknn";
|
|
|
|
FaceEngine engine;
|
|
|
|
if (!engine.init(scrfd_model, sface_model)) {
|
|
std::cerr
|
|
<< "Impossibile inizializzare FaceEngine\n";
|
|
|
|
return 3;
|
|
}
|
|
|
|
std::vector<Face> faces;
|
|
int image_width = 0;
|
|
int image_height = 0;
|
|
|
|
if (!engine.process_image(
|
|
argv[1],
|
|
faces,
|
|
image_width,
|
|
image_height)) {
|
|
std::cerr
|
|
<< "Scansione fallita: "
|
|
<< argv[1]
|
|
<< "\n";
|
|
|
|
return 4;
|
|
}
|
|
|
|
for (std::size_t i = 0; i < faces.size(); ++i) {
|
|
if (!finite_face(faces[i])) {
|
|
std::cerr
|
|
<< "Risultato non valido per face_index="
|
|
<< i
|
|
<< "\n";
|
|
|
|
return 5;
|
|
}
|
|
}
|
|
|
|
std::cout << std::setprecision(9);
|
|
|
|
std::cout << "{";
|
|
|
|
std::cout << "\"image\":{";
|
|
|
|
std::cout << "\"path\":";
|
|
write_json_string(argv[1]);
|
|
|
|
std::cout
|
|
<< ",\"width\":"
|
|
<< image_width
|
|
<< ",\"height\":"
|
|
<< image_height;
|
|
|
|
std::cout << "},";
|
|
|
|
std::cout << "\"faces\":[";
|
|
|
|
for (std::size_t i = 0; i < faces.size(); ++i) {
|
|
if (i != 0)
|
|
std::cout << ",";
|
|
|
|
write_face_json(faces[i], i);
|
|
}
|
|
|
|
std::cout << "]";
|
|
|
|
std::cout << "}\n";
|
|
|
|
return 0;
|
|
}
|