Goal
Detect pixels of high radial symmetry in a grayscale image on pixel domain . Output: a real-valued symmetry map where large positive values correspond to bright radially-symmetric regions and large negative values to dark ones; local maxima and minima of are the detected points of interest. Each pixel casts gradient-direction votes to two affected pixels at distance , accumulating orientation counts and gradient magnitudes into a pair of projection images per radius; the per-radius contribution is formed by combining those projections, raising the orientation count to a power to penalise non-radial votes, and convolving with a small Gaussian. Summing contributions across all radii yields at cost for a -pixel image with detection radii, with no gradient-orientation quantisation and no neighbourhood convolution loops over pixel pairs.
Algorithm
Let denote the grayscale image on pixel domain . Let denote the image gradient at pixel , computed with, e.g., the Sobel operator. Let denote the set of detection radii in pixels. Let denote the radial strictness parameter. Let denote the gradient magnitude threshold below which a pixel casts no votes. Let denote the orientation projection image at radius , initialised to zero. Let denote the magnitude projection image at radius , initialised to zero. Let and denote the max-normalised projections. Let denote a 2-D Gaussian kernel of size and standard deviation . Let denote 2-D convolution.
For each pixel with gradient of nonzero magnitude, the two affected pixel coordinates at radius are:
where is one radius ahead in the gradient direction and is one radius behind. Rounding the continuous unit-gradient offset to the nearest integer pixel introduces a quantisation error of up to pixels per vote at oblique gradient angles.
For each pixel with , the projection images are updated:
A radially-symmetric structure causes the surrounding gradient vectors to point coherently toward (or away from) its centre, producing a large coherent count at that location in both and .
The per-radius symmetry contribution before spatial spreading:
Raising the normalised orientation count to the power suppresses votes that are weakly focused — for example, from elongated structures where gradient vectors are approximately collinear rather than radially convergent.
The orientation–magnitude combination spread by a Gaussian kernel:
where is a 2-D Gaussian of size and standard deviation . The convolution distributes each vote's influence over a neighbourhood proportional to the detection radius.
The ECCV 2002 conference version of this paper states in the Figure 3 caption but in the Table 1 experimental settings. The Table 1 value is treated as operative.
The contributions across all radii are summed:
Positive values of correspond to bright radially-symmetric regions; negative values to dark ones (assuming the gradient is oriented from dark to light).
Procedure
- Compute the image gradient at every pixel, e.g. with the Sobel operator.
- Initialise the output map across .
- For each radius :
- Initialise and across .
- For each pixel with , compute and by rounding the unit gradient scaled by ; update and at those two locations.
- Normalise: , .
- Compute at every pixel.
- Construct the Gaussian kernel of size and standard deviation .
- Accumulate .
- Return . Detect interest points as local maxima (bright features) and local minima (dark features) of .
Implementation
The per-radius vote-and-accumulate kernel in Rust:
fn frst_radius(
gx: &[f32], gy: &[f32],
width: usize, height: usize,
n: usize, alpha: u32, beta: f32,
o_n: &mut [f32], m_n: &mut [f32],
) {
let stride = width as i32;
for y in 0..height as i32 {
for x in 0..width as i32 {
let idx = (y * stride + x) as usize;
let gx_p = gx[idx];
let gy_p = gy[idx];
let mag = (gx_p * gx_p + gy_p * gy_p).sqrt();
if mag < beta { continue; }
// Unit gradient scaled by radius → round to nearest integer offset.
let scale = n as f32 / mag;
let dx = (gx_p * scale).round() as i32;
let dy = (gy_p * scale).round() as i32;
// p⁺ = p + round(ĝ · n), p⁻ = p − round(ĝ · n)
for (sign, vote_mag) in [(1i32, mag), (-1i32, -mag)] {
let nx = x + sign * dx;
let ny = y + sign * dy;
if nx >= 0 && nx < stride && ny >= 0 && ny < height as i32 {
let nidx = (ny * stride + nx) as usize;
o_n[nidx] += sign as f32; // O_n(p±) += ±1
m_n[nidx] += vote_mag; // M_n(p±) += ±‖g‖
}
}
}
}
// Õ_n = O_n / max|O_n|, M̃_n = M_n / max|M_n|.
let o_max = o_n.iter().fold(0f32, |a, &v| a.max(v.abs()));
let m_max = m_n.iter().fold(0f32, |a, &v| a.max(v.abs()));
if o_max > 0.0 && m_max > 0.0 {
// F_n(p) = |Õ_n(p)|^α · M̃_n(p), written back into o_n for the caller.
for i in 0..o_n.len() {
let o_norm = o_n[i] / o_max;
let m_norm = m_n[i] / m_max;
o_n[i] = o_norm.abs().powi(alpha as i32) * m_norm;
}
}
// Caller convolves o_n with A_n (Gaussian, size n×n, σ = 0.5n) and adds the result to S.
}
The dx/dy variables implement from the definition. The sign loop handles both affected pixels in a single pass: sign = +1 accumulates and ; sign = -1 gives and . The normalisation block followed by the powi(alpha) call implements . The Gaussian convolution and accumulation into are standard separable-filter operations and are left to the caller.
Remarks
- Complexity: for a -pixel image with detection radii. Each radius requires one gradient pass, one vote-accumulation pass, and one Gaussian convolution; all three are with separable filters. No pairwise pixel comparisons are performed.
- Parameter sensitivity: eliminates line responses while preserving circular-feature responses; reduces to a linear combination, minimises computation, and admits more edge false positives. of the maximum gradient magnitude is the speed–quality trade-off recommended in Table 1 of the paper.
- Failure modes: elongated structures (edges, lines) produce diffuse rather than peaked responses because their gradient vectors are approximately collinear rather than radially convergent — attenuates but does not eliminate the bias. Very small radii () suffer coarse gradient quantisation; at only 4–8 distinct integer offset directions exist. Sparse-gradient regions (low-contrast scenes, uniform patches) produce a near-zero because few votes are cast.
- Scope: the transform localises interest points to integer pixel precision only; the rounding of limits intrinsic accuracy to pixels without additional sub-pixel refinement. The original formulation operates on a scalar gradient field; multi-channel images require a channel-fusion step before the vote stage.
- Multi-radius strategy: computing over a representative sparse subset of radii (e.g. rather than ) closely approximates the full-range output at roughly half the cost.
References
- G. Loy, A. Zelinsky. Fast radial symmetry for detecting points of interest. IEEE TPAMI 25(8)–973, 2003. ieeexplore.ieee.org/document/1217601