Face: Auto Blemish
Spot Healing for Portraits That Keeps the Pores
- image
- mask
- protect_mask
- image
- spot_mask
- face_count
Here's the thing about the automatic detailing loop everyone runs on faces: ADetailer and friends re-render the face with the diffusion model. That fixes the missing-eye, plastic-skin problem of a 70-pixel face, but it doesn't do retouching. A pimple doesn't get healed, it gets re-rolled along with the whole face.
Face: Auto Blemish (JHPixelProAutoBlemish) is the other job. It finds the small marks on skin and heals them deterministically, keeping the pores that were actually there.
What it does, step by step
- Find the faces. YuNet via Kornia (
core/face_detect_lite.py) - it works whether or not MediaPipe is installed. Each face box is grown by 25% and processed as its own crop, so cost scales with faces, not with frame size. Inside the crop only skin-like pixels survive a soft YCrCb test, minus discs placed around the eyes, brows and mouth from the five landmarks. Eyes and mouth are never touched. - Find the marks. The dust/spot detector from the pack's Dust & Spot Removal runs on a signal built from luma darkening plus redness, because a pimple is redder more than it is darker. A likely-local-max blob has to be compact and sit in calm surroundings, which is what stops it from eating eyelashes. The largest mark it will go after is about 5% of that face's width.
- Heal. Using the texture fill, not a blur: the best-matching nearby skin patch is copied in, brightness- and colour-matched to the ring around the spot. Pores continue through the healed area instead of turning into a smooth dollop.
That last point is the whole reason this node is worth installing over a generic spot remover. A blur fill on skin reads as a smudge at 100%; a matched patch doesn't.
The inputs that matter
image - the portrait. Batches work.
sensitivity (0–1, default 0.5) is the one knob you'll touch first. Higher catches fainter marks, and the tooltip is refreshingly blunt about the cost: very high also removes freckles.
spot_scale (0.25–4, default 1) is the size ceiling, relative to that 5%-of-face-width default. A mark that survived is usually bigger than the limit rather than missed - raise this before you reach for anything else.
Then the two optional masks, which are the difference between "cool demo" and "actually usable":
mask replaces the face search entirely. Give it skin (back, hands, arms, chest) and it cleans there instead. protect_mask is the one you'll use on a real client: beauty marks, a freckle pattern, tattoos. The node is documented as removing natural moles unless you protect them - believe the docs on this, it's not coy.
Outputs: image (retouched), spot_mask (exactly which pixels were healed), face_count (0 when you supplied a mask).
Wire spot_mask into something
Always look at it once, via Mask Preview as an overlay. It's the fastest answer to "did it catch blemishes or did it start eating texture?" If it's lighting up long lines or thousands of pores, your sensitivity is too high. face_count is the other cheap diagnostic: 0 on an obvious portrait means the detector missed and the node did nothing at all - switch to mask and carry on.
Install
Manager: search ComfyUI-JH-PixelPro → Install → restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/jetthuangai/ComfyUI-JH-PixelPro.git
cd ComfyUI-JH-PixelPro
pip install -r requirements.txt # the Python that runs ComfyUI
Then it's under Add Node → ComfyUI-JH-PixelPro → face. Deps are kornia>=0.7, mediapipe>=0.10.33, opencv-python-headless>=4.8, scipy>=1.10, plus ComfyUI's own PyTorch. The YuNet weights download once into the torch hub cache on first run - small (~0.4 MB), but it does need that first-run network hit.
Practical notes
- Order matters. Warp/resize the face first, then blemish, then skin smoothing or frequency separation. Cleaning a face you're about to reshape is wasted work.
- It is not a smoother. Auto Blemish removes marks; it does nothing about blotchy tone. Follow with Edge-Aware Smoother or the pack's Frequency Separation for that. If you're doing the frequency-separation dance, this is the step that fixes individual spots and the low layer handles the rest.
- CPU is fine. About 5 seconds for an 8 MP portrait, under 1.1 GB VRAM. Nothing exotic.
- Group photos work because each face gets its own crop and its own spot size - but a face turned past ~45° is YuNet's weak spot, same as with any detector in this family.
The pack is Apache-2.0, maintained by JH (@jetthuangai), 64 nodes and versioned releases. It also has no meaningful Reddit footprint yet, so there's no cottage industry of "here's my Auto Blemish settings" posts to lean on. The docs ship a before/after per node, which is the next best thing.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Portrait to retouch. | |
| sensitivity | FLOAT | 0.500–1 | Higher catches fainter marks; very high also removes freckles. |
| spot_scale | FLOAT | 1.000.25–4 | Largest mark to remove, relative to the automatic size (5 % of the face width). Raise it for bigger pimples. |
| maskopt | MASK | Skin area to clean instead of the detected faces (body, back, hands). | |
| protect_maskopt | MASK | Never touch these areas (a beauty mark you keep, tattoos). |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | The retouched image. |
| spot_mask | MASK | Pixels that were healed (check it with Mask Preview). |
| face_count | INT | Faces found (0 when a mask is given). |