原始问题

如果给你 N 种最大距离的颜色(以及一些相关的距离度量),你能想出一种方法将这些颜色按某种顺序排序,使得前 M 种颜色也相当接近于最大不同的集合吗?

换句话说,给定一堆不同的颜色,提出一个排序,这样我就可以从一开始就使用尽可能多的颜色,并合理地保证它们都是不同的,并且附近的颜色也非常不同(例如,蓝红色不次于红蓝色)。

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

澄清:给定一些大的且视觉上不同的颜色集(例如 256 或 1024),我想对它们进行排序,以便当我使用其中的第一个(例如 16 个)时,我可以获得视觉上相对不同的颜色子集。粗略地说,这相当于说我想对这个包含 1024 个颜色的列表进行排序,以便各个颜色在视觉上越接近,它们在列表中的距离就越远。

没有正确的解决方案

其他提示

这对我来说也听起来像是某种 电阻图 您尝试绘制出阻力最小的路径。如果你反转最大阻力的要求,它也许可以用来产生一个集合,从一开始就产生最大的差异,并且在最后开始返回到更接近其他值的值。

例如,这里有一种方法可以做你想做的事。

  1. 计算距离(参考 你的其他帖子) 从每种颜色到所有其他颜色
  2. 将每种颜色的距离相加,这将为您提供以下指示: 该颜色与所有其他颜色的总距离有多远
  3. 按距离向下排序列表

这似乎会产生一个列表,该列表以距所有其他颜色最远的颜色开始,然后向下,接近列表末尾的颜色通常会更接近其他颜色。

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

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

看来感知对您来说很重要,在这种情况下,您可能需要考虑使用感知色彩空间,例如 YUV、YCbCr 或 Lab。每次我使用它们时,它们都给了我比单独使用 sRGB 更好的结果。

与 sRGB 之间的转换可能会很痛苦,但在您的情况下,它实际上可以使算法更简单,而且作为奖励,它也主要适用于色盲!

N 个最远颜色可以被视为 3 维(颜色)空间中的一组均匀分布的点。如果您可以从 霍尔顿序列, ,那么任何前缀(前 M 种颜色)也由均匀分布的点组成。

如果我正确理解这个问题,您希望获得以下子集 中号 颜色与 最大平均距离 颜色之间,给定一些距离函数 d.

换句话说,考虑初始集合 颜色作为一个大的无向图,其中所有颜色都是连接的,您想要找到 最长路径 访问任何 中号 节点。

恐怕解决 NP 完全图问题远远超出了我的能力,但你可以尝试运行一个简单的物理模拟:

  1. 产生 中号 颜色空间中的随机点
  2. 计算每个点之间的距离
  3. 计算每个点的斥力矢量,使其远离所有其他点(使用 1 / (距离 ^ 2) 作为向量的大小)
  4. 对每个点的斥力矢量求和
  5. 根据斥力矢量之和更新每个点的位置
  6. 限制任何超出范围的坐标(例如光度变为负值或大于 1)
  7. 重复步骤 2 直至点稳定
  8. 对于每个点,从原始集合中选择最接近的颜色

这远非高效,但对于小型企业来说 中号 它可能足够有效,并且会给出接近最佳的结果。

如果您的颜色距离函数很简单,则可能有一种更具确定性的方法来生成最佳子集。

  1. 从两个列表开始。CandidateColors,最初包含您的独特颜色和 SortedColors,最初为空。
  2. 选择任何颜色并将其从 CandidateColors 中删除,然后将其放入 SortedColors 中。这是第一种颜色,也是最常见的颜色,因此这是选择与您的应用程序相匹配的颜色的好地方。
  3. 对于 CandidateColors 中的每种颜色,计算其总距离。总距离是从 CandidateColor 到 SortedColors 中每种颜色的距离之和。
  4. 从 CandidateColors 中删除总距离最大的颜色,并将其添加到 SortedColors 的末尾。
  5. 如果 CandidateColors 不为空,则返回步骤 3。

这种贪心算法应该会给你很好的结果。

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

使用欧几里得颜色距离:

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;
            }
        }
    }
}

您的意思是从一组 N 种颜色中,您需要选择 M 种颜色,其中 M < N,这样 M 就是 最好的 M空间中N种颜色的表示?

作为一个更好的示例,将真彩色(24 位颜色空间)减少为 8 位映射颜色空间(GIF?)。

有一些量化算法可以实现这一点,例如 自适应空间细分 ImageMagic 使用的算法。

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

如果您需要其他东西,那么我不明白您的问题:)

您可以将它们拆分为 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

因此,您唯一需要决定的是您希望颜色有多接近,以及分段被认为不同的可接受的差异是多少。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top