Given a color either in RGB or Hex, how do I find colors that are similar to it? By similar I mean they should be distinguishable by small values.
-
1why not simply take the euclidian distance between their rgb codes? something like numpy.sqrt((r1 - r0)**2 + (g1 - g0)**2 + (b1 - b0)**2.) – user2660966 Jun 08 '17 at 06:37
-
@user2660966 But the human perception of colors is different and won't match with the euclidian distance. – moritzg Jun 08 '17 at 06:39
-
You might consider converting your colors to HSV colorspace. – taras Jun 08 '17 at 06:53
-
@user128285 And then how do i proceed? – Jp Reddy Jun 08 '17 at 08:31
-
@JpReddy this might help: https://stackoverflow.com/a/35114586/3023116 – taras Jun 08 '17 at 09:48
2 Answers
The RGB color space is device dependent and not perceptually uniform. If you intend to measure color similarities, you should transform first the RGB values into a device-independent and more perceptually uniform color space, for example CIELAB. Then you can measure the color differences through a proper similarity metric, like Lab Delta E.
Demo
Consider this image:
Let us assume that your reference colors are a shade of green and a shade of magenta, whose RGB values are for example [0, 160, 0]
and [120, 0, 140]
. The following snippet identifies those image pixels whose Delta E with respect to the reference colors is lower than a certain threshold (15
and 20
, respectively).
import numpy as np
from skimage import io
from skimage.color import rgb2lab, deltaE_cie76
rgb = io.imread('https://i.stack.imgur.com/npnrv.png')
lab = rgb2lab(rgb)
green = [0, 160, 0]
magenta = [120, 0, 140]
threshold_green = 15
threshold_magenta = 20
green_3d = np.uint8(np.asarray([[green]]))
magenta_3d = np.uint8(np.asarray([[magenta]]))
dE_green = deltaE_cie76(rgb2lab(green_3d), lab)
dE_magenta = deltaE_cie76(rgb2lab(magenta_3d), lab)
rgb[dE_green < threshold_green] = green_3d
rgb[dE_magenta < threshold_magenta] = magenta_3d
io.imshow(rgb)
Based on Tonechas answer,
To have a similar color detection value (and not a visualization):
import numpy as np
from skimage import io
from skimage.color import rgb2lab, deltaE_cie76
def get_pct_color(img_rgb, rgb_color, threshold=10):
img_lab = rgb2lab(img_rgb)
rgb_color_3d = np.uint8(np.asarray([[rgb_color]]))
rgb_color_lab = rgb2lab(rgb_color_3d)
delta = deltaE_cie76(rgb_color_lab, img_lab)
x_positions, y_positions = np.where(delta < threshold)
nb_pixel = img_rgb.shape[0] * img_rgb.shape[1]
pct_color = len(x_positions) / nb_pixel
return pct_color
With an example:
img_rgb = io.imread('https://i.stack.imgur.com/npnrv.png')
green = [0, 160, 0]
get_pct_color(img_rgb, green, 10)
# 0.016131591796875
get_pct_color(img_rgb, green, 250)
# 1.0