argus-curator
argus-curator 0.15.2.dev2+g97021d6 @ 97021d6PyPI (opens in new tab)Source (opens in new tab)Changelog (opens in new tab)
Imported from README.md on argus-curator's dev branch at that commit. Fixes go upstream, not here.
Image curation and moderation: score, de-duplicate, and tag images by face, apparent age, scene and garment, then filter on those tags with a reason recorded for every exclusion. Use it on its own to audit or moderate an image collection, or as the LoRA data-prep front-end of the Argus suite, captioned downstream by argus-lens (opens in new tab).
Two ways to use it:
- Standalone moderation and dataset auditing. Scan a folder or call the HTTP API, review the per-image report, and keep, drop or quarantine images on criteria you choose. Nothing has to be trained or captioned. See Standalone moderation and dataset auditing.
- The curation stage of the Argus suite, described below.
argus-curator is the curation stage of the Argus suite. Upstream,
argus-quarry (opens in new tab) acquires provenance-clean
images; curator decides which images, of whom, at what quality belong in a
LoRA training set; argus-lens then decides what's in each image. Curator and
lens share one TargetProfile, so a manifest written here is captioned
downstream with no remapping.
argus-quarry argus-curator (:8101) argus-lens (:8100) imogen / kohya
─ download ─┐ ─ scan + score ─┐ ─ caption ─┐ ─ train ─
─ provenance ─┤ images ─ face-cluster ─┤ manifest ─ buckets ─┤ dataset ─ LoRA ─
─ verify ─────┴─────────► ─ select ───────┴────────► (identity/ ─┴────────► ───────►
─ export ───────► wardrobe/…)
A scan only reads the source folder (unless you ask for XMP sidecars beside
the originals). It records, per image, its quality
score, near-duplicate group, faces and identities, and whatever optional checks
you turn on: apparent age and gender, scene, garments, nudity and a moderation
policy verdict. An export then filters on that record and gives every excluded
image a keep_reason, so the result doubles as an audit trail.
Why not FiftyOne / fastdup / Immich?
It's LoRA-native, identity-aware, and caption-integrated — the reason the suite exists.
The shared TargetProfile (the moat)
Both services speak the same taxonomy. This single schema is the contract:
from argus_curator import TargetProfile
TargetProfile(
target_style="photo", # "photo" | "anime"
target_backend="sdxl", # "sdxl" | "flux-dev-1" | ...
checkpoint=None,
target_category="identity", # identity | wardrobe | pose_composition | setting | concept
)
The curator uses it to weight scoring and label exports; argus-lens inherits it verbatim.
The style and category values are argus-cortex's (argus_cortex.taxonomy), the one
copy the whole suite shares. concept is a style or visual-concept LoRA: face count
never lowers its score, and clean, high-resolution images get the composition bonus.
Installation
pip install argus-curator # engine only (Pillow, numpy, ImageHash, pydantic)
pip install "argus-curator[server,cli]" # FastAPI server + CLI
pip install "argus-curator[faces]" # + InsightFace identity clustering (CPU onnxruntime)
pip install "argus-curator[gpu]" # + onnxruntime-gpu for GPU face detection
pip install "argus-curator[all]" # everything
System libraries for the face stack (Ubuntu/Debian):
sudo apt install -y libgl1 libglib2.0-0 libgomp1
Face attributes, scenes and garments read ONNX models that are converted once
(mivolo-convert, fairface-convert, places365-convert,
garments-convert); each feature's page says how. The nudity, policy and
watermark checks talk to their own servers over HTTP. A Docker image is
published for CPU and GPU: see Docker and the GPU.
Quick start
Python
from argus_curator import scan_folder, TargetProfile, ScanConfig, FaceConfig
summary = scan_folder(
"/data/images",
profile=TargetProfile(target_category="identity"),
cfg=ScanConfig(min_short_side=512, blur_threshold=100.0, cluster_distance=10),
faces_cfg=FaceConfig(enabled=True, model="buffalo_l", cluster_eps=0.5),
)
print(summary.passed, "passed,", summary.duplicates, "near-dupes")
for fc in summary.face_clusters:
print(fc.cluster_id, fc.size, "faces, rep:", fc.representative_rel_path)
CLI
# Report only — see the score distribution before committing to a threshold
argus-curator scan /data/images --csv report.csv
# Identity curation with face clustering, copy 0.65+ keepers (structure preserved)
argus-curator scan /data/images \
--target-category identity --faces --device cuda \
--min-score 0.65 --copy-to /data/curated
# Export only specific identities, capped to a diverse 200
argus-curator scan /data/images --faces \
--face-clusters face_1,face_2 --max-keep 200 --copy-to /data/curated
# Pick a pose-balanced subset (head-on + 3/4 only, drop side profiles)
argus-curator scan /data/images --faces \
--pose frontal,three_quarter --copy-to /data/curated
# Predict age in years and gender per face (MiVOLO), then keep adults up to 35
# whose gender prediction is confident
argus-curator scan /data/images --mivolo \
--gender female --min-attr-conf 0.6 --min-age 25 --max-age 35 --copy-to /data/curated
# Which detectors are available?
argus-curator detectors
The full list of commands and options is in the CLI reference.
HTTP server
pip install "argus-curator[server,faces]"
argus-curator serve --cors --port 8101 --source-root /data/images --export-root /data/out
Scans and exports then run over HTTP (POST /scan/folder, POST /export);
see the HTTP API.
An image with a MiVOLO age under 18 and any exposed nudity score in the frame
is never kept, whatever the request. ARGUS_CURATOR_MINOR_EXPOSED=overlap
narrows that to exposure on the young person's box; see
the under-18 rule.
Documentation
Using curator
- Standalone moderation and dataset auditing: what each check records, a scan-review-act pass, and its limits
- How scoring works: hard filters, the composite score, near-duplicates, selection
- CLI reference: every command and option (generated)
- HTTP API: the :8101 server, its routes, streaming, request bodies and scan cache
- Docker and the GPU: the CPU and GPU images, and sharing a card with the rest of the suite
Checks and filters
- Face attributes: MiVOLO age and gender, FairFace race, gender and age bracket, set age
- Face sources: head pose, face sharpness, eyes and mouth, identity distance, the argus-mask preset
- Scene tags: Places365 scenes and indoor/outdoor
- Garments: Fashionpedia garments, colours and cut-off
- Nudity detection: NudeNet, the EraX second pass, content rating
- Policy check: SingGuard verdicts, policies and context
- Prefilter: drop images before the slow checks
- Crops: watermarks and borders, given or detected
Export and handoff
- Manifest reference: the
manifest.jsonlcontract, its fields, versions and compatibility rule - Sidecars and run stats: carrying captions and XMP with an export
- XMP sidecars: face regions, person names and content rating
- Synthetic source portraits: darkroom, curator and lens for argus-mask
Handoff to argus-lens
Export writes manifest.jsonl, one row per exported image, carrying the
shared TargetProfile, the real exported path, and the primary face's
measurements. argus-lens batch-captions it with no remapping; set
caption_url on the export request to POST it straight to lens for a
one-click curate-then-caption run. The rows, their versions (currently 2.3)
and the rule for consumers (refuse an unknown major) are in the
manifest reference.
Related projects
- argus-quarry (opens in new tab) — provenance-first acquisition of public-domain / CC0 portraits (the suite's input stage).
- argus-lens (opens in new tab) — intent-aware, multi-model captioning (consumes the manifest this package exports).
- argus-studio (opens in new tab) — the suite's Next.js web UI (its
/curateview drives this server). - argus-darkroom (opens in new tab) — guarded image generation; its records carry with an export under
--carry-sidecars. - argus-mask (opens in new tab) — a talking face. docs/synthetic-face-sets.md shows how darkroom, curator and lens make its synthetic source portraits.
License
MIT — matches the rest of the Argus suite.