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

Java 以编程方式查找相似颜色,java,colors,Java,Colors,我有一个java缓冲图像,我想根据颜色值记录每个像素与另一个像素的相似程度。因此,具有“相似”颜色的像素将具有更高的相似值。例如,红色和粉色的相似度值为1000,但红色和蓝色的相似度值约为300或更小 我怎样才能做到这一点。当我从缓冲图像像素获取RGB时,它会返回一个负整数。我不知道如何用它实现这一点。首先,如何获取整数值 获得RGB值后,可以尝试 ((r2-r1)2+(g2-g1)2+(b2-b1)2)1/2 这将在3D空间中显示两个点之间的距离,每个点由(r1、g1、b1)和(r2、g2、b

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


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

首先,如何获取整数值

获得RGB值后,可以尝试

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

这将在3D空间中显示两个点之间的距离,每个点由(r1、g1、b1)和(r2、g2、b2)指定


或者有更复杂的方法使用颜色的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;

我建议你从这里开始阅读


如果你想把这件事做好。它解释了计算色差的
ΔE*ab
ΔE*94
ΔE*00
ΔE*CMC
公式。

我发现HSL值更容易理解。解释它们如何工作,并提供转换例程。就像另一个答案一样,你需要确定similiar对你意味着什么。

HSL是一个糟糕的举动。L*a*b是一个颜色空间,设计用来表示人们对颜色的实际感知,它基于数百个实验的数据,这些实验涉及到人们的真实眼睛看着不同的颜色,并说“我能分辨出这两种颜色之间的区别,但不能分辨出这两种颜色”

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


转换成L*a*b后,只需在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);
如果您在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之外,还有其他颜色空间可供选择,RGB可能更适合您的问题。

我尝试过。HSL/HSV值绝对没有用处。例如:

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

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

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


因此,我建议使用不带根的欧几里德RGB距离(r2-r1)²+(g2-g1)²+(b2-b1)²。然后(主观)阈值1000适用于类似颜色。色差大于1000的颜色可以通过人眼很好地分辨。此外,以不同的方式对组件进行称重也很有帮助(参见上一篇文章)。

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

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空间时,你只需要从原点得到两个向量,然后应用余弦定律来计算XY空间中的距离:

C² = A² + B² + 2*A*B*Cos(Theta)
其中,A=第一个值的S*V,B=第二个值的S*V,余弦为差值θ或H0-H1

然后将Z因子引入,将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);

注意,因为余弦定律给了我们C²,我们就把它插在这里,Z的变化值为1 Cos和1 Sqrt。HSV非常有用,你只需要知道它描述的是什么类型的颜色空间。你不能只是把它们放入欧几里德函数中,然后从中得到连贯的东西。

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

一种用于基于内容的图像和视频检索的具有相关颜色相似性度量的新的感知均匀颜色空间 作者:M.Sarifuddin和Rokia Missaoui

您可以使用Google,特别是[Google Scholar.][1]轻松找到这一点

总之,一些颜色空间(例如RGB、HSV、Lab)和距离度量(例如几何平均值和欧几里德距离)比其他颜色空间更好地表示了人类对颜色相似性的感知。本文讨论了一种新的颜色空间,它比其他颜色空间更好,但它也提供了一个很好的比较t