CV Detect Line Segments (FLD)
The line detector that can merge its own pieces
- image
- segments
- lengths
- count
FLD - the Fast Line Detector from OpenCV's ximgproc contrib module - is the third of the line-segment families this pack exposes, and it's the one I'd reach for by default. It runs Canny, chains edge pixels, and splits each chain where the chain stops being straight. The output is a clean list of segments. No voting, no accumulation, no "infinite lines then cut them to size".
Why this one over Hough or LSD
The node description lays out the comparison better than most docs do, so here it is in plain terms:
- HoughLinesP votes for infinite lines and then cuts them afterwards. It fuses collinear edges nicely, and it makes you tune three thresholds to get there.
- LSD works directly on the gradient field, with no edge-detection step, and reports a width and a false-alarm number per segment. Precise, slower, and it has no length knob at all - you post-filter if you want to drop threes and keep doors.
- FLD is the fast one, has an explicit
length_threshold, and - the useful bit - can merge collinear neighbouring segments back together (do_merge). LSD will not do that. So an edge broken into five pieces by noise and JPEG artefacts comes back as one segment.
That merge behaviour is the feature you'll notice first in practice, especially on long architectural lines and anything captured from video.
The inputs that matter
image- the original image, converted to grayscale internally.length_threshold(default 10, minimum 3) - the detector itself discards segments shorter than this. Raise it to keep only structural edges.distance_threshold(default 1.414214) - how far a pixel can sit from the hypothesised line before it counts as an outlier and ends the segment. Small gives you many short straight pieces; large gives you fewer, looser segments that bend around curves.canny_th1/canny_th2(default 50 each) - the hysteresis of FLD's internal Canny.canny_aperture_size- a combo:3 (default),5,7, or0 - the input IS an edge map. That last option is the interesting one: it skips Canny entirely and treats your input as a binary edge map, so you can drive FLD fromCV Edge Drawing'sedge_map,cv2_Canny, or any thresholded-gradient node in the pack. It's the only line detector here that can be used that way.do_merge(default off) - turn it on to join collinear, adjacent segments.min_length(optional, default 0) - a post-filter on the measured length, applied after merging. Note the distinction in the tooltip:length_thresholdgates the detector,min_lengthgates the result, and they stop meaning the same thing oncedo_mergeis on.
Outputs are segments (Nx4 float32 (x1, y1, x2, y2) - the same layout HoughLinesP and LSD produce, so CV Draw Segments plugs straight in), lengths ((N,) in pixels, which is what you actually came for if you're measuring anything), and count for branching. Finding nothing is valid: count = 0 and empty arrays, never an error.
The classic workflow
Canny or threshold → FLD → filter by lengths (drop the specks) → CV Draw Segments to check yourself, or feed the endpoints into the geometry nodes. If you're measuring a structure rather than drawing it, lengths is the output to do arithmetic on: sort it, take the top percentile, and you have the structural lines of a facade or a document without ever touching a threshold on the image.
Install
# 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
Python ≥ 3.12 and a recent ComfyUI (V3 node API) are hard requirements. The one dependency is opencv-contrib-python-headless~=5.0.0.93, and this node lives in the contrib module, so the contrib-ness is not theoretical: if you install a plain opencv-python over the top, all four OpenCV distributions share one site-packages/cv2 and the contrib submodules empty out, taking this node with them. The pack ships a repair tool for exactly that:
python tools/repair_opencv_contrib.py --check
python tools/repair_opencv_contrib.py --apply
When it disappoints
- One long line, reported as twelve pieces. Turn on
do_merge. - Segments bending around curves.
distance_thresholdtoo high - it's letting the line chase the curve. Lower it. - Everything is a segment.
length_thresholdtoo low, or your internal Canny thresholds are too low. Also remembermin_lengthonly filters after the fact. - Empty result on a busy image. Check you didn't set
canny_aperture_sizeto 0 while feeding it a photograph rather than an edge map - with Canny skipped, a grayscale photo is mostly "not an edge", and you get nothing.
bmad4ever's pack is a fork of geroldmeisinger's opencv-comfyui rewritten on the modern node API, and the author is upfront that it was written with heavy LLM assistance and isn't production-grade. This node is a thin, honest wrapper around a well-documented OpenCV class - the kind of component the disclaimer barely applies to.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| image | NPARRAY,IMAGE | Image to search (converted to grayscale internally). Feed the ORIGINAL image - unless canny_aperture_size is 0, in which case feed a BINARY edge map. 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. | |
| length_threshold | INT | 103–10000 | Segments shorter than this many pixels are discarded by the detector itself (unlike LSD, which has no length knob and needs a post-filter). Raise it to keep only structural edges. |
| distance_threshold | FLOAT | 1.40–100 | A pixel farther than this from the hypothesised line is an outlier, which ends the segment. Small = many short straight pieces; large = fewer, looser segments that bend. |
| canny_th1 | FLOAT | 500–1000 | Lower hysteresis threshold of the INTERNAL Canny. Ignored when canny_aperture_size is 0. |
| canny_th2 | FLOAT | 500–1000 | Upper hysteresis threshold of the internal Canny. Ignored when canny_aperture_size is 0. |
| canny_aperture_size | COMBO | 3 (default) | Sobel aperture of the internal Canny. '0' skips Canny entirely and treats the input as an edge map, so you can drive FLD from any edge node in the pack. |
| do_merge | BOOLEAN | false | Incrementally merge segments that are collinear and adjacent, so one long edge broken by noise comes back as one segment instead of a chain of pieces. |
| min_lengthopt | FLOAT | 00–10000 | Post-filter on the measured length, applied after any merging - length_threshold gates the detector, this gates the RESULT (they differ once do_merge is on). 0 keeps every segment. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| segments | NPARRAY | Nx4 float32 (x1, y1, x2, y2) endpoints - the same layout HoughLinesP and LSD produce, so 'OpenCV Draw Segments' plugs straight in. |
| lengths | NPARRAY | (N,) float32 segment length in pixels. |
| count | INT | How many segments survived - branch on it with if/else for the nothing-found case. |