是否有 CIEDE2000 或 CIE94 Delta-E 色差计算算法的已知实现?

问题描述 投票:0回答:4

我需要计算两种颜色之间的 Delta-E 距离。在 CIELab 颜色空间中使用两种颜色执行此操作的算法如下所示:

enter image description here

该算法是否有已知的开源实现?实现起来并不难,但从我上次尝试实现颜色空间转换算法来看,我宁愿在轮子已经上路并经过测试时不再重新开发轮子。

CIEDE2000 也很好,而且更准确,但在 iPhone 上也可能有点过分了。我想 CIE94 就可以了。

c algorithm math image-processing colors
4个回答
6
投票

您提供的 CIE94 公式有一个开源 C# 实现:

https://github.com/THEjoezack/ColorMine/blob/master/ColorMine/ColorSpaces/Comparisons/Cie94Comparison.cs

它要求您的颜色位于 LAB 颜色空间中,如果需要,其转换源位于同一库中。

您也可以使用相同的库在线检查您的 cIE94 计算。

这是相关的代码片段,labA 和 labB 是输入:

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

“常量”是根据您的应用程序类型定义的:

case Application.GraphicArts: Kl = 1.0; K1 = .045; K2 = .015; break; case Application.Textiles: Kl = 2.0; K1 = .048; K2 = .014; break;
    

2
投票
我输入了等式(对于 Common Lisp 代码,请参见底部)并 进行了一些随机评估。参数按以下顺序列出: L*1 a*1 b*1 L*2 a*2 b*2 DeltaE*

我不完全确定结果是否正确。但如果你的代码给出 相同的结果,那么可能就足够了。

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

这是源代码(在 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))
    

1
投票
Sharma 等人发表了一篇名为“The CIEDE2000 Color-Difference Formula: Implement Notes, Supplementary Test Data, and Mathematical Observations”的论文。谁对CIEDE2000的表述和数值表提出了一些修正建议。他们还在此处附上了 MATLAB 和 MS Excel 的实现:

http://www.ece.rochester.edu/~gsharma/ciede2000/

您可以轻松地将Excel文件集成到您的项目中以恢复结果或让Matlab函数在C#环境下工作。如果您没有 matlab,您可以轻松地使用 Octave 来为您完成此操作。以防万一,这里有一份在 C# 程序中使用 matlab 代码的手册:

http://www.mathworks.com/matlabcentral/fileexchange/12987-integrating-matlab-with-c


0
投票
提出了

CIEDE2000色差公式的实现,在6种编程语言中得到了一致的结果:

    JavaScript
  • C
  • Python
  • PHP
  • Java
  • 红宝石
源代码位于公共领域

github.com/michel-leonard/delta-e-2000,因此对于CIEDE2000色差公式的C99实现,我建议:

#include <math.h> static double ciede_2000(const double l_1, const double a_1, const double b_1, const double l_2, const double a_2, const double b_2) { // Working with the CIEDE2000 color-difference formula. // k_l, k_c, k_h are parametric factors to be adjusted according to // different viewing parameters such as textures, backgrounds... const double k_l = 1.0, k_c = 1.0, k_h = 1.0; double n = (hypot(a_1, b_1) + hypot(a_2, b_2)) * 0.5; n = n * n * n * n * n * n * n; // A factor involving chroma raised to the power of 7 designed to make // the influence of chroma on the total color difference more accurate. n = 1.0 + 0.5 * (1.0 - sqrt(n / (n + 6103515625.0))); // hypot calculates the Euclidean distance while avoiding overflow/underflow. const double c_1 = hypot(a_1 * n, b_1), c_2 = hypot(a_2 * n, b_2); // atan2 is preferred over atan because it accurately computes the angle of // a point (x, y) in all quadrants, handling the signs of both coordinates. double h_1 = atan2(b_1, a_1 * n), h_2 = atan2(b_2, a_2 * n); h_1 += 2.0 * M_PI * (h_1 < 0.0); h_2 += 2.0 * M_PI * (h_2 < 0.0); n = fabs(h_2 - h_1); // Cross-implementation consistent rounding. if (M_PI - 1E-14 < n && n < M_PI + 1E-14) n = M_PI; // When the hue angles lie in different quadrants, the straightforward // average can produce a mean that incorrectly suggests a hue angle in // the wrong quadrant, the next lines handle this issue. double h_m = 0.5 * h_1 + 0.5 * h_2, h_d = (h_2 - h_1) * 0.5; if (M_PI < n) { if (0.0 < h_d) h_d -= M_PI; else h_d += M_PI; h_m += M_PI; } const double p = (36.0 * h_m - 55.0 * M_PI); n = (c_1 + c_2) * 0.5; n = n * n * n * n * n * n * n; // The hue rotation correction term is designed to account for the // non-linear behavior of hue differences in the blue region. const double r_t = -2.0 * sqrt(n / (n + 6103515625.0)) * sin(M_PI / 3.0 * exp(p * p / (-25.0 * M_PI * M_PI))); n = (l_1 + l_2) * 0.5; n = (n - 50.0) * (n - 50.0); // Lightness. const double l = (l_2 - l_1) / (k_l * (1.0 + 0.015 * n / sqrt(20.0 + n))); // These coefficients adjust the impact of different harmonic // components on the hue difference calculation. const double t = 1.0 + 0.24 * sin(2.0 * h_m + M_PI_2) + 0.32 * sin(3.0 * h_m + 8.0 * M_PI / 15.0) - 0.17 * sin(h_m + M_PI / 3.0) - 0.20 * sin(4.0 * h_m + 3.0 * M_PI_2 / 10.0); n = c_1 + c_2; // Hue. const double h = 2.0 * sqrt(c_1 * c_2) * sin(h_d) / (k_h * (1.0 + 0.0075 * n * t)); // Chroma. const double c = (c_2 - c_1) / (k_c * (1.0 + 0.0225 * n)); // Returning the square root ensures that the result represents // the "true" geometric distance in the color space. return sqrt(l * l + h * h + c * c + c * h * r_t); }
    
© www.soinside.com 2019 - 2024. All rights reserved.