Hough Accumulator
Implement a Hough accumulator array for line detection given a list of edge points. The goal is to build a 2D voting array indexed by θ and ρ to detect lines in an image.
The Hough transform is a feature extraction technique used in image processing to detect lines, circles, and other shapes. It works by transforming image points into a parameter space, where each point in the image votes for all possible lines that could pass through it. The Hough accumulator is a 2D array where each cell represents a possible line in the image, parameterized by θ (angle) and ρ (distance from origin).
Here are the steps to build the accumulator:
- For each edge point (x,y)
- For each θ bin (0° to 180°)
- Compute ρ=x⋅cos(θ)+y⋅sin(θ)
- Map ρ to a bin index and increment that cell
This technique is widely used in computer vision for line detection and image processing.
Example:
edge_points = [(0, 0), (1, 1), (2, 2)] theta_bins = 4 rho_bins = 5 max_rho = 3
[[1, 1, 1, 1, 1], [0, 1, 2, 1, 0], [0, 0, 1, 2, 1], [0, 1, 1, 1, 1]]
-
Theta angles: 0°, 45°, 90°, 135° (4 bins from 0 to π)
-
Rho range: [-3, 3] mapped to 5 bins
-
For point (0,0): ρ=0 for all θ → votes in middle bin
-
For point (1,1):
- θ=0°: ρ=1 → bin 3
- θ=45°: ρ=√2≈1.41 → bin 3-4
- θ=90°: ρ=1 → bin 3
- θ=135°: ρ=0 → bin 2
-
For point (2,2): similar pattern
The collinear points create a peak at θ=45° (or 135°), showing their line.
Constraints:
- edge_points is a list of (x, y) coordinates
- theta_bins is the number of θ bins (covering 0 to π)
- rho_bins is the number of ρ bins
- max_rho is the maximum absolute ρ value
- Return 2D accumulator array of shape (theta_bins, rho_bins)
More from CV: Feature Detection and Matching
The task is to implement the Hough line transform accumulator: for each edge point, vote in a 2D array over angle \theta and distance ρ, counting how many points support each possible line.
1. Background Knowledge (Concepts & Theory)
- A straight line in image (Cartesian) coordinates (x,y) can be written in Hough form:
where:
-
ρ is the perpendicular distance from the origin to the line.
-
\theta is the angle of the line’s normal vector with the x-axis.
-
The Hough transform maps points in image space to curves in parameter space (\theta,ρ).
-
One image point lies on infinitely many lines → in (\theta,ρ) space this is represented as a sinusoidal curve.
-
If many points lie on the same geometric line, their curves intersect at a common (\theta,ρ). Counting votes in a 2D accumulator lets you find peaks that correspond to actual lines in the image.
-
Because images are discrete and bounded, you:
-
Discretize \theta into bins in [0∘,180∘).
-
Discretize ρ into bins in [−ρmax,ρmax], where
- Use a 2D array acc[theta_idx][rho_idx] to count votes.
2. Algorithm / General Approach
Pattern for this problem:
- Precompute discretization:
- Choose number of \theta bins (numTheta).
- Derive number of ρ bins (numRho) from image size and desired resolution.
- Precompute trigonometry:
- For each \theta-bin, precompute cos(theta) and sin(theta).
- Iterate over all edge points:
- For each point (x,y) and for every \theta-bin:
- Compute continuous ρ.
- Map ρ to a discrete bin index.
- Increment the corresponding accumulator cell.
- Optionally, peak detection on the accumulator gives detected lines (not required for just building the accumulator).
This is a nested-loop voting algorithm: outer loop over points, inner loop over parameter bins, updating a shared 2D histogram.
3. Step-by-Step Strategy (Implementation Outline)
Assume you’re given:
- Image width, height
- List of edge points edges = [(x1, y1), (x2, y2),...]
- numTheta and numRho (or at least numTheta and you derive numRho)
1) Define parameter ranges
import math
max_rho = math.sqrt(width**2 + height**2)
# theta in [0, 180)
num_theta = N_theta # e.g. 180 or 360 depending on resolution
theta_step = math.pi / num_theta # radians per bin
# rho in [-max_rho, max_rho]
num_rho = N_rho # choose resolution; e.g. int(2 * max_rho) or so
rho_step = (2 * max_rho) / num_rho
2) Precompute sin/cos for each θ-bin
cos_t = [math.cos(i * theta_step) for i in range(num_theta)]
sin_t = [math.sin(i * theta_step) for i in range(num_theta)]
3) Initialize the accumulator
# 2D array: theta index × rho index
acc = [[0 for _ in range(num_rho)] for _ in range(num_theta)]
4) Voting loop
Core idea: map continuous ρ to an integer bin:
rho_idx=⌊rho_stepρ+ρmax⌋for (x, y) in edges:
for t_idx in range(num_theta):
rho = x * cos_t[t_idx] + y * sin_t[t_idx] # continuous
rho_idx = int((rho + max_rho) / rho_step) # shift to [0, 2*max_rho]
if 0 <= rho_idx < num_rho:
acc[t_idx][rho_idx] += 1
At the end, acc is your Hough accumulator.
4. Common Pitfalls
-
Wrong coordinate origin:
-
Make sure (x,y) are defined consistently with your Hough equation.
-
Many implementations use origin at the image center instead of top-left; if the problem assumes one, stick to that consistently.
-
Incorrect ρ indexing / negative ρ:
-
ρ can be negative. You must shift by +max_rho before dividing by rho_step to get a non-negative index.
-
Check boundary conditions so rho_idx never goes outside [0, num_rho-1].
-
Angle units:
-
Use radians for sin/cos in code, even if conceptual description uses degrees.
-
Ensure the mapping from theta_idx to actual angle is correct:
theta = theta_idx * theta_step # theta_step in radians
-
Too coarse or too fine bin sizes:
-
Very coarse bins → accumulator too “blurry”, peaks are weak or merged.
-
Extremely fine bins → accumulator huge and sparse, expensive and noisy.
-
Performance issues:
-
Complexity is O(N_\text{points} \times N_\theta). With many points and large numTheta, this is expensive; precomputing sin/cos helps, and sometimes you limit theta range using gradient orientation (not required here but common in practice).
5. Time & Space Complexity
Let:
-
P = number of edge points
-
T = number of \theta-bins (numTheta)
-
R = number of ρ-bins (numRho)
-
Time Complexity:
-
Outer loop over all points: P
-
Inner loop over all angles: T
-
Constant work inside (a few arithmetic ops, one array increment).
-
Overall:
- Space Complexity:
- Accumulator is a 2D array of size T×R.
- Auxiliary arrays for sin/cos are size T.
- Overall dominated by accumulator: