Advertisement
TwentyEight

region3d

Dec 31st, 2018
247
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
MatLab 7.02 KB | None | 0 0
  1. function [P, J] = regionGrowing(cIM, initPos, thresVal, maxDist, tfMean, tfFillHoles, tfSimplify)
  2. % REGIONGROWING Region growing algorithm for 2D/3D grayscale images
  3. %
  4. % Syntax:
  5. %   P = regionGrowing();
  6. %   P = regionGrowing(cIM);
  7. %   P = regionGrowing(cIM, initPos)
  8. %   P = regionGrowing(..., thresVal, maxDist, tfMean, tfFillHoles, tfSimpl)
  9. %   [P, J] = regionGrowing(...);
  10. %
  11. % Inputs:
  12. %          cIM: 2D/3D grayscale matrix                      {current image}
  13. %      initPos: Coordinates for initial seed position     {ginput position}
  14. %     thresVal: Absolute threshold level to be included     {5% of max-min}
  15. %      maxDist: Maximum distance to the initial position in [px]      {Inf}
  16. %       tfMean: Updates the initial value to the region mean (slow) {false}
  17. %  tfFillHoles: Fills enclosed holes in the binary mask              {true}
  18. %   tfSimplify: Reduces the number of vertices {true, if dpsimplify exists}
  19. %
  20. % Outputs:
  21. %   P: VxN array (with V number of vertices, N number of dimensions)
  22. %      P is the enclosing polygon for all associated pixel/voxel
  23. %   J: Binary mask (with the same size as the input image) indicating
  24. %      1 (true) for associated pixel/voxel and 0 (false) for outside
  25. %  
  26. % Examples:
  27. %   % 2D Example
  28. %   load example
  29. %   figure, imshow(cIM, [0 1500]), hold all
  30. %   poly = regionGrowing(cIM, [], 300); % click somewhere inside the lungs
  31. %   plot(poly(:,1), poly(:,2), 'LineWidth', 2)
  32. %  
  33. %   % 3D Example
  34. %   load mri
  35. %   poly = regionGrowing(squeeze(D), [66,55,13], 60, Inf, [], true, false);
  36. %   plot3(poly(:,1), poly(:,2), poly(:,3), 'x', 'LineWidth', 2)
  37. %
  38. % Requirements:
  39. %   TheMathWorks Image Processing Toolbox for bwboundaries() and axes2pix()
  40. %   Optional: Line Simplification by Wolfgang Schwanghart to reduce the
  41. %             number of polygon vertices (see the MATLAB FileExchange)
  42. %
  43. % Remarks:
  44. %   The queue is not preallocated and the region mean computation is slow.
  45. %   I haven't implemented a preallocation nor a queue counter yet for the
  46. %   sake of clarity, however this would be of course more efficient.
  47. %
  48. % Author:
  49. %   Daniel Kellner, 2011, braggpeaks{}googlemail.com
  50. %   History: v1.00: 2011/08/14
  51.  
  52.  
  53. % error checking on input arguments
  54. if nargin > 7
  55.     error('Wrong number of input arguments!')
  56. end
  57.  
  58. if ~exist('cIM', 'var')
  59.     himage = findobj('Type', 'image');
  60.     if isempty(himage) || length(himage) > 1
  61.         error('Please define one of the current images!')
  62.     end
  63.    
  64.     cIM = get(himage, 'CData');
  65. end
  66.  
  67. if ~exist('initPos', 'var') || isempty(initPos)
  68.     himage = findobj('Type', 'image');
  69.     if isempty(himage)
  70.         himage = imshow(cIM, []);
  71.     end
  72.    
  73.     % graphical user input for the initial position
  74.     p = ginput(1);
  75.    
  76.     % get the pixel position concerning to the current axes coordinates
  77.     initPos(1) = round(axes2pix(size(cIM, 2), get(himage, 'XData'), p(2)));
  78.     initPos(2) = round(axes2pix(size(cIM, 1), get(himage, 'YData'), p(1)));
  79. end
  80.  
  81. if ~exist('thresVal', 'var') || isempty(thresVal)
  82.     thresVal = double((max(cIM(:)) - min(cIM(:)))) * 0.05;
  83. end
  84.  
  85. if ~exist('maxDist', 'var') || isempty(maxDist)
  86.     maxDist = Inf;
  87. end
  88.  
  89. if ~exist('tfMean', 'var') || isempty(tfMean)
  90.     tfMean = false;
  91. end
  92.  
  93. if ~exist('tfFillHoles', 'var')
  94.     tfFillHoles = true;
  95. end
  96.  
  97. if isequal(ndims(cIM), 2)
  98.     initPos(3) = 1;
  99. elseif isequal(ndims(cIM),1) || ndims(cIM) > 3
  100.     error('There are only 2D images and 3D image sets allowed!')
  101. end
  102.  
  103. [nRow, nCol, nSli] = size(cIM);
  104.  
  105. if initPos(1) < 1 || initPos(2) < 1 ||...
  106.    initPos(1) > nRow || initPos(2) > nCol
  107.     error('Initial position out of bounds, please try again!')
  108. end
  109.  
  110. if thresVal < 0 || maxDist < 0
  111.     error('Threshold and maximum distance values must be positive!')
  112. end
  113.  
  114. if ~isempty(which('dpsimplify.m'))
  115.     if ~exist('tfSimplify', 'var')
  116.         tfSimplify = true;
  117.     end
  118.     simplifyTolerance = 1;
  119. else
  120.     tfSimplify = false;
  121. end
  122.  
  123.  
  124. % initial pixel value
  125. regVal = double(cIM(initPos(1), initPos(2), initPos(3)));
  126.  
  127. % text output with initial parameters
  128. disp(['RegionGrowing Opening: Initial position (' num2str(initPos(1))...
  129.       '|' num2str(initPos(2)) '|' num2str(initPos(3)) ') with '...
  130.       num2str(regVal) ' as initial pixel value!'])
  131.  
  132. % preallocate array
  133. J = false(nRow, nCol, nSli);
  134.  
  135. % add the initial pixel to the queue
  136. queue = [initPos(1), initPos(2), initPos(3)];
  137.  
  138.  
  139. %%% START OF REGION GROWING ALGORITHM
  140. while size(queue, 1)
  141.   % the first queue position determines the new values
  142.   xv = queue(1,1);
  143.   yv = queue(1,2);
  144.   zv = queue(1,3);
  145.  
  146.   % .. and delete the first queue position
  147.   queue(1,:) = [];
  148.    
  149.   % check the neighbors for the current position
  150.   for i = -1:1
  151.     for j = -1:1
  152.       for k = -1:1
  153.            
  154.         if xv+i > 0  &&  xv+i <= nRow &&...          % within the x-bounds?
  155.            yv+j > 0  &&  yv+j <= nCol &&...          % within the y-bounds?          
  156.            zv+k > 0  &&  zv+k <= nSli &&...          % within the z-bounds?
  157.            any([i, j, k])       &&...      % i/j/k of (0/0/0) is redundant!
  158.            ~J(xv+i, yv+j, zv+k) &&...          % pixelposition already set?
  159.            sqrt( (xv+i-initPos(1))^2 +...
  160.                  (yv+j-initPos(2))^2 +...
  161.                  (zv+k-initPos(3))^2 ) < maxDist &&...   % within distance?
  162.            cIM(xv+i, yv+j, zv+k) <= (regVal + thresVal) &&...% within range
  163.            cIM(xv+i, yv+j, zv+k) >= (regVal - thresVal) % of the threshold?
  164.  
  165.            % current pixel is true, if all properties are fullfilled
  166.            J(xv+i, yv+j, zv+k) = true;
  167.  
  168.            % add the current pixel to the computation queue (recursive)
  169.            queue(end+1,:) = [xv+i, yv+j, zv+k];
  170.  
  171.            if tfMean
  172.                regVal = mean(mean(cIM(J > 0))); % --> slow!
  173.            end
  174.        
  175.         end        
  176.       end
  177.     end  
  178.   end
  179. end
  180. %%% END OF REGION GROWING ALGORITHM
  181.  
  182.  
  183. % loop through each slice, fill holes and extract the polygon vertices
  184. P = [];
  185. for cSli = 1:nSli
  186.     if ~any(J(:,:,cSli))
  187.         continue
  188.     end
  189.    
  190.     % use bwboundaries() to extract the enclosing polygon
  191.     if tfFillHoles
  192.         % fill the holes inside the mask
  193.         J(:,:,cSli) = imfill(J(:,:,cSli), 'holes');    
  194.         B = bwboundaries(J(:,:,cSli), 8, 'noholes');
  195.     else
  196.         B = bwboundaries(J(:,:,cSli));
  197.     end
  198.    
  199.     newVertices = [B{1}(:,2), B{1}(:,1)];
  200.    
  201.     % simplify the polygon via Line Simplification
  202.     if tfSimplify
  203.         newVertices = dpsimplify(newVertices, simplifyTolerance);        
  204.     end
  205.    
  206.     % number of new vertices to be added
  207.     nNew = size(newVertices, 1);
  208.    
  209.     % append the new vertices to the existing polygon matrix
  210.     if isequal(nSli, 1) % 2D
  211.         P(end+1:end+nNew, :) = newVertices;
  212.     else                % 3D
  213.         P(end+1:end+nNew, :) = [newVertices, repmat(cSli, nNew, 1)];
  214.     end
  215. end
  216.  
  217. % text output with final number of vertices
  218. disp(['RegionGrowing Ending: Found ' num2str(length(find(J)))...
  219.       ' pixels within the threshold range (' num2str(size(P, 1))...
  220.       ' polygon vertices)!'])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement