- Forensic report: adds screenshot disclosure explaining that photographic forensic
tests don't apply to UI screenshots, LCD pixel grid artifacts mimic diffusion
harmonics, and verdict should be interpreted with this limitation in mind
- Court brief: overrides conclusion/recommendation text when screenshot detected,
recommending manual content review instead of photographic forensics
feat: overhaul screenshot detection + suppression + explanation text (v7)
Three remaining false positive signals on macro DSLR images:
- Vignetting cos⁴θ (+0.40→+0.12): macro lenses have non-standard field illumination
- Bokeh Shape (+0.30→+0.09): macro bokeh is extremely smooth/circular from long focal length
- Fixed Pattern Noise (+0.20→+0.06): smooth bokeh background has low row/column variance
All suppressed at ×0.3 multiplier. Should push Optical Agent from +0.008 toward ~-0.02
and P(Fake) from 46.4% toward 44-45%, matching the portrait photo floor.
The old Laplacian-based bokeh detection in m05_autocorrelation() failed for macro
DSLR images because the 10%-of-peak-sharpness threshold didn't reliably capture
the bokeh region when the sharp-to-smooth transition was gradual.
New approach uses uniform_filter to compute local variance (E[X²]-E[X]²) over
32×32 windows, then thresholds at 5% of the P95 variance. This works because:
- Real bokeh: P95 is high (sharp subject), most pixels are far below → detected
- AI smooth: P95 is low (<50), guard clause blocks bokeh excuse → override fires
- Normal photo: variance spread evenly, few pixels below 5% of P95 → no false trigger
For the Unsplash macro DSLR test image, this should:
- Drop Autocorrelation Peak from +0.80 to +0.15 (bokeh explained)
- Remove override_suppression flag → modality ×0.1 can further reduce to +0.015
- Move Generative Model Agent from ~+0.054 to ~-0.02 (neutral/authentic)
- Push P(Fake) from ~46.9% to ~44-45%
v5: Add minimum Bayer margin (0.005) to prevent JPEG-induced false Bayer detection on AI images