ComfyUI Node Runs on cloud

FindThreshold

Auto-Tune the Threshold That Gets You the Mask You Want

By bmad4ever·Created 3 years ago·Updated 9 months ago· 70
FindThreshold
  • src
  • IMAGE
start_at1
end_at255
thresh_typeBINARY
downscale_factor2
condition# Some expression that returns True or False

FindThreshold searches a range of threshold values until the thresholded image satisfies a condition you write, then applies that winning threshold at full resolution. It's a "find me the threshold that works" node - you describe the result you want, and it hunts for the setting that produces it.

Why you'd reach for it

Thresholding a grayscale image into black and white is the first step of half the CV tricks in ComfyUI: isolating a bright region, turning an edge map into a mask, prepping input for the pack's GrabCut nodes. The problem is that the "right" threshold varies per image, and hand-tuning it per frame is miserable. FindThreshold automates the hunt: instead of guessing that 128 is right, you say "I want a threshold where at least 50% of the pixels are black" and it goes and finds it.

Where this shines is anything that runs across many images - video frames, batches - where a fixed threshold that works on frame 1 silently breaks by frame 40. The condition gives you a target that stays true while the image changes.

How it works

For each candidate value in the range start_at..end_at, it applies OpenCV's threshold with your chosen thresh_type (BINARY, BINARY_INV, TRUNC, TOZERO, TOZERO_INV), evaluates your condition expression on the result, and stops at the first value that returns true. The search runs on a downscaled copy (downscale_factor, default 2) so it's fast; the winner is then re-applied at full resolution for the output. If nothing satisfies the condition, it falls back to end_at.

The condition box is evaluated with simpleeval (sandboxed, with a timeout). You get t (the thresholded image), plus cv, np, and m (math). The README's own examples:

cv.countNonZero(t) > 100                              # more than 100 non-black pixels
(t.size - cv.countNonZero(t)) / t.size > .50          # more than 50% black pixels

The inputs that matter

  • start_at / end_at - the search range (1–255). Note it searches in order, so if end_at < start_at it runs the range in reverse.
  • thresh_type - the OpenCV threshold mode applied to each candidate.
  • condition - your True/False expression; this is the actual specification of "the mask I want."
  • downscale_factor - search-speed tradeoff; 1 searches at full res, higher is faster.

Output is a single IMAGE: the full-resolution threshold at the found value.

Install

This is one of the nodes that genuinely needs the pack's dependencies:

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_bmad_nodes
pip install -r requirements.txt

then restart ComfyUI. Manager users search "comfyui_bmad_nodes". Without opencv-python the CV nodes fail to load.

Common issues

  • "Nothing ever matches." The condition never comes true in the range, so it silently returns end_at. Add a print-style debug or loosen the condition.
  • Condition syntax errors. You're writing a Python expression with t as the thresholded image. If the node throws, check you used t (not img) and that cv/np are your only module prefixes.
  • Slow search. The downscale exists precisely because full-res thresholding of 255 candidates is slow; drop downscale_factor only when you're sure you need exact pixels.

It turns "which threshold?" into "this condition," and for batch work that's a genuinely better question to be asking.

CategoryBmad/CV/Thresholding

Inputs (6)

NameTypeDefaultDescription
srcIMAGE
start_atINT11–255
end_atINT2551–255
thresh_typeCOMBOBINARY5 options: BINARY, BINARY_INV, TRUNC, TOZERO, TOZERO_INV
downscale_factorINT2
conditionSTRING# Some expression that returns True or False

Outputs (1)

NameTypeDescription
IMAGEIMAGE