0

I'm trying to obtain an image which has everything but several colorful objects grayed out, as shown here:

intended result

My original image is this (the caps have slightly different colors than the example above):

original image

I tried to apply a threshold process then binarize the image, which gave me the following result (mask is on the left, result of multiplication is on the right):

after thresholding

And now I'm trying to combine all of these masks. Should I use if loop to combine it into a single image or is there a better way? I tried using (&,&,&) but it turned into a black images.

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
Jason Tan
  • 1
  • 2
  • You should always describe what is it that you're trying to do (_why_ also helps) instead of jumping straight to code. Note that you should use `|` in this case. – Dev-iL Dec 25 '18 at 11:59
  • @Dev-iL thank you for the edit and I'll take more time to format my question. – Jason Tan Dec 25 '18 at 12:16

2 Answers2

4

Your original image has 7 distinct regions: 5 colorful tips, the hand, and the background. The question then becomes, how do we disregard the wall and the hand, which happen to be the two largest regions, and only keep the color of the tips.

If your MATLAB license permits, I would recommend using the Color Thresholder App (colorThresholder), which allows you to find a suitable representation of the colors in your image. Experimenting with it for a minute I can say that the L*a*b* color space allows good separation between the regions/colors:

enter image description here

We can then export this function, yielding the following:

function [BW,maskedRGBImage] = createMask(RGB)
%createMask  Threshold RGB image using auto-generated code from colorThresholder app.
%  [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using
%  auto-generated code from the colorThresholder app. The colorspace and
%  range for each channel of the colorspace were set within the app. The
%  segmentation mask is returned in BW, and a composite of the mask and
%  original RGB images is returned in maskedRGBImage.

% Auto-generated by colorThresholder app on 25-Dec-2018
%------------------------------------------------------


% Convert RGB image to chosen color space
I = rgb2lab(RGB);

% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.040;
channel1Max = 88.466;

% Define thresholds for channel 2 based on histogram settings
channel2Min = -4.428;
channel2Max = 26.417;

% Define thresholds for channel 3 based on histogram settings
channel3Min = -12.019;
channel3Max = 38.908;

% Create mask based on chosen histogram thresholds
sliderBW = (I(:,:,1) >= channel1Min ) & (I(:,:,1) <= channel1Max) & ...
  (I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
  (I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;

% Invert mask
BW = ~BW;

% Initialize output masked image based on input image.
maskedRGBImage = RGB;

% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;

end

Now that you have the mask we can easily convert the original image to grayscale, replicate it along the 3rd dimension, then take the colorful pixels from the original image using logical indexing:

function q53922067
img = imread("https://i.stack.imgur.com/39WNm.jpg");

% Image segmentation:
BW = repmat( createMask(img), 1, 1, 3 ); % Note that this is the function shown above

% Keeping the ROI colorful and the rest gray:
gImg = repmat( rgb2gray(img), 1, 1, 3 ); % This is done for easier assignment later
gImg(BW) = img(BW);

% Final result:
figure(); imshow(gImg);
end

Which yields:

enter image description here

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
1

To combine masks, use | (element-wise logical OR), not & (logical AND).

mask = mask1 | mask2 | mask3;
Cris Luengo
  • 55,762
  • 10
  • 62
  • 120