4

I have ten hex / rgb values for colours (they're skin tones) - I want to be able to find the closest match to a specific hex / rgb value.

Would I somehow iterate from the start colour until I fall within a specific range? But how do I organize the ranges?

I'll be honest, I have absolute zero idea how to do it, or what even to search for, so any help, or a nod in the right direction would be greatly appreciated.

Cheers

Don't Panic
  • 41,125
  • 10
  • 61
  • 80
ojsglobal
  • 525
  • 1
  • 6
  • 31

3 Answers3

3

While Euclidean distance over RGB might help, it would be much better to use a proper color model. I would advise LCH or at least HSL. Then assign weights to each channel. For instance, for human eye, lightness is perceived at logarithmic scale. Tuning down its effect might give better matches. So, following would never happen:

#400 (very dark red) matches #222 (almost blackish gray, distance 12) instead of #800 (dark red, distance 16)

Cem Kalyoncu
  • 14,120
  • 4
  • 40
  • 62
  • Indeed when I use the Euclidean formula I am getting a lot of incorrect matches. @cem-kalyoncu, would you happen to have/know where we can find a better formula? – gmoz22 May 13 '18 at 22:47
  • Use HSL color system and assign a multiplier to channels. Use heigher value for H. If you want even better results go for LCH color system. Formulas are widely available. – Cem Kalyoncu May 15 '18 at 05:21
  • I find this fascinating. Would you be able to provide an example on how to do this in JavaScript? I found [chroma.js](https://gka.github.io/chroma.js/) but the science behind this is beyond my grasp. There was recently a question about [colour detection](https://stackoverflow.com/q/64839035/1244884) which I found very interesting but I provided a very limited answer. Perhaps you could shed some lights there? ;) – customcommander Nov 16 '20 at 21:56
  • Conversions are not very difficult, it's a lot of multiplications. Here is a tested formula that you can use: https://en.wikipedia.org/wiki/Color_difference#CIELAB_%CE%94E* – Cem Kalyoncu Nov 17 '20 at 22:25
2

First off, it's not necessarily a programming question but...

Euclidean distance is a good method for this. As an example:

Using regular html color names, BlueViolet (#8A2BE2) and GoldenRod (#DAA520), which is closer to LightSeaGreen (#20B2AA)? Split the 3 hex values to a 3D vector as such:

BV = 138,43,226
GR = 218,165,32
LSG = 32,178,170

Using the formula:

d(p,q) = sqrt((px - qx)^2 + (py - qy)^2 + (pz - qz)^2)

d(BV,LSG) = sqrt((138-32)^2 + (43-178)^2 + (226-170)^2)
d(BV,LSG) = sqrt(11236 + 18225 + 3136)
d(BV,LSG) = sqrt(32597)
d(BV,LSG) = 180.546

d(GR,LSG) = sqrt((218-32)^2 + (165-178)^2 + (32-170)^2)
d(GR,LSG) = sqrt(34596 + 169 + 19044)
d(GR,LSG) = sqrt(53809)
d(GR,LSG) = 231.967

So as you can see d(BV,LSG) is smaller than d(GR,LSG) so BlueViolet is closer to LightSeaGreen than GoldenRod is.

anothershrubery
  • 20,461
  • 14
  • 53
  • 98
0

I can offer you to use Euclidean distance between 2 colors. If you have any 2 colors, for example #89a839 and #ad9009 , you can convert it into 3 dimentional vectors, and you will get this 2 vectors (ad,90,09) and (89,a8,39); then convert numbers to decimal range. and just count euclidean distance beetween this two points

d = sqrt((x1-x2)^2,(y1-y2)^2,(z1-z2)^2,)

Just count this distance beetween your color and for all colors you have, and find smallest value, then your color will closest to specific color.

If you have any problems for coding this, feel free to ask.

Gor
  • 2,808
  • 6
  • 25
  • 46