以编程方式查找相似的颜色

我在java中有一个缓冲的图像,我想根据颜色值记录每个像素与另一个像素的相似程度。 所以具有“相似”颜色的像素将具有更高的相似度值。 例如,红色和粉红色的相似度值为1000,但红色和蓝色的相似值为300或更小。

我怎样才能做到这一点。 当我从缓冲的Image像素中获取RGB时,它返回一个负整数,我不知道如何用它来实现它。

首先,你如何得到整数值?

获得RGB值后,您可以尝试

((r2-r1) 2 +(g2-g1) 2 +(b2-b1) 21/2

这将为您提供距离两个点的3D空间距离,每个点由(r1,g1,b1)和(r2,g2,b2)指定。

或者使用颜色的HSV值有更复杂的方法。

我建议你从这里开始阅读

色差公式,如果你想这样做。 它解释了用于计算色差的ΔE*abΔE*94ΔE*00ΔE*CMC公式。

HSL是一个糟糕的举动。 L * a * b是一个色彩空间,旨在表示色彩实际上是如何被实现的,并且是基于数百个实验的数据,这些实验涉及真实眼睛看不同颜色的人,并说“我可以分辨出这两者之间的区别。但不是那两个“。

L * a * b空间中的距离表示根据这些实验得出的预测的实际距离。

一旦转换为L * a * b,您只需要测量3D空间中的线性距离。

如果您打算使用HSV,您需要意识到HSV不是三维空间中的点,而是锥体的角度,大小和距离顶部的距离。 要计算HSV值的距离,您需要通过变换确定3d空间中的点。

X = Cos(H)* S * V.

Y = Sin(H)* S * V.

Z = V.

对于这两点,然后取它们之间的欧几里德距离:

 Sqrt((X0 - X1)*(X0 - X1) + (Y0 - Y1)*(Y0 - Y1) + (Z0 - Z1)*(Z0 - Z1)) 

代价为2 Cos,2 Sin和平方根。

或者你可以通过以下方式更容易地计算距离,因为你会意识到当平面化为2D空间时,你只需要从原点得到两个向量,并应用cosign定律来找到XY空间中的距离:

 C² = A² + B² + 2*A*B*Cos(Theta) 

其中A = S * V的第一个值,B = S * V的第二个和cosign是差值theta或H0-H1

然后将因子考虑在内,将2D空间扩展到3D空间。

 A = S0*V0 B = S1*V1 dTheta = H1-H0 dZ = V0-V1 distance = sqrt(dZ*dZ + A*A + B*B + 2*A*B*Cos(dTheta); 

请注意,因为cosigns定律给我们C²,我们只需将其插入Z中即可。它的成本为1 Cos和1 Sqrt。 HSV非常有用,你只需要知道它描述的是什么类型的色彩空间。 你不能只是将它们打成一个欧几里德函数,并从中得到一些连贯的东西。

最简单的方法是将两种颜色转换为HSV值并找出H值的差异。 最小的变化意味着颜色相似。 您可以自定义阈值。

你可能在每个像素上调用getRGB(),它返回的颜色为4 8位字节,高字节alpha,下一个字节为红色,下一个字节为绿色,下一个字节为蓝色。 您需要将频道分开。 即使这样,RGB空间中的颜色相似性也不是很大 – 使用HSL或HSV空间可能会获得更好的结果。 请参阅此处获取转换代码。

换一种说法:

 int a = (argb >> 24) & 0xff; int r = (argb >> 16) & 0xff; int g = (argb >> 8) & 0xff; int b = argb & 0xff; 

我不知道java缓冲图像中的特定字节顺序,但我认为这是对的。

您可以获得单独的字节,如下所示:

 int rgb = bufferedImage.getRGB(x, y); // Returns by default ARGB. int alpha = (rgb >>> 24) & 0xFF; int red = (rgb >>> 16) & 0xFF; int green = (rgb >>> 8) & 0xFF; int blue = (rgb >>> 0) & 0xFF; 

我发现HSL值更容易理解。 HSL Color解释了它们的工作原理并提供了转换程序。 与其他答案一样,您需要确定与您类似的方法。

有一篇关于这个问题的有趣论文:

用于基于内容的图像和video检索 相关颜色相似性测量的新的感知均匀颜色空间 由M. Sarifuddin和Rokia Missaoui提供

您可以使用Google或特别是[Google学术搜索]轻松找到这一点。[1]

总而言之,一些颜色空间(例如RGB,HSV,Lab)和距离测量(例如几何平均和欧几里德距离)是人类对颜色相似性的感知的更好表示。 本文讨论了一种新的色彩空间,它比其他色彩空间更好,但它也提供了对常见的色彩空间和距离测量的良好比较。 定性*,似乎使用常用颜色空间的感知距离的最佳度量是:HSV颜色空间和圆柱距离测量。

*至少,根据参考文献中的图15。

圆柱距离度量(以Latex表示法):

D_ {cyl} = \ sqrt {\ Delta V ^ {2} + S_1 ^ {2} + S_2 ^ {2} -2S_1S_2cos(\ Delta H)}

这是与#1634206类似的问题。

如果您正在寻找RGB空间中的距离,则欧几里德距离将起作用,假设您将红色,绿色和蓝色值均等地处理。

如果您想要对它们进行不同的加权,就像将颜色/ RGB转换为灰度时通常所做的那样,您需要将每个组件加权不同的量。 例如,使用流行的RGB转换为30%红色+ 59%绿色+ 11%蓝色的灰度:

 d2 = (30*(r1-r2))**2 + (59*(g1-g2))**2 + (11*(b1-b2))**2; 

d2的值越小,颜色(r1,g1,b1)(r2,g2,b2)越接近。

但是还有其他颜色空间可供选择,而不仅仅是RGB,这可能更适合您的问题。

颜色感知不是线性的, 因为人眼对某些颜色比其他颜色更敏感。

所以抖动 正确回答

我试了一下。 HSL / HSV值绝对没用。 例如:

  • L = 0的所有颜色都是“黑色”(RGB 000000),尽管它们的HSL差异可能暗示高色距。

  • S = 0的所有颜色都是“灰色”的阴影,尽管它们的HSL差异可能暗示高颜色距离。

  • H(色调)范围以“红色”的阴影开始和结束,因此H = 0且H = [max](360°或100%或240,取决于应用)都是红色的并且彼此相对相似,但欧几里德HSL距离接近最大值。

所以我的建议是使用Euclidean RGB距离(r2-r1)²+(g2-g1)²+(b2-b1)²无根。 (主观)阈值1000然后适用于类似的颜色。 差异> 1000的颜色可以通过人眼很好地区分。 另外,对组件进行不同的加权可能会很有帮助(参见前文)。