10 KiB
Face Clustering RK3588
Toolkit C++ riutilizzabile per il rilevamento dei volti, la generazione di embedding facciali e il futuro clustering tramite HDBSCAN su dispositivi Rockchip RK3588.
Il progetto usa RKNN per eseguire sulla NPU:
- SCRFD per il rilevamento dei volti;
- SFace per la generazione degli embedding;
- normalizzazione L2 degli embedding;
- confronto tramite cosine similarity.
Il motore non dipende da database, server o applicazioni specifiche e può
essere integrato in altri programmi C++ oppure utilizzato tramite il
programma face_scan e il relativo output JSON.
Stato del progetto
Funzionalità attualmente disponibili:
- caricamento delle immagini RGB;
- rilevamento facciale tramite SCRFD;
- confidence score per ogni volto;
- bounding box;
- cinque landmark facciali;
- non-maximum suppression;
- allineamento del volto a 112 x 112 pixel;
- generazione di embedding SFace a 128 dimensioni;
- conversione dell'output in float32;
- normalizzazione L2;
- confronto tramite cosine similarity;
- output JSON per applicazioni esterne;
- compilazione tramite Makefile.
Funzionalità pianificate:
- ricerca kNN tramite OpenCL;
- TOPK uguale a 32;
- core distance;
- mutual reachability distance;
- minimum spanning tree;
- condensed tree;
- clustering HDBSCAN;
- assegnazione di un cluster a ogni embedding facciale.
Pipeline facciale
Immagine
|
v
Caricamento RGB
|
v
Resize proporzionale
|
v
Input SCRFD 640 x 640
|
v
SCRFD su RKNN/NPU
|
+-- confidence score
+-- bounding box
+-- cinque landmark
|
v
Non-maximum suppression
|
v
Similarity transform
|
v
Volto allineato 112 x 112
|
v
SFace su RKNN/NPU
|
v
Embedding float32[128]
|
v
Normalizzazione L2
Poiché gli embedding sono normalizzati, la cosine similarity tra due embedding corrisponde al loro prodotto scalare.
Programmi disponibili
face_recognition
face_recognition è il programma dimostrativo con output leggibile
da una persona.
Può analizzare una singola immagine oppure confrontare tutti i volti trovati in due immagini.
Scansione di una singola immagine:
./bin/face_recognition test/image.jpg
Confronto tra due immagini:
./bin/face_recognition \
test/reference.jpg \
test/query.jpg
Per ogni volto il programma mostra:
- confidence score;
- bounding box;
- cinque landmark.
Nel confronto fra due immagini calcola la cosine similarity tra ogni volto della prima immagine e ogni volto della seconda.
La soglia dimostrativa attuale è:
0.363
Questa soglia deve essere validata sul dataset reale dell'applicazione.
face_scan
face_scan è destinato all'integrazione con altri programmi.
Accetta il percorso di una singola immagine:
./bin/face_scan test/image.jpg
Scrive:
- il risultato JSON su standard output;
- errori e diagnostica su standard error;
- exit code 0 in caso di successo;
- exit code diverso da 0 in caso di errore.
Per salvare il risultato:
./bin/face_scan \
test/image.jpg \
> result.json
Per verificare e formattare il JSON:
python3 -m json.tool result.json
Il JSON contiene:
- percorso dell'immagine;
- larghezza e altezza originali;
- elenco dei volti;
- indice sequenziale del volto;
- confidence score;
- bounding box;
- cinque landmark;
- embedding di 128 valori.
Il formato completo è documentato in
docs/json-format.md.
Requisiti
- Linux AArch64;
- Rockchip RK3588 o piattaforma RKNN compatibile;
- compilatore con supporto C++17;
- GNU Make;
- runtime RKNN;
- modello SCRFD in formato RKNN;
- modello SFace in formato RKNN;
- Python 3 per la validazione dei test JSON.
File locali richiesti
Modelli RKNN
Copiare i modelli nella directory models:
models/SCRFD_500M_KPS_640.rknn
models/face_recognition_sface_2021dec.rknn
Runtime RKNN
Copiare la libreria runtime in:
lib/librknnrt.so
I modelli RKNN e la libreria runtime sono esclusi dal repository tramite
.gitignore.
Prima di distribuire questi file, verificare le rispettive condizioni di licenza e redistribuzione.
Compilazione
Dalla directory principale del repository:
make
Compilazione parallela:
make -j"$(nproc)"
I programmi vengono creati in:
bin/face_recognition
bin/face_scan
Per effettuare una compilazione pulita:
make clean
make -j"$(nproc)"
Test
Le immagini di test locali devono essere copiate nella directory
test.
Per eseguire i test automatici:
make test
Il test:
- esegue
face_recognition; - esegue
face_scan; - salva temporaneamente il JSON;
- valida la sintassi JSON tramite Python.
Le immagini sono escluse dal repository tramite .gitignore.
Utilizzo da un altro programma C++
Includere l'header pubblico:
#include "face_engine.h"
Inizializzare il motore:
FaceEngine engine;
if (!engine.init(
"models/SCRFD_500M_KPS_640.rknn",
"models/face_recognition_sface_2021dec.rknn")) {
return 1;
}
Elaborare un'immagine:
std::vector<Face> faces;
int image_width = 0;
int image_height = 0;
if (!engine.process_image(
"image.jpg",
faces,
image_width,
image_height)) {
return 1;
}
Ogni elemento Face contiene:
score, confidence del detector;x1,y1,x2ey2;- cinque elementi
kps; - un embedding L2-normalizzato di 128 elementi.
Esempio di accesso ai risultati:
for (const Face& face : faces) {
std::cout
<< "score=" << face.score
<< " bbox="
<< face.x1 << ","
<< face.y1 << ","
<< face.x2 << ","
<< face.y2
<< "\n";
if (face.embedding.size() == 128) {
std::cout << "Embedding valido\n";
}
}
Utilizzo da altri linguaggi
Programmi Node.js, Python, Java, Dart o scritti in altri linguaggi possono
eseguire bin/face_scan come processo figlio.
Il contratto di integrazione è:
Input percorso di una singola immagine
stdout oggetto JSON completo
stderr diagnostica ed errori
exit 0 scansione completata
exit != 0 errore
Un'immagine valida senza volti produce comunque exit code 0 e:
{
"image": {
"path": "image.jpg",
"width": 1920,
"height": 1080
},
"faces": []
}
Formato dell'embedding
Ogni embedding contiene:
Dimensione logica 128
Tipo nel motore float32
Norma L2 circa 1.0
Valori tutti finiti
Se salvato come sequenza binaria float32:
128 x 4 byte = 512 byte
Questo formato sarà utilizzabile direttamente dai futuri moduli OpenCL.
Struttura del repository
face-clustering-rk3588/
|-- Makefile
|-- README.md
|-- include/
| |-- face_config.h
| |-- face_engine.h
| |-- rknn_api.h
| `-- stb_image.h
|-- src/
| |-- face_engine.cc
| |-- face_recognition.cc
| `-- face_scan.cc
|-- docs/
| |-- architecture.md
| `-- json-format.md
|-- models/
| `-- README.md
|-- lib/
| `-- README.md
|-- test/
| `-- README.md
|-- modules/
| |-- knn-opencl/
| |-- mutual-reachability/
| |-- mst/
| `-- hdbscan/
|-- build/
`-- bin/
Architettura del motore
Il codice è diviso in tre componenti principali.
face_engine
Implementa:
- caricamento immagine;
- resize bilineare;
- conversione float32 e float16;
- inferenza SCRFD;
- decodifica dei risultati;
- non-maximum suppression;
- allineamento facciale;
- inferenza SFace;
- normalizzazione dell'embedding.
face_recognition
Fornisce un programma dimostrativo e permette di verificare visivamente:
- volti rilevati;
- bounding box;
- landmark;
- similarità fra embedding.
face_scan
Fornisce un'interfaccia machine-readable tramite JSON.
Il programma non scrive log su standard output, così l'output può essere letto direttamente con un parser JSON.
Pipeline futura di clustering
Il repository verrà esteso con questa pipeline:
Embedding SFace float32[N][128]
|
v
OpenCL brute-force kNN
|
v
TOPK=32
|
+-- indices[N][32]
`-- scores[N][32]
|
v
Core distance
|
v
Mutual reachability graph
|
v
Minimum spanning tree
|
v
Single linkage hierarchy
|
v
Condensed tree
|
v
HDBSCAN cluster assignment
Moduli futuri
knn-opencl
Calcolerà i 32 vicini più prossimi per ogni embedding usando il prodotto scalare tra vettori L2-normalizzati.
mutual-reachability
Calcolerà:
mrd(i,j) =
max(
core_distance(i),
core_distance(j),
distance(i,j)
)
mst
Costruirà il minimum spanning tree del grafo di mutual reachability.
hdbscan
Produrrà:
- gerarchia single linkage;
- condensed tree;
- stabilità dei cluster;
- assegnazione finale dei cluster;
- identificazione del rumore.
Roadmap
Face detection e embedding completato
Confronto cosine completato
Output JSON completato
Makefile completato
Documentazione completato
OpenCL kNN TOPK=32 pianificato
Core distance pianificato
Mutual reachability pianificato
Minimum spanning tree pianificato
HDBSCAN condensed tree pianificato
Cluster assignment pianificato
Licenze e componenti esterni
Il repository contiene o utilizza componenti esterni, inclusi:
- stb_image;
- header API RKNN;
- runtime RKNN;
- modelli SCRFD;
- modello SFace.
Prima della pubblicazione o redistribuzione verificare separatamente le condizioni di licenza di ogni componente.
I modelli e il runtime non vengono inseriti automaticamente nel repository.
Obiettivo finale
L'obiettivo è fornire una pipeline indipendente e riutilizzabile:
Immagini
|
v
Volti e embedding
|
v
Grafo kNN
|
v
HDBSCAN
|
v
Cluster di identità facciali
Il server o l'applicazione che utilizza il toolkit rimane responsabile della persistenza, dell'interfaccia utente e dell'eventuale associazione dei cluster a persone reali.