Nodes/ComfyUI-JH-PixelPro/Filters: Smart Sharpen
ComfyUI Node

Filters: Smart Sharpen

Sharpen the Detail, Leave the Noise Alone

By jetthuangai·Created 6 months ago·Updated a day ago· 6
Filters: Smart Sharpen
  • image
  • mask
  • image
◄amount1.00►
◄radius1.0►
◄threshold0.000►
◄luminance_onlytrue►

Everything in ComfyUI sharpens by accident. Any VAE round trip, any upscale, any resize softens the frame, and the usual fix is to crank a detail slider on the sampler and hope. Filters: Smart Sharpen (JHPixelProSmartSharpen) is the boring correct answer: an unsharp mask with three real controls and a mask input, applied as the last step where it belongs.

The mechanism, because it explains every setting

"Sharpening" is unsharp masking, and the name is literally the recipe. Blur a copy of the image. Subtract it from the original - what's left is the detail layer. Add that detail back, scaled up. There's no magic and no model.

Here: detail = image − gaussian_blur(image, sigma = radius), soft-thresholded, then out = image + amount × detail × mask, clamped to 0..1. Every knob falls out of that one line:

  • amount (0 to 5, default 1) is how hard you add it back. 0.5 to 1 is usually enough. Above 2 you're buying halos.
  • radius (0.3 to 10, default 1) is the blur sigma, meaning what counts as detail. Small radius = fine texture, grain-adjacent. Large radius = edge contrast, which is really local contrast wearing a sharpening hat. 0.5–1 for web-size output, 1.5–3 for large prints.
  • threshold (0 to 0.5, default 0) zeroes out detail weaker than the threshold - the noise suppression. On a grainy or lightly-noised image, 0.02 to 0.05 stops you amplifying exactly the texture you don't want. It uses a soft ramp rather than a hard cut, so you don't get speckle at the boundary.
  • luminance_only (on by default) takes the detail from BT.601 luma and adds it equally to R, G and B. Brightness moves, colour doesn't - which is why you don't get coloured fringes on high-contrast edges.

And then mask, where 1 means full sharpening and 0 means none. That's the setting that makes this better than a global filter: sharpen eyes, lashes, hair and fabric; leave skin and sky smooth. A high-frequency detail mask feeding this input is the professional move, and it's the difference between "sharp" and "sharp where it counts".

Where it belongs in the chain

Order matters more than parameters here. Sharpen after smoothing, never before - otherwise you're sharpening the blemishes you're about to remove. Sharpen after colour work and after resizing, since a resize resamples detail you'd otherwise double-sharpen. And sharpen last, localised, at output size.

For motion-blurred or composited work the same rule holds: blur the background, composite, then sharpen the subject through its mask. Two nodes, in that order, and a shot that reads as photographed rather than rendered.

Install

ComfyUI Manager, search ComfyUI-JH-PixelPro, install, restart. Manual:

cd ComfyUI/custom_nodes
git clone https://github.com/jetthuangai/ComfyUI-JH-PixelPro.git
cd ComfyUI-JH-PixelPro
pip install -r requirements.txt

Then Add Node → ComfyUI-JH-PixelPro → filters. Pack requirements: Python 3.10+, kornia>=0.7, MediaPipe ≥ 0.10, OpenCV ≥ 4.8, SciPy ≥ 1.10 - and it needs no models, so nothing downloads. 64 nodes, Apache-2.0, one maintainer, GPU-first but CPU-safe.

Common issues

"Image must be larger than ceil(3 × radius)". The Gaussian kernel is 2·ceil(3·radius)+1 wide, so a big radius on a small crop is physically impossible. Either drop the radius or sharpen after the upscale.

A white halo along edges. amount too high or radius too high for the subject. Pull amount to 1 and radius to 1, then raise one at a time. Halos are inherent to the technique - the only real fix is less sharpening, or a mask so you sharpen less area.

The grain got worse. threshold is 0. Raise it until the flat areas stop sparkling; on a film-grain pass you specifically want the grain left alone, so threshold up rather than amount down.

Skin looks rough and textured. You sharpened globally. Mask it to detail areas only - this node has the input for exactly that reason.

Nothing changed. amount at 0, or an all-black mask. Both pass through by design.

It's the last node before saving and now the PNG looks crunchy. Sharpening is resolution-dependent, so a workflow tuned at 1024 gets aggressive at 2048. Re-tune at output size, not at preview size.

Worth setting expectations about the pack itself: there's no community discussion of it to search - no threads, no shared workflows, nothing on the subreddits. That's a real cost for a beginner, since there's no "someone already hit this" thread. The compensation is that the docs are written at this level of detail - sigma, kernel size, the threshold ramp - so the node is auditable rather than mysterious. For a deterministic filter, that's most of what support would have given you anyway.

CategoryComfyUI-JH-PixelPro/filters

Inputs (6)

NameTypeDefaultDescription
imageIMAGE—
amountFLOAT1.000–5Sharpening strength. 0 leaves the image unchanged.
radiusFLOAT1.00.3–10Blur radius (sigma, pixels) of the detail layer.
thresholdFLOAT0.0000–0.5Detail weaker than this is not sharpened (suppresses noise).
luminance_onlyBOOLEANtrueSharpen brightness only; colours stay untouched (no fringes).
maskoptMASKWhere the mask is 1 sharpening applies fully; 0 leaves it.

Outputs (1)

NameTypeDescription
imageIMAGE—