Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

To resolve issues starting MATLAB on Mac OS X 10.10 (Yosemite) visit: http://www.mathworks.com/matlabcentral/answers/159016

Relabel ROIs in a circular pattern

Asked by Jeremy on 28 Jun 2013

I have a set of blobs in a circular pattern, that is, they all are lined up in a circular pattern and I need to label them according the circle starting from the bottom of the circle. The way bwlabel works makes it very difficult to see an easy way to do this, the far left blob on the circle is one and the blob on the far right of the circle is the last label 8. Anyone have any ideas or have done this before? I have an idea to find the center of the circle and use angles to determine each blobs relative position, but then I'm pretty lost. Thank you!!

0 Comments

Jeremy

2 Answers

Answer by Sean de Wolski on 28 Jun 2013
Edited by Sean de Wolski on 28 Jun 2013
Accepted answer
  • Use bwconncomp() instead of bwlabvel.
  • The will return a Connected Components structure with the field 'PixelIdxList'.
  • Each cell in this list corresponds to one blob
  • You can reorder this list based on whatever sorting algorithm you want. NOTE, this can be passed into regionprops directly if you want to use regionprops to help with the algorithm
  • Once you have sorted 'PixelIdxList' to be your choice order, use labelmatrix (aptly named!) to convert the Connected Components structure into a label matrix.

So a full example:

% Synthetic image
I = imread('coins.png');
BW = imfill(I > 100,'holes');
%% Make the circular matrix
szBW = size(BW);
C = zeros(szBW);
for ii = 1:ceil(size(BW,1)./2)
    C(ii:(end-(ii-1)),ii:(end-(ii-1))) = circlemat(szBW-2*(ii-1))+max(C(:));    
end
%% Connect components
CC = bwconncomp(BW);
[~,order] = sort(cellfun(@(x)min(C(x)),CC.PixelIdxList)); %find order in C
CC.PixelIdxList = CC.PixelIdxList(order); %reorder
LL = labelmatrix(CC); %make label matrix
imshow(label2rgb(LL,jet(CC.NumObjects+1))) %view it

Where circlemat is:

function C = circlemat(szC)
%Default
if ~nargin
    szC = [10 10];
end
%Initial conditions and sizes
C = zeros(szC);
szhalf = floor(szC./2);
%Seed the first position
rr = 1;
cc = 1;
C(1) = 1;
%Quadrants
QQ = [1 2;3 4];
for ii = 2:(sum(szC)*2-4) %number of elements
    %Determine quadrant
    Q = QQ((rr > szhalf(1))+1, (cc > szhalf(2))+1);       
      switch Q
          case 1   %Upper left
              if cc == 1
                  rr = rr+1;
              else
                  cc = cc-1;            
              end
          case 2    %Lower left
              if rr == 1
                  cc = cc-1';
              else
                  rr = rr-1;
              end
          case 3    %lower right
              if rr == szC(1)
                  cc = cc+1;
              else
                  rr = rr+1;
              end
          case 4    %upper right
              if cc == szC(2)
                  rr = rr-1;
              else
                  cc = cc+1;
              end                  
      end
      C(rr,cc) = ii;
end

2 Comments

Sean de Wolski on 28 Jun 2013

How you create you circular matrix seems like a really good topic for a CODY question :)

 [1 8 7
  2 9 6
  3 4 5] 
Sean de Wolski on 28 Jun 2013

Alright, you piqued my interest. Now I can go home.

Sean de Wolski
Answer by Image Analyst on 28 Jun 2013

Where did you post your image? I imagine you'd have to segment your blobs and get their centroids. Then renumber your blobs according to your own custom algorithm, perhaps based on the angle from the center of the image or something. Then you can do a relabeling really fast by using intlut and your original labeled image along with your renumbered list. Then, you can either sort your measurements from regionprops the same way, or simply start all over again by calling regionprops with your newly labeled image.

2 Comments

Jeremy on 28 Jun 2013

http://i.imgur.com/8SzRpvi.png

Here is the web address: http://imgur.com/8SzRpvi

Now I am trying to label from 1 at the bottom of the inner circle and T1 at the bottom of the outer circle counting up one for each in a counter-clockwise direction.

Image Analyst on 28 Jun 2013

The algorithm I gave should work. I'd just mask out the center of the image because you don't want those. Can you do it? Here's some code to get you started:

clc;    % Clear the command window.
close all;  % Close all figures (except those of imtool.)
imtool close all;  % Close all imtool figures if you have the Image Processing Toolbox.
clear;  % Erase all existing variables. Or clearvars if you want.
workspace;  % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
% Read in a standard MATLAB gray scale demo image.
folder = 'D:\Temporary stuff';
baseFileName = '8SzRpvi.png';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
	% File doesn't exist -- didn't find it there.  Check the search path for it.
	fullFileName = baseFileName; % No path this time.
	if ~exist(fullFileName, 'file')
		% Still didn't find it.  Alert user.
		errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
		uiwait(warndlg(errorMessage));
		return;
	end
end
grayImage = imread(fullFileName);
% Get the dimensions of the image.  
% numberOfColorBands should be = 1.
[rows, columns, numberOfColorBands] = size(grayImage);
if numberOfColorBands > 1
	% It's not really gray scale like we expected - it's color.
	% Convert it to gray scale by taking only the green channel.
	grayImage = grayImage(:, :, 2); % Take green channel.
end
% Display the original gray scale image.
subplot(2, 2, 1);
imshow(grayImage, []);
title('Original Grayscale Image', 'FontSize', fontSize);
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
% Give a name to the title bar.
set(gcf,'name','Demo by ImageAnalyst','numbertitle','off') 
% Binarize the image
binaryImage = grayImage > 128;
% Get rid of small particles.
binaryImage = bwareaopen(binaryImage, 400);
% Mask out central area.
binaryImage(130:380, 130:380) = false;
subplot(2, 2, 2);
imshow(binaryImage, []);
title('Masked Binary Image', 'FontSize', fontSize);
% Do connected components labeling.
cc = bwconncomp(binaryImage);
% Measure the centroid locations.
measurements = regionprops(cc, 'Centroid');
allCentroids = [measurements.Centroid]
% Plot centroids over the image.
centroidX = allCentroids(1:2:end);
centroidY = allCentroids(2:2:end);
hold on;
plot(centroidX, centroidY, 'b*');
% Specify the center of the image.
imageCenterX = columns / 2;
imageCenterY = rows / 2;
% Calculate the angles from the center to the discs.
angles = atand((centroidY - imageCenterY) ./ (centroidX - imageCenterX))
% Find the blob closest to the bottom with angle -pi/2
[~, minIndex] = min(angles - (-pi/2))
% Plot a red square over that one
plot(centroidX(minIndex), centroidY(minIndex), ...
	'rs', 'MarkerSize', 20, 'LineWidth', 2);
% Plot the initial numbers
for blob = 1 : cc.NumObjects
	x = centroidX(blob)
	y = centroidY(blob) - 5
	text(x, y, num2str(blob), 'Color', [1, 0, 0], 'FontWeight', 'Bold');
end
[sortedAngles, sortIndexes] = sort(angles, 'ascend')
% Get a labeled matrix.  Bottom blob has angle +pi/2 since y increases as it goes downward.
labeledImage = labelmatrix(cc);

See if you can finish it.

Image Analyst

Contact us