How to convert specific GrayScale into coloured pixel

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

Can you define "good" in the final image?
I see that you ahieved what you described. Are you looking for gradiant color profiles instead of sharp colors?
If what you're hoping for is a less-speckled image, perhaps you could try running medfilt2() before thresholding. Of course, what makes a pleasing image may not be what makes an accurate account of phase percentages.
You might also consider looking at the histogram and see if your breakpoints can be optimized a bit more.
imhist(my2Dgrayimage)
If you want, you can remove "holes" or "islands" smaller than some specified number of pixels, inside a larger region, though clever use of morphological functions like imfill, and and() or xor(), etc.
Like the others asked, what in your mind defines a good or not good colorized image? For example not pure colors, but blended with the gray scale image underneath, or what?????
The colored image must have only blue, green and yellow color, but are still appearing some black and light green points from the 1st image showed.
I would like to calculate the percentage of blue(graphite), green(perlite), and yellow(ferrite) pixels of the last image. When I had the B&W image I only count the black pixels and divided them by the total area, so I have the graphite percentage, but now with colored image, I couldn't do it in the same way I've done with B&W.
FWIW, you could do the same without color. What you're doing could be done with what is essentially a label or index image -- a grayscale image with discrete levels for each object/region of interest. The only reason you might need color to represent classes of things in an image is if certain parts of the image represent multiple classes simultaneously.
Your case has no regions multiply represented, and it should have no regions which have no representation. It can be reduced to a set of non-intersecting masks whose union spans the entire image. You could represent the same information with a grayscale image with only 3 discrete gray levels.
I'd throw down an example, but frankly I don't know how best to deal with the illumination variability caused by the reflectivity of the surface. Your thresholds are already pretty good for fixed thresholds.
If you want color for some aesthetic reason, that's your decision to make. I'm just saying it's not adding any more information than the binary masks give, and it only complicates processing.
If all you want is the area fractions then that should be easy enough. If as I mentioned, the masks are non-intersecting and their union spans the entire image, then the fraction would be
perlitefraction = sum(perlitemask(:))/numel(perlitemask);
for example.
Thank you DGM for your comment.
I already do the calcs in grayscale, I'm trying to use the colored image just for an aesthetic reason and to be more intuitive for people who will read my paperwork, and sincerely I'm almost giving up to use a colored image.
I was looking for some alternatives. A watershed image segmentation could be used for what I need? or just will complicate the process?
The problem is the pixels values that do not fit in the considerations. In the image for example [128 125 106], any threshold values do not satisfy this condition. I've set the thresholds with other conditions but I'm afraid that can impact the right phase counting. There is a way to set a boundary limit and calculate the area by that?

Sign in to comment.

 Accepted Answer

DGM
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.

More Answers (0)

Categories

Find more on Convert Image Type in Help Center and File Exchange

Asked:

on 2 Mar 2021

Edited:

DGM
on 3 Jun 2021

Community Treasure Hunt

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

Start Hunting!