Remove Gemini AI watermarks from images using GeminiWatermarkTool (GWT). Use this skill whenever the user mentions: Gemini watermark, 浮水印, AI image cleanup, removing logos from Gemini-generated images, Google ImageFX cleanup, batch processing AI-generated photos, or anything about a semi-transparent logo in the bottom-right corner of an image — even if they don't say "GeminiWatermarkTool" explicitly. Also trigger for follow-up requests like "the corner still looks dirty" or "there's still res...
Scanned 5/27/2026
Install via CLI
openskills install allenk/gwt-integrations---
name: gwt
description: >
Remove Gemini AI watermarks from images using GeminiWatermarkTool (GWT).
Use this skill whenever the user mentions: Gemini watermark, 浮水印, AI image
cleanup, removing logos from Gemini-generated images, Google ImageFX cleanup,
batch processing AI-generated photos, or anything about a semi-transparent logo
in the bottom-right corner of an image — even if they don't say
"GeminiWatermarkTool" explicitly. Also trigger for follow-up requests like
"the corner still looks dirty" or "there's still residual artifacts" after a
previous removal attempt.
---
# GeminiWatermarkTool Skill for Claude-Like Agents
## Overview
GeminiWatermarkTool (GWT) removes visible Gemini AI watermarks from images using
mathematically accurate reverse alpha blending, with optional AI denoising
(FDnCNN + NCNN Vulkan GPU) for residual cleanup.
Source: https://github.com/allenk/GeminiWatermarkTool
---
## Binary Location
Search in this order:
1. Environment variable: `GWT_BINARY_PATH`
2. System PATH: `GeminiWatermarkTool` (or `.exe` on Windows)
3. Claude skill bin directory:
- Windows: `%USERPROFILE%\.claude\skills\gwt\bin\GeminiWatermarkTool.exe`
- Linux/macOS: `~/.claude/skills/gwt/bin/GeminiWatermarkTool`
4. Repo-local bin directory (validation mode / fallback):
- Windows: `.\bin\GeminiWatermarkTool.exe`
- Linux/macOS: `./bin/GeminiWatermarkTool`
If not found, run the installer:
```
python ~/.claude/skills/gwt/install.py
```
For local validation inside this repo only:
```
python ~/.claude/skills/gwt/install.py --dir ./bin
```
**Always pass `--no-banner`** when calling GWT — suppresses ASCII art that wastes tokens.
---
## Watermark Profile Selection (v0.3.1+)
GWT ships with two watermark profiles. **The default targets Gemini 3.5 and later, with automatic legacy fallback.**
| Profile | Targets | When tried |
|---------|---------|------------|
| Current (V2) | Gemini 3.5 and later outputs | first, by default |
| Legacy (V1) | Pre-Gemini-3.5 outputs | automatically retried if V2 skips |
This means `remove_watermark(input, output)` already handles mixed Gemini-3.5+
and pre-3.5 inputs without supervision — the CLI tries the current profile,
and on skip retries with the legacy profile before reporting the final outcome.
Two opt-out paths exist for the rare case where you need to pin a profile:
- `no_legacy=True` parameter — disable the automatic fallback (current only)
- `remove_watermark_legacy` / `remove_watermark_batch_legacy` — pin legacy only
**Always start with `remove_watermark` / `remove_watermark_batch`.** The
auto-fallback handles the common case. The dedicated `*_legacy` tools are
mostly there for callers that have side knowledge an image is pre-3.5 and
want to skip the V2 attempt entirely.
### What to do when detection fails ("skipped")
A `skipped=True` result from the default tool means **both profiles tried
their best and neither matched**. The two indistinguishable causes are:
1. The image was generated by Gemini, but its watermark has been destroyed
by heavy editing/resizing/re-encoding.
2. The image was not generated by Gemini at all.
**Do NOT silently re-invoke `remove_watermark_legacy`** — the automatic
fallback has already attempted that. Instead, surface the result to the
user and ask whether to escalate:
> "I couldn't detect a Gemini watermark on this image (confidence X% on
> the current profile, Y% on legacy). Either it isn't a Gemini output, or
> the watermark has been damaged by post-processing. I can try forcing
> removal at a custom region if you can point me at one — otherwise there's
> nothing to do."
Escalation paths the agent can offer:
- `--fallback-region br:64,64,500,500 --snap` — multi-scale search in a
user-supplied area (good for resized / cropped images)
- Lower `--threshold` (e.g. 0.15) — relaxes the safety gate; risky on
non-Gemini files but legitimate when the user is certain
- Custom region in the GUI — most user-friendly for one-off cleanup
---
## Decision Logic
### Pipeline selection (automatic, based on flags)
| Flags | Internal behavior |
|-------|-------------------|
| No advanced flags | Standard 3-stage NCC detection → process or skip |
| `--fallback-region` only | Standard detection first → if not found, apply to fallback region |
| `--fallback-region --snap` | **Skip standard detection entirely** → snap search directly |
| `--force` | Skip detection, process unconditionally |
| `--legacy` | Pin V1 profile (pre-Gemini-3.5 outputs); skip the V2 attempt entirely |
| `--no-legacy` | Disable the auto V2 → V1 fallback (current profile only) |
| _no `--legacy` and no `--no-legacy`_ | V2 first; auto-retry on V1 if V2 skips (v0.3.1+ default) |
### Case A — Standard image (not resized after generation)
```bash
GeminiWatermarkTool --no-banner -i input.jpg -o clean.jpg
```
Detection on by default (threshold 25%). Non-watermarked images are skipped safely.
### Case B — Image was resized or recompressed
`--fallback-region --snap` together skips standard detection and goes straight to
multi-scale snap search:
```bash
GeminiWatermarkTool --no-banner \
-i input.jpg -o clean.jpg \
--fallback-region br:64,64,500,500 \
--snap --snap-max-size 320 --snap-threshold 0.60 \
--denoise ai --sigma 50 --strength 120
```
### Case C — Unknown image (try standard first, fallback on failure)
Use `--fallback-region` **without** `--snap`. Standard detection runs first;
fallback region only activates if standard detection fails:
```bash
GeminiWatermarkTool --no-banner \
-i input.jpg -o clean.jpg \
--fallback-region br:64,64,500,500 \
--denoise ai --sigma 50 --strength 120
```
---
## Full CLI Reference
### Core options
| Flag | Default | Description |
|------|---------|-------------|
| `-i, --input <path>` | — | Input file or directory |
| `-o, --output <path>` | — | Output file or directory |
| `-f, --force` | false | Skip detection, process unconditionally |
| `-t, --threshold <0.0-1.0>` | 0.25 | Detection confidence threshold |
| `--force-small` | — | Force small watermark size |
| `--force-large` | — | Force large watermark size |
| `--legacy` | — | Pin pre-Gemini-3.5 profile (V1); skips V2 attempt. |
| `--no-legacy` | — | Disable the automatic V2 → V1 fallback. |
| `-v, --verbose` | false | Detailed output |
| `-q, --quiet` | false | Suppress output except errors |
| `--no-banner` | — | Hide ASCII banner (always use in this skill) |
### Region options
| Flag | Description |
|------|-------------|
| `--region <spec>` | Explicit watermark region |
| `--fallback-region <spec>` | Search region when standard detection fails |
**Region spec formats:**
| Format | Meaning |
|--------|---------|
| `x,y,w,h` | Absolute pixel coordinates |
| `br:mx,my,w,h` | Bottom-right: margin_right, margin_bottom, width, height |
| `bl:mx,my,w,h` | Bottom-left relative |
| `tr:mx,my,w,h` | Top-right relative |
| `tl:mx,my,w,h` | Top-left / absolute |
| `br:auto` | Gemini default position for this image size |
### Snap engine
| Flag | Default | Description |
|------|---------|-------------|
| `--snap` | false | Multi-scale snap within region/fallback-region |
| `--snap-max-size <32-320>` | 160 | Maximum watermark size to search |
| `--snap-threshold <0.0-1.0>` | 0.60 | Minimum confidence to accept match |
### Denoise / inpaint
| Flag | Default | Description |
|------|---------|-------------|
| `--denoise <method>` | off | `ai` \| `ns` \| `telea` \| `soft` \| `off` |
| `--sigma <1-150>` | 50 | FDnCNN noise sigma (`ai` only) |
| `--strength <0-300>` | 120 (ai) / 85 (others) | Blend strength in percent |
| `--radius <1-25>` | 10 | Inpaint radius (`ns` / `telea` / `soft` only) |
---
## Watermark Size Auto-Detection
| Profile | Small logo | Large logo | Threshold |
|---------|-----------|-----------|-----------|
| V2 (default — Gemini 3.5+) | 36×36 | 96×96 | long side > 1024 → large |
| V1 (`--legacy`, pre-3.5) | 48×48 | 96×96 | long side > 1024 → large |
Override with `--force-small` or `--force-large`. Profile is selected by
`--legacy` (off = V2, on = V1).
---
## Parameter Tuning Guide
| Situation | Action |
|-----------|--------|
| Faint residual | `--denoise ai --sigma 50 --strength 120` |
| Visible edge artifacts | `--sigma 75 --strength 180` |
| Strong residual (heavily resized) | `--sigma 100 --strength 250` |
| Detection keeps skipping | Lower `--threshold 0.15` or add `--fallback-region` |
| Snap finds nothing | Widen region, increase `--snap-max-size 320` |
| Snap confidence too low | Lower `--snap-threshold 0.40` |
| Wrong size detected | `--force-small` or `--force-large` |
---
## Exit Codes (v0.3.1+)
| Code | Meaning |
|------|---------|
| 0 | File processed (or batch directory completed without errors) |
| 1 | Single-file invocation skipped — no watermark detected on any profile that the chosen flag combination tried |
| 2 | Real failure — bad arguments, missing input, IO/write error |
Batch directory mode keeps lenient semantics (exit 0 unless something
actually fails) since partial skips are expected when scanning a folder.
---
## Important Notes
1. **AI denoise GPU fallback**: Vulkan GPU used when available, falls back to CPU
automatically. If AI init fails entirely, GWT falls back to NS inpainting.
2. **SynthID cannot be removed**: Statistically embedded during generation,
inseparable from image content.
3. **Supported formats**: jpg, jpeg, png, webp, bmp
4. **Batch mode**: `-i dir/ -o dir/` processes all images; non-watermarked files
are skipped safely by default.
5. **Profile auto-fallback (v0.3.1+)**: by default the CLI tries the current
profile, then automatically retries with the legacy profile on skip.
Pin a single profile with `--legacy` (V1 only) or `--no-legacy` (V2 only)
if the auto-fallback isn't what you want.
No comments yet. Be the first to comment!