将RGB转换为灰度/强度

151

将RGB转换为灰度时,据说应该应用特定的通道R、G和B权重。这些权重是:0.2989、0.5870、0.1140。

据说原因是人类对这三种颜色的感知/敏感度不同。有时也说这些值用于计算NTSC信号。

然而,我在网上没有找到一个好的参考。这些值的来源是什么?

还可以看看之前的这些问题:这里这里


CCIR 601。请参阅维基百科片段:http://en.wikipedia.org/wiki/Luma_(video)#Rec._601_luma_versus_Rec._709_luma_coefficients - David Jones
2
@pnizzle http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC9 - ypnos
8个回答

101

问题中的具体数字来自于CCIR 601(参见Wikipedia文章)。

如果你用稍微不同的数字或方法将RGB转换为灰度, 在普通计算机屏幕下,在正常光照条件下,你几乎看不到任何区别——试试吧。

以下是一些关于颜色的链接:

维基百科亮度(Luma)

Bruce Lindbloom的优秀网站

Colin Ware的书《Information Visualization》的第4章,ISBN 1-55860-819-2; Ware在books.google.com 的这个长链接可能可用也可能不可用

cambridgeincolor: 出色、写作精良, “使用以概念为重点而非过程的视觉方法来获取、解释和处理数字照片的教程”

如果你遇到“线性”与“非线性”RGB, 这里是我自己关于此问题的一部分旧笔记。 重申,实际上你几乎看不到什么区别。


### RGB -> ^gamma -> Y -> L*

在色彩科学中,通常的RGB值,如html rgb(10%,20%,30%), 被称为“非线性”或 伽玛校正。 “线性”值的定义为

Rlin = R^gamma,  Glin = G^gamma,  Blin = B^gamma

众所周知,许多个人电脑中的 gamma 值为 2.2。

通常情况下,R、G、B 有时被写作 R'、G'、B'(其中 R' = Rlin ^ (1/gamma))。 (纯粹主义者会挑剔这种写法)但在这里,我会将这个标识符省略。

CRT 显示器上的亮度与 RGBlin = RGB ^ gamma 成正比, 因此 CRT 上的 50% 灰色相当暗淡:.5 ^ 2.2 = 最大亮度的22%。 (液晶显示器更加复杂; 此外,一些显卡会补偿 gamma 值。)

要从 RGB 获得称为 L* 的亮度测量值, 首先将 R、G、B 分别除以 255,并计算:

Y = .2126 * R^gamma + .7152 * G^gamma + .0722 * B^gamma

这是在XYZ颜色空间中的Y,它是颜色“亮度”的一种度量。(真实公式并不完全是x^gamma,但接近;初步使用x^gamma即可)。

最后,

L* = 116 * Y ^ 1/3 - 16

"...渴望色觉均匀性,并且与人类对亮度的感知非常接近。"-- 维基百科LAB颜色空间


9
Y = 0.2126 * R + 0.7152 * G + 0.0722 * B 是将 RGB 颜色空间转换为灰度图像的公式,其中 R、G 和 B 分别表示红色、绿色和蓝色通道的亮度值。该公式可以在维基百科的灰度页面(http://en.wikipedia.org/wiki/Grayscale)中找到。 - iamantony
你好,我能通过将RGB彩色图像显示为灰度图像来获得等效的全色图像吗?或者说,是否可以将从RGB转换而来的HIS格式图像的强度分量表示为全色图像? - emberbillow
@emberbillow,将颜色映射到灰度有许多方法,其中一些可能足够好,有时候会起作用。你使用的是什么程序?你有没有阅读过它的文档?你可以在几张你自己的测试图像上尝试并查看效果。 - denis

17

我在之前的类似问题的答案中找到了这篇参考文献,很有帮助,页面包含了几个示例图像:

《颜色转灰度图像的感知评估》,作者Martin Čadík,发表于2008年的《计算机图形学论坛》(Computer Graphics Forum)

该出版物探讨了使用多种方法生成不同结果的灰度图像:

  • CIE Y
  • Color2Gray
  • Decolorize
  • Smith08
  • Rasche05
  • Bala04
  • Neumann07

有趣的是,它得出结论:没有普适的最佳转换方法,因为每种方法在输入上的表现都有好坏之分。


9
这是一段用C语言将RGB转换为灰度图像的代码。 RGB到灰度的真实权重为0.3R+0.6G+0.11B。 这些权重并不是绝对关键的,所以你可以尝试调整它们。 我已经将它们设置为0.25R+0.5G+0.25B。这会产生略微较暗的图像。 注意:以下代码假设xRGB为32位像素格式。
unsigned int *pntrBWImage=(unsigned int*)..data pointer..;  //assumes 4*width*height bytes with 32 bits i.e. 4 bytes per pixel
unsigned int fourBytes;
        unsigned char r,g,b;
        for (int index=0;index<width*height;index++)
        {
            fourBytes=pntrBWImage[index];//caches 4 bytes at a time
            r=(fourBytes>>16);
            g=(fourBytes>>8);
            b=fourBytes;

            I_Out[index] = (r >>2)+ (g>>1) + (b>>2); //This runs in 0.00065s on my pc and produces slightly darker results
            //I_Out[index]=((unsigned int)(r+g+b))/3;     //This runs in 0.0011s on my pc and produces a pure average
        }

2
0.3、0.6、0.11不加起来等于1。维基百科似乎建议使用0.30、0.59、0.11。 - damix911
真的,但是它们不相加为1的唯一结果将是强度的微小变化。建议的0.25、0.5、0.25方法确实相加为1,但如果没有也无所谓。这是一种优化,因此放弃一点精度是一个合理的权衡。 - twerdster
4
@twerdster,两组系数都不正确。0.3、0.6、0.11是旧的NTSC标准,而不是网络和大多数电脑使用的sRGB/Rec709。而你的0.25、0.5、0.25并不合理——B仅占亮度的7%,你的错误率高达347%。sRGB/r709(线性化后)的系数为:Rlin * 0.2126 + Glin * 0.7152 + Blin * 0.0722 = Y 这些光谱权重是从人类视觉感知推导出来的。你不能随意插入任何数字以方便计算并希望准确无误。你需要将sRGB进行线性化,然后应用正确的系数。 - Myndex
如果你处于除法过于昂贵的情况下,可以使用一个单一的移位和加法乘法近似值:0.11111111 * ((G + (G<<1) + R) <<1) + B)。这相当于(2*R+6*G+B) / 9)0.222 R + 0.666 G + 0.111 B。在进入生产之前,请将其与各种测试用例的准确公式进行比较。 - ToolmakerSteve

6

请查看颜色常见问题解答,了解相关信息。这些数值来自于我们在显示器中使用的RGB数值的标准化。实际上,根据颜色常见问题解答,您使用的数值已经过时,因为它们是用于原始NTSC标准而不是现代显示器的数值。


3

这些值的来源是什么?

这些系数的“来源”是可以在Rec601Characteristics of Television中看到的NTSC规格说明。

“最终来源”是CIE约1931年对人类色彩感知的实验。人类视觉的光谱响应并不均匀。实验导致基于感知加权的三刺激值。我们的L、M和S锥体1对我们所认定为“红色”、“绿色”和“蓝色”的光波长敏感,这就是三刺激值的原色派生的地方。2

sRGB(和Rec709)的线性光3光谱加权如下:

Rlin * 0.2126 + Glin * 0.7152 + Blin * 0.0722 = Y

的翻译结果是:

Rlin * 0.2126 + Glin * 0.7152 + Blin * 0.0722 = Y


这些公式适用于sRGB和Rec709颜色空间,旨在表示计算机监视器(sRGB)或HDTV监视器(Rec709),详细信息可以在ITU文档Rec709BT.2380-2 (10/2018)中找到。 脚注 (1) 锥细胞是眼睛视网膜中的色彩感知细胞。
(2) 然而,所选择的三刺激值波长并非每种锥体类型的“峰值”,而是选择这些三刺激值以使它们在某些锥体类型上的刺激远大于其他类型,即刺激分离。
(3) 在应用系数之前,您需要线性化您的sRGB值。我在另一个答案中讨论了这个问题。

1

-2

这些值因人而异,尤其是对于色盲的人来说。


我不明白为什么人们对这篇帖子点踩。 没错。我们使用的是一个平均值,足够好,但评论超过了相关程度。 - Alexis Martial

-8

这一切真的有必要吗?人类感知和CRT与LCD会有所不同,但RGB强度却不会。为什么不使用L = (R + G + B)/3并将新的RGB设置为L、L、L呢?


9
简单地对三种颜色原色(红、绿、蓝)进行平均处理会认为它们在感知上是相等的,但这并不符合人类视觉系统的情况。 - Bill Feth

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