MATLAB: How to make the applied color look more natural/blend into the skin

faceImage Processing Toolboximage/color processingrosy cheeks

theta = 0 : 0.01 : 2*pi;
radius = 45;
I = imread('Image3.jpg');
NoseDetect = vision.CascadeObjectDetector('Nose','MergeThreshold',30);
HSV=rgb2hsv(I);
imshow(HSV); hold on
nbox = step(NoseDetect, I);
nx = nbox(1) + nbox(3)/2;
ny = nbox(2) + nbox(4)/2;
final_x = nx - 145;
final_y = ny - 25;
X = radius * cos(theta) + final_x;
Y = radius * sin(theta) + final_y;
plot(X, Y, 'b-', 'LineWidth', 1);
hueImage = HSV(:,:,1);
satImage = HSV(:,:,2);
valueImage = HSV(:,:,3);
[rows, columns] = size(hueImage);
mask = poly2mask(X, Y, rows, columns);
hueImage(mask) = hueImage(mask) + 1 / 360 * 355;
satImage(mask) = satImage(mask) + 0.01 * 1;
valueImage(mask) = valueImage(mask) + 0.01 * 5;
hueImage(hueImage>1)=1; hueImage(hueImage<0)=0;
satImage(satImage>1)=1; satImage(satImage<0)=0;
valueImage(valueImage>1)=1; valueImage(valueImage<0)=0;
HSV(:,:,1) = hueImage;
HSV(:,:,2) = satImage;
HSV(:,:,3) = valueImage;
final_x = nx + 145;
final_y = ny - 25;
X2 = radius * cos(theta) + final_x;
Y2 = radius * sin(theta) + final_y;
plot(X2, Y2, 'b-', 'LineWidth', 1);
hueImage = HSV(:,:,1);
satImage = HSV(:,:,2);
valueImage = HSV(:,:,3);
[rows, columns] = size(hueImage);
mask = poly2mask(X2, Y2, rows, columns);
hueImage(mask) = hueImage(mask) + 1 / 360 * 355 ;
satImage(mask) = satImage(mask) + 0.01 * 1;
valueImage(mask) = valueImage(mask) + 0.01 * 5;
hueImage(hueImage>1)=1; hueImage(hueImage<0)=0;
satImage(satImage>1)=1; satImage(satImage<0)=0;
valueImage(valueImage>1)=1; valueImage(valueImage<0)=0;
HSV(:,:,1) = hueImage;
HSV(:,:,2) = satImage;
HSV(:,:,3) = valueImage;
newRGBImage = hsv2rgb(HSV);
imshow(newRGBImage);

Best Answer

Try this. I drew the nose up higher so you can see the difference. Adjust the blur window size to soften the rosy disk.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 25;
%===============================================================================

% Get the name of the image the user wants to use.
baseFileName = 'capture.png';
% Get the full filename, with path prepended.
folder = pwd
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
%===============================================================================
% Read in demo image.
rgbImage = imread(fullFileName);
% Get the dimensions of the image.
[rows, columns, numberOfColorChannels] = size(rgbImage);
% Display the original image.
% subplot(2, 2, 1);
imshow(rgbImage, []);
axis on;
caption = sprintf('Original Color Image, %s', baseFileName);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
hp = impixelinfo();
% Set up figure properties:

% Enlarge figure to full screen.


set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0.05 1 0.95]);
% Get rid of tool bar and pulldown menus that are along top of figure.

% set(gcf, 'Toolbar', 'none', 'Menu', 'none');

% Give a name to the title bar.

set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Extract the individual red, green, and blue color channels.
redChannel = rgbImage(:, :, 1);
% greenChannel = rgbImage(:, :, 2);
% blueChannel = rgbImage(:, :, 3);
% Let user draw a box around the nose.
uiwait(helpdlg('Locate the nose. Double-click inside it to accept it'));
hRect = imrect();
noseBox = wait(hRect);
% Draw the image again.
subplot(2, 2, 1);
imshow(rgbImage);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
hold on;
rectangle('Position', noseBox, 'EdgeColor', 'b');
axis on;
% Convert from RGB color space to HSV color space.
hsvImage = rgb2hsv(rgbImage);
hueImage = hsvImage(:,:,1);
satImage = hsvImage(:,:,2);
valueImage = hsvImage(:,:,3);
subplot(2, 2, 2);
imshow(hsvImage);
title('HSV Image, displayed in RGB', 'FontSize', fontSize, 'Interpreter', 'None');
hold on
hold on;
rectangle('Position', noseBox, 'EdgeColor', 'r');
axis on;
impixelinfo(); % Display status line when user mouses around over image.
%=========================================================
% Create a mask of two circles.
% Define center of circle to the right of the nose.
nx = noseBox(1) + noseBox(3)/2;
ny = noseBox(2) + noseBox(4)/2;
final_x = nx - 145;
final_y = ny - 25;
% Make a circular mask on the left side of the image (right side of her face).
theta = 0 : 0.01 : 2*pi;
radius = 45;
X = radius * cos(theta) + final_x;
Y = radius * sin(theta) + final_y;
plot(X, Y, 'b-', 'LineWidth', 1);
leftMask = poly2mask(X, Y, rows, columns);
% Make a circular mask on the right side of the image (left side of her face).
final_x = nx + 145;
theta = 0 : 0.01 : 2*pi;
X2 = radius * cos(theta) + final_x;
plot(X2, Y, 'b-', 'LineWidth', 1);
rightMask = poly2mask(X2, Y, rows, columns);
% Make a mask with both of the circles.
mask = leftMask | rightMask;
% Blur the mask to soften the edges.
blurWindowWidth = 21;
se = strel('disk', blurWindowWidth, 0); % Big circle.
kernel = se.Neighborhood;
kernel = kernel / sum(kernel(:)); % Normalize.
blurredMask = conv2(double(mask), ones(blurWindowWidth)/blurWindowWidth^2, 'same');
% Find the non-zero areas of the blurred mask.
mask = blurredMask > 0;
subplot(2, 2, 3);
imshow(blurredMask);
title('Mask', 'FontSize', fontSize, 'Interpreter', 'None');
hold on
axis on;
% Alter the hue, saturation, and value.
% Desired hue = 0.25.
hueImage(mask) = hueImage(mask) .* (1 - blurredMask(mask));
satImage = satImage + 0.01 * blurredMask;
valueImage = valueImage + 0.01 * 5 * blurredMask;
% Clip to valid range of 0-1.
hueImage(hueImage>1)=1; hueImage(hueImage<0)=0;
satImage(satImage>1)=1; satImage(satImage<0)=0;
valueImage(valueImage>1)=1; valueImage(valueImage<0)=0;
% Put back altered images into hsvImage so we can convert back to RGB.
hsvImage = cat(3, hueImage, satImage, valueImage);
% Convert back to RGB color space.
newRGBImage = hsv2rgb(hsvImage);
subplot(2, 2, 4);
imshow(newRGBImage);
title('New Image', 'FontSize', fontSize, 'Interpreter', 'None');
hold on;
rectangle('Position', noseBox, 'EdgeColor', 'b');
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0.05 1 0.95]);
% Get rid of tool bar and pulldown menus that are along top of figure.
% set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')
% Bring up the new image full screen alone.
figure;
imshow(newRGBImage);
title('New Image', 'FontSize', fontSize, 'Interpreter', 'None');
hold on;
rectangle('Position', noseBox, 'EdgeColor', 'b');
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0.05 1 0.95]);