将RGB转换为灰度图像(C语言实现)

9

我曾经使用了许多公式将RGB转换为灰度,但与GIMP相比,结果并不理想。

我已经测试了以下公式:

gray = (int)(0.299 * r + 0.587 * g + 0.144 * b);

gray = (int)(0.299 * r + 0.587 * g + 0.114 * b);

gray = (int)(0.2126 * r + 0.7152 * g + 0.0722 * b);

gray = (int) (0.35*r + 0.50*g + 0.15*b);

gray = ((r * 61) + (g * 174) + (b * 21)) / 256;

gray = (int)((4897 * r + 9617 * g + 1868 * b) >> 14);

gray = r; if(g > gray) gray = g; if(b > gray) gray = b;

我认为这不是一个真正的主题,因为它是一个(主观的)图形问题,而不是一个编程问题。话虽如此,GIMP是开源的,所以你考虑过只是看看它是如何做的吗? - Useless
你不能只是使用 libgimp 来为你完成吗? - teppic
由于眼睛在绿色的最大灵敏度,因此似乎是第一或第四个公式正确。 - Eddy_Em
3个回答

15
为了正确地将RGB转换为灰度图像,您应该将伽马校正的R、G和B值转换为线性颜色空间,应用线性空间中的转换,然后对结果进行伽马校正。 sRGB颜色空间有一个近似伽马曲线的变换。有关详细信息,请参阅Wikipedia文章。维基百科还有一个具体的section介绍了关于sRGB到灰度的内容。
基本上,要将sRGB组件转换为线性格式:
double sRGB_to_linear(double x) {
    if (x < 0.04045) return x/12.92;
    return pow((x+0.055)/1.055, 2.4);
}

然后,要将sRGB转换为线性灰度:
double R_linear = sRGB_to_linear(R/255.0);
double G_linear = sRGB_to_linear(G/255.0);
double B_linear = sRGB_to_linear(B/255.0);
double gray_linear = 0.2126 * R_linear + 0.7152 * G_linear + 0.0722 * B_linear;

然后,再次应用sRGB伽马校正:
double linear_to_sRGB(double y) {
    if (y <= 0.0031308) return 12.92 * y;
    return 1.055 * pow(y, 1/2.4) - 0.055;
}

double gray_color = round(linear_to_sRGB(gray_linear) * 255);

你能给我一个参考或方程式吗? - user2000255
我在维基百科的“将彩色转换为灰度”标题下找到了数学方程式,但我不理解它的含义。谢谢。 - user2000255
1
这些系数(0.2126、0.7152和0.0722)最初来自于线性RGB -> XYZ空间转换矩阵(矩阵的中间行,计算Y值)。结果产生的“强度”值实际上是XYZ向量中的Y值。https://en.wikipedia.org/wiki/SRGB#The_reverse_transformation - R. Navega

2

一篇GIMP教程介绍了几种不同的方法,可以将彩色图像转换为灰度图像。其中一种方法是加权去饱和度,就像您已经尝试过的那样,该文章给出了一些可以用来近似GIMP转换的权重。

GIMP的gegl库是其所有图像操作的基础,它具有一个相当复杂的机制,用于将彩色转换为灰度,它考虑了相邻像素的颜色,并使用迭代方法来模拟黑白照片的处理过程。


1

GIMP去饱和工具帮助中列出了三种可用公式,对应于名为“亮度”、“亮度值”和“平均值”的选项。它们分别是:

亮度: 0.5 * (max(R,G,B) + min(R,G,B))

亮度值: (0.21 * R) + (0.72 * G) + (0.07 * B)

平均值: (R + G + B)/3


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