Assigning colors to segmented pictures in MATLAB - matlab

I was dealing with color segmentation with MATLAB. I used k-means clustering based on this document and come this far codewise;
global imgRGB;
global imgLAB;
img = imgRGB;
cform = makecform('srgb2lab');
imgLAB = applycform(img, cform);
ab = double(imgLAB(:,:,2:3));
rows = size(ab,1)
cols = size(ab,2);
ab = reshape(ab, rows*cols, 2);
cluster = 5;
[idx center] = kmeans(ab, cluster, 'distance', 'sqEuclidean', 'Replicates', 5);
label = reshape(idx, rows, cols);
figure; imshow(label, []);
imgSeg = cell(5);
rgb_label = repmat(pixel_labels, [1 1 3]);
for k=1:cluster
color = img;
color(rgb_label ~= k) = 0;
imgSeg{k} = color;
end
figure;
imshow(imgSeg{1});
I take image as input that is why it is defined global.
For a colored image like the one in link, it produces the grayscale output.
I think it assigns gray tones as colors but I need to assign a color to each cluster. I mean not gray tone but a color. How can I achieve that?

You should use a different colormap for your figure, when displaying the labels directly.
Try:
figure;
imshow(label, []);
colormap( rnad(max(imgSeg{1}(:))+1, 3) ); % use random color map
However, if you wish to convert the pixel_labels to an RGB image (3 color channels per pixel), you want to use ind2rgb (instead of replicating the labels to all channels). Replace rgb_label = repmat(pixel_labels, [1 1 3]); with
rgb_label = ind2rgb(pixel_labels, rand(max(pixel_labels(:)),3));

Related

Filling region of RGB image specified by polygon in Matlab

After finding boundaries of my regions of interest in an RGB image I want to fill them with specific color on the original picture
img=imread('I.png');
BW=~im2bw(img,0.5);
B = bwboundaries(a2);
for k = 1:length(B)
boundary = B{k};
% here should color everything inside boundary in blue
end
What function can I use to do this? I tried also using imshow() and than ploting regions on it, but don't know how to save it in the original resolution.
If you insist on filling with polygon, you can use fill, but then you might face some problems:
img = imread('Prueba.jpg');
figure;
imshow(img)
BW = ~im2bw(img, 0.55);
B = bwboundaries(BW);
hold on
for k = 1:length(B)
boundary = B{k};
fill(boundary(:, 2), boundary(:, 1), 'b')
end
As shown in this example, there are regions of the image that are surrounded by a boundary but they are actually supposed to be outside the boundary.
Instead, in this way you can avoid the issue:
imgR = img(:, :, 1);
imgG = img(:, :, 2);
imgB = img(:, :, 3);
imgR(BW) = 0;
imgG(BW) = 0;
imgB(BW) = intmax(class(imgB));
IMG = cat(3, imgR, imgG, imgB);
figure; imshow(IMG)

k-means segmentation of an image

I came across the following code, which segments an image using num no. of clusters, via the k-means clustering algorithm. However, I could not understand the meaning of the second statement in the first for loop. Please help me understand what the statement is doing and also what ~= means(here).
Also, when I run the code, I get the following error:
??? Attempt to grow array along ambiguous dimension.
Error in ==> kmeansseg at 42
color(rgb_label ~= k) = 0;
It seem that I get this error for every value other than num=3. So, does it mean that I cannot cluster an rgb image into more than 3 colors? The input image has 6 colors that I can tell apart. Can someone suggest a solution for this?
Function call:
>> f=imread('peppers.png');
>> kmeansseg(f,6)
Here is the code:
function kmeansseg(im,num)
figure(1),imshow(im), title('original image');
cform = makecform('srgb2lab');
lab_im = applycform(im,cform);
ab = double(lab_im(:,:,2:3));
nrows = size(ab,1);
ncols = size(ab,2);
ab = reshape(ab,nrows*ncols,2);
nColors = num;
[cluster_idx, cluster_center] = kmeans(ab,nColors,'distance','sqEuclidean', ...
'Replicates',3);
pixel_labels = reshape(cluster_idx,nrows,ncols);
figure(2),imshow(pixel_labels,[]), title('image labeled by cluster index');
segmented_images = cell(1,nColors);
rgb_label = repmat(pixel_labels,[1 1 nColors]);
for k = 1:nColors
color = im;
color(rgb_label ~= k) = 0; %meaning?
segmented_images{k} = color;
end
figure(3),imshow(segmented_images{1}), title('objects in cluster 1');
figure(4),imshow(segmented_images{2}), title('objects in cluster 2');
figure(5),imshow(segmented_images{3}), title('objects in cluster 3');
end
end
It is setting to zero any elements of the image that don't correspond to that particular label. That's how you get a series of segmented images. It gets the segregation labels from the rgb_label variable.
What ~= means there is "for every pixel of the segmentation image is NOT equal to the current segmentation number, set the image pixel to zero, leaving the other image pixels unchanged"
In regards to your edit - it looks like the color and rgb_label matrices do not have the same dimensions.

identify the redness in an image & then compare with the other image using Matlab

I want to identify redness in the image and then compare that value with the redness in another image. I am quite new to Matlab and don't have image processing knowledge. However, I have been trying some random techniques to do this. Till now, I have used histograms of RGB channels of individual images and have also compared average numeric values of RGB channels in individual images. Unfortunately, I see almost similar results in both cases and cannot identify difference between less red and more red image.
I randomly tried working with grayscale histograms as well but found it to be useless.
(source: ucoz.ru)
(source: luc.edu)
P.S. I searched on this forum and tried to find a similar problem but i did not find anything that could help me.
What I need is:
a. Which technique could be used to check redness in images?
b. How Matlab can me help there?
%-------------------------------------------
%For histograms of all 3 RGB channels in an image
i = imread('<Path>\a7.png');
imgr = i(:,:,1);
imgg = i(:,:,2);
imgb = i(:,:,3);
histr = hist(imgr(:), bins);
histg = hist(imgg(:), bins);
histb = hist(imgb(:), bins);
hfinal = [histr(:); histg(:); histb(:)];
plot(bins, histr);
%-------------------------------------------
%To compare mean values of R channels of all images
clear all;
%read all images in a sequence
flist=dir('<Path>\*.png');
for p = 1:length(flist)
for q = 1 : 3
fread = strcat('<Path>\',flist(p).name);
im = imread(fread);
meanim(p,q) = mean2(im(:,:,q));
end
end
%disp(meanim);
rm = meanim(:,1);
frm = sum(rm(:));
gm = meanim(:,2);
fgm = sum(gm(:));
bm = meanim(:,3);
fbm = sum(bm(:));
figure();
set(0,'DefaultAxesColorOrder',[1 0 0;0 1 0;0 0 1]);
pall = [rm(:), gm(:), bm(:)];
plot(pall);
title('Mean values of R, G and B in 12 images');
leg1 = legend('Red','Green','Blue', ...
'Location','Best');
print (gcf, '-dbmp', 'rgbchannels.bmp')
sm = sum(meanim);
fsum = sum(sm(:));
% disp(fsum);
f2 = figure(2);
set(f2, 'Name','Average Values');
t = uitable('Parent', f2, 'Position', [20 20 520 380]);
set(t, 'ColumnName', {'Average R', 'Average G', 'Average B'});
set(t, 'Data', pall);
print (gcf, '-dbmp', 'rgbtable.bmp') ;
rgbratio = rm ./ fsum;
disp(rgbratio);
f3 = figure(3);
aind = 1:6;
hold on;
subplot(1,2,1);
plot(rgbratio(aind),'r+');
title('Plot of anemic images - having more pallor');
nind = 7:12;
subplot(1,2,2);
plot(rgbratio(nind),'b.');
title('Plot of non anemic images - having less pallor');
hold off;
print (gcf, '-dbmp', 'anemicpics.bmp');
You can't assume the red channel is the same as the redness of a pixel by itself. A good estimate of redness of a pixel may be achieved by something like this:
redness = max(0, red - (blue + green) / 2);
Where red, green and blue are values of different RGB channels in the image.
Once you calculated this value for an image, you can estimate the redness of the image by some approaches like averaging or histograms.

How to set edgecolor same as the facecolor while drawing polygos in matlab?

I am plotting many polygons using the command fill.
fill(X1,Y1,1)
fill(X2,Y2,2)
...
I want to set the edge color the same as the face color. What do I have to do for that?
I am plotting many polygons and I need to find a way to set the edgecolor same as the facecolor. Even the facecolors are not known to me.
I have to use numbers, because I am plotting a data.
I don't get what's wrong with the suggestion of CitizenInsane, but if you just want to save some code you could use a little helper function:
FillItLikeIWant = #(x,y,color) fill(x, y, color, 'EdgeColor',color)
FillItLikeIWant(x,y,'r')
Alternatively you can define all your "Styles" in advance, thats how I usually do it with line plots, in an array like this:
myStyles = {{'r','EdgeColor','r'};
{'b','EdgeColor','b'};
{'g','EdgeColor','g'}}
and then iterate through the styles:
for ii = 1:3
fill(x,y,myStyles{ii}{:}); hold on
end
Edit:
I don't know what the single number 1 or 2 in your example fill(X1,Y1,1) is supposed to do, but maybe you want to create and use a colormap like this:
N = 500;
Cmap = colormap(jet(N));
Now use the helper function and every polygon gets another color of the Cmap.
for ii = 1:500
h{ii} = FillItLikeIWant(x,y,Cmap(ii,:));
end
you can keep track of all colors just by the indices. Alternatively save the handles of every single polygon.
So afterwards you can get the color of a polygon by its handle:
get(h{500},'FaceColor')
ans =
0.504 0 0
which is the same as:
Cmap(500,:)
ans =
0.504 0 0
Just set EdgeColor property/value pair, with the same color as faces:
t = (1/16:1/8:1)'*2*pi;
x = sin(t);
y = cos(t);
fill(x, y, 'r', 'EdgeColor', 'r');
Sample code for drawing multiple polygons with different colors in a for loop (using current colormap):
function [] = foo()
%[
cmap = colormap; % Use some colormap to have different color for polygons
ccount = size(cmap, 1); % Number of elements in the colormap
figure; % Create a figure
hold on; % Avoids deleting previous polygons
pcount = 50; % number of polygons
for i = 1:pcount,
% Create randomly translated polygon
t = (1/16:1/8:1)'*2*pi;
x = 0.1*sin(t) + rand;
y = 0.1*cos(t) + rand;
% Select a color in the colormap
colorIndex = mod(i, ccount);
if (colorIndex == 0), colorIndex = ccount; end
colorValue = cmap(colorIndex, :);
% Draw the polygon
fill(x, y, colorValue, 'EdgeColor', colorValue);
end
%]
end

display cluster in an image

I have an image, test3:
I want to cluster points on the image.
My code:
[I,map]=imread('test3','bmp');
I = ~I;
imshow(I,map);
[m n]=size(I)
P = [];
for i=1:m
for j=1:n
if I(i,j)==1
P = [P ; i j];
end
end
end
size(P)
MON=P;
[IDX,ctrs] = kmeans(MON,3)
As I plot the clusters in the image, I also want to draw IDX and ctrs in the image.
How do I get an image with 3 new clusters, with each cluster a different color in the image.
To generate the k-means clusters:
% locations of the black pixels
[I,map]=imread('test3','bmp'); I = ~I;
[ii,jj] = find(I==1);
P = [ii jj];
k = 3;
[IDX,ctrs] = kmeans(P,k);
To plot the points with different colors for each cluster:
cm = jet(k);
hold on
for ik=1:k,
imap = IDX==ik;
plot(P(imap,2),P(imap,1),'.','color',cm(:,ik));
end
axis image
axis ij
Add markers for the centers:
plot(ctrs(:,2),ctrs(:,1),'r*','markersize',10)
Result:
Or to make a color-coded image out of the cluster indexes:
kimg = zeros(size(I));
kimg(sub2ind(size(I),P(:,1),P(:,2))) = IDX;
cmap = [ones(1,3); jet(k)]
kimgRGB = ind2rgb(kimg+1,cmap);
imwrite(kimgRGB,'kimg.png')
Result:
Note that I have chosen the jet colormap, but you can use any map you wish. Also, I have set the background to white (ones(1,3) is the color for index value 1).