Nodes/MKRShift_Nodes/Skin Tone Check
ComfyUI Node

Skin Tone Check

Skin Tone Check heatmaps the damage

By criskb·Created 7 months ago·Updated 5 months ago· 0
Skin Tone Check
  • image
  • mask
  • image
  • mask
  • skin_tone_check_info
settings_json{"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}

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) and val_min (0.15) - the saturation/value window that fences off non-skin.
  • overlay_opacity and show_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.

CategoryMKRShift Nodes/Color/Analyze

Inputs (3)

NameTypeDefaultDescription
imageIMAGE
settings_jsonSTRING{"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}
maskoptMASK

Outputs (3)

NameTypeDescription
imageIMAGE
maskMASK
skin_tone_check_infoSTRING