Nodes/ComfyUI_LC123_nodes/LC Skin Upscale
ComfyUI Node

LC Skin Upscale

Put the pores back without re-rolling the face

By lonecatone23·Created 3 months ago·Updated about 21 hours ago· 46
LC Skin Upscale
  • image
  • upscale_model
  • mask
  • protect_mask
  • image
  • skin_mask
◄modedetail 1x►
◄blend0.75►
◄mask_sourceinput+chroma►
◄mask_sensitivity0.55►
◄mask_feather0.45►
◄tile512►
◄overlap32►
◄transferdetail band►
◄softness0.50►

"Too smooth skin" is the oldest complaint in this hobby and still the first one people make about a brand-new architecture - it's why the Z-Image Turbo writeups of 2026 open with the skincare-ad problem. The usual answers all involve sampling again: FaceDetailer, a low-denoise img2img pass, SeedVR2. Every one of those invents a face.

LC Skin Upscale is the other kind of fix. One CNN upscale model, applied where a mask says, composited back over the original pixels. No sampler, no seed, no CFG - and, per the author, not a stack and not Ultimate SD Upscale. It sits between "leave the skin alone" and "run the face through a generative detailer".

How it actually works

Building the matte. mask_source decides where the effect lands. input uses only the MASK you wire in. chroma ignores your mask and derives one from skin-colour heuristics - RGB ranges plus a CIELAB chroma window, box-blurred and thresholded with mask_sensitivity as the dial. input+chroma is the AND of the two. The matte then gets feathered, and the node crops to its bounding box (padded 16px, snapped to a multiple of eight).

Running the model on the crop. It hands that crop to your UPSCALE_MODEL through Comfy's tiled scaler, and retries at half the tile size if it runs out of VRAM. Then:

  • detail 1x resizes the model's output back down to the crop's size and pastes it in. Nothing gets bigger. This is the mode for 1× skin models like 1xSkinContrast-High-SuperUltraCompact or 1x-ITF-SkinDiffDetail-Lite-v1.
  • scale keeps the model's native factor - the canvas genuinely grows, unmasked area bilinear, masked area run through the model. Only for when you wanted pixels.

Final pixels are original × (1 − mask × blend) + patch × (mask × blend) - the strength you get is mask and blend multiplied, not either alone.

It's a preview node underneath (a PreviewImage subclass), which is where the on-node before/after wipe comes from. Outputs are image (composited, batch-preserved) and skin_mask.

The inputs worth touching

  • upscale_model - load it with the core UpscaleModelLoader from ComfyUI/models/upscale_models, and load a 1× skin model, not a generic 4×. The author's daily is 1xSkinContrast-High-SuperUltraCompact.
  • blend - 0 is the original image, 1 is a full replacement under the matte. The pack's own recipe is 0.75, dropping to 0.55–0.65 on already-sharp Krea plates.
  • mask_source - input if you're wiring a proper person mask, which is the recommended path.
  • mask_feather - soft edge on the composite matte, and the one to nudge if you can see where the patch ends (0.45 in the author's recipe).
  • tile / overlap - the author's numbers are 256 / 16 on large plates, on the grounds that 512 is slower for very little gain. tile: 0 means "try the whole crop and shrink if it OOMs".

Install

Manager: search ComfyUI_LC123_nodes. Manually:

cd ComfyUI/custom_nodes
git clone https://github.com/lonecatone23/ComfyUI_LC123_nodes

Then restart. __init__.py has to sit directly in that folder - if you unzipped a pack zip inside an existing clone and ended up with ComfyUI_LC123_nodes/ComfyUI_LC123_nodes/, move the inner files up a level. The console should print an LC123 load line when it comes up. No pip dependencies, but the maskers and the models don't ship with it.

Grab the 1× skin CNN from the pack's model table (openmodeldb, or notkenski/upscalers on HuggingFace) and drop it in:

ComfyUI/models/upscale_models/1xSkinContrast-High-SuperUltraCompact.pth

For the mask, the author's example workflow wires a LayerMask: PersonMaskUltra V2 matte with face + body on. That node lives in chflame163's LayerStyle Advance, not here.

Where it goes wrong

Loading a 4× model in detail 1x. You pay 4× the time, then throw three-quarters of the pixels away. The README warns about this first, and it's invisible in the output - it just gets slow.

The empty-matte no-op, and skin-coloured leaks. If the bounding box comes back empty, or blend is effectively zero, the node hands you the original frame unchanged - so "I ran it and nothing happened" usually means the chroma heuristic found no skin (heavy makeup, green screen, cool grade) or mask_source: input with a mask that's black everywhere. Check skin_mask first. The opposite failure is just as common: the auto matte happily swallows tan fabric, wood and warm walls, so lower mask_sensitivity or wire a real person mask - which is the recommended path anyway, since mask_source ships as input+chroma and quietly falls back to auto-skin if you wire nothing. Related trick: input with no MASK wired gives an all-white matte, i.e. a full-frame 1× pass.

It's a detail pass, not a detail generator. A CNN can't invent a nose, and it won't rescue a soft source - that's SeedVR2's or a face detailer's job. Run it at native resolution, before you upscale, on skin that's clean but too smooth.

PersonMaskUltra friction. It wants mediapipe, and "No module named 'mediapipe'" is a long-running annoyance in the wild. If the mask side breaks, that's a separate pack's dependency, not LC123's.

CategoryLC123/image

Inputs (13)

NameTypeDefaultDescription
imageIMAGESource image (batch ok).
upscale_modelUPSCALE_MODELOne CNN upscaler. 1× SkinContrast for detail.
modeCOMBOdetail 1xdetail 1x = paste back at original size. scale = keep the model's native factor.
blendFLOAT0.750–1How hard the upscaled patch replaces the original under the mask.
mask_sourceCOMBOinput+chromainput = wired mask only. chroma = auto skin. input+chroma = AND.
mask_sensitivityFLOAT0.550–1Auto-skin reach when chroma is used.
mask_featherFLOAT0.450–1Soft edge on the composite matte.
tileINT5120–2048CNN tile size. 0 = try full crop, shrink on OOM.
overlapINT320–256Tile overlap in pixels.
transferCOMBOdetail banddetail band = take only the model's pore and fold detail (brightness only, softly capped, eased off at edges and in deep shadow / bright highlights): no colour shift, no 1-pixel grain. full paste = paste the model's whole output (the old behaviour).
softnessFLOAT0.500–1detail band only: higher = smoother, gentler detail. Lower = crisper.
maskoptMASKPerson / skin matte from RMBG or similar. Stay external.
protect_maskoptMASKOptional. Areas left alone, e.g. the faces and hands the detailers already redrew (LC VOSR2 Upscale (pipe) 'protected' output, or LC Smart Detailer's mask). Keeps skin detail from being added twice.

Outputs (2)

NameTypeDescription
imageIMAGE—
skin_maskMASK—