CV Draw Segments
Actually see the lines Hough found
- source
- segments
- labels
- image
- count
You run a Hough transform, get an array of endpoint pairs, and then... nothing. There is no core node that draws an Nx4 array of line segments onto an image. CV Draw Segments is the missing renderer: it takes the raw output of the pack's line detectors and paints it over your picture so you can tell whether the detection is good or you are just hoping.
What it's for
Detection nodes in this pack are deliberately data-only - the pack's own docs split "measuring" nodes from "viz" nodes, so that nothing draws unless you asked it to. Which is great for wiring, and annoying for the first ten minutes. This node closes the loop: you feed it an image plus segments, and get the image back with the lines on it. That is the debugging half of every line-detection workflow - Hough (cv2_HoughLinesP), CV Detect Lines (Hough), FLD, LSD, and the lines output of CV Edge Drawing all emit the same layout, so they all plug straight in.
How it works
The segments input accepts either Nx1x4 or Nx4 - the node reshapes to (-1, 4) and treats each row as (x1, y1, x2, y2). So HoughLinesP's awkward Nx1x4 (which returns literally None when it finds nothing) lands on the node without a conversion step.
Each segment is drawn with cv2.line in anti-aliased mode. When you pick a line_style other than solid, the node stops being one cv2.line call: OpenCV has no stroke pattern, so the dash pattern is walked along the segment by arc length and emitted as short solid pieces, with the run lengths scaled by thickness so a fat dashed line still reads as dashed. If labels is connected, each segment is coloured by its cluster label using the same palette as CV Draw Points, and color is ignored.
Empty or None segments pass the image through unchanged and report count = 0. That matters, because it means the nothing-found case doesn't blow up your graph.
The inputs you'll touch
source- the image or mask to draw on. A copy is made, so the input isn't mutated; an IMAGE stays an IMAGE, a MASK stays a mask.segments- the(x1, y1, x2, y2)rows.thickness- 1 to 64. No fill option here, unlike the circle node.color- a single value broadcast to every channel, or a BGR tuple string like(0, 255, 0). BGR, not RGB, so(255, 0, 0)is blue. Shorter tuples are zero-padded.line_style(optional) -solid,dashed,dotted,dash-dot.labels(optional) - one integer per segment. Length must match the segment count or the node raises, which is a nicer failure than silently miscolouring.
Outputs are image (same format as the input) and count, an INT you can branch on with an if/else when zero segments is a real possibility.
The one design point worth stealing
The author is oddly insistent about this in the node description, and he's right: two segment sets drawn on the same image should differ in style, not just colour. A dashed set over a solid one reads for every viewer, in greyscale, on a projector, and to the roughly 8% of men with red-green colour deficiency. Green over red reads for you and nobody else. If you're doing A/B on two detectors, that's the setting to change.
Install
The whole pack installs at once:
# ComfyUI Manager → search "ComfyUI CV" → install → restart
# or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
cd comfyui_cv && pip install -r requirements.txt
Then restart ComfyUI. Two requirements people trip on: Python 3.12 or newer, and a recent ComfyUI - this pack is written against the V3 node API, so on an older build the nodes simply don't appear. The only real dependency is opencv-contrib-python-headless~=5.0.0.93 (numpy and torch alongside it), which is the version the author curated behaviour against.
When it bites
- Nothing draws. Check
countfirst. Zero is a legitimate result and the image comes back untouched - that's the node working, not failing. labelsmismatch. One label per segment, or it raises.- Wrong colour. It's BGR.
(0, 0, 255)is red. - The contrib trap. If you install a plain
opencv-pythonwheel over the contrib one, all four OpenCV distributions share onesite-packages/cv2and the contrib submodules silently empty out. The pack shipstools/repair_opencv_contrib.py- run it with--check, then--apply- which is worth knowing if a Contrib-category node of this pack ever vanishes after you installed something else.
One last framing note: this pack is the OpenCV toolbox inside ComfyUI - the deterministic pixel operations that predate any of the models you're running. It's also, by the author's own very loud disclaimer, LLM-generated and explicitly not production-grade. For a debug renderer, that's a fine trade.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| source | COMFY_MATCHTYPE_V3 | Image or mask to draw on (a copy is made). Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size. | |
| segments | NPARRAY | Nx1x4 or Nx4 endpoint quadruples (x1, y1, x2, y2); cv2_HoughLinesP plugs in directly. | |
| thickness | INT | 21–64 | Line thickness in pixels. |
| color | STRING | (0, 255, 0) | Color as a single value (broadcast to all channels) or BGR tuple, e.g. '255' or '(0, 255, 0)'. Shorter tuples are zero-padded; longer tuples are truncated. Ignored when labels are connected. |
| labelsopt | NPARRAY | (N,) integer labels: one color per cluster. | |
| line_styleopt | COMBO | solid | Stroke pattern. Colour alone cannot separate two overlaid line sets for a colour-blind viewer or in greyscale - give the second set a different style and the picture reads without the palette. 'solid' is cv2's own line. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | COMFY_MATCHTYPE_V3 | Same format as the image input. |
| count | INT | How many segments were drawn - branch on it with if/else for the nothing-found case. |