Add calibrated SynthID pixel detector

This commit is contained in:
Victor Kuznetsov
2026-08-11 11:09:55 -07:00
parent 7091d73f2e
commit 8a648794ad
32 changed files with 2394 additions and 146 deletions
+20 -2
View File
@@ -14,6 +14,7 @@ defaults. This page focuses on choosing the right command.
| Command or signal | Required installation |
| --- | --- |
| `metadata` and metadata-only `identify` | Default package |
| `detect-synthid` and the calibrated-size SynthID pixel signal in `identify` | `remove-ai-watermarks[pixels]` |
| Visible signals in `identify` | `remove-ai-watermarks[visible]` (`pixels` is the minimal runtime) |
| Open DWT-DCT signals in `identify` | `remove-ai-watermarks[detect]` |
| Adobe TrustMark signals in `identify` | `remove-ai-watermarks[trustmark]` |
@@ -54,8 +55,25 @@ Metadata only inspection:
remove-ai-watermarks identify image.png --no-visible
```
Despite the historical option name, `--no-visible` skips both visible and open
invisible pixel detectors. Metadata inspection still runs.
Despite the historical option name, `--no-visible` skips all pixel detectors,
including the supported SynthID carrier, visible marks, open DWT-DCT, and
TrustMark. Metadata inspection still runs.
## Detect the supported SynthID pixel carrier
```bash
remove-ai-watermarks detect-synthid image.png
remove-ai-watermarks detect-synthid image.png --json
```
The command returns one of `detected`, `not_detected`, or `unsupported`. The
runtime detector covers one frozen periodic carrier family in the
[calibrated image-size range](synthid.md#32-how-our-tool-detects-the-supported-carrier)
and needs the `pixels` extra. It never resizes the input and does not register
a carrier whose sampling period changed through arbitrary spatial resampling.
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.
## Remove known visible marks
+11 -8
View File
@@ -79,8 +79,9 @@ enough yet barely touches flat fills. So the survivors FLIP by content type —
choice alone does not guarantee removal.
**2. Seed non-determinism near threshold.** img2img uses a random seed unless `--seed`
is passed, and there is no local SynthID detector to self-verify. The bracelet survived
controlnet @0.15 in one run and CLEARED @0.15 in another (same pipeline+strength+res).
is passed, and these geometries are outside the current local detector's scope.
The bracelet survived controlnet @0.15 in one run and CLEARED @0.15 in another
(same pipeline+strength+res).
So a single clean run does NOT establish a strength as safe — characterizing a reliable
floor needs a seed-repeatability sweep (N runs, varied seed), not one pass.
@@ -144,8 +145,8 @@ Gemini app; the two payloads are vendor-specific and never cross-checked):
but never recovered original identity precisely — every setting traded one problem
for another. See `docs/synthid-robust-identity-research-2026-06-08.md`
"Empirical follow-up" for the full sweep.
- **No local SynthID detector exists** → the service can't self-verify; bake in strength
margin and periodic oracle spot-checks.
- **No applicable local detector exists for these geometries** → the service
can't self-verify; bake in strength margin and periodic oracle spot-checks.
- **Lesson:** visual-quality / face-identity recovery does NOT prove removal — only the
oracle does, across MULTIPLE content types; never conclude from a partial result (the
photoreal-only data first read as "controlnet shields, default removes"; the flat-graphic
@@ -298,8 +299,9 @@ attention-slicing; ~1-2 min/image, so a coarse sweep is a sub-hour background ru
is needed ONLY for the separate
native-large-Gemini (2816 px) case, which OOMs even without a ControlNet (that requires a
GPU task). The genuine external dependency is NOT compute but the **manual SynthID oracle**:
there is no local SynthID detector, so removal is verified by hand in the Gemini app
("Verify with SynthID") per image, regardless of where the diffusion runs.
these geometries are outside the current local detector's scope, so removal is
verified by hand in the Gemini app ("Verify with SynthID") per image, regardless
of where the diffusion runs.
Runner: **`scripts/controlnet_sweep.py`** (built 2026-06-02) implements exactly this sweep —
SDXL base 1.0 + an SDXL-native ControlNet img2img, one output per (control x strength x scale)
@@ -441,8 +443,9 @@ shielding risk; defer to a v2 after the single-canny path is dialed in.
**Hard caveat:** every change that increases preservation (higher scale, denser canny, fuller window,
softer edges) marginally REDUCES effective regeneration and so raises the chance the watermark
survives -- exactly the shielding failure mode. There is no local SynthID detector, so each tuning
change must be re-confirmed on the oracle. These are img2img-context recommendations derived from
survives -- exactly the shielding failure mode. These geometries are outside the
current local detector's scope, so each tuning change must be re-confirmed on
the oracle. These are img2img-context recommendations derived from
generation-context sources plus our own measurements; treat the playbook as hypotheses to verify, not
settled defaults.
+1 -1
View File
@@ -94,7 +94,7 @@ application actually uses:
| Extra | Capability | Automatically includes | Torch or model download |
| --- | --- | --- | --- |
| `pixels` | Shared BGR array and image-processing runtime | NumPy, headless OpenCV | No |
| `pixels` | Shared BGR runtime and calibrated-size SynthID carrier detection | NumPy, headless OpenCV | No |
| `heif` | HEIC, HEIF, and AVIF pixel decoding | pillow-heif | No |
| `visible` | Visible mark detection, OpenCV inpainting, and manual erasing | `pixels` | No |
| `video` | Visible video identification/removal and timestamp preservation | `visible`, PyAV | No |
+12 -5
View File
@@ -64,12 +64,19 @@ 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.
### Removal cannot be verified locally for proprietary SynthID
### Local SynthID detection covers one image-carrier family
The project has no public local SynthID pixel decoder. It recognizes presence
from supported provenance metadata: Google AI C2PA under Google's all-media
policy, or current OpenAI C2PA with an explicit watermark action. A missing
provenance signal is not a negative pixel verdict.
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 that size range, crop, strong JPEG compression,
video, or future carrier epochs. Arbitrary dimensions inside the range are
supported only while the recovered carrier retains its measured 16-pixel
sampling lattice. A spatial resize changes that period; the runtime does not
yet search fractional periods or infer the pre-resize geometry. A `not_detected`
or `unsupported` result is not a negative universal verdict, and removal still
requires the matching provider oracle for confirmation.
For important outputs:
+50 -1
View File
@@ -451,7 +451,56 @@ 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 and open invisible-watermark decoders after extraction.
visible-mark, open invisible-watermark, and supported SynthID carrier
detectors after extraction.
### SynthID periodic carrier detector
[`synthid_detector.py`](../src/remove_ai_watermarks/synthid_detector.py) is the
runtime form of the frozen 2048x2048 periodic-tile experiment. It folds a
Gaussian high-pass residual modulo 16x16 within a calibrated pixel-count range
and compares the normalized RGB tile with the bundled float64 template
`assets/synthid_periodic_tile_2048_v1.npz`. Exact multiples use the original
reshape-and-mean path; other sizes use count-correct modulo folding,
without resize. Channels are filtered and folded sequentially, and partial edge
blocks are accumulated without a full-frame padding buffer so the 18-megapixel
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`.
The direct API returns `detected`, `not_detected`, or `unsupported`; the last is
distinct because no resize is performed. Support is based on a calibrated range
of 1,000,000 through 18,000,000 decoded pixels. The 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.
Arbitrary geometry is not the same as arbitrary spatial resampling. On a
stratified 80-image fixed-positive sample, one-step resizes at seven nonidentity
scales from 0.5 through 1.5 reduced the unchanged 16x16 detector from 80 accepted
sources to zero at every scale. Restoring the original geometry recovered 58-80
sources, showing that the carrier period scaled with the pixels. A discovery
bank that scaled the template to integer periods 8, 10, 12, 14, 18, 20, and 24
was promising: a threshold frozen above 3,000 resized COCO controls accepted no
view in a 2,000-control final partition and accepted 672 of 800 source-disjoint
provider positives. It also stayed below threshold on the tracked OpenAI and
Adobe controls. The branch remains research-only because noninteger periods at
scales 0.8, 0.9, 1.1, 1.2, and 1.333 collapsed, while separate per-period
thresholds accepted five final controls. The runtime therefore keeps only the
fixed 16-pixel lattice.
A follow-up fractional-period probe sampled the 30 strongest template harmonics
over a continuous 7.5-24.5 period range. The correct period appeared within
0.05 pixels among the top three candidates for 58 of 60 transformed positives.
Testing nine neighboring reconstructed geometries then recovered 44 of 60 at
the native threshold, compared with an upper bound of 48 when the true source
geometry was supplied. The complete search still failed its small frozen
control split: a threshold above 250 development controls accepted two of 150
final controls. Multiplying the canonical score by spectral-period confidence
also accepted two. This branch is not a calibrated runtime fallback.
### Portable metadata record
+21
View File
@@ -12,6 +12,27 @@ 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
Install `remove-ai-watermarks[pixels]`, then call the lazy top-level API:
```python
import remove_ai_watermarks as raiw
result = raiw.detect_synthid("input.png")
print(result.status) # "detected" | "not_detected" | "unsupported"
print(result.score) # float for a supported image size, otherwise None
print(result.threshold) # frozen operating point
```
The detector is positive-only and covers one measured periodic carrier family
in the [calibrated image-size range](synthid.md#32-how-our-tool-detects-the-supported-carrier).
Arbitrary dimensions are accepted inside that range, but arbitrary spatial
resampling can change the carrier period and is not registered. `not_detected`
means only that this model did not find its carrier; `unsupported` is kept
separate from a negative result. Neither is proof that the image contains no
SynthID watermark.
## Remove visible marks
Install `remove-ai-watermarks[visible]` before using the visible-removal API.
+17 -7
View File
@@ -79,6 +79,7 @@ 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;
- open Stable Diffusion style DWT-DCT watermarks with the `detect` extra;
- Adobe TrustMark with the `trustmark` extra.
@@ -125,12 +126,21 @@ Current pipeline values, both CUDA-only:
The `controlnet`, `sdxl`, `qwen` and `default` values were removed. A retired name
is rejected at parse time rather than remapped onto a surviving profile.
SynthID does not have a public local pixel decoder in this project. The tool
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. After provenance metadata is removed, a local negative result
is still inconclusive.
Google does not publish the SynthID payload decoder. This project ships a
positive-only detector for one measured periodic image-carrier 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. Arbitrary dimensions in the calibrated range are accepted,
but the input must retain the measured 16-pixel carrier scale: arbitrary spatial
resampling is not registered. The detector does not attribute a provider locally.
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`
remains inconclusive for other sizes, epochs, codecs, and payloads.
For MP4, MOV, and M4V, `video invisible` or the explicit
`video all --invisible` option can regenerate the video through a VAE and strip
@@ -149,7 +159,7 @@ not a universal clean verdict.
| Provider or family | Visible | Invisible path | Metadata or provenance |
| --- | --- | --- | --- |
| Google Gemini | Sparkle | Diffusion regeneration for SynthID | C2PA and related source signals |
| Google Gemini | Sparkle | Local positive-only calibrated-size detector; diffusion regeneration | C2PA and related source signals |
| Google Veo video | Veo diamond and legacy text | Oracle-certified VAE removal for SynthID | C2PA and related source signals |
| OpenAI image generators | None registered | Diffusion regeneration for supported invisible signals | C2PA and generator provenance |
| Stable Diffusion and SDXL | None registered | Diffusion regeneration; optional open decoder | Embedded parameters and text metadata |
+322 -4
View File
@@ -1074,10 +1074,10 @@ provider-specific expert for the supported 1536x2816 carrier epoch. Identity
and bounded translation views use the frozen phase and support thresholds;
unsupported geometry, insufficient carrier magnitude, and ambiguous phase
return `abstain`. Vendor attribution may select the expert that supplied
accepted evidence, but it must not turn an abstention into a provider label. The next
calibration gate still requires at least 3,000 native-support negatives,
same-provider oracle negatives, matched non-target solid outputs, and a new
temporal positive that influenced neither profile nor threshold.
accepted evidence, but it must not turn an abstention into a provider label.
The next calibration gate still requires at least 3,000 native-support
negatives, same-provider oracle negatives, matched non-target solid outputs,
and a new temporal positive that influenced neither profile nor threshold.
### 2026-08-10: 2048 periodic-tile detector
@@ -1151,6 +1151,323 @@ family, but the two cross-source carrier matches prohibit a stronger vendor
claim until an oracle distinguishes direct provider output from shared-backend
output.
A pixel-space ablation then tested whether the frozen tile merely predicted the
local scores or controlled them. At twice the train-median tile norm, aligned
subtraction changed the fixed-tile decision from 29 of 30 accepted originals to
zero and the independently fitted sparse-phase decision from 27 of 30 to zero.
The median fidelity was 53.74 dB PSNR and 0.99681 SSIM. Cyclically shifting the
same tile by one row and column left one phase acceptance, while a seeded
zero-mean random tile orthogonal to the learned template left 13; their median
PSNRs were within 0.13 dB of the aligned edit. For both local representations,
the aligned edit reduced the score more than either control on all 30 paired
images, with a two-sided sign-test p-value of 1.86e-9 for each comparison.
The same aligned edit reversed both local decisions on each of the two disputed
cross-source matches, while the orthogonal control left both phase decisions
accepted. That two-item result is descriptive but makes an accidental threshold
crossing less likely; it still cannot distinguish a shared carrier from direct
provider output.
This is the strongest local causal evidence for the 16x16 mechanism, but the
strength was selected after inspecting this locked test and is therefore
discovery-only. The shifted control also suppressed the phase representation
substantially, so local score reversal cannot certify signal removal. A matching
provider oracle must still compare untouched sources, aligned candidates, and
norm-matched controls before any removal claim. The reproducible local harness
is `scripts/synthid_periodic_tile_ablation.py`; its report records input and
model hashes without writing derivative images.
### 2026-08-10: confirmatory oracle-batch readiness
The corpus audit found no new 2048x2048 positive collected after the tile rule
and subtraction strength were frozen. Existing test images cannot be renamed as
a temporal holdout, so the confirmatory oracle batch remains blocked on new
provider output at the supported native geometry.
The batch mechanics are ready in `scripts/synthid_oracle_batch.py`. For each new
source, it preregisters five requests in a fixed order: untouched source,
lossless re-encode, aligned subtraction, cyclic-shifted subtraction, and an
orthogonal norm-matched tile. It refuses to write media inside the repository,
records artifact and decoded-pixel hashes, pins both model artifacts and the
matching provider, and detects any post-registration byte change. Oracle results
live in a separate manifest-bound file so the preregistration remains immutable;
the evaluator requires complete ordered results, verbatim responses,
timezone-aware timestamps, and separate SynthID and C2PA verdicts.
A causal success requires the source, re-encode, shifted, and orthogonal views
all to remain `detected` while only the aligned view becomes `not_detected`.
`Indeterminate` and refusal remain indeterminate. A one-source dry run on an old
test positive verified all five artifacts and the local scoring path, but is
pipeline validation only and contributes no confirmatory evidence.
### 2026-08-10: first confirmatory oracle attempt
Four new 2048x2048 Gemini outputs were generated after the local rule and
strength were frozen, then registered as a 20-request batch. The manifest and
all 20 artifacts passed hash verification before submission. The first source
group produced these ordered results:
| Role | Local tile/phase decision | Provider result |
| --- | --- | --- |
| source | detected / detected | SynthID indeterminate; Google C2PA present |
| re-encode control | detected / detected | Google AI signal detected |
| aligned subtraction | detected / not detected | Google AI signal detected |
| shifted control | detected / detected | Google AI signal detected |
| orthogonal control | detected / detected | refused: verification quota exceeded |
The quota response instructed the account to wait 24 hours. No adaptive retry
was made, and the remaining 15 preregistered requests were not submitted. The
batch cannot receive its preregistered aggregate verdict until complete ordered
results exist.
Even incomplete, this attempt rejects the frozen removal recipe for the first
temporal source: aligned subtraction crossed the phase threshold but remained
above the tile threshold and did not clear the provider oracle. The remaining
sources can still measure transfer and disagreement between the two local
experts, but they cannot turn this first aligned result into a universal
pixel-only removal success.
### 2026-08-10: positive-only runtime detector
Removal is deferred while the transferred tile signal is exposed as a bounded
detector. `src/remove_ai_watermarks/synthid_detector.py` loads the frozen model
as a bundled pickle-free runtime asset and returns `detected`, `not_detected`,
or `unsupported` without resizing input. The direct API and
`detect-synthid` CLI initially covered only native 2048x2048 images; `identify`
consumes a positive match as high-confidence evidence but never treats a
negative or unsupported result as proof of absence.
The operating point and model are unchanged from the locked experiment. The
detector accepted all four post-freeze Gemini outputs, including the source
whose frozen phase score missed, while retaining the prior 29-of-30 locked-test
sensitivity and zero accepted validation/test negatives. The unresolved two
external-source matches remain the reason a runtime positive names the carrier
but does not attribute a provider.
### 2026-08-10: calibrated native-geometry extension
The frozen 16x16 template and threshold transfer across the common native
geometries in the provider-positive evidence. Non-divisible image dimensions
use direct modulo folding with per-cell sample counts; divisible dimensions,
including 2048x2048, retain the original numerical path. All prior 2048x2048
records were replayed and matched exactly, including floating-point scores.
The runtime registry was expanded only after the unchanged threshold accepted
none of 60,000 public COCO challenge views, 3,000 at each of 20 target
geometries. This is a geometry extension of the same positive-only carrier
expert, not an OpenAI pixel detector or a proprietary payload decoder.
### 2026-08-11: calibrated image-size range
The fixed template was then evaluated on every provider-positive image in the
local evidence set rather than only its common geometries. It accepted 3,928 of
4,698 images across 757 exact geometries. Sensitivity separated by pixel count:
1,987 of 2,021 images at or above three megapixels crossed the threshold, while
1,940 of 2,672 images from one through two megapixels did. This establishes a
carrier-family boundary, not universal SynthID recall: explicit C2PA watermark
actions also occur below threshold, and three strong carriers use a different
cyclic phase.
Two public-image geometry challenges tested whether geometry itself creates
false matches. The first balanced 5,000 COCO images across all 757 observed
geometries, with every geometry present in both development and final partitions;
the maximum fixed score was 0.12549 and none crossed the unchanged 0.17357
threshold. The second transformed the same 5,000 source images at 256 generated
geometries from one through 18 megapixels, covering every width/height remainder
pair modulo 16. Its maximum was 0.16387 and again none crossed the threshold.
Runtime support therefore uses that challenged pixel-count interval instead of
an enumerated geometry registry, still without resizing.
A cyclic-registration branch was rejected after the public-image challenge.
At a low threshold it recovered 130 fixed-phase misses but false-fired on
tracked OpenAI and Adobe controls. Raising the threshold above all development
controls recovered only 23 in-range provider positives while adding 84
cross-source matches beyond the fixed detector. Three strong shifted Google
carriers remain a documented miss rather than weakening the runtime rule.
Top-level source labels were not treated as watermark-negative truth. Of 237
non-Google-labeled corpus images crossing the fixed threshold, 81 retained
SynthID provenance. High-scoring Adobe manifests explicitly named Gemini Flash
as the remote provider, and perceptual matching found direct Google derivatives
under editing or relabeling categories. The remaining source labels cannot prove
absence of the carrier, so they constrain provider attribution but do not justify
raising the pixel threshold.
### 2026-08-11: spatial-resampling boundary
Arbitrary decoded geometry did not imply arbitrary resize robustness. A
stratified sample of 80 fixed-positive provider images was rescaled in memory at
0.5, 0.625, 0.75, 0.875, 1.125, 1.25, and 1.5. The unchanged 16x16 detector
accepted none of the 80 images at every nonidentity scale. Restoring each view
to its source dimensions recovered 58-80, which isolates the failure to the
scaled sampling lattice rather than simple information destruction.
Scaling the template and modulo fold to the corresponding integer periods 8,
10, 12, 14, 18, 20, and 24 recovered 73-80 of the discovery images at the
native threshold. Searching all eight periods raised control scores, so a
single threshold was frozen above the maximum of 3,000 deterministically
resized COCO development views. It accepted none of 2,000 final controls and
672 of 800 source-disjoint provider positives, with 77-88 accepted at each
scale. Six tracked OpenAI and Adobe controls remained below the frozen threshold.
This did not generalize to arbitrary scaling. Factors 0.8, 0.9, 1.1, 1.2, and
1.333 create noninteger carrier periods; rounding the period accepted zero of
80 images in the fixed-phase branch at every factor, and cyclic registration
accepted only 1-16. Period-specific thresholds improved sensitivity but accepted
five of the 2,000 final controls. The integer-period bank is therefore retained
as a research result, not added to the runtime. A universal resize branch needs
fractional-period registration or reliable reconstruction of the pre-resize
geometry, followed by a new multiple-search calibration.
A discovery follow-up tested that fractional-period direction with the 30
strongest template harmonics. A continuous 7.5-24.5 spectral search placed the
true period within 0.05 pixels among its top three candidates for 58 of 60
transformed positives. Searching nine neighboring integer reconstruction
geometries recovered 44 of 60 at the native threshold; even the true source
geometry recovered only 48, so resampling damage sets a separate upper bound.
The full search then failed a frozen 250-development/150-final COCO challenge:
the calibration threshold accepted two final controls. A preselected product
of canonical correlation and spectral confidence increased positive
acceptance from 49 to 52 of 60 at its development threshold but accepted the
same two final controls. This fractional FFT baseline is rejected for runtime
use; better period estimation alone does not solve multiple-search specificity.
### 2026-08-10: OpenAI periodic-carrier challenge
The OpenAI track repeated the Google carrier method without runtime provenance
features. C2PA selected the research labels, but every candidate score consumed
only decoded RGB pixels. The temporally split corpus contained 4,615 OpenAI
training positives, 1,280 validation positives, 1,364 development-test
positives, 8,668 difficult external-source controls, and 3,000 COCO controls.
The development test is not called a locked holdout because earlier
representations had already exposed it.
High-pass residuals were folded modulo 8x8, 16x16, and 32x32 and normalized as
in the Google fixed-tile expert. A single 16x16 OpenAI template accepted only
one of 1,280 validation positives at the threshold above all 2,287 validation
controls. A 16-template geometry bank improved that to 12 positives but
accepted one of 3,372 development-test controls. The corresponding
development-test sensitivity was 9 of 1,364. The frozen Google template did
not transfer: at its unchanged threshold it accepted 14 validation positives
and 572 validation controls.
The apparent native-size signal was a confound. At 1024x1536, 91.6% of the
learned template energy projected onto a 2x2 periodic lattice, compared with
5.6% for the frozen Google template. Firefly, China AIGC-labeled, local
diffusion, and unidentified hosted-generator controls reached correlations of
0.92-0.98 against the uncorrected OpenAI template. This is operational evidence
for a shared decoder or upscaler lattice, not an OpenAI watermark carrier.
Projecting the 2x2 nuisance lattice out of every 16x16 fold isolated a weaker
epoch-specific residual. The 1024x1536 expert accepted 5 of 55 validation and
10 of 51 development-test positives while accepting none of the full
validation or development-test controls. Nine of the ten development-test
matches occurred from July 12 through July 14; later dates contributed only
one of 27. The 1536x1024 expert accepted 6 of 37 validation and 2 of 51
development-test positives with no development-test controls. Amplitude,
active-support, channel-consensus, payload-invariant power, and spherical
multi-template branches did not improve this frontier without false positives.
The OpenAI branch therefore remains research-only and is not added to the
runtime detector. The next valid training epoch requires same-content
OpenAI-oracle `detected` and `not_detected` pairs, or provider-authorized decoder
labels, followed by a fresh temporal holdout. Source provenance alone cannot
distinguish a true watermark carrier from the measured generator lattice.
### 2026-08-10: OpenAI content-dependent decoder challenge
The periodic result did not exhaust the neural-watermark hypothesis. OpenAI's
ChatGPT Images 2.0 system card describes its watermark as content-specific, and
the SynthID-Image paper says the encoder is content-dependent by design. The
paper also separates watermark detection from payload recovery and evaluates
the external SynthID-O model at its preferred 512x512 input size. These facts
support a learned full-field decoder, but they do not establish that OpenAI and
Google deploy identical model weights, payloads, or pixel spectra.
A second corpus audit found 261 same-provider candidate controls. Their signed
provenance contained `created` and `converted` actions without the
`c2pa.watermarked.unbound` action, but a subsequent software-agent audit showed
that they do not all come from the positive generation epoch. Only 118 name
`gpt-image 2.0`: 97 training, 16 validation, and five development-test images.
Another 108 name an earlier version and 35 do not expose a usable version. The
full 261-image split remains 217/26/18. These are useful confound controls, but
even the exact-version subset is action-derived rather than a provider-oracle
negative label.
Two pixel-only native-resolution experts were trained with the mixed-version
control set. A
local residual CNN accepted 132 of 1,280 validation positives and 149 of 1,364
development-test positives, with zero same-provider or COCO controls in both
splits and two of 1,373 difficult development-test controls. A separate
spectral, autocorrelation, bit-plane, and residual-error expert accepted 175
validation and 167 development-test positives with no accepted controls. A
validation-selected linear combination accepted 243 positives in each split,
with no accepted validation or development-test control. The zero-error
development-test bound across 3,391 controls is 0.0883% at one-sided 95%
confidence, but the same-provider subset contains only 18 images and therefore
does not independently establish provider specificity.
The exact-version audit did not invalidate the native score counts, but it
weakened their attribution. None of the 16 validation or five development-test
`gpt-image 2.0` controls crossed the residual, forensic, ensemble, canonical,
or JPEG-equalized thresholds. That is directionally useful, but five temporal
test controls cannot establish deployment specificity. Perceptual-hash and
local CLIP searches compared all 118 exact-version controls with 7,259
positives. They recovered a few near-content matches but no clean before/after
watermark pair. Sub-pixel affine alignment left content, edge, and photometric
changes in the residual, while 8x8, 16x16, and 32x32 folded residual
correlations varied in sign and magnitude. Those candidates cannot be used as
causal watermark differences.
Transformation challenges rejected the combined native expert as a SynthID
decoder. Of its 243 accepted development-test positives, 121 remained accepted
after a 5% crop round trip, six after a 75% resize round trip, and none after a
JPEG-95 round trip. No transformed same-provider control was accepted. The
codec fragility is inconsistent with treating the score as the documented
robust watermark without further evidence.
The 512x512 branch also failed the held-out specificity gate. Its selected
model accepted 238 validation and 194 development-test positives, but also
accepted two of 18 same-provider, four of 1,373 difficult, and nine of 2,000
COCO development-test controls. Finally, a CNN trained and evaluated only
after applying the same JPEG-95 round trip to every positive and control
accepted eight validation positives and six development-test positives while
accepting five of 2,000 development-test COCO controls. Equalizing the codec
therefore removed nearly all of the apparent signal instead of revealing a
robust hidden decoder feature.
An independent three-CNN OpenAI surrogate was also evaluated from its
published weights, without adopting its code or claims. At the published 0.5
threshold its ensemble marked 82.0% of COCO validation controls and 83.4% of
COCO development-test controls as watermarked. It also marked 56.3% of
difficult development-test controls and 15 of 16 exact-version OpenAI
validation controls, compared with 87.3% of OpenAI validation positives. The
repository does not publish its training corpus or logs, and its implementation
applies supposedly shared pair augmentation independently. This result rejects
the model as a SynthID decoder and demonstrates why same-content-looking
regenerations are not sufficient negative labels.
A final transform-augmented full-field branch tested the closest practical
approximation to the documented neural decoder. A 512x512 CNN consumed both
RGB and a fixed high-pass residual and trained with random crop/resize,
JPEG 70-100, horizontal flip, and mild color transforms. Training sampling
balanced watermarked positives, difficult controls, and the exact-version
OpenAI candidate controls. Selection required a score above every control for
both native and JPEG-95 validation views. All four fixed training epochs
accepted zero of 500 selection positives. On the full validation set the
frozen model accepted zero of 1,280 OpenAI positives in native, JPEG-95,
75%-resize, and 5%-crop views, while accepting up to two unrelated controls.
On development test it accepted zero of 1,364 OpenAI positives in native,
JPEG-95, and resize views. The crop view accepted one OpenAI positive and one
of 1,373 difficult controls. Transform augmentation therefore did not recover
a usable weaker OpenAI signal.
The measured OpenAI-native separation is best classified as an export or
rendering noiseprint, not a validated SynthID detector. None of these models is
added to runtime. Transform-augmented training has now also failed. A
defensible next epoch needs provider-authorized labels or clean same-content
before/after watermark pairs, plus a fresh temporal holdout that has not
influenced representation or threshold selection.
## Decision record
The program has four possible honest outcomes per provider:
@@ -1184,5 +1501,6 @@ Only after this milestone should implementation of D3 and D4 begin.
## Primary sources
- OpenAI, [Content provenance](https://developers.openai.com/api/docs/guides/content-provenance).
- OpenAI, [ChatGPT Images 2.0 system card](https://deploymentsafety.openai.com/chatgpt-images-2-0/automated-evaluations-and-adversarial-testing).
- Google, [Verify AI-generated images, videos, and audio](https://support.google.com/gemini/answer/16722517?hl=en).
- Gowal et al., [SynthID-Image: Image watermarking at internet scale](https://arxiv.org/abs/2510.09263).
+101 -12
View File
@@ -308,6 +308,30 @@ limited JPEG and crop robustness. The pickle-free research implementation is
`scripts/synthid_periodic_tile_probe.py`; exact evidence and caveats are in the
[`2048 periodic-tile experiment`](synthid-detector-removal-plan.md#2026-08-10-2048-periodic-tile-detector).
An aligned-subtraction ablation strengthened the mechanism finding without
clearing the oracle gate. At a discovery-selected amplitude, it reversed both
the fixed-tile and independently fitted phase decisions on all 30 test images
at a median 53.74 dB PSNR and 0.99681 SSIM. The aligned edit reduced both scores
more than cyclic-shifted and orthogonal random tile controls on every paired
image. A shifted tile nevertheless suppressed the phase score enough to leave
only one accepted image, so these local reversals remain surrogate evidence,
not verified SynthID removal. The exact controls and caveats are recorded in
the linked experiment section.
The immutable oracle-batch and result evaluator are implemented. On 2026-08-10,
four new 2048x2048 Gemini images were generated after the rule was frozen and
registered as a 20-request confirmatory batch. The first source group exhausted
the account's verification quota after five requests. The untouched source
returned Google C2PA Content Credentials without a separate SynthID verdict;
the lossless re-encode, aligned subtraction, and cyclic-shifted control all
still returned a Google AI signal. The orthogonal control was refused because
the quota had been exceeded, and the remaining 15 requests were not submitted.
This incomplete run is already negative evidence for the frozen pixel-only
recipe: the aligned candidate cleared the phase detector but remained positive
under the tile detector and the provider oracle. The local carrier expert
therefore ships only as a positive-only, exact-geometry detector; it is not a
universal SynthID detector or a remover.
A controlled study (June 2026, clean v0.8.6 with text/face protection OFF,
native resolution on this repo's default SDXL pipeline) measured the minimum
img2img strength that removes the SynthID pixel watermark, verified per image on
@@ -402,7 +426,7 @@ diffusion prior."
## 3. Detectability and verifier access
### 3.1 No public local decoder
### 3.1 No public payload decoder
The SynthID decoder is proprietary and not released:
@@ -411,8 +435,8 @@ The SynthID decoder is proprietary and not released:
> available to trusted testers."
> -- Gowal et al., arXiv:2510.09263
There are no released decoder weights and no reproducible algorithm for local
detection. Google provides verification in Gemini and a limited SynthID Detector
There are no released payload-decoder weights or public algorithm. Google
provides verification in Gemini and a limited SynthID Detector
portal. OpenAI now documents a synchronous Content Provenance API whose image
response contains separate C2PA and SynthID outcomes. That API is a remote,
OpenAI-scoped verifier, not a local decoder. Its documentation also says not to
@@ -425,12 +449,73 @@ Google's SynthID Detector service is:
> professionals" on a waitlist
> -- deepmind.google/models/synthid/
The external variant SynthID-O is available "through partnerships" only. Our
tool does not currently detect SynthID pixels locally. The gated research path
for determining whether that can change is documented in
The external variant SynthID-O is available "through partnerships" only. This
project instead detects one empirically recovered periodic carrier family in a
calibrated image-size range. It does not decode the proprietary payload or
generalize that local signal to unsupported sizes,
codecs, video, or future epochs. The evidence and gates are documented in
[`synthid-detector-removal-plan.md`](synthid-detector-removal-plan.md).
### 3.2 How our tool recognizes SynthID from provenance
### 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
threshold remain frozen from the 2048x2048 experiment. 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. Runtime support is therefore the
challenged interval of 1,000,000 through 18,000,000 decoded pixels rather than
an enumerated width-by-height registry. The original 2048x2048 scores remain
exactly unchanged.
This geometry support does not imply arbitrary resize robustness. The fixed
carrier has a 16-pixel sampling lattice. In a stratified 80-image positive
sample, direct detection fell from 80 accepted originals to zero after each of
seven nonidentity resizes from 0.5 through 1.5. Scaling the template and folding
period to matching integers recovered the signal, and a conservative threshold
above 3,000 resized COCO development controls accepted 672 of 800 source-disjoint
provider positives with no acceptance in 2,000 final controls. That branch is
not shipped: noninteger periods from ordinary scale factors collapsed, and
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.
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 same modulo-folding method has been tested separately on a large,
temporally split OpenAI-labeled corpus. Its strongest native-size template was
dominated by a generic 2x2 generator lattice that also appeared in multiple
non-OpenAI controls. Removing that nuisance component left a sparse,
time-limited signal with inadequate sensitivity. OpenAI pixel detection is
therefore not part of the runtime expert.
Learned residual, forensic, ensemble, and canonical 512x512 representations
were also tested against 261 same-provider candidate controls. A later
software-agent audit found that only 118 of those controls explicitly name
`gpt-image 2.0`; the rest come from earlier or unknown versions. The strongest
native ensemble accepted 243 of 1,364 development-test positives with no
accepted controls, but accepted none of those positives after a JPEG-95 round
trip. A model trained after equalizing every image through JPEG-95 accepted
only six development-test positives and five COCO controls. The apparent
native signal is therefore treated as an export noiseprint rather than a
validated robust watermark. A local CLIP search over the exact-version subset
found no clean same-content before/after pair, and a published third-party CNN
surrogate mislabeled 83.4% of held-out COCO controls at its stated threshold.
A transform-augmented 512x512 RGB-plus-residual CNN then accepted zero of 1,364
development-test positives in native, JPEG-95, and resize views; its crop view
accepted one positive and one difficult control. Detailed counts and rejected
alternatives are in
the [`OpenAI periodic-carrier challenge`](synthid-detector-removal-plan.md#2026-08-10-openai-periodic-carrier-challenge)
and [`OpenAI content-dependent decoder challenge`](synthid-detector-removal-plan.md#2026-08-10-openai-content-dependent-decoder-challenge).
### 3.3 How our tool recognizes SynthID from provenance
We recognize SynthID indirectly from supported C2PA evidence; this is not a
pixel watermark decode. Google states that all media generated by its tools is
@@ -451,7 +536,7 @@ This is why:
- A quiet `identify` output is not proof that SynthID was removed -- it only
means the metadata signal is gone.
### 3.3 Oracle scope: each vendor detects only their own
### 3.4 Oracle scope: each vendor detects only their own
OpenAI's current Content Provenance API documentation says it checks supported
OpenAI signals and is not a general-purpose AI detector. Google's current Gemini
@@ -470,7 +555,7 @@ A Google-SynthID image reads clean on openai.com/verify. An OpenAI image reads
clean in the Gemini oracle. They are different payloads within the same
framework.
### 3.4 Video verification and attack harness
### 3.5 Video verification and attack harness
Gemini's built-in verification flow reports whether and where it detects Google
SynthID in a video. This remains a proprietary oracle: invoke `@synthid`, use
@@ -699,7 +784,8 @@ photoreal, `sdxl` on flat graphics, the §5.1 content-x-pipeline table), BUT on
hard case (flat fills) `sdxl` is the WEAKER remover (plain img2img barely perturbs a
flat region at low strength), so it needs AT LEAST controlnet's strength -- the
certified floor is therefore the right floor for `sdxl` too. This is a MARGIN argument
for `sdxl`, not a separate certification (no local SynthID detector to self-verify).
for `sdxl`, not a separate certification (the tested geometries are outside the
current local detector's scope).
The higher strength costs little quality where it matters, because `controlnet` is now
the default pipeline, so `sdxl` is reached only via an explicit `--pipeline sdxl` (a
deliberate opt-down), where over-regeneration has no faces/text to damage.
@@ -810,7 +896,7 @@ random (unset) seed differed between runs. So **0.15 is the borderline floor for
controlnet photoreal, not a robust guarantee**: at the threshold the same
image+settings can pass or fail run-to-run. img2img runs with `seed=None` (random)
unless `--seed` is passed, so a removal SERVICE gets a coin-flip near threshold and
has no local SynthID detector to self-verify.
has no applicable local SynthID detector at these geometries to self-verify.
**Controlnet strength ladder on the two photoreal images (oracle, `--auto`,
`--max-resolution 1536`):**
@@ -825,7 +911,7 @@ has no local SynthID detector to self-verify.
non-deterministic borderline); both photoreal survivors cleared at 0.20. Honest
caveat: 0.20 is one confirming run WITH margin, not an N-run repeatability proof --
for a removal service, add a little more margin or validate repeatability, since
there is no local SynthID detector to self-check. **Implications:** (1) the
these geometries are outside the current local detector's scope. **Implications:** (1) the
content×pipeline table above conflates a borderline/non-deterministic 0.15 result
with deterministic content behavior -- the photoreal-survives-controlnet effect is
solid at 0.10 but at 0.15 it is near-threshold noise; (2) for reliable removal pick
@@ -910,3 +996,6 @@ reproducible verification requires a fixed seed.
8. Jiang et al. (2025). **VideoMarkBench: Benchmarking Robustness of Video
Watermarking.** arXiv:2505.21620.
https://arxiv.org/abs/2505.21620
9. OpenAI. **ChatGPT Images 2.0 system card.**
https://deploymentsafety.openai.com/chatgpt-images-2-0/automated-evaluations-and-adversarial-testing
+6 -1
View File
@@ -64,7 +64,12 @@ payloads. Removal remuxes either container through ffmpeg with stream copy.
may carry IPTC metadata but no registered C2PA or pixel watermark. The open
DWT-DCT decoder only applies when the producing pipeline actually ran its
encoder and the carrier remains decodable.
- **Invisible but NOT locally detectable (proprietary, API/oracle only — same wall as SynthID):** Amazon Titan Image Generator + Nova Canvas (Bedrock `DetectGeneratedContent` API), Kakao (new SynthID image adopter, May 2026), NVIDIA Cosmos (SynthID video). No local detector possible; treat like SynthID.
- **Invisible but NOT locally detectable (proprietary, API/oracle only):**
Amazon Titan Image Generator + Nova Canvas (Bedrock
`DetectGeneratedContent` API), Kakao (new SynthID image adopter, May 2026),
and NVIDIA Cosmos (SynthID video). No public payload decoder is available;
unlike the project's calibrated-size SynthID carrier expert, these signals
have no measured local detector here.
- **C2PA 2.4 "Durable Content Credentials" (April 2026; verified against the spec) raise the bar for metadata stripping.** 2.4 defines soft bindings (an invisible watermark or a content fingerprint) plus a server-side manifest repository and a new `c2pa.repository-receipt` assertion. Per the spec: "if a C2PA manifest is removed from an asset, but a copy of that manifest remains in a provenance store elsewhere, the manifest and asset may be matched using available soft bindings." So our local `metadata --remove` deletes the *embedded* manifest, but a fingerprint/watermark soft binding can still re-link the image to its manifest in a repository server-side. Stripping the file is becoming necessary-but-not-sufficient against durable provenance. (Our parsers target the stable embedded-manifest format documented in C2PA 2.1 §11; that format is unchanged in 2.4 -- the new pieces are repository/soft-binding infra, not the on-file box layout, so no parser change is implied.) Spec: https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html We now READ the soft-binding `alg` (`C2PA_SOFT_BINDINGS` / `soft_binding_vendors_in`) to name the forensic-watermark vendor, and locally DECODE the one open scheme, Adobe TrustMark (`trustmark_detector`); the rest (Digimarc/Imatag/Steg.AI/...) stay name-only (proprietary decoders).
- **Built in the dated batch:** soft-binding vendor detection, IPTC Photo
Metadata AI-disclosure fields, C2PA detection and stripping for supported