cv2.HoughLinesWithAccumulator
Line detection that tells you how sure it is
- image
- nparray
cv2.HoughLines gives you each line as (rho, theta) and nothing else. This variant appends the accumulator value, so every line arrives as (rho, theta, votes). That one number is the difference between "a line exists" and "a line exists and I can tell the wall from the wallpaper."
Line detection on real images returns a long tail of weak, nearly-parallel detections from texture. The usual fix is to raise threshold until the tail disappears - which also deletes the genuinely faint lines you cared about, and then no threshold is right for the whole image. Votes let you keep the threshold permissive and rank instead: take the top five lines by vote count, or branch on "is there any line above 200 votes". Same trick the circles equivalent uses.
How it works
Classic Hough internals: every edge pixel votes into a (rho, theta) accumulator, peaks become lines. rho is the distance resolution in pixels (1 is the usual value, the widget starts at an unusable 0), theta in radians (0.01745, one degree, is standard), threshold the minimum votes for a line to be returned at all. The accumulator value that comes back with each line is its score - the counts of agreeing edge pixels along that line.
Then the extras, which are the OpenCV-5 part of the API and worth knowing: srn / stn are the multi-scale distance and angle divisors for the multi-scale transform (0 keeps you single-scale), min_theta / max_theta restrict the angle search, and use_edgeval switches on the weighted transform so that strong edges outvote weak ones instead of counting equally. Since the whole point of this node is the score, use_edgeval is the most interesting of the four.
Note the frame behavior: like its siblings, this one reads frame 0 of a batch - it is not in the pack's list of per-frame functions, so split a batch before feeding it.
Inputs and outputs
image- 8-bit single-channel binary edge map. Runcv2.Cannyupstream. A colour IMAGE link is converted to gray automatically, but gray is not the same as edges, and this function votes on edges.rho,theta,threshold- as above; all three start at 0 and need real values.srn,stn,min_theta,max_theta,use_edgeval- optional knobs, all preset to OpenCV's own defaults.
Output is one nparray of (rho, theta, votes) rows, ordered by strength. It is polar, so it is data: CV Array To Text to read the numbers, Preview CV Array for a look at the distribution, cv2.sortIdx / CV Take By Index to keep the strongest, and the output layout matches the image-based HoughLines except for the extra column - if you plan to mix them, do not assume a shared shape.
Expect this node to be missing from your UI on older OpenCV builds. The pack's registry is generated from cv2's stubs and probed against the installed build, so functions a build does not expose simply produce no node rather than a broken one. Behavior is curated against opencv-contrib-python-headless~=5.0.0.93.
Install
Manager → search comfyui_cv (bmad4ever), or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"
Python ≥ 3.12 and a recent ComfyUI on the V3 node API. One dependency, zero models, and the whole pack is a fork of geroldmeisinger/opencv-comfyui rebuilt on the newer V3 node API.
When it goes wrong
- Votes are not comparable across images, resolutions or settings. They scale with edge density,
thetaresolution and image size. Rank within a run; do not ship a "> 100 votes is a real line" rule. - Hundreds of near-duplicate lines. Standard Hough behaviour on thick edges - both sides of one edge vote, and neighbouring accumulator cells all clear the threshold. Raise
thetaorthreshold, or switch tocv2.HoughLinesP, whoseminLineLengthandmaxLineGapare far easier to reason about, and whose endpoint output draws directly withCV Draw Segments. rhoorthetaat 0. The widgets default to 0 and the value is passed through, so an accumulator with zero resolution gets built and you get nothing. Set 1 and 0.01745.- Gray photo in, nothing out. Feed a Canny or lineart-style edge map, not a photograph (
controlnet.mdcovers the edge-map family if you want a mental model of what good structure looks like). - Frame 0 only. Batch inputs collapse; slice with
CV Unstack Batchfor per-frame work. - Empty output is a valid result. Branch on it with a
count-style check rather than letting downstream nodes assume lines.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| image | NPARRAY,IMAGE,MASK | - - - 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. | |
| rho | FLOAT | 0.0000-1e+38–1e+38 | - - - |
| theta | FLOAT | 0.0000-1e+38–1e+38 | - - - |
| threshold | INT | 0-2147483648–2147483647 | - - - |
| srnopt | FLOAT | 0.0000-1e+38–1e+38 | - - - Preset to the OpenCV default (0.0). |
| stnopt | FLOAT | 0.0000-1e+38–1e+38 | - - - Preset to the OpenCV default (0.0). |
| min_thetaopt | FLOAT | 0.0000-1e+38–1e+38 | - - - Preset to the OpenCV default (0.0). |
| max_thetaopt | FLOAT | 3.1416-1e+38–1e+38 | - - - Preset to the OpenCV default (3.141592653589793). |
| use_edgevalopt | BOOLEAN | false | - - - Preset to the OpenCV default (False). |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| nparray | NPARRAY | — |