【问题标题】:Is there an algorithm for color mixing that works like mixing real colors?是否有一种颜色混合算法可以像混合真实颜色一样工作?
【发布时间】:2010-11-23 23:59:22
【问题描述】:

常见的RGB混色与绘画混色有很大不同, 它是光的混合,而不是颜料的混合。

例如:

Blue (0,0,255) + Yellow (255,255,0) = Grey (128,128,128)

(应该是蓝色+黄色=绿色)

是否有任何已知的颜色混合算法可以像混合真实颜色一样工作?


我的方法

我已经尝试过以下操作:

将两种颜色转换为 HSV 并混合色调(乘以从饱和度计算的系数), 以及饱和度和价值通道的简单平均值。然后我计算了两者的平均亮度 颜色并调整生成的颜色以匹配此亮度。 这工作得很好,但色调混合有时是错误的,例如。 g.:

Red (Hue 0°) + Blue (Hue 240°) = Green (Hue 120°)

我发现有时我需要将色调值移动 360°(当 色调大于 180°)。

Red (Hue 360°) + Blue (Hue 240°) = Magenta/fuchsia (Hue 300°)

但这种转变也不是很好,例如:

Cyan (Hue 179°) + Red (Hue 0°) = Hue 89.5°
Cyan (Hue 181°) + Red (Hue 0°) --> shifting is performed (the difference is greater than 180°)
Cyan (Hue 181°) + Red (Hue 360°) = Hue 270.5°

(Hue 179 + Red) 和 (Hue 181 + Red) 会产生两种完全不同的颜色。


然后我尝试了 CIE Lab 色彩空间(就像在 Photoshop 中一样),它旨在更接近人类感知颜色的方式。

我对每个对应的两个通道只使用了一个简单的平均值,但结果并不令人满意, 例如,我从蓝色 (98, -16, 93) 和黄色 (30, 68, -112) 中得到粉色 (64, 26, -9.5)。这些系数 取自 Photoshop。

也许如果我使用一些不同于平均水平的操作,它可以工作,但是 我不知道是什么。


CMYK 也不好用,结果就像 RGB 或 LAB 一样。


似乎在任何这些色彩空间中微不足道的加法或减法颜色混合都不会产生自然的结果。


工作实施

Krita – 绘画混合器

光栅图形编辑器 Krita 在某些时候实现了更逼真的颜色混合:http://commit-digest.org/issues/2007-08-12/(Painterly 混合器插件)

他们说这是第一个使用描述颜料行为的 Kubelka 和 Munk 方程实现特殊技术的公共应用程序。

这是 Krita 混色的视频:https://www.youtube.com/watch?v=lyLPZDVdQiQ

五十三的论文

还有由FiftyThree开发的article about color blending in the Paper app for iOS。他们描述了他们如何在该领域进行创新和实验,并提供混合蓝色和黄色的样本,从而产生绿色。然而,实际的过程或算法并没有真正描述在那里。

引用:

“在寻找一种好的混合算法时,我们最初尝试在各种颜色空间中进行插值:RGB、HSV 和 HSL,然后是 CieLAB 和 CieLUV。结果令人失望,”Chen 说。 “我们知道红色和黄色应该产生橙色,或者红色和蓝色应该产生紫色——但无论你使用什么色彩空间,都没有办法得到这些颜色。有一个工程公理:做最简单的事情可能会奏效。好吧,我们现在已经尝试了最简单的方法,但他们甚至感觉都不对。”

好像和 Krita 一样,Paper 实现了 Kubelka-Munk 模型:

[...] Kubelka-Munk 模型对每种颜色至少有六个值,包括每种 RGB 颜色的反射和吸收值。 “虽然屏幕上颜色的外观可以用三个维度来描述,但颜色的混合实际上是在六维空间中发生的,”FiftyThree 的联合创始人兼首席执行官 Georg Petschnigg 解释道。 Kubelka-Munk 的论文使团队能够将美学问题转化为数学框架。 [...]

从所有这些信息来看,基于 Kubelka-Munk 模型的实施似乎是前进的方向,并提供更接近现实的结果。

尽管它看起来像一个复杂的过程,但我还没有看到太多关于如何实现这样的东西的好信息。


相关问题

这些问题是在这个问题之后发布的,都与同一件事有关。

他们都没有真正的答案。


其他相关链接和资源

【问题讨论】:

标签: algorithm colors language-agnostic blending color-space


【解决方案1】:

想知道 RGB 值的反转计算是否有效。因为是光的减法,从技术上讲,减法部分可以通过简单的数学计算出来。

例如青色+黄色

青色 = 0x00ffff 黄色 = 0xffff00

它们的反转是 0xff0000 和 0x0000ff,这意味着它们完全吸收了红光和蓝光。它们的 1:1 混合应该吸收一半的红光和蓝光(因为混合的另一半仍然可以反射一些红光和蓝光),这与 (0xff0000 + 0x00ffff) / 2 = 0x7f007f 一致。现在我们从 0xffffff 中减去这个值,我们得到 0x80ff80,它是绿色的!

【讨论】:

  • 青色是另一种颜色。尝试将蓝色(0x0000ff)与黄色混合,你会得到灰色。如果您在现实世界中将这些完全相同的色调混合在油漆中,您将永远不会变灰。
【解决方案2】:

对 RGB 颜色进行减法混合的一种方法是首先将 RGB 颜色转换为光谱反射曲线。转换相当简单,一旦完成,您可以对反射率曲线进行真正的减法混合,然后将结果转换回 RGB。还有另一个类似的问题:stackoverflow.com/questions/10254022/,这里对这个过程进行了更详细的讨论。

【讨论】:

    【解决方案3】:

    查看implementation 了解加法、减法和其他混合算法。

    功能齐全(用 java 编写),因此您可以测试您需要混合的任何颜色,看看它是否符合您的需求。

    正如其他回复所指出的那样,Blue + Yellow(正好是Cyan + Yellow)是Green 关于减法 CMYK 算法。自己看

    【讨论】:

    • 是的,但无论是加色还是减色混合,在所有情况下都不能很好地工作。尝试混合真正的蓝色 (#0000ff) 和黄色 (#ffff00),这两者都不会产生绿色。
    • 那么,真正的蓝色是什么?这是蓝色和黄色的真正混合youtube.com/watch?v=OQ0qEBMC5xs,视频中的蓝色看起来是青色。不是吗?
    • 在我看来,视频中的颜色看起来是蓝色而不是青色。但这不是重点,即使你将强烈的蓝色与黄色混合,你也不会变成灰色,而是一些绿色。
    【解决方案4】:

    在 krita 中有以逼真的方式混合颜色的代码:https://projects.kde.org/projects/calligra/repository/revisions/master/show/krita/plugins/extensions/painterlyframework

    请注意,包含光源文件的代码是 GPLv2+。它可以从 RGB 转换为波长,进行合成并转换回来。

    【讨论】:

    • 感谢您的链接。我在我的问题中提到了 Krita,我只是找不到相关的源代码。但真的是驱动算法的光波长吗?蓝光的波长约为 475 nm,红光的波长约为 650 nm。波长如何组合得到紫光?它必须使用比光波长更困难的东西。我确信算法本身非常复杂,我仍在寻找它的,至少是简短的解释。
    • 你需要回到 2.4.x 版本,似乎代码被删除了,因为它没有被维护。
    • 源码在github上,现在被历史埋没了:github.com/KDE/krita/tree/…
    【解决方案5】:

    我认为组合色调的问题在于,您是通过将两个角度相加并除以二来实现的。正如您所注意到的,结果通常没有意义。我认为你最好将角度转换为单位圆上的笛卡尔坐标,对它们进行平均,然后找到结果点的角度(忽略大小)。

    【讨论】:

    • 得出:青色(色调 179°)+红色(色调 0°)= 89.5°,青色(色调 181°)+红色(色调 0°)= -89.5° = 270.5°跨度>
    【解决方案6】:

    正确的答案是否定的,因为没有正确 工作模型来说明“现实世界中的颜色混合”如何真正起作用。它太复杂和有条件,根本不像我们在学校学到的简单的红蓝黄东西(实际上它需要所有的化学和大量的物理和生物来解决)。

    不过,简单的答案是:是的,使用减法混合而不是加法混合。

    我们在小学学习的颜色混合是基于颜料组合的,它是减色混合的一种形式(非常简单)。那就是我们加在一起的颜色越多,颜色就越深,因为每种颜料都会减去更多的光。

    另一方面,几乎所有计算机配色方案都是加法,因为它们基于组合光波(非常简单),因此它们会变得更亮,因为每种颜色都会增加一点点光。

    RGB+ 方案在某种程度上是对我们在大多数美国小学学习的减法方案(即 RBY-)的加法补充。但是,它们并不完全匹配,并且很难在它们之间进行转换(现在正在研究......)


    好的,如果你只是想从 RGB 中的加法组合切换到减法组合,你可以使用下面的 reverse-bayesan 类型公式来组合两种颜色:

    NewColor.R = (Color1.R * Color2.R)/255
    NewColor.G = (Color1.G * Color2.G)/255
    NewColor.B = (Color1.B * Color2.B)/255
    

    调整色极的差异(G 到 Y,然后回到 G)要困难得多......


    已经指出,对于示例问题,这会产生黑色,从技术上讲,这对于真正的减法系统是正确的,但是,如果您想要更多的稀释/减法系统,您可以试试这个:

    NewColor.R = 255 - SQRT(((255-Color1.R)^2 + (255-Color2.R)^2)/2)
    NewColor.G = 255 - SQRT(((255-Color1.G)^2 + (255-Color2.G)^2)/2)
    NewColor.B = 255 - SQRT(((255-Color1.B)^2 + (255-Color2.B)^2)/2)
    

    这会产生深灰色而不是黑色。但是要获得黄色或任何接近的东西,您仍然必须解决颜色方案的极点对齐问题。

    【讨论】:

    • 这个公式在提到的情况下会给出黑色,不是吗?
    • 那么你找到更好的了吗?
    • 不,在任何减法方法中都很难不想出黑方,因为所有三个极点都在源中最大化。我能看到的唯一解决方案需要重新映射到我一直试图避免的“简单”解决方案的不同方案。嗯,……今天早上给我几个小时,我可能有一个“简单”的重新映射来修复它……
    • 染料混合是减色法,但许多染料实际上并不作用于原色。油漆混合不是减法,但可能是加法、减法和古怪而古怪的任意组合,具体取决于油漆。
    • 油漆混合是减法或平均,这取决于“混合”的含义。它永远不能是添加剂,因为油漆不能创造自己的光。 (你可以用荧光和磷光来争论这一点,但这些都是 ntis)。
    【解决方案7】:

    组合颜色有两种不同的可能性:

    1. additive mixing(如 RGB)

    2. subtractive mixing(如 CMYK)

    所以在减色混合中,结果是你所期望的,但没有蓝色,而是青色:

    黄色 + 青色 = 绿色

    一般来说,减色混合只是从白色“带走”(过滤),而加色混合是从黑色加起来。 (减色的基色与加色相反:红色->青色;绿色->品红色;蓝色->黄色)

    因此,如果您从应用过滤器的白屏开始:

    min(白色 (255,255,255), 黄色 (255,255,0), 青色 (0,255,255)) = 绿色 (0,255,0)

    【讨论】:

    • 如果我尝试蓝色作为青色 + 品红色 (100%, 100%, 0, 0)。当我将它与黄色混合时,它看起来不是很逼真和自然。
    • “规则“黄色+蓝色=绿色”是一种误解。您必须将青色与黄色混合才能得到蓝色(减色)。
    • CMYK 也不“正确”。它是一个近似模型,就像 RBY-。您可能会争辩说它比 RBY-“更”正确。
    • @RBarryYoung:CMYK 仅在应用于刻意配制以使其相当准确的油墨或染料时才是准确的模型。相比之下,RGB 加法合成相对准确,无论颜色是否“纯”。
    猜你喜欢
    • 2012-05-02
    • 1970-01-01
    • 2012-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-01
    • 1970-01-01
    相关资源
    最近更新 更多