Hair Edge Color Overlay
Want a different hair color without re-rolling? This node dyes it for you.
- image
- hair_mask
- face_mask
- image
- overlay_mask
You just generated a portrait you love, and the only thing wrong with it is the hair color. Your first instinct is to change the prompt and re-roll - which changes the pose, the lighting, and half the face too. Hair Edge Color Overlay (class HairEdgeOverlay, from the ComfyUI-HairOverlay pack) is the cheap deterministic alternative: it tints the hair that's already there, airbrush-style, strongest near the face and fading out toward the back of the head. No re-sampling, no seed roulette.
It's a pure post-process node - image in, image out - so it lives after your VAE decode and before Save Image. It's the "preview the dye job" tool: crank in a color, see if pink hair works on this character, then either keep it or re-roll with a changed prompt. For a real recolor you'd still rather inpaint, but for previewing shades this is instant and free.
How it works
The mechanism is three layers multiplied together, which the source makes easy to follow:
- A hair mask. If you feed the optional
hair_mask, it uses that (and resizes it to your image if needed). Otherwise it auto-detects hair by brightness: pixels with HSV value belowdark_thresholdand low saturation count as hair, then it runs morphological fill and a Gaussian blur scaled bysmoothnessto get a soft mask. - A face-proximity gradient. This is the whole trick. It finds the face - either from an optional
face_mask, or by detecting it - then builds a falloff that's 1.0 right at the face and decays toward zero withfalloffcontrolling the curve. That's why the color is bold at the hairline and gone by the back of the head. - The final mask is hair × face-proximity, blurred again, then clamped so color never bleeds past the hair. The color is just added on top:
result = image + overlay_color × mask × color_intensity.
The output overlay_mask is that exact final mask, which is handy if you want to see what it "decided" was hair - or composite the color yourself.
The inputs that matter
Most of the sliders are set-and-forget, but three are worth touching:
overlay_r/overlay_g/overlay_b- the RGB color, defaulting to a warm pink-red (255/50/60). This is the whole point of the node.color_intensity- how strongly the color applies (default 0.25).dark_threshold- the hair-brightness cutoff for auto hair detection. Default 120 works for dark hair; bright/blonde hair will need it raised or the node simply won't see your hair.
face_range widens how far from the face the effect reaches, falloff sharpens the fade, smoothness is the airbrush softness, and face_detect picks between auto_skin (HSV skin detection) and center_bias (assumes the face sits top-center). Both optional mask inputs, hair_mask and face_mask, are the fast path to accurate results.
Install
It's a one-file node with no dependencies beyond what ComfyUI already ships (torch, numpy, PIL - there's no requirements.txt). Easiest via Manager: search ComfyUI-HairOverlay, install, restart. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/mingyu4537-creator/ComfyUI-HairOverlay.git
Then restart ComfyUI. The node shows up under image/color as "Hair Edge Color Overlay". It also handles batches, so it runs per-frame on an animated or multi-image batch without extra work.
Where it trips you up
The auto face detection is genuinely crude - no face model, just skin-color statistics. On non-skin tones, busy backgrounds, or faces shot from the side, auto_skin can guess wrong and the overlay lands on the forehead instead of the hair. center_bias just assumes the face is top-center, which is fine for a centered portrait and useless otherwise. If the effect keeps landing wrong, stop fighting the knobs and wire in a face_mask from a segmentation/face-detect node - the whole node is far more predictable when you give it masks.
Also remember what this is: it's tinting pixels, not re-rendering. The result will always look a bit like a dye job laid over the original. That's the point for previewing, but if you need the color to actually re-light the scene, inpaint instead. For everything else, this is a surprisingly handy little node to keep one click away.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| overlay_r | INT | 2550–255 | — |
| overlay_g | INT | 500–255 | — |
| overlay_b | INT | 600–255 | — |
| dark_threshold | INT | 12010–250 | — |
| face_range | FLOAT | 0.600.1–3 | — |
| color_intensity | FLOAT | 0.250.05–1 | — |
| smoothness | INT | 305–100 | — |
| falloff | FLOAT | 2.51–5 | — |
| face_detect | COMBO | 2 options: auto_skin, center_bias | |
| hair_maskopt | MASK | — | |
| face_maskopt | MASK | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| overlay_mask | MASK | — |