The Hough Transform
Imagine a photo of a chessboard where an Edge Detection pass has marked thousands of edge pixels. It tells you nothing about which pixels belong to the same straight line. Broken edges, noise, and occlusion mean that no single pixel neighborhood reveals the global structure. Somehow a detector needs to look at all the fragments at once. It must ask: which lines, if drawn on this image, would explain the largest number of edge points simultaneously? The Hough Transform answers this by flipping the question from image space to parameter space. This lets every edge pixel "vote" for every line it could plausibly lie on. This reframing matters because most interesting shapes in computer vision are locally ambiguous but globally simple. Examples include lane markings on a road, the rims of coins, and barcode boundaries. A single edge pixel cannot tell you it is part of a circle. A histogram of votes across all possible circles can. The Hough Transform turns shape detection into a counting problem. Counting problems are robust: a shape corrupted by 40% missing points and heavy noise can still produce a clear peak in vote space. This happens because the surviving points still agree with each other, even though no contiguous piece of the shape survives intact. The technique originated in particle-physics bubble-chamber photograph analysis in the early 1960s. It was reintroduced to computer vision in the 1970s with the now-standard slope-intercept and polar parameterizations. It generalizes cleanly: lines, circles, ellipses, and even arbitrary shapes (via the Generalized Hough Transform) all fit the same voting template. This works provided the shape can be described by a small number of parameters. This article builds the transform from first principles. It covers dual spaces, the polar parameterization that fixes the vertical-line problem, and the accumulator array as the central data structure. It then walks through pseudocode, a full complexity and correctness analysis, and a hand-traced numeric example. It closes by connecting the idea to RANSAC Robust Estimation, the other major strategy for fitting models to noisy data.
- The Hough Transform detects parametric shapes (lines, circles) by having each edge point vote for every shape it could belong to.
- Votes accumulate in a discretized parameter space (the accumulator array); peaks correspond to detected shapes.
- The polar line parameterization avoids the infinite-slope problem of .
- Time complexity is for edge points and parameter samples per point; circles cost more because the parameter space has one more dimension.
- The method is robust to noise and partial occlusion because it aggregates evidence globally rather than locally.
- It is the classical precursor to RANSAC Robust Estimation, which handles higher-dimensional models more efficiently by sampling instead of exhaustive voting.
Every edge point does not know which line it belongs to, but it can vote for all lines it is consistent with — and the correct line is simply the one with the most votes.
The idea
The Hough Transform detects instances of a parametric curve family in an image by converting a detection problem in image space into a voting problem in parameter space. A shape family, such as the set of all lines, is described by a small tuple of parameters — slope and intercept, or radius and center. Every edge pixel in the image, if it lies on some instance of that shape, must satisfy the shape's equation for a specific parameter value. Because a single point does not know which instance it belongs to, it instead considers all parameter values consistent with its coordinates and casts a vote for each one. The parameter space is discretized into a grid called the accumulator array or Hough space. Each cell corresponds to one candidate parameter setting (e.g., one specific line or one specific circle). As edge points cast votes, cells corresponding to true shapes accumulate many votes — one from every point that actually lies on that shape — while cells corresponding to spurious combinations receive votes from unrelated, uncoordinated points and stay low. After all points have voted, the algorithm reports local maxima ("peaks") in the accumulator whose vote count exceeds a threshold; each peak is a detected shape instance. The key structural fact that makes this work is a point–curve duality. A point in image space, when substituted into the line equation, traces out a curve in parameter space (all lines through that point). Conversely, a point in parameter space corresponds to one specific line in image space. Collinear points in image space map to curves in parameter space that all intersect at the same point — the parameters of the shared line. Voting is simply an efficient, discretized way of finding that common intersection without solving simultaneous equations symbolically, which would be brittle under noise. This duality generalizes: for circles the parameter space is 3-D ; for ellipses it is 5-D; the Generalized Hough Transform extends the idea to arbitrary shapes using a lookup table (the R-table) instead of a closed-form equation.
How it works
Step 1 — Choose the parameterization. For lines, the naive form fails because vertical lines have . The standard fix is the normal (polar) form:
Here is the perpendicular distance from the origin to the line, and is the angle of that perpendicular. Every line has a finite, bounded representation: ranges over a bounded interval and ranges over where is the image diagonal.
Step 2 — Build the accumulator. Discretize into bins (e.g., 1° steps, so ) and into bins (e.g., 1-pixel steps across ). Initialize a 2-D integer array to zero.
Step 3 — Vote. For every edge pixel (typically pre-filtered by a gradient-magnitude threshold), and for every discretized angle , compute , round it to the nearest bin, and increment . Each edge point traces a sinusoidal curve through -space.
Step 4 — Find peaks. After all points vote, scan for local maxima above a threshold . Optionally apply non-maximum suppression in a neighborhood to avoid reporting near-duplicate lines from the same physical edge (which, because of pixel-level noise, often spreads votes across a few adjacent bins).
Step 5 — Recover the shapes. Each surviving peak is converted back to a line equation and, optionally, its finite extent is recovered by re-examining which edge pixels actually voted for that bin and taking their convex extent along the line. For circles, the equation has three unknowns. If the radius is known or restricted to a small range, the accumulator is 3-D over . A major efficiency gain uses the gradient direction at each edge pixel: since the gradient at a point on a circle points radially, each edge point only needs to vote along the line through in the gradient direction, for each candidate radius, rather than over all possible centers — this collapses the vote from a full circle of candidate centers to a single ray, drastically cutting redundant votes. ``` function HOUGH_LINES(edge_points, theta_bins, rho_bins, image_diag, threshold):
# edge_points: list of (x, y) coordinates of edge pixels
# theta_bins: number of angle samples over [0, pi)
# rho_bins: number of distance samples over [-image_diag, image_diag] A = new integer array of size [theta_bins][rho_bins], all zeros theta_step = pi / theta_bins rho_step = (2 * image_diag) / rho_bins
# precompute cos/sin tables once -- avoids re-evaluating trig NK times for k in 0 .. theta_bins - 1: cos_table[k] = cos(k theta_step) sin_table[k] = sin(k theta_step) for (x, y) in edge_points: for k in 0 .. theta_bins - 1: rho = x cos_table[k] + y sin_table[k] r_idx = round((rho + image_diag) / rho_step) # shift into [0, rho_bins) if 0 <= r_idx < rho_bins: A[k][r_idx] += 1 peaks = empty list for k in 0 .. theta_bins - 1: for r in 0 .. rho_bins - 1: if A[k][r] >= threshold and IS_LOCAL_MAX(A, k, r, window=5): theta = k theta_step rho = -image_diag + r * rho_step peaks.append( (theta, rho, A[k][r]) ) sort peaks by vote count descending return peaks
function IS_LOCAL_MAX(A, k, r, window): for dk in -window..window: for dr in -window..window: if (dk, dr) != (0, 0) and A[wrap(k+dk)][clip(r+dr)] > A[k][r]: return false return true ``` ``` function HOUGH_CIRCLES(edge_points, gradients, radii_range, a_bins, b_bins):
# gradients[i] is the gradient direction (unit vector) at edge_points[i] A = new integer array of size [a_bins][b_bins][len(radii_range)], all zeros for i in 0 .. len(edge_points) - 1: (x, y) = edge_points[i] (gx, gy) = gradients[i] # unit gradient direction for r in radii_range:
# candidate center lies along the gradient ray, distance r away,
# in EITHER direction (dark-on-light or light-on-dark boundary) for sign in (+1, -1): a = x - sign r gx b = y - sign r gy if in_bounds(a, b): A[bin(a)][bin(b)][index(r)] += 1 return TOP_PEAKS(A, threshold) ```
Complexity & correctness
Time complexity — lines. For edge points and angular samples, the voting loop performs work, since each point casts exactly one vote per angle bin. With typically a small constant (90–360), this is effectively in practice, though it should honestly be stated as . Peak-finding scans the accumulator, which has cells ( = number of bins), so total time is
Since (edge pixels) usually dominates (a few hundred by a few hundred accumulator cells) in images of interest, the transform scales linearly with the amount of edge evidence — a major advantage over combinatorial line-fitting (checking all point pairs, , and then verifying which other points are collinear with each pair, pushing worst-case cost to ).
Time complexity — circles. With a fixed radius, the accumulator is 2-D and cost is where is the number of candidate radii tried (or per fixed radius using the gradient-direction speedup, since each point votes along one ray instead of an entire circle of candidate centers). Without the gradient trick, a full 3-D brute-force circle Hough (voting for every possible center on the circle of radius around each edge point, for every candidate ) costs where is the number of angular samples used to trace out each candidate circle of centers — this is why the gradient-direction restriction (Step 5 above) is the standard practical implementation.
Space complexity. The accumulator requires for lines and for circles — the latter can become large enough (millions of cells) that coarse quantization or a hierarchical/multi-resolution accumulator is used in practice.
Correctness argument. The core invariant is: a cell in the accumulator receives one vote from point if and only if lies exactly on the shape instance that cell represents (up to quantization). This follows directly from substituting the discretized parameter values into the shape equation during voting — voting is literally evaluating "does this point satisfy this parameterized equation" and incrementing on success. Consequently, if a true line passes through edge points, the accumulator cell for receives exactly votes (modulo quantization spreading votes into 1–2 adjacent bins), while any other cell receives votes only from points that happen to be collinear with respect to a different, spurious line — an event whose expected count under a reasonably scattered noise/background distribution is much lower than for images with a real, well-supported line. This is why peak height serves as reliable evidence: it directly counts corroborating observations, and the corroboration is invariant to the order in which points appear, to gaps in the line (missing points do not create false votes elsewhere), and to a bounded amount of coordinate noise (which merely spreads the vote of a true point across a small neighborhood of bins rather than eliminating it).
Tradeoffs to be honest about. Bin resolution trades accuracy against discretization: too coarse a grid merges distinct nearby lines into one peak (or blurs estimates); too fine a grid spreads a true line's votes across many adjacent cells, weakening peak height and risking it falling below threshold — a phenomenon sometimes mitigated with Gaussian-smoothed accumulators before peak detection. The transform also does not exploit continuity or ordering along the curve, only feature membership, so it can hallucinate lines from coincidentally aligned but visually unrelated points in cluttered scenes (false positives grow with clutter density). Extending to shapes with more parameters (ellipses have 5) suffers a curse-of-dimensionality-like accumulator blow-up, which is exactly the pressure that motivates randomized sampling approaches like RANSAC Robust Estimation for higher-parameter models.
Worked example
Consider four edge points intended to lie on the line (so points like , , ), plus one noise point that does not lie on that line. Use 6 angle bins spanning , computing and rounding to the nearest integer.
| Point | θ=0° | θ=30° | θ=60° | θ=90° | θ=120° | θ=150° |
|---|---|---|---|---|---|---|
| (1, 2) | ρ=1.0 | ρ=1.87 | ρ=2.23 | ρ=2.0 | ρ=1.23 | ρ=0.13 |
| (2, 3) | ρ=2.0 | ρ=3.23 | ρ=3.60 | ρ=3.0 | ρ=1.60 | ρ=-0.23 |
| (3, 4) | ρ=3.0 | ρ=4.60 | ρ=4.96 | ρ=4.0 | ρ=1.96 | ρ=-0.60 |
| (5, 1) | ρ=5.0 | ρ=4.83 | ρ=3.37 | ρ=1.0 | ρ=-3.37 | ρ=-4.33 |
Rounding each to the nearest integer bin and tallying votes per cell:
- At : , , — no agreement here, these spread out.
- At : , , — partial agreement (2 votes at ).
- Checking the true angle more carefully: the line has slope 1, so its perpendicular angle is (not one of our coarse bins), and true . With only 30°-resolution bins, this line's votes spread between the 120° and 150° columns rather than stacking cleanly — illustrating the discretization tradeoff described above.
Refining to 5° resolution near would show all three collinear points' curves crossing almost exactly at , producing a clean peak with 3 votes, while 's sinusoidal curve passes nowhere near that cell — its votes land in unrelated bins across the table, never stacking with the other three. This is the expected behavior: finer angular resolution near the true parameter recovers a sharp peak, while a noise point's votes disperse rather than concentrate. The peak-finding step, run on the fine-resolution accumulator, would report with vote count 3, correctly identifying the line and correctly excluding the noise point — without ever explicitly testing "are these three points collinear" as a combinatorial check.
Common pitfalls & traps
| Pitfall | Why it happens | Fix |
|---|---|---|
| Using parameterization | Vertical lines have , breaking the accumulator's finite range | Use the polar form |
| Accumulator too coarse | Distinct nearby lines merge into a single blurred peak | Increase bin resolution near expected peak; use sub-pixel peak refinement |
| Accumulator too fine | True line's votes spread across many adjacent bins and never exceed threshold | Smooth accumulator (Gaussian blur) before peak detection, or use coarse-to-fine search |
| No non-maximum suppression | The same physical line produces several adjacent peaks, reported as duplicate lines | Suppress neighbors within a window around each accepted peak |
| Forgetting to bound by image diagonal | Out-of-range votes silently dropped or index out of bounds | Precompute and size the axis to |
| Treating peak height as absolute confidence | Longer lines and denser edge maps produce naturally higher peaks, biasing comparisons across images | Normalize by expected line length or edge-point density before thresholding |
| Applying raw Hough circles at full resolution without the gradient-direction trick | blow-up in the 3-D accumulator makes it impractical for realistic radius ranges | Use gradient direction to vote along a ray, not a full candidate circle |
Pioneers & history
The transform's ancestor was devised for particle-physics photograph analysis, where physicists needed to automatically trace particle trajectories (which are lines or arcs) through cluttered bubble-chamber images — the same "many candidate curves through noisy points" problem that appears in computer vision.
Origins · 1 minPaul V. C. Hough and how this was discovered
Hough, an American physicist, patented a method for machine recognition of complex lines in bubble-chamber photographs — the slope-intercept ancestor of the modern transform, designed to automate what had been tedious manual measurement of particle tracks.
Where this matters
Lane-line detection in early and current advanced-driver-assistance systems (ADAS) uses Hough line detection on edge-filtered camera frames to find lane boundaries in real time, often as a preprocessing stage before more sophisticated tracking. Document scanning and deskewing pipelines use the Hough line transform to find the dominant page-boundary angle and rotate scanned images to be axis-aligned. Industrial inspection systems use the circle Hough transform to count and measure circular objects — bottle caps, drilled holes, pills — on assembly lines. Iris and pupil localization in biometric and medical imaging historically relied on circular Hough fitting to find the pupil boundary before deep-learning segmentation became dominant. Barcode and QR-code preprocessing pipelines sometimes use Hough line detection to find the dominant orientation of a tilted code before rectification. OpenCV's `HoughLines`, `HoughLinesP` (probabilistic variant), and `HoughCircles` remain some of the most widely used functions in the library, taught as a canonical bridge between Edge Detection and higher-level shape reasoning, and forming the conceptual stepping stone to sampling-based fitting methods like RANSAC Robust Estimation that scale better to models with many parameters or heavy outlier contamination.
Ask the tutor: How would the accumulator and voting rule change if I wanted to detect ellipses instead of circles?
How is the accumulator array chosen in size, and what happens if it is too small or too large?
The accumulator's dimensions are set by the discretization of each parameter: for lines, typically spans bins (1° resolution) and spans the image diagonal in pixel-sized bins. Too coarse a grid causes distinct nearby lines to merge into a single blurred peak, losing precision. Too fine a grid spreads a true line's votes thinly across many adjacent cells, so no single cell reaches the detection threshold, causing missed detections. Practical systems often use a coarse-to-fine strategy: detect approximate peaks on a coarse grid, then refine each candidate's locally on a finer grid, balancing speed against precision.
Can the Hough Transform detect line segments, or only infinite lines?
The basic transform only recovers infinite lines described by , since the parameterization has no notion of endpoints. To recover finite segments, a common post-processing step re-examines which edge pixels actually voted for a given peak, projects them onto the detected line, and takes the extremal points along that projection as the segment's endpoints, often merging nearby collinear runs and discarding small isolated fragments as noise. The "probabilistic Hough transform" (as in OpenCV's `HoughLinesP`) instead samples a random subset of edge points during voting and directly tracks segment extents during accumulation, which is faster and produces segments natively.
Why does the circle Hough Transform need a 3-D accumulator, and how expensive is that in practice?
A circle is defined by center and radius , three free parameters, so naively the accumulator must span all three: . For an image with hundreds of possible center positions in each dimension and dozens of candidate radii, this can require tens of millions of cells, which is expensive in both memory and vote-casting time if done by brute force (each edge point voting for every possible circle it could lie on). The gradient-direction restriction reduces this dramatically: since the edge gradient at a true circle boundary points radially, each point only needs to vote along one ray per candidate radius, not an entire candidate circle of centers, cutting the dominant cost factor from a full circular sweep to a single directional lookup.
How does the Hough Transform relate to RANSAC, and when would you prefer one over the other?
Both are strategies for fitting a parametric model to noisy, partially corrupted point data. The Hough Transform exhaustively discretizes and votes over the entire parameter space, which is robust and deterministic but only tractable when the parameter space is low-dimensional (2–3 parameters). RANSAC Robust Estimation instead randomly samples minimal subsets of points, fits a candidate model to each subset, and counts inliers, which scales far better to higher-dimensional models (homographies, fundamental matrices) where an exhaustive accumulator would be astronomically large. For lines and circles specifically, the Hough Transform is often preferred because its exhaustive voting gives a globally stable, threshold-free notion of peak strength, while RANSAC's randomized sampling can occasionally miss the true model in a fixed number of iterations.
Does the Hough Transform require edge detection as a preprocessing step?
In the standard formulation, yes — the input to the transform is a sparse set of candidate edge points, usually produced by an edge detector such as Canny, sometimes further filtered by gradient magnitude or direction to reduce noise votes. Feeding in raw, dense pixel intensities without edge filtering would cause every pixel to vote, overwhelming the accumulator with irrelevant votes and destroying the signal-to-noise advantage that makes the method work. The quality of the edge map directly determines the quality of the Hough result: broken or noisy edges spread votes and weaken true peaks, which is why gradient-based edge detection, covered under Image Gradients, is treated as a prerequisite rather than an optional preprocessing choice.
Why do false peaks sometimes appear in cluttered scenes, and how are they mitigated?
In images with many unrelated edges (dense texture, foliage, crowds), it becomes statistically likely that some subset of unrelated points happens to be roughly collinear or roughly co-circular purely by chance, producing spurious accumulator peaks with moderate vote counts. Because voting has no notion of spatial continuity or proximity, an arbitrary scattering of points across the whole image can outvote a genuine but short or partially occluded shape. Mitigations include weighting votes by gradient magnitude (favoring high-contrast edges), restricting voting to points whose gradient direction is consistent with the candidate shape's orientation at that point, and applying a minimum-vote threshold calibrated to the expected length or size of genuine shapes in the scene.
What is the Generalized Hough Transform and how does it differ from the line/circle case?
The Generalized Hough Transform (Ballard, 1981) extends voting to shapes with no closed-form parametric equation, such as an arbitrary silhouette. Instead of a formula, it precomputes an R-table: for a reference shape, it records, for each possible edge gradient direction, the vector offset from an edge point to a chosen reference point (such as the centroid). At detection time, each edge point looks up its gradient direction in the R-table and votes for all reference-point locations consistent with that offset (optionally over a range of scales and rotations, expanding the accumulator's dimensionality accordingly). It reduces to the standard Hough Transform when the shape family has a genuine closed-form equation.