【问题标题】:Given an RGB value what would be the best way to find the closest match in the database?给定一个 RGB 值,在数据库中找到最接近匹配的最佳方法是什么?
【发布时间】:2010-12-23 06:09:37
【问题描述】:

我有一个 rgb 值,如果它不存在于我数据库的颜色表中,我需要找到最接近的颜色。我正在考虑比较所有值并找出差异(红色、绿色和蓝色),然后取平均值。最低的平均偏差应该是最接近的颜色。在我看来,应该有更好的方法。有什么想法吗?

【问题讨论】:

  • 存储颜色的表格的结构是什么?
  • 虽然每个答案都暗示 RGB 空间中的欧几里得距离,但不要! HSV 比 RGB 更适合于对感知距离进行建模,因此您应该首先转换您的色彩空间。
  • CIELAB 是描述颜色感知的标准方式。

标签: sql algorithm colors


【解决方案1】:

每次都将颜色样本与整个颜色列表进行比较可能不是最佳选择。这可以通过将颜色列表中的颜色放入搜索树中来优化。如果您要比较颜色样本的红色、绿色和蓝色 (RGB) 值,您可以将颜色列表中的颜色放入三维搜索树中。搜索树可以创建一次并保存到 (json, xml) 文件或数据库中。如果速度很重要,这可能是值得的,例如有很多要比较的地方。

【讨论】:

    【解决方案2】:

    将颜色视为 3 维空间中的向量,然后您可以使用 3d 毕达哥拉斯轻松计算差异:

    d = sqrt((r2-r1)^2 + (g2-g1)^2 + (b2-b1)^2)
    

    但是,请注意,由于颜色会受到不那么完美的眼睛的解释,您可能需要调整颜色以避免它们具有相同的重要性。

    例如,使用a typical weighted approach:

    d = sqrt(((r2-r1)*0.3)^2 + ((g2-g1)*0.59)^2 + ((b2-b1)*0.11)^2)
    

    由于眼睛对绿色最敏感,而对蓝色最不敏感,因此仅在蓝色分量上不同的两种颜色必须具有更大的数字差异,才能被认为比具有相同数字差异的颜色“更不同”。绿色组件。

    还有多种方法可以优化此计算。例如,由于您对实际的 d 值并不真正感兴趣,因此您可以省去平方根:

    d =   ((r2-r1)*0.30)^2
        + ((g2-g1)*0.59)^2
        + ((b2-b1)*0.11)^2
    

    在此请注意,在许多基于 C 语法的编程语言(如 C#)中,^ 并不意味着“提升到幂”,而是“二进制异或”。

    因此,如果这是 C#,您将使用 Math.Pow 来计算该部分,或者只是展开并进行乘法运算。

    添加:从Color difference on Wikipedia 上的页面来看,有各种标准试图处理感知差异。例如,CIE94 使用了不同的公式,在 L*C*h 颜色模型中看起来值得研究,但这取决于您希望它有多准确。

    【讨论】:

    • +1。这似乎接近我,除了眼睛对亮度也比对颜色更敏感,因此最佳差异还应该考虑颜色向量之间的角度,以及它们的长度和从尖端到尖端的距离-提示。
    • 当然。 “最接近的颜色”不仅仅是数学差异,而是更多的理论。
    • 不错的答案...是的,颜色可能不仅仅是数学上的差异...因此可以测量调整。
    • 权重是一种技巧;正如您在编辑中提到的那样,感知颜色模型更适合于此。
    【解决方案3】:

    Euclidean distancedifference = sqrt(sqr(red1 - red2) + sqr(green1 - green2) + sqr(blue1 - blue2))standard way 来判断两种颜色的相似度。

    但是,如果您将颜色放在一个简单的列表中,那么要找到最接近的颜色需要计算新颜色与列表中每种颜色的距离。这是一个 O(n) 操作。

    sqrt() 是一项昂贵的操作,如果您只是比较两个距离,那么您可以简单地省略 sqrt()

    如果您有一个非常大的调色板,将颜色组织到kd tree(或alternatives 之一)中可能会更快,以减少需要计算的差异数量。

    【讨论】:

      【解决方案4】:

      以下内容完全符合您的描述:

      select (abs(my_R - t.r) + abs(my_G - t.g) + abs(my_B - t.b)) / 3 as difference, t.*
      from RGBtable t
      order by difference desc;
      

      但是,使用非线性的东西可能会获得更好的结果。在“取平均值”方法中,如果您的目标颜色是 (25, 25, 25),则颜色 (45, 25, 25) 将比 (35, 35, 35) 更接近。但是,我敢打赌,第二个实际上会看起来更近,因为它也是灰色的。

      我想到了一些想法:您可以先将差值求平方,然后再取平均值。或者,您可以做一些复杂的事情,找到不同值之间比率最接近的颜色。找到最接近的比率将使您最接近正确的色调,但不会考虑饱和度(如果我没记错的话......)

      【讨论】:

        【解决方案5】:

        比平均值好一步是最接近的平方根:

        ((delta red)^2 + (delta green)^2 + (delta blue)^2)^0.5
        

        这会最小化 3D 色彩空间中的距离。

        由于根是严格递增的,因此您可以搜索平方的最大值。如何在 SQL 中表达这一点取决于您使用的 RDBMS。

        【讨论】:

          【解决方案6】:

          让数据库为你做:

          select top 1
            c.r,
            c.b,
            c.g
          from
            color c
          order by
            (square(c.r - @r) + square(c.g - @g) + square(c.b - @b))
          

          其中@r@g@b 是您正在搜索的颜色的 r、g、b 值(SQL Server 参数语法,因为您没有指定数据库)。请注意,这仍然需要进行表扫描,因为 order by 中有一个函数调用。

          请注意,实际上并不需要额外的平方根调用,因为它是一个单调函数。并不是说它可能非常重要,但仍然如此。

          【讨论】:

          • 数据库不是魔杖。这样做需要做的工作与自己做一样多 - 您只是将工作卸载到数据库中。
          • 好吧,因为数据已经在数据库中,所以我只获取所需的行而不是获取所有行来自己计算距离对我来说更有意义。
          【解决方案7】:

          the Wikipedia page on Color difference 来看,这个想法是将 RGB 颜色视为三个维度中的点。两种颜色的区别就等于两点之间的距离:

          difference = sqrt((red1 - red2)^2 + (green1 - green2)^2 + (blue1 - blue2)^2)
          

          【讨论】:

            【解决方案8】:

            像这样计算平均值和距离:

            (r + g + b) / 3 = average
            (r - average) + (g - average) + (b - average) = distance
            

            这应该让您对最接近的值有一个很好的了解。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-05-20
              • 2017-10-26
              • 1970-01-01
              相关资源
              最近更新 更多