# Process the output of **cv2.HoughLines**

There are a lot of articles that show how to detect lines using cv2.HoughLines. In this post I will present some functions that will help you process the lines.

# Polar to Cartesian coordinate system

cv2.HoughLines returns lines in Polar coordinate system. Converting them to Cartesian coordinate system helps in calculating points on the line and point of intersection between two lines.

*y = m * x + b* … [1]

**def **polar2cartesian(rho: float, theta_rad: float, rotate90: bool = **False**):

*"""*

Converts line equation from polar to cartesian coordinates

Args:

rho: input line rho

theta_rad: input line theta

rotate90: output line perpendicular to the input line

Returns:

m: slope of the line

For horizontal line: m = 0

For vertical line: m = np.nan

b: intercept when x=0

"""

x = np.cos(theta_rad) * rho

y = np.sin(theta_rad) * rho

m = np.nan

**if not **np.isclose(x, 0.0):

m = y / x

**if **rotate90:

**if **m **is **np.nan:

m = 0.0

**elif **np.isclose(m, 0.0):

m = np.nan

**else**:

m = -1.0 / m

b = 0.0

**if **m **is not **np.nan:

b = y - m * x

**return **m, b

The Cartesian line equations can be used to find points on the edge of the image that lie on the line detected by cv2.HoughLines.

In equation [1], substituting *x* equal to 0 and the width of the image will get us the *y* coordinate. Similarly, setting *y* equal to 0 and the height of the image will get us *x* coordinates of the edge.

defline_end_points_on_image(rho: float, theta: float, image_shape: tuple):

"""m, b = polar2cartesian(rho, theta,

Returns end points of the line on the end of the image

Args:

rho: input line rho

theta: input line theta

image_shape: shape of the image

Returns:

list: [(x1, y1), (x2, y2)]

"""

True)

end_pts = []

if notnp.isclose(m, 0.0):

x = int(0)

y = int(solve4y(x, m, b))

ifpoint_on_image(x, y, image_shape):

end_pts.append((x, y))

x = int(image_shape[1] - 1)

y = int(solve4y(x, m, b))

ifpoint_on_image(x, y, image_shape):

end_pts.append((x, y))

ifmis notnp.nan:

y = int(0)

x = int(solve4x(y, m, b))

ifpoint_on_image(x, y, image_shape):

end_pts.append((x, y))

y = int(image_shape[0] - 1)

x = int(solve4x(y, m, b))

ifpoint_on_image(x, y, image_shape):

end_pts.append((x, y))

returnend_ptsdefsolve4x(y: float, m: float, b: float):

"""

From y = m * x + b

x = (y - b) / m

"""

ifnp.isclose(m, 0.0):

return0.0

ifmisnp.nan:

returnb

return(y - b) / mdefsolve4y(x: float, m: float, b: float):

"""

y = m * x + b

"""

ifmisnp.nan:

returnb

returnm * x + b

To check if the points lie on the image we use this.

**def **point_on_image(x: int, y: int, image_shape: tuple):

*"""*

Returns true is x and y are on the image

"""

**return **0 <= y < image_shape[0] **and **0 <= x < image_shape[1]

# Point of Intersection

Using the line equation in Cartesian coordinates the point of intersection of the lines can be found by considering *y*’s are equal and solving for *x*.

*m1 * x + b1 = m2 * x + b2 x = (b2 — b1)/(m1 — m2)*

Then substituting the value of *x* in [1] and solving for *y*.

**def **intersection(m1: float, b1: float, m2: float, b2: float):

*# Consider y to be equal and solve for x*

# Solve:

# m1 * x + b1 = m2 * x + b2

x = (b2 - b1) / (m1 - m2)

*# Use the value of x to calculate y*

y = m1 * x + b1

**return **int(round(x)), int(round(y))

The above functions can be used to find end points of the Hough lines on the image edge and points of intersection of all possible combinations of lines returned from cv2.HoughLines.

defhough_lines_end_points(lines: np.array, image_shape: tuple):

"""

Returns end points of the lines on the edge of the image

"""

iflen(lines.shape) == 3and\

lines.shape[1] == 1andlines.shape[2] == 2:

lines = np.squeeze(lines)

end_pts = []

forlineinlines:

rho, theta = line

end_pts.append(

line_end_points_on_image(rho, theta, image_shape))

returnend_ptsdefhough_lines_intersection(lines: np.array, image_shape: tuple):

"""

Returns the intersection points that lie on the image

for all combinations of the lines

"""

iflen(lines.shape) == 3and\

lines.shape[1] == 1andlines.shape[2] == 2:

lines = np.squeeze(lines)

lines_count = len(lines)

intersect_pts = []

foriinrange(lines_count - 1):

forjinrange(i + 1, lines_count):

m1, b1 = polar2cartesian(lines[i][0], lines[i][1],True)

m2, b2 = polar2cartesian(lines[j][0], lines[j][1],True)

x, y = intersection(m1, b1, m2, b2)

ifpoint_on_image(x, y, image_shape):

intersect_pts.append([x, y])

returnnp.array(intersect_pts, dtype=int)

The functions that you see in this post can be found in this gist to use as a python module in your project.

Hope this module helps you in some way. Please let me know if you would like to see more functions that would be helpful in processing the output from cv2.HoughLines.

Here is an application to straighten a page image using the code discussed above.