19

如何将像素的 RGB 值转换为单个单色值?

4

7 回答 7

21

我在颜色常见问题解答中找到了一种可能的解决方案。亮度分量Y(来自CIE XYZ 系统)在一个通道中捕获人类最感知的颜色。所以,使用这些系数:

mono = (0.2125 * color.r) + (0.7154 * color.g) + (0.0721 * color.b);
于 2008-08-18T08:27:43.830 回答
7

这篇最近的科学文章比较了将彩色照片转换为灰度的最新技术,包括简单的亮度公式和更复杂的技术。

于 2008-08-25T08:19:59.660 回答
6

这篇 MSDN 文章使用(0.299 * color.R + 0.587 * color.G + 0.114 * color.B);

这篇维基百科文章使用(0.3* color.R + 0.59 * color.G + 0.11 * color.B);

于 2008-08-18T08:40:50.403 回答
5

这取决于你的动机是什么。如果您只想将任意图像转换为灰度并让它看起来不错,那么此问题的其他答案中的转换就可以了。

如果您要将彩色照片转换为黑白,则该过程可能非常复杂且主观,需要对每张图像进行特定调整。要了解可能涉及的内容,请查看 Adob​​e for Photoshop 的本教程

在代码中复制这一点相当复杂,并且仍然需要用户干预才能获得美学上“完美”的结果图像(无论这意味着什么!)。

于 2008-08-18T19:38:49.233 回答
4

如前所述,来自 RGB 三元组的灰度转换(请注意,单色图像不必是灰度的)取决于口味。

例如,您可以作弊,只提取蓝色分量,只需将红色和绿色分量扔掉,然后复制蓝色值来代替它们。另一个简单且通常可以的解决方案是取像素的 RGB 三元组的平均值,并在所有三个分量中使用该值。

仅用于 Photoshop 的专业且不是很便宜的灰度/单色转换器插件就有相当大的市场这一事实表明,转换与您希望的一样简单或复杂。

于 2008-08-25T08:30:01.367 回答
1

将任何基于 RGB 的图片转换为单色的逻辑都不是简单的线性变换。在我看来,这样的问题最好通过“颜色分割”技术来解决。您可以通过 k-means 聚类实现“颜色分割”。

请参阅 MathWorks 网站上的参考示例。

https://www.mathworks.com/examples/image/mw/images-ex71219044-color-based-segmentation-using-k-means-clustering

原图彩色。

带颜色的图片

使用 k-means 聚类转换为单色后 使用 k-means 聚类转换为单色后的图片

这是如何运作的?

从整个图像中收集所有像素值。从 W 像素宽和 H 像素高的图像中,您将获得 W *H 颜色值。现在,使用 k-means 算法创建 2 个集群(或箱)并将颜色放入适当的“箱”中。2 个簇代表您的黑白色调。

Youtube 视频演示使用 k-means 进行图像分割? https://www.youtube.com/watch?v=yR7k19YBqiw

这种方法的挑战

k-means 聚类算法容易受到异常值的影响。RGB 距离远离其他人群的颜色的一些随机像素很容易使质心倾斜,从而产生意想不到的结果。

于 2018-07-10T09:50:23.130 回答
0

只是为了在自选答案中指出,您必须先线性化 sRGB 值,然后才能应用系数。这意味着移除转移曲线。

要去除功率曲线,请将 8 位 RG 和 B 通道除以 255.0,然后使用推荐用于图像处理的sRGB 分段变换,或者您可以作弊并将每个通道提高到 2.2 的幂。

只有在线性化之后才能应用显示的系数(在所选答案中也不完全正确)。

标准是0.2126 0.71520.0722。将每个通道乘以其系数,然后将它们相加得到 Y,即亮度。然后将伽玛重新应用到 Y 并乘以 255,然后复制到所有三个通道,然后你就有了一个灰度(单色)图像。

这一切都在一个简单的行中:

// Andy's Easy Greyscale in one line.
// Send it sR sG sB channels as 8 bit ints, and
// it returns three channels sRgrey sGgrey sBgrey
// as 8 bit ints that display glorious grey.


  sRgrey = sGgrey = sBgrey = Math.min(Math.pow((Math.pow(sR/255.0,2.2)*0.2126+Math.pow(sG/255.0,2.2)*0.7152+Math.pow(sB/255.0,2.2)*0.0722),0.454545)*255),255);

就是这样。除非你必须解析十六进制字符串......

于 2021-11-15T21:07:16.847 回答