给定一个颜色的RGB分量,如何确定人类是否会将其视为灰色?

3

一个简单的方法是当RGB颜色值相等时,它们形成灰色。

然而,这并不是全部,因为如果它们只有微小的差异,它们仍然看起来是灰色的。

假设观察者具有良好的色彩视觉,我如何确定给定的值是否会被感知为灰色(可能需要可调节的“灰度”阈值)?


看这个: https://dev59.com/8Wkw5IYBdhLWcg3wlroa - user2318700
2个回答

4
一个相对简单的方法是将RGB值转换为HSV颜色空间,并在饱和度分量上使用阈值,例如"如果饱和度小于0.05,则为'几乎灰色',否则不是灰色"
实际上,饱和度按定义就是“灰度/彩度”。
这种方法比使用R、G和B通道之间的差异要准确得多(因为人眼在光亮和暗淡的颜色上感知饱和度不同)。另一方面,将RGB转换为HSV需要计算量大。由您决定哪个更有价值-精确答案(灰色/非灰色)还是性能。
如果您需要更精确的方法,可以使用L*a*b*颜色空间并计算色度为sqrt(a*a + b*b)(请参见此处),然后对该值进行阈值处理。但是,这将会使计算量更大。
您还可以结合多种方法
  • 计算R、G、B三个分量之间的简单差异。如果颜色可以被确定为明显不饱和(例如,max(abs(R-G), abs(R-B), abs(G-B)) <= 5),或者明显饱和(例如,max(abs(R-G), abs(R-B), abs(G-B)) > 100),则停止。

  • 否则,转换为L*a*b*,计算色度值为sqrt(a*a + b*b),并对该值进行阈值处理。


谢谢。实际上我正在使用Color.GetSaturation(),我认为它会在内部转换为HSV。然而,在这个应用程序中速度不是一个问题。感谢您的建议。 - Tamás Szelei
@fish:不用谢!你说得对,Color.GetSaturation()返回HSB空间中的亮度组件(HSB与我在这个答案中提到的HSV非常相似)。 - Alex Shesterov
1
亮度?我认为它返回饱和度(文档也是这么说的)。 - Tamás Szelei
@fish:哦,抱歉,那是我的一个愚蠢的打字错误...当然,它返回饱和度 :) 亮度/值对你的目的完全没有重要性。 - Alex Shesterov
@PeterO。感谢您的留言,但这并不完全正确。以下是公式(适用于除 RGB(0,0,0) 之外的值):饱和度 = (MAX(R, G, B) - MIN(R, G, B)) / MAX(R, G, B)当然,计算色调和亮度并非必要,可以避免。 - Alex Shesterov
显示剩余2条评论

0

r = 160; g = 179; b = 151;

tolerance = 20;

如果 (Math.abs(r-g) < 20 && Math.abs(r-b) < 20) { #则被视为灰色 }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接