How to convert specific GrayScale into coloured pixel
7 views (last 30 days)
Show older comments
Hello; I need your very helps about my project in University. I need to colorize metalographic images.
The original Image

I need to quantify the iron phases. I have converted the RGB image to GrayScale because I think is easier to define the regions.
This is the GrayScale one, and I need to convert the light phase into yellow, the almost black into green and the black (circles) into blue.
The aim of this is to quantify the percentual of each phase.
I have tried by RGB image using this code
%%
% Extract the individual red, green, and blue color channels.
redChannel = rgbImage(:, :, 1);
greenChannel = rgbImage(:, :, 2);
blueChannel = rgbImage(:, :, 3);
% Get the Perlite mask
yellowMask =redChannel >= 130 & greenChannel >= 130 & blueChannel >= 130;
% Get the Ferrite mask
GreenMask = redChannel > 60 & greenChannel > 60 & blueChannel > 60 & redChannel < 130 & greenChannel < 130 & blueChannel < 130;
% Get the Graphite mask
BlueMask = redChannel <= 60 & greenChannel <= 60 & blueChannel <= 60;
% Make Perlit mask Yellow
redChannel(yellowMask) = 255;
greenChannel(yellowMask) =255;
blueChannel(yellowMask) = 0;
% Make the white mask Green
redChannel(GreenMask) = 0;
greenChannel(GreenMask) = 255;
blueChannel(GreenMask) = 0;
% Make the Graphite mask Blue
redChannel(BlueMask) = 0;
greenChannel(BlueMask) = 0;
blueChannel(BlueMask) = 255;
% Recombine separate color channels into a single, true color RGB image.
rgbImage2 = cat(3, redChannel, greenChannel, blueChannel);
figure
imshow(rgbImage2)
The final result was not as good I've expected

Thanks very much in advance!
Daniel
7 Comments
Accepted Answer
DGM
on 3 Jun 2021
Edited: DGM
on 3 Jun 2021
I forgot you were doing masking in RGB. You're right. The union of the masks won't span the image. You could find the set difference, but the color points are all very close to the diagonal. It might suffice to just use a brightness metric. It's the same difference really, but it's just less code.
Let's just recreate the masks as calculated
inpict = imread('phases.jpg');
mkperlite = inpict(:,:,1)>=130 & inpict(:,:,2)>=130 & inpict(:,:,3)>=130;
mkgraphite = inpict(:,:,1)<=60 & inpict(:,:,2)<=60 & inpict(:,:,3)<=60;
mkferrite = inpict(:,:,1)<130 & inpict(:,:,2)<130 & inpict(:,:,3)<130 ...
& inpict(:,:,1)>60 & inpict(:,:,2)>60 & inpict(:,:,3)>60;
% this information doesn't necessarily need color unless you want it
outpict = zeros(size(mkperlite));
outpict(mkgraphite) = 0.33;
outpict(mkferrite) = 0.67;
outpict(mkperlite) = 1;

Certainly, there are holes in the sum of masks.
You could use a single brightness metric to avoid having to deal with as many comparisons. Using the difference of masks ensures that the sum of masks spans the image.
ipict = mean(inpict,3); % this calculates I as in HSI
% you could also use V, L, Y, etc
bp = [60 130]; % choose some breakpoints (feel free to tweak)
mkperlite = ipict>=bp(2);
mkgraphite = ipict<=bp(1);
mkferrite = ~(mkperlite | mkgraphite); % this makes the masks span the image
% generating the image is the same
outpict2 = zeros(size(mkperlite));
outpict2(mkgraphite) = 0.33;
outpict2(mkferrite) = 0.67;
outpict2(mkperlite) = 1;
imshow2(outpict2,'invert')
% mask fractions can be calculated
N = numel(mkgraphite);
fracgraphite = sum(mkgraphite(:))/N
fracferrite = sum(mkferrite(:))/N
fracperlite = sum(mkperlite(:))/N
sum([fracgraphite fracferrite fracperlite]) % equals 1 like expected

There could still probably be some improvement made (e.g. the southeast corner) in dealing with the reflectivity/lighting issues. I'm not sure how to approach that.
It's worth pointing out what the geometry of the masks looks like in three dimensions. Consider the masks you're calculating in RGB:

Note that the union of the box selections don't span the domain. If the color points in the image lie in a band about the diagonal of the domain, many points will escape all box selections. You could choose to select two (e.g. the upper and lower ones) and then pick the third by difference as described. That would span the domain, but in this case, it would mean that one of the three selections is much more inclusive than the others.
On the other hand, we can look at what the surfaces of V, I, and L look like. These aren't really selections so much as the boundary between selected regions in the cube:



As you can see, I and L tend to subdivide the volume evenly -- that is a boundary at 50% I or L divides the RGB cube in half. Contrast this against a boundary at 50% V which does not.
I just picked I because it's simple and symmetrically splits the RGB cube where the original box selections touch.
0 Comments
More Answers (0)
See Also
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!