Mask: Decontaminate Colors
Kill the Green Fringe on Hair Before You Composite
- image
- mask
- image
Cut a subject out against a green screen, drop it on a beach, and the hair glows faintly green. Everyone assumes the mask is wrong. It isn't - the mask is fine. The pixels are wrong: every soft edge pixel is a mix of subject and old background, and a mix of hair and green screen is, physically, green hair. No alpha value can un-mix it.
Mask: Decontaminate Colors (JHPixelProDecontaminateColors) does the un-mixing. Same idea as Photoshop's "Decontaminate Colors" checkbox in Select and Mask, and it's the step people skip right before blaming their matte.
The maths, which is short
Soft edge pixels follow the compositing equation: I = α·F + (1−α)·B. You know I (the pixel) and α (your matte). You need F, the subject's true colour.
The node estimates both ends by normalised convolution from nearby solid pixels: subject colour F_blur from pixels with α ≥ 0.95, background B from pixels with α ≤ 0.05. Where α is large the equation is solved directly for F = (I − (1−α)·B) / α, which is what preserves fine hair strands. Where α is small that solve is numerically unstable - dividing by almost nothing - so it falls back to the nearby subject colour, and the two blend in between. If no solid pixels exist within radius, wider blurs fill in.
Pixels at α = 1 and α = 0 are untouched. This only ever writes the edge band.
What you set
image - the image the mask was made from. Not the new background; the old one.
mask - the subject mask with soft edges, 1 = subject. From Alpha Matte, Sub-Pixel Mask Refiner or Edge-Aware Mask Refiner.
radius (1–256, default 16) - how far to look for the subject's own colour. Raise it for wide wispy hair, keep it low for crisp product edges.
strength (0–1) - blend, 0 = unchanged.
One output: image, with edge colours taken from the subject instead of the background.
Use it like this
Decontaminate, then composite with the decontaminated image and the same mask. The mask still decides how much subject shows - this node never touches alpha. Judge the result on the final background, not the old one; on a green screen the fringe is invisible because it matches.
And it needs a soft matte to do anything. If every mask value is exactly 0 or 1, there are no edge pixels and nothing changes. That's a common "the node does nothing" report, and it's correct behaviour: go make a soft edge first.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/jetthuangai/ComfyUI-JH-PixelPro.git
cd ComfyUI-JH-PixelPro
pip install -r requirements.txt # the Python that runs ComfyUI
ComfyUI Manager: search ComfyUI-JH-PixelPro → Install → restart. Then Add Node → ComfyUI-JH-PixelPro → mask. Deps: kornia>=0.7, mediapipe>=0.10.33, opencv-python-headless>=4.8, scipy>=1.10; PyTorch from ComfyUI. No model downloads. About 0.9 GB VRAM at 4K, and the blurs run on a reduced copy so memory scales with pixel count only.
Where it goes wrong
- "It did nothing." Hard mask, or no soft edge within
radius. Check the mask's histogram first. - Green still visible on the hair.
radiustoo small for the spread of the fringe. Raise it - long hair needs a lot of search room. - The edge went grey / desaturated.
radiustoo large, so it's pulling subject colour from somewhere unrepresentative. Back it off. - Order. Refine the matte first (Mask Cleanup, then an edge refiner), then decontaminate. Doing it the other way means cleaning up pixels you're about to rewrite.
The wider context: cutting out a subject is the easy half of compositing, and the fringe is the half nobody warns you about, because it only appears on the new background. This is the node that sits between "I have a matte" and "it looks like it was shot there", and it's plain arithmetic - no model, no seed, same result every run. That's the right kind of tool for the layer of the pipeline that has to be reproducible.
Pack facts, once: Apache-2.0, by JH (@jetthuangai), 64 nodes at v1.10.0, bilingual (EN/VI) docs with a before/after image per node. Zero Reddit footprint as of writing - a search for the pack name turns up one unrelated browser extension - so the tooltips and docs are the reference, not forum lore.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Image the mask was made from. | |
| mask | MASK | Subject mask with soft edges (1 = subject), e.g. Alpha Matte. | |
| radius | INT | 161–256 | How far to look for the subject's own colour. Raise it for wide, wispy edges such as hair. |
| strength | FLOAT | 1.000–1 | 0 = unchanged, 1 = full correction. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | Image whose edge colours come from the subject, not the background. |