Heatmap
Turn any channel into a color-coded readout
- image
- source_mask
- effect_mask
- image
- mask
- heatmap_info
Heatmap is the debugging-and-review node you didn't know you needed: it takes one scalar property of your image - luma, a channel, saturation - and paints it through a scientific color palette so you can actually see where the values sit. Think of the false-color readouts on a camera's focus peaking, or a range check in a grading suite. That's this node, in your graph, for free.
It lives in MKRShift Nodes/Color/Analyze, the pack's answer to "I want to look at my image, not just guess at it." Where its sibling x1HistogramScope shows you a one-dimensional distribution, Heatmap keeps everything spatially honest: you see where in the frame the brightness or saturation lives.
How it works
Under the hood it's a small, clean pipeline: pick a source_mode (luma, red, green, blue, max_rgb, saturation, value, alpha, or mask), pull that scalar out per pixel, normalize it, and run it through a palette.
The normalization step is where the utility hides:
manual_rangemaps yourvalue_min/value_maxdirectly - fixed range, no surprises.auto_rangestretches to the image's actual min/max - best contrast, but it rescales between frames, which is annoying for video.auto_percentileusespercentile_low/percentile_high(defaults 2–98) - the one you'll want for video, because it's stable frame to frame and shrugs off a few outlier pixels.
gamma reshapes the middle, invert_values flips it, and overlay_opacity blends the colored overlay back over the original - 1.0 gives pure false color, lower values let you see it in context. The palette choices are the matplotlib crowd-pleasers: inferno, viridis, plasma, magma, turbo, thermal, icefire.
The two masks
This node takes two optional masks, which trips people up. source_mask restricts which pixels get analyzed (everything outside it reads as low/black) while effect_mask restricts where the colored overlay is drawn - like a scissor on top of the result. Use source_mask to check a region, effect_mask to tint only part of the frame. Both feed mask_feather/invert_mask.
Outputs: the overlaid image, a mask holding the normalized scalar as grayscale (handy to reuse as a matte - a luma heatmap's mask is literally a luma matte), and a heatmap_info string with the resolved source, range, and mask coverage. Read it with a Show Text node when you want to confirm the auto-range behaved.
Installing and the usual caveats
This is one of the discrete-input nodes in the pack (no settings_json bundle), so every knob is a real widget on the node. Install is the pack standard:
cd ComfyUI/custom_nodes
git clone https://github.com/criskb/MKRShift_Nodes
then restart, or search MKRShift_Nodes in ComfyUI Manager. No models, no pip extras for this family.
One trap: for a plain preview you mostly want luma or saturation - don't overthink the nine modes. And when something looks wrong, check the heatmap_info string: it tells you the actual min/max the normalizer landed on, which is usually the "oh, right, the image had a blown pixel" moment.
Inputs (15)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| source_mode | COMBO | 9 options: luma, red, green, blue, max_rgb, saturation, +3 | |
| palette | COMBO | 7 options: inferno, viridis, plasma, magma, turbo, thermal, +1 | |
| normalize_mode | COMBO | 3 options: manual_range, auto_range, auto_percentile | |
| value_min | FLOAT | 0.0000–1 | — |
| value_max | FLOAT | 1.0000–1 | — |
| percentile_low | FLOAT | 2.00–100 | — |
| percentile_high | FLOAT | 98.00–100 | — |
| gamma | FLOAT | 1.000.1–4 | — |
| invert_values | BOOLEAN | false | — |
| overlay_opacity | FLOAT | 1.000–1 | — |
| mask_feather | FLOAT | 12.00–256 | — |
| invert_mask | BOOLEAN | false | — |
| source_maskopt | MASK | — | |
| effect_maskopt | MASK | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| heatmap_info | STRING | — |