function dE2000 = ComputeDE2000_Lab(Lab1,Lab2, kLCH) % Computes the deltaE values (CIEDE2000) for color pairs given in CIELAB coordinates (L*a*b*). % % dE2000 = ComputeDE2000_Lab(Lab1,Lab2[,kLCH]); % % The inputs 'Lab1' and 'Lab2' are N*3 matrices each with one color per row [L*,a*,b*]. % The output is a column vector with N elements, containing the according % dE2000 values. % 'kLCH' is optional and contains one or three elements for the weighting % factors kL, kC, kH (either one value for all, or three values for each). % The weighting factors are set to 1, if 'kLCH' is not specified. % % This implementation might not be the most efficient but it follows the formulas % given in https://en.wikipedia.org/wiki/Color_difference#CIEDE2000 as closely % as possible for better traceability. % HISTORY: % 12/01/2017 (MR = Marc Repnow, EPFL) Initial version. if nargin==0 testMe(); return end if any(size(Lab1)~=size(Lab2)) || size(Lab1,2)~=3 error('L*a*b* input parameters must be of size Nx3 (N>=1).'); end if nargin>2 if length(kLCH)==1 kLCH = kLCH*[1,1,1]; elseif isempty(kLCH) kLCH = [1,1,1]; elseif numel(kLCH)~=3 error('Input parameter ''kLCH'' must have either 1 or 3 elements.'); end else kLCH = [1,1,1]; end %--- "Degree"-versions of sin() and cos(). sinD = @(deg) sin(deg*pi()/180); cosD = @(deg) cos(deg*pi()/180); %--- Lstar12 = [Lab1(:,1), Lab2(:,1)]; aStar12 = [Lab1(:,2), Lab2(:,2)]; bStar12 = [Lab1(:,3), Lab2(:,3)]; CprimeStar12 = sqrt(aStar12.^2 + bStar12.^2); dLprime = Lstar12(:,2) - Lstar12(:,1); Lbar = (Lstar12(:,2) + Lstar12(:,1))/2; Cbar = (CprimeStar12(:,1)+CprimeStar12(:,2))/2; aPrime12 = aStar12 .* repmat(1 + 0.5*(1 - sqrt(Cbar.^7./(Cbar.^7 + 25^7))), 1,2); Cprime12 = sqrt(aPrime12.^2 + bStar12.^2); dCprime = Cprime12(:,2)-Cprime12(:,1); CbarPrime = (Cprime12(:,1)+Cprime12(:,2))/2; %--- Note that atan2(0,0) will return 0. hPrime12 = mod(atan2(bStar12, aPrime12)*180/pi() + 10*360, 360); N = length(dLprime); dhPrime = zeros(N,1); HbarPrime = zeros(N,1); for i=1:N diff_hPrime12 = hPrime12(i,2)-hPrime12(i,1); sum_hPrime12 = hPrime12(i,2)+hPrime12(i,1); if any(abs(Cprime12(i,:))<10*eps) dhPrime(i) = 0; elseif abs(diff_hPrime12)<=180 dhPrime(i) = diff_hPrime12; elseif diff_hPrime12 <= 0 dhPrime(i) = diff_hPrime12 + 360; else dhPrime(i) = diff_hPrime12 - 360; end if any(abs(Cprime12(i,:))<10*eps) HbarPrime(i) = sum_hPrime12; elseif abs(diff_hPrime12)<=180 HbarPrime(i) = (sum_hPrime12)/2; elseif sum_hPrime12 < 360 HbarPrime(i) = (sum_hPrime12 + 360)/2; else HbarPrime(i) = (sum_hPrime12 - 360)/2; end end dHprime = 2*sqrt(Cprime12(:,1).*Cprime12(:,2)).*sinD(dhPrime/2); T = 1 - 0.17*cosD(HbarPrime-30) + 0.24*cosD(2*HbarPrime) ... + 0.32*cosD(3*HbarPrime+6) - 0.2*cosD(4*HbarPrime-63); SL = 1 + 0.015*(Lbar-50).^2 ./ sqrt(20 + (Lbar-50).^2); SC = 1 + 0.045*CbarPrime; SH = 1 + 0.015*CbarPrime.*T; RT = -2*sqrt(CbarPrime.^7./(CbarPrime.^7 + 25^7)) .* sinD(60*exp(-((HbarPrime-275)./25).^2)); kL = kLCH(1); kC = kLCH(2); kH = kLCH(3); dE2000 = sqrt((dLprime./(kL*SL)).^2 + (dCprime./(kC*SC)).^2 + (dHprime./(kH*SH)).^2 ... + RT.*dCprime./(kC*SC).*dHprime./(kH*SH)); end %%%% %-------------------------------------------------------------------------------------- function testMe() % Test data are from % Sharma et al., 2005, "The CIEDE2000 Color-Difference Formula: Implementation Notes, % Supplementary Test Data, and Mathematical Observations". % The values in this publication are given with 4 decimal places. For this test function here, % the MATLAB script provided by Sharma was used to get more precise values (8 decimal places). % L*a*b* 1, L*a*b* 2, dE2000 testset = ... [ 50.0000, 2.6772, -79.7751, 50.0000, 0.0000, -82.7485, 2.04245968; 50.0000, 3.1571, -77.2803, 50.0000, 0.0000, -82.7485, 2.86151017; 50.0000, 2.8361, -74.0200, 50.0000, 0.0000, -82.7485, 3.44119060; 50.0000, -1.3802, -84.2814, 50.0000, 0.0000, -82.7485, 0.99999886; 50.0000, -1.1848, -84.8006, 50.0000, 0.0000, -82.7485, 1.00000470; 50.0000, -0.9009, -85.5211, 50.0000, 0.0000, -82.7485, 1.00001297; 50.0000, 0.0000, 0.0000, 50.0000, -1.0000, 2.0000, 2.36685882; 50.0000, -1.0000, 2.0000, 50.0000, 0.0000, 0.0000, 2.36685882; 50.0000, 2.4900, -0.0010, 50.0000, -2.4900, 0.0009, 7.17917201; 50.0000, 2.4900, -0.0010, 50.0000, -2.4900, 0.0010, 7.17916264; 50.0000, 2.4900, -0.0010, 50.0000, -2.4900, 0.0011, 7.21947215; 50.0000, 2.4900, -0.0010, 50.0000, -2.4900, 0.0012, 7.21947421; 50.0000, -0.0010, 2.4900, 50.0000, 0.0009, -2.4900, 4.80452169; 50.0000, -0.0010, 2.4900, 50.0000, 0.0010, -2.4900, 4.80452451; 50.0000, -0.0010, 2.4900, 50.0000, 0.0011, -2.4900, 4.74607111; 50.0000, 2.5000, 0.0000, 50.0000, 0.0000, -2.5000, 4.30648210; 50.0000, 2.5000, 0.0000, 73.0000, 25.0000, -18.0000, 27.14923130; 50.0000, 2.5000, 0.0000, 61.0000, -5.0000, 29.0000, 22.89769247; 50.0000, 2.5000, 0.0000, 56.0000, -27.0000, -3.0000, 31.90300465; 50.0000, 2.5000, 0.0000, 58.0000, 24.0000, 15.0000, 19.45352143; 50.0000, 2.5000, 0.0000, 50.0000, 3.1736, 0.5854, 1.00002634; 50.0000, 2.5000, 0.0000, 50.0000, 3.2972, 0.0000, 0.99997287; 50.0000, 2.5000, 0.0000, 50.0000, 1.8634, 0.5757, 1.00004950; 50.0000, 2.5000, 0.0000, 50.0000, 3.2592, 0.3350, 1.00003476; 60.2574, -34.0099, 36.2677, 60.4626, -34.1751, 39.4387, 1.26442001; 63.0109, -31.0961, -5.8663, 62.8187, -29.7946, -4.0864, 1.26295930; 61.2901, 3.7196, -5.3901, 61.4292, 2.2480, -4.9620, 1.87307050; 35.0831, -44.1164, 3.7933, 35.0232, -40.0716, 1.5901, 1.86449523; 22.7233, 20.0904, -46.6940, 23.0331, 14.9730, -42.5619, 2.03725827; 36.4612, 47.8580, 18.3852, 36.2715, 50.5065, 21.2231, 1.41457792; 90.8027, -2.0831, 1.4410, 91.1528, -1.6435, 0.0447, 1.44412908; 90.9257, -0.5406, -0.9208, 88.6381, -0.8985, -0.7239, 1.53811701; 6.7747, -0.2908, -2.4247, 5.8714, -0.0985, -2.2286, 0.63772767; 2.0776, 0.0795, -1.1350, 0.9033, -0.0636, -0.5514, 0.90823284]; dE2000 = ComputeDE2000_Lab(testset(:,1:3), testset(:,4:6)); %--- Our test case deltaE's are given with 8 decimal places, % so ignore differences that can be explained by the according % round-off errors. if any(abs(dE2000 - testset(:,end)) > 0.5e-8) fprintf('ComputeDE2000_Lab test failed.\n'); [~, i] = max(abs(dE2000 - testset(:,end))); fprintf('e.g. worst test case (#%d): Lab2dE2000([%.4f,%.4f,%.4f],[%.4f,%.4f,%.4f]==%.8f (expected: %.8f)\n',... i, testset(i,1:6), dE2000(i), testset(i,end)); else fprintf('ComputeDE2000_Lab test passed.\n'); end end