RGB相似颜色近似算法

7
鉴于在RGB中,我们可以表示256^3=16,777,216种颜色组合,而人眼只能区分大约10,000,000种颜色,很明显,还有6,777,216种RGB组合与对应的颜色在色彩上是无法区分的。

压缩算法基于此原理,在近似处理帧范围内颜色差异方面发挥作用。考虑到这一点,如何可靠计算给定颜色是否与另一个颜色的“相似范围”之内呢?

当然,“相似性”将是一些可以调整的任意/可调参数,但这只是一个近似值。那么,有没有一些指针、伪代码、直观的代码示例或资源来帮助我建立这样的函数呢?

非常感谢您的帮助。


你说“超过6,777,216”的时候,好像有将近一半的信息被浪费了。但事实并非如此。这6,777,216种颜色占据了信息的1-log2(1000000)/24即3.11%。不要指望用它来压缩! - sam hocevar
1
多年过去了,这个问题仍然似乎很相关。如果有帮助的话,我最近写了一篇关于使用HSL的不同解决方案的文章在这里 - Darius
3个回答

12

计算颜色之间的距离有许多方法,最简单的方法是在任何颜色空间中定义颜色组件。这些是RGB颜色(r1,g1,b1)和(r2,g2,b2)之间的常见“距离”或指标:

  • L1:abs(r1-r2) + abs(g1-g2) + abs(b1-b2)
  • L2:sqrt((r1-r2)² + (g1-g2)² + (b1-b2)²)
  • L:max(abs(r1-r2), abs(g1-g2), abs(b1-b2))

然而这些距离并没有考虑到人类视觉对于颜色的敏感程度不及亮度。为了获得最佳结果,应该将RGB转换为一种将亮度和颜色分别编码的颜色空间。然后在新的颜色空间中使用上述指标之一,可能会给予亮度成分更多权重,颜色成分较少。

彼此无法区分的颜色区域称为MacAdam椭圆。在CIELUVCIELAB颜色空间中,这些椭圆变得近似圆形,非常适合计算,但不幸的是,从RGB进入这些颜色空间并不那么简单。

JPEG将颜色转换为YCbCr,其中Y是亮度,两个C编码颜色,然后将C分量的分辨率减半。您可以执行相同的操作,然后使用上述指标的加权版本,例如:

diff = sqrt(1.4*sqr(y1-y2) + .8*sqr(cb1-cb2) + .8*sqr(cr1-cr2)) 

维基百科上有一篇关于颜色差异的文章,其中提供了不同颜色空间的更多示例。


这真的很棒,谢谢你的建议。近似颜色是一项棘手的业务! - Darius

6
感知色差可以使用CIEDE2000颜色差公式进行计算。CIEDE2000公式基于LCH颜色空间(亮度、色度和色相)进行计算。LCH颜色空间表示为一个圆柱体(见此处的图像)。
一个不太准确(但更易管理)的模型是基于Lab color space ( L*a*b*)CIE76颜色差异公式。RGB或CMYK值与L*a*b*之间没有简单的转换公式,因为RGB和CMYK颜色模型是设备相关的。RGB或CMYK值首先需要转换为特定的绝对颜色空间,例如sRGB或Adobe RGB。这种调整将取决于设备,但转换后的数据将是设备无关的,允许数据转换到CIE 1931颜色空间,然后转换为L*a*b*。本文解释了该过程和公式。

非常棒的资源!让我回忆起了我在本科时学习色彩感知的图形模块。感谢您提供的指引。 - Darius

1

RGB颜色系统的设计是这样的,如果两种颜色的值相近,那么它们在感知上也会很接近。

例如:

RGB =(100,100,100)定义的颜色在感知上几乎与颜色RGB =(101,101,100),RGB =(98,100,99)等相同...


那么,任何一列中可能的n<5的方差程度都不应该产生可察觉的色差差异,对吧?这是测试的好起点,谢谢。 - Darius
是的。尝试使用这个在线工具进行测试:颜色方案 - Krešimir Lukin
请注意,您必须逐个组件地检查值的接近程度,不能仅仅通过 (color1 - color2) < 阈值 来判断,因为这样会受到数据表示方式的影响。这一点很明显,但也可能是一个陷阱。 - Thomas

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