cv2.fitLine
The dominant direction through a point set
- points
- nparray
cv2.fitLine answers a question you'll hit constantly once you start measuring images: given a set of points that should lie on a line, what line is that? Use it to deskew a scanned page, to find the horizon in a landscape, to measure the angle of a rail or a shelf, or to sanity-check that the Hough lines you detected are all telling the same story.
It's a raw wrapper in ComfyUI CV (bmad4ever), the pack that exposes OpenCV 5.0 as ComfyUI nodes. Quality-of-life warning that applies to the whole low-level layer: the author states the pack was created with heavy LLM assistance and that the raw wrappers are uncurated by design - you get OpenCV's signature, OpenCV's defaults and NPARRAY sockets, and you're expected to know what the parameters mean. For fitLine that means knowing it returns a line, not a segment.
What comes out - and what doesn't
One output: nparray. It is four numbers for a 2D fit - the normalized direction vector (vx, vy) followed by a point on the line (x0, y0) (six numbers if you fed it a 3D cloud). That's it. There are no endpoints, and this trips people up constantly, because a "fit a line" node looks like it should give you two points you can hand to a drawing node.
To draw it you have to construct the segment yourself: pick a length, step from the anchor point along the direction, and build the two endpoints. The pack's array utilities do this in nodes (CV Slice Array to pull components out, CV Concat Arrays to build the endpoint array, CV Points for literals), and you can then draw with cv2.line or the segment/connection drawing nodes. If your real goal is "show me the lines I found in this image", the pack's curated CV Detect Lines (Hough) node - Canny plus probabilistic Hough in one step - is far less work.
The five inputs
points- NPARRAY only (the tooltip says data array, not image). Nx1x2 or Nx1x3 floats: cv2 fits 2D or 3D point sets with this same function, so a 3D cloud works too. Two points is the mathematical minimum; a few hundred noisy ones is the realistic case. Build it from CV Contour To Points, a keypoint set, or CV Annotate Points.distType- a dropdown over the M-estimator family:DIST_L2(the default),DIST_L1,DIST_C,DIST_L12,DIST_FAIR,DIST_WELSCH,DIST_HUBER.L2is plain least squares: the right pick for clean points, and a magnet for outliers.L1/Care the robust options when a few points clearly don't belong. The rest are the iteratively reweighted estimators, whereparambecomes a tuning constant instead of a distance.param- cv2's numeric parameter for the chosen distance function; irrelevant forL2.reps/aeps- the radius and angle accuracy the iteration converges to, in pixels and radians. OpenCV's own documentation recommends0.01for both, and the problem is that this node's widgets default to 0, which is exactly the value that makes an iterative solver's stop condition meaningless. Type 0.01 in both fields. This is the one setting where the raw-wrapper defaults will bite you.
Install
ComfyUI Manager → ComfyUI CV (search that, not "OpenCV"), or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install -r comfyui_cv/requirements.txt
Python ≥3.12, current ComfyUI built on the V3 node API, restart when finished. Dependency is opencv-contrib-python-headless~=5.0.0.93; fitLine is core imgproc so it's present regardless, but the contrib-only categories (fisheye, aruco, ft, ximgproc) vanish if a plain opencv-python wheel has overwritten the shared cv2. The pack ships tools/repair_opencv_contrib.py --check / --apply for that.
Common issues
A line pointing the wrong way. Least squares through two clusters gives you the line between the clusters, not through either. That's the L2 outlier magnet; switch to DIST_L1 or pre-filter with CV Filter Points By Distance.
Direction vector looks tiny. It's normalized - the magnitude is 1 by construction. Scale it yourself to place endpoints at a distance.
Points in the wrong shape. cv2 rejects (3,) rows with unhelpful noise; CV Reshape Array exists in this pack specifically because of it ("required before cv2 arithmetic on (3,) rows").
Your fit disagrees with the Hough lines. Usually it's the point selection, not the fit: Hough returns infinite-length lines parameterised as (rho, theta), this returns a direction and a point. Compare angles rather than positions, then fix the geometry once you know which one you believe.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| points | NPARRAY | - - - A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. | |
| distType | COMBO | DIST_L2 | - - - |
| param | FLOAT | 0.0000-1e+38–1e+38 | - - - |
| reps | FLOAT | 0.0000-1e+38–1e+38 | - - - |
| aeps | FLOAT | 0.0000-1e+38–1e+38 | - - - |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| nparray | NPARRAY | — |