Automated face dataset builder for LoRA training. Extracts faces from videos/photos, creates multi-variant crops with captions. GPU-accelerated, with optional person removal via YOLO+LaMa.
Find a file
2026-03-08 11:25:31 +01:00
.gitignore Add batch cleanup/download scripts, update gitignore und README 2026-03-08 11:25:31 +01:00
batch_cleanup.py Add batch cleanup/download scripts, update gitignore und README 2026-03-08 11:25:31 +01:00
build_dataset.py Add --name parameter for per-run output folders, fix _rejected location 2026-02-03 22:54:15 +01:00
download_photos.py Add batch cleanup/download scripts, update gitignore und README 2026-03-08 11:25:31 +01:00
LICENSE Initial commit: face-dataset-builder 2026-02-02 13:42:30 +01:00
qwen_cleanup_workflow.json Add batch cleanup/download scripts, update gitignore und README 2026-03-08 11:25:31 +01:00
README.md Add batch cleanup/download scripts, update gitignore und README 2026-03-08 11:25:31 +01:00
requirements.txt Rename extract_frames.py to build_dataset.py and integrate Joy-Caption 2026-02-02 16:32:02 +01:00
train_config_test.yaml Add ROCm/HIP support and update training configs 2026-02-02 17:11:28 +01:00
train_wan22_images.yaml Add ROCm/HIP support and update training configs 2026-02-02 17:11:28 +01:00
train_wan22_video.yaml Add ROCm/HIP support and update training configs 2026-02-02 17:11:28 +01:00
validate_dataset.py Add batch cleanup/download scripts, update gitignore und README 2026-03-08 11:25:31 +01:00

face-dataset-builder

Automatischer Dataset-Builder und -Filter fuer Face-LoRA-Training. Extrahiert Gesichter aus Videos und Fotos, erstellt trainingsfertige Crops in mehreren Varianten mit passenden KI-Captions, und filtert automatisch nach Qualitaet.

Entwickelt fuer die Verwendung mit ai-toolkit (FLUX, Qwen Image, WAN 2.2 LoRA Training).

Features

  • Videos + Fotos als Eingabequellen
  • Gesichtserkennung via OpenCV YuNet (schnell, CPU oder GPU)
  • Referenzgesicht-Matching via SFace -- filtert nach einer bestimmten Person
  • 4 Crop-Varianten pro erkanntem Gesicht: close, medium, wide, full
  • KI-Captions via Joy-Caption Alpha Two (natuerlicher, casual Stil)
  • Qualitaetsfilter: Gesichts-Confidence, Schaerfe, Duplikat-Erkennung, Belichtung
  • Automatisches Filtern: Behaelt nur die besten N Einzelbilder (Intra-Set-Deduplizierung, ausgeglichene Crop-Verteilung)
  • Progressbars fuer alle langwierigen Schritte (tqdm)
  • GPU-Beschleunigung via OpenCL (AMD, Intel, NVIDIA)
  • Personenentfernung via YOLO11n-seg + LaMa Inpainting
  • Textentfernung via PP-OCR + LaMa Inpainting (Untertitel, Wasserzeichen)

Voraussetzungen

  • Python 3.10+
  • OpenCV mit DNN-Modul
  • Optional: ONNX Runtime (fuer --remove-people, --remove-text)
  • Optional: PyTorch + Transformers (fuer --caption)

Installation

git clone https://github.com/swissYoshi/face-dataset-builder.git
cd face-dataset-builder

python -m venv venv
source venv/bin/activate  # Linux/Mac
# oder: venv\Scripts\activate  # Windows

pip install -r requirements.txt

Verzeichnisstruktur

face-dataset-builder/
├── download_photos.py         # Fotos aus Immich herunterladen
├── build_dataset.py           # Dataset-Builder (Haupttool)
├── batch_cleanup.py           # Batch-Bildbereinigung via ComfyUI + Qwen Image Edit
├── qwen_cleanup_workflow.json # ComfyUI API-Workflow fuer batch_cleanup.py
├── validate_dataset.py        # Dataset-Validator und -Filter
├── requirements.txt
├── dataset/
│   ├── videos/            # Eingabe: Videos (mp4, mov, mkv, ...)
│   ├── photos/            # Eingabe: Rohe Einzelbilder (jpg, png, ...)
│   ├── cleaned/           # Ausgabe: Bereinigte Bilder (nach batch_cleanup.py)
│   ├── reference.jpg      # Optional: Referenzgesicht
│   ├── <name>/            # Ausgabe: Crops + Captions (pro Durchlauf)
│   └── _rejected/
│       └── <name>/        # Vom Filter aussortierte Bilder (ausserhalb des Trainingsordners)
├── models/                # Wird automatisch erstellt
└── output/                # Training-Output

Verwendung

0a. Fotos aus Immich herunterladen (optional)

Laedt alle Fotos einer erkannten Person direkt aus der Immich-Bibliothek herunter.

Voraussetzungen: Immich-Server erreichbar, API-Key konfiguriert (via --api-key, IMMICH_API_KEY env, oder .immich_api_key Datei).

# Alle Personen anzeigen
python download_photos.py --list

# Fotos einer Person herunterladen
python download_photos.py "Yoshi"

# Mit Optionen
python download_photos.py "Yoshi" --skip-existing --min-size 1024 --limit 200

Optionen:

  name                   Name der Person in Immich
  --server URL           Immich Server (default: http://192.168.2.214:2283)
  --api-key KEY          API-Key
  --output ORDNER        Ausgabe-Ordner (default: dataset/photos)
  --list                 Alle erkannten Personen mit Foto-Anzahl anzeigen
  --skip-existing        Bereits vorhandene Bilder ueberspringen
  --min-size PIXEL       Mindestaufloesung kuerzeste Seite (default: 0 = alle)
  --limit N              Max. Anzahl Downloads (default: 0 = alle)

0b. Bilder bereinigen (optional, via ComfyUI + Qwen Image Edit)

Entfernt Text/Emojis/Personen, verbessert Beleuchtung und schaerft Gesichter per KI-Bildbearbeitung.

Voraussetzungen: ComfyUI muss laufen (python main.py im ComfyUI-Verzeichnis).

# Standard: dataset/photos/ -> dataset/cleaned/
python batch_cleanup.py

# Eigene Pfade
python batch_cleanup.py --input dataset/photos --output dataset/cleaned

# Bereits verarbeitete Bilder ueberspringen
python batch_cleanup.py --skip-existing

# Eigener Cleanup-Prompt
python batch_cleanup.py --prompt "Remove background clutter and improve lighting"

Pipeline:

Immich (Personen-Gesichtserkennung)
       |  download_photos.py "Name"
       v
dataset/photos/ (Rohe Fotos)
       |  batch_cleanup.py (ComfyUI API -> Qwen Image Edit)
       v
dataset/cleaned/ (Bereinigte Fotos)
       |  build_dataset.py --photos dataset/cleaned --name <name>
       v
dataset/<name>/ (Trainings-Dataset mit Crops + Captions)

Optionen:

  --input ORDNER       Eingabe-Ordner (default: dataset/photos)
  --output ORDNER      Ausgabe-Ordner (default: dataset/cleaned)
  --workflow JSON      Workflow-Datei (default: qwen_cleanup_workflow.json)
  --server URL         ComfyUI Server (default: http://127.0.0.1:8188)
  --prompt TEXT        Positiver Prompt
  --negative TEXT      Negativer Prompt
  --skip-existing      Bereits verarbeitete Bilder ueberspringen
  --timeout SEKUNDEN   Timeout pro Bild (default: 300)

1. Dataset erstellen

Lege Videos in dataset/videos/ und/oder Fotos in dataset/photos/ ab.

# Grundlegend (Template-Captions)
python build_dataset.py --name flux1_v1

# Mit KI-Captions (empfohlen)
python build_dataset.py --name flux1_v1 --caption

# Mit KI-Captions, quantisiert (~10GB statt ~17GB VRAM)
python build_dataset.py --name flux1_v1 --caption --caption-quantize

# Vollstaendig: Referenzgesicht, Personenentfernung, Textentfernung, KI-Captions
python build_dataset.py --name flux1_v1 --reference mein_foto.jpg --remove-people --remove-text --caption --verbose

Der --name Parameter ist Pflicht und bestimmt den Output-Ordner: dataset/<name>/.

2. Dataset validieren

python validate_dataset.py

Prueft: Schaerfe, Aufloesung, Belichtung, Gesichtserkennung, Gesichtswinkel-Verteilung, Duplikate, Captions, Gesamtscore.

3. Dataset filtern

# Vorschau: zeigt was gefiltert wuerde (mit Zusammenfassung)
python build_dataset.py --only-filter --name flux1_v1 --keep 80 --dry-run

# Filtern: behaelt die besten 80 Bilder (default)
python build_dataset.py --only-filter --name flux1_v1 --keep 80

# Oder ueber validate_dataset.py direkt:
python validate_dataset.py --filter --keep 50
python validate_dataset.py --dry-run --keep 50

# Mit Belichtungs-Filter
python validate_dataset.py --filter --filter-exposure

Der Filter waehlt die besten Einzelbilder aus dem gesamten Pool (nicht set-basiert). Redundante Varianten innerhalb eines Sets werden automatisch eliminiert, und die Crop-Groessen werden gleichmaessig verteilt. Aussortierte Bilder landen in dataset/_rejected/<name>/ und koennen bei Bedarf wiederhergestellt werden.

Filter-Pipeline (4 Stufen):

  1. Harte Ausschluesse: Kein Gesicht erkannt (ausser full-Variante), optional stark unter-/ueberbelichtete Bilder (--filter-exposure)
  2. Intra-Set Deduplizierung: Pro Quellbild werden visuell zu aehnliche Varianten eliminiert (>92% Histogramm-Korrelation). Z.B. wenn bei einem Portrait close/medium/wide fast identisch aussehen, wird nur die beste behalten.
  3. Inter-Set Duplikate: Zwischen verschiedenen Quellbildern wird bei Duplikaten das schlechtere entfernt
  4. Top-N mit Bucket-Filling: Die besten N Bilder werden mit ausgeglichener Verteilung ueber Crop-Groessen gewaehlt. Jede Variante (close/medium/wide/full) erhaelt einen gleichen Basis-Anteil, Restplaetze werden nach globalem Score aufgefuellt.

Score-Gewichtung (pro Einzelbild):

Kriterium Punkte Beschreibung
Gesichts-Confidence 0-30 YuNet-Confidence (verdeckte Gesichter = niedriger)
Schaerfe 0-25 Laplacian-Varianz
Gesichtsgroesse 0-15 Anteil des Gesichts am Bild
Belichtung 0-10 Optimal bei 100-160 Helligkeit
Gesichtswinkel 0-10 Frontal > 3/4 > Profil
Aufloesung 0-10 Minimale Seitenlaenge

Statistiken: Nach jedem Filter-Lauf (auch ohne --dry-run) wird eine Zusammenfassung ausgegeben: Score-Bereich, Ablehnungsgruende, Crop-Verteilung als Balkendiagramm, Quellen-Abdeckung, und die 5 besten/schlechtesten behaltenen Bilder.

4. Training starten

cd /pfad/zu/ai-toolkit
python run.py /pfad/zu/train_config.yaml

Crop-Varianten

Jeder erkannte Frame erzeugt bis zu 4 Crop-Varianten:

Variante Face-Factor Beschreibung Caption
close 55% Nahaufnahme Gesicht a close up photo of <trigger>
medium 30% Portrait a portrait photo of <trigger>
wide 18% Oberkoerper a photo of <trigger>
full -- Ganzes Bild, proportional skaliert a full body photo of <trigger>

Die full-Variante behält das gesamte Bild mit originalem Seitenverhältnis (kein quadratischer Crop).

Bei Verwendung von --caption werden die Template-Captions durch KI-generierte, natuerliche Beschreibungen ersetzt.

Optionen: build_dataset.py

Eingabe:
  --name NAME            Name fuer diesen Durchlauf (Output: dataset/<name>/)
  --videos ORDNER        Ordner mit Videos (default: dataset/videos)
  --photos ORDNER        Ordner mit Einzelbildern (default: dataset/photos)
  --output ORDNER        Basis-Ausgabeordner (default: dataset/)

Gesichtserkennung:
  --reference BILD       Referenzbild fuer Gesichtsfilterung
  --threshold FLOAT      Aehnlichkeitsschwelle (default: 0.35)

Video-Extraktion:
  --interval SEKUNDEN    Abstand zwischen Frame-Checks (default: 1.0)
  --max-frames N         Max Frames pro Video (default: 50)
  --min-sharpness FLOAT  Minimale Schaerfe (default: 30)
  --min-similarity FLOAT Duplikat-Schwelle (default: 0.97)

Crops:
  --size PIXEL           Crop-Groesse (default: 1024)
  --variants LISTE       Crop-Varianten (default: close,medium,wide,full)
  --trigger WORT         Trigger-Wort fuer Captions (default: y0sh1face)

Bereinigung:
  --remove-people        Andere Personen aus Bildern entfernen
  --remove-text          Text-Overlays entfernen (Untertitel, Wasserzeichen)

KI-Captions:
  --caption              KI-Captions via Joy-Caption generieren
  --caption-quantize     Joy-Caption mit NF4-Quantisierung (~10 GB statt ~17 GB)
  --caption-prompt TEXT   Eigener Captioning-Prompt
  --caption-max-tokens N Max. Tokens pro Caption (default: 256)

Filterung:
  --no-filter            Automatisches Filtern nach Extraktion deaktivieren
  --only-filter          Nur filtern (keine Extraktion), auf bestehendes Dataset
  --dry-run              Zeigt was gefiltert wuerde (mit --only-filter)
  --keep N               Maximale Anzahl Bilder die behalten werden (default: 80)

Sonstiges:
  --no-gpu               GPU-Beschleunigung deaktivieren
  --verbose              Debug-Ausgabe

Optionen: validate_dataset.py

Validierung:
  --dataset ORDNER       Dataset-Ordner (default: dataset/images)
  --trigger WORT         Trigger-Wort (default: y0sh1face)
  --min-images N         Minimale Anzahl guter Bilder (default: 15)
  --ideal-images N       Ideale Anzahl Bilder (default: 50)

Filterung:
  --filter               Schlechte Bilder nach _rejected/ verschieben
  --dry-run              Zeigt was gefiltert wuerde (ohne Aenderungen)
  --keep N               Maximale Anzahl Bilder die behalten werden (default: 80)
  --filter-exposure      Stark unter-/ueberbelichtete Bilder filtern

Beispiele

# Schneller Test mit wenigen Frames
python build_dataset.py --name test_v1 --interval 2.0 --max-frames 10

# Nur close und medium Crops
python build_dataset.py --name test_v1 --variants close,medium

# Nur Full-Body fuer WAN 2.2 Training
python build_dataset.py --name wan_v1 --variants full --caption

# Strenge Qualitaet: hohe Schaerfe, geringe Duplikat-Toleranz
python build_dataset.py --name flux_v2 --min-sharpness 50 --min-similarity 0.90 --reference foto.jpg

# Komplett-Pipeline
python build_dataset.py --name flux_v2 --reference foto.jpg --remove-people --remove-text \
    --caption --caption-quantize --keep 60 --verbose

# Nur bestehendes Dataset filtern (ohne Neuextraktion)
python build_dataset.py --only-filter --name flux_v2 --keep 80 --dry-run
python build_dataset.py --only-filter --name flux_v2 --keep 80

Modelle

Die Modelle werden beim ersten Start automatisch heruntergeladen:

Modell Groesse Zweck
YuNet 227 KB Gesichtserkennung
SFace 37 MB Gesichts-Identifikation (mit --reference)
YOLO11n-seg 11 MB Personen-Segmentierung (--remove-people)
LaMa 198 MB Inpainting (--remove-people, --remove-text)
PP-OCR v3 2.3 MB Texterkennung (--remove-text)
Joy-Caption ~17 GB KI-Captions (--caption, ~10 GB mit --caption-quantize)

Fuer batch_cleanup.py (via ComfyUI):

Modell Groesse Zweck
Qwen Image Edit GGUF (Q6_K) ~16 GB Bildbearbeitung
Qwen 2.5 VL 7B fp8 ~7 GB Text-Encoder
Qwen Image VAE ~100 MB VAE
Qwen Image Lightning LoRA ~200 MB 4-8 Steps statt 30

Hardware

Getestet auf:

  • AMD Radeon RX 7900 XTX (24GB VRAM) mit ROCm
  • OpenCL GPU-Beschleunigung fuer Face-Detection
  • Joy-Caption benoetigt ~10-17 GB VRAM

Lizenz

MIT