ImagesImage forensics, in two tiers
Provenance first, physics second. We never let a statistical guess override a record the file carries about itself.
Tier 1 · provenanceWhat the file says about itself
We walk JPEG segment markers, PNG chunks and RIFF containers by hand — no decoding library — to recover:
- C2PA Content Credentials, including the
trainedAlgorithmicMedia declaration - Full EXIF IFD walk: camera make, model, lens, exposure, aperture, ISO, GPS
- PNG
tEXt/iTXt/zTXt chunks, where Stable Diffusion writes its prompt and ComfyUI writes the entire workflow graph - XMP packets, including Adobe's digital source type
- Generator strings for DALL·E, Midjourney, Firefly, Imagen, Flux, Ideogram, Leonardo, NovelAI, Grok and more
- JPEG quantisation tables, which recover the encoder's quality setting
Tier 2 · pixelsWhat the physics says
When metadata has been stripped — as it is by every social platform — we fall back on capture physics:
- Cross-channel residual agreement d=1.35
Mean correlation between the red, green and blue high-frequency residuals. - Chroma residual energy d=1.20
The same physics stated as an energy rather than a correlation: how much micro-texture is left once the shared luminance component is subtracted. - Per-channel tone-curve comb d=0.87
Bin-to-bin roughness of each colour histogram. - Saturation dispersion d=0.81
Spread of per-pixel saturation. - Gradient kurtosis d=0.72
Natural images have heavy-tailed gradients: mostly flat, with rare hard edges. - Luminance tone-curve comb d=0.72
The luminance version of the per-channel comb. - Genuinely flat tiles d=0.67
Fraction of 16x16 tiles whose residual is essentially zero. - Histogram gap ratio d=0.58
Empty bins left by in-camera tone mapping and quantisation. - Spectral falloff exponent d=0.45
Natural scenes follow a 1/f^a power spectrum. - High-frequency energy share d=0.40
Proportion of spectral energy above mid-band. - Demosaicing periodicity d=0.35
Bayer sensors interpolate half their green samples, leaving a two-pixel periodic signature. - Mid-band spectral energy share d not measuredprior
Share of spectral power in the 0.10–0.40 Nyquist band. - Neighbour-pixel micro-contrast d not measuredprior
Mean |pixel − mean of 4-neighbours| over mean luminance. - Noise–luminance coupling d not measuredprior
Correlation of per-tile noise against √luminance. - Spectral entropy d not measuredprior
Shannon entropy of the radial Fourier power profile. - Noise-level slope d not measuredprior
OLS slope of per-tile noise on √luminance — the same shot-noise physics as the coupling above, stated as a slope rather than a correlation. - Noise non-uniformity d not measuredprior
Coefficient of variation of per-tile noise. - Local-entropy variation d not measuredprior
Spread of per-tile Shannon entropy. - Upsampler grid energy d not measuredprior
Mean excess energy at exact half/quarter Nyquist grid positions. - DCT Benford deviation d not measuredprior
Chi-square deviation of block-DCT first digits from Benford’s law (scaled ×100/N). - Edge density d not measuredprior
Share of Sobel magnitudes above threshold. - Tonal richness d not measuredprior
Distinct 6-bit colours per sampled pixel. - Clipped-pixel share d not measuredprior
Share of pixels at the sensor rails (near-black or near-white).
A d figure is Cohen's separation, measured on the validation sets on Accuracy. Tests tagged prior showd not measured because they never were — they carry a literature prior with a deliberately wide spread and a low weight, and we will not print a separation number we have not earned.
A camera cannot paint all three colours at once
The measurement that carries this tier is not a stylistic tell that a better model will fix. It is a consequence of how the two kinds of image are physically made.
A camera builds each colour channel from different sensor sites. The photons arriving at a red-filtered well are counted independently of those at its green neighbour, so shot noise is uncorrelated between channels. The demosaicer then interpolates each channel with a different kernel — green has twice as many samples as red or blue on a Bayer grid. And the lens focuses red and blue light at slightly different planes, so their fine detail is not even the same detail. Take the high-frequency residual of each channel and the three disagree: on our 29 camera originals, mean correlation 0.883.
A latent-diffusion decoder makes all three channels from one shared latent tensor. The micro-texture is essentially a single pattern painted three times. The residuals agree almost perfectly: on our 14 generated images, mean correlation 0.980. That is d = 1.35, and unlike every sensor-level test it survives downscaling, because it is a property of the colour relationship rather than of the pixel grid.
It has one fatal enemy, and we would rather name it than hide it: JPEG 4:2:0 chroma subsampling averages colour over 2×2 blocks, which forces the channels to share fine detail and fakes the synthetic signature on real photographs. So we parse the JPEG SOF sampling factors, and on a subsampled file we cut these tests to 12% of their weight and say so on the result card. See the numbers.
Three decisions that stopped it lying
Separate spreads per class, but not the measured one. Generated images cluster far more tightly than camera originals (σ = 0.014 against 0.100), and camera values drift upward whenever a file is resized. Encoding the measured σ would assert that every generator, present and future, lands in exactly the same spot — on the validation set that produced five false accusations on native photographs and eighteen on recompressed ones. We use 0.9 × σcamera: the useful asymmetry without the unearned confidence.
Weights are d2.5, not d. With linear weights a cluster of weak, mutually-agreeing signals could outvote the one strong one. A product shot measuring 0.9965 cross-channel correlation — about as synthetic as a number gets — was averaged down to an inconclusive 57%. Raising the exponent lets decisive evidence actually decide.
A confidence multiplier on the whole tier. Every pixel measurement assumes it is seeing something close to what the sensor or the decoder produced. Resizing, recompression and subsampling each erode that assumption, and past a threshold the numbers stop meaning what the calibration says. So the tier is shrunk toward the prior in proportion to the damage — a mangled file returns "inconclusive" rather than a confident guess.
What we got wrong the first time
We originally wrote these baselines from the forensics literature. Measured against real camera originals and real generator output, two were directionally backwards. Deviation from Benford's law is widely cited as a synthesis indicator; JPEG-quantised camera output actually deviates more. Shot-noise theory predicts brightness and noise correlate positively; in real photographs the correlation is usually negative, because bright regions are skies and dark regions are foliage. A third, saturation dispersion, is real but points the opposite way to the folklore — generators produce more saturation variance than camera JPEGs, not less.
Every centre on this page is now measured rather than cited — with explicit exceptions. Tests tagged prior in the list above carry literature priors with deliberately wide spreads and low weights, marked prior wherever they appear, until the next measurement round. The scripts that produced the measured centres ship in research/.