# 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 ```text 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: ```bash ./bin/face_recognition test/image.jpg ``` Confronto tra due immagini: ```bash ./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 è: ```text 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: ```bash ./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: ```bash ./bin/face_scan \ test/image.jpg \ > result.json ``` Per verificare e formattare il JSON: ```bash 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`: ```text models/SCRFD_500M_KPS_640.rknn models/face_recognition_sface_2021dec.rknn ``` ### Runtime RKNN Copiare la libreria runtime in: ```text 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: ```bash make ``` Compilazione parallela: ```bash make -j"$(nproc)" ``` I programmi vengono creati in: ```text bin/face_recognition bin/face_scan ``` Per effettuare una compilazione pulita: ```bash make clean make -j"$(nproc)" ``` ## Test Le immagini di test locali devono essere copiate nella directory `test`. Per eseguire i test automatici: ```bash make test ``` Il test: 1. esegue `face_recognition`; 2. esegue `face_scan`; 3. salva temporaneamente il JSON; 4. valida la sintassi JSON tramite Python. Le immagini sono escluse dal repository tramite `.gitignore`. ## Utilizzo da un altro programma C++ Includere l'header pubblico: ```cpp #include "face_engine.h" ``` Inizializzare il motore: ```cpp FaceEngine engine; if (!engine.init( "models/SCRFD_500M_KPS_640.rknn", "models/face_recognition_sface_2021dec.rknn")) { return 1; } ``` Elaborare un'immagine: ```cpp std::vector 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`, `x2` e `y2`; - cinque elementi `kps`; - un embedding L2-normalizzato di 128 elementi. Esempio di accesso ai risultati: ```cpp 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 è: ```text 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: ```json { "image": { "path": "image.jpg", "width": 1920, "height": 1080 }, "faces": [] } ``` ## Formato dell'embedding Ogni embedding contiene: ```text Dimensione logica 128 Tipo nel motore float32 Norma L2 circa 1.0 Valori tutti finiti ``` Se salvato come sequenza binaria float32: ```text 128 x 4 byte = 512 byte ``` Questo formato sarà utilizzabile direttamente dai futuri moduli OpenCL. ## Struttura del repository ```text 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: ```text 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à: ```text 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 ```text 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: ```text 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.