Nodes/Blind_watermark_Comfyui/πŸ” Extract Image Watermark
ComfyUI Node

πŸ” Extract Image Watermark

Pull the hidden logo back out of a watermarked image

By TianDongLΒ·Created 11 months agoΒ·Updated 11 months agoΒ· 22
πŸ” Extract Image Watermark
  • image
  • extracted_watermark
β—„wm_width128β–Ί
β—„wm_height128β–Ί
β—„password_img1β–Ί
β—„password_wm1β–Ί
β—„processesautoβ–Ί

This is the verification half of the pack's image-watermark story. You embedded a logo into a carrier with WatermarkEmbedImage; this node runs the same DWT-DCT-SVD math in reverse, digs the logo back out of the pixels, and hands you an image you can actually look at. If you found a suspicious copy of your work floating around, this is how you check whether it's carrying your signature.

It's a dead-simple node to operate, which makes the failure modes hurt more. Feed it the image, tell it how big the watermark was, give it the same passwords, and you get an IMAGE back. The catch is that the passwords and dimensions have to match the embed exactly - this isn't a "decode anything" tool.

The inputs that matter

  • image - the (possibly re-encoded, possibly cropped) image you suspect is watermarked.
  • wm_width / wm_height - the watermark's dimensions at embed time. These must match the logo you hid, not the carrier. The info string from the embed node records them - that's why it exists.
  • password_img / password_wm - the exact pair used when embedding. Wrong key, wrong output.
  • processes - CPU pool sizing; "auto" is right for everyone.

The single output is extracted_watermark (IMAGE). Wire it into a PreviewImage node and compare it to your original logo. It won't be a pixel-perfect copy - the extraction is a reconstruction, so expect something softer and lower-contrast than the original. That's normal.

How it works

Under the hood the node takes the carrier through the reverse transform: it re-derives the per-block singular values, reads the quantized bit from each, then un-shuffles with password_wm to reassemble the 1-bit pattern, reshapes it to wm_width Γ— wm_height, and writes it out. The ComfyUI node itself is a thin wrapper - it runs the library's extract() with mode='img', writing to a temp file and reading it back as a tensor.

One thing worth knowing: the node returns a black image instead of erroring out if something goes wrong. So an all-black output isn't a crash - it's the node politely telling you the passwords, dimensions, or both are wrong, or that the image genuinely doesn't carry that watermark. Check the console; the node prints a real error message there.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/TianDongL/Blind_watermark_Comfyui.git
pip install -r requirements.txt
# restart ComfyUI

Or install "Blind Watermark" via ComfyUI Manager. No models, no GPU - pure CPU, and the requirements are just numpy, opencv-python, PyWavelets, qrcode and pyzbar.

Troubleshooting

  • Black output - wrong passwords, wrong wm_width/wm_height, or the image was edited past the watermark's resilience (aggressive cropping, heavy filters, multiple re-saves). Start by confirming the image was never re-saved as JPEG after embedding; each save costs bits.
  • Static / noise instead of a logo - the watermark image was low-contrast or color-heavy at embed time, so the 1-bit conversion already destroyed it. Not fixable at extract time; re-embed with a high-contrast B&W logo.
  • "Image too small" style failures - the node enforces a minimum carrier size based on watermark dimensions (max(int(sqrt(wm_width*wm_height)*4), 128)). A 2048Γ—2048 watermark on a small carrier was never going to work.
CategoryBlindWatermark/Extract

Inputs (6)

NameTypeDefaultDescription
imageIMAGEβ€”
wm_widthINT1281–2048β€”
wm_heightINT1281–2048β€”
password_imgINT11–999999β€”
password_wmINT11–999999β€”
processesCOMBOauto7 options: auto, 1, 2, 4, 8, multiprocessing, +1

Outputs (1)

NameTypeDescription
extracted_watermarkIMAGEβ€”