MATLAB: Creation of a mask on RGB image

image processingmaskrgb image

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.
Imm = imread('lena .bmp');
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.
binaryImage = hFH.createMask();
% Display the freehand mask
figure
imshow(binaryImage)
title('Binary mask of the region');
%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.

Best Answer

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);