RGB转单色转换

22

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


1
这篇最近的科学文章比较了将彩色照片转换为灰度图像的现有技术,包括简单的亮度公式和更复杂的技术。 - palm3D
2
我觉得你的意思应该是灰度。单色意味着图像只有一种色调,但仍然是彩色的。 - golopot
6个回答

27

我在颜色常见问题解答中找到了一个可能的解决方案。 CIE XYZ系统亮度分量Y在一个通道中捕捉到人类感知的大部分颜色。因此,使用这些系数:

mono = (0.2125 * color.r) + (0.7154 * color.g) + (0.0721 * color.b);

在应用系数之前,您必须将sRGB值线性化,然后重新应用伽马。 - Myndex
将典型的sRGB图像转换为浮点数0-1,然后将其提高到2.2的指数,然后应用以下系数:Y = pow(color.r, 2.2) * 0.2126 + pow(color.g, 2.2) * 0.7152 + pow(color.b, 2.2) * 0.0722;是使其快速、简单地工作的方法。 - Myndex

6

3
我认为这两个适用于伽马校正的RGB值,对于这个应用是错的。 - Jason Sundram
1
这些实际上是相同的。 - user877329

5
这取决于您的动机。如果您只想将任意图像转换为灰度,并使其看起来很好,其他回答中的转换方法就可以做到。
如果您要将彩色照片转换为黑白照片,则该过程可能既非常复杂又主观,需要针对每个图像进行特定的调整。了解可能涉及的内容,请查看Adobe为Photoshop提供的教程
在代码中复制这个过程会相当复杂,并且仍然需要用户干预才能获得结果完美的图像(无论这意味着什么!)。

5

如前所述,从RGB三元组进行灰度翻译(请注意单色图像不需为灰度)取决于个人喜好。

例如,您可以采用欺骗性的方法,只提取蓝色分量,将红色和绿色部分丢弃,并在它们的位置上复制蓝色值。另一种简单且通常可行的解决方案是取RGB三元组的平均值,并在所有三个组件中使用该值。

事实上,Photoshop专业的非常昂贵的灰度/单色转换插件市场的存在,说明转换的复杂程度可以随意选择。


这里最好的答案是 -> 添加你提到的公式会更加引人注目。我使用简单的 (R+G+B) / 3 .... 就可以解决问题,而且速度相当快(尤其是在嵌入式系统上工作时)。 - Shlomi Hassid

1
将任何基于RGB的图片转换为单色模式的逻辑并不是一种简单的线性变换。在我看来,这样的问题最好通过“颜色分割”技术来解决。您可以通过k-means聚类实现“颜色分割”。
请参见MathWorks网站上的参考示例。

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

原始彩色图片。

Picture with colours

使用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距离相差很大,可能会轻易地扭曲质心以产生意外结果。


1
只是想指出在自选答案中,您必须先线性化sRGB值,然后才能应用系数。这意味着要去除传输曲线。
为了消除幂曲线,将8位R G和B通道除以255.0,然后使用sRGB分段转换(建议用于图像处理),或者可以作弊并将每个通道的值提高到2.2次幂。
只有在线性化之后,您才能应用所示的系数(也不是完全正确的自选答案)。
标准值为0.2126 0.71520.0722。将每个通道乘以其系数并将它们相加得到亮度Y。然后重新应用gamma到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);

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


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