Tal_Rofe

circle_hough

Jan 21st, 2018
32
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
MatLab 3.61 KB | None | 0 0
  1. function [h, margin] = circle_hough(b, rrange, varargin)
  2. %CIRCLE_HOUGH Hough transform for circles
  3. %   [H, MARGIN] = CIRCLE_HOUGH(B, RADII) takes a binary 2-D image B and a
  4. %   vector RADII giving the radii of circles to detect. It returns the 3-D
  5. %   accumulator array H, and an integer MARGIN such that H(I,J,K) contains
  6. %   the number of votes for the circle centred at B(I-MARGIN, J-MARGIN),
  7. %   with radius RADII(K). Circles which pass through B but whose centres
  8. %   are outside B receive votes.
  9. %
  10. %   [H, MARGIN] = CIRCLE_HOUGH(B, RADII, opt1, ...) allows options to be
  11. %   set. Each option is a string, which if included has the following
  12. %   effect:
  13. %
  14. %   'same' returns only the part of H corresponding to centre positions
  15. %   within the image. In this case H(:,:,k) has the same dimensions as B,
  16. %   and MARGIN is 0. This option should not be used if circles whose
  17. %   centres are outside the image are to be detected.
  18. %
  19. %   'normalise' multiplies each slice of H, H(:,:,K), by 1/RADII(K). This
  20. %   may be useful because larger circles get more votes, roughly in
  21. %   proportion to their radius.
  22. %
  23. %   The spatial resolution of the accumulator is the same as the spatial
  24. %   resolution of the original image. Smoothing the accumulator array
  25. %   allows the effective resolution to be controlled, and this is probably
  26. %   essential for sensitivity to circles of arbitrary radius if the spacing
  27. %   between radii is greater than 1. If time or memory requirements are a
  28. %   problem, a generalisation of this function to allow larger bins to be
  29. %   used from the start would be worthwhile.
  30. %
  31. %   Each feature in B is allowed 1 vote for each circle. This function
  32. %   could easily be generalised to allow weighted features.
  33. %
  34. %   See also CIRCLEPOINTS, CIRCLE_HOUGHPEAKS, CIRCLE_HOUGHDEMO
  35.  
  36. % Copyright David Young 2008, 2010
  37.  
  38. % argument checking
  39. opts = {'same' 'normalise'};
  40. narginchk(2, 2+length(opts));
  41. validateattributes(rrange, {'double'}, {'real' 'positive' 'vector'});
  42. if ~all(ismember(varargin, opts))
  43.     error('Unrecognised option');
  44. end
  45.  
  46. % get indices of non-zero features of b
  47. [featR, featC] = find(b);
  48.  
  49. % set up accumulator array - with a margin to avoid need for bounds checking
  50. [nr, nc] = size(b);
  51. nradii = length(rrange);
  52. margin = ceil(max(rrange));
  53. nrh = nr + 2*margin;        % increase size of accumulator
  54. nch = nc + 2*margin;
  55. h = zeros(nrh*nch*nradii, 1, 'uint32');  % 1-D for now, uint32 a touch faster
  56.  
  57. % get templates for circles at all radii - these specify accumulator
  58. % elements to increment relative to a given feature
  59. tempR = []; tempC = []; tempRad = [];
  60. for i = 1:nradii
  61.     [tR, tC] = circlepoints(rrange(i));
  62.     tempR = [tempR tR]; %#ok<*AGROW>
  63.     tempC = [tempC tC];
  64.     tempRad = [tempRad repmat(i, 1, length(tR))];
  65. end
  66.  
  67. % Convert offsets into linear indices into h - this is similar to sub2ind.
  68. % Take care to avoid negative elements in either of these so can use
  69. % uint32, which speeds up processing by a factor of more than 3 (in version
  70. % 7.5.0.342)!
  71. tempInd = uint32( tempR+margin + nrh*(tempC+margin) + nrh*nch*(tempRad-1) );
  72. featInd = uint32( featR' + nrh*(featC-1)' );
  73.  
  74. % Loop over features
  75. for f = featInd
  76.     % shift template to be centred on this feature
  77.     incI = tempInd + f;
  78.     % and update the accumulator
  79.     h(incI) = h(incI) + 1;
  80. end
  81.  
  82. % Reshape h, convert to double, and apply options
  83. h = reshape(double(h), nrh, nch, nradii);
  84.  
  85. if ismember('same', varargin)
  86.     h = h(1+margin:end-margin, 1+margin:end-margin, :);
  87.     margin = 0;
  88. end
  89.  
  90. if ismember('normalise', varargin)
  91.     h = bsxfun(@rdivide, h, reshape(rrange, 1, 1, length(rrange)));
  92. end
  93.  
  94. end
Add Comment
Please, Sign In to add comment