5

我正在尝试找到一种基于百分比量混合颜色的算法。我正在做一个选举项目,希望能够为比赛中的每个候选人分配不同的颜色,然后根据候选人获得的选票创建一个“结果”颜色。

这个问题:

是否有一种颜色混合算法可以像混合真实颜色一样工作?

接近我要问的问题 - 但可能我需要能够将 3 或 4 或 5 种颜色混合在一起。我知道这最终是一个非常复杂的问题 - 但我很好奇建议的方法是在超过 2 种颜色上执行此操作。所以,我可能有:

红色 (40%)、绿色 (10%)、蓝色 (50%)

或者

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

再一次,我知道最后一个例子可能会产生某种灰色或棕色或黑色 - 这很好。我的问题是我什至没有试图解决这个问题的算法。


编辑:所以 - 发布此消息后,我意识到我真正想要完成的基本上是 PAINT 颜色混合。换句话说,我不想要 LIGHT 颜色混合,我想模拟 PAINT 混合会发生什么 - 因为这是我一直“期待”的“可预测”结果 - 并且难以获得。

我找到了这个链接: http: //painting.about.com/library/blpaint/blcolormixingpalette1.htm

这与我想要完成的工作非常接近 - 并暴露了我最初想法中的一个小“缺陷”。所展示的是,即使我可以使用该算法混合多达 6 种颜色,实际的“数据”总是被分解为 3 种原色。

即便如此 - 这非常接近。

感谢所有为这个线程做出贡献的人——所有这些建议都对探索这个令人惊讶的复杂问题/领域非常有帮助。

4

3 回答 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

于 2012-11-02T18:22:58.813 回答
2

RGB 颜色系统不适合这种计算,因为它不像我们人类感知颜色那样工作。例如,我们只是不认为黄色是绿色和红色的混合物。第一步是在颜色空间中转换颜色,其中有一个亮度坐标和两个颜色坐标。这可以是 HLS 或 CIELAB。HLS 转换更简单,但 CIELAB 中的坐标更能代表人类色彩体验。这个色彩空间中的相等距离​​至少是人类感知中大致相等的距离。

在这个颜色空间中,您有坐标 L、A 和 B。对于所有颜色,L 应该相同。你的基色应该在灰点周围的一个圆圈上,所以它们有相同的距离,没有颜色比其他颜色强。所以你基本上在平面上有几个点,需要计算这些点的加权中点。您将此点转换回 RGB。

于 2012-11-03T23:50:08.957 回答
1

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

也就是说,任何不是红色、绿色或蓝色的颜色,您都可以将它们分解为红色、绿色和蓝色对应物,然后将这些权重乘以总体权重。

在您的第二个示例中:

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

黄色和橙色需要分解。假设你有Color橙色的实例,你可以这样做:

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

这实际上可以在所有 Color实例中推广(对于原色,只有和中的一个将具有值) R,然后可以采用总和和加权平均值来获得混合颜色。GB

一个简单的扩展方法是:

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);
}
于 2012-11-02T18:28:21.297 回答