Adversarial ML
The CLR Journey
From a perspective-warp curiosity to an on-device provenance stack — my research log building a physics-first AI-image detector.
All figures are curated from my original research notebooks — I measured every number here, and I've kept the refutations alongside the wins.
CLR ("Computational Light Reconstruction") began with a single question I couldn't put down: if a real photograph is a record of physics, can I detect the absence of that physics without ever looking at content? This post retraces the journey in order — the early three-architecture exploration, the hypothesis that reframed the problem, the feature-by-feature AUC climb to v1.8, the fusion that broke the warp ceiling, the v2.0 probe that refuted my own generalization claim, and the routed specialist stack that ships on-device today.
Try it live: obscur.rao.nyc — the current stack, running on your own images.
Detection is one half of a broader synthetic-media accountability effort I'm pursuing — the prevention half, a Candidate Likeness Registry I proposed, argues for stopping deceptive likenesses at generation time, before they ever reach a feed.
This is an open research log, not a retrospective. CLR is ongoing — the last version below is where the work stands today, not where it ends, and nothing here has been through a proper deployment yet; the demo above is as close as it gets. I've built the whole research process independently: the corpus, the feature store, the retrain flywheel, the battery that gates every promote. That independence is what has made the journey so enjoyable so far. A refutation can reorganize the entire roadmap in an afternoon — which is exactly what happened in chapter 5 — with nothing pushing me to bury it, so the chapters that follow keep every one of those refutations in view.
Each chapter is a self-contained page. Read in order, or jump to a critical point from the contents below.
The journey at a glance
v1 3 architectures in parallel (transformer / GAN / trees) — trees win on probe scalars
v1.3 hypothesis-grounded features only ...................... AUC 0.627
v1.4–1.5 + residual-heterogeneity and cross-recovery features ... AUC 0.754
v1.6 high-pass content isolation (the pivot)
v1.7 + seam features ....................................... AUC 0.761
v1.8 the 10-feature descriptor FROZEN ...................... AUC 0.775 (tile), ~0.73 (image)
v1.9 warp ⊕ DINOv2 ⊕ capture signature ..................... image AUC 0.897
v2.0 cross-source probe: warp/dino/capture ALL sign-invert
on unseen 2025 generators — generalization = data coverage
v2.3 JPEG container provenance signs raw captures at 0.998
v2.4 shipped regime: hardened warp + fusion (AUC 0.922), full Swift parity
v2.5+ flywheel (scrape → features → warm-start retrain → battery → promote),
specialist priors, domain heads, x-domain gate
v2.6–2.7 directional signatures · WarpGAN distillation (student beats teacher)
next proper deployment — the chapter that isn't written yetHow to read this
- The warp round-trip residual is the spine of everything: warp a 32 px tile with a small random homography, warp it back, and measure what the double resampling destroyed. Real sensor noise is fragile; synthetic texture is not. Chapter 2 makes this precise.
- Numbers are reported at the level they were measured: per-tile AUC (weak by design), per-image AUC (aggregation recovers signal), and held-out battery results (what actually gates a ship).
- Negative results are first-class citizens here. The crop-bypass fix, the seam features going dead, the v2.0 inversion table, and the anomaly-route refutation each changed the architecture more than most of my wins did.
Contents