Given an RGB value what would be the best way to find the closest match in the database?

前端 未结 8 1580
别跟我提以往
别跟我提以往 2020-12-04 17:02

I have a rgb value and if it doesn\'t exist in the color table in my database I need to find the closest color. I was thinking of comparing all values and finding the diffe

相关标签:
8条回答
  • 2020-12-04 17:15

    Consider a color as a vector in 3-dimensional space, you can then easily compute the difference by using 3d pythagoras:

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

    However, note that due to colors being subject to interpretation by not-so-perfect eyes, you might want to adjust the colors to avoid them having the same importance.

    For instance, using a typical weighted approach:

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

    Since eyes are most sensitive to green, and least sensitive to blue, two colors that differ only in the blue component must thus have a larger numeric difference to be considered "more different" than one that is the same numeric difference in the green component.

    There's also various ways to optimize this calculation. For instance, since you're not really interested in the actual d value, you can dispense with the square root:

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

    Note here that in many C-syntax-based programming languages (like C#), ^ does not mean "raise to the power of", but rather "binary exclusive or".

    So if this was C#, you would use Math.Pow to calculate that part, or just expand and do the multiplication.

    Added: Judging by the page on Color difference on Wikipedia, there's various standards that try to handle perceptual differences. For instance, the one called CIE94 uses a different formula, in the L*C*h color model that looks like it's worth looking into, but it depends on how accurate you want it to be.

    0 讨论(0)
  • 2020-12-04 17:20

    Calculate both the average and the distance like this:

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

    This should give you a good idea of the closest value.

    0 讨论(0)
  • 2020-12-04 17:22

    Let the database do it for you:

    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))
    

    Where @r, @g, and @b are the r,g,b values of the color that you're searching for (SQL Server parameter syntax, since you didn't specify a database). Note that this is still going to have to do a table scan since the order by has a function call in it.

    Note that the extra square root call isn't actually required since it's a monotonic function. Not that it would probably matter very much, but still.

    0 讨论(0)
  • 2020-12-04 17:24

    One step better than average is nearest square root:

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

    This minimizes the distance in 3D color space.

    Since a root is strictly increasing, you can search for the maximum of the square instead. How you express this in SQL would depend on which RDBMS you're using.

    0 讨论(0)
  • 2020-12-04 17:25

    From looking at the Wikipedia page on Color difference, the idea is to treat RGB colours as points in three dimensions. The difference between two colours is the same as the distance between two points:

    difference = sqrt((red1 - red2)^2 + (green1 - green2)^2 + (blue1 - blue2)^2)
    
    0 讨论(0)
  • 2020-12-04 17:32

    Comparing a color sample to the whole color list every time is probably not optimal. This can be optimized by putting the colors in the color list into a search tree. If you are comparing the color sample on its Red, Green and Blue (RGB) value, you would put the colors in the color list into a three dimensional search tree. The search tree could be created once and saved to a (json, xml) file or in a database. This may be worth it if speed is important, e.g. there are many points to compare.

    • Use a [k-d tree] with the R, G and B values 0-256 as X, Y, and Z coordinates1.
    • Or another type of nearest neighbour search.
    0 讨论(0)
提交回复
热议问题