GROUT Threshold
Tune your GROUT mask without re-running the model
- probability_heatmap
- binary_mask
- mask
GROUTThreshold is the node that makes you appreciate the pack's design. It exists because the model is the slow part and thresholding is instant, so the author split the two into separate nodes. You run the expensive inference once, then tune the mask forever without paying for it again.
Mechanically it's almost nothing, which is the point. GROUT Segmentation hands you a probability heatmap - a grayscale image where each pixel is the model's confidence (0 to 1) that it's looking at grout. GROUTThreshold slices that heatmap: everything above the threshold becomes 1, everything below becomes 0. No model, no inference, no weights involved. It reads the first channel of the heatmap, applies a prob > threshold comparison, and outputs a binary image and a proper mask.
That separation is what makes iteration fast. Because the threshold lives in its own node, you run inference exactly once, then drag the slider and watch the mask change live. Want slightly thicker grout lines? Nudge the threshold down. Too much noise bleeding into the mask? Nudge it up. The entire point is that you never re-run the model just to find out where the cutoff should sit.
Inputs and outputs are minimal, which is the whole appeal:
- probability_heatmap - wire this from GROUT Segmentation's first output.
- threshold - 0.0–1.0, default 0.5, the only knob that matters. 0.5 is a fine starting point; for real tile imagery you'll often drift toward 0.4–0.6 depending on how confident the model is and how heavy the seams are.
Outputs: binary_mask (a black-and-white IMAGE) and mask (a ComfyUI MASK). The IMAGE version is for looking at and saving; the MASK version is what you feed into compositing, inpainting, or anything that expects a proper mask tensor.
The pack's recommended flow is exactly this: Load Image → GROUT Segmentation → probability_heatmap → GROUT Threshold → mask, with the heatmap also fanning out to GROUT Heatmap Colorize for a colored preview. Threshold is the node you're actually fiddling with while the others sit still.
One implementation detail that will never bite you but is fun to know: the comparison is strict > rather than >=, so a pixel sitting exactly at the threshold value counts as "not grout." On a continuous float image that's a measure-zero event. Ignore it.
Installation is whatever you did for the pack itself. If GROUT Segmentation runs, this node is already installed - all three live in one custom_nodes folder and share a requirements.txt, and this one adds no heavy dependency of its own. It's pure tensor work.
The one real failure mode: feeding it something that isn't a GROUT heatmap. It reads channel 0 of whatever IMAGE you give it, so wire in a regular color photo and you get a threshold applied to its red channel, which is nonsense. Keep the heatmap as the source and you're fine.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| probability_heatmap | IMAGE | — | |
| threshold | FLOAT | 0.500–1 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| binary_mask | IMAGE | — |
| mask | MASK | — |