Computer Vision Hough Transform

The Hough Transform finds straight lines and circles in an edge image, even when parts of the shape are missing or noisy. Road lane markings, document edges, and coins on a table all become easy targets. The method turns a hard search problem into a simple voting contest.

The Voting Idea

Imagine a classroom where every edge pixel is a student. Each student writes down every straight line that could pass through their position and casts one vote for each. Lines that many students share collect the most votes. The line with the highest tally wins, because many pixels agree on it.

Edge pixels:        Votes collected per line:

 .                  line A  |||||||||||  (11 votes)  <- winner
   .                line B  |||          (3 votes)
     .              line C  ||           (2 votes)
       .
         .

Describing a Line With Two Numbers

A vertical line breaks the familiar slope equation, so the transform uses polar form. Two numbers describe any line.

rho   = shortest distance from the image corner to the line
theta = angle of that shortest path

Line equation:  rho = x cos(theta) + y sin(theta)

Each edge pixel draws a wave-shaped curve in a table of rho and theta values. Pixels that sit on the same real line draw curves that cross at one shared cell.

The Accumulator Grid

The table that collects votes is called the accumulator. Rows hold rho values and columns hold theta values.

            theta ->
          0   30   60   90  120  150
rho  10   .    .    1    .    .    .
     20   .    1    .    .    2    .
     30   1    .    .   14    .    .   <- bright cell = strong line
     40   .    .    1    .    .    1

The cell with 14 votes marks a clear line. A threshold setting decides how many votes count as a real line.

Detecting Lines in Code

Edge detection comes first, since the transform needs edge pixels as input.

import cv2
import numpy as np

img = cv2.imread("road.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150)

lines = cv2.HoughLinesP(edges, rho=1, theta=np.pi / 180,
                        threshold=80, minLineLength=40,
                        maxLineGap=10)

if lines is not None:
    for x1, y1, x2, y2 in lines[:, 0]:
        cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)

Standard and Probabilistic Versions

  • HoughLines returns endless lines described by rho and theta
  • HoughLinesP returns real segments with start and end points and runs faster

Parameter Guide

Parameter        Meaning                          Effect of raising it
---------------  -------------------------------  ----------------------
threshold        votes needed for a line          fewer, stronger lines
minLineLength    shortest segment accepted        drops short fragments
maxLineGap       largest gap that gets joined     merges broken segments

Detecting Circles

A circle needs three numbers: center x, center y, and radius. Votes now fill a three-part table, so OpenCV uses a smarter gradient-based method to keep the work light. Blur the image first to avoid false circles.

gray = cv2.medianBlur(gray, 5)
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, dp=1.2,
                           minDist=30, param1=100, param2=40,
                           minRadius=10, maxRadius=80)

if circles is not None:
    for x, y, r in np.round(circles[0]).astype(int):
        cv2.circle(img, (x, y), r, (0, 255, 0), 2)
  • minDist sets the smallest gap between circle centers
  • param2 acts as the vote threshold; lower values find more circles and more false ones
  • minRadius and maxRadius narrow the search and speed it up

Real-World Uses

  • Lane marking detection in driver assistance
  • Straightening tilted scanned pages
  • Counting coins, bolts, and bottle caps
  • Finding the horizon line in outdoor photos

Limits to Remember

Cluttered backgrounds produce many false lines. Large images slow the voting step, so resize first or crop a region of interest. Good edge maps decide the quality of every Hough result, so tune Canny thresholds before touching Hough settings.

Real-World Walkthrough: Finding Lane Lines

A dashboard camera records a road. The pipeline converts each frame to grayscale and runs Canny edge detection. A triangular mask keeps only the road area in front of the car, which removes trees and buildings. The probabilistic transform reports short segments along the painted markings. Averaging the slopes of left and right segments produces two clean lane lines.

Frame -> Grayscale -> Canny -> Road mask -> HoughLinesP -> Average slopes -> Two lane lines

Common Mistakes

  • Feeding a color photo straight into the transform without edge detection
  • Setting the vote threshold too low and receiving hundreds of false lines
  • Skipping the blur before circle detection
  • Searching the entire image when a smaller region of interest would do

Practice Exercise

Photograph a sheet of ruled paper on a desk. Detect the printed lines, measure their average angle, and rotate the image to straighten the page. The same trick fixes tilted scans before text recognition.