# Face Recognition RK3588 OpenCL Motore C++ per rilevamento facciale, generazione di embedding e riconoscimento kNN accelerato su Rockchip RK3588. Il progetto usa: - NPU tramite RKNN per SCRFD e SFace; - GPU Mali-G610 tramite OpenCL per kNN; - CPU C++ come riferimento numerico e fallback. ## Funzionalità - rilevamento volti con SCRFD; - confidence, bounding box e cinque landmark; - non-maximum suppression; - allineamento volto 112 x 112; - embedding SFace float32 a 128 dimensioni; - normalizzazione L2; - cosine similarity tramite prodotto scalare; - kNN CPU e OpenCL; - conteggi dinamici, TOPK configurabile e chunking; - leave-one-out tramite self-map; - JSON su stdout e diagnostica su stderr. ## Architettura ```text Immagine | v SCRFD tramite RKNN / NPU | v Bounding box e landmark | v Allineamento volto 112 x 112 | v SFace tramite RKNN / NPU | v Embedding float32[128] normalizzato L2 | +-----------------------------+ | | v v kNN CPU C++ kNN OpenCL / Mali-G610 | | +-------------+---------------+ | v TOPK prototype | v Leave-one-out opzionale | v Soglia di riconoscimento ``` ## Formato degli embedding ```text Dimensione: 128 Tipo: float32 Dimensione binaria: 512 byte Ordine byte: little-endian Normalizzazione: L2 Norma attesa: circa 1.0 ``` Poiché gli embedding sono normalizzati: ```text cosine_similarity(a, b) = dot(a, b) ``` ## Componenti ### Face engine RKNN ```text include/face_config.h include/face_engine.h include/rknn_api.h src/face_engine.cc src/face_recognition.cc src/face_scan.cc ``` ### Motore kNN ```text include/knn_opencl.h src/knn_opencl.cc src/knn_opencl_backend.cc src/face_knn.cc kernels/knn_float4_topk.cl kernels/knn_reference.cl ``` Il kernel produttivo viene compilato a runtime, ad esempio con: ```text -cl-fast-relaxed-math -D DIM=128 -D TOPK=5 -D QUERY_COUNT=21 -D LANES_PER_QUERY=8 ``` ## Requisiti - Linux AArch64; - Rockchip RK3588 o piattaforma compatibile; - compilatore C++17 e GNU Make; - runtime RKNN; - OpenCL ICD loader e driver Mali; - modelli SCRFD e SFace in formato RKNN. Su Debian: ```bash sudo apt-get install \ build-essential \ opencl-headers \ ocl-icd-opencl-dev ``` Verifica OpenCL: ```bash clinfo 2>/dev/null \ | grep -E 'Platform Name|Device Name|Device Type|Device Version' ``` ## File locali richiesti Non sono versionati: ```text models/SCRFD_500M_KPS_640.rknn models/face_recognition_sface_2021dec.rknn lib/librknnrt.so ``` ## Compilazione Dalla root del repository: ```bash make clean make -j"$(nproc)" ``` Binari previsti: ```text bin/face_recognition bin/face_scan bin/face_knn ``` Verifica del binario OpenCL: ```bash file bin/face_knn ldd bin/face_knn | grep -Ei 'opencl|stdc|not found' ``` ## Utilizzo dei binari ### face_recognition Programma dimostrativo con output destinato alla lettura umana. Analisi di una singola fotografia: ```bash ./bin/face_recognition test/test.jpg ``` Confronto tra due fotografie: ```bash ./bin/face_recognition \ test/test.jpg \ test/test3f.jpg ``` Usarlo per verificare modelli e runtime RKNN, detection, landmark, embedding e similarità. Non è il binario consigliato per integrazioni applicative. ### face_scan Elabora una fotografia e produce JSON con immagine, volti, confidence, bounding box, landmark ed embedding. ```bash ./bin/face_scan test/test3f.jpg ``` Separazione di risultato e diagnostica: ```bash ./bin/face_scan test/test3f.jpg \ > /tmp/face-scan.json \ 2> /tmp/face-scan.stderr ``` Validazione: ```bash python3 -m json.tool /tmp/face-scan.json > /dev/null \ && echo "OK: JSON valido" ``` Exit code: ```text 0 scansione completata 2 argomenti non validi 3 inizializzazione FaceEngine fallita 4 caricamento o elaborazione immagine fallita 5 risultato facciale o embedding non valido ``` Usarlo per integrare il face engine con Node.js, Python o altri linguaggi e per costruire query destinate a `face_knn`. ### face_knn Confronta embedding query con un database di prototype. Backend disponibili: ```text cpu opencl ``` Il programma va normalmente eseguito dalla root del repository, perché il kernel viene caricato da: ```text kernels/knn_float4_topk.cl ``` Help: ```bash ./bin/face_knn --help ``` Backend CPU: ```bash ./bin/face_knn \ --queries queries.bin \ --database prototypes.bin \ --query-count 21 \ --database-count 5 \ --dimension 128 \ --top-k 5 \ --threshold 0.50 \ --backend cpu ``` Backend OpenCL: ```bash ./bin/face_knn \ --queries queries.bin \ --database prototypes.bin \ --query-count 21 \ --database-count 5 \ --dimension 128 \ --top-k 5 \ --threshold 0.50 \ --backend opencl ``` Argomenti: ```text --queries file binario degli embedding query --database file binario degli embedding prototype --query-count numero di query --database-count numero di prototype --dimension componenti per embedding, 128 per SFace --top-k numero massimo di vicini --threshold soglia minima di riconoscimento --self-map esclusioni leave-one-out opzionali --backend cpu oppure opencl ``` Il TOPK effettivo è: ```text effective_top_k = min(top_k, database_count) ``` #### Leave-one-out Quando una query è anche un prototype, il confronto con sé stessa va escluso. La self-map contiene una riga per query: ```text -1 1 3 0 4 -1 ``` `-1` indica nessuna esclusione; un valore da zero in su indica l'indice del prototype da escludere. ```bash ./bin/face_knn \ --queries queries.bin \ --database prototypes.bin \ --query-count 21 \ --database-count 5 \ --dimension 128 \ --top-k 5 \ --threshold 0.50 \ --self-map self-map.txt \ --backend opencl ``` #### Output e diagnostica ```bash ./bin/face_knn \ --queries queries.bin \ --database prototypes.bin \ --query-count 21 \ --database-count 5 \ --dimension 128 \ --top-k 5 \ --threshold 0.50 \ --self-map self-map.txt \ --backend opencl \ > /tmp/face-knn.json \ 2> /tmp/face-knn.stderr ``` ```text stdout → JSON valido stderr → diagnostica OpenCL e driver Mali ``` Validazione: ```bash python3 -m json.tool /tmp/face-knn.json > /dev/null \ && echo "OK: JSON valido" ``` Campi principali del JSON: ```text backend, device_name, query_count, database_count, dimension, top_k, threshold, leave_one_out, elapsed_ms, results, recognized_count, below_threshold_count, coverage_percent ``` Per ogni query: ```text query_index, excluded_index, recognized, best_index, best_score, neighbors ``` ### test_knn_cpu Sorgente: ```text test/knn/test_knn_cpu.cc ``` Esecuzione, se compilato: ```bash ./bin/test_knn_cpu ``` Output atteso: ```text OK: backend CPU dinamico query_count=2 database_count=3 top_k=2 ``` ## Scelta del backend Usare CPU per database piccoli, riferimento numerico o fallback. Usare OpenCL per database grandi o molte query. Con cinque prototype l'overhead OpenCL può superare il costo del calcolo; con 350000 prototype e 256 query è stato misurato uno speedup di circa 7 volte. ## Flusso completo ```text face_scan → estrae gli embedding → applicazione seleziona i prototype → face_knn calcola TOPK → applicazione associa gli indici alle identità → applicazione applica soglia e margine → applicazione salva il risultato ``` ## Prestazioni sintetiche validate ```text Database: 350000 Query: 256 Dimensione: 128 TOPK: 32 Chunk: 50000 GPU: Mali-G610 r0p0 CPU: 9663.226 ms OpenCL: 1373.797 ms Speedup: 7.034x TOPK identico: 8192 / 8192 ``` Variante float4 min-replace: ```text Kernel: 1244.576 ms Throughput: 71.992 M vector/s Dot rate: 18.430 GFLOP/s Traffico effettivo: 36.860 GB/s ``` ## Validazione reale ```text Query: 21 Prototype: 5 Dimensione: 128 Soglia: 0.50 Leave-one-out: attivo Riconosciuti: 20 / 21 Copertura: 95.2% Caso sotto soglia: IMG_0183.JPG Score: 0.466428 Miglior prototype: IMG_0143.JPG ``` Confronti: ```text Python vs C++ CPU: 21 / 21 query coerenti CPU vs OpenCL dopo leave-one-out: 100 / 100 posizioni CPU vs OpenCL TOPK grezzo: 105 / 105 posizioni Errore massimo CPU/OpenCL: 3.58e-7 ``` Dettagli: ```text VALIDATION_JESSICA.md README1.md modules/knn-opencl/reference/VALIDATION.md ``` ## Integrazione applicativa Un'applicazione deve leggere e validare i prototype, generare i file binari e i metadati, invocare `face_knn`, associare gli indici alle identità, applicare soglia e margine e salvare il risultato. La prima integrazione dovrebbe funzionare in modalità shadow, confrontando il risultato corrente con OpenCL prima dell'attivazione definitiva. ## Stato ```text Face engine RKNN: validato Backend CPU: validato Backend OpenCL: validato Mali-G610: validata TOPK dinamico: validato Chunking: validato Leave-one-out: validato Output JSON puro: validato Dataset reale: validato Integrazione applicativa: da completare ```