比较c#中的RGB颜色

我正试图找到一种比较两种颜色的方法,以找出它们的相似之处。 我似乎无法找到有关该主题的任何资源,所以我希望在这里得到一些指示。

理想情况下,我想得到一个分数,告诉他们有多相似。 例如,0到100,其中100将相等,0将完全不同。

谢谢!

编辑:

从答案中了解更多关于颜色的知识我理解我的问题有点模糊。 我会尝试解释我需要的东西。

我有800×600大小的应用程序窗口的pixeldata(位置和颜色),所以我可以通过检查每个x间隔来查明某个窗口是否打开。

但是,一旦调整应用程序的大小(内容被缩放,而不是移动),此方法就会失败。 我可以计算出像素移动的位置,但由于四舍五入和防眩化,颜色可能略有不同。

在这种情况下,彼得的解决方案对我来说已经足够了,尽管其他所有回复都非常有用,所以我只是向所有人投了赞成票。 我确实认为ColorEye的答案是从专业方式看这个问题时最准确的,所以我将其标记为答案。

您正在寻找的是Delta-E

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

它是LAB颜色空间中两种颜色之间的距离。 据说人眼无法区分1 DeltaE以下的颜色(我发现我的眼睛可以找到低于1 DeltaE的颜色差异,每个人都不同。)

‘色差’有4个公式。

  • Delta E(CIE 1976)
  • Delta E(CIE 1994)
  • Delta E(CIE 2000)
  • Delta E(CMC)

检查本网站上的数学链接:

所以正确的答案是使用给定的公式将RGB转换为LAB,然后使用DeltaE 1976来确定颜色的“差异”。 0的结果表示相同的颜色。 任何高于0的值都可以通过以下规则判断:“大多数人无法区分1或更小的delta e”。

颜色有不同的重量影响人眼。 因此,使用计算出的权重将颜色转换为灰度:

灰色= .11 * B + .59 * G + .30 * R.

你的差异将是(GrayColor1 – GrayColor2)* 100.0 / 256.0

这实际上是常用的,非常简单的方法,用于计算图像处理中的图像差异。

– 这是一个非常简单且仍然可用的公式 – 即使在商业应用中也是如此。 如果你想要深入,你应该看看名为CIE1976,CIE1994,CIE2000和CMC的色差方法。在这里你可以找到更详细的信息: http : //en.wikipedia.org/wiki/Color_difference

将RGB颜色转换为HSL颜色空间通常会产生良好的结果。 检查维基百科的转换公式。 您可以根据H,颜色,S,颜色的“深度”和L的差异来分配权重,它是多么明亮。

有一个开源的.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()); 

像这样的东西:

  public static int CompareColors(Color a, Color b) { return 100 * (int)( 1.0 - ((double)( Math.Abs(aR - bR) + Math.Abs(aG - bG) + Math.Abs(aB - bB) ) / (256.0 * 3)) ); } 

颜色感知取决于许多因素,并且可以通过多种方式测量相似性。 只是比较R,G和B组分的相似程度通常会得出人们不同意的结果。

在维基百科中有一些关于颜色比较的一般材料 ,以及在这个问题中使用C#中的自然颜色空间 。

我发现了一种名为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)); } 

我已经将Bruce Lindbloom页面上的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  #include  #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 ) ); }