Известны ли реализации алгоритма вычисления цветовой разницы CIEDE2000 или CIE94 Delta-E? - PullRequest
13 голосов
/ 09 июля 2011

Мне нужно рассчитать расстояние Delta-E между двумя цветами. Алгоритм для этого с двумя цветами в цветовом пространстве CIELab выглядит следующим образом:

enter image description here

Известны ли реализации этого алгоритма с открытым исходным кодом? Это не сложно реализовать, но из моей последней попытки реализовать алгоритм преобразования цветового пространства я предпочел бы не заново разрабатывать колесо, когда оно уже в дороге и протестировано.

CIEDE2000 тоже подойдет и точнее, но также может быть излишним для iPhone. Полагаю, CIE94 будет в порядке.

Ответы [ 3 ]

4 голосов
/ 24 августа 2013

Существует открытая реализация C # формулы CIE94, которую вы предоставили:

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 голосов
/ 12 июля 2011

Я набрал в уравнении (код 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))
0 голосов
/ 27 января 2014

Существует статья под названием «Формула цветоразностных характеристик CIEDE2000: замечания по реализации, дополнительные данные испытаний и математические наблюдения», автор Sharma et al. кто предложил некоторые исправления в формулировку CIEDE2000 и таблицу значений. Они также прикрепили реализацию для MATLAB и MS Excel здесь: http://www.ece.rochester.edu/~gsharma/ciede2000/

Вы можете легко интегрировать файл Excel в свой проект, чтобы восстановить результаты или заставить работать функцию Matlab в среде C #. Если у вас нет matlab, вы можете легко заставить Octave сделать это за вас. На всякий случай есть руководство по использованию кода Matlab в программах на C #: http://www.mathworks.com/matlabcentral/fileexchange/12987-integrating-matlab-with-c

...