how do i assign a color to the same type of shape

6 views (last 30 days)
jason on 12 Nov 2014
Edited: DGM on 14 Mar 2023 at 6:43
Now that each shape is classified into its group, how would i go about to add color to each shape, each shape must be colored according to group i.e squares all blue, circles all red,but shape that don't fall into the classification should be black in color. I used RGB2 below but i cant add the shapes together into an image with a white background. Is there any other method???
RGB2 = label2rgb(L==n, 'copper', 'w', 'noshuffle');
eg. squares=blue
eg. circles=r

Answers (3)

Doug Hull
Doug Hull on 12 Nov 2014
If you make this a binary image, you can run it through regionprops. There are a variety of metrics in there that should be usefull in identifying equal shapes. Without much more information, I think this will be enough to get you in the right direction.
  1 Comment
jason on 13 Nov 2014
thank you, but i am not allowed to use region prop command.

Sign in to comment.

Image Analyst
Image Analyst on 12 Nov 2014
Once you've identified the shapes, which we've talked about in your other question, you can use a for loop to reassign your labeled region to the desired number, like 1 for squares = blue, 2 for circles = red, and so on. Then just create the colormap and pass that plus the labeled image in to ind2rgb() to get an RGB image with shapes having the desired color.
jason on 13 Nov 2014
here is my code with the classified shapes, take a look @ it please, where would i add the color to codes.

Sign in to comment.

DGM on 14 Mar 2023 at 5:33
Edited: DGM on 14 Mar 2023 at 6:43
It's no surprise OP got lost. That's an awful lot of duplicated code, unused code, and misleading variable names. I got lost.
This is an attempt to clean it up so that it runs at least as much as it did before. There are still a lot of things that could be simplified, fixed, or otherwise improved.
The code as given wouldn't run with the given image, since the edge detection generates a bunch of spurious blobs. That's probably because the input is a crusty JPG.
clearvars % clean up
close all
fontsize = 8; % used for figure labels
textbgc = 'y';
RGB = imread('test_shapes.jpg'); %read the loaded image
sharp=imsharpen(RGB); %sharpen the read image
grayscale=rgb2gray(sharp); %convert from rgb image to grayscale format
h = fspecial('gaussian',40,1); %create a smoothing filter
filtered = imfilter(grayscale,h); %filtering
Edgecanny = edge(filtered,'canny'); %edge detection
X = imfill(Edgecanny,'holes'); %fill in with holes
% get rid of all the tiny blobs created by doing edge detection on a JPG
Bw = bwareaopen(X,1500);
% get the label image
[L numblobs] = bwlabel(Bw);
% define shape class names
shapeclasses = {'Circle','Square','Triangle','Rectangle','Pentagon', ...
% preallocate
blobcentroids = zeros(numblobs,2); % the [x y] centroid location for each blob
blobclasses = zeros(numblobs,1); % the class number for each blob
blobaream = zeros(numblobs,1); % the unrounded area for each blob (in sq m)
for n=1:numblobs
thisblobonly = L==n; % do it once instead of 14 times
[row, col] = find(thisblobonly);
% Find Bounding Box
sx = min(col)-0.5; %starting position for column
sy = min(row)-0.5; %starting position for row
breadth = max(col)-min(col)+1; %gives breadth of the box
length = max(row)-min(row)+1; %gives length of the box
BBox = [sx sy breadth length]; %Bounding Box value for the range of n
% Find area ratio
blobarea = bwarea(thisblobonly); %calculates the area of each binary component
blobaream(n) = round(blobarea) * 0.001; %converting from mm to m
bboxarea = (length*breadth); %calculates the area of each bounding box
extent = blobarea/bboxarea; %calculates the ratio of area's
fprintf('Extent: %.4f\n',extent)
% Find Perimeter
thisboundary = bwboundaries(thisblobonly); %Find the boundary of the labeled components boundary pixels
c = cell2mat(thisboundary(1)); %converts the cell to a matrix
Perimeter = 0; %declaring a start at zero for sum
for i = 1:size(c,1)-1 %creates a loop that extracts perimeter of each binary component
Perimeter = Perimeter+sqrt((c(i,1)-c(i+1,1)).^2+(c(i,2)-c(i+1,2)).^2);
fprintf('Perimeter: %.3f\n',Perimeter); %display perimeter
% Find Roundness
Roundness = (4*blobarea*pi)/Perimeter.^2; %defines how close the binary component is to a circle
fprintf('Roundness: %.3f\n',Roundness); %display roundness factor
% Find aspect ratio instead of distance between first three vertices
aspectratio = min(BBox(3:4))/max(BBox(3:4)); % normalized
fprintf('Aspect: %.3f\n',aspectratio);
% Find Centroid
X = mean(col); %calculates average of columns
Y = mean(row); %calculates average of rows
blobcentroids(n,:) = [X Y]; %matrix of centroid dimensions
fprintf('Centroid: [%d %d]\n',round(blobcentroids(n,:))); %display centroid
if extent>=0.782 && extent<=0.800 && Roundness>=0.909
blobclasses(n) = 1; % CIRCLE
elseif aspectratio>=0.9 && extent>=0.97
blobclasses(n) = 2; % SQUARE
elseif extent>=0.526 && extent<=0.550 && Roundness>=0.541 && Roundness<=0.559
blobclasses(n) = 3; % TRIANGLE
elseif aspectratio<0.9 && extent>=0.97
blobclasses(n) = 4; % RECTANGLE
elseif extent>=0.694 && extent<=0.714
blobclasses(n) = 5; % PENTAGON
elseif extent>=0.758 && extent<=0.769
blobclasses(n) = 6; % HEXAGON
elseif extent>=0.782 && extent<=0.800 && Roundness<0.909
blobclasses(n) = 7; % ELLIPSE
elseif extent>=0.833 && extent<=0.909
blobclasses(n) = 8; % OCTAGON
elseif extent>=0.526 && extent<=0.535 && Roundness>=0.714 && Roundness<=0.769
blobclasses(n) = 9; % DIAMOND
blobclasses(n) = 10; % NOT CLASSIFIED SHAPE
% dump another message into the console
fprintf('Blob %d is a %s\n\n',n,lower(shapeclasses{blobclasses(n)}));
% create a bunch of subplots
% doing the junk with blind axes position manipulation is a nightmare
% it's entirely dependent on the relationship between the aspect ratio of the figure window
% and the aspect ratio of the images.
% there's no reason to expect that the titles will even be visible.
% the modern suggestion would be to use tiledlayout, but that wasn't an option in 2014.
% FEX subplot_tight() would have probably been sufficient at the time
title('Original Image');
% idk why the original plotted the input image twice
% i'm just going to plot the binarized image
% since that's why this whole mess wouldn't work in the first place
title('Binarized Image');
title('Classified Shapes');
for k = 1:numblobs
ht = text(blobcentroids(k,1),blobcentroids(k,2),shapeclasses{blobclasses(k)});
title('Area in m^2');
for k = 1:numblobs
ht = text(blobcentroids(k,1),blobcentroids(k,2),sprintf('%.3f',blobaream(k)));
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% create an image with blobs colored by class
% this could also have been done in the main loop
labeledbyclass = zeros(size(Bw),'uint16'); % integer-class
for k = 1:numblobs
thisblobonly = L==k;
labeledbyclass(thisblobonly) = blobclasses(k);
% labeloverlay() was not available in 2014
% treat the new label image as an indexed image
% indexed image mapping depends on the numeric class
% for float inputs, mapping starts at 1
% for integer-class inputs, mapping starts at 0
CT = brewermap(numblobs,'paired'); % create the color table
CT = [0 0 0; CT]; % include a black row for the background
coloredbyclass = ind2rgb(labeledbyclass,CT);
This uses subplot_tight() and brewermap() from the File Exchange. Both would have been available at the time, so I think that's fair. I used brewermap() here simply as a quick way to get a categorical colormap that's long enough for the 10 classes given. The built-in lines() map is not. There would have been alternatives to both.
Note that the classification doesn't actually work very well. I didn't bother to fix that. This was mostly just an exercise creating the colored label image with period-correct tools, but it got sidetracked by simplifying existing code without actually digging into OP's classification approach. Similarly, I'm not touching the question of whether doing edge detection is even an appropriate part of the binarization task. Maybe I'll come back to this some other day.
EDIT: Nevermind; I went ahead and made the classification work at least. It's still not great, but at least it works for this image, and the console dump is helpfully formatted.
You might ask why there aren't any circles or squares detected. That's because there aren't any. Test it with a different image:


Find more on Images in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by