混合超过2种颜色的颜色混合

5
我正在寻找一种算法,可以根据百分比混合颜色。我正在开展一个选举项目,希望能够为竞选人分配不同的颜色,并根据该候选人获得的选票数量创建“结果”颜色。
这个问题:有没有一种像混合真实颜色一样工作的颜色混合算法?与我提出的问题相似,但可能需要能够混合三到五种颜色。我知道这最终是一个非常复杂的问题,但我很好奇在处理两种以上颜色时建议使用的方法是什么。因此,我可能会有:
红色(40%),绿色(10%),蓝色(50%)

红色(40%),黄色(5%),蓝色(10%),橙色(45%)
再次强调,我知道最后一个示例可能会产生某种灰色、棕色或黑色-这没关系。我的问题是我甚至没有尝试解决这个问题的算法。
编辑: 发布此消息后,我意识到自己实际上想要做的事情基本上是油漆颜色混合。换句话说,我不想要光线颜色混合,我想模拟油漆混合会发生什么-因为这是我一直“期望”的“可预测”结果-并且很难实现。
我在这里找到了这个链接:http://painting.about.com/library/blpaint/blcolormixingpalette1.htm,它的行为非常接近我想要实现的内容,并暴露了我最初想法中的一个小“缺陷”。它所展示的是,即使我可以使用此算法混合多达6种颜色,实际的“数据”始终被分解为3种原色。
即便如此,这也非常接近。
感谢所有为这个帖子做出贡献的人-所有这些建议都对这个令人惊讶的复杂问题/领域的探索非常有帮助。

一个简单的实现方法是将每种颜色的组成部分乘以它们的百分比权重。例如,40% 的红色和 60% 的绿色可以通过将红色组件乘以 0.4,绿色组件乘以 0.6,然后像平常一样相加来形成。只要您的百分比总和为100%或更少,这就保证了不会剪切任何组件。 - Kenogu Labz
可能是如何在C#中“自然”混合颜色?的重复问题。 - Peter O.
3个回答

7

你尝试过简单地进行加权求和吗?

d.R = a.R*0.25 + b.R*0.25 + c.R*0.5
d.G = a.G*0.25 + b.G*0.25 + c.G*0.5
...
where a, b, c are the colors you're mixing

根据我的研究,似乎没有一个正确的答案,但是应该选择能够产生最合适效果的方法。此外,我认为仅仅混合颜色并不能在信息图表上表现出任何东西。你最好尝试一些像粒子抖动这样的处理方式。http://en.wikipedia.org/wiki/Dither#Digital_photography_and_image_processing


虽然加法 RGB 颜色混合是正确的(并且经典的),但 OP 特别要求真正的颜色混合(就像油漆一样),所以那种方法行不通。 - user703016
“真正”颜色混合的一种方法是找到各种油漆的BRDF和/或各种灯光的光谱功率分布,并将它们组合起来,然后使用颜色匹配函数将结果光谱转换为RGB。我假设OP实际上想要某种快速粗略的近似值。 - user1067042

2
RGB颜色系统不适合进行这种计算,因为它不能像人类感知颜色那样工作。例如,我们并不认为黄色是绿色和红色的混合物。 第一步是将您的颜色转换为一个颜色空间,在该空间中,您具有亮度坐标和两个颜色坐标。 这可以是HLS或CIELAB。 HLS转换更简单,但CIELAB中的坐标更好地表示了人类的颜色体验。在此颜色空间中,等距离至少大致相等于人类感知中的等距离。 在此颜色空间中,您有L、A和B三个坐标。 L应该对所有颜色都相同。您的基本颜色应位于灰点周围的圆上,因此它们具有相同的距离,并且没有任何颜色比其他颜色更强。因此,您基本上需要在平面上计算这些点的加权中心点。然后将此点转换回RGB格式。

1

这完全取决于您颜色模型中的原色。看起来您正在使用RGB颜色模型,这意味着所有颜色都可以通过红、绿和蓝的混合来表示。

话虽如此,任何不是红、绿或蓝的颜色都需要将其分解为它们的红、绿和蓝色对应部分,然后将这些权重乘以总体权重。

在您的第二个示例中:

红色(40%),黄色(5%),蓝色(10%),橙色(45%)

黄色和橙色需要被分解。假设您有橙色的Color实例,则可以执行以下操作:

orangeRed = o.R * .05;
orangeBlue = o.B * .05;
orangeGreen = o.G * .05;

这实际上可以推广到所有的颜色实例(对于主要颜色,只有一个RGB会有值),然后可以进行求和和加权平均来得到混合颜色。

一个简单的扩展方法可以实现这一点:

static Color Mix(this IEnumerable<Tuple<Color, double>> colors)
{
    // The red, green, and blue values.
    double red = 0.0, green = 0.0, blue = 0.0;

    // The denominator for the weighted average for a color.
    double denominator = byte.MaxValue * 3.0;

    // Cycle through the colors.
    foreach (Tuple<Color, double> color in colors)
    {
        // Get the weighted average value for each component, and then
        // multiply that by the weight for the color.
        red   += ((color.Item1.R / denominator) * color.Item2);
        green += ((color.Item1.G / denominator) * color.Item2);
        blue  += ((color.Item1.B / denominator) * color.Item2);
    }

    // Create the color and return.
    return Color.FromArgb((int) red, (int) green, (int) blue);
}

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