Record pipeline-lattice reframing and registered-v3 phase lock

Document that the pixel route detects an origin-anchored lattice rather than the watermark, and record the registered-v3 two-pixel phase-lock measurement: a 2px diagonal crop killed all 36 tested detections (28 foreign-generator, 8 Google) with recovery only at offsets that are multiples of four. Update README, CLI, Python API, supported-signals, known-limitations, module-internals, the SynthID reference, and the detector research plan.
This commit is contained in:
Victor Kuznetsov
2026-08-16 21:53:50 -07:00
parent 8eb9c06265
commit e74b06d1a0
8 changed files with 2679 additions and 134 deletions
+41 -18
View File
@@ -30,7 +30,7 @@ removal.
| Goal | Command | GPU |
| --- | --- | --- |
| Find provenance signals and watermarks | `identify` | No |
| Detect the SynthID pixel carrier in the calibrated image-size range | `detect-synthid` | No |
| Detect a generation-pipeline pixel lattice, experimental, not the watermark | `detect-synthid` | No |
| Verify supported OpenAI SynthID from pixels with the official remote API | `verify-openai-synthid` | No |
| Remove known visible AI marks | `visible` | No |
| Erase a region you select | `erase` | No |
@@ -78,31 +78,54 @@ Inspect an image:
remove-ai-watermarks identify image.png
```
Detect the supported SynthID pixel carrier after installing the pixel runtime:
Signed provenance is the supported route for SynthID and `identify` reads it.
The pixel route below is experimental and answers a different question. Install
the pixel runtime first:
```bash
uv tool install --force "remove-ai-watermarks[pixels]"
remove-ai-watermarks detect-synthid image.png
remove-ai-watermarks detect-synthid resized.png --register-scale
remove-ai-watermarks detect-synthid native-period.png --fixed-period
```
This detector is positive-only and limited to one measured carrier family in
This is experimental and does not detect the SynthID watermark. The statistic it reports is
destroyed by cropping off the tile grid — a seven-pixel crop on the large branch
and a two-pixel crop on the ordinary-size registered-v3 route — while SynthID's
published evaluation keeps 99.97% of its detection rate under aggressive crop
and resize, so a positive identifies the generation pipeline rather than the
mark. Measured on 2026-08-16: it accepted 8 of 11 fresh large Google generations
and 29 of 223 images from other generators, and 0 of 6 when the same positives
were cropped off the tile grid; a two-pixel crop also removed all 36 tested
registered-v3 detections across foreign-generator and Google images. It is
positive-only
and limited to one measured lattice family in
the [calibrated image-size range](docs/synthid.md#32-how-our-tool-detects-the-supported-carrier).
The native default uses the fixed fold through 10 megapixels and a separately
challenged opponent-color large-image branch above 10 through 18 megapixels;
the large branch requires both sides to be at least 2,048 pixels. Both expect
the recovered carrier at its measured 16-pixel sampling scale.
`--register-scale` opts into a much slower bounded scale search
for resized images from 250,000 through 10,000,000 decoded pixels, with both
sides at least 64 pixels. Its measured positive scale range is approximately
0.65 through 1.5; 0.5x resizes remain outside reliable detection. `identify`
keeps the fast default. `not_detected` or `unsupported` is not a clean-image
guarantee.
The production default uses registered-v3 from 250,000 through 10,000,000
decoded pixels with both sides at least 256 pixels. When that route abstains,
a narrower opponent-registered-v1 fallback covers 1 through 10 megapixels,
both sides at least 768 pixels, and carrier periods 7.9 through 12.0. Period-8
candidates additionally require a decoded-pixel block-edge veto that separates
the measured carrier from ordinary JPEG lattices. The
separately challenged opponent-color large-v1 branch runs
above 10 through 18 megapixels; large-v1 requires both sides to be at least
2,048 pixels. Registered-v3 is a bounded scale search with a measured positive
scale range of approximately 0.65 through 1.5. The fallback recovered 49/49
losslessly resized views at scales 0.5 through 0.75 from seven official
pixel-positive parents. The period-8 veto rejected all 1,790 previously crossing
codec-lattice controls, while 350 matched 0.5x Picsum controls had no base
crossing; the earlier period-band rule also accepted 0/1,000 frozen controls.
`--fixed-period` explicitly selects the faster legacy 16-pixel diagnostic; it
is not a production positive route. `--register-scale` forces the registered
expert, including on geometry where the default would choose large-v1.
`identify` uses the production router. `indeterminate` means no qualified local
expert crossed its threshold; `unsupported` means no expert covers the input.
Neither is a clean-image guarantee.
The large native branch is not recompression-robust: all seven official large
positives fell below its frozen threshold after same-size JPEG-95 and JPEG-90
re-encoding. Use it for original or losslessly copied pixels, and treat a miss
after lossy transcoding as inconclusive.
The large native and opponent-registered branches are not recompression-robust.
The large branch lost all seven official positives after same-size JPEG-95 and
JPEG-90; the fallback retained 0/63 JPEG-95, JPEG-85, and WebP-95 views. Use
them for original or losslessly copied pixels, and treat a miss after lossy
transcoding as inconclusive.
For supported OpenAI images, the optional official verifier provides a broader
pixel-watermark verdict than the incomplete local OpenAI research signal:
+53 -21
View File
@@ -57,36 +57,58 @@ remove-ai-watermarks identify image.png --no-visible
```
Despite the historical option name, `--no-visible` skips all pixel detectors,
including the supported SynthID carrier, visible marks, open DWT-DCT, and
including the pipeline lattice described below, visible marks, open DWT-DCT, and
TrustMark. Metadata inspection still runs.
## Detect the supported SynthID pixel carrier
## Detect the generation-pipeline pixel lattice (experimental)
```bash
remove-ai-watermarks detect-synthid image.png
remove-ai-watermarks detect-synthid image.png --json
remove-ai-watermarks detect-synthid resized.png --register-scale
remove-ai-watermarks detect-synthid native-period.png --fixed-period
```
The command returns one of `detected`, `not_detected`, or `unsupported`. The
runtime detector covers one frozen periodic carrier family in the
This route is experimental. Signed provenance, read by `identify` and confirmed
against the provider by `verify-openai-synthid`, remains the supported way to
establish SynthID. The command returns one of `detected`, `indeterminate`, or
`unsupported`, and it does not detect the SynthID watermark: its statistic disappears when the image
is cropped off the tile grid, and it changes when the generator's pipeline
changes, so read a positive as evidence about the pipeline and never as a
watermark claim. The JSON carries `identifies_watermark` and
`tile_aligned_crop_required` for exactly this reason. The
runtime detector covers one frozen periodic lattice family in the
[calibrated image-size range](synthid.md#32-how-our-tool-detects-the-supported-carrier)
and needs the `pixels` extra. The native default uses the fixed fold from
1,000,000 through 10,000,000 decoded pixels and the separately challenged
opponent-color large branch above 10,000,000 through 18,000,000 pixels when
both sides are at least 2,048 pixels. It never resizes the input and does not
register a carrier whose sampling period changed through spatial resampling.
`--register-scale` enables a substantially slower bounded search over measured
carrier periods for images from 250,000 through 10,000,000 decoded pixels, with
both sides at least 64 pixels. It is opt-in and is not used by `identify`.
The measured positive scale range is approximately 0.65 through 1.5; 0.5x
resizes are not reliably detected.
The native large branch is also codec-sensitive: same-size JPEG-95 and JPEG-90
re-encoding reduced its seven official large positives from 7/7 to 0/7. A miss
on a lossy re-encode is therefore inconclusive.
It is positive-only: `not_detected` means the score stayed below this detector's
threshold, while `unsupported` means the image geometry is outside its scope.
Neither result proves that another SynthID epoch or payload is absent.
and needs the `pixels` extra. The production default uses registered-v3 from
250,000 through 10,000,000 decoded pixels with both sides at least 256 pixels.
An opponent-registered-v1 fallback covers 1 through 10 megapixels, both sides
at least 768 pixels, and selected carrier periods 7.9 through 12.0. Period-8
candidates must also pass an opponent-color block-edge veto for the native JPEG
lattice. The
separately challenged opponent-color large-v1 branch covers above 10,000,000
through 18,000,000 pixels when both sides are at least 2,048 pixels.
Registered-v3 performs a bounded carrier-period search and independent split-
patch confirmation. Its measured positive
scale range is approximately 0.65 through 1.5. The fallback recovered 49/49
lossless 0.5x-0.75x views from seven official positives. Its period-8 veto
rejected 1,790 codec-lattice crossings, and 350 matched 0.5x controls produced no
base crossing. The earlier period-band rule accepted 0/1,000 post-freeze Picsum
controls. `identify` uses this production router.
`--fixed-period` explicitly selects the faster legacy fixed-v2 diagnostic below
10 megapixels. It does not resize or register the carrier and is not a
production positive route. `--register-scale` forces the registered-v3 cascade,
including its opponent fallback, on geometry where the default would select
large-v1.
The native large and opponent-registered branches are codec-sensitive. The
large branch fell from 7/7 to 0/7 after same-size JPEG-95 or JPEG-90; the
fallback retained 0/63 JPEG-95, JPEG-85, and WebP-95 views. A miss on a lossy
re-encode is therefore inconclusive.
It is positive-only: `indeterminate` means the score stayed below this
detector's threshold, while `unsupported` means the image geometry is outside
its scope. Neither result proves that another SynthID epoch or payload is
absent.
JSON output includes the exact reason plus provider scope, backend, pixel
preservation, and metadata-use audit fields.
## Verify OpenAI SynthID from pixels
@@ -110,6 +132,16 @@ Retention, `--acknowledge-upload` is mandatory. This command is never called by
`identify`. `not_detected` means only that OpenAI's verifier did not recognize a
supported watermark in this file; it is not proof of human authorship.
The built-in client bounds the request at 120 seconds and disables automatic
SDK retries, so one acknowledgement cannot silently upload the media multiple
times. A timeout, disconnect, malformed response, access failure, or rate limit
is an error, never a negative watermark verdict. API failures expose status,
error code, request id, `Retry-After`, and whether an explicit caller-controlled
retry is appropriate through `OpenAIProvenanceError`; the verifier itself never
retries an upload.
The JSON result uses the same provider-scope, backend, pixel-preservation, and
metadata-use audit fields as the local detector.
The Python API enforces the same boundary with the required explicit intent
flag `verify_openai_synthid(path, acknowledge_upload=True)`.
+65 -15
View File
@@ -64,22 +64,72 @@ identity or exact texture, and each then runs the same face stage.
`qwen-zimage` is the higher fidelity of the two. Both are large, slow, and may
still alter small text or difficult faces.
### Local SynthID detection covers one image-carrier family
### The experimental pixel route reads a pipeline lattice, not the watermark
Google does not publish the proprietary SynthID payload decoder. The project
ships a positive-only detector for one measured periodic image carrier in a
calibrated image-size range, plus provenance-based recognition
from Google AI C2PA or current OpenAI C2PA with an explicit watermark action.
It does not cover images outside the selected mode's size range, crop, strong
JPEG compression, video, or future carrier epochs. Arbitrary dimensions inside
the default range are supported only while the recovered carrier retains its
measured 16-pixel sampling lattice. A spatial resize changes that period. The
opt-in `detect-synthid --register-scale` mode searches a bounded
fractional-period range for images from 250,000 through 10,000,000 pixels, but
requires both sides to be at least 64 pixels. Its measured positive range is
approximately scale 0.65 through 1.5; a 0.5 resize aliases the carrier with
ordinary resize lattices and is not reliably detected. It is also slower. A
`not_detected` or `unsupported` result is not a negative universal verdict, and
Signed provenance is the primary and supported route for SynthID in this
project; the pixel route described here is experimental. Google does not
publish the proprietary SynthID payload decoder, and nothing
in this project reproduces one. What the local pixel route detects is a
periodic lattice anchored at the image origin: it is destroyed by a crop of
seven pixels on the large branch and by a crop of two pixels on the
ordinary-size registered-v3 route, whereas the published SynthID evaluation
retains 99.97% of its detection rate under aggressive crop and resize. A
positive therefore
identifies the generation pipeline that leaves the lattice, and says nothing
about whether the image carries a watermark. It also changes when a provider
changes pipeline: output from `gemini-2.5-flash-image` scores at the level of
unrelated photographs. The project additionally offers provenance-based
recognition from Google AI C2PA or current OpenAI C2PA with an explicit
watermark action, and that provenance route is the only one that speaks about
a watermark at all.
The ordinary-size route shares the same phase lock. On 2026-08-16 a two-pixel
diagonal crop removed all 28 in-geometry foreign-generator detections and all 8
detected Google provenance positives from registered-v3, with the statistic
recovering only at crop offsets that are multiples of four. The route therefore
fires on other vendors' images because those pipelines leave a matching
origin-anchored lattice, not because a watermark is present.
The published control rates for this route were all measured on photographs.
Against other generators' output, which is the population a provenance tool is
actually pointed at, the shipped runtime accepted 29 of 223 signed non-Google
images on 2026-08-16: 13.0% overall, 24.1% on Adobe Firefly, with a top score
of 3.01 against a threshold of 1.0. Treat a positive as evidence only when the
alternative generators have been ruled out by other means.
Sensitivity has only ever been reported on images the route was calibrated
against. The first out-of-distribution measurement was taken on 2026-08-16: 11
images generated at 5632x3072 by `gemini-3.1-flash-image`, a model that did not
exist when the large branch was calibrated, written straight from the API with
no lossy-codec history and watermarked by Google's documented policy that all
generated images carry SynthID. Eight were detected and three returned
indeterminate, a rate of 72.7% with a one-sided 95% lower bound of 43.6%. The
sample is small and one provider wide, so read it as an order of magnitude
rather than an operating point.
Cropping the same images to 4096x2560 on the tile grid retained 4 of 6. Taking
the identical crop seven pixels off the grid retained 0 of 6, with every score
negative. A crop that is not tile-aligned removes the signal entirely, which is
the sharpest way to see that this route does not read the watermark: the
published SynthID evaluation keeps 99.97% of its detection rate under
aggressive crop and resize.
The route's declared scope is narrower still. It does not cover images outside
the selected mode's size range, crop, strong
JPEG compression, video, or future carrier epochs. The production default
searches a bounded fractional-period range from 250,000 through 10,000,000
pixels and requires both sides to be at least 256 pixels. Its measured positive
range is approximately scale 0.65 through 1.5. A precision-first opponent-color
fallback covers only 1 through 10 megapixels, sides of at least 768 pixels, and
periods 7.9 through 12.0; it recovered the measured lossless 0.5x-0.75x cohort.
At period 8, an additional block-edge veto rejects the ordinary JPEG lattice;
this does not make arbitrary crops or codecs supported. The fallback retained
0/63 lossy JPEG/WebP views, so a lossy miss remains inconclusive. Above 10
through 18
megapixels, the separate large-v1 route requires native, lossless pixels and
both sides at least 2,048 pixels. The fixed-v2 branch is retained only behind
the explicit `detect-synthid --fixed-period` diagnostic. A
`indeterminate` or `unsupported` result is not a negative universal verdict, and
removal still requires the matching provider oracle for confirmation.
For important outputs:
+153 -17
View File
@@ -451,7 +451,7 @@ metadata extraction from verdict logic:
both extractors reach the same answer. It did not, and the record path silently
reported no SynthID for images the file path flagged.
- `identify` preserves the path-based API and adds the optional registered
visible-mark, open invisible-watermark, and supported SynthID carrier
visible-mark, open invisible-watermark, and generation-pipeline lattice
detectors after extraction.
### SynthID periodic carrier detector
@@ -468,17 +468,29 @@ ceiling does not require multiple three-channel float workspaces. The model hash
is pinned by a test, and the unchanged operating threshold is
`0.17357069773071196` through 10 megapixels.
The direct API returns `detected`, `not_detected`, or `unsupported`; the last is
distinct because no resize is performed. The fixed branch is selected from
1,000,000 through 10,000,000 decoded pixels. The frozen threshold accepted
That fixed threshold is not production-qualified. A later source-fresh
Open Images test-split challenge produced 5 crossings among the 211 images in
its supported geometry. A precision-first `0.28` replacement is frozen as a
research candidate after retaining all 12 available source-diverse native
positives and rejecting those five crossings. It then failed the second
untouched holdout at 1/213, with score `0.322542963`. The replacement is
rejected and fixed-v2 remains an explicit diagnostic only.
The direct API returns `detected`, `indeterminate`, or `unsupported`. Passing
`register_scale=False` selects fixed-v2 from 1,000,000 through 10,000,000
decoded pixels as an explicit diagnostic. Its frozen threshold accepted
none of 5,000 public COCO views balanced across every observed target geometry,
and none of a separate 5,000-view challenge over 256 generated geometries
covering every pair of modulo-16 edge remainders. The original 2048x2048
verdicts and exact scores remain unchanged. Runtime matches do not attribute a
provider. `identify` adds only positive matches as high-confidence
evidence and never turns a local negative into a clean verdict.
The result envelope also names the signal family, provider scope, backend,
whether metadata contributed to the verdict, whether pixels were preserved,
and an explicit reason for unsupported or indeterminate results. These fields
are shared with the official OpenAI verifier's JSON boundary.
The native default selects `synthid-periodic-tile-large-v1` above 10 through 18
The production router selects `synthid-periodic-tile-large-v1` above 10 through 18
megapixels when both dimensions are at least 2,048 pixels. It evaluates all
phase-aligned 2,048-square windows and combines the minimum fixed-template,
Red-minus-Green, and Blue-minus-Yellow spatial correlations with the most
@@ -532,7 +544,67 @@ final controls. Multiplying the canonical score by spectral-period confidence
also accepted two. That baseline was rejected rather than shipped at its
discovery threshold.
The opt-in `register_scale=True` path is the later calibrated successor. It
The research-only
[`synthid_affine_lattice_probe.py`](../scripts/synthid_affine_lattice_probe.py)
adds split-confirm synchronization. It estimates complex harmonic coherence on
one checkerboard of patches, confirms the selected period on the other, and
reports amplitude-aware confirmation, a locally content-whitened multichannel
code match, and phase-preserving and cyclically registered template scores. A
0.1-pixel grid recovered the expected
12.8, 14.4, 17.6, and 19.2 periods in 20/20 transformed views from five official
positive parents. A provisional conjunction accepted none of 800 corresponding
views from 200 oracle-negative parents, none of 469 OpenAI-labeled rows, and
three of 276 broad non-Google rows whose TC260 or Samsung provenance prevents
treating them as clean oracle negatives. This probe is not runtime routing:
positive diversity is still inadequate, period 8 remains rejected, and the
amplitude stage currently handles isotropic scale at zero rotation only. Full
protocol and caveats are in the detector research plan.
The whitened match uses neighboring noncarrier bins to estimate complex
Green/opponent-color covariance around every selected harmonic. It corrected a
period-24 alias on one native official positive, giving the broad native search
the correct period 16 on all five ordinary-size positives. It was retained only
as a candidate reranker: its positive-to-negative margin was smaller than the
existing spatial-template margin in both the native pilot and a locked 0.8
resize challenge. Two of the three TC260/Samsung-provenance challenge crossings
also matched the full whitened code more strongly than the weakest official
large positive, so the pixel result identifies a compatible signal family, not
a provider.
The same probe also exposes a payload-agnostic H5 confirmation. It estimates a
complex harmonic vector independently on the two checkerboards and measures
their fixed relative-phase inner product; the codeword need not match the known
template. Free cyclic-shift selection was rejected because natural phase aliases
overlapped the controls. The fixed all-harmonic statistic separated five native
official positives from 130 controls with margin `0.1619`, and five 0.8-resized
views from 200 fresh-parent controls with margin `0.1541`; all seven large
official positives also passed the observed gap. It remains research-only
because these tests supplied the period, reuse one negative source family, and
contain only 12 independent positive parents.
The separate research-only
[`synthid_cyclostationary_probe.py`](../scripts/synthid_cyclostationary_probe.py)
measures full complex cross-channel spectral correlation at carrier shifts
against neighboring-shift same-image nulls. It recognizes synthetic amplitude
modulation and rejects both independent noise and a purely additive carrier.
The real native pilot overlapped completely: five official-positive joint
contrasts ranged from `-0.0027` to `0.0337`, while 130 controls reached `0.0593`.
The cyclostationary branch is rejected rather than tuned on new frequency bands.
The affine-lattice research CLI also supports symmetric in-memory JPEG and
top-left crop challenges. At fixed native period 16, codec-specific
phase-preserving template thresholds retained all five repeated positive views
and accepted none of 80 locked controls at JPEG qualities 95, 90, and 80. The
locked margins declined from `0.1054` to `0.0257`; whitened and unknown-codeword
scores were rejected for lossy JPEG. A separate registered crop conjunction
retained all five views and accepted none of 80 controls after both 5% and 10%
top-left crops, with registered-template margins above `0.22`. These are
research pilots, not runtime experts: the period was supplied, positive parents
were reused, and only one codec implementation and one negative family were
tested.
The `register_scale=True` path is the calibrated ordinary-size production
expert. It
keeps the harmonic search, adds three-level scale-space consistency and quadrant
agreement. Its calibrated decision requires the canonical winner to be the
strongest spectral-period candidate, its three-way amplitude to cross the
@@ -556,11 +628,51 @@ accepted seven, so fixed and registered results cannot safely be unioned. In
overlapping geometry the registered decision remains the validated path;
fixed-only evidence is a diagnostic rather than a universal-cascade positive.
The research-only router in `scripts/synthid_routed_expert_bank.py` encodes that
precedence and always abstains on fixed-only evidence. Its three-observation
schema keeps the fixed, registered, and large identities explicit. Registered
and large crossings are positive routes only in their disjoint calibrated
ranges; the bank never returns a clean-image verdict.
A later source-fresh 3,000-image Open Images test-split challenge superseded the
registered-v2 precision claim: it accepted 4 of 2,997 supported controls. The
registered-v3 confirmation uses disjoint patch groups for phase, cyclic
amplitude, and held-out-codeword evidence. It rejected all four crossings,
retained 147 of 148 base-accepted source-diverse positives, and retained all 359
base-accepted views in a dense 0.65-1.50 transform matrix over 12 independent
parents. Frozen unchanged, it then accepted 0/2,996 controls from a second
nonoverlapping Open Images cohort and 0/2,366 supported controls from a
3,000-image COCO second-family challenge. Registered-v3 is now the default
ordinary-size positive route. The exact gates, acquisition hashes, and rejected
weak-signal rescue are recorded in the detector research plan.
Every one of those control rates is photographic. Against 223 corpus images
whose C2PA names a non-Google generator, the unchanged entry point accepted 29
(`0.130`, Adobe Firefly `0.241`, highest foreign score `3.01`), all from
registered-v3. The branch reads a lattice shared across generation pipelines,
which is why `identify` reports it as the experimental `pipeline_lattice`
signal and never as a watermark.
The branch is also phase-locked to the image origin, exactly like the large
expert. A two-pixel diagonal crop killed all 28 in-geometry foreign detections
and all 8 detected Google provenance positives (maximum remaining scores
`0.779` and `0.311` against the `1.0` threshold); the signal recovers only at
offsets that are multiples of four. Registered-v3 therefore detects the same
crop-destroyed generation-pipeline lattice as `large-v1`, on ordinary sizes.
When registered-v3 abstains, opponent-registered-v1 searches the same frozen
template in Red-minus-Green and Blue-minus-Yellow space. It reranks three
separated scale candidates with fixed RGB and two spatial opponent-color gates,
then accepts only periods 7.9-12.0 on 1-10 megapixel rasters whose sides are at
least 768 pixels. Period-8 candidates additionally require Red-Green and
Blue-Yellow 8-pixel edge ratios no greater than `1.05`; this vetoes the
deterministic JPEG block lattice without using container metadata. The final
rule recovered 49/49 lossless 0.5x-0.75x views from seven official-positive
parents. It rejected all 1,790 measured period-8 codec crossings, while 350
identically resized controls had no base crossing and the earlier period-band
rule accepted 0/1,000 post-freeze Picsum controls. Period 12.8 remains excluded,
and lossy JPEG/WebP views remain inconclusive.
The runtime precedence is registered-v3, the bounded opponent fallback, then
large-v1 above 10 megapixels. Passing
`register_scale=False`, or the CLI's `--fixed-period`, selects the legacy fixed
diagnostic explicitly. The research bank in
`scripts/synthid_routed_expert_bank.py` keeps all three observations for audits.
Neither runtime nor research routing returns a clean-image verdict.
An unchanged registered challenge from 10 to 18 megapixels retained only 1 of
37 Google candidates and zero of 89 non-Google controls. Twenty-eight positives
@@ -635,6 +747,17 @@ period-8 model retained 5 of 158 and zero controls, then 1 of 40 fresh OpenAI
rows and 1 of 50 fresh controls. They neither explain the known oracle-positive
miss nor justify runtime routing.
An image-level patch-bag model over nine normalized high-pass patches was the
strongest later local OpenAI classifier. It accepted 324/1,364 development-test
OpenAI rows with 4/3,373 heterogeneous controls, then transferred to 120/486
OpenAI rows, 8/504 general controls, and 5/33 same-provider non-assertion rows
in the later temporal challenge. Assertion enrichment over the same-provider
stratum was not independently significant (`p = 0.151`, one-sided exact test).
JPEG-95 reduced the unchanged conjunction to
1/486 positives and zero controls. The native temporal hits were complementary
to the signed period-8 hits, but the same-provider rate and codec collapse
identify another export noiseprint rather than a runtime SynthID expert.
The separate OpenAI period-8 DTCWT component is persistent rather than tied to
one short rollout: exact-generator asserted hits were 3/16, 46/365, and 26/200
from May through July, with 75/581 overall versus 1/52 same-generator rows
@@ -655,12 +778,12 @@ development positives and finished at 0/50 positives, 0/199 controls, and AUC
0.374. Neither branch is part of runtime routing; full split and oracle details
are in the detector research plan.
The separately measured geometry range remains 250,000 through 10,000,000
decoded pixels with both sides at least 64 pixels. The default path and
`identify` remain native-only and select either the fixed or large branch by
geometry; scale registration stays opt-in. A 20-image real-corpus drift check was
byte-identical after integration. The calibration history and caveats are in the
linked detector research plan.
The separately measured registered geometry range remains 250,000 through
10,000,000 decoded pixels with both sides at least 256 pixels. The default path
and `identify` use registered-v3, then the narrower opponent-registered-v1
fallback in its 1-10 megapixel domain, and large-v1 above 10 megapixels. A
20-image real-corpus drift check was byte-identical after the earlier v2 integration.
The calibration history and caveats are in the linked detector research plan.
### Official OpenAI SynthID verifier
@@ -681,6 +804,19 @@ multipart file to `content_provenance_checks.create` and parses exactly one
used as fallback evidence. Missing, duplicate, or unknown SynthID outcomes are
errors rather than negative detections.
The default SDK client has a 120-second request timeout and zero automatic
retries. One upload acknowledgement therefore authorizes at most one media
transmission rather than inheriting the SDK's retry default. Request logs keep
the endpoint, temporary basename, media type, byte count, timeout, retry policy,
duration, HTTP status, error code, and request id when available, but omit the
source path, image bytes, credentials, and decoded-pixel fingerprint.
`OpenAIProvenanceError` preserves the status, API error code, request id,
`Retry-After` value, and a transient-only `retryable` flag. The library does not
automatically act on that flag: an explicit caller invocation is required for
every additional upload. Transport and schema failures remain errors rather
than becoming `not_detected` or a local detector result.
The result remains provider-scoped and positive-evidence-only. `not_detected`
does not mean human-created, and the official endpoint's published prohibition
on repeated reverse-engineering or evasion queries prevents using this backend
+40 -17
View File
@@ -12,7 +12,7 @@ path that still runs on CPU and combines `video` and `diffusion`. Add `heif`
independently when path-based pixel APIs must decode HEIC, HEIF, or AVIF. See
the complete [feature-extra matrix](installation.md#feature-extras).
## Detect the supported SynthID carrier
## Detect the generation-pipeline lattice (experimental)
Install `remove-ai-watermarks[pixels]`, then call the lazy top-level API:
@@ -20,26 +20,48 @@ Install `remove-ai-watermarks[pixels]`, then call the lazy top-level API:
import remove_ai_watermarks as raiw
result = raiw.detect_synthid("input.png")
print(result.status) # "detected" | "not_detected" | "unsupported"
print(result.status) # "detected" | "indeterminate" | "unsupported"
print(result.score) # float for a supported image size, otherwise None
print(result.threshold) # frozen operating point
print(result.reason) # support or non-detection reason, otherwise None
# Opt in when the image may have been spatially resized.
registered = raiw.detect_synthid("resized.png", register_scale=True)
# Force the legacy native-period diagnostic only when auditing that expert.
fixed_diagnostic = raiw.detect_synthid("native-period.png", register_scale=False)
```
The detector is positive-only and covers one measured periodic carrier family
This is experimental and is not a watermark detector. Signed provenance through
`identify` is the supported SynthID route. Its statistic is destroyed by a seven-pixel
crop while the published SynthID evaluation survives aggressive crop and
resize, so a positive identifies the generation pipeline. The result exposes
`identifies_watermark` and `tile_aligned_crop_required` so a caller cannot
reach the wrong conclusion from `status` alone. It is positive-only and covers
one measured periodic lattice family
in the [calibrated image-size range](synthid.md#32-how-our-tool-detects-the-supported-carrier).
Arbitrary dimensions are accepted inside the default range, but spatial
resampling can change the carrier period. `register_scale=True` enables the
slower scale-registered operating point over 250,000 through 10,000,000 decoded
pixels, with both sides at least 64 pixels; the default remains the native-period
detector used by `identify`. Its score is a normalized multi-gate statistic with
a threshold of `1.0`, not the native detector's raw template correlation. Scale
0.5 is outside its reliable positive range.
`not_detected` means only that the selected model did not find its carrier;
`unsupported` is kept separate from a negative result. Neither is proof that
the image contains no SynthID watermark.
The default and `identify` use registered-v3 over 250,000 through 10,000,000
decoded pixels, with both sides at least 256 pixels. An opponent-registered-v1
fallback covers 1 through 10 megapixels, sides of at least 768 pixels, and
periods 7.9 through 12.0; period-8 candidates also require the opponent-color
block-edge codec veto. Large-v1 covers 10 through 18 megapixels. Each score
uses a threshold of `1.0`; registered-v3 also requires independent split-patch
confirmation. The fallback is qualified for measured lossless 0.5x-0.75x
views, not lossy retranscodes.
`register_scale=True` forces the registered-v3 cascade, including its bounded
opponent fallback, while `False` explicitly selects the legacy native-period
fixed-v2 diagnostic below the large-image boundary.
`indeterminate` means only that the selected local model did not find its
carrier; `unsupported` means no local expert covers the input geometry. Neither
is proof that the image contains no SynthID watermark.
Both local and official OpenAI JSON results expose `signal_family`,
`provider_scope`, `backend`, `metadata_used_for_verdict`, and
`pixels_preserved`; the local result adds `identifies_watermark` and
`tile_aligned_crop_required`, so callers do not need to infer the evidence boundary from
the detector name.
Remote transport and response failures raise `OpenAIProvenanceError`. Its
`status_code`, `error_code`, `request_id`, `retry_after`, and `retryable`
attributes let a caller implement bounded backoff or a circuit breaker without
turning an API outage into a false `not_detected` result. One function call still
performs at most one upload.
## Remove visible marks
@@ -330,8 +352,9 @@ Timings and spatial artifacts are opt-in. Artifacts include image-identifying da
such as a thumbnail and perceptual hash; aggregate feature families do not.
`identify_from_evidence` does not reopen the source file by default: it evaluates
metadata only, and registered visible marks and pixel-backed invisible watermarks
remain in the path-based `identify` call.
metadata only, and the pixel-backed checks remain in the path-based `identify`
call: registered visible marks, open invisible-watermark decoders, and the
experimental generation-pipeline lattice signal.
Pass `image_path` together with `check_visible` or `check_invisible` to add those
pixel detectors on top of the SAME evidence. That is how a caller asking one file
+38 -17
View File
@@ -79,7 +79,9 @@ The inspection and stripping code handles signals in these groups:
- xAI and Grok EXIF signature fields;
- Samsung AI editing markers;
- Hugging Face job metadata;
- one positive-only SynthID periodic pixel carrier in a calibrated image-size range;
- one positive-only generation-pipeline pixel lattice in a calibrated image-size
range, experimental, which identifies the pipeline and not the SynthID
watermark; signed provenance remains the supported SynthID route;
- open Stable Diffusion style DWT-DCT watermarks with the `detect` extra;
- Adobe TrustMark with the `trustmark` extra.
@@ -127,32 +129,51 @@ The `controlnet`, `sdxl`, `qwen` and `default` values were removed. A retired na
is rejected at parse time rather than remapped onto a surviving profile.
Google does not publish the SynthID payload decoder. This project ships a
positive-only detector for one measured periodic image-carrier family in a
positive-only detector for one measured periodic image-lattice family in a
calibrated image-size range, available through `detect-synthid`
and the default pixel pass in `identify` when the `pixels` extra is installed.
The unchanged fixed threshold accepted none of the public COCO views in both
an observed-geometry challenge and a generated-geometry challenge covering all
modulo-16 edge cases. Above 10 through 18 megapixels, the native default uses a
That lattice is not the watermark. It is anchored at the image origin: a
seven-pixel crop removes it from the large branch and a two-pixel crop removes
it from registered-v3 (all 36 tested detections across foreign-generator and
Google images), while the published SynthID evaluation survives aggressive crop
and resize, so every control rate below describes a generation-pipeline
signature and not watermark detection. Every rate quoted
below was also measured on photographs; on 223 signed non-Google generator
images the same runtime accepted 29, a rate of 13.0%. Sensitivity outside the
calibration distribution was measured once, on 11 fresh 5632x3072 images from
`gemini-3.1-flash-image`: 8 detected, 72.7%, one-sided 95% lower bound 43.6%.
The same images cropped seven pixels off the tile grid returned 0 of 6.
The default ordinary-size route uses registered-v3, including independent
split-patch phase and codeword confirmation. It accepted none of 5,993
supported controls across two nonoverlapping Open Images test cohorts and none
of 2,366 supported controls in a second-family COCO challenge. A precision-first
opponent-registered-v1 fallback covers 1 through 10 megapixels, sides of at
least 768 pixels, and carrier periods 7.9 through 12.0. Period-8 candidates must
also pass an opponent-color block-edge codec veto. It recovered 49/49 lossless
0.5x-0.75x views from seven separate official positives. The veto rejected all
1,790 measured period-8 codec crossings, 350 matched 0.5x controls had no base
crossing, and the earlier period-band rule accepted 0/1,000 post-freeze
controls. Above 10 through
18 megapixels, the production router uses a
separately challenged large branch over phase-aligned windows and opponent-color
phase agreement; both sides must be at least 2,048 pixels. It retained all seven
officially verified large Google pixel positives and accepted none of 2,637
feature-unseen, decoded-pixel-unique natural controls. A smaller post-freeze
Open Images acquisition also produced 0/41 detections. Arbitrary dimensions in
the default calibrated ranges are accepted, but the input must retain the
measured 16-pixel carrier scale. The large branch retained 0/7 official
positives after either JPEG-95 or JPEG-90 re-encoding, so its native-size scope
does not include lossy retranscodes. The
opt-in `detect-synthid --register-scale` mode performs a slower bounded scale
search over its separately measured 250,000-through-10,000,000-pixel range and
requires both sides to be at least 64 pixels. Its measured positive scale range
is approximately 0.65 through 1.5; 0.5x resizes are not reliably detected.
`identify` does not enable that search. Neither detector attributes a provider
locally.
Open Images acquisition also produced 0/41 detections. Registered-v3 has a
measured scale range of approximately 0.65 through 1.5; the narrower fallback
adds the measured lossless 0.5x-0.75x range. The large branch retained 0/7
official positives after either
JPEG-95 or JPEG-90 re-encoding, and the opponent-registered fallback retained
0/63 JPEG-95, JPEG-85, and WebP-95 views. Their scope does not include lossy
retranscodes. `detect-synthid --fixed-period` exposes
fixed-v2 only as a legacy diagnostic; its fresh-source false-positive rate
disqualified it as a production positive route. No local production expert
attributes a provider.
The tool also recognizes presence from supported provenance: Google AI C2PA
under Google's all-media watermark policy, and current OpenAI C2PA carrying an
explicit `c2pa.watermarked.*` action. Legacy OpenAI C2PA without that action
does not assert SynthID. A pixel result of `not_detected` or `unsupported`
does not assert SynthID. A local pixel result of `indeterminate` or `unsupported`
remains inconclusive for other sizes, epochs, codecs, and payloads.
The optional `verify-openai-synthid` command is a separate official remote
File diff suppressed because it is too large Load Diff
+207 -27
View File
@@ -585,21 +585,32 @@ codecs, video, or future epochs. The evidence and gates are documented in
### 3.2 How our tool detects the supported carrier
`remove-ai-watermarks detect-synthid image.png` folds the image residual modulo
16x16 and compares it with a frozen float64 template. It evaluates only native
input, without resize. Exact-multiple dimensions retain the original folding
path; non-divisible dimensions use count-correct modulo folding. The model and
The heading is kept because README, `cli.md` and `python-api.md` link to this
anchor, but the name is inherited and inaccurate. What the local experts read
is a periodic lattice anchored at the image origin, measured on 2026-08-16 to
vanish under a seven-pixel crop that the published SynthID evaluation survives
at 99.97% TPR. Everything in this section describes that pipeline signature,
not watermark recovery; the measurement is in the empirical log of
[`synthid-detector-removal-plan.md`](synthid-detector-removal-plan.md).
`remove-ai-watermarks detect-synthid image.png --fixed-period` exposes the
legacy fixed-v2 diagnostic. It folds the image residual modulo 16x16 and
compares it with a frozen float64 template. It evaluates only native input,
without resize. Exact-multiple dimensions retain the original folding path;
non-divisible dimensions use count-correct modulo folding. The model and
threshold remain frozen from the 2048x2048 experiment. Through 10 megapixels,
the fixed threshold
accepted none of 5,000 public COCO views balanced across every observed target
geometry. A separate 5,000-view challenge used 256 generated geometries from one
through 18 megapixels and covered every pair of width/height remainders modulo
16; it also produced no accepted view. Fixed-branch support is therefore the
challenged interval of 1,000,000 through 10,000,000 decoded pixels rather than
an enumerated width-by-height registry. The original 2048x2048 scores remain
exactly unchanged.
16; it also produced no accepted view. Later fresh-source challenges invalidated
that precision claim: fixed-v2 accepted 5/211 supported controls in one Open
Images cohort, and a proposed `0.28` threshold still accepted 1/213 in the
second. The branch is therefore diagnostic only and is never unioned into the
production positive route. The original 2048x2048 scores remain exactly
unchanged.
Above 10,000,000 through 18,000,000 decoded pixels, the native default selects
Above 10,000,000 through 18,000,000 decoded pixels, the production default selects
the separate `synthid-periodic-tile-large-v1` branch when both sides are at
least 2,048 pixels. It scores every phase-aligned 2,048-square window without
resizing. Every window must retain the combined template, Red-minus-Green, and
@@ -646,15 +657,19 @@ less conservative per-period thresholds accepted five final controls. The
runtime therefore detects arbitrary decoded dimensions only when the carrier
retains its measured 16-pixel scale.
`remove-ai-watermarks detect-synthid image.png --register-scale` opts into the
separately calibrated scale-registered detector. It samples the 30 strongest
Through 10,000,000 decoded pixels, `remove-ai-watermarks detect-synthid
image.png` selects the registered-v3 detector by default. `--register-scale`
forces this branch even where the router would otherwise select large-v1. The
registered expert samples the 30 strongest
template harmonics over fractional periods, reconstructs the three strongest
canonical candidates, and combines full-frame correlation with quadrant and
three-level scale-space consistency. A positive result additionally requires
the canonical winner to be the strongest spectral candidate, a calibrated
threshold for its recovered period, and agreement in two independent
high-frequency template bands. The reported score is the minimum normalized
margin across these requirements; its threshold is `1.0`.
high-frequency template bands. Registered-v3 then confirms base crossings on
disjoint patch groups using origin-corrected harmonic phase, cyclic amplitude,
and a held-out unknown-codeword statistic. The reported score preserves the
base normalized margin only after confirmation; its threshold is `1.0`.
The final rule retained 229 of 355 source-disjoint transformed positives and
accepted none of 499 previously untouched Open Images controls. It retained
@@ -662,8 +677,9 @@ accepted none of 499 previously untouched Open Images controls. It retained
A separate period-8 rescue was rejected because symmetric 0.5x control resizing
reproduced the same lattice and fully overlapped the positive feature range.
The measured input range is 250,000 through 10,000,000 decoded pixels.
Both dimensions must also be at least 64 pixels so every canonical quadrant can
retain one 16-by-16 carrier tile.
Both dimensions must also be at least 256 pixels because the frozen positive
confirmation requires complete disjoint 256-pixel patch groups. Narrower
geometries need a separately calibrated adaptive-patch expert.
A later frozen 1,000-image Open Images reserve preserved zero registered
detections. Only 81 of those images were large enough for the fixed expert, and
@@ -673,12 +689,151 @@ is the validated decision and a fixed-only crossing remains ambiguous. The
fixed expert is retained as a separately scoped carrier diagnostic, not as an
independent recall addition to registered mode.
The research router in `scripts/synthid_routed_expert_bank.py` makes this policy
explicit and always abstains on fixed-only evidence. It records fixed,
registered, and large observations separately: the registered threshold is the
positive route in its measured scale-search range, while the large threshold is
the positive route in its disjoint native large-image range. It never claims
absence because encoder-version coverage remains incomplete.
Registered-v2 later accepted 4/2,997 supported controls in a source-fresh Open
Images test cohort. The frozen v3 confirmation rejected all four while retaining
147/148 base-accepted source-diverse positives and all 359 base-accepted views
in a dense 0.65-1.50 scale matrix. Without changing the rule, v3 then accepted
0/2,996 controls from a second nonoverlapping Open Images cohort and 0/2,366
supported controls from a 3,000-image COCO second-family challenge. The two Open
Images cohorts give a one-sided 95% zero-error false-positive upper bound of
about 0.050%. These results qualify a precision-first positive route, not an
absence verdict; the v2 sensitivity benchmark and scale-0.5 exclusion remain.
Those control rates are photographic. On 223 corpus images whose C2PA names a
non-Google generator, the unchanged production entry point accepted 29, a rate
of `0.130`, with `0.241` on Adobe Firefly and a highest foreign score of `3.01`
against the `1.0` threshold. Every acceptance came from registered-v3. The
lattice this branch reads is therefore shared across generation pipelines, and
the photographic upper bound above does not describe the rate a user meets on
AI-generated input. The branch is also phase-locked to the image origin: a
two-pixel diagonal crop killed all 28 in-geometry foreign detections and all 8
detected Google provenance positives, with the signal recovering only at
offsets that are multiples of four. A mark that survived cropping would not do
that; the route detects pipeline lattice on ordinary sizes as well as large
ones.
An exact runtime-parity check subsequently applied the recorded transform to
each of the 226 source-diverse assignments before invoking registered-v3. Two
half-scale outputs became too small for the research confirmation grid; 224
were scored. Registered-v3 detected 147/224 overall. All 40 supported 0.5x
views missed, while the measured 0.65x-1.5x range detected 147/184 (79.9%). The
unchanged registered-v2 base accepted 148 of those 184; v3 confirmation removed
only one true base crossing. The remaining sensitivity loss is therefore
period selection, amplitude, or high-band failure after resampling, not an
overly strict confirmation gate.
A preregistered same-image-null follow-up compares the selected carrier on the
two patch checkerboards with 16 neighboring periods from plus or minus 0.35 to
2.0 pixels. On two combined Open Images development cohorts, a near-threshold
base floor of 0.8, the existing frozen confirmation, and minimum joint
coherence excess `0.05695968150082637` rescued 7 of the 36 sub-threshold
0.65x-1.5x views. The frozen rule accepted none of the first 3,000 COCO
controls. It remains research-only until the untouched final control partition
and new positive parents pass unchanged. The final 2,000 COCO files contained
1,598 registered-supported images and seven near-threshold candidates. Four
candidates could not form the required two 256-pixel patch groups; the three
scored candidates had same-image excess at most zero. The frozen recovery rule
therefore accepted 0/1,598, as did registered-v3 itself. The negative-side gate
passed, but the lack of unseen positive parents still keeps the rescue outside
runtime.
Same-image contrast also failed to rescue spatial/spectral period mismatches.
Across the two 3,000-file Open Images cohorts, 469 controls passed the
preregistered mismatch prefilters and 212 passed frozen split confirmation.
Their maximum joint excess, `0.1762448251`, exceeded the `0.1464860382` maximum
of the five eligible transformed positive mismatches. The requirement that the
canonical and spectral period winners agree remains part of registered-v3.
A later content-adaptive research branch uses the registered tile only as a
synchronization basis. It standardizes every patch against all cyclic tile
shifts, chooses one phase on a checkerboard of selection patches, and confirms
the same phase on the disjoint checkerboard. A frozen joint standardized score
of `2.5`, combined with matching periods, the existing confirmation, both base
gate margins at least `0.45`, and one margin at least `1.0`, recovered 5 of 18
scored amplitude/high-band failures. It accepted none of 88 first-cohort gate
failures and none of 334 previously scored control candidates, but those are
development results. Its separately started Picsum feature-holdout then
accepted 0/350 decoded-pixel-unique controls unchanged. Only two controls
reached the mechanism pre-gates and their maximum joint patch-shift score was
`0.7029283` against `2.5`. The branch remains research-only pending unseen
positive parents. That check then failed: 21 resized views at 0.65, 0.70, and
0.75 from seven separate official pixel-positive large Gemini parents produced
0/21 registered-v3 detections and 0/21 patch-phase rescues. Their surviving
amplitude but inverted or weak RGB high-band response points to a different
carrier epoch or representation. The patch branch is not promoted; the next
test registers the separately measured large-v1 opponent-color signal.
The first opponent-color registration experiment then recovered 21/21 of
those views and selected the exact transformed period every time. It searches
7.5-14.5 pixels in the Red-minus-Green and Blue-minus-Yellow spectrum, then
requires fixed RGB, Red-minus-Green spatial, and Blue-minus-Yellow spatial
scores of at least `0.16`, `0.60`, and `0.55`. The same frozen candidate
accepted 0/21 symmetrically resized views from seven large Open Images
controls. The frozen candidate then accepted 0/350 decoded-pixel-unique Picsum
controls with a maximum decision margin of `0.7778322`.
The unrestricted branch was not production-safe. It accepted 605/2,997 and
587/2,996 controls from two wider Open Images cohorts; almost every crossing
selected the period-8 or period-12.8 codec lattice. It also accepted one of
3,964 COCO controls at period 10, below one megapixel, and 28/3,772
non-Google/non-OpenAI Spaces controls, all at period 8 or 12.8. Lossy
re-encoding destroyed the measured positive route: raw lossless resize retained
21/21 views at scales 0.5, 0.625, and 0.75, while JPEG-95, JPEG-85, and WebP-95
retained 0/63.
Those failures defined a narrower precision-first expert before a new control
holdout: 1-10 megapixels, both sides at least 768 pixels, and a selected period
from 8.1 through 12.0. It keeps the original three score thresholds and does
not require the strongest spectral alias to equal the spatially reranked
period. The latter restriction was removed after a public-API test showed that
it reduced the 0.55x cohort from 7/7 to 1/7 while the geometry gate already
excluded its only reserve control crossing. The final rule then accepted
0/1,000 untouched Picsum controls, with a maximum unrestricted decision margin
of `0.7953734`, and the production API detected 42/42 lossless views at scales
0.55 through 0.75 from the seven official-positive parents. It now ships as
`synthid-periodic-tile-opponent-registered-v1` after registered-v3 abstains.
A later period-8 codec-confound experiment extended that frozen expert without
mistaking the JPEG grid for a watermark. Half-scale lossless views retained 7/7
official positives at period 8, but ordinary JPEG controls produced the same
large template correlation. Their decoded opponent-color edge geometry was
different: every positive had both the Red-Green and Blue-Yellow native
8-pixel edge ratio at or below `1.05`. The threshold was selected against 600
development codec crossings, then rejected all 582 crossings in the held-out
Open Images cohort, all 601 in the feature-unseen frozen reserve, and all seven
in the heterogeneous Spaces challenge. Separately, 350 controls passed through
the same lossless 0.5x resize had no base carrier crossing. The runtime now
accepts periods 7.9-12.0 and applies this pixel-only veto through period 8.1.
The production API consequently detects 49/49 measured lossless views at scales
0.5-0.75 from the seven official-positive parents.
The same work did not recover lossy retranscodes. JPEG 4:2:0 creates a strong
inverted period-8 template in positives and natural controls alike. A
matched-transform 512-feature codec-residual discriminant accepted up to
86/525 holdout controls and did not generalize across positive parents. Eighty
block-DCT coherence variants also failed the precision-first gate: the best
zero-holdout-error statistic retained only 2/21 JPEG views. These are rejected
hypotheses, not hidden fallback branches.
The wider provider challenge produced a useful but non-attributive observation:
the unrestricted score accepted 95/7,254 OpenAI files with an explicit SynthID
provenance assertion, all at periods 10.70-10.80. It also accepted 4/287 OpenAI
lineage files without that assertion, including three in the production period
band. Missing assertion is not an oracle-negative watermark label, and the
feature does not identify a provider. All 95 decoded rasters were unique and
none overlapped the 94 hits from the earlier period-8 OpenAI candidate, so the
union covered 189/7,259 asserted files. The new component was nevertheless
codec-fragile: JPEG-95 and WebP-95 each reduced 95/95 native hits to 0/95.
It may be a complementary carrier epoch or an associated export/resampling
lattice; current labels cannot distinguish those causes. The local detector
therefore remains provider-neutral; OpenAI-wide coverage still comes from the
official pixel verifier.
Runtime routing now applies these policies directly and always abstains on
fixed-only evidence. The research bank in
`scripts/synthid_routed_expert_bank.py` still records fixed, registered, and
large observations separately for audits. No route claims absence because
encoder-version coverage remains incomplete.
Running the unchanged registered components directly above the declared range
did not justify a larger ceiling. From 10 to 18 megapixels it accepted 1 of 37
@@ -931,10 +1086,12 @@ the aligned result. Together with the failed third-carrier fit, this exhausts
the current linear native 16-by-16 Google hypothesis as two jointly controllable
states. It still does not replace a matching-provider oracle result.
This mode is not the default because the bounded search is materially slower;
scale registration is explicit and `identify` keeps the native detector. The
registered mode does not reliably detect 0.5x carriers and does not make the
detector universal across crop, codecs, carrier states, or providers.
The bounded search is materially slower, but registered-v3 is now the default
ordinary-size route because fixed-v2 failed its fresh-source precision gate.
Registered-v3 itself does not reliably detect 0.5x carriers. The later bounded
opponent fallback covers the measured lossless 0.5x case with its codec-grid
veto, but does not make the detector universal across crop, codecs, carrier
states, or providers.
A crop-specific follow-up tested cube-root LMS and OKLab projections, all six
DTCWT orientations, and explicit FFT phase-lock metrics after period-and-phase
@@ -1185,8 +1342,9 @@ runtime until a new future holdout confirms it.
A positive result identifies the carrier but does not attribute a provider.
Provider identity still comes from provenance.
The command reports `not_detected` separately from `unsupported`. Both are
inconclusive outside the measured carrier family and calibrated image-size range.
The command reports `indeterminate` separately from `unsupported`. Both are
inconclusive: the first means no qualified local expert crossed its threshold,
and the second means no local expert covers the geometry.
The same modulo-folding method has been tested separately on a large,
temporally split OpenAI-labeled corpus. Its strongest native-size template was
@@ -1543,6 +1701,23 @@ the signed OpenAI period-8 candidate accepted 4 of 417 unique positives and 1
of 454 general-control groups, the OpenAI full-image noiseprint accepted 68 of
417, and the Google runtime detector accepted 153 of 211 unique positives.
A previously prepared image-level patch-bag hypothesis was then executed. It
aggregates the mean, standard deviation, minimum, and maximum of nine learned
embeddings from normalized high-pass luminance and opponent-color patches. The
validation-selected model accepted 285 of 1,280 OpenAI rows above every
validation control. Without changing its weights or threshold, it accepted 324
of 1,364 development-test rows, 3 of 1,373 difficult controls, and 1 of 2,000
COCO controls. The later August temporal challenge accepted 120 of 486 OpenAI
rows, 8 of 504 general controls, and 5 of 33 same-provider rows without a
watermark assertion. Assertion enrichment over that same-provider stratum was
not independently significant (`p = 0.151`, one-sided exact test). Content
grouping reduced those counts to 107 of 417, 4 of 453, and 4 of 30,
respectively. A JPEG-95 conjunction retained only 1 of 486
OpenAI rows and no controls. Its native hits did not overlap the frozen signed
period-8 temporal hits. The model therefore reveals a complementary OpenAI
export noiseprint, not a codec-robust or watermark-specific decoder, and does
not enter runtime.
### 3.3 Official OpenAI pixel verification
`remove-ai-watermarks verify-openai-synthid image.png
@@ -1559,6 +1734,11 @@ entry. The source is not modified. Tests deliberately cover C2PA-only positive
responses, pixel mutation, surviving metadata, malformed response shapes, and
documented access and rate-limit failures.
The default SDK client fixes a 120-second request timeout and disables
automatic retries. One explicit acknowledgement therefore cannot silently
transmit the sanitized raster more than once. Timeout and connection failures
are errors, and request logs omit source paths and decoded-pixel hashes.
A live 2026-08-14 web-verifier smoke used the same sanitization invariant. Two
metadata-stripped, pixel-identical OpenAI images at 1536 by 1024 and 1024 by
1536 both returned `SynthID detected` with `Content Credentials not detected`.