from webcolors import html4_hex_to_names, hex_to_rgb # 16 основных цветов, hex соответвуют hex цветам livecarta # названия другие html4_hex_to_names = {'#00ffff': 'aqua', '#000000': 'black', '#0000ff': 'blue', '#ff00ff': 'fuchsia', '#008000': 'green', '#808080': 'grey', '#00ff00': 'lime', '#800000': 'maroon', '#000080': 'navy', '#808000': 'olive', '#800080': 'purple', '#ff0000': 'red', '#c0c0c0': 'silver', '#008080': 'teal', '#ffffff': 'white', '#ffff00': 'yellow'} def rgb2hsv(r, g, b): r /= 255 g /= 255 b /= 255 max_c = max(r, g, b) min_c = min(r, g, b) value = max_c if min_c == max_c: return 0.0, 0.0, value * 100 saturation = (max_c - min_c) / max_c rc = (max_c - r) / (max_c - min_c) gc = (max_c - g) / (max_c - min_c) bc = (max_c - b) / (max_c - min_c) if r == max_c: hue = 0.0 + bc - gc elif g == max_c: hue = 2.0 + rc - bc else: hue = 4.0 + gc - rc hue2 = ((hue + 6) / 6.0) if (hue < 0) else (hue / 6.0) return hue2 * 360, saturation * 100, value * 100 HTML_COLORS_HSV = {} for key, name in html4_hex_to_names.items(): r, g, b = hex_to_rgb(key) h, s, v = rgb2hsv(r, g, b) HTML_COLORS_HSV[name] = (h, s, v) def rgb2closest_html_color_name(color): """ - get color in hsv (hue, saturation, value) - try to match with black, grey, silver (black, darkGray, lightGray) as this colors matches badly even in hsv model - calc hue difference between color and all base colors - if for new base color hue diff same as for any other, try to measure saturation and value (it happens for similar colors like red - pink, blue - dark blue) :param color: str, color in hex :return: base color name that matches best to a given color """ if color == (255, 255, 255): return 'white' diff2base_color_dict = {} rgb = hex_to_rgb(color) hue_request, s_request, v_request = rgb2hsv(*rgb) if v_request <= 30: return 'black' if v_request <= 50 and s_request <= 25: # ** return 'gray' if s_request <= 10 and (90 <= v_request <= 100): return 'white' if s_request <= 40: return 'silver' for _, name in html4_hex_to_names.items(): if name in ['white', 'black', 'grey', 'silver']: continue hue_html, s_html, v_html = HTML_COLORS_HSV[name] hue_diff = abs(hue_html - hue_request) if hue_diff == 20: pass if hue_diff in diff2base_color_dict: dist_cur_color =(hue_request - hue_html) ** 2 + (s_request - s_html) ** 2 + (v_request - v_html) ** 2 hue_prev, s_prev, v_prev = HTML_COLORS_HSV[diff2base_color_dict[hue_diff]] dist_prev_color = (hue_request - hue_prev) ** 2 + (s_request - s_prev) ** 2 + (v_request - v_prev) ** 2 if dist_cur_color < dist_prev_color: diff2base_color_dict[hue_diff] = name else: diff2base_color_dict[hue_diff] = name return diff2base_color_dict[min(diff2base_color_dict.keys())] if __name__ == '__main__': hex_colors = [ #'#945893', # '#96F', # '#000', # black # '#4C4C4C', # black # '#A00', # '#99F', '#f89921', # '#f89921', '#EFF8F6' # '#e5c099', # yellow # '#008b90', # teal # '#c4762a', # red # '#996A95', '#70416F', # purple # '#D5C9D3', '#E9E2E8', # silver # '#FFD472', '#F47B4D', '#FFFBEF', '#F47B4D', # yellow, red ,yellow, red # '#B0DFD7', '#EFF8F6', '#5CC4B7' ] for c in hex_colors: n = rgb2closest_html_color_name(c) print(n) # "Actual colour:", c, ", closest colour name:", # print()