CV Detect Lines (Hough)
Canny, votes, and a drawing on the way out
- image
- overlay
- lines_only
CV Detect Lines (Hough) is the pipeline-simplification node: it runs Canny, then the probabilistic Hough transform, then draws what it found and hands you the overlay as an IMAGE.
Two cv2 calls, five tuning knobs and a lot of shape plumbing - which is exactly the kind of thing worth collapsing into one node. Reach for it for architectural lines, perspective correction (find the horizon and the vanishing edges), scan/document cleanup, or a quick "how straight is this" check on a rendered image.
How it works
Canny first, with hysteresis at canny_low / canny_high: gradients above the high threshold seed edges, gradients above the low one are kept only if they connect to a seed. Then HoughLinesP accumulates votes: every edge pixel votes for the lines passing through it, and a line that collects at least threshold votes becomes a candidate. The "P" is probabilistic - instead of returning infinite lines it returns actual endpoints, so what you get out is a set of segments, not the equations of lines.
That distinction matters downstream. A segment has a length, so min_length and max_gap can filter and merge; an infinite line has neither.
The inputs you'll actually touch
Required, in the order you'll touch them:
image- an IMAGE; a batch is processed frame by frame.canny_low(50) andcanny_high(150) - the edge pass. If you get no lines, this is the first place to look: on a low-contrast image, 50/150 may be selecting almost no edges at all.threshold(50) - minimum votes. Higher finds fewer, stronger lines. This is the real "how confident" knob.min_length(50) - drop segments shorter than this.max_gap(10) - how far two collinear segments can be apart before they count as one line.thickness(2) - line width in the drawn output.
Two outputs: overlay, the input with the segments drawn on it, and lines_only, the segments on black. Both are plain IMAGEs, so they go into Save Image or a preview with no conversion. Note this node draws for you - that's the difference between it and the raw cv2_HoughLinesP wrapper, which returns numbers. If you want the segments as data to feed a geometry node, use the wrapper, or reach for CV Detect Line Segments (LSD), which is built around returning the numbers.
Install
Part of comfyui_cv (bmad4ever/comfyui_cv). Search "ComfyUI CV" in ComfyUI Manager, or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"
Then restart ComfyUI. Python ≥ 3.12 and a recent ComfyUI on the V3 node API. The one dependency is pinned to a specific OpenCV build on purpose - the pack is curated against 5.0.0.93. Contrib is required, and this is the part that bites: all four OpenCV distributions share a single site-packages/cv2, so any other pack that installs opencv-python over your contrib wheel silently removes the contrib nodes. Diagnose with python tools/repair_opencv_contrib.py --check, repair with --apply. It's the most common real-world breakage of any OpenCV-based ComfyUI install - the "node pack won't load, cv2 import failed" threads online are nearly all this, not a missing runtime.
Common issues
- Nothing detected. Raise the Canny range down (try low 30 / high 100), or lower
threshold. Also check you didn't feed it an image that's already an edge map - Canny on a Canny output finds very little. - Everything detected. A noisy or heavily textured image generates edge pixels everywhere and Hough votes for all of them. Blur slightly first (a
cv2_GaussianBlurorcv2_medianBlurnode upstream), then raisethreshold. - The same physical line comes back as five segments. Raise
max_gapso collinear pieces get merged. - Lines bunch at the image edges. Canny's response at the border. Crop or pad before detection if it matters.
- Deterministic-ish, but not identical between runs. The probabilistic variant samples; don't expect bit-exact repeatability across OpenCV versions, and don't build a pipeline that depends on segment order.
For clean, single-pass edge geometry with no threshold to tune, CV Detect Line Segments (LSD) is the better tool - it works on the gradient field directly, so it won't fuse two collinear edges into one line, and it returns subpixel endpoints plus measured widths as data.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Input image. A batch is processed frame by frame. | |
| canny_low | FLOAT | 50.000–5000 | Lower Canny hysteresis threshold for the edge pass that feeds Hough; edges weaker than this are discarded. |
| canny_high | FLOAT | 150.000–5000 | Upper Canny hysteresis threshold; edges stronger than this are always kept. |
| threshold | INT | 501–10000 | Minimum number of votes - higher finds fewer, stronger lines. |
| min_length | FLOAT | 50.001–16384 | Minimum segment length in pixels. |
| max_gap | FLOAT | 10.000–1000 | Maximum gap between collinear segments to merge them. |
| thickness | INT | 21–64 | Line width in pixels used to draw the detected segments. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| overlay | IMAGE | — |
| lines_only | IMAGE | — |