Search code examples
image-processingcomputer-visionhough-transform

Unable to properly calculate [a, b] space in Hough transformation for circle detection


Code of function performing accumulation in [a, b] space

  • minr: minimum radius.
  • maxr: maximum radius.
  • Magnitude: Binary output after edge detection using Sobel. Binary thinned image
  • Gradient: Direction map. Calculated with 'atan(Ix./Iy)' where Ix is horizontal and Iy is vertical. enter image description here

    function [A] = accumulation(minr, maxr, magnitude, gradient)
        [rows, cols, ~] = size(magnitude);
        A = zeros(rows, cols, maxr);
    
        for row = 1:rows
            for col = 1:cols
                for r = minr:maxr
                    a = row - r * cos(gradient(row, col));
                    b = col - r * sin(gradient(row, col));
    
                    a = round(a);
                    b = round(b);
    
                    if (a > 0 && a <= rows && b > 0 && b <= cols)
                        A(a, b, r) = A(a, b, r) + (magnitude(row, col)/r);
                    end
                end
            end
        end
    end
    

Output

Although, I am using 3 dimensional array, following image is in 2D just to show the issue. ab-space

Steps performed before accumulation in [a, b] space

  1. Smoothing using 3x3 Gaussian filter.
  2. Edge detection using Sobel operators which returns magnitude and direction map.
  3. Thresholding and thinning.

Source I am using Circle Detection Using Hough Transforms Documentation by Jaroslav Borovicka for guidance.


Solution

  • One issue I see in you code is that you set only one point per r. You need two. Note that the gradient gives you the orientation of the edge, but you don't know the direction towards the center -- unless you're computing the gradient of an image with solid disks, and you know the contrast with the background (i.e it's always black in white or white on black). Typically one sets a point at distance r in direction theta and another in direction theta + pi.

    Another problem you might be having is inaccuracy in the computation of the gradient. If you compute this on a binarized image, the direction of the gradient will be off by a lot. Smithing your grey-value image before computing the gradient might help (or better, use Gaussian gradients).

    "Smoothing using 3x3 Gaussian filter" is wrong by definition. See the link above.

    "Thresholding and thinning" -- try not thresholding. Your code is set up to accumulate using gradient magnitude as weights. Use those, they'll help.

    Finally, don't use atan, use atan2 instead.