# Creation of a mask on RGB image

4 views (last 30 days)
Federica Soda on 3 Sep 2020
Commented: Federica Soda on 3 Sep 2020
Hello,
I have applied a mask with irregular contours to a RGB image and then changed the saturation only in the area of the mask.
imshow(Imm);
title('Original Image');
message = sprintf('After you see the cross hairs, \nleft-click and hold to begin drawing.\nSimply lift the mouse button to finish');
uiwait(msgbox(message));
hFH = drawfreehand();
% Create a binary image ("mask") from the ROI object.
figure
imshow(binaryImage)
%Get HSV image from the RGB image
hsvImage = rgb2hsv(Imm);
hueImage = hsvImage(:, :, 1);
saturationImage = hsvImage(:, :, 2);
valueImage = hsvImage(:, :, 3);
% Increase saturation only within the mask area.
satFactor = 1.6;
saturationImage(binaryImage) = saturationImage(binaryImage) * satFactor;
% Recombine
hsvImage = cat(3, hueImage, saturationImage, valueImage);
% Convert back to RGB
rgbImage2 = hsv2rgb(hsvImage);
figure
imshow(rgbImage2);
impixelinfo;
title('Altered RGB Image');
Here the result I got:
Do you know how to obtain a less sharper transition between the mask and the rest of the image in order to get a less artificial effect?
Thank you in advance for your help, I'm not very skilled on Image Processing yet.

J. Alex Lee on 3 Sep 2020
Instead of multiplying pixels in the mask by a constant value, you can mulitply all pixels by an "image" of the saturation multiplier.
So rather than the scalar "1.6", which could as well have been a element-by-element multiplication, your original strategy could have been executed as
[M,N] = size(Imm)
satFactorMat = 1.6*ones(M,N);
satFactorMat(binaryImage) = 1.6;
saturationImage = saturationImage .* satFactorMat;
So now hopefully it is clear you don't really need the mask concept for the operation of altering the image itself, you just might use it to define the satFactorMat "topography", which looks like a mesa.Now you can just smooth it out using something like a smoothing function; you can use imgaussfilt
satFactorMat = imgaussfilt(satFactorMat,6);
You may need to convert everything to doubles first before doing the imgaussfilt and elementwise multiplication, and then convert back to uint8.
Also, note that multiplying is dangerous because you may end up with values outside valid range (>255). So it would be safe to exponentiate (but then you have to normalize your pixel values onto (0,1) first.
hsvImage = double(hsvImage)/255;
% ... everythign in between
% except instead of multiply by satFactorMat, you can do something like
satPowerMat = ones(M,N);
satPowerMat(binaryImage) = 0.3;
satPowerMat = imgaussfilt(satPowerMat,6);
saturationImage = saturationImage .* satPowerMat;
% Recombine
hsvImage = cat(3, hueImage, saturationImage, valueImage);
hsvImage = uint8(hsvImage*255);

Federica Soda on 3 Sep 2020
Thank you very very much for your help!
That's what I was looking for.
J. Alex Lee on 3 Sep 2020
My pleasure! By teh way I just realized if you convert from and to uint8, it will take care of out-of-bounds by rounding back down to 255, so I guess the multiplication is still "safe".
Federica Soda on 3 Sep 2020
Thanks again, I will also consider this aspect.