krites cull¶
Description¶
Judge a shoot — analyse every frame and assign a keep / maybe / reject
verdict with reasons (spec 0001 §4.2). For each frame krites measures
model-free quality signals — focus (variance of the Laplacian) and
exposure (blown-highlight / crushed-shadow clipping) — and resolves a verdict
through a cull profile. Hard gates reject, a soft focus floor demotes to
maybe, and a clean frame is a keep. Near-duplicate bursts are then
grouped (perceptual hash): the sharpest frame is kept and the rest demoted to
maybe, tagged with the burst they belong to (R-DUP-1).
krites proposes; you dispose — a verdict is a label written to
.krites/verdicts.yaml, never a file operation (R-CULL-3). Originals are
never touched.
Each cull also banks an analysis cache (.krites/analysis.yaml) — the raw
per-frame signals plus the profile fingerprint in force — and, on every verdict,
records the machine's proposed ruling alongside your final one. That captured
history is what the Phase-4 learning loop will train on to auto-tune the profile
to your taste (spec 0005); it also makes verdicts explainable and re-culls fast.
The shoot must already be registered with krites ingest.
Usage¶
The shoot is taken from --shoot, or the current working directory if omitted
(R-SCOPE-1).
Flags¶
| Flag | Description | Default |
|---|---|---|
--shoot |
Shoot directory to cull | the current directory |
--profile |
Cull profile to apply | wedding-default |
--reanalyze |
Recompute analysis, ignoring the cache | false |
--output |
Output format: text or json |
text |
Examples¶
# Cull the shoot in the current directory
cd ~/shoots/smith-wedding && krites cull
# Or target it by path, with JSON output
krites cull --shoot ~/shoots/smith-wedding --output json
Text output:
Shoot "smith-wedding" — 4 frames
keep 1 maybe 0 reject 3
keep 01-sharp.jpg
reject 02-flat.jpg — out of focus (sharpness 0 below 50)
reject 03-dark.jpg — out of focus (sharpness 0 below 50); crushed shadows (100% over 30%)
reject 04-bright.jpg — out of focus (sharpness 0 below 50); blown highlights (100% over 10%)
Eye / blink signal¶
The cull engine also judges eyes open vs. closed (spec 0004): the
wedding-default profile carries an eye gate, and when a face provider is
configured the worst-face eye-open probability drives the verdict —
- a likely blink (below
eye_open_soft, seed0.50) demotes a frame to maybe with asubject blinking …reason; eye_open_hardis disabled by default (0), so a closed-eye frame is never auto-rejected — it may be the only record of a moment, so you dispose (spec0004R-EYE-3). Raise it to opt into auto-reject;- only faces clearing
min_face_box(seed0.10of the frame's shorter side) count, so a blinking guest in the far background doesn't demote a portrait; - within a near-duplicate burst, an open-eyed frame is kept over a sharper blink (R-EYE-6).
The face detection that feeds the eye signal is a local ONNX model (UltraFace detector + InsightFace landmarks → eye-aspect-ratio), run with no CGO. It is off by default (local-first, opt-in); enable it in config:
face:
enabled: true
library_path: /path/to/libonnxruntime.so # or .dylib on macOS
# detector_model / landmark_model are optional — when omitted, krites fetches
# the pinned models into its cache once and verifies their checksums.
# optional — the EAR→eye-open calibration (defaults are tuned to real frames):
ear:
closed: 0.12 # EAR at/below which eyes read fully closed
open: 0.26 # EAR at/above which eyes read fully open
The ONNX models are fetched + checksum-verified automatically on first use; only the ONNX Runtime library path is supplied by hand (it's platform-specific).
With it on, the cull demotes blinks to maybe — subject blinking (N% eye-open,
below 50%) — and banks min_eye_open per frame. Off, the cull runs model-free
(no faces ⇒ no eye penalty), exactly as before. The deterministic gate, signal
projection and burst ranking are pure / WASM-safe; only the native adapter is
gated behind config. See spec 0004.
Notes & current limits¶
- The
wedding-defaultprofile is the seed ruleset; its focus/exposure/eye thresholds are tunable starting points (spec0001§6). A configurable profile catalog (krites profile …) lands later; onlywedding-defaultis available today. - Re-culls reuse the analysis cache — tuning a threshold and re-culling
re-resolves verdicts from the cached signals (no re-decode, no model pass), so
it's near-instant on a big shoot (
R-GLOBAL-6).--reanalyzeforces a full recompute; the cache is also invalidated automatically when a signal-affecting setting (the face-size floor, or turning eye detection on/off) changes. - Eye detection runs on the CPU execution provider today; the Apple-Silicon
CoreML acceleration and automatic model fetch (so you don't supply the
model paths by hand) are the remaining
0004follow-ups. RAW frames decode via JPEG/PNG only for now (cull on embedded previews is later).