CV Threshold Flags
Pick Your Thresholding Mode Once, Share It Everywhere
- flags
- value
cv2.threshold's type argument is a bit field hiding a decision. THRESH_BINARY, THRESH_BINARY_INV, TRUNC, TOZERO, TOZERO_INV - five different meanings riding on one integer - plus two modifier bits that auto-compute the threshold from the histogram. This node turns that into a dropdown with toggles, and lets you wire one configuration into every threshold node in the graph.
Thresholding is the workhorse of mask extraction: it's what turns a saliency map, a difference image, or a channel into something you can actually mask with. The pack's 04_threshold_playground.json exists because getting the mode right is most of the job, and eyeballing five variants on the same image is faster than reasoning about them.
What the flags mean
The base picks the method:
THRESH_BINARY(the default) - above the threshold becomes max, below becomes 0.THRESH_BINARY_INV- the same, inverted. The one you reach for when your subject came out black on white instead of white on black.THRESH_TRUNC- everything above the threshold is clipped down to it. A highlight limiter, not a mask.THRESH_TOZERO- below goes to 0, above is untouched. Useful for killing background noise while keeping real values.THRESH_TOZERO_INV- the mirror image of that.
Then two toggles:
THRESH_OTSUcomputes the threshold from the image's histogram instead of using the number you passed, picking the split that best separates two populations. This is the "I don't want to tune a value" option, and it deserves a warning: it's implemented only for 8-bit single-channel images, and it's really meant to pair with BINARY or BINARY_INV. Combine it withTRUNCand you're relying on undefined behaviour.THRESH_TRIANGLEdoes the same trick using the histogram's peak-to-tail distance - better than Otsu on the skewed, one-sided histograms you get from fluorescence or heavily backlit images.
When either auto method is toggled on, the threshold value you passed is ignored. That surprises people who set both and wonder which won.
Outputs
Two of them, matching the pack's other flag nodes:
flags(STRING) - the pipe-joined constant names, for wiring into theflagsinput ofcv2_thresholdorcv2_thresholdWithMask. This is the type-safe path: the string is resolved and validated when the node runs, so a typo errors loudly instead of OR-ing nonsense bits.value(INT) - the resolved integer, for raw INT flag parameters or arithmetic in aMathExpression.
Because it's a STRING that fans out, one node can configure every threshold call in a workflow. When you decide mid-run that Otsu was the wrong call, you flip one toggle instead of five.
Install
ComfyUI Manager → search ComfyUI CV (publisher bmad4ever), or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"
Restart after. Python ≥ 3.12 and a recent ComfyUI on the V3 node API. Keep the contrib wheel - a plain opencv-python installed over it shares site-packages/cv2 and silently empties the contrib submodules, breaking other nodes in the pack. tools/repair_opencv_contrib.py --check / --apply handles the repair.
04_threshold_playground.json is the reference graph; the sample images come in via 01_install_example_inputs.json (run it once, then reload the page).
Where it bites
The dropdown-and-toggles renderer comes from a per-node spec the pack ships with the widget. On an older frontend build flags renders as a plain text box and you'd be typing constant names by hand - still valid, just less pleasant.
Beyond that: nothing here checks that you wired it somewhere sensible. cv2_threshold will happily take a flags value meant for something else. The pack ships one flag builder per target family precisely because that's the failure mode, so match the node to the consumer.
And the pack's standing disclaimer, since it applies to everything in this collection: bmad4ever's README describes a personal, heavily LLM-assisted project, curated against a specific OpenCV build, with no support planned and workflows built to demonstrate rather than ship. A flags OR-er with two outputs is about as safe as that gets.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| flags | STRING | THRESH_BINARY | Pipe-joined cv2 constant names, e.g. "THRESH_BINARY | THRESH_OTSU". In the UI this renders as a base dropdown with one toggle per flag. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| flags | STRING | The pipe-joined flags string - wire it into the flags input of cv2_threshold / cv2_thresholdWithMask nodes. |
| value | INT | The resolved integer (constants OR-ed together). |