Nodes/was-node-suite-comfyui/WAS Latent Detail Boost
ComfyUI Node Runs on cloud

WAS Latent Detail Boost

Sharpening a latent without the embossed look

By WASasquatch·Created 4 years ago·Updated a day ago· 1,864
WAS Latent Detail Boost
  • latent
  • latent
  • mask
  • mask_preview
◄sigma_small0.60►
◄sigma_large1.40►
◄gain0.35►
◄limit1.25►
◄rms_sigma1.20►
◄rms_floor0.060►
◄edge_protect0.45►
◄edge_sigma0.80►
◄edge_threshold0.25►
◄edge_softness0.10►
◄preview_mask_scale8►
◄preview_modedetail_mask►

Sharpening has a fixed recipe. Blur a copy, subtract it to isolate the high-frequency detail, add that detail back scaled by an amount. That's unsharp masking, it's the only thing "sharpen" has ever meant, and the reason it looks bad when you crank it is that the same amount gets added everywhere - including on both sides of every edge, where it produces the bright rim and the dark outline people call haloing.

Do that in latent space and it's worse, because the latent's "high frequency" isn't texture, it's encoding noise. Sharpen a latent directly and you get dark outlines and an embossed, metallic look that no prompt asked for.

This node is a band-pass with three guards bolted on, and each one is aimed at a specific failure of plain sharpening.

What it does

It isolates one band of detail rather than "all the sharp stuff": sigma_small is the fine end (0.6 in latent blocks by default) and sigma_large the coarse end (1.4), and the gap between them is what gets boosted. A narrow band like 0.6 against 1.4 reads as texture; widen it and you start treating larger features. Set sigma_small to 0.0 and you reach the very finest detail - including noise, which is why 0.6 is a better default than 0.0. The two are swapped if you enter them the wrong way round, so don't worry about the order.

gain is how much of that isolated detail is added back. 0.35 is a gentle lift; above about 1.0 the texture starts to dominate the picture.

Then the guards.

The contrast limit is the interesting one. The detail is levelled against the local amount of contrast before it's added, measured over rms_sigma (1.2 by default) - so a smooth sky gains as much texture as a busy tree, instead of being left behind by a process calibrated for the busy areas. rms_floor puts a floor under that measurement so genuinely flat regions aren't amplified into grain; raise it toward 0.2 if skies come out sandy, lower it toward 0.0 to treat flat areas as hard as everything else. limit (1.25) squashes the detail before it lands, which is what stops a strong edge ringing - 4.0 flattens the strongest detail to a uniform level, 0.1 barely limits at all. Setting rms_sigma to 0.0 measures over the whole frame instead and gives you plain, uniform sharpening - the behaviour you came here to avoid, kept around as a comparison.

Edge protection holds the effect back on strong boundaries. edge_protect 0.45 halves it there, 1.0 leaves boundaries untouched, 0.0 disables the pass (and skips finding edges entirely). edge_sigma blurs before edges are detected, so fine texture isn't mistaken for a boundary and protected from the very treatment it wants; edge_threshold is how strong a boundary has to be, measured against the strongest in the picture; edge_softness is how gradually protection fades in - 0.1, because a hard-edged protected strip is visible as a strip.

Video, and seeing the masks

Video latents with a time axis are handled frame by frame, so a sequence gets the same treatment frame to frame instead of flickering.

Outputs: latent, plus mask and mask_preview so you can see which map the node is working from rather than guessing, and preview_mask_scale (8 by default, matching what most VAEs decode to) sets how many preview pixels each latent block becomes. preview_mode picks which of the two maps the node shows - edge_mask or detail_mask. The masks are the underrated part: when the boost isn't doing anything, the mask tells you whether it's the threshold or your image.

Where it fits

Between a latent upscale and the second sampler in a hires pass. The latent upscale interpolates and softens; this puts some detail back before the sampler re-resolves, which lets you sit at a slightly lower denoise and keep more of the composition you liked. Also at the tail of a chained sequence run, where contrast and detail have accumulated - though there, the more correct fix is turning the drift down rather than sharpening on top of it.

Installing it

It ships in WAS Node Suite v3 - MIT, by WASasquatch, 468 nodes:

cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/was-node-suite-comfyui.git

ComfyUI Manager, search WAS Node Suite v3, is the recommended route. ComfyUI 0.14.0+ and Python 3.10+; no pip packages, no downloads, no build. Config and folders land in <ComfyUI user dir>/was-node-suite/ on first start, which is why that first boot is a second slower and an update repeats it. Latent upscalers and this node are among the 27 in the extras feature group, on by default - check features.extras in config.yaml if it's missing from your menu. And if an older guide tells you to install scikit-image first, close the tab; that was v2.

CategoryWAS Suite/Latent

Inputs (13)

NameTypeDefaultDescription
latentLATENTThe latent to enhance. A video latent with a time axis is handled frame by frame.
sigma_smallFLOAT0.600–8The fine end of the detail that is boosted, in latent blocks. Together with sigma_large it picks which size of feature is affected: 0.6 keeps the treatment on the smallest structures. Set to 0.0 to reach the very finest detail, including noise.
sigma_largeFLOAT1.400–16The coarse end of the detail that is boosted, in latent blocks. Widening the gap between it and sigma_small treats larger features as well; 1.4 against 0.6 gives a narrow band that reads as texture. The two are swapped if entered the wrong way round.
gainFLOAT0.350–2How much of the isolated detail is added back. 0.0 leaves the latent alone, 0.35 is a gentle lift, and above about 1.0 the texture starts to dominate the picture.
limitFLOAT1.250.1–8How hard the detail is squashed before it is added, which is what stops a strong edge ringing. High values such as 4.0 flatten the strongest detail to a uniform level; 1.25 keeps most of the variation; 0.1 barely limits at all.
rms_sigmaFLOAT1.200–16How large an area the local amount of contrast is measured over, in latent blocks. It is what lets a smooth sky gain as much texture as a busy tree instead of being left behind. 0.0 measures over the whole frame instead, which restores the plain behaviour of sharpening everything by the same amount.
rms_floorFLOAT0.0600–1A floor under that local measurement, which keeps genuinely flat areas from being amplified into noise. Raise it towards 0.2 if a clear sky or a plain wall comes out grainy; lower it towards 0.0 to treat flat areas as hard as everything else.
edge_protectFLOAT0.450–1How much the enhancement is held back on strong boundaries, which is what prevents dark outlines around objects. 0.0 turns the protection off and skips finding edges at all; 1.0 leaves boundaries completely untouched; 0.45 halves the effect there.
edge_sigmaFLOAT0.800–8Blur applied before boundaries are looked for, in latent blocks. Raise it so that fine texture is not counted as an edge and protected from the very treatment it wants; 0.0 finds the finest boundaries.
edge_thresholdFLOAT0.250–1How strong a boundary has to be to be protected, measured against the strongest one in the picture. 0.25 covers the clear outlines; lower values protect more and enhance less.
edge_softnessFLOAT0.100.0005–1How gradually the protection fades in around that threshold. Small values give a hard-edged protected strip that can be seen; 0.10 fades over a comfortable range.
preview_mask_scaleINT81–16How many preview pixels each latent block becomes. 8 matches the size the latent decodes to on most VAEs, so the preview lines up with the finished picture; 1 gives the small raw map. This affects the preview image only, never the mask output.
preview_modeCOMBOdetail_maskWhich map leaves the node. `detail_mask` shows where detail was added and how much, which is what to watch while setting gain. `edge_mask` shows the boundaries that were protected, which is what to watch while setting edge_threshold.

Outputs (3)

NameTypeDescription
latentLATENTThe enhanced latent, ready for a sampler or a decode.
maskMASKThe chosen map at latent resolution, useful for driving another node from the same areas this one treated.
mask_previewIMAGEThe same map as a viewable image, enlarged by preview_mask_scale.