Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draw fitted line (OpenCV)

I'm using OpenCV to fit a line from a set of points using cvFitLine()

cvFitLine() returns a normalized vector that is co-linear to the line and a point on the line. See details here

Using this information how can I get the equation of a line so that I can draw the line?

like image 425
Sunny Avatar asked May 01 '10 17:05

Sunny


People also ask

How do you draw a line with an angle in OpenCV?

x = (int)round(P1. x + length * cos(angle * CV_PI / 180.0)); P2. y = (int)round(P1. y + length * sin(angle * CV_PI / 180.0));

How do you draw a polygon in OpenCV?

Step 1: Import cv2 and numpy. Step 2: Define the endpoints. Step 3: Define the image using zeros. Step 4: Draw the polygon using the fillpoly() function.


2 Answers

This just spells out @brainjam's answer in python for any passers by.

The formula for a line using a unit vector (vx, vy) and some point on the line (x0, y0) is:

(x, y) = (x0, y0) + t*(vx, vy)

The return from cv2.fitLine() is:

np.array([vx, vy, x0, y0])

In the example case, I have a line spanning the height of my image, so I want to find the t0 and t1 that intersect with y=0 and y=img.shape[0] (the top/bottom boundaries).

# get the fitLine for your set of points in the array, `line`
fit_line = cv2.fitLine(line, cv2.DIST_L2, 0, 0.01, 0.01)

# compute t0 for y=0 and t1 for y=img.shape[0]: (y-y0)/vy
t0 = (0-fit_line[3])/fit_line[1]
t1 = (img.shape[0]-fit_line[3])/fit_line[1]

# plug into the line formula to find the two endpoints, p0 and p1
# to plot, we need pixel locations so convert to int
p0 = (fit_line[2:4] + (t0 * fit_line[0:2])).astype(np.uint32)
p1 = (fit_line[2:4] + (t1 * fit_line[0:2])).astype(np.uint32)

# draw the line. For my version of opencv, it wants tuples so we
# flatten the arrays and convert
# args: cv2.line(image, p0, p1, color, thickness)
cv2.line(img, tuple(p0.ravel()), tuple(p1.ravel()), (0, 255, 0), 10)
like image 96
Hendy Avatar answered Sep 19 '22 05:09

Hendy


If cvFitLine() returns normalized vector (vx,vy) and point (x0,y0), then the equation of the line is

(x,y) = (x0,y0) + t*(vx,vy)

where t runs from −∞ to +∞.

This is what you asked for, but probably isn't immediately helpful in drawing the line. You would want to clip it either to the screen boundaries, or perhaps the bounding box of the the original set of points. To clip a line to a rectangle, just solve for values of t where the line crosses the boundary of the rectangle.

like image 39
brainjam Avatar answered Sep 22 '22 05:09

brainjam