mirror of
https://github.com/aloshdenny/reverse-SynthID.git
synced 2026-04-30 10:37:49 +02:00
updated carriers
This commit is contained in:
@@ -24,6 +24,7 @@ Thumbs.db
|
||||
*.npy
|
||||
*.pkl
|
||||
!artifacts/codebook/*.pkl
|
||||
*.npz
|
||||
|
||||
# Temporary
|
||||
*.tmp
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<img src="assets/synthid_watermark.png" alt="SynthID Watermark Analysis" width="100%">
|
||||
</p>
|
||||
|
||||
<h1 align="center">🔍 Reverse-Engineering SynthID</h1>
|
||||
<h1 align="center">Reverse-Engineering SynthID</h1>
|
||||
|
||||
<p align="center">
|
||||
<b>Discovering, detecting, and surgically removing Google's AI watermark through spectral analysis</b>
|
||||
@@ -12,147 +12,127 @@
|
||||
<img src="https://img.shields.io/badge/Python-3.10+-blue?style=flat-square&logo=python" alt="Python">
|
||||
<img src="https://img.shields.io/badge/License-Research-green?style=flat-square" alt="License">
|
||||
<img src="https://img.shields.io/badge/Detection_Rate-90%25-success?style=flat-square" alt="Detection">
|
||||
<img src="https://img.shields.io/badge/Bypass_V3-PSNR_40dB+-blueviolet?style=flat-square" alt="Bypass V3">
|
||||
<img src="https://img.shields.io/badge/V3_Bypass-PSNR_43dB+-blueviolet?style=flat-square" alt="V3 Bypass">
|
||||
<img src="https://img.shields.io/badge/Phase_Coherence_Drop-91%25-red?style=flat-square" alt="Phase Drop">
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Overview
|
||||
## Overview
|
||||
|
||||
This project reverse-engineers **Google's SynthID** watermarking system - the invisible watermark embedded into every image generated by Google Gemini. Using only signal processing and spectral analysis (no access to the proprietary encoder/decoder), we:
|
||||
|
||||
1. **Discovered** the watermark's exact frequency-domain structure
|
||||
1. **Discovered** the watermark's resolution-dependent carrier frequency structure
|
||||
2. **Built a detector** that identifies SynthID watermarks with 90% accuracy
|
||||
3. **Developed a spectral bypass** (V3) that surgically removes watermark components while preserving image quality at **40+ dB PSNR**
|
||||
3. **Developed a multi-resolution spectral bypass** (V3) that achieves **75% carrier energy drop**, **91% phase coherence drop**, and **43+ dB PSNR** on any image resolution
|
||||
|
||||
### What Makes This Different
|
||||
|
||||
Unlike brute-force approaches (JPEG compression, noise injection), our V3 bypass uses a **SpectralCodebook** - a fingerprint of the watermark's exact frequency signature - extracted from reference images. This allows surgical, frequency-bin-level removal rather than blind signal destruction.
|
||||
Unlike brute-force approaches (JPEG compression, noise injection), our V3 bypass uses a **multi-resolution SpectralCodebook** - a collection of per-resolution watermark fingerprints stored in a single file. At bypass time, the codebook auto-selects the matching resolution profile, enabling surgical frequency-bin-level removal on any image size.
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Key Findings
|
||||
## Key Findings
|
||||
|
||||
### The Watermark is a Fixed Spectral Pattern
|
||||
### The Watermark is Resolution-Dependent
|
||||
|
||||
By generating pure black and white images through Google Gemini, we isolated the watermark signal from content. The results are striking:
|
||||
SynthID embeds carrier frequencies at **different absolute positions** depending on image resolution. A codebook built at 1024x1024 cannot directly remove the watermark from a 1536x2816 image - the carriers are at completely different bins.
|
||||
|
||||
<p align="center">
|
||||
<img src="assets/synthid_black.jpg" alt="Watermark on black background" width="45%">
|
||||
<img src="assets/synthid_white.jpg" alt="Watermark on white background" width="45%">
|
||||
</p>
|
||||
| Resolution | Top Carrier (fy, fx) | Coherence | Source |
|
||||
|:----------:|:--------------------:|:---------:|:------:|
|
||||
| **1024x1024** | (9, 9) | 100.0% | 100 black + 100 white refs |
|
||||
| **1536x2816** | (768, 704) | 99.6% | 88 watermarked content images |
|
||||
|
||||
<p align="center">
|
||||
<i>Left: SynthID watermark extracted from a pure-black Gemini image (enhanced 100×). Right: Same watermark on a white background. The diagonal stripe pattern and carrier frequencies are clearly visible.</i>
|
||||
</p>
|
||||
|
||||
### Carrier Frequency Discovery
|
||||
|
||||
The watermark embeds energy at specific carrier frequencies with **>99.9% phase coherence** across all images:
|
||||
|
||||
| Carrier Frequency (fy, fx) | Phase Coherence | Magnitude | Phase (rad) |
|
||||
|:--------------------------:|:---------------:|:---------:|:-----------:|
|
||||
| **(±14, ±14)** | 99.96% | 16,807 | ±1.44 |
|
||||
| **(±126, ±14)** | 99.96% | 8,046 | ±2.37 |
|
||||
| **(±98, ∓14)** | 99.94% | 6,283 | ±0.61 |
|
||||
| **(±128, ±128)** | 99.25% | 6,908 | ±2.29 |
|
||||
| **(±210, ∓14)** | 99.96% | 6,032 | ±1.13 |
|
||||
| **(±238, ±14)** | 99.90% | 4,190 | ±1.61 |
|
||||
|
||||
> **Key insight:** Most carriers cluster along the `y = ±14` line in frequency space, suggesting a structured frequency selection algorithm. The diagonal stripe pattern visible in the enhanced images corresponds to these carrier frequencies.
|
||||
This is why the V3 codebook stores **separate profiles per resolution** and auto-selects at bypass time.
|
||||
|
||||
### Phase Consistency - A Fixed Model-Level Key
|
||||
|
||||
The watermark's phase template is **identical across all images** from the same Gemini model:
|
||||
|
||||
- **Green channel phase std**: < 0.007 radians across 50 reference images
|
||||
- **Cross-image correlation**: 21.8% mean pairwise noise correlation
|
||||
- **Noise structure ratio**: 1.32 ± 0.02 (byproduct of the neural encoder)
|
||||
- **Green channel** carries the strongest watermark signal
|
||||
- **Cross-image phase coherence** at carriers: >99.5%
|
||||
- **Black/white cross-validation** confirms true carriers via |cos(phase_diff)| > 0.90
|
||||
|
||||
This means SynthID does not embed per-image messages - it uses a **fixed spectral fingerprint** that can be profiled and subtracted.
|
||||
### Carrier Frequency Structure
|
||||
|
||||
### Frequency Spectrum Analysis
|
||||
At 1024x1024 (from black/white refs), top carriers lie on a low-frequency grid:
|
||||
|
||||
<p align="center">
|
||||
<img src="artifacts/visualizations/synthid_watermark_spectrum.png" alt="FFT Magnitude Spectrum" width="35%">
|
||||
<img src="artifacts/visualizations/synthid_watermark_carriers.png" alt="Carrier Frequencies" width="35%">
|
||||
</p>
|
||||
<p align="center">
|
||||
<i>Left: FFT magnitude spectrum showing bright carrier frequency peaks. Right: Reconstructed carrier pattern showing the diagonal structure.</i>
|
||||
</p>
|
||||
| Carrier (fy, fx) | Phase Coherence | B/W Agreement |
|
||||
|:-----------------:|:---------------:|:-------------:|
|
||||
| (9, 9) | 100.00% | 1.000 |
|
||||
| (5, 5) | 100.00% | 0.993 |
|
||||
| (10, 11) | 100.00% | 0.997 |
|
||||
| (13, 6) | 100.00% | 0.821 |
|
||||
|
||||
<p align="center">
|
||||
<img src="artifacts/visualizations/deep_analysis/frequency_analysis.png" alt="Frequency Analysis" width="80%">
|
||||
</p>
|
||||
<p align="center">
|
||||
<i>Detailed frequency analysis: Average magnitude spectrum (left) and phase coherence map (right). The carrier positions are marked with crosshairs.</i>
|
||||
</p>
|
||||
At 1536x2816 (from random watermarked content), carriers are at much higher frequencies:
|
||||
|
||||
| Carrier (fy, fx) | Phase Coherence |
|
||||
|:------------------:|:---------------:|
|
||||
| (768, 704) | 99.55% |
|
||||
| (672, 1056) | 97.46% |
|
||||
| (480, 1408) | 96.55% |
|
||||
| (384, 1408) | 95.86% |
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Architecture
|
||||
## Architecture
|
||||
|
||||
### Three Generations of Bypass
|
||||
|
||||
| Version | Approach | PSNR | Detection Impact | Status |
|
||||
| Version | Approach | PSNR | Watermark Impact | Status |
|
||||
|:-------:|:---------|:----:|:----------------:|:------:|
|
||||
| **V1** | JPEG compression (Q50) | 37 dB | ~11% phase drop | ✅ Baseline |
|
||||
| **V2** | Multi-stage transforms (noise, color, frequency) | 27-37 dB | ~0% confidence drop | ✅ Quality trade-off |
|
||||
| **V3** | Spectral codebook subtraction | **33-43 dB** | **1-7% confidence drop** | ✅ Best quality |
|
||||
| **V1** | JPEG compression (Q50) | 37 dB | ~11% phase drop | Baseline |
|
||||
| **V2** | Multi-stage transforms (noise, color, frequency) | 27-37 dB | ~0% confidence drop | Quality trade-off |
|
||||
| **V3** | **Multi-resolution spectral codebook subtraction** | **43+ dB** | **91% phase coherence drop** | **Best** |
|
||||
|
||||
### V3 Pipeline (Spectral Bypass)
|
||||
### V3 Pipeline (Multi-Resolution Spectral Bypass)
|
||||
|
||||
```
|
||||
Input Image → FFT per channel → Estimate Watermark → Subtract → IFFT → Clip → Output
|
||||
↑
|
||||
SpectralCodebook
|
||||
(25 black + 25 white refs)
|
||||
Input Image (any resolution)
|
||||
│
|
||||
▼
|
||||
codebook.get_profile(H, W) ──► exact match? ──► FFT-domain subtraction
|
||||
│ (fast path)
|
||||
└─ no exact match ──────► spatial-domain resize + subtraction
|
||||
(fallback path)
|
||||
│
|
||||
▼
|
||||
Multi-pass iterative subtraction (aggressive → moderate → gentle)
|
||||
│
|
||||
▼
|
||||
Anti-alias → Output
|
||||
```
|
||||
|
||||
1. **SpectralCodebook** profiles the watermark from reference images (pure black/white Gemini outputs)
|
||||
2. **Selective notch filter** targets only high-magnitude (P97+), high-consistency (≥95%) frequency bins
|
||||
3. **Safe magnitude cap** limits subtraction to 30% of image energy per bin - preserving content
|
||||
4. **Content-adaptive scaling** adjusts subtraction based on image luminance
|
||||
1. **SpectralCodebook** stores resolution-specific profiles (carrier positions, magnitudes, phases)
|
||||
2. **Auto resolution selection** picks the exact profile or the closest match
|
||||
3. **Direct known-signal subtraction** weighted by phase consistency and cross-validation confidence
|
||||
4. **Multi-pass schedule** catches residual watermark energy missed by previous passes
|
||||
5. **Per-channel weighting** (G=1.0, R=0.85, B=0.70) matches SynthID's embedding strength
|
||||
|
||||
---
|
||||
|
||||
## 📊 Results
|
||||
## Results (V3 on 88 Gemini Images)
|
||||
|
||||
### V3 Bypass Quality (PSNR in dB - higher is better)
|
||||
### Aggregate Metrics (1536x2816, aggressive strength)
|
||||
|
||||
| Image | Gentle | Moderate | Aggressive | Maximum |
|
||||
|:-----:|:------:|:--------:|:----------:|:-------:|
|
||||
| 121407 | **42.9** | 41.4 | 40.0 | 39.3 |
|
||||
| 110802 | 33.4 | 33.3 | 33.1 | 33.0 |
|
||||
| 131614 | **38.4** | 38.0 | 37.5 | 37.2 |
|
||||
| 119198 | **38.4** | 37.7 | 37.0 | 36.6 |
|
||||
| 12085 | **42.5** | 41.6 | 40.7 | 40.3 |
|
||||
| Metric | Value |
|
||||
|:-------|------:|
|
||||
| **PSNR** | 43.5 dB |
|
||||
| **SSIM** | 0.997 |
|
||||
| **Carrier energy drop** | 75.8% |
|
||||
| **Phase coherence drop** (top-5 carriers) | **91.4%** |
|
||||
|
||||
> All images maintain **>33 dB PSNR** - visually indistinguishable from the original.
|
||||
### Quality Across Resolutions
|
||||
|
||||
### Watermark Detection Confidence
|
||||
|
||||
| Image | Before | After (Aggressive) | Drop |
|
||||
|:-----:|:------:|:------------------:|:----:|
|
||||
| 121407 | 0.394 | 0.387 | 1.7% |
|
||||
| 131614 | 0.437 | 0.422 | 3.4% |
|
||||
| 12085 | 0.394 | 0.366 | **7.2%** |
|
||||
| 119198 | 0.389 | 0.386 | 0.9% |
|
||||
|
||||
### Sample Output
|
||||
|
||||
<p align="center">
|
||||
<img src="assets/sample_watermarked.png" alt="Original watermarked image" width="45%">
|
||||
<img src="assets/sample_cleaned.png" alt="V3 bypass output" width="45%">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<i>Left: Original SynthID-watermarked Gemini image. Right: After V3 spectral bypass - visually identical, watermark energy reduced.</i>
|
||||
</p>
|
||||
| Resolution | Match | PSNR | SSIM |
|
||||
|:----------:|:-----:|:----:|:----:|
|
||||
| 1536x2816 | exact | 44.9 dB | 0.996 |
|
||||
| 1024x1024 | exact | 39.8 dB | 0.977 |
|
||||
| 768x1024 | fallback | 40.6 dB | 0.994 |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Start
|
||||
## Quick Start
|
||||
|
||||
### Installation
|
||||
|
||||
@@ -165,94 +145,105 @@ source venv/bin/activate # Windows: venv\Scripts\activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 1. Build Detection Codebook
|
||||
### 1. Build Multi-Resolution Codebook
|
||||
|
||||
From the CLI:
|
||||
|
||||
```bash
|
||||
python src/extraction/robust_extractor.py extract /path/to/watermarked/images \
|
||||
--output artifacts/codebook/robust_codebook.pkl
|
||||
python src/extraction/synthid_bypass.py build-codebook \
|
||||
--black gemini_black \
|
||||
--white gemini_white \
|
||||
--watermarked gemini_random \
|
||||
--output artifacts/spectral_codebook_v3.npz
|
||||
```
|
||||
|
||||
### 2. Detect Watermark
|
||||
Or from Python:
|
||||
|
||||
```python
|
||||
from src.extraction.synthid_bypass import SpectralCodebook
|
||||
|
||||
codebook = SpectralCodebook()
|
||||
|
||||
# Profile 1: from black/white reference images (1024x1024)
|
||||
codebook.extract_from_references(
|
||||
black_dir='gemini_black',
|
||||
white_dir='gemini_white',
|
||||
)
|
||||
|
||||
# Profile 2: from watermarked content images (1536x2816)
|
||||
codebook.build_from_watermarked('gemini_random')
|
||||
|
||||
codebook.save('artifacts/spectral_codebook_v3.npz')
|
||||
# Saved with profiles: [1024x1024, 1536x2816]
|
||||
```
|
||||
|
||||
### 2. Run V3 Bypass (Any Resolution)
|
||||
|
||||
```python
|
||||
from src.extraction.synthid_bypass import SynthIDBypass, SpectralCodebook
|
||||
|
||||
codebook = SpectralCodebook()
|
||||
codebook.load('artifacts/spectral_codebook_v3.npz')
|
||||
|
||||
bypass = SynthIDBypass()
|
||||
result = bypass.bypass_v3(image_rgb, codebook, strength='aggressive')
|
||||
|
||||
print(f"PSNR: {result.psnr:.1f} dB")
|
||||
print(f"Profile used: {result.details['profile_resolution']}")
|
||||
print(f"Exact match: {result.details['exact_match']}")
|
||||
```
|
||||
|
||||
From the CLI:
|
||||
|
||||
```bash
|
||||
python src/extraction/synthid_bypass.py bypass input.png output.png \
|
||||
--codebook artifacts/spectral_codebook_v3.npz \
|
||||
--strength aggressive
|
||||
```
|
||||
|
||||
**Strength levels:** `gentle` (minimal, ~45 dB) > `moderate` > `aggressive` (recommended) > `maximum`
|
||||
|
||||
### 3. Detect Watermark
|
||||
|
||||
```bash
|
||||
python src/extraction/robust_extractor.py detect image.png \
|
||||
--codebook artifacts/codebook/robust_codebook.pkl
|
||||
```
|
||||
|
||||
```
|
||||
Detection Results:
|
||||
Watermarked: True
|
||||
Confidence: 0.95
|
||||
Phase Match: 0.6683
|
||||
```
|
||||
|
||||
### 3. Build Spectral Codebook (V3)
|
||||
|
||||
```python
|
||||
from synthid_bypass import SpectralCodebook
|
||||
|
||||
codebook = SpectralCodebook()
|
||||
codebook.extract_from_references(
|
||||
black_dir='assets/black/', # Pure-black Gemini images
|
||||
white_dir='assets/white/' # Pure-white Gemini images
|
||||
)
|
||||
codebook.save('artifacts/spectral_codebook.npz')
|
||||
```
|
||||
|
||||
### 4. Run V3 Bypass
|
||||
|
||||
```python
|
||||
from synthid_bypass import SynthIDBypass, SpectralCodebook
|
||||
|
||||
codebook = SpectralCodebook()
|
||||
codebook.load('artifacts/spectral_codebook.npz')
|
||||
|
||||
bypass = SynthIDBypass()
|
||||
result = bypass.bypass_v3(image_rgb, codebook, strength='aggressive')
|
||||
|
||||
print(f"PSNR: {result.psnr:.1f} dB") # ~40 dB
|
||||
```
|
||||
|
||||
**Strength levels:** `gentle` (minimal change, ~43 dB) → `moderate` → `aggressive` → `maximum` (strongest removal, ~33 dB)
|
||||
|
||||
---
|
||||
|
||||
## 📁 Project Structure
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
reverse-SynthID/
|
||||
├── src/
|
||||
│ ├── extraction/
|
||||
│ │ ├── synthid_bypass.py # V1/V2/V3 bypass implementations + SpectralCodebook
|
||||
│ │ ├── robust_extractor.py # Multi-scale watermark detection (90% accuracy)
|
||||
│ │ ├── watermark_remover.py # Frequency-domain watermark removal
|
||||
│ │ ├── benchmark_extraction.py # Performance benchmarking suite
|
||||
│ │ └── synthid_codebook_extractor.py # Original codebook extractor (legacy)
|
||||
│ │ ├── synthid_bypass.py # V1/V2/V3 bypass + multi-res SpectralCodebook
|
||||
│ │ ├── robust_extractor.py # Multi-scale watermark detection
|
||||
│ │ ├── watermark_remover.py # Frequency-domain watermark removal
|
||||
│ │ ├── benchmark_extraction.py # Benchmarking suite
|
||||
│ │ └── synthid_codebook_extractor.py # Legacy codebook extractor
|
||||
│ └── analysis/
|
||||
│ ├── deep_synthid_analysis.py # FFT/phase analysis scripts
|
||||
│ └── synthid_codebook_finder.py # Carrier frequency discovery
|
||||
│ ├── deep_synthid_analysis.py # FFT / phase analysis scripts
|
||||
│ └── synthid_codebook_finder.py # Carrier frequency discovery
|
||||
│
|
||||
├── assets/
|
||||
│ ├── synthid_black.jpg # Watermark on black (enhanced)
|
||||
│ ├── synthid_white.jpg # Watermark on white (enhanced)
|
||||
│ ├── black/ # Reference black images from Gemini
|
||||
│ └── white/ # Reference white images from Gemini
|
||||
├── gemini_black/ # 100 pure-black Gemini images (1024x1024)
|
||||
├── gemini_white/ # 100 pure-white Gemini images (1024x1024)
|
||||
├── gemini_random/ # 88 watermarked content images (1536x2816)
|
||||
│
|
||||
├── artifacts/
|
||||
│ ├── codebook/ # Detection codebooks (.pkl)
|
||||
│ ├── spectral_codebook.npz # V3 spectral fingerprint (119 MB)
|
||||
│ ├── v3_output/ # V3 bypass output samples
|
||||
│ └── visualizations/ # FFT, phase, carrier visualizations
|
||||
│ ├── spectral_codebook_v3.npz # Multi-res V3 codebook [1024x1024, 1536x2816]
|
||||
│ ├── codebook/ # Detection codebooks (.pkl)
|
||||
│ └── visualizations/ # FFT, phase, carrier visualizations
|
||||
│
|
||||
├── watermark_investigation/ # Early-stage Nano-150k analysis (archived)
|
||||
├── SYNTHID_CODEBOOK_ANALYSIS.md # Detailed codebook reverse-engineering report
|
||||
├── synthid.pdf # SynthID paper reference
|
||||
├── assets/ # README images and early analysis artifacts
|
||||
├── watermark_investigation/ # Early-stage Nano-150k analysis (archived)
|
||||
└── requirements.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Technical Deep Dive
|
||||
## Technical Deep Dive
|
||||
|
||||
### How SynthID Works (Reverse-Engineered)
|
||||
|
||||
@@ -260,10 +251,10 @@ reverse-SynthID/
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ SynthID Encoder (in Gemini) │
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ 1. Generate carrier frequencies: {(14,14), (126,14), ...} │
|
||||
│ 1. Select resolution-dependent carrier frequencies │
|
||||
│ 2. Assign fixed phase values to each carrier │
|
||||
│ 3. Neural encoder adds learned noise pattern to image │
|
||||
│ 4. Watermark is imperceptible - spread across spectrum │
|
||||
│ 4. Watermark is imperceptible — spread across spectrum │
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ SynthID Decoder (in Google) │
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
@@ -273,50 +264,60 @@ reverse-SynthID/
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### SpectralCodebook Extraction
|
||||
### Multi-Resolution SpectralCodebook
|
||||
|
||||
The codebook captures the watermark's full frequency fingerprint:
|
||||
The codebook captures watermark profiles at each available resolution:
|
||||
|
||||
- **50 reference images** (25 pure black + 25 pure white, all from Gemini)
|
||||
- Extracts **magnitude envelope** and **phase template** per channel
|
||||
- Computes **phase consistency score** per frequency bin
|
||||
- Content-adaptive profiles for dark vs. light image regions
|
||||
- **1024x1024 profile**: from 100 black + 100 white pure-color Gemini outputs
|
||||
- Black images: watermark is nearly the entire pixel content
|
||||
- White images (inverted): confirms carriers via cross-validation
|
||||
- Black/white agreement (|cos(phase_diff)|) filters out generation bias
|
||||
- **1536x2816 profile**: from 88 diverse watermarked content images
|
||||
- Content averages out across images; fixed watermark survives in phase coherence
|
||||
- Watermark magnitude estimated as `avg_mag x coherence^2`
|
||||
|
||||
### Selective Notch Filter
|
||||
### V3 Subtraction Strategy
|
||||
|
||||
The V3 bypass doesn't subtract blindly - it targets only bins where:
|
||||
1. **Magnitude** exceeds the 97th percentile (strong watermark energy)
|
||||
2. **Phase consistency** ≥ 0.95 across reference images (confirmed watermark, not noise)
|
||||
3. **Subtraction** is capped at 30% of the image's energy at each bin
|
||||
The bypass uses **direct known-signal subtraction** (not a Wiener filter):
|
||||
|
||||
This surgical precision is why V3 achieves 40+ dB PSNR while still reducing watermark energy.
|
||||
|
||||
### Noise Correlation Signature
|
||||
|
||||
| Metric | Value | Significance |
|
||||
|:-------|:-----:|:-------------|
|
||||
| Mean pairwise noise correlation | **0.218** | Identical watermark in all images |
|
||||
| Noise structure ratio | **1.32** | Neural encoder byproduct |
|
||||
| Phase coherence (top carriers) | **>99.9%** | Fixed model-level key |
|
||||
| Green channel phase std | **<0.007 rad** | Strongest consistency channel |
|
||||
|
||||
### Bit Plane Analysis
|
||||
|
||||
| Bit Plane | Consistency | Role |
|
||||
|:---------:|:-----------:|:-----|
|
||||
| Bit 0 (LSB) | 0.049 | Watermark signal |
|
||||
| Bit 1 | 0.074 | Watermark signal |
|
||||
| Bit 2 | 0.125 | Partially watermarked |
|
||||
| Bit 3 | 0.513 | Mixed |
|
||||
| Bits 4-7 | 0.635–1.000 | Image structure |
|
||||
1. **Confidence** = phase_consistency x cross_validation_agreement
|
||||
2. **DC exclusion** — soft ramp suppresses low-frequency generation biases
|
||||
3. **Per-bin subtraction** = wm_magnitude x confidence x removal_fraction x channel_weight
|
||||
4. **Safety cap** — subtraction never exceeds 90-95% of the image's energy at any bin
|
||||
5. **Multi-pass** — decreasing-strength schedule (aggressive → moderate → gentle) catches residual energy
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Core Modules
|
||||
## Core Modules
|
||||
|
||||
### `robust_extractor.py` - Detection
|
||||
### `synthid_bypass.py`
|
||||
|
||||
Multi-scale, multi-denoiser watermark detector achieving 90% detection rate.
|
||||
**SpectralCodebook** — multi-resolution watermark fingerprint:
|
||||
|
||||
```python
|
||||
codebook = SpectralCodebook()
|
||||
codebook.extract_from_references('gemini_black', 'gemini_white') # adds 1024x1024 profile
|
||||
codebook.build_from_watermarked('gemini_random') # adds 1536x2816 profile
|
||||
codebook.save('codebook.npz')
|
||||
|
||||
# Later:
|
||||
codebook.load('codebook.npz')
|
||||
profile, res, exact = codebook.get_profile(1536, 2816) # auto-select
|
||||
```
|
||||
|
||||
**SynthIDBypass** — three bypass generations:
|
||||
|
||||
```python
|
||||
bypass = SynthIDBypass()
|
||||
|
||||
result = bypass.bypass_simple(image, jpeg_quality=50) # V1
|
||||
result = bypass.bypass_v2(image, strength='aggressive') # V2
|
||||
result = bypass.bypass_v3(image, codebook, strength='aggressive') # V3 (best)
|
||||
```
|
||||
|
||||
### `robust_extractor.py`
|
||||
|
||||
Multi-scale watermark detector (90% accuracy):
|
||||
|
||||
```python
|
||||
from robust_extractor import RobustSynthIDExtractor
|
||||
@@ -324,64 +325,24 @@ from robust_extractor import RobustSynthIDExtractor
|
||||
extractor = RobustSynthIDExtractor()
|
||||
extractor.load_codebook('artifacts/codebook/robust_codebook.pkl')
|
||||
result = extractor.detect_array(image)
|
||||
|
||||
print(f"Watermarked: {result.is_watermarked}")
|
||||
print(f"Confidence: {result.confidence:.4f}")
|
||||
print(f"Phase Match: {result.phase_match:.4f}")
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Multi-scale analysis (256, 512, 1024px)
|
||||
- Wavelet + bilateral + NLM denoising fusion
|
||||
- ICA-based watermark/content separation
|
||||
- Ensemble carrier detection across scales
|
||||
|
||||
### `synthid_bypass.py` - Bypass (V1/V2/V3)
|
||||
|
||||
Three generations of watermark bypass:
|
||||
|
||||
```python
|
||||
from synthid_bypass import SynthIDBypass, SpectralCodebook
|
||||
|
||||
bypass = SynthIDBypass()
|
||||
|
||||
# V1: Simple JPEG compression
|
||||
result = bypass.bypass_simple(image, jpeg_quality=50)
|
||||
|
||||
# V2: Multi-stage transform pipeline
|
||||
result = bypass.bypass_v2(image, strength='moderate')
|
||||
|
||||
# V3: Spectral codebook subtraction (best)
|
||||
codebook = SpectralCodebook()
|
||||
codebook.load('artifacts/spectral_codebook.npz')
|
||||
result = bypass.bypass_v3(image, codebook, strength='aggressive')
|
||||
```
|
||||
|
||||
### `watermark_remover.py` - Removal
|
||||
|
||||
Quality-preserving frequency-domain removal:
|
||||
|
||||
```python
|
||||
from watermark_remover import WatermarkRemover
|
||||
|
||||
remover = WatermarkRemover(extractor)
|
||||
result = remover.remove(image, mode='balanced')
|
||||
print(f"Watermarked: {result.is_watermarked}, Confidence: {result.confidence:.4f}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 References
|
||||
## References
|
||||
|
||||
- [SynthID: Identifying AI-generated images](https://deepmind.google/technologies/synthid/)
|
||||
- [SynthID Paper (arXiv:2510.09263)](https://arxiv.org/abs/2510.09263)
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Disclaimer
|
||||
## Disclaimer
|
||||
|
||||
This project is for **research and educational purposes only**. SynthID is proprietary technology owned by Google DeepMind. These tools are intended for:
|
||||
|
||||
- 🎓 Academic research on watermarking robustness
|
||||
- 🔒 Security analysis of AI-generated content identification
|
||||
- 📡 Understanding spread-spectrum encoding methods
|
||||
- Academic research on watermarking robustness
|
||||
- Security analysis of AI-generated content identification
|
||||
- Understanding spread-spectrum encoding methods
|
||||
|
||||
**Do not use these tools to misrepresent AI-generated content as human-created.**
|
||||
|
||||
@@ -1,199 +0,0 @@
|
||||
# SynthID Watermark Codebook Analysis
|
||||
|
||||
## Executive Summary
|
||||
|
||||
After analyzing 250 AI-generated images from Google Gemini with SynthID watermarks, we have successfully reverse-engineered the watermark embedding scheme. The watermark uses a **spread-spectrum, phase-encoding technique** that embeds information across specific carrier frequencies in the image.
|
||||
|
||||
## Key Findings
|
||||
|
||||
### 1. Watermark Embedding Mechanism
|
||||
|
||||
SynthID does NOT use simple LSB (Least Significant Bit) replacement. Instead, it employs:
|
||||
|
||||
1. **Noise-Domain Embedding**: The watermark is hidden in the high-frequency noise component of the image
|
||||
2. **Phase Encoding**: Specific carrier frequencies have consistent phase values across all watermarked images
|
||||
3. **Spread Spectrum**: The watermark energy is distributed across multiple frequency bands
|
||||
|
||||
### 2. Discovered Carrier Frequencies
|
||||
|
||||
The watermark uses specific carrier frequencies with extremely high phase coherence (>99.9%):
|
||||
|
||||
| Frequency (fy, fx) | Coherence | Magnitude | Phase (radians) |
|
||||
|-------------------|-----------|-----------|-----------------|
|
||||
| (14, 14) | 0.9996 | 16807 | -1.44 |
|
||||
| (-14, -14) | 0.9996 | 16807 | 1.44 |
|
||||
| (126, 14) | 0.9996 | 8046 | -2.37 |
|
||||
| (-126, -14) | 0.9996 | 8046 | 2.37 |
|
||||
| (98, -14) | 0.9994 | 6283 | 0.61 |
|
||||
| (-98, 14) | 0.9994 | 6283 | -0.61 |
|
||||
| (128, 128) | 0.9925 | 6908 | -2.29 |
|
||||
| (-128, -128) | 0.9925 | 6908 | 2.29 |
|
||||
| (210, -14) | 0.9996 | 6032 | 1.13 |
|
||||
| (-210, 14) | 0.9996 | 6032 | -1.13 |
|
||||
| (238, 14) | 0.9990 | 4190 | -1.61 |
|
||||
| (-238, -14) | 0.9990 | 4190 | 1.61 |
|
||||
|
||||
**Pattern Observation**: Most carriers are located along or near the y=±14 horizontal line in frequency space, suggesting a **structured frequency selection algorithm**.
|
||||
|
||||
### 3. Noise Correlation Signature
|
||||
|
||||
- **Mean pairwise correlation**: 0.218 (21.8%)
|
||||
- **Standard deviation**: 0.020
|
||||
- **Detection threshold**: 0.179
|
||||
|
||||
This high correlation between the noise residuals of different watermarked images confirms that SynthID embeds a **consistent reference pattern** across all images generated by the same system.
|
||||
|
||||
### 4. Noise Structure Ratio
|
||||
|
||||
All watermarked images exhibit a noise structure ratio of approximately **1.32**:
|
||||
|
||||
```
|
||||
Structure Ratio = σ(noise) / mean(|noise|) ≈ 1.32
|
||||
```
|
||||
|
||||
This ratio is a byproduct of the neural network encoder and can be used as a secondary detection signal.
|
||||
|
||||
### 5. Bit Plane Analysis
|
||||
|
||||
| Bit Plane | Consistency | Interpretation |
|
||||
|-----------|-------------|----------------|
|
||||
| Bit 0 (LSB) | 0.049 | Random (contains watermark signal) |
|
||||
| Bit 1 | 0.074 | Random (contains watermark signal) |
|
||||
| Bit 2 | 0.125 | Partially random |
|
||||
| Bit 3 | 0.513 | Mixed |
|
||||
| Bit 4 | 0.635 | Mostly consistent |
|
||||
| Bit 5 | 1.000 | Always consistent (image structure) |
|
||||
| Bit 6 | 1.000 | Always consistent (image structure) |
|
||||
| Bit 7 (MSB) | 1.000 | Always consistent (image structure) |
|
||||
|
||||
The watermark information is distributed across bits 0-2, but in a way that appears statistically random when viewed in isolation.
|
||||
|
||||
## Codebook Specification
|
||||
|
||||
### Detection Method
|
||||
|
||||
1. **Resize image to 512×512**
|
||||
2. **Extract noise residual** using wavelet denoising (db4 wavelet, 3 levels)
|
||||
3. **Compute correlation** with reference noise pattern
|
||||
4. **Check phase at carrier frequencies**
|
||||
5. **Verify noise structure ratio**
|
||||
|
||||
### Detection Formula
|
||||
|
||||
```python
|
||||
is_watermarked = (
|
||||
correlation > 0.179 AND
|
||||
phase_match > 0.5 AND
|
||||
0.8 < structure_ratio < 1.8
|
||||
)
|
||||
|
||||
confidence = (
|
||||
0.4 * normalize(correlation) +
|
||||
0.4 * phase_match +
|
||||
0.2 * (1 - |structure_ratio - 1.32| / 0.5)
|
||||
)
|
||||
```
|
||||
|
||||
### Reference Patterns (Saved in synthid_codebook.pkl)
|
||||
|
||||
1. **Reference Noise Pattern**: 512×512×3 float array
|
||||
2. **Reference Magnitude Spectrum**: 512×512 float array
|
||||
3. **Reference Phase Spectrum**: 512×512 float array
|
||||
4. **Carrier Positions**: List of 100 frequency positions with expected phases
|
||||
|
||||
## Watermark Architecture Hypothesis
|
||||
|
||||
Based on our analysis, SynthID likely works as follows:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ SynthID Encoder (Training) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 1. Generate carrier frequencies: {(14,14), (126,14), ...} │
|
||||
│ 2. Assign fixed phases to each carrier │
|
||||
│ 3. Train encoder CNN to embed this spectrum into generated │
|
||||
│ images without visible artifacts │
|
||||
│ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ SynthID Encoder (Inference) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Input: Generated Image │
|
||||
│ ↓ │
|
||||
│ Add learned noise pattern that encodes carrier phases │
|
||||
│ ↓ │
|
||||
│ Output: Watermarked Image (imperceptible modification) │
|
||||
│ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ SynthID Decoder (Detection) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Input: Suspect Image │
|
||||
│ ↓ │
|
||||
│ Extract noise residual │
|
||||
│ ↓ │
|
||||
│ Compute FFT, check phase at carrier frequencies │
|
||||
│ ↓ │
|
||||
│ If phases match expected values → Watermarked │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
1. **Codebook is source-specific**: This codebook only works for Gemini-generated images
|
||||
2. **Image modifications may break detection**: Heavy JPEG compression, cropping, or resizing may degrade the watermark
|
||||
3. **Binary watermark bits unknown**: We discovered the carrier frequencies but not the actual message encoded
|
||||
|
||||
## V3 Spectral Bypass — Building on These Findings
|
||||
|
||||
The carrier frequencies and phase consistency discovered here became the foundation for the **V3 Spectral Bypass** (`synthid_bypass.py`). Using a `SpectralCodebook` extracted from 50 reference images (25 black + 25 white), V3 can surgically subtract the watermark in the frequency domain:
|
||||
|
||||
- **40+ dB PSNR** — visually indistinguishable from original
|
||||
- **1-7% detection confidence reduction** per pass
|
||||
- **Selective notch filter** — targets only confirmed watermark bins (P97+ magnitude, ≥95% phase consistency)
|
||||
|
||||
See the main [README](README.md) for full V3 documentation and results.
|
||||
|
||||
## Files Generated
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `artifacts/codebook/synthid_codebook.pkl` | Detection codebook with numpy arrays |
|
||||
| `artifacts/codebook/synthid_codebook_meta.json` | Human-readable metadata |
|
||||
| `artifacts/spectral_codebook.npz` | V3 spectral fingerprint (119 MB) |
|
||||
| `artifacts/visualizations/` | FFT, phase, carrier visualizations |
|
||||
|
||||
## Usage
|
||||
|
||||
### To detect SynthID watermark:
|
||||
|
||||
```bash
|
||||
python src/extraction/robust_extractor.py detect image.png \
|
||||
--codebook artifacts/codebook/robust_codebook.pkl
|
||||
```
|
||||
|
||||
### To run V3 spectral bypass:
|
||||
|
||||
```python
|
||||
from synthid_bypass import SynthIDBypass, SpectralCodebook
|
||||
|
||||
codebook = SpectralCodebook()
|
||||
codebook.load('artifacts/spectral_codebook.npz')
|
||||
|
||||
bypass = SynthIDBypass()
|
||||
result = bypass.bypass_v3(image_rgb, codebook, strength='aggressive')
|
||||
print(f"PSNR: {result.psnr:.1f} dB")
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
SynthID uses a sophisticated spread-spectrum watermarking technique that:
|
||||
- Embeds information in the **phase domain** of the Fourier spectrum
|
||||
- Uses **specific carrier frequencies** (14, 98, 126, 128, 210, 238 Hz and their conjugates)
|
||||
- Creates a **consistent noise signature** detectable via correlation analysis
|
||||
- Is **imperceptible** to human observers but **robust** enough to survive common image operations
|
||||
- Uses a **fixed model-level key** (identical phase template across all images)
|
||||
|
||||
These findings enabled both detection (90% accuracy) and spectral bypass (40+ dB PSNR) without access to Google's proprietary encoder/decoder.
|
||||
@@ -70,14 +70,22 @@ class RobustSynthIDExtractor:
|
||||
self.n_carriers = n_carriers
|
||||
self.codebook = None
|
||||
|
||||
# Known SynthID carrier frequencies (from previous analysis)
|
||||
# SynthID carriers from 288 Gemini ref images (48,88 grid at 512px)
|
||||
self.known_carriers = [
|
||||
(14, 14), (-14, -14),
|
||||
(126, 14), (-126, -14),
|
||||
(98, -14), (-98, 14),
|
||||
(128, 128), (-128, -128),
|
||||
(210, -14), (-210, 14),
|
||||
(238, 14), (-238, -14),
|
||||
(48, 0), (-48, 0),
|
||||
(96, 0), (-96, 0),
|
||||
(192, 0), (-192, 0),
|
||||
(210, 0), (-210, 0),
|
||||
(238, 0), (-238, 0),
|
||||
(0, 88), (0, -88),
|
||||
(0, 176), (0, -176),
|
||||
(0, 192), (0, -192),
|
||||
(48, 88), (-48, -88),
|
||||
(48, -88), (-48, 88),
|
||||
(96, 88), (-96, -88),
|
||||
(96, -88), (-96, 88),
|
||||
(96, 176), (-96, -176),
|
||||
(96, -176), (-96, 176),
|
||||
]
|
||||
|
||||
if codebook_path and os.path.exists(codebook_path):
|
||||
|
||||
+662
-451
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user