diff --git a/README.md b/README.md index b67f92c..2af9d17 100644 --- a/README.md +++ b/README.md @@ -60,19 +60,18 @@ uv pip install -e . After installation the `remove-ai-watermarks` command is available system-wide. -#### Invisible watermark removal (additional setup) +#### Invisible watermark removal -Invisible removal uses diffusion models and requires a **HuggingFace token** and a GPU for reasonable speed. +Invisible removal uses diffusion models and a GPU for reasonable speed. ```bash -# 1. Create a free token at https://huggingface.co/settings/tokens -# 2. Copy the example env file and paste your token +# On first run, the model (~2 GB) will be downloaded automatically. +# Device is auto-detected: CUDA (Linux/Windows) > MPS (macOS) > CPU. +# To force a device: --device cuda / --device mps / --device cpu + +# Optional: set a HuggingFace token for gated/private models cp .env.example .env # Edit .env and set HF_TOKEN=hf_your_token_here - -# 3. On first run, the model (~2 GB) will be downloaded automatically. -# Device is auto-detected: CUDA (Linux/Windows) > MPS (macOS) > CPU. -# To force a device: --device cuda / --device mps / --device cpu ``` #### Developer setup @@ -95,21 +94,28 @@ pytest ### CLI ```bash -# Remove visible Gemini watermark +# Remove all watermarks from a single image (visible + invisible + metadata) +remove-ai-watermarks all image.png -o clean.png + +# Process an entire directory +remove-ai-watermarks batch ./images/ --mode all +``` + +#### Individual commands + +```bash +# Visible watermark only (Gemini sparkle) — fast, offline remove-ai-watermarks visible image.png -o clean.png -# Remove invisible watermarks (SynthID etc.) with optimal quality retention +# Invisible watermark only (SynthID etc.) — requires GPU remove-ai-watermarks invisible image.png -o clean.png --humanize 4.0 -# Strip AI metadata +# Check / strip AI metadata only remove-ai-watermarks metadata image.png --check remove-ai-watermarks metadata image.png --remove -# Batch processing +# Batch with a specific mode remove-ai-watermarks batch ./images/ --mode visible - -# Full pipeline: visible + invisible + metadata -remove-ai-watermarks all image.png -o clean.png ``` ### Python API diff --git a/pyproject.toml b/pyproject.toml index ddb72b9..aef6e15 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "remove-ai-watermarks" -version = "0.2.1" +version = "0.2.2" description = "Unified tool for removing visible and invisible AI watermarks from images" readme = "README.md" requires-python = ">=3.10" diff --git a/src/remove_ai_watermarks/__init__.py b/src/remove_ai_watermarks/__init__.py index e2c03ed..7d5b221 100644 --- a/src/remove_ai_watermarks/__init__.py +++ b/src/remove_ai_watermarks/__init__.py @@ -1,3 +1,3 @@ """Remove-AI-Watermarks: Unified tool for removing visible and invisible AI watermarks.""" -__version__ = "0.2.1" +__version__ = "0.2.2" diff --git a/src/remove_ai_watermarks/cli.py b/src/remove_ai_watermarks/cli.py index 063d8c5..c6f7d28 100644 --- a/src/remove_ai_watermarks/cli.py +++ b/src/remove_ai_watermarks/cli.py @@ -321,8 +321,8 @@ def cmd_metadata( @click.option( "--inpaint-method", type=click.Choice(["ns", "telea", "gaussian"]), default="ns", help="Inpainting method." ) -@click.option("--strength", type=float, default=0.04, help="Invisible watermark denoising strength (0.0–1.0).") -@click.option("--steps", type=int, default=50, help="Number of denoising steps for invisible removal.") +@click.option("--strength", type=float, default=0.02, help="Invisible watermark denoising strength (0.0–1.0).") +@click.option("--steps", type=int, default=100, help="Number of denoising steps for invisible removal.") @click.option( "--pipeline", type=click.Choice(["default", "ctrlregen"]), diff --git a/tests/test_cli.py b/tests/test_cli.py index 122c8ae..542ca29 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -79,7 +79,7 @@ class TestMainGroup: def test_version(self, runner): result = runner.invoke(main, ["--version"]) assert result.exit_code == 0 - assert "0.2.1" in result.output + assert "0.2.2" in result.output def test_no_command_shows_banner(self, runner): result = runner.invoke(main, []) diff --git a/uv.lock b/uv.lock index ae7d314..6484133 100644 --- a/uv.lock +++ b/uv.lock @@ -1993,7 +1993,7 @@ wheels = [ [[package]] name = "remove-ai-watermarks" -version = "0.2.1" +version = "0.2.2" source = { editable = "." } dependencies = [ { name = "accelerate" },