- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我想通过代码(android)完全像上图一样。但我对这样做的算法感到困惑。我只知道:
每个像素:
将 RGB 转换为 HSL
???
将 HSL 转换回 RGB
任何人都可以为我解释在第 2 步中要做什么吗?非常感谢。
ps: 我可以通过 ColorMatrix.setSaturation(0) 在 android 中设置饱和度,但结果图像与 Photoshop 不一样(因为色相和亮度没有改变?)
最佳答案
您有很多选项可以降低图像的饱和度。此外请注意,对图像进行去饱和处理不是只是将其变成黑白,但对于某些应用程序,您可能认为它们是等价的。
我用更多细节更新了这篇文章。
这是学生可以将图像转换为灰度的第一件事(至少我过去首先想到的是这样!)并且看起来像去饱和:
level = (R + G + B) / 3
它不会产生糟糕的结果,而且实现起来又快又容易。但它有一个很大的缺点,就是它不符合人类感知光度的方式。
第二种方法(亮度有时称为发光度、Luma 或强度)是我们眼睛感知亮度方式的更好模型。这是基于一个事实 cone density在眼睛中,颜色不均匀。我们对绿色的感知比红色强烈得多,对红色的感知比蓝色强烈得多。
因为我们不会以相同的强度感知所有颜色,所以平均方法是不准确的(至少它不会产生看起来自然的结果)。如何管理这个?只需使用加权平均值:
level = R * 0.3 + G * 0.59 + B * 0.11
您可以想象,关于这些值(value)观的讨论有很多。最初的 ITU-R 建议提出了这个公式:
level = R * 0.2126 + G * 0.7152 + B * 0.0722
如果我没记错的话,Photoshop 使用这个来实现其简单 去饱和功能(是的,它是第一个的未舍入版本):
level = R * 0.299 + G * 0.587 + B * 0.114
我不认为我们可能会注意到很多差异,反正最近更改了推荐,看看 here on Wikipedia有关此公式的更多详细信息。
您想了解更多详情吗?阅读 Charles Poynton 的这篇文章:The rehabilitation of gamma和他的 FAQ关于这个话题。
每个像素都用 RGB color model 描述但饱和度属于HSL color model (实际上,当处理饱和时,您可以同时使用 HSL 或 HSV 模型)。请阅读链接以了解有关这些模型的更多详细信息。
图像去饱和包括以下步骤:
setSaturation(0)
所做的)让我介绍一下这个过程的大简化:您可以对颜色进行去饱和,找到 RGB 的最大值和 RGB 的最小值之间的中点(亮度,你还记得颜色,在RGB color space ,是 3D 空间中的一个点吗?)。获得去饱和图像的(简化)公式是:
level = (max(R, G, B) + min(R, G, B)) / 2
一种更简单的去饱和形式,有时称为局部最大分解,只是选择每个 RGB 三元组的最大值:
level = max(R, G, B);
正如您想象的那样,您可以同时使用局部最大值或局部最小值(我写成 local 是因为它会搜索每个像素的最小值/最大值)。
不要忘记,您可以非常快速地获得黑白图像(然后看起来像去饱和图像),只需从 RGB 三元组中保留一个 channel (例如绿色 channel )并将该值复制到所有 channel )。
有时 Photoshops 教程不使用它的功能来降低图像的饱和度(去饱和度功能和调整调色板),但为了获得更好的效果,他们添加了一个具有统一颜色的图层(根据 Luminance 部分的值计算)然后他们将该层与原始图像合并(搜索教程并重现代码中的步骤)。
关于android - 如何将图像转换为灰度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9839013/
我是一名优秀的程序员,十分优秀!