将 RGB 转换为灰度/强度
Posted
技术标签:
【中文标题】将 RGB 转换为灰度/强度【英文标题】:Converting RGB to grayscale/intensity 【发布时间】:2010-10-15 19:03:59 【问题描述】:当从 RGB 转换为灰度时,据说应该对通道 R、G 和 B 应用特定的权重。这些权重是:0.2989、0.5870、0.1140。
据说这是因为人类对这三种颜色的感知/感受不同。有时也有人说这些是用于计算 NTSC 信号的值。
但是,我在网上没有找到很好的参考资料。这些值的来源是什么?
另请参阅之前的这些问题:here 和 here。
【问题讨论】:
是的。我一直在对 RGB 值进行编程。如果您希望您的应用物有所值,那么将“真实世界”值应用于这些计算非常重要。 许多程序员可能不关心和计算“错误”的灰度图片,但我关心。 我同意它与编码相关 - 如果您正在编码图形,这无疑是一个有趣且相关的问题。 +1,因为我想自己知道答案 RGB 是编程相关的。它与解析日期字符串一样与编程相关。将文本“true”转换为布尔值。 @pnizzle poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC9 【参考方案1】:问题中的具体数字来自 CCIR 601(参见Wikipedia article)。
如果你用稍微不同的数字/不同的方法转换 RGB -> 灰度, 在普通的电脑屏幕上你根本看不到太大的区别 在正常光照条件下——试试吧。
这里有更多关于颜色的链接:
***Luma
Bruce Lindbloom 的优秀网站
Colin Ware 所著的“信息可视化”一书中关于颜色的第 4 章,isbn 1-55860-819-2; 这个长链接到books.google.com中的Ware 可能有效也可能无效
cambridgeincolor : 很好,写得很好 “关于如何获取、解释和处理数码照片的教程 使用以视觉为导向的方法,强调概念而非过程"
如果您遇到“线性”与“非线性”RGB, 这是对我自己的旧笔记的一部分。 重复一遍,在实践中你不会看到太大的不同。
### RGB -> ^gamma -> Y -> L*
在色彩科学中,常见的 RGB 值,如 html rgb( 10%, 20%, 30% ), 被称为“非线性”或 Gamma corrected。 “线性”值定义为
Rlin = R^gamma, Glin = G^gamma, Blin = B^gamma
对于许多 PC,gamma 为 2.2。 通常的 R G B 有时写为 R' G' B' (R' = Rlin ^ (1/gamma)) (纯粹主义者的舌头点击)但在这里我会放弃'。
CRT 显示器的亮度与 RGBlin = RGB ^ gamma 成正比, 所以 CRT 上 50% 的灰色非常暗:0.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 color space
【讨论】:
Y = 0.2126 * R + 0.7152 * G + 0.0722 * B - *** (en.wikipedia.org/wiki/Grayscale) 您好,我可以通过将 RGB 彩色图像显示为灰度图像来获得等效的全色图像吗?或者从RGB转换成HIS格式图像的强度分量能否代表全色图像? @emberbillow,有 许多 种将颜色映射到灰度的方法,其中一些可能在某些时候效果很好。你在用什么程序,你读过它的文档吗?您可以在几张您的测试图像上试一试。 谢谢你,丹尼斯。我没有使用软件。当我阅读全色图像的定义时,我才想到这个问题。众所周知,全色图像上像素的亮度大致代表了地表的反射能力。因此,由于 RGB 彩色图像大约覆盖了可见光的波段间隔,我猜它的灰度格式可以代表全色图像。我不确定我的理解是否正确。 @enberbillow,*** 是针对软件和编程问题的,最好是an example。试试 google RGB IHS 全色灰度?【参考方案2】:我发现此出版物在对先前类似问题的回答中被引用。很有帮助,页面有几个示例图片:
Perceptual Evaluation of Color-to-Grayscale Image Conversions Martin Čadík,计算机图形学论坛,2008 年第 27 卷
该出版物探讨了其他几种生成具有不同结果的灰度图像的方法:
CIE Y Color2Gray 脱色 史密斯08 Rasche05 巴拉04 纽曼07有趣的是,它得出的结论是,没有普遍最佳的转换方法,因为每种方法的表现都比其他方法更好或更差,具体取决于输入。
【讨论】:
@JackDeeth 我不知道如何总结链接的网站,因为它都是关于视觉比较的。 你说得对,我不应该投这样的票。对不起!【参考方案3】:这是 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
【讨论】:
0.3 0.6 0.11 不要加到 1。***似乎建议 0.30 0.59 0.11。 是的,但它们不加 1 的唯一结果是强度会发生非常轻微的变化。建议的 0.25,0.5,0.25 方法确实加到 1,但如果不加也没有关系。这是一种优化,因此放弃一点点准确性是一个合理的权衡。 @twerdster 两组系数都不正确。 .3,.6,.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 进行线性化,然后应用正确的系数。 如果您处于除法过于昂贵的情况下,使用单次乘法和移位和加法的近似值是:0.11111111 * ((G + (G<<1) + R) <<1) + B)
。这相当于(2*R+6*G+B) / 9)
或0.222 R + 0.666 G + 0.111 B
。在投入生产之前,与各种测试用例的准确公式进行比较。【参考方案4】:
查看Color FAQ 了解相关信息。这些值来自我们在显示器中使用的 RGB 值的标准化。实际上,根据颜色常见问题解答,您使用的值已经过时,因为它们是用于原始 NTSC 标准而不是现代显示器的值。
【讨论】:
【参考方案5】:这些值的来源是什么?
发布的系数的“来源”是 NTSC 规范,可以在 Rec601 和 Characteristics of Television 中看到。
“最终来源”是 CIE 大约 1931 年关于人类颜色感知的实验。人类视觉的光谱响应是不均匀的。实验导致基于感知的三刺激值加权。我们的 L、M 和 S 视锥1 对我们识别为“红色”、“绿色”和“蓝色”(分别)的光波长敏感,这是派生三原色的地方.2
sRGB(和 Rec709)的线性光3 光谱权重为:
Rlin * 0.2126 + Glin * 0.7152 + Blin * 0.0722 = Y
这些特定于 sRGB 和 Rec709 色彩空间,旨在表示计算机显示器 (sRGB) 或 HDTV 显示器 (Rec709),并在 Rec709 和 BT.2380-2 (10/2018) 的 ITU 文档中进行了详细说明
脚注 (1) 视锥细胞是眼睛视网膜的颜色检测细胞。 (2) 但是,选择的三色刺激波长不在每个锥体类型的“峰值”处 - 而是选择三色值,以使它们对特定锥体类型的刺激明显多于另一种,即刺激分离。 (3) 在应用系数之前,您需要对 sRGB 值进行线性化。我在another answer here.讨论这个问题
【讨论】:
【参考方案6】:开始一个列表来列举不同的软件包是如何做到的。 Here is a good CVPR paper to read as well.
FreeImage
#define LUMA_REC709(r, g, b) (0.2126F * r + 0.7152F * g + 0.0722F * b)
#define GREY(r, g, b) (BYTE)(LUMA_REC709(r, g, b) + 0.5F)
OpenCV
nVidia Performance Primitives
Intel Performance Primitives
Matlab
nGray = 0.299F * R + 0.587F * G + 0.114F * B;
【讨论】:
【参考方案7】:这些价值观因人而异,尤其是对于色盲的人。
【讨论】:
【参考方案8】:这一切真的有必要吗,人类的感知和 CRT vs LCD 会有所不同,但 R G B 强度不会,为什么不L = (R + G + B)/3
并将新的 RGB 设置为 L、L、L?
【讨论】:
简单地对所有三个 R、G、B 原色进行平均就可以将它们视为感知上的平等,而人类视觉系统并非如此。以上是关于将 RGB 转换为灰度/强度的主要内容,如果未能解决你的问题,请参考以下文章