有没有有效的方法来找到这样的颜色?

时间:2012-11-12 10:07:19

标签: algorithm math

在我们的项目中,我们将尝试为不同的数字使用不同的颜色。这些颜色应满足以下条件:

  1. 所有颜色应满足:abs(A.R-A.G)+ abs(A.G-A.B)+ abs(A.B-A.R)> 250
  2. 所有颜色应该足够不同。如果颜色A和B满足:abs(A.R-B.R)+ abs(A.G-B.G)+ abs(A.B-B.B)> = 50,则它们足够不同。 问题是我们可以获得多少颜色?有没有快速的方法来获取颜色而不枚举所有组合?

2 个答案:

答案 0 :(得分:2)

这取决于您需要的颜色(网站,图片,......)。我曾遇到过一个非常类似的问题,下面是我发现的。最后,我只使用了一个HSV色彩空间(在我的应用中很容易),它允许你将色调范围分成相同大小的间隔,每次都会得到不同的颜色。

这是我觉得有用的东西:

Generate distinctly different RGB colors in graphs

How to automatically generate N "distinct" colors?

Generate unique colours

答案 1 :(得分:2)

我认为获得准确结果的最简单方法是通过拉斯维加斯算法,在这种算法中,您尝试通过逐步添加不会使当前集无效的随机颜色来组合一组尽可能大的颜色。如果没有这样的颜色可用(例如因为最后100次尝试找到这样的颜色失败),则当前集合形成结果。

请注意,当它卡住时,它不会尝试“撤消”可能的错误添加,它只会终止,这会使算法报告很多次优集,但速度非常快。因此,您需要运行此算法几(千?)次,以查看您可以编写的集合大小。

我认为这是通过相对较少的编程或分析工作获得合适结果的更快捷的方法之一。

修改:快速完成了几次:我发现的非冲突颜色组成的最大设置尺寸 273

编辑2 根据要求,提供相应的(相关的)源代码:

public class Colour
{
    public int Red;
    public int Green;
    public int Blue;

    public int Primality
    {
        get { return Math.Abs(Red - Green) + Math.Abs(Green - Blue) + Math.Abs(Blue - Red); }
    }

    public int Difference(Colour other)
    {
        return Math.Abs(this.Red - other.Red) + Math.Abs(this.Green - other.Green) + Math.Abs(this.Blue - other.Blue);
    }

    public Colour(int red, int green, int blue)
    {
        Red = red;
        Green = green;
        Blue = blue;
    }

    public static Colour Generate(Random rnd)
    {
        return new Colour(rnd.Next(256), rnd.Next(256), rnd.Next(256));
    }

    public static Colour GeneratePrimal(Random rnd)
    {
        Colour candidate = null;
        do
        {
            candidate = Generate(rnd);
        } while (candidate.Primality <= 250);

        return candidate;
    }
}

使用此类,所描述算法的单次运行将如下所示:

private Random _rnd = new Random();

public List<Colour> Run()
{
    List<Colour> resultSet = new List<Colour>();

    //Shouldn't find a set larger than 1000 Colours.
    for (int colourCount = 0; colourCount < 1000; colourCount++)
    {
        Colour candidate = null;
        bool found = false;

        //100000 means: Try *very* hard to find a next candidate
        for (int index = 0; index < 100000; index++)
        {
            candidate = Colour.GeneratePrimal(_rnd);
            if (resultSet.Any(col => candidate.Difference(col) < 50) == false)
            {
                resultSet.Add(candidate);
                found = true;
                break;
            }
        }

        if (found == false)
            return resultSet;
    }

    return resultSet;
}