MATLAB: How to Separate the RGB channels from an image and get the average of each RGB channel separetly

remove backgroundrgb channelrgb channel average

How to Separate the RGB channels from an image and get the average of each RGB channel separately
Hello MATLAB community,
I have a set of 20 images, which I need to process simultaneously. All the images have a stain of red colourant in the middle, which I need to separate from the white background. I need to obtain the RGB value average of each channel (pixels) of the stained red area. I am new to the MATLAB world. Hence I am a bit unsure how to proceed. I leave an example of one of the images I have.
Thank you for your time. I appreciate all your help.

Best Answer

I'm feeling particularly lazy today, so I'm not going out of my way to make this solution avoid nonstandard tools. They could be replaced, but let's see what I came up with.
% read images
inpict=imread('stain.jpg');
% use thresholding in chroma to isolate red areas
mask=mono(inpict,'clch')>0.25*255;
% get rid of fabric patterning from bleed
mask=imopen(mask,strel('disk',10));
% pick only the central blob
mask=bwareafilt(mask,1);
% fill in any holes before erosion
mask=imclose(mask,strel('disk',10));
% erode to get rid of any remaining light edges
mask=imerode(mask,strel('disk',10));
% display masked region
maskedpict=inpict.*uint8(mask);
imshow(maskedpict)
% calculate mean color tuple
selectedpix=inpict(repmat(mask,[1 1 3]));
meancolor=mean(reshape(selectedpix,[numel(selectedpix)/3 3]))/255
This will isolate the central part of the stain
and the mean color tuple (normalized) is dumped to console:
meancolor =
0.3814 0.0423 0.0695
So at least for this image, it works. The thresholding and strel sizes may need to be adjusted. If you only ever need one size of strel, you can just save it and reuse it instead of regenerating it every time. I just did that in case they needed tweaking.
mono() is part of the MIMT, which can be downloaded here if desired.
In this example, I'm thresholding chroma in LCHab. You could do the same thing using rgb2lab() and then converting to polar coordinates, etc. The main point is to leverage the lightness/color separation of the color model to avoid needing to deal with the shadows.
EDIT: I got to thinking that depending on your goals, it may be beneficial to further process the ROI. Removing specular highlights from the wet gauze would help keep them from lightening/desaturating your result. Furthermore, the materials used in the gauze would tend to skew the results a bit. It may be more meaningful to use a median of the sample area.
Consider this example.
% remove specular highlights from the mask
mpc=mono(maskedpict,'y')<0.2*255;
maskedpict2=inpict.*uint8(mpc & mask);
% get mean, median, and mode colors (imstats is from MIMT)
selectedpix=inpict(repmat(mpc & mask,[1 1 3]));
[mn md mo]=imstats(im2double(reshape(selectedpix,[numel(selectedpix)/3 1 3])), ...
'mean','median','modecolor')
Using the mean, median, and mode colors returned for both cases, I threw together this sample comparison image:
Against the white background of this website, it's a bit hard to tell, but sampling the mean is most susceptible to the influence of the specular highlights. The mode color is least affected.
Related Question