# 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.

`def line_end_points_on_image(rho: float, theta: float, image_shape: tuple):    """    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)]    """    m, b = polar2cartesian(rho, theta, True)    end_pts = []    if not np.isclose(m, 0.0):        x = int(0)        y = int(solve4y(x, m, b))        if point_on_image(x, y, image_shape):            end_pts.append((x, y))            x = int(image_shape[1] - 1)            y = int(solve4y(x, m, b))            if point_on_image(x, y, image_shape):                end_pts.append((x, y))    if m is not np.nan:        y = int(0)        x = int(solve4x(y, m, b))        if point_on_image(x, y, image_shape):            end_pts.append((x, y))            y = int(image_shape[0] - 1)            x = int(solve4x(y, m, b))            if point_on_image(x, y, image_shape):                end_pts.append((x, y))    return end_ptsdef solve4x(y: float, m: float, b: float):    """    From y = m * x + b         x = (y - b) / m    """    if np.isclose(m, 0.0):        return 0.0    if m is np.nan:        return b    return (y - b) / mdef solve4y(x: float, m: float, b: float):    """    y = m * x + b    """    if m is np.nan:        return b    return m * 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.

`def hough_lines_end_points(lines: np.array, image_shape: tuple):    """    Returns end points of the lines on the edge of the image    """    if len(lines.shape) == 3 and \            lines.shape[1] == 1 and lines.shape[2] == 2:        lines = np.squeeze(lines)    end_pts = []    for line in lines:        rho, theta = line        end_pts.append(            line_end_points_on_image(rho, theta, image_shape))    return end_ptsdef hough_lines_intersection(lines: np.array, image_shape: tuple):    """    Returns the intersection points that lie on the image    for all combinations of the lines    """    if len(lines.shape) == 3 and \            lines.shape[1] == 1 and lines.shape[2] == 2:        lines = np.squeeze(lines)    lines_count = len(lines)    intersect_pts = []    for i in range(lines_count - 1):        for j in range(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)            if point_on_image(x, y, image_shape):                intersect_pts.append([x, y])    return np.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.

Computer Vision | Machine Learning | Deep Learning https://arccoder.github.io/

Computer Vision | Machine Learning | Deep Learning https://arccoder.github.io/

Get the Medium app