Open-source project
zuruoke/watermark-removal avatar
zuruoke/watermark-removal

watermark-removal: TensorFlow 1.15 inpainting with a per-watermark checkpoint

a machine learning image inpainting task that instinctively removes watermarks from image indistinguishable from the ground truth image

5,165 stars598 forksPythonLicense varies

At a glance

What is it?
zuruoke/watermark-removal is a Python inference front end for a TensorFlow 1.15 inpainting model, driven by a downloaded checkpoint and a watermark_type flag. It is a narrow tool with a narrow dependency window, and the README says as much.
Who is it for?
Adopt this only if you can pin TensorFlow 1.15 and can obtain the Google Drive checkpoint, and only for non-commercial work under the CC BY-NC badge the README displays. Do not adopt it if you need a pip-installable package, a maintained runtime, or a licence that permits commercial use.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 33 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem is a fixed watermark, not watermarks in general

Stock photo sites stamp a visible mark across preview images. The mark sits on top of real pixels, so removing it is not a matter of cropping or masking a border region. The pixels underneath are gone and have to be guessed. That is image inpainting, and this repository frames itself as exactly that: a machine learning image inpainting task. The README claims the result is indistinguishable from the ground truth version of the image. Treat that as the author's stated goal rather than a measured result, because the repository does not publish a metric, a test set or a comparison table.

The intended user is someone with a small, known set of images and a known watermark pattern. The command line takes a single input image and a single output path, plus a watermark_type argument. There is no batch flag in the material. If you have ten thousand images, you are writing the loop yourself. If you are trying to remove an arbitrary watermark you have never seen, nothing in the README suggests the tool adapts to it.

Two papers, one checkpoint, and a watermark_type switch

The architecture is not described in the README beyond its lineage. The author credits Contextual Attention (CVPR 2018) and Gated Convolution (ICCV 2019 Oral), both by the same group, and links a Medium article series by Chu-Tak Li as background reading. Those two papers are the reference points for how the generator attends to distant pixels and how it masks invalid regions during convolution.

What is visible from the repository layout is the data flow. A checkpoint directory holds trained weights. The entry point is main.py, which accepts an image path, an output path, a checkpoint directory and a watermark type. The neuralgym package is installed as a dependency, which is the same toolkit published alongside the Contextual Attention work. That suggests the model definition and the graph construction follow the neuralgym conventions rather than being self-contained. The practical consequence: the checkpoint and the code are coupled. You cannot swap in a checkpoint trained by a different codebase and expect the variable names to line up.

The watermark_type argument is the interesting design choice. Rather than one model that generalises across watermarks, the interface implies separate checkpoints per watermark family, with istock given as the example value. That is a reasonable engineering decision for a small project, and it also means coverage is limited to whatever types the author trained and shipped. The README does not enumerate them.

Running it: Docker is the documented path, Colab is marked broken

The README offers two routes and explicitly labels one of them broken. The Colab section carries the heading Google colab (broken), which is about as direct as documentation gets.

The Docker route is four steps. Clone the repository, then build from the root:

docker build -t watermark-removal .

Download the model directory from the linked Google Drive folder, then run the container with three volume mounts, one each for the model, the input image and the output location:

docker run --rm -v '<path_to_model_dir>:/repo/model' -v '<path_to_input_dir>:/input' -v '<path_to_output_dir>:/output' watermark-removal --checkpoint_dir /repo/model --image '/input/<input_image_file>' --output '/output/<output_image_file>' --watermark_type istock

The local Python route is the same command without the container wrapper:

python main.py --image path-to-input-image --output path-to-output-image --checkpoint_dir model/ --watermark_type istock

The Colab instructions add two dependencies beyond the repository itself. You install TensorFlow 1.15.0 with pip, and you install neuralgym from its GitHub URL rather than from PyPI:

pip install git+https://github.com/JiahuiYu/neuralgym

One detail in the README is worth repeating because it will cost you an afternoon otherwise: after downloading the checkpoint from Google Drive, the file named checkpoint may arrive as checkpoint.txt, and the README instructs you to rename it back. That is a Google Drive artefact, not a project bug, but it is the kind of thing that produces an unhelpful error at load time.

TensorFlow 1.15 is the constraint that shapes everything else

The version badge in the README reads tensorflow v1.15.0. That single number rules out a large fraction of current Python environments. TensorFlow 1.x is end of life, and the pip resolver will not place it alongside a modern stack. The Colab instructions acknowledge the friction directly: Colab ships TensorFlow 2.x, so the notebook tells you to downgrade and restart the runtime, with a parenthetical noting that newer Colab builds may not require the restart.

There is no setup.py, no pyproject.toml and no requirements file mentioned in the supplied material, so the dependency set is whatever the Dockerfile contains plus neuralgym. If you are not using the Docker image, you are reconstructing the environment from the README prose. That is a real maintenance cost, and it is the reason the Docker path is worth preferring even if you have a working local Python.

The Google Drive checkpoint is a second structural constraint. Model weights distributed through a Drive link rather than a release asset or a package index mean no version pinning, no checksum, and no guarantee the link stays live. The repository does have a tagged release, v1.0.0, dated 2026-06-05, but the material does not indicate whether that release bundles weights. Assume it does not until you check.

Licence: the README shows CC BY-NC, and that decides your use case

The licence badge in the README reads CC BY-NC. The repository metadata supplied here lists the licence as unknown, so the badge is the only signal available, and a badge is not a licence file. There is no LICENSE file referenced in the material.

CC BY-NC is a Creative Commons licence with a non-commercial restriction. If that is the actual terms, commercial use is out, and the NonCommercial clause is the one that matters for anyone evaluating this for paid work. Creative Commons themselves note that CC licences are not designed for software and that the NonCommercial term is ambiguous when applied to code. I am not giving legal advice, and you should not treat a shield badge as the operative text. What you can say concretely is that the project presents itself as non-commercial, and that a company adopting it would need to resolve that before shipping anything.

There is a second layer worth separating. The two cited papers, Contextual Attention and Gated Convolution, are research publications with their own terms, and the neuralgym dependency is installed from a separate repository with its own licence. The checkpoint weights are a third artefact with no stated terms at all. Three inputs, three sets of conditions, and the repository only speaks to one of them.

Where this is the wrong tool, and what to use instead

This is the wrong tool when the watermark is not one the shipped checkpoints were trained on. The interface is a type selector, not a detector. Pass a type the model does not know and you get whatever the network produces, with no failure signal in the documented interface. It is also the wrong tool when you need throughput. Single image in, single image out, per process invocation, with no documented batch mode.

A real alternative in a different style is LaMa, the large-mask inpainting model released by Samsung AI Center in 2021. The difference in approach is the point. LaMa uses fast Fourier convolutions to give the network a global receptive field at training time, and it is trained on a large, diverse mask distribution so that a single set of weights handles many mask shapes. This project takes the opposite route: gated and contextual convolutions from the 2018 and 2019 papers, plus separate checkpoints per watermark type. LaMa trades a heavier one-time download for generality across mask shapes; this repository trades generality for a smaller, watermark-specific model.

If your marks are text overlays on documents rather than stock photo stamps, neither is the right starting point. Text removal is a different problem with different tooling, and the README does not claim to handle it.

What the repository does not tell you

There is no stated accuracy figure, no evaluation set, no ablation, and no example output with a corresponding input. The README shows a grid of images but does not label them as before and after pairs, so you cannot tell from the material which images are inputs and which are model outputs. The claim that results are indistinguishable from ground truth is an assertion, not a measurement.

The README also carries a broken badge: the downloads shield points at pepy.tech/project/prompttools, a different project entirely, while the image alt text says Total Downloads. That is cosmetic, but it is a small signal about how carefully the badges were assembled, and it means you should not read the badge row as verified information about this repository.

Finally, the README says the Colab path is broken and does not say why. It could be the TensorFlow downgrade, the neuralgym install, the checkpoint rename, or something else. Until you run it, you do not know which of those the author already tried to fix.

Editorial conclusion

Adopt this only if you can pin TensorFlow 1.15 and can obtain the Google Drive checkpoint, and only for non-commercial work under the CC BY-NC badge the README displays. Do not adopt it if you need a pip-installable package, a maintained runtime, or a licence that permits commercial use. Before anything else, verify two things: that the checkpoint folder contains a file literally named checkpoint rather than checkpoint.txt, and that the watermark_type value you pass matches a model the repository actually ships.

Official sources

  1. Issues
  2. README
  3. Releases
  4. zuruoke/watermark-removal on GitHub
Community notes

Community notes