Skin Highlight Remover
Removing Skin Highlights Without Re-rolling the Dice
- image
- exclude_mask
- image
- highlight_mask
You know that thing where an anime character looks like they've been standing under a ring light - that glowy, pale-white shine smeared across their skin, even in dark scenes? It's one of the most common failure modes in this hobby, and people usually attack it by re-prompting ("warm light", "no highlights", the usual begging) or by inpainting every spot by hand. Skin Highlight Remover is the third option: a deterministic post-process fix that blurs the shine into the surrounding skin, the way a blur brush works in Clip Studio Paint. No sampler roulette, no second denoise pass - you feed it the image and get a cleaned one back.
The pack is tiny and open (MIT, one node, one file of Python). The trick it pulls off is deceptively simple: it finds the highlight pixels, then blends them toward their neighborhood with an edge-preserving filter. Under the hood it runs everything in HSV color space. It first builds a skin mask from hue/saturation/value ranges - broad ranges for anime, tighter ones for realistic, and both if you can't decide. Then it stacks four highlight detectors: how much brighter a pixel is than its local skin neighborhood, bright-but-desaturated white lines near skin, bright desaturated spots on skin, and local saturation drop (highlights bleach color). It takes the max of all four, so it catches both soft blobs and those thin white streak lines. The blur itself is a bilateral filter - strong blending where the highlight is intense, gentle elsewhere - so skin texture doesn't melt into plastic.
The settings that actually matter are few. local_contrast (default 25) is your detection sensitivity; lower it if highlights slip through, raise it if it's eating your shading. blur_strength (15) is the brush size - bigger for large shine areas, smaller for fine work. strength (1.0) is the overall effect; at 0.5 you get a half-blend that's handy when the mask overshoots. skin_mode picks anime/realistic/both. And lineart_enhance (0.3) darkens the lineart back up after blurring - the author's own tooltip says set it to 0 if lines start looking dirty, and honestly you'll probably end up doing exactly that. There's also mask_expand, face_expand, and an optional exclude_mask input if you want to protect something the auto-detection can't see. Outputs are two: image (the cleaned render) and highlight_mask, a MASK you can preview or wire into other nodes to see exactly what it thinks it's fixing.
Install is trivial. ComfyUI Manager can find it as "Skin Highlight Remover," or:
cd ComfyUI/custom_nodes
git clone https://github.com/mingyu4537-creator/ComfyUI-SkinHighlightRemover.git
Restart ComfyUI and you're done - it ships with zero dependencies beyond the OpenCV/numpy/torch ComfyUI already has, and no model downloads. That's the good news. The gotcha: the code tries to load lbpcascade_animeface.xml for anime face detection, but that file isn't bundled in the repo. So for anime images it silently falls back to OpenCV's generic Haar cascade, which is worse at cartoon faces - meaning face exclusion can miss, and you'll get shine removed from faces you wanted left alone. If you see that, drop a real lbpcascade_animeface.xml (easy to find online, it's a tiny file) next to skin_highlight_remover.py and the anime detector kicks in. The fallback means it still works out of the box, just more defensively on faces.
A few real-world tips: it processes every frame in the batch, so it works on image sequences fine, but each frame runs on CPU - still fast enough. Because highlights are detected as brighter than surroundings, over-bright shading can get misread as shine; dropping local_contrast handles most of that. And if you're just annoyed at one specific glossy spot, strength at 0.5–0.7 plus an exclude_mask for the rest of the image is the surgical move. It's not going to replace inpainting for serious fixes - but for killing that ring-light sheen on a render you already like, it's the tool you didn't know you needed.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| local_contrast | INT | 255–80 | How much brighter than surroundings = highlight. Lower = catch more highlights. |
| detect_radius | INT | 155–50 | Neighborhood size. Larger = catch bigger highlight areas. |
| blur_strength | INT | 153–50 | Blur brush size. Larger = stronger blending into skin. |
| mask_expand | INT | 30–20 | Expand detected highlight area by pixels. |
| strength | FLOAT | 1.00–1 | Overall effect strength. 1.0 = full blur, 0.5 = half blend. |
| skin_mode | COMBO | anime | 3 options: anime, realistic, both |
| face_expand | FLOAT | 0.50–2 | Face exclusion zone expansion. |
| lineart_enhance | FLOAT | 0.300–1 | Lineart darkening strength. 0 = off, 0.3 = 30% darker. Set to 0 if lines look dirty. |
| exclude_maskopt | MASK | Optional extra region to exclude. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| highlight_mask | MASK | — |