it-swarm.com.ru

Сравните цвета RGB в c #

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

В идеале, я хотел бы получить оценку, которая показывает, насколько они похожи. Например, от 0 до 100, где 100 будет равно, а 0 будет совершенно другим.

Спасибо!

Правка:

Узнав немного больше о цветах из ответов, я понимаю, что мой вопрос был немного расплывчатым. Я постараюсь объяснить, для чего мне это нужно.

У меня есть пиксельные данные (местоположение и цвет) окна приложения размером 800x600, чтобы я мог узнать, открыто ли определенное окно или нет, проверяя каждый x-интервал.

Однако этот метод не работает, как только размер приложения изменяется (содержимое масштабируется, а не перемещается). Я могу рассчитать, где движутся пиксели, но из-за округления и сглаживания цвет может немного отличаться.

Решение Питера было достаточно для меня в этом случае, хотя все остальные ответы также были чрезвычайно полезными, поэтому я просто проголосовал за всех. Я думаю, что ответ ColorEye является наиболее точным, если смотреть на это с профессиональной точки зрения, поэтому я отметил его как ответ.

21
SaphuA

То, что вы ищете, называется Delta-E.

http://www.colorwiki.com/wiki/Delta_E:_The_Color_Difference

Это расстояние между двумя цветами в цветовом пространстве LAB. Говорят, что человеческий глаз не может различить цвета ниже 1 DeltaE (я считаю, что мои глаза могут находить различия в цветах ниже 1 DeltaE, каждый человек индивидуален).

Есть 4 формулы для «разницы в цвете».

  • Дельта E (CIE 1976) 
  • Дельта E (CIE 1994) 
  • Дельта E (CIE 2000) 
  • Дельта E (CMC) 

Проверьте математическую ссылку на этом сайте:

Таким образом, правильный ответ - преобразовать ваш RGB в LAB, используя приведенную формулу, а затем используйте DeltaE 1976, чтобы определить «разницу» в ваших цветах. Результат 0 будет означать идентичные цвета. Любое значение выше 0 можно судить по правилу «Дельта 1 или меньше для большинства людей неразличима».

19
ColorEyes

Цвета имеют различный вес, влияющий на человеческий глаз ... Поэтому преобразуйте цвета в оттенки серого, используя их рассчитанные веса:

Серый цвет = . 11 * B + . 59 * G + . 30 * R

И ваша разница будет (GrayColor1 - GrayColor2) * 100,0/256,0

На самом деле это широко используемый и очень простой подход, который используется для расчета различий в изображениях при обработке изображений.

-edit Это очень простая и все еще используемая формула - даже в коммерческих приложениях . Если вы хотите углубиться, вы должны проверить методы разницы в цвете: CIE1976, CIE1994, CIE2000 и CMC Здесь Вы можете найти более подробную информацию: http://en.wikipedia.org/wiki/Color_difference

11
honibis

Преобразование цвета RGB в цветовое пространство HSL часто дает хорошие результаты. Проверьте Википедию для формулы преобразования. Вы должны назначить веса для различий в H, цвете, S, насколько «глубокий» цвет и L, насколько он яркий.

11
Hans Passant

Существует библиотека с открытым исходным кодом .net, которая позволяет вам сделать это легко: https://github.com/THEjoezack/ColorMine

Наиболее распространенным методом сравнения цветов является CIE76 :

var a = new Rgb { R = 149, G = 13, B = 12 }
var b = new Rgb { R = 255, G = 13, B = 12 }

var deltaE = a.Compare(b,new Cie1976Comparison());
11
Joe Zack

Что-то вроде этого:

    public static int CompareColors(Color a, Color b)
    {
        return 100 * (int)(
            1.0 - ((double)(
                Math.Abs(a.R - b.R) +
                Math.Abs(a.G - b.G) +
                Math.Abs(a.B - b.B)
            ) / (256.0 * 3))
        );
    }
9
Pieter van Ginkel

Восприятие цвета зависит от многих факторов, и сходство можно измерить разными способами. Простое сравнение того, насколько похожи компоненты R, G и B, обычно дает результаты, с которыми люди не согласятся. 

Есть некоторый общий материал о сравнениях цветов в Википедии и о работе с естественными цветовыми пространствами в C # in этот вопрос

6
Pontus Gagge

Я нашел интересный подход под названием Color metric и адаптировал его к C #

public static double ColourDistance(Color e1, Color e2)
{
    long rmean = ((long)e1.R + (long)e2.R) / 2;
    long r = (long)e1.R - (long)e2.R;
    long g = (long)e1.G - (long)e2.G;
    long b = (long)e1.B - (long)e2.B;
    return Math.Sqrt((((512 + rmean) * r * r) >> 8) + 4 * g * g + (((767 - rmean) * b * b) >> 8));
}
3
fubo

Я перевел код для DeltaE2000 на странице Брюса Линдблума на C. 

Вот:

     //
     //  deltae2000.c
     //
     //  Translated by Dr Cube on 10/1/16.
     //  Translated to C from this javascript code written by Bruce LindBloom:
     //    http://www.brucelindbloom.com/index.html?Eqn_DeltaE_CIE2000.html
     //    http://www.brucelindbloom.com/javascript/ColorDiff.js

     #include <stdio.h>
     #include <math.h>

     #define Lab2k struct Lab2kStruct
     Lab2k
     {
        float L;
        float a;
        float b;
     };

     // function expects Lab where: 0 >= L <=100.0 , -100 >=a <= 100.0  and  -100 >= b <= 100.0

     float
     DeltaE2000(Lab2k Lab1,Lab2k Lab2)
     {
        float kL = 1.0;
        float kC = 1.0;
        float kH = 1.0;
        float lBarPrime = 0.5 * (Lab1.L + Lab2.L);
        float c1 = sqrtf(Lab1.a * Lab1.a + Lab1.b * Lab1.b);
        float c2 = sqrtf(Lab2.a * Lab2.a + Lab2.b * Lab2.b);
        float cBar = 0.5 * (c1 + c2);
        float cBar7 = cBar * cBar * cBar * cBar * cBar * cBar * cBar;
        float g = 0.5 * (1.0 - sqrtf(cBar7 / (cBar7 + 6103515625.0)));  /* 6103515625 = 25^7 */
        float a1Prime = Lab1.a * (1.0 + g);
        float a2Prime = Lab2.a * (1.0 + g);
        float c1Prime = sqrtf(a1Prime * a1Prime + Lab1.b * Lab1.b);
        float c2Prime = sqrtf(a2Prime * a2Prime + Lab2.b * Lab2.b);
        float cBarPrime = 0.5 * (c1Prime + c2Prime);
        float h1Prime = (atan2f(Lab1.b, a1Prime) * 180.0) / M_PI;
        float dhPrime; // not initialized on purpose

        if (h1Prime < 0.0)
           h1Prime += 360.0;
        float h2Prime = (atan2f(Lab2.b, a2Prime) * 180.0) / M_PI;
        if (h2Prime < 0.0)
           h2Prime += 360.0;
        float hBarPrime = (fabsf(h1Prime - h2Prime) > 180.0) ? (0.5 * (h1Prime + h2Prime + 360.0)) : (0.5 * (h1Prime + h2Prime));
        float t = 1.0 -
        0.17 * cosf(M_PI * (      hBarPrime - 30.0) / 180.0) +
        0.24 * cosf(M_PI * (2.0 * hBarPrime       ) / 180.0) +
        0.32 * cosf(M_PI * (3.0 * hBarPrime +  6.0) / 180.0) -
        0.20 * cosf(M_PI * (4.0 * hBarPrime - 63.0) / 180.0);
        if (fabsf(h2Prime - h1Prime) <= 180.0)
           dhPrime = h2Prime - h1Prime;
        else
           dhPrime = (h2Prime <= h1Prime) ? (h2Prime - h1Prime + 360.0) : (h2Prime - h1Prime - 360.0);
        float dLPrime = Lab2.L - Lab1.L;
        float dCPrime = c2Prime - c1Prime;
        float dHPrime = 2.0 * sqrtf(c1Prime * c2Prime) * sinf(M_PI * (0.5 * dhPrime) / 180.0);
        float sL = 1.0 + ((0.015 * (lBarPrime - 50.0) * (lBarPrime - 50.0)) / sqrtf(20.0 + (lBarPrime - 50.0) * (lBarPrime - 50.0)));
        float sC = 1.0 + 0.045 * cBarPrime;
        float sH = 1.0 + 0.015 * cBarPrime * t;
        float dTheta = 30.0 * expf(-((hBarPrime - 275.0) / 25.0) * ((hBarPrime - 275.0) / 25.0));
        float cBarPrime7 = cBarPrime * cBarPrime * cBarPrime * cBarPrime * cBarPrime * cBarPrime * cBarPrime;
        float rC = sqrtf(cBarPrime7 / (cBarPrime7 + 6103515625.0));
        float rT = -2.0 * rC * sinf(M_PI * (2.0 * dTheta) / 180.0);
        return(sqrtf(
                           (dLPrime / (kL * sL)) * (dLPrime / (kL * sL)) +
                           (dCPrime / (kC * sC)) * (dCPrime / (kC * sC)) +
                           (dHPrime / (kH * sH)) * (dHPrime / (kH * sH)) +
                           (dCPrime / (kC * sC)) * (dHPrime / (kH * sH)) * rT
                      )
         );
     }
0
EddingtonsMonkey