【问题标题】:Color Logic Algorithm颜色逻辑算法
【发布时间】:2010-01-20 17:16:38
【问题描述】:

我们正在构建一个体育应用程序,并希望在应用程序的各个部分中加入球队颜色。

现在每个团队都可以使用几种不同的颜色来表示。

我想做的是进行检查以验证两个团队颜色是否在一定范围内,这样我就不会显示两个相似的颜色。

所以,如果团队 1 的主要团队颜色的值为 rgb(255,0,0)(或 #FF0000),并且团队 2 的主要颜色相似,例如 rgb(250,0,0),那么我们会为其中一个团队选择不同的颜色。

如果可能,我可以采取什么方法进行检查?

谢谢

【问题讨论】:

    标签: java javascript algorithm colors


    【解决方案1】:

    这是theoretical explanation

    C 中的算法:

    typedef struct {
        unsigned char r, g, b;
    } RGB;
    
    double ColourDistance(RGB e1, RGB e2)
    {
        long rmean = ( (long)e1.r + (long)e2.r ) / 2;
        long r = (long)e1.r - (long)e2.r;
        long g = (long)e1.g - (long)e2.g;
        long b = (long)e1.b - (long)e2.b;
        return sqrt((((512+rmean)*r*r)>>8) + 4*g*g + (((767-rmean)*b*b)>>8));
    }
    

    【讨论】:

    • 是将 rgb 值归一化为区间 0..1 还是范围 0..255 的常规值?
    • 最好添加一个注释,该算法与 Wikipedia 的 color difference 文章中描述的技术相比如何,例如。 CIEDE2000.
    • 这个算法是否可以在预定义的颜色中找到最接近的颜色?
    • @Thariama 它们是 0-255,如无符号字符(1 字节)所示
    • @bluenote10 几年前我写了一篇关于这个的博客文章。 (godsnotwheregodsnot.blogspot.com/2012/09/…) 写这篇文章的人做得很棒。它实际上与 CIEdE2k 相比非常有利,因为它只是尺寸的一小部分。它基本上可以很好地捕捉到对色彩空间和权重的最重要的修复。
    【解决方案2】:

    这是 Java 中 pgras 的算法:

    public double ColourDistance(Color c1, Color c2)
    {
        double rmean = ( c1.getRed() + c2.getRed() )/2;
        int r = c1.getRed() - c2.getRed();
        int g = c1.getGreen() - c2.getGreen();
        int b = c1.getBlue() - c2.getBlue();
        double weightR = 2 + rmean/256;
        double weightG = 4.0;
        double weightB = 2 + (255-rmean)/256;
        return Math.sqrt(weightR*r*r + weightG*g*g + weightB*b*b);
    } 
    

    【讨论】:

    • 你还没有申请“>>8”?
    • @sam_k: >>8 是写/256 的不好方式。
    • 为什么不好?你能解释一下我的学习目的吗?
    • @sam_k:代码应该写得易于阅读。当您的意思是“除以 256”时,写 >>8 并没有明确说明意图,因此更难理解。有些人这样做的原因是他们(错误地)相信它使代码更快。它没有——即使是最愚蠢的优化器也足够聪明,可以自动进行优化。
    【解决方案3】:

    这个问题的大多数答案都建议在将 RGB 值映射到 3D 空间时计算两种颜色之间的距离。这种技术的问题在于,在 3D RGB 空间中,具有相似色调但饱和度或亮度级别不同的两种颜色可能比具有不同色调但饱和度和亮度级别非常相似的两种颜色映射得更远。换句话说,在 3D RGB 空间中,蓝色和绿色可能比红色的两种色调更接近。在这个应用程序中,确保团队颜色不同,色调差异应该比亮度和饱和度更重要。

    所以我会将颜色映射从 RGB 转换为色相、饱和度和亮度级别,然后只检查色相值是否有足够的距离。

    Wikipedia has an explanation for converting RGB to HSV.LiteratePrograms has some sample code.

    【讨论】:

    • 我在第一次阅读时错过了 Java 标签。 java.awt.Color 类有一个用于转换的 RGBtoHSB 方法。
    • 如果 OP 只有六个团队就足够了;但如果有 20 或 30+,那么他必须考虑饱和度和亮度。 pgras 给出的链接声称他们的算法比 HSV 距离提供更好的结果(这当然是主观的)。
    • 正如 OP 所说,目标是一次只比较两种颜色。如果 RGB 距离方法的结果不足,我建议使用此方法进行尝试。当我对此进行更多思考时,在比较具有较高饱和度和亮度值的颜色时,仅比较色调值会产生良好的结果,而在比较具有低亮度或低饱和度的颜色时会失败。对这种方法的改进是在检查色调差异之前检查至少一种颜色是否具有足够高的饱和度和亮度值。
    【解决方案4】:

    我会使用两种颜色之间的 3d 距离,其中 x、y、z 是 R、G、B 值。

    看看这个 Perl 库:

    http://metacpan.org/pod/Color::Similarity::RGB

    这很容易自己实现。

    只要确保 (R1-R2)^2 + (G1-G2)^2 + (B1-B2)^2 >= 阈值^2

    【讨论】:

    • 我不得不承认这对于计算机视觉来说效果很好,但我并没有真正考虑到这个答案。
    • 是的,我会说两种颜色看起来有多相似(而不是它们有多相似),我会使用 pgras 算法。人眼远非完美:我们对绿色比对红色或蓝色更敏感,我们的亮度感知是对数的,等等。
    • 根据您的应用程序,您可以使用不同的算法。这个是最简单的。您还可以将 RGB 因子缩放 22、43、35 并获得更好的结果。尽管由 Thiadmer Riemersma 编写,但此处称为 pgras 的 redmean 公式更进一步。然后你继续使用 CIEdE2000,它开始拉伸和拉动色彩空间,使眼睛越来越均匀。它还取决于诸如 XYZ 之类的东西,它可以让您更轻松地解决色盲等问题。
    【解决方案5】:

    Wikipedia 详细介绍了可用于此目的的一些算法。

    还有这个以前的 StackOverflow 问题:Finding an accurate “distance” between colors

    【讨论】:

      【解决方案6】:

      从算法的角度来看,这相当简单。每种颜色代表 3D 空间中的一个点,颜色之间的差异是这些点之间的距离。

      大概这里的重点是确保颜色明显不同。如果是这种情况,确定最小距离可能会相当困难。问题是(至少对于视力正常的人来说)某些差异比其他差异更容易看到。例如,大多数人对绿色阴影的微小差异比对红色或蓝色阴影的同样微小变化更敏感。有一些算法可以考虑到这一点,但它们基于人类的平均视觉,因此不能保证对任何人​​都完全正确。

      只是为了好玩,您可能想看看X-rite's online color vision test

      【讨论】:

      • 那个页面差点让我呕吐
      • 嗯,3D 空间中的一个点是一个简单的观点,我不同意,但我为色觉测试链接 +1
      【解决方案7】:

      我使用了第一个回复中给出的算法,虽然结果没有达到预期,直到我找到了 DeltaE 库,它可以更好地计算颜色之间的距离。

      适用于 Node.js,请查看here

      【讨论】:

        猜你喜欢
        • 2011-11-22
        • 2023-03-10
        • 1970-01-01
        • 2012-02-22
        • 2021-05-16
        • 2020-11-20
        • 2020-11-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多