I need to calculate the Delta-E distance between two colors. The algorithm to do so with two colors in CIELab color spa开发者_JAVA技巧ce looks like this:
Are there known open-sourced implementations of this algorithm? It's not hard to implement, but from my last attempt of implementing a color-space conversion algorithm I'd prefer to not re-develop the wheel when it's already on the road and tested.
CIEDE2000 would be nice too and more accurate, but might also be overkill on the iPhone. CIE94 would be just fine I guess.
There's an open-source C# implementation of the CIE94 formula you provided:
https://github.com/THEjoezack/ColorMine/blob/master/ColorMine/ColorSpaces/Comparisons/Cie94Comparison.cs
It requires your colors be in LAB color space, the conversion source for which is in the same library if needed.
You can check your cIE94 calculations online using the same library as well.
Here's the relevant snippet of code, labA and labB are the inputs:
var deltaL = labA.L - labB.L;
var deltaA = labA.A - labB.A;
var deltaB = labA.B - labB.B;
var c1 = Math.Sqrt(Math.Pow(labA.A, 2) + Math.Pow(labA.B, 2));
var c2 = Math.Sqrt(Math.Pow(labB.A, 2) + Math.Pow(labB.B, 2));
var deltaC = c1 - c2;
var deltaH = Math.Pow(deltaA,2) + Math.Pow(deltaB,2) - Math.Pow(deltaC,2);
deltaH = deltaH < 0 ? 0 : Math.Sqrt(deltaH);
const double sl = 1.0;
const double kc = 1.0;
const double kh = 1.0;
var sc = 1.0 + Constants.K1*c1;
var sh = 1.0 + Constants.K2*c1;
var i = Math.Pow(deltaL/(Constants.Kl*sl), 2) +
Math.Pow(deltaC/(kc*sc), 2) +
Math.Pow(deltaH/(kh*sh), 2);
var finalResult = i < 0 ? 0 : Math.Sqrt(i);
The "Constants" are defined based on your application type:
case Application.GraphicArts:
Kl = 1.0;
K1 = .045;
K2 = .015;
break;
case Application.Textiles:
Kl = 2.0;
K1 = .048;
K2 = .014;
break;
I typed in the equation (for Common Lisp code see at bottom) and ran a few random evaluations. The parameters are listed in this order: L*1 a*1 b*1 L*2 a*2 b*2 DeltaE*
I'm not perfectly sure that the results are correct. But if your code gives the same results, then it's probably sufficient.
((53.0 0.65 0.15 33.0 -0.45 -0.1 20.03112)
(42.0 -0.3 0.1 74.0 -0.2 -0.15 32.001118)
(12.0 -1.0 -0.45 32.0 0.3 0.9 20.084782)
(94.0 -0.1 -0.55 77.0 0.5 0.45 17.03928)
(75.0 -0.8 0.35 46.0 -0.6 -0.85 29.02483)
(83.0 -0.65 -0.7 67.0 0.75 0.0 16.074173)
(70.0 -0.7 0.9 54.0 0.35 -0.95 16.13608)
(81.0 0.45 -0.8 53.0 -0.35 0.05 28.023375)
(40.0 -0.2 -0.65 25.0 -1.0 0.8 15.088856)
(66.0 0.85 -0.7 93.0 0.55 0.15 27.014244)
(44.0 -0.5 0.5 23.0 -0.9 0.5 21.00363)
(67.0 0.4 0.25 42.0 -0.25 0.6 25.010727)
(32.0 0.6 0.55 86.0 0.0 0.25 54.003925)
(96.0 -0.15 -0.9 87.0 0.25 -0.3 9.027307)
(100.0 -0.6 0.3 61.0 -0.25 -0.75 39.015385)
(2.0 -0.2 -0.65 73.0 -0.3 0.65 71.01173)
(74.0 0.1 -0.65 96.0 -0.5 0.8 22.05474)
(22.0 -0.3 -0.85 64.0 -0.65 -0.95 42.0015)
(73.0 -0.35 0.3 38.0 0.25 -1.0 35.02875)
(91.0 0.6 0.45 82.0 -0.25 0.2 9.042115))
And here is the source code (tested in SBCL):
;; http://en.wikipedia.org/wiki/Hypot thats not necessary if numbers
;; are not float and even if they are float the values of L*, a* and
;; b* are bound to tiny range
(defun hypot (x y)
"Compute hypotenuse, prevent overflow."
(declare (type number x y)
(values number &optional))
(let ((ax (abs x))
(ay (abs y)))
(if (or (< ax 1e-6) (< ay 1e-6))
(sqrt (+ (* ax ax) (* ay ay)))
(if (< ay ax)
(* ax (sqrt (1+ (expt (/ y x) 2))))
(* ay (sqrt (1+ (expt (/ x y) 2))))))))
#+nil
(list
(hypot 1 0)
(hypot 0 1)
(hypot (sqrt 2) (sqrt 2))
(hypot 2 10000))
;; http://www.devmaster.net/forums/archive/index.php/t-12680.html
(defun hypot3 (x y z)
(hypot (hypot x y) z))
(defun delta-e*-94 (l1 a1 b1 l2 a2 b2 &key (application :graphic-arts))
"Distance in CIE L* a* b* color space."
(declare (type number l1 a1 b1 l2 a2 b2)
(type (member :graphic-arts :textiles) application)
(values number &optional))
(destructuring-bind (kl k1 k2)
(ecase application
(:graphic-arts '(1 .045 .015))
(:textiles '(2 .048 .014)))
(let* ((delta-l (- l1 l2))
(c1 (hypot a1 b1))
(c2 (hypot a2 b2))
(delta-c (- c1 c2))
(delta-a (- a1 a2))
(delta-b (- b1 b2))
(delta-h (sqrt (+ (expt delta-a 2)
(expt delta-b 2)
(* -1 (expt delta-c 2)))))
(l/k (/ delta-l kl))
(c/k (/ delta-c (1+ (* k1 c1))))
(h/k (/ delta-h (1+ (* k2 c1)))))
(hypot3 l/k c/k h/k))))
#+nil ;; some test runs
(labels ((rL () ;; random number from 0..100 inclusive
(random 101))
(r- ()
(/ (- (random 40) 20) 20))
(r3 ()
(list (rL) (r-) (r-))))
(loop for i below 20 collect
(destructuring-bind (l a b) (r3)
(destructuring-bind (ll aa bb) (r3)
(mapcar #'(lambda (x) (* 1s0 x))
(list l a b ll aa bb (delta-e*-94 l a b ll aa bb)))))))
#+nil ;; example test run
((80.0 0.85 0.35 13.0 0.4 -0.8 67.01107)
(11.0 0.25 -0.35 66.0 0.45 0.15 55.002594)
(74.0 -0.55 0.45 98.0 0.7 -0.85 24.066118)
(37.0 -0.3 0.35 60.0 0.55 -0.3 23.02452)
(20.0 -0.85 0.5 20.0 -0.25 0.1 0.6907073)
(23.0 0.25 -0.05 15.0 0.55 -0.8 8.039892)
(29.0 -0.55 0.05 9.0 -0.2 -0.8 20.020708)
(11.0 0.55 -0.45 60.0 0.9 -0.15 49.00211)
(70.0 0.5 -0.15 66.0 -0.8 0.85 4.3169336)
(18.0 -0.5 0.55 49.0 0.5 -0.25 31.025839)
(27.0 -0.95 0.3 43.0 -0.1 0.2 16.021187)
(5.0 -0.4 0.5 70.0 -0.75 -0.75 65.012665)
(9.0 -1.0 -0.2 66.0 0.4 0.05 57.01702)
(10.0 0.25 -0.75 13.0 -0.85 -0.75 3.1900785)
(16.0 -0.65 -0.4 31.0 -0.6 -0.5 15.000405)
(90.0 0.4 0.1 18.0 -0.6 -0.85 72.01298)
(92.0 0.4 0.1 31.0 -0.7 0.2 61.009853)
(99.0 -0.7 -0.5 40.0 -0.9 0.35 59.006287)
(40.0 0.95 -0.2 62.0 -0.7 -0.25 22.06002)
(16.0 0.5 0.7 35.0 0.35 -0.45 19.03436))
There is a paper named "The CIEDE2000 Color-Difference Formula: Implementation Notes, Supplementary Test Data, and Mathematical Observations," by Sharma et al. who suggested some corrections to CIEDE2000 formulation and value table. They also attached the implementation for MATLAB and MS Excel here: http://www.ece.rochester.edu/~gsharma/ciede2000/
You can easily integrate the excel file in your project to recover the results or get the Matlab function work under C# environment. If you don't have matlab you can easily get the Octave to do it for you. Just in case there is a manual for using matlab code in C# programs here: http://www.mathworks.com/matlabcentral/fileexchange/12987-integrating-matlab-with-c
精彩评论