Nodes/comfyui-dit-watermark/GROW Watermark Detect
ComfyUI Node

GROW Watermark Detect

Finds the watermark without rerunning the model — one VAE encode is all it takes

By zhangp365·Created 2 months ago·Updated 2 months ago· 1
GROW Watermark Detect
  • image
  • vae
  • config
  • decoded_message
  • ecc_valid
  • corrected_symbols
  • min_vote_margin
  • raw_codeword_hex
◄max_watermark_bytes64►
◄robust_modenone►

The usual way to check an image for a watermark is to reverse the generation process - diffusion inversion, or re-running the model with the payload as conditioning. That's slow and fragile. GROW Watermark Detect does neither: it VAE-encodes the image once and reads the watermark straight out of the latent's frequency signs. No diffusion model loaded, no inversion, no sampling. For batch verification of thousands of images, that speed difference is the whole point.

It's the detection half of the comfyui-dit-watermark pack. The clever part is that it's blind: it doesn't need to know the watermark content in advance. Each payload is stored as a self-describing frame - 1 byte of UTF-8 length, the payload, and 4 Reed–Solomon parity bytes (N+5 total) - so the detector tries candidate lengths up to your limit and accepts the first frame whose length, parity, and UTF-8 all validate. The RS code corrects up to two corrupted bytes, which is what keeps the scheme alive through JPEG q50, AVIF, HEIF, JXL, and crops.

The inputs that matter

  • image / vae - the watermarked image and the same VAE used to embed it. If your detector uses a different VAE, you're comparing frequency domains from different spaces and it will usually fail.
  • config - the GROW_CONFIG output from GROW Watermark Config. This is non-negotiable: the detector rebuilds the exact keyed frequency layout from it, and any mismatch means ecc_valid=False.
  • max_watermark_bytes (default 64) - how far the blind length search goes. Larger is slower; 64 covers the pack's own watermarks plus the legacy 32-byte frame with room to spare.
  • robust_mode - none is fastest and correct for clean images. rotation, crop_scale, or rotation_crop_scale brute-force a bounded set of affine candidates (identity first, then angles/scales) and keep whichever decodes. Crops recover cleanly in testing; rotation still leaves residual errors, so don't promise it.

What comes out

Five outputs, and honestly you mostly care about two:

  • decoded_message - the payload text, if any.
  • ecc_valid - the authoritative check. True means a frame passed RS validation and you have a genuine GROW watermark. A high min_vote_margin with ecc_valid=False means someone misconfigured the layout, not that the watermark is fine.
  • corrected_symbols - how many corrupted bytes RS had to fix (0 is cleanest).
  • min_vote_margin - the weakest bit's majority margin, 0–1; useful for judging how much headroom you have left.
  • raw_codeword_hex - the raw decoded frame in hex, for debugging your own experiments.

The node also prints a summary line to the UI with all of it plus which alignment candidate won.

Installing

Same pack as the other three nodes:

cd ComfyUI/custom_nodes
git clone https://github.com/zhangp365/comfyui-dit-watermark

Restart ComfyUI (or use Manager and search comfyui-dit-watermark). No models to download and no extra Python packages - the RS codec is bundled, and detection only needs PyTorch.

Where people get burned

  • Wrong VAE or wrong config. Both must match the embed side exactly. This is the #1 cause of ecc_valid=False on an image you know is watermarked.
  • ecc_valid=False doesn't mean "no watermark". It means the frame didn't validate - the image may be damaged beyond two symbols, un-watermarked, or from a different config. Check raw_codeword_hex and the margin before blaming the image.
  • Over-attacked images. The README's own numbers are honest: Flux2 Klein images recovered 43 of 48 attack samples (89.58%), Qwen 12 of 16 (75%). JPEG below ~q50 and aggressive rotation are where it falls over. Build error-correction headroom in at embed time if you know images will be roughed up.
CategoryGROW/watermark

Inputs (5)

NameTypeDefaultDescription
imageIMAGE—
vaeVAE—
configGROW_CONFIG—
max_watermark_bytesINT641–250Blind detection checks candidate UTF-8 byte lengths up to this value; a larger limit is slower.
robust_modeCOMBOnone4 options: none, rotation, crop_scale, rotation_crop_scale

Outputs (5)

NameTypeDescription
decoded_messageSTRING—
ecc_validBOOLEAN—
corrected_symbolsINT—
min_vote_marginFLOAT—
raw_codeword_hexSTRING—