Fusion and the ceiling — v1.9
How I diagnosed the warp foundation's structural blind spot and broke it, curated from my original research notebooks.
The evader
The warp residual reads photographic capture physics. So what happens on AI images that were never pretending to be photographs? bahamut.jpg — a piece of generated concept art — gave me the answer: the warp model called it real. Non-photographic AI art has no photo-PRNU to be fragile; its residual looks like "no sensor here," which the photo-trained model reads as benign.
My diagnosis figure: real photos (blue) separate cleanly on residual energy, but the evaders (orange — bahamut, gita1, test set art) cluster at low cross-correlation AND low residual spread. A simple residual-energy gate splits "this probe applies" from "this probe is blind."
I tried the dead end first, and measured it honestly: over a dozen hand-crafted low-level global features added to warp moved image AUC from 0.751 to 0.754 (+0.003). A real painting and an AI painting are indistinguishable at the low level — the difference is semantic. No amount of feature engineering on this substrate was going to close an art gap.
The fusion stack
In v1.9 I kept warp as the foundation and fused two complementary, commercially-clean signals through a small XGBoost head:
- DINOv2-small (frozen embedding, Apache-2.0) — the semantic channel that sees what kind of image this is.
- The capture signature (a compact, learned-free feature family, entirely original) — a generator-agnostic camera cue: a real sensor's color-filter-array demosaicing leaves a periodic signature in the frequency domain that no generator reproduces. Native resolution only — downsampling destroys it. Measured cleanly, it separates real-from-AI at 0.97 on essentially a single measurement.
The decomposition on held-out, art-enriched data:
| stage | image AUC | Δ |
|---|---|---|
| warp, per-tile | 0.606 | — |
| warp-only, per-image | 0.726 | aggregation |
| + DINOv2 | 0.871 | +0.145 |
| + capture signature | 0.897 | +0.026 |
AI-art detection went 35% → 92%; bahamut → 0.99 generated. Warp is not vestigial in this stack — it catches photo-vs-AI-photo cases DINOv2 misses and anchors the head. A screenshot gate (a learned-free flat-pixel heuristic) closed the remaining structural domain: a screenshot is real but not a camera capture, and the camera-anchored stack would otherwise false-fire on it.
The dataset journey underneath
None of the above was measurable without data that evolved in lockstep, so I rebuilt the corpus four times:
- Local/synthetic (v1) — camera photos vs FLUX.1-schnell. Enough to prove the residual idea.
- The corpus scale-out — public and scraped pools, including native-resolution phone hard-negatives and screenshots. This is what surfaced my real failure modes.
- The failure-aware retrain set — thousands per class, deliberately enriched with everything my then-current model got wrong. Per-pool diagnostics exposed the central number: the AI-art pool at 28% accuracy — AI art called real, the blind spot quantified.
- The art corpus — human-art-vs-AI-art, built around a single style-matched CC0 source so the model learns real-vs-AI rather than style-vs-era, plus WikiArt on the real side. Provenance-curated and commercial-safe.
The durable meta-finding: base dataset size plateaus; composition and calibration dominate. Scale-alone ablations showed a several-fold larger base buying nothing — every real gain after v1.8 came from what was in the data, not how much. (My early instinct — "datasets should always be mixed, but heavily weighted toward the category" — turned out to be the operating principle of every retrain since.)
At 0.89–0.90 held-out AUC, the fusion stack became the shippable commercial detector. It also quietly carried an assumption I had never examined: that its generalization came from physics rather than from coverage. The next chapter is the experiment where I tested that assumption against unseen 2025 generators — and the answer that reorganized my whole roadmap.