Binary to RGB image with specific colour in specific area

I need to convert a binary image to RGB image with specific colour in three specfic area. Actually this discrimination is needed to separate three areas. I am attaching two images (one binary and one RGB) to show how the RGB image should look like.

 Accepted Answer

yes,sir,may be use regionprops to compute region property,and make rule to find first、second、third class,use findpeaks to segment rectangle block,such as
but the segment method should be consider,because the segment locating may be not match

7 Comments

I know the "rule" for the third class could be how close the centroid is to the middle column of the image, like I suggested. Or you could also check if the solidity is high
props = regionprops(mask, 'Solidity');
yellowIndexes = find([props.Solidity] > 0.8); % or whatever number works.
but what would be the rule to get your cyan and dark blue blobs? They are actually the same blob (but only some of the time) in the original mask and so (sometimes) they need to be divided into two blobs. Plus some of the divisions, like on the third blob down on the right, don't seem to follow the same rule.
yes,sir,may be use the stat segment method,such as
clc; clear all; close all;
warning off all;
img = imread('https://ww2.mathworks.cn/matlabcentral/answers/uploaded_files/867905/PWH00200113720160111000P3.png');
bw = im2bw(img);
sz = size(bw);
[L,num] = bwlabel(bw);
Lm = zeros(size(L));
stats = regionprops(L, 'all');
th = 5;
for i = 1 : num
ceni = stats(i).Centroid;
bwi = L == i;
if stats(i).Solidity > 0.95 && abs(stats(i).Orientation) < 20
% third label
Lm(bwi > 0) = 3;
continue;
end
recti = stats(i).BoundingBox;
if recti(3) < sz(2)/6
% small,second
Lm(bwi > 0) = 2;
continue;
end
if recti(1) < sz(2)/2
% left
cs = sum(bwi, 1);
cs2 = cs;
[pks2,locs2] = findpeaks(-cs2);
% first,second
bwi2 = bwi; bwi3 = bwi;
bwi2(:, round(locs2(end))+th:end) = 0;
bwi3(:, 1:round(locs2(end))+th) = 0;
Lm(bwi2 > 0) = 1;
Lm(bwi3 > 0) = 2;
continue;
end
if recti(1)+recti(3) > sz(2)/2
% right
cs = sum(bwi, 1);
cs2 = cs;
[pks2,locs2] = findpeaks(-cs2);
% second, first
bwi2 = bwi; bwi3 = bwi;
bwi2(:, round(locs2(end))-th:end) = 0;
bwi3(:, 1:round(locs2(end))-th) = 0;
Lm(bwi2 > 0) = 2;
Lm(bwi3 > 0) = 1;
end
end
figure; imshow(label2rgb(Lm));
figure; imshow(label2rgb(Lm));
yes,sir,this is used to reduce peak noise,if do not get this function,may use low pass filter to reduce noise
Can you tell me the function for that?
yes,sir,if can not update MATLAB version,just delete this smooth filter
@Sunetra Banerjee, I tried to improve the code by adding comments and renaming variables and other things, but there are still parts I'm confused about and it doesn't seem to find the narrow part (like the wrist of the arm/fist-shaped blobs) so the ball/fist is not being found at the ideal location. Why do you need to do this anyway? Please give us some context.
% Initialization Steps.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 18;
% warning off all;
img = imread('https://ww2.mathworks.cn/matlabcentral/answers/uploaded_files/867905/PWH00200113720160111000P3.png');
bw = im2bw(img);
subplot(1, 3, 1);
imshow(bw);
title('Original Binary Image')
[rows, columns, numberOfColorChannels] = size(bw)
[labeledImage, numBlobs] = bwlabel(bw);
Lm = zeros(size(labeledImage));
subplot(1, 3, 2);
imshow(labeledImage, []);
imshow(label2rgb(labeledImage));
title('Original Labeled Image')
drawnow;
stats = regionprops(labeledImage, 'all')
th = 5; % Not sure what this is.
for i = 1 : numBlobs
% ceni = stats(i).Centroid;
% Extract the ith blob.
bwi = labeledImage == i;
if stats(i).Solidity > 0.95 && abs(stats(i).Orientation) < 20
% Make convex blobs at low angles class 3.
Lm(bwi > 0) = 3;
continue;
end
% Get the bounding box, which is a 1x4 vector like [xLeft, yTop, width, height]
rectBB = stats(i).BoundingBox; % [xLeft, yTop, width, height]
if rectBB(3) < columns/6
% small,second
Lm(bwi > 0) = 2;
continue;
end
if rectBB(1) < columns/2
% Blob is on the left side.
% Get the horizontal profile, which is the height of the blob at every column.
horizontalHeightProfile = sum(bwi, 1);
% Find the narrowest part, which is a valley,
% which you can get by inverting (negating) the height profile.
[pks2,locs2] = findpeaks(-horizontalHeightProfile);
% first,second
bwi2 = bwi;
bwi3 = bwi;
bwi2(:, round(locs2(end))+th:end) = 0;
bwi3(:, 1:round(locs2(end))+th) = 0;
% Define bw1 to be class 1, and bwi3 to be class 2.
Lm(bwi2 > 0) = 1;
Lm(bwi3 > 0) = 2;
elseif rectBB(1) + rectBB(3) > columns/2
% Blob is on the right side.
% Get the horizontal profile, which is the height of the blob at every column.
horizontalHeightProfile = sum(bwi, 1);
% Find the narrowest part, which is a valley,
% which you can get by inverting (negating) the height profile.
[pks2,locs2] = findpeaks(-horizontalHeightProfile);
% second, first
bwi2 = bwi;
bwi3 = bwi;
bwi2(:, round(locs2(end))-th:end) = 0;
bwi3(:, 1:round(locs2(end))-th) = 0;
% Define bw1 to be class 2, and bwi3 to be class 1.
Lm(bwi2 > 0) = 2;
Lm(bwi3 > 0) = 1;
end
end
subplot(1, 3, 3);
imshow(label2rgb(Lm));
title('Final Labeled Image')
@Image Analyst Thanks a lot for your effort and help. I tried another image with your code and I am attaching the output image here.
The context is, above the round shaped blob like things are my ROI and I need to find their centroids for further calculations. The attached hand like areas I need to discard, so I need to differntly colourcode them.

Sign in to comment.

More Answers (2)

Well, I could do it, but not within the few minutes I typically donate to people. There are basically 2 ways: the traditional shape analysis way, and the deep learning way.
If you want deep learning I suggest you use SegNet and have lots of training images.
If you want to do the traditional way, what I'd do is to use regionprops to find the centroid of all the blobs
props = regionprops(mask, 'Centroid');
xy = vertcat(props.Centroid);
and find all blobs whose centroids are with some distance of the center of the image, like 10%
x = xy(:, 1);
[rows, columns, numberOfColorChannels] = size(mask)
middleColumn = columns/2;
inMiddle = find((x > 0.45 * middleColumn) & (x < 0.55 * middleColumn));
[labeledImage, numBlobs] = bwlabel(mask);
blueBlobs = ismember(labeledImage, inMiddle);
Now to find the green balls at the end of the zipper teeth is trickier. I might start by taking each blob and getting the boundary with bwboundaries(). Then get the coordinates that are the leftmost 10 columns (for the right zipper) or rightmost 10 columns (for the left zipper). Then take those and fit a circle to them with the FAQ:
Then use the center and radius (gotten from the fit) to create x and y for a perfect circle. Now use poly2mask to create a perfect circle mask. Do that for each zipper tooth. So now you have an array of balls.
greenBlobs = false(rows, columns);
for k = 1 : numBlobs
thisBlob = ismember(labeledImage, k);
% Get boundary
boundary = bwboundaries(thisBlob);
b = boundary{1}; % Pull out of cell array.
% Get x and y coordinates.
xb = b(:, 2);
yb = b(:, 1);
% Get centroid
props = regionprops(thisBlob, 'Centroid');
xy = vertcat(props.Centroid);
x = xy(:, 1);
% Determine if the blob is to the right or left.
if x < columns/2
% It's on the left
% Find rightmost coordinates.
maxx = max(x);
indexes = x > maxx - 10; % All coordinates within 10 pixels of the right end.
else
% It's on the right.
end
% Now fit xb and yb to a circle using the FAQ.
% to do, create xc and yc using the FAQ
% Now turn into a mask
circleMask = poly2mask(xCircle, yCircle, rows, columns);
greenBlobs = greenBlobs | circleMask
end
You can use that plus the blueBlobs mask to get the red teeth
redBlobs = mask; % Initialize
redBlobs(~blueBlobs) = false; % Erase where there are blue blobs.
redBlobs(~greenBlobs) = false; % Erase where there are green blobs.
Then you can use bwareaopen() to clean up any little tiny bits left over by erasing the green and blue blobs.
redBlobs = bwareaopen(redBlobs, 50); % Remove litter (small blobs)
I'm not going to do all of it for you, you can do that and learn something, but this is a good start. I've already spent more time than I want to spend tonight on that. This is untested code off the top of my head so expect to do some debugging, because there will be some errors.
@yanqi liu How did you differentiate the two regions with blue and sky blue separately? I am trying to follow this code. Did you try the same code?

6 Comments

Hi, Thanks for your help. I was mentioning your code. But, I am not able to separate the green balls. How to take each blob separately for calculating its boundary and then fit the same into a circle?
I have 200 binary images that I have to convert to RGB.
Actually I need the blue and green area and discard the red area, thats why I need to convert it to binary to RGB. Is there any process to do that without converting it to RGB?
yes,sir,the code use stat method,may be exist over segmentation
@Sunetra Banerjee, OK, my code. So, if I have time over the weekend I'll see what I can do.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!