# Strange purple areas after color transfer with Lab color space

4 views (last 30 days)
Giulio Puzella on 10 Jun 2022
Edited: DGM on 10 Jun 2022
I'm doing a project for an university course and I am applying the Color Transfer between Images code using the Lab color space as explained by Reinhard et al. What I'm trying to do is to correctly color an analog pic (img_x - original) using another analog pic (img_ref - source)that has the correct colors. I asked my professor and she said it was ok, but the final image has some purple areas that I don't know how to explain. Probably it's a stupid question but I'm just starting using Matlab.
Thank you.
This is my code
img2 = imrotate(img2,90);
% Converting images. img_ref is the image we are taking the color from,
% img_x is the one that needs to be corrected.
img_ref = im2double(img1);
img_x = im2double(img2);
% Displaying images
figure
subplot(1,2,1), imshow(img_ref), title("Good image")
subplot(1,2,2), imshow(img_x), title("Not so good image")
% RGB to LMS colorspace conversion
x_LMS = rgb2lms(img_x);
ref_LMS = rgb2lms(img_ref);
% Due to the fact that the data in this color space shows a grat deal of
% skew, we can convert the data to logarithmic space
x_LMS = log(x_LMS);
ref_LMS = log(ref_LMS);
% Converting from LMS to lab colorspace using the function that uses the
% transform suggested by Ruderman et al.
x_lab = lms2lab(x_LMS);
ref_lab = lms2lab(ref_LMS);
% lab colorspace has a less strong correlation between channels and that
% lets us work on them separately.
% To do the color transfer, we first need to calculate the mean and the
% standard deviations along each of the three axes, for both the source
% and the target images
% Calculating the mean using the mean2 command that computes the mean of
% all values in an array.
avgRef_l = mean2(ref_lab(:, :, 1));
avgRef_a = mean2(ref_lab(:, :, 2));
avgRef_b = mean2(ref_lab(:, :, 3));
avgx_l = mean2(x_lab(:, :, 1));
avgx_a = mean2(x_lab(:, :, 2));
avgx_b = mean2(x_lab(:, :, 3));
% Calculating the standard deviation using the std2 command that computes
% the standard deviation of all values in an array.
devRef_l = std2(ref_lab(:, :, 1));
devRef_a = std2(ref_lab(:, :, 2));
devRef_b = std2(ref_lab(:, :, 3));
devx_l = std2(x_lab(:, :, 1));
devx_a = std2(x_lab(:, :, 2));
devx_b = std2(x_lab(:, :, 3));
% Extracting the color channels from the lab colorspace for the target
% image
xL = x_lab(:,:,1);
xa = x_lab(:,:,2);
xb = x_lab(:,:,3);
% Subtracting the mean from the target image color channels
xL = xL - avgx_l;
xa = xa - avgx_a;
xb = xb - avgx_b;
% Defining the new color channels scaling using the standard deviations
% Converting back from lab to LMS colorspace.
L = (devRef_l/devx_l) * xL;
a = (devRef_a/devx_a) * xa;
b = (devRef_b/devx_b) * xb;
% After this transformation, the resulting data points have standard
% deviations that conform to the photograph.
L2 = L + avgRef_l;
a2 = a + avgRef_a;
b2 = b + avgRef_b;
% Constructing the new color channels that will be used.
clear final_Lab
final_Lab(:,:,1) = L2;
final_Lab(:,:,2) = a2;
final_Lab(:,:,3) = b2;
% lab to LMS conversion.
final_LMS = lab2lms(final_Lab);
% Raising to the power ten (inverse operation of the logaritm).
final_LMS = 10.^final_LMS;
% Converting back to rgb.
final_img = lms2rgb(final_LMS);
% Let's see what happened.
figure,
subplot(1, 3, 1), imshow(img_x), title('Original image')
subplot(1, 3, 2), imshow(img_ref), title('Source image')
subplot(1, 3, 3), imshow(final_img), title('Final image');

DGM on 10 Jun 2022
Edited: DGM on 10 Jun 2022
I'm not really familiar with LMS, and I don't know what tools you're using to do the LMS conversions, so I can't really test anything. It's not immediately apparent to me why everything would be getting shoved into Q4 of LAB. I would question how the LMS-LAB conversion handles strongly negative inputs that would come from the use of log().
That said, there is one thing that looks like an error. You use base-10 here
final_LMS = 10.^final_LMS;
... but you're using the natural log here. The base-10 log is log10()
x_LMS = log(x_LMS);
ref_LMS = log(ref_LMS);
That would definitely skew things, but I'm not really sure which direction the color points would tend to move off the top of my head.
I'd suggest working on a small sample image and visualizing the distribution of color points at different steps in the process using something like scatter3().

Image Analyst on 10 Jun 2022