跟进:通过独特性“排序”颜色

时间:2008-08-04 15:14:48

标签: algorithm language-agnostic colors

Original Question

如果给你N个最远距离的颜色(以及一些相关的距离度量),你能想出一种方法将这些颜色排序成某种顺序,这样第一个M也可以合理地接近最大不同的颜色吗? / p>

换句话说,给定一堆不同的颜色,想出一个订单,这样我就可以使用从一开始就需要的尽可能多的颜色,并合理地确保它们都是独特的,并且附近的颜色也非常明显(例如,蓝红色不是红蓝色旁边的。)

随机化是可以的,但肯定不是最佳的。

澄清:鉴于一些大而且在视觉上截然不同的颜色(比如256或1024),我想对它们进行排序,这样当我使用第一个时,比方说,其中16个,我得到一个相对视觉上不同的颜色颜色子集。这大致等同于说我要对1024的这个列表进行排序,以便在视觉上更接近单个颜色,它们在列表中的距离越远。

9 个答案:

答案 0 :(得分:2)

这个问题被称为颜色量化,并且有许多众所周知的算法:http://en.wikipedia.org/wiki/Color_quantization我知道实施八叉树方法的人效果很好。

答案 1 :(得分:2)

似乎感知对您很重要,在这种情况下,您可能需要考虑使用感知颜色空间,例如YUV,YCbCr或Lab。每次我使用它们,它们给我的结果比单独的sRGB好得多。

转换为sRGB和从sRGB转换可能会很痛苦,但在您的情况下,它实际上可以使算法更简单,作为奖励,它也将主要用于彩色百叶窗!

答案 2 :(得分:2)

这对我来说也像某种电阻图,在那里你试图绘制阻力最小的路径。如果你颠倒了最​​大阻力的路径要求,它可能会用来产生一个从一开始就产生最大差异的一组,并且在结束时开始回到更接近其他的值。

例如,这是一种可能做你想做的事情。

  1. 计算每种颜色与所有其他颜色的距离(参考your other post
  2. 对每种颜色的距离求和,这样可以指示此颜色与所有其他颜色相距多远
  3. 按距离订购列表,下载
  4. 这似乎会生成一个列表,该列表以距离所有其他颜色最远的颜色开始,然后向下,列表末尾的颜色通常会更接近其他颜色。

    编辑:阅读你对我的第一篇文章的回复,关于空间细分,不完全符合上面的描述,因为接近其他颜色的颜色会落到列表的底部,但是假设你有一组颜色在某个地方,该群集中的至少一种颜色将位于列表的开头附近,并且它通常是总共距离所有其他颜色最远的那种颜色。如果这是有道理的。

答案 3 :(得分:2)

N个最远距离的颜色可以被认为是三维(颜色)空间中的一组分布均匀的点。如果你可以从Halton sequence生成它们,那么任何前缀(前M种颜色)也都包含分布均匀的点。

答案 4 :(得分:1)

  1. 从两个列表开始。 CandidateColors,最初包含您的不同颜色和SortedColors,最初是空的。
  2. 选择任何颜色并将其从CandidateColors中删除并将其放入SortedColors。这是第一种颜色,也是最常见的颜色,因此它是一个选择适合您应用的颜色的好地方。
  3. 对于CandidateColors中的每种颜色,计算其总距离。总距离是从CandidateColor到SortedColors中每种颜色的距离之和。
  4. 从CandidateColors中删除总距离最大的颜色,并将其添加到SortedColors的末尾。
  5. 如果CandidateColors不为空,请返回步骤3.
  6. 这种贪婪的算法应该会给你带来好的结果。

答案 5 :(得分:1)

如果我正确理解了这个问题,你希望获得 M 颜色的子集,颜色之间的最高平均距离给定一些距离函数 d

换句话说,将 N 颜色的初始集合视为连接所有颜色的大型无向图,您希望找到访问的最长路径任何 M 节点。

解决NP完全图形问题超出了我的恐惧,但您可以尝试运行简单的物理模拟:

  1. 在色彩空间中生成 M 随机点
  2. 计算每个点之间的距离
  3. 计算每个点的排斥向量,使其远离所有其他点(使用1 /(距离 ^ 2)作为向量的大小)
  4. 求和每个点的排斥矢量
  5. 根据求和的排斥向量更新每个点的位置
  6. 约束任何出界坐标(例如亮度为负值或高于1)
  7. 从步骤2开始重复,直到点稳定
  8. 对于每个点,从原始 N
  9. 组中选择最接近的颜色

    它远没有效率,但对于小 M ,它可能足够有效,并且它将提供接近最佳的结果。

    如果您的色距功能很简单,可能会有更确定的方法来生成最佳子集。

答案 6 :(得分:1)

您可以根据与任何索引颜色的最小距离的最大距离对候选颜色进行排序。

使用欧几里德色距:

public double colordistance(Color color0, Color color1) {
    int c0 = color0.getRGB();
    int c1 = color1.getRGB();
    return distance(((c0>>16)&0xFF), ((c0>>8)&0xFF), (c0&0xFF), ((c1>>16)&0xFF), ((c1>>8)&0xFF), (c1&0xFF));
}

public double distance(int r1, int g1, int b1, int r2, int g2, int b2) {
    int dr = (r1 - r2);
    int dg = (g1 - g2);
    int db = (b1 - b2);
    return Math.sqrt(dr * dr + dg * dg + db * db);
}

虽然你可以用你想要的任何东西替换它。它只需要一个颜色距离程序。

public void colordistancesort(Color[] candidateColors, Color[] indexColors) {
    double current;

    double distance[] = new double[candidateColors.length];
    for (int j = 0; j < candidateColors.length; j++) {
        distance[j] = -1;
        for (int k = 0; k < indexColors.length; k++) {
            current = colordistance(indexColors[k], candidateColors[j]);
            if ((distance[j] == -1) || (current < distance[j])) {
                distance[j] = current;
            }
        }
    }

    //just sorts.
    for (int j = 0; j < candidateColors.length; j++) {
        for (int k = j + 1; k < candidateColors.length; k++) {
            if (distance[j] > distance[k]) {
                double d = distance[k];
                distance[k] = distance[j];
                distance[j] = d;

                Color m = candidateColors[k];
                candidateColors[k] = candidateColors[j];
                candidateColors[j] = m;
            }
        }
    }
}

答案 7 :(得分:0)

你的意思是从一组N种颜色中,你需要选择M种颜色,其中M&lt; N,M是M空间中N种颜色的最佳表示?

更好的例子是,将真彩色(24位色彩空间)缩小为8位映射色彩空间(GIF?)。

对此有量化算法,例如ImageMagic使用的Adaptive Spatial Subdivision算法。

这些算法通常不只是从源空间中选择现有颜色,而是在目标空间中创建与源颜色最相似的新颜色。作为简化示例,如果原始图像中有3种颜色,其中两种是红色(具有不同的强度或蓝色等),第三种是蓝色,并且需要减少为两种颜色,目标图像可能具有红色这是原始图像的原始两个红色+蓝色的某种平均值。

如果你还需要其他东西,那我就不明白你的问题:)

答案 8 :(得分:0)

您可以将它们分割为RGB HEX格式,以便您可以将R与不同颜色的R进行比较,与G和B相同。

与HTML格式相同

XX XX XX
RR GG BB

00 00 00 = black
ff ff ff = white
ff 00 00 = red
00 ff 00 = green
00 00 ff = blue

因此,您唯一需要决定的是您希望颜色的接近程度以及这些细分可以接受的差异是什么。