Automatischer Gesichteralbum-Aufbau aus reComputer-Videos
Ein Endgerät-Projekt zum automatischen Aufbau eines Gesichteralbums basierend auf Hailo-8 / SCRFD / ArcFace.

Den Quellcode dieses Projekts finden Sie auf GitHub: https://github.com/doublelf/person_face_sign
1. Projektüberblick
Person Face Sign ist ein Projekt zum Offline-Aufbau eines „Gesichteralbums" auf einem Edge-Gerät (reComputer + Hailo-8 NPU). Das Hauptziel besteht darin, alle in einem Überwachungs- oder Aktivitätsvideo vorkommenden Gesichter automatisch den jeweiligen „Identitätsalben" zuzuordnen, um sie später leichter nachschlagen, statistisch auswerten oder archivieren zu können.
Typische Anwendungsfälle
- Empfang & Besucherregistrierung: Übergeben Sie stundenlanges Rezeptionskameramaterial an das Skript, das automatisch „heute kamen 23 Personen, jede mit N Bildern" erzeugt.
- Unterrichts- / Sitzungs-Anwesenheitsunterstützung: Vorlesungsaufnahmen werden kopfweise archiviert und dienen als elektronische Anwesenheitsliste.
- Automatische Sortierung von Eventfotos: Zusammenführen und Clustern von Multi-Cam- und Multi-Winkel-Aufnahmen vor Ort zur automatischen Erzeugung personenbezogener Alben.
- Sekundärrecherche in Videomaterial: Person statt Zeitstempel als Suchkriterium.
Kern-Pipeline
Video (data/*.mp4)
│
▼
[VideoSampler] —— 1 Frame pro Sekunde (1280×720)
│
▼
[YOLOv8n] —— Personenerkennung (640×640)
│
▼
[IoUTracker] —— Personentracking + gedrosselte Gesichtsentnahme (abschaltbar)
│
▼
[SCRFD-10G] —— Gesichtserkennung + 5-Punkt-Landmarks
│
▼
[FaceAlign 5pt] —— Affine Ausrichtung auf 112×112
│
▼
[ArcFace MobileFaceNet] —— 512-d L2-norm Embedding
│
▼
[AlbumCluster] —— pHash bevorzugt / Faiss HNSW als Fallback → Zuweisung person_id
│
▼
[AlbumStorage] —— Datei schreiben + Doppel-Dedup + manifest.json aktualisieren
│
▼
[Web Browser :8080] —— Ergebnis durchblättern / durchsuchen2. Schnellstart
Im Folgenden ein End-to-End-Ablauf, der der Reihe nach ausgeführt wird, um ein durchblätterbares Gesichteralbum auf dem reComputer aufzubauen.
2.1 Repository klonen
git clone https://github.com/doublelf/person_face_sign.git
cd person_face_sign2.2 Virtuelle Umgebung anlegen
Die Verwendung von venv wird empfohlen (in Python integriert, keine zusätzliche Installation nötig).
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip2.3 Python-Abhängigkeiten installieren
pip install -r requirements.txt2.4 Systemweite Voraussetzungen installieren
build_album.py ruft über subprocess ffmpeg / ffprobe zum Framen-Sampling auf. Diese müssen auf Systemebene installiert sein:
# Debian / Ubuntu (einschließlich reComputer)
sudo apt update
sudo apt install -y ffmpeg
# Verifizieren
ffmpeg -version | head -n 1
ffprobe -version | head -n 12.5 HEF-Modelldateien vorbereiten
person_face_sign/
└── models/
├── yolov8n.hef # ~4.3 MB
├── scrfd_10g.hef # ~10 MB
└── arcface_mobilefacenet.hef # ~5 MB| Zweck | Modell | Standardpfad (in build_album.py hartcodiert) | Tatsächliche Quelle |
|---|---|---|---|
| Personenerkennung | YOLOv8n | <Projekt-Root>/models/yolov8n.hef | Im offiziellen Docker-Image eingebaut, Containerpfad /app/model/yolov8n.hef |
| Gesichtserkennung | SCRFD-10G | <Projekt-Root>/models/scrfd_10g.hef | Im HailoRT-deb-Paket enthalten (kann nach models/ kopiert werden) |
| Gesichts-Embedding | ArcFace MobileFaceNet | <Projekt-Root>/models/arcface_mobilefacenet.hef | Im HailoRT-deb-Paket enthalten (kann nach models/ kopiert werden) |
2.5.1 SCRFD + ArcFace beziehen (am einfachsten)
SCRFD-10G und ArcFace MobileFaceNet HEFs sind offiziell von Hailo vorkompilierte Modelle. Sie werden mit dem hailort-deb-Paket unter /usr/local/hailo/resources/models/hailo8/ installiert — einfach in das models/-Verzeichnis dieses Projekts kopieren:
sudo apt install hailort
ls /usr/local/hailo/resources/models/hailo8/
# Es sollten zu sehen sein:
# arcface_mobilefacenet.hef
# scrfd_10g.hef
# sowie weitere offizielle Beispielmodelle
# In das lokale models/-Verzeichnis des Projekts kopieren
cp /usr/local/hailo/resources/models/hailo8/scrfd_10g.hef models/
cp /usr/local/hailo/resources/models/hailo8/arcface_mobilefacenet.hef models/
ls -lh models/2.5.2 YOLOv8n beziehen
Siehe https://sensecraft.seeed.cc/ai-lab/en/models/yolov8/hailo-8. Das YOLOv8n HEF ist bereits in ghcr.io/seeed-projects/recomputer-r20-cv/yolov8:latest gepackt. Der Containerpfad ist /app/model/yolov8n.hef.
mkdir -p models
# 1. Offizielles Image ziehen
docker pull ghcr.io/seeed-projects/recomputer-r20-cv/yolov8:latest
# 2. Eine nicht laufende Container-Instanz mit `create` anlegen (nur um an die Datei zu kommen)
docker create --name yolov8-temp ghcr.io/seeed-projects/recomputer-r20-cv/yolov8:latest
# 3. yolov8n.hef aus dem Container in das models/-Verzeichnis des Projekts kopieren
docker cp yolov8-temp:/app/model/yolov8n.hef models/yolov8n.hef
# 4. Temporären Container entfernen
docker rm yolov8-temp
# 5. Verifizieren
ls -lh models/yolov8n.hef2.6 Gesichteralbum aufbauen (Kernschritt)
Das Repository enthält ein Demo-Video data/tex.mp4 (etwa 11 MB). Mit dem folgenden Befehl wird das Album erzeugt:
python apps/build_album.py \
--video data/tex.mp4 \
--out data/album \
--no-tracker \
--scrfd-score 0.6 \
--cluster-thresh 0.85 \
--skip-dedupParameter:
| Parameter | Wert | Beschreibung |
|---|---|---|
--video | data/tex.mp4 | Eingabevideo; kann mehrfach oder durch Kommas getrennt angegeben werden |
--out | data/album | Ausgabeverzeichnis für das Album |
--no-tracker | flag | IoU-Tracker ausschalten; pro Frame jedes Gesicht aufnehmen (für kurze Sample-Videos empfohlen) |
--scrfd-score | 0.6 | SCRFD-Gesichtserkennungs-Konfidenzschwelle (Standard 0,60) |
--cluster-thresh | 0.85 | Lockeres Clustering: Cosine-Distance-Schwelle; Details siehe Abschnitt 4.2 |
--skip-dedup | flag | pHash-/Embedding-Doppel-Dedup beim Schreiben überspringen (pHash-bevorzugtes Clustering bleibt erhalten) |
Nach dem Aufbau erscheint unter data/album/:
data/album/
├── manifest.json
├── thumbnails/
│ ├── person_0001.jpg
│ ├── person_0002.jpg
│ └── ...
├── person_0001/
│ ├── representative.jpg
│ ├── info.json
│ ├── embeddings.npz
│ └── img_0001_ts_2.00s_score_0.78.jpg
│ └── img_0002_ts_5.00s_score_0.74.jpg
│ └── ...
├── person_0002/
└── ...2.7 Web-Albumgalerie-Browser starten
Öffnen Sie nach dem Aufbau in einem weiteren Terminal den schlanken Web-Dienst:
python apps/web_browser.py --port 8080Im Browser http://<reComputer-IP>:8080/ aufrufen:
- Die obere Statistikleiste zeigt die Gesamtzahl der Personen, der Bilder und der Quellvideos;
- Das Hauptraster zeigt nach „1 Bild = 1 Person" die Thumbnails (Thumbnails stammen aus
representative.jpg, absteigend nach Bildanzahl sortiert); - Klick auf eine Person öffnet die Detailseite mit allen
img_*.jpgdieser Person; - Klick auf ein Bild öffnet den Vollbild-Viewer.
3. Ergebnisinterpretation
3.1 Verzeichnisstruktur der Daten
data/album/
├── manifest.json # Globale Statistik + Personenliste (Datenquelle der Web-UI)
├── thumbnails/
│ └── person_<id>.jpg # Thumbnail (Kopie von representative.jpg)
└── person_<NNNN>/ # Pro Identität ein Verzeichnis, NNNN ist eine 4-stellige Zero-Padded-ID
├── info.json # Metadaten pro Person: count / first_ts / last_ts / best_score / source_videos
├── embeddings.npz # Top-N-Embeddings dieser Person (Standard N=5, nach Score sortiert)
├── representative.jpg # Bestbewertetes „Titelbild", wird auch nach thumbnails/ synchronisiert
└── img_<NNNN>_ts_<ts>s_score_<score>.jpg # Jedes beibehaltene Gesicht (nach 112×112-Ausrichtung)Beispiele für die Dateinamenkonvention:
person_0001/img_0001_ts_2.00s_score_0.78.jpg: 1. Bild, 2,00 Sekunden, SCRFD-Score = 0,78person_0001/img_0014_ts_18.50s_score_0.82.jpg: 14. Bild, 18,50 Sekunden
3.2 Schlüsselfelder in manifest.json
{
"version": "1.0",
"created_at": "2026-09-26T10:23:11",
"updated_at": "2026-09-26T10:24:48",
"total_persons": 6,
"total_images": 142,
"source_videos": ["tex"],
"config": {
"interval_s": 1.0,
"cosine_distance_threshold": 0.85,
"min_face_size": [40, 40],
"min_face_score": 0.6,
"best_n_embeddings": 5,
"phash_max_dist": 4
},
"persons": [
{
"id": 1,
"count": 28,
"first_ts": 2.0,
"last_ts": 82.0,
"best_score": 0.85,
"source_videos": ["tex"],
"thumbnail": "thumbnails/person_0001.jpg"
},
...
]
}Feldbedeutungen:
| Feld | Bedeutung |
|---|---|
total_persons | Gesamtzahl der geclusterten Personen (steigt monoton bei inkrementellem Build) |
total_images | Gesamtzahl aller Gesichtsbilder (nach Dedup) |
config | Snapshot der Build-Parameter (in das Album zurückgeschrieben für Rückverfolgbarkeit) |
persons[].count | Anzahl der Gesichtsbilder dieser Person |
persons[].first_ts / last_ts | Zeitstempel des ersten / letzten Auftretens (Sekunden) |
persons[].best_score | Höchster SCRFD-Erkennungs-Score |
3.3 Interaktionen der Web-UI
Das Web-Frontend nutzt nur http.server + statisches HTML/CSS/JS ohne Datenbank. Alle Daten werden live aus manifest.json und dem Dateisystem gelesen.
Hauptinteraktionspfade:
- Startseite (
/): Lädt/manifest.json, listet alle Personen-Thumbnails absteigend nachcount; - Personendetails öffnen: Klick auf Thumbnail → Backend globt
person_<id>/img_*.jpg→ listet alle Bilder auf; - Bildvorschau: Klick auf ein Bild →
<dialog>-Vollbildmodal; - Aktualisieren: Klick auf
↻oben lädtmanifest.jsonneu.