0xROOTPLS/DeSynth

DeSynth removes the SynthID invisible watermark from both OpenAI/Google generated images. (SynthID Bypass)

Python

45

6 commits

updated Jun 5, 2026

See the code

See what people are saying (1)

SourceMessageScoreDate

Spymarks, Not Watermarks

Much prior art here, works against both Google and OpenAI's SynthID: https://github.com/0xROOTPLS/DeSynth

0

Sep 22, 2026

README

Desynth

A tool & pipeline for removing OpenAI & Google's SynthID watermark from images.
This project is intended solely for research, education, and authorized evaluation.

Results

Edge Mode: reference vs desynth (edge mode) Gaussian Mode (Default): reference vs desynth (gaussian mode)

Metrics

All scores are input image vs output via the included compare.py.

Against other research (Gemini/Google, 2752×1536)

metricour methodcompetitor
PSNR28.75 dB20.21 dB
SSIM0.9460.624
SSIM (low-frequency)0.9440.812
SSIM (high-frequency)0.9870.641
MAE (lower is better)5.3312.18
Output resolution2752×15361501×835
SynthID verdictnot foundnot found

Our own test image (GPT Image 2.0/OpenAI, 1460×1078)

metricgaussian (default)edge mode
PSNR32.47 dB31.47 dB
SSIM0.9560.948
SSIM (low-frequency)0.9590.955
SSIM (high-frequency)0.9910.984
MAE3.824.08
SynthID verdictnot foundnot found
  • Edge mode trades a small amount of measurable detail for better perceptual shape continuity at contours.

How it works

flowchart TD
    A["Original.png"]
    B["Qwen-Image GGUF Q4<br>+ Lightning 4-step LoRA"]
    B_note["2 Lightning steps\n(strength 0.25)"]
    C["Frequency-domain restore<br>low_clean + high_orig"]
    C_note["Gaussian split, sigma=1.95<br>low band from clean<br>high band from Original"]
    D["[output]\nNAME_desynth_r1.95.png"]

    A --> B
    B -- "clean: no SynthID, blurry-ish" --> C
    C --> D
    B -.- B_note
    C -.- C_note

    classDef note fill:#f6f8fa,stroke:#d0d7de,color:#57606a;
    class B_note,C_note note;

Usage

Download the two model files into the repo root:

filesizesource
qwen-image-2512-Q4_K_M.gguf~13 GBFrederic75/Qwen-Image-2512-GGUF
Qwen-Image-2512-Lightning-4steps-V1.0-fp32.safetensors~1.6 GBlightx2v/Qwen-Image-2512-Lightning

Run

python desynth.py                          # processes original.png
python desynth.py path\to\image.png        # processes any input

Output: out/<name>_desynth_s8_d0.250_p1_r1.95.png. Random seed per run by default. First run downloads ~250 MB of VAE + configs from Hugging Face and caches them.

Flags

flagdefaultwhen to use
--seed Nrandomreproducible runs
--denoise X [X X]0.25sweep denoise
--steps N8per-pass step count
--passes N1iterate img2img
--restore-sigma X1.95tune detail restore
--restore-mode Mgaussianedge for shape-coherent contours
--unsharp X0.0post-restore sharpen; 0.2 is the perceptual sweet spot
--no-restoreoffskip the frequency restore step
--keep-intermediateoffsave the pre-restore clean output
--transformer PATHQ4_K_Mtry a different GGUF quant

Quality check

python compare.py Original.png out\<output>.png

Prints PSNR, SSIM (full + low/high band), MAE, MSE, and per-channel histogram correlation.

Files

filerole
desynth.pymain pipeline: img2img + restore in one call
compare.pysimilarity metrics between two images
embeds_cache.ptcached prompt embeddings (~430 KB)
qwen-image-2512-Q4_K_M.ggufQwen-Image transformer, GGUF Q4 quant (~13 GB)
Qwen-Image-2512-Lightning-4steps-V1.0-fp32.safetensors4-step Lightning distillation LoRA (~1.6 GB)

Hardware Requirements

Tested on Windows 10, RTX 5060 Ti 8 GB, 32 GB DDR4 RAM. Sequential CPU offload is required with < 12GB VRAM

Known limitations

  • Lightning's 4-step distillation is the source of most of the residual drift.
    (Dropping it for proper 20+ step sampling would likely tighten metrics further at the cost of 5x longer runs.)

Credits

Baseline workflow and watermark hypothesis from 00quebec/Synthid-Bypass.
This pipeline reimplements the core idea in plain Python without ComfyUI, ControlNet, or the face-detail path, and replaces the heavier redraw with a two-step minimum denoise + frequency-domain restore.

Contributors

0xROOTPLS

6 commits

0xROOTPLS/DeSynth

DeSynth removes the SynthID invisible watermark from both OpenAI/Google generated images. (SynthID Bypass)

Python

45

6 commits

updated Jun 5, 2026

See the code

See what people are saying (1)

SourceMessageScoreDate

Spymarks, Not Watermarks

Much prior art here, works against both Google and OpenAI's SynthID: https://github.com/0xROOTPLS/DeSynth

0

Sep 22, 2026

README

Desynth

A tool & pipeline for removing OpenAI & Google's SynthID watermark from images.
This project is intended solely for research, education, and authorized evaluation.

Results

Edge Mode: reference vs desynth (edge mode) Gaussian Mode (Default): reference vs desynth (gaussian mode)

Metrics

All scores are input image vs output via the included compare.py.

Against other research (Gemini/Google, 2752×1536)

metricour methodcompetitor
PSNR28.75 dB20.21 dB
SSIM0.9460.624
SSIM (low-frequency)0.9440.812
SSIM (high-frequency)0.9870.641
MAE (lower is better)5.3312.18
Output resolution2752×15361501×835
SynthID verdictnot foundnot found

Our own test image (GPT Image 2.0/OpenAI, 1460×1078)

metricgaussian (default)edge mode
PSNR32.47 dB31.47 dB
SSIM0.9560.948
SSIM (low-frequency)0.9590.955
SSIM (high-frequency)0.9910.984
MAE3.824.08
SynthID verdictnot foundnot found
  • Edge mode trades a small amount of measurable detail for better perceptual shape continuity at contours.

How it works

flowchart TD
    A["Original.png"]
    B["Qwen-Image GGUF Q4<br>+ Lightning 4-step LoRA"]
    B_note["2 Lightning steps\n(strength 0.25)"]
    C["Frequency-domain restore<br>low_clean + high_orig"]
    C_note["Gaussian split, sigma=1.95<br>low band from clean<br>high band from Original"]
    D["[output]\nNAME_desynth_r1.95.png"]

    A --> B
    B -- "clean: no SynthID, blurry-ish" --> C
    C --> D
    B -.- B_note
    C -.- C_note

    classDef note fill:#f6f8fa,stroke:#d0d7de,color:#57606a;
    class B_note,C_note note;

Usage

Download the two model files into the repo root:

filesizesource
qwen-image-2512-Q4_K_M.gguf~13 GBFrederic75/Qwen-Image-2512-GGUF
Qwen-Image-2512-Lightning-4steps-V1.0-fp32.safetensors~1.6 GBlightx2v/Qwen-Image-2512-Lightning

Run

python desynth.py                          # processes original.png
python desynth.py path\to\image.png        # processes any input

Output: out/<name>_desynth_s8_d0.250_p1_r1.95.png. Random seed per run by default. First run downloads ~250 MB of VAE + configs from Hugging Face and caches them.

Flags

flagdefaultwhen to use
--seed Nrandomreproducible runs
--denoise X [X X]0.25sweep denoise
--steps N8per-pass step count
--passes N1iterate img2img
--restore-sigma X1.95tune detail restore
--restore-mode Mgaussianedge for shape-coherent contours
--unsharp X0.0post-restore sharpen; 0.2 is the perceptual sweet spot
--no-restoreoffskip the frequency restore step
--keep-intermediateoffsave the pre-restore clean output
--transformer PATHQ4_K_Mtry a different GGUF quant

Quality check

python compare.py Original.png out\<output>.png

Prints PSNR, SSIM (full + low/high band), MAE, MSE, and per-channel histogram correlation.

Files

filerole
desynth.pymain pipeline: img2img + restore in one call
compare.pysimilarity metrics between two images
embeds_cache.ptcached prompt embeddings (~430 KB)
qwen-image-2512-Q4_K_M.ggufQwen-Image transformer, GGUF Q4 quant (~13 GB)
Qwen-Image-2512-Lightning-4steps-V1.0-fp32.safetensors4-step Lightning distillation LoRA (~1.6 GB)

Hardware Requirements

Tested on Windows 10, RTX 5060 Ti 8 GB, 32 GB DDR4 RAM. Sequential CPU offload is required with < 12GB VRAM

Known limitations

  • Lightning's 4-step distillation is the source of most of the residual drift.
    (Dropping it for proper 20+ step sampling would likely tighten metrics further at the cost of 5x longer runs.)

Credits

Baseline workflow and watermark hypothesis from 00quebec/Synthid-Bypass.
This pipeline reimplements the core idea in plain Python without ComfyUI, ControlNet, or the face-detail path, and replaces the heavier redraw with a two-step minimum denoise + frequency-domain restore.

Contributors

0xROOTPLS

6 commits

Languages

Python

100.0%