A visual style fingerprint for LoRA training sets.
Curate a set of images to a stable look, treat it as the gold standard, and Lookprint distills it into a set of interpretable photographic metrics — a yardstick it then uses to measure how far any other image sits from that style. It is built around two jobs:
1. Refine the training set. It scores every image in the gold-standard dataset and flags the ones that clearly deviate from the overall style. A handful of outliers dilutes a style; dropping them before training (a marker only — originals are never touched) sharpens the fingerprint.
2. Check the generation output. Point it at any folder — for example the images your LoRA produces — and it scores each one against the gold standard, so you can see whether the generated results actually match the style of the training set.
The gold standard defines the look: film emulation, cinematic color grading, clean digital, or any style you curate.
Runs fully local as a small web UI (FastAPI, port 8788): histograms and scopes, outlier review with a lightbox, candidate folder scanning — no cloud, no telemetry.
English | 简体中文 | 设计说明 / Design notes
Dataset curation tools usually score images with black-box embeddings (CLIP/DINO) or single aesthetic numbers. That answers "is this a good photo?" but not the question a style-LoRA trainer actually has:
Is this image the same look as my curated set — same color family, same light?
Lookprint answers that with interpretable photographic metrics instead: split toning, chiaroscuro bimodality, highlight roll-off, grain residual, gradient direction. Every number maps to photographic language you can act on. The gold set defines the look — film emulation, cinematic color grading, clean digital, or any rendering style you curate. And a key design stance: a large distance does not mean "delete it" — a big blue sky or a snowfield is often a lighting variant that helps LoRA generalization. What deserves review is an image whose toning family has left the batch.
- Dataset refinement (outlier review) — sort by Mahalanobis distance; per-image diagnosis groups out-of-range metrics into families (toning / light & subject / technical / composite) with a suggested action; keep / maybe / drop with lightbox hotkeys — clean the set before you train
- Generation check (candidate scan) — score any folder against the gold standard; pass/review by the p90 threshold; e.g. point it at your LoRA's output folder to see how well it sticks to the training style. Keepers can be merged straight into the gold-standard folder (copy only, originals untouched, captions follow) to grow the reference set over time
- Fingerprint — ~35 interpretable metrics per image → mean/covariance of the set = the style fingerprint; GMM (BIC-selected) clusters, PCA projection
- Caption-aware export — exports copy images and their same-stem
.txtcaptions together (renames follow collisions), so the output is a ready-to-train image+caption pair - Fully local — no cloud, no telemetry; dropping is logical, originals untouched, no sidecar files next to your dataset
# Windows
py -3.12 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\run.ps1 # or: run.bat
# macOS / Linux
python3 -m venv .venv
./.venv/bin/python -m pip install -r requirements.txt
./run.shOpen http://127.0.0.1:8788 — you land on Overview. First run: go to the Project tab, set your gold-standard folder, then click Re-analyze gold set. The UI is bilingual (中/EN toggle in the header).
Requires Python 3.12+. The dataset folder should contain images with same-stem .txt captions (optional but recommended).
- Overview — fingerprint stats, 9 most-typical / 9 most-distant images, luma & RGB histograms, vectorscope, light×saturation scatter
- Outliers — images above a distance cut (slider); diagnosis under each card; keep/maybe/drop (
1/2/3in the lightbox); export remaining or dropped - Scan — score a candidate folder; ≤ cut = pass, else review; mark, copy marked files (with captions) to a new folder, or merge them straight into the gold standard
- Project — project name, gold path, outlier percentile (default 90)
python -m lookprint analyze # build fingerprint from the gold set
python -m lookprint scan "D:/new_picks" # score a folder
python -m lookprint scan "D:/new_picks" --recursive--project selects a project id (defaults to the first existing project).
Each image is resized to 640 on the long edge and reduced to ~35 metrics: luma percentiles/entropy/bimodality, split-tone a*/b* in shadows vs highlights, Hasler colorfulness, structure-tensor anisotropy, bilateral-filter grain residual, etc. The set's mean/covariance over these metrics defines the fingerprint; a new image's Mahalanobis distance scores it.
Outlier diagnosis walks the Tukey fences (q ± 1.5·IQR) per metric, then groups breaches by family — because identical "out of range" numbers mean different things:
| Family | Meaning | Suggested action |
|---|---|---|
| Toning | the color family left the batch — the style itself changed | review / drop |
| Light & subject | subject-driven shift (sky, snow, night) | keep — good for generalization |
| Technical | grain/sharpness residual — recompression or over-sharpening | review |
| Composite | no single breach; mild drifts stack up to push the distance | judge manually |
If the whole distance is still below the cut, breaches are reported as mild — keep for now.
Runtime data lives in data/ (git-ignored):
data/projects/<id>/
project.json gold path & percentile
fingerprint.json human-readable summary
fingerprint.pkl scaler / covariance / GMM / PCA
metrics.csv per-image metrics + distances
plots/ analysis charts (Chinese labels; English copies in plots_en/)
decisions.json outlier review: keep / maybe / drop
marked_candidates.json scan marks
scans/ + last_scan.json scan history
Re-analyzing after pointing the gold path at a different dataset recomputes everything (fingerprint, distances, thresholds, diagnosis fences, charts) — there are no hard-coded style values. Old drop decisions belong to the previous dataset and are cleared on a successful re-analysis; scan history is kept but its scores refer to the old fingerprint.
python -m pip install -r requirements-dev.txt
python -m pytest tests -qIssues and PRs welcome. Ideas worth exploring: per-format (PNG/JPEG) statistic groups, a semantic layer (CLIP/DINOv2) alongside the photographic layer, multi-project UI.



