java 以编程方式查找相似的颜色
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1725505/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
finding similar colors programmatically
提问by anon
I have a buffered image in java and I want to record how similar each pixel is to another based on the color value. so the pixels with 'similar' colors will have a higher similarity value. for example red and pink will have a similarity value 1000 but red and blue will have something like 300 or less.
我在 java 中有一个缓冲图像,我想根据颜色值记录每个像素与另一个像素的相似程度。因此具有“相似”颜色的像素将具有更高的相似度值。例如,红色和粉色的相似度值为 1000,但红色和蓝色的相似度值为 300 或更少。
how can I do this. when I get the RGB from a buffered Image pixel it returns a negative integer I am not sure how to implement this with that.
我怎样才能做到这一点。当我从缓冲的图像像素获取 RGB 时,它返回一个负整数,我不确定如何用它来实现。
回答by lavinio
First, how are you getting the integer value?
首先,你如何获得整数值?
Once you get the RGB values, you could try
获得RGB值后,您可以尝试
((r2 - r1)2+ (g2 - g1)2+ (b2 - b1)2)1/2
((r2 - r1) 2+ (g2 - g1) 2+ (b2 - b1) 2) 1/2
This would give you the distance in 3D space from the two points, each designated by (r1,g1,b1) and (r2,g2,b2).
这将为您提供 3D 空间中两个点的距离,每个点由 (r1,g1,b1) 和 (r2,g2,b2) 指定。
Or there are more sophisticated ways using the HSV value of the color.
或者有更复杂的方法使用颜色的 HSV 值。
回答by jitter
I suggest you start reading here
我建议你从这里开始阅读
Color difference formulasif you want to do this right. It explains the ΔE*ab, ΔE*94, ΔE*00and ΔE*CMCformulas for calculating color difference.
如果您想正确地做到这一点,请使用色差公式。它解释了ΔE*ab,ΔE*94,ΔE*00并ΔE*CMC计算色差公式。
回答by Breton
HSL is a bad move. L*a*b is a color space designed to represent how color is actually percieved, and is based on data from hundreds of experiments involving people with real eyes looking at different colors and saying "I can tell the difference between those two. But not those two".
HSL 是一个糟糕的举动。L*a*b 是一个颜色空间,旨在表示颜色的实际感知方式,它基于数百个实验的数据,这些实验涉及用真眼观察不同颜色的人并说“我可以分辨出这两者之间的区别。但不能那两个”。
Distance in L*a*b space represents actual percieved distance according to the predictions derived from those experiments.
L*a*b 空间中的距离代表根据这些实验得出的预测的实际感知距离。
Once you convert into L*a*b you just need to measure linear distance in a 3D space.
转换为 L*a*b 后,您只需要测量 3D 空间中的线性距离。
回答by Tatarize
If you are going to use HSV you need to realize that HSV are not points in a three dimensional space but rather the angle, magnitude, and distance-from-top of a cone. To calculate the distance of an HSV value you either need to determine your points in 3d space by transforming.
如果您打算使用 HSV,您需要意识到 HSV 不是三维空间中的点,而是锥体的角度、大小和距顶部的距离。要计算 HSV 值的距离,您需要通过变换来确定 3d 空间中的点。
X = Cos(H)*S*V
X = Cos(H)*S*V
Y = Sin(H)*S*V
Y = Sin(H)*S*V
Z = V
Z = V
For both points and then taking the Euclidian distance between them:
对于两个点,然后取它们之间的欧几里得距离:
Sqrt((X0 - X1)*(X0 - X1) + (Y0 - Y1)*(Y0 - Y1) + (Z0 - Z1)*(Z0 - Z1))
At a cost of 2 Cos, 2 Sin, and a square root.
成本为 2 Cos、2 Sin 和平方根。
Alternatively you can actually calculate distance a bit more easily if you're so inclined by realizing that when flattened to 2D space you simply have two vectors from the origin, and applying the law of cosign to find the distance in XY space:
或者,如果您意识到当展平到 2D 空间时,您只需从原点获得两个向量,并应用余弦定理来找到 XY 空间中的距离,那么您实际上可以更轻松地计算距离:
C2 = A2 + B2 + 2*A*B*Cos(Theta)
Where A = S*V of the first value, and B = S*V of the second and cosign is the difference theta or H0-H1
其中 A = 第一个值的 S*V,而 B = 第二个值的 S*V,余弦是 theta 或 H0-H1 的差值
Then you factor in Z, to expand the 2D space into 3D space.
然后将 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);
Note that because the law of cosigns gives us C2 we just plug it right in there with the change in Z. Which costs 1 Cos and 1 Sqrt. HSV is plenty useful, you just need to know what type of color space it's describing. You can't just slap them into a euclidian function and get something coherent out of it.
请注意,因为余弦定律为我们提供了 C2,所以我们只需将其插入到 Z 的变化中即可。这需要 1 Cos 和 1 Sqrt。HSV 非常有用,您只需要知道它所描述的颜色空间类型。你不能只是把它们变成欧几里得函数并从中得到一些连贯的东西。
回答by EmFi
The easiest is to convert both colours to HSV value and find the difference in H values. Minimal changes means the colours are similar. It's up to you to define a threshold though.
最简单的方法是将两种颜色都转换为 HSV 值并找出 H 值的差异。最小的变化意味着颜色相似。不过,由您来定义阈值。
回答by plinth
You're probably calling getRGB() on each pixel which is returning the color as 4 8 bits bytes, the high byte alpha, the next byte red, the next byte green, the next byte blue. You need to separate out the channels. Even then, color similarity in RGB space is not so great - you might get much better results using HSL or HSV space. See herefor conversion code.
您可能在每个像素上调用 getRGB() ,它以 4 个 8 位字节返回颜色,高字节 alpha,下一个字节红色,下一个字节绿色,下一个字节蓝色。您需要将通道分开。即便如此,RGB 空间中的颜色相似性也不是那么好 - 使用 HSL 或 HSV 空间可能会获得更好的结果。请参阅此处获取转换代码。
In other words:
换句话说:
int a = (argb >> 24) & 0xff;
int r = (argb >> 16) & 0xff;
int g = (argb >> 8) & 0xff;
int b = argb & 0xff;
I don't know the specific byte ordering in java buffered images, but I think that's right.
我不知道 java 缓冲图像中的具体字节顺序,但我认为这是正确的。
回答by BalusC
You could get the separate bytes as follows:
您可以按如下方式获取单独的字节:
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;
回答by camickr
回答by Tim Gee
There's an interesting paper on exactly this problem:
有一篇关于这个问题的有趣论文:
A New Perceptually Uniform Color Space with Associated Color Similarity Measure for Content-Based Image and Video Retrievalby M. Sarifuddin and Rokia Missaoui
M. Sarifuddin 和 Rokia Missaoui用于基于内容的图像和视频检索的具有相关颜色相似性度量的新感知均匀颜色空间
You can find this easily using Google or in particular [Google Scholar.][1]
您可以使用 Google 或特别是 [Google Scholar.][1] 轻松找到此信息
To summarise, some color spaces (e.g. RGB, HSV, Lab) and distance measures (such as Geometric mean and Euclidean distance) are better representations of human perception of color similarity than others. The paper talks about a new color space, which is better than the rest, but it also provides a good comparison of the common existing color spaces and distance measures. Qualitatively*, it seems the best measure for perceptual distance using commonly available color spaces is : the HSV color space and a cylindrical distance measure.
总而言之,某些颜色空间(例如 RGB、HSV、Lab)和距离度量(例如几何均值和欧几里得距离)比其他颜色空间更能代表人类对颜色相似性的感知。这篇论文讨论了一种新的色彩空间,它比其他的要好,但它也提供了对常见的现有色彩空间和距离度量的很好的比较。定性地*,似乎使用常用颜色空间的感知距离的最佳度量是:HSV 颜色空间和圆柱距离度量。
*At least, according to Figure 15 in the referenced paper.
*至少,根据参考论文中的图 15。
The cylindrical distance measure is (in Latex notation):
圆柱距离度量为(以 Latex 表示法):
D_{cyl} = \sqrt{\Delta V^{2}+S_1^{2}+S_2^{2}-2S_1S_2cos(\Delta H)}
D_{cyl} = \sqrt{\Delta V^{2}+S_1^{2}+S_2^{2}-2S_1S_2cos(\Delta H)}
回答by Pylyp
Color perception is not linear because the human eye is more sensitive to certain colors than others.
颜色感知不是线性的,因为人眼对某些颜色比其他颜色更敏感。

