ZeST: Grayout Subject
The ZeST Grayout Node Doesn't Transfer Material — and That's the Point
- target_image
- subject_mask
- IMAGE
The name oversells it. "ZeST: Grayout Subject" is not where the material transfer happens - it's the one piece of the ZeST pipeline that isn't a standard ComfyUI node, packaged so you can build the rest yourself. ZeST (Zero-Shot Material Transfer from a Single Image, arXiv 2404.06425) takes a photo of, say, a pumpkin and a single exemplar like a gold bowl, and repaints the pumpkin in gold with the lighting from the original photo intact. The research trick that makes that work: before the diffusion model redraws the subject, you destroy its material appearance - the color, the texture, everything that says "this is orange waxy pumpkin" - while keeping only its luminance, the light hitting it. Then the inpaint step re-emits the subject in the target material under that baked-in lighting. That grayout is exactly what this node does.
It's a tiny node. No model runs inside it, no weights to download, no API key. The source is about forty lines of Pillow: it takes the subject region from your mask, converts it to luminosity (grayscale) and back to RGB, applies a brightness scale, and composites it over the untouched background using ImageChops blend ops. The real requirements file is just torch, numpy, pillow - the ControlNet / IP-Adapter / SAM dependencies in the README belong to the workflow around it, not to this class.
Three inputs, and only one of them is interesting:
- target_image - your original photo.
- subject_mask - same mask you'll feed the inpaint node, so it must cover exactly the material you want replaced (background removal tools like rembg/Bria work well here).
- brighter - float, default 1.0, range 0–10. The README's rule of thumb: you want the subject in middle grey before inpainting. A bright, high-key material comes out too hot when the model re-lights it, so nudge
brighterbelow 1 to darken; a subject sitting in shadow benefits from a value above 1.
Output is a single IMAGE: your photo with the subject in grey, background untouched. That output feeds the positive conditioning of an inpaint node (in the bundled zest_workflow.json, it's InpaintModelConditioning), with the same mask and a KSampler - where IP-Adapter supplies the material style from the exemplar and ControlNet supplies depth, the way the original ZeST demo does it.
Install is trivial: search "ComfyUI-ZeroShot-MTrans" in ComfyUI Manager, or cd ComfyUI/custom_nodes && git clone https://github.com/kealiu/ComfyUI-ZeroShot-MTrans and restart. No model downloads for the node itself.
Where people get burned: they run the grayout, look at the grey blob, and think it's broken. It's not - it's the intermediate. The other trap is feeding the node a mask that includes background; then the background gets greyed too and the "untouched" guarantee quietly dies. And remember this is one half of a two-half trick: the grayout handles illumination, but if you skip IP-Adapter or drop the exemplar, the inpaint will happily redraw the subject in whatever material the prompt implies - you get re-lighting, not material transfer. The pack is a neat, honest little node from a small corner of the ecosystem; it just won't do anything standing alone.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| target_image | IMAGE | — | |
| subject_mask | MASK | — | |
| brighter | FLOAT | 1.000–10 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |