5.2 KiB
anime-facesaver
Scene-gated still extractor for building anime training datasets from
video. Fork of facesaver, created Oct 2026.
Why this fork exists
The original facesaver ran stock COCO yolov11l.pt and accepted
class 0 — person — as a "proxy for face" (their comment, not ours).
COCO has no face class, so every frame containing a large enough person
passed: full-body shots, headless crops, a hand at 75% confidence. That
is why the old Gabriel Dropout output contained stills of shoes.
anime-facesaver uses a dedicated anime-face detector instead:
yolov8x6_animeface
— yolov8x6 fine-tuned at 1280px on 10k manually annotated anime images
(P=0.957 R=0.924 mAP50=0.955 on its test set). It detects faces. Only
faces. The scene-change gate from the original is preserved: at most one
still is saved per detected scene, which keeps near-duplicates out of
the dataset.
Setup
uv venv --python 3.12 .venv # or: python3.12 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt # add --index-url for your CUDA ver
python anime_facesaver.py --download-model ... # fetches weights once
Weights land in models/yolov8x6_animeface.pt (~195 MB, AGPL-3.0).
Usage
python anime_facesaver.py \
-I /home/alex/Documents/image-training-datasets/gabriel-dropout-show \
-O /home/alex/Documents/image-training-datasets/gabriel-dropout-v2 \
--gpu 1 \
--preview-dir /home/alex/Documents/image-training-datasets/gabriel-dropout-v2-preview
GPU pinning (important on the shared .80 box)
--gpu sets CUDA_VISIBLE_DEVICES before torch initializes, so no
context leaks onto the wrong card:
| flag | effect |
|---|---|
--gpu 1 |
pin to physical GPU 1 (recommended on .80) |
--gpu 0 |
pin to GPU 0 — OOMs while Strata holds it |
--gpu cpu |
force CPU |
--gpu auto |
let torch pick |
Key options
| flag | default | meaning |
|---|---|---|
--conf |
0.3 | detector confidence (model's own recommendation; it is high-precision) |
--min-width / --min-height |
100 | minimum face box size in px |
--min-face-fraction |
0.005 | face box area as fraction of frame — kills distant background extras; 0 disables |
--max-face-fraction |
0.30 | face box area upper cap — kills detector meltdowns on full-frame ED/OP effects (feather storms etc.); 0 disables |
--min-aspect / --max-aspect |
0.45 / 1.6 | face box W/H ratio window — effect blobs rarely keep face proportions |
--edge-margin |
0 | require faces this far inside frame edges; 0 accepts edge-touching faces (original hard-rejected them) |
--scene-threshold |
30.0 | PySceneDetect ContentDetector threshold (same as original) |
--imgsz |
1280 | inference size; model was trained at 1280, 640 is faster at some recall cost |
--all-files |
off | also scan OP/ED files. Off by default: music videos are full of stylized graphics (feather storms, transformation emblems) that false-positive as face-shaped; episodes carry the real character close-ups |
--preview-dir |
off | also write annotated copies (green boxes) of every saved frame for eyeball QC |
Notes
- Runs every frame of every scene until a face qualifies, then waits for the next scene start. That is the original behavior and it is why dense scenes don't flood the output.
- The detector ships as
yolov8x6— big and a little slow (it was trained to be precise, not cheap). On a 3090 at 1280px expect roughly 8-12 fps; an hour of 24fps anime is ~15 min of inference per GPU. - License: the model weights are AGPL-3.0 (Fuyucchi); ultralytics is AGPL-3.0 too. Fine for personal/research dataset building; if this ever ships in a product, revisit.
QC: auditing an existing collection
audit_stills.py runs the same detector over a directory of stills and
reports how many contain no face at all — e.g. measuring the damage the
old person-proxy pipeline did:
python audit_stills.py -I ~/Documents/image-training-datasets/gabriel-dropout \
--gpu 1 --write-report old_run_report.csv
Verified run (Gabriel Dropout, Oct 18 2026)
12 episodes + 2 specials, OP/ED skipped: 3,526 stills vs 887 from the old person-proxy run (~4x yield — chibi reaction faces no longer missed). QC: full box-size distribution audited (p5=0.7%, median 6.6%, max 29.9%); 5 largest and 5 smallest saves inspected with annotated copies — all real faces; zero faceless images found. The 5 largest sit against the 30% area cap and are legitimate extreme close-ups (crying faces count).
Verification workflow
Always run with --preview-dir and eyeball the _ann.png files: every
saved frame should show a green box on a real face. Pay attention to
saves clustered against a gate (e.g. many boxes at ~max area) — that
pattern means the gate is doing work and deserves a look. For a
known-dirty legacy collection, audit_stills.py quantifies the damage.
Recipe:
python anime_facesaver.py -I <show_dir> -O <out> --gpu <n> \
--preview-dir <out>-preview