Skin Tone Check
Skin Tone Check heatmaps the damage
- image
- mask
- image
- mask
- skin_tone_check_info
You grade a portrait, the skin turns waxy green in the shadows, and you don't notice until you've regenerated the whole workflow twice. x1SkinToneCheck exists to make that visible before you ship: it finds the pixels in your image that look like skin and paints them in a heatmap - green where the tone is healthy, yellow as it drifts, red where it's broken. Run it after a heavy color pass and you'll see the damage instantly.
How it works
It's an HSV qualifier, not a segmentation model - no AI involved, just math. It converts the image to HSV and builds a soft matte from three gates: target_hue (default 28°, the warm-orange hue of human skin), hue_width (52°, how far from that hue still counts as skin), and a saturation/val_min window that separates actual skin from backgrounds that happen to share the hue. Each pixel gets a distance from target hue score, and that distance is mapped to the heat ramp: close = green, mid = amber, far = red.
Then it composites the heat over the original at overlay_opacity (0.82), so you see the face through the diagnostic. Flip show_isolation to true and it instead shows only the skin heat on a near-black background - the most useful mode for eyeballing whether your grade pushed cheeks into the red zone. The returned mask is the skin matte itself, and skin_tone_check_info reports a confidence score plus mask coverage, so you can compare "before grade" and "after grade" runs numerically instead of squinting.
The inputs that matter
Settings live in a settings_json string, prefilled with sensible defaults:
target_hue(28) - the skin hue you're checking against. 28° is the standard starting point for caucasian skin; deeper skin tones can sit a few degrees off, so if the whole face reads red, nudge this first.hue_width(52) - how tolerant the qualifier is. Too wide and it catches the wall; too narrow and it misses the face.sat_min/sat_max(0.10/0.82) andval_min(0.15) - the saturation/value window that fences off non-skin.overlay_opacityandshow_isolation- how you want to see the result.
Outputs are image, mask, and skin_tone_check_info. Feed the mask into a preview to save it as an actual alpha - the heat overlay image is for looking, the mask is for wiring downstream.
Installing it
It ships inside the MKRShift Nodes pack. ComfyUI Manager: search "MKRShift", install, restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/criskb/MKRShift_Nodes
Restart after. No models, no downloads - pure numpy HSV math.
Gotchas
The hue-gate approach has one blind spot worth knowing: it keys off hue, so any warm object in frame (wood, amber lighting, a terracotta wall) can read as skin if it falls in the window. That's what the sat_min/val_min gates are for, but a busy scene will still flag false positives - treat this as a check on the subject, not an exact skin segmentation. And note it pairs naturally with the pack's x1SkinToneProtect: check where the grade is hurting skin, then protect it. Check first, protect after - that two-node loop is the whole workflow.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| settings_json | STRING | {"target_hue":28.0,"hue_width":52.0,"sat_min":0.1,"sat_max":0.82,"val_min":0.15,"line_tolerance":0.18,"overlay_opacity":0.82,"show_isolation":false,"mask_feather":12.0,"invert_mask":false} | — |
| maskopt | MASK | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| skin_tone_check_info | STRING | — |