Convert Rgb Values to Color Name

Convert RGB values to color name

  1. Populate a list of "known" colors.
  2. For each known color compute:

    rgbDistance = Math.abs(myColor.getRed() - colorI.getRed() + 
    Math.abs(myColor.getGreen() - colorI.getGreen()) +
    Math.abs(myColor.getBlue() - colorI.getBlue())
  3. Return the name of colorI for which rgbDistance was smallest.

Convert RGB color to English color name, like 'green' with Python

It looks like webcolors will allow you to do this:

rgb_to_name(rgb_triplet, spec='css3')

Convert a 3-tuple of integers, suitable for use in an rgb() color triplet, to its corresponding normalized color name, if any such name exists; valid values are html4, css2, css21 and css3, and the default is css3.

Example:

>>> rgb_to_name((0, 0, 0))
'black'

it is vice-versa-able:

>>> name_to_rgb('navy')
(0, 0, 128)

#To find the closest colour name:

However webcolors raises an exception if it can't find a match for the requested colour. I've written a little fix that delivers the closest matching name for the requested RGB colour. It matches by Euclidian distance in the RGB space.

import webcolors

def closest_colour(requested_colour):
min_colours = {}
for key, name in webcolors.css3_hex_to_names.items():
r_c, g_c, b_c = webcolors.hex_to_rgb(key)
rd = (r_c - requested_colour[0]) ** 2
gd = (g_c - requested_colour[1]) ** 2
bd = (b_c - requested_colour[2]) ** 2
min_colours[(rd + gd + bd)] = name
return min_colours[min(min_colours.keys())]

def get_colour_name(requested_colour):
try:
closest_name = actual_name = webcolors.rgb_to_name(requested_colour)
except ValueError:
closest_name = closest_colour(requested_colour)
actual_name = None
return actual_name, closest_name

requested_colour = (119, 172, 152)
actual_name, closest_name = get_colour_name(requested_colour)

print "Actual colour name:", actual_name, ", closest colour name:", closest_name

Output:

Actual colour name: None , closest colour name: cadetblue

RGB to Color Name Mapping (Approximate Color Mapping)

I am not sure if it is the best way, but if I ever had to do something like this, I think I would first convert these hex values to hsl.

Then you would have to check for saturation and luminance in order to find grays and add more granularity in your findings.

Here is a rough proof of concept using only 6 base colors and with a stolen code from an older question to do this hex => hsl conversion.

inp.oninput = e => {  if (!inp.checkValidity()) return;  var val = inp.value;  if (val.length !== 3 && val.length !== 6) return;  var color = hexToName(inp.value);  if (color) {    inp.style.backgroundColor = '#' + val;    log.textContent = color;  }}

function hexToName(hex) { // first get hsl correspondance var hsl = hexToHsl(hex); if(!hsl){ return; } // get the base color var color = getColorName(hsl[0] * 360); // check saturation and luminosity // needs more granularity, left as an exercise for the reader if (hsl[1] < .5) { return hsl[2] <= .5 ? hsl[2] === 0? 'black' : 'darkgray' : hsl[2] === 1 ? 'white': 'gray'; } return hsl[2] <= .5 ? color : 'light' + color;}function getColorName(hue) { // here you will need more work: // we use fixed distance for this simple demo var names = ['red', 'yellow', 'green', 'cyan', 'blue', 'magenta']; var angles = [0, 60, 120, 180, 240, 300]; var match = angles.filter(a => a - 60 <= hue && a + 60 > hue )[0] || 0; return names[angles.indexOf(match)];}// shamelessly stolen from https://stackoverflow.com/a/3732187/3702797function hexToHsl(hex) { if (hex.length === 3) { hex = hex.split('').map(c => c.repeat(2)).join(''); } if (hex.length !== 6) { return; } var r = parseInt(hex[0] + hex[1], 16); var g = parseInt(hex[2] + hex[3], 16); var b = parseInt(hex[4] + hex[5], 16);
r /= 255, g /= 255, b /= 255; var max = Math.max(r, g, b), min = Math.min(r, g, b); var h, s, l = (max + min) / 2;
if (max == min) { h = s = 0; // achromatic } else { var d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; }
return [h, s, l];}
#<input id="inp" type="text" pattern="[0-9a-fA-F]+"><pre id="log"><pre>

Converting RGB values into color

There are an example to return the color name which depend on using Reflection to get the name of the color (java.awt.Color)

public static String getNameReflection(Color colorParam) {
try {
//first read all fields in array
Field[] field = Class.forName("java.awt.Color").getDeclaredFields();
for (Field f : field) {
String colorName = f.getName();
Class<?> t = f.getType();
if (t == java.awt.Color.class) {
Color defined = (Color) f.get(null);
if (defined.equals(colorParam)) {
System.out.println(colorName);
return colorName.toUpperCase();
}
}
}
} catch (Exception e) {
System.out.println("Error... " + e.toString());
}
return "NO_MATCH";
}

and in the main

        Color colr = new Color(1.0f, 0.0f, 0.0f);
Main m = new Main();
m.getNameReflection(colr);
}

You have to know that :"java.awt.Color" defined this colors:

white
WHITE
lightGray
LIGHT_GRAY
gray
GRAY
darkGray
DARK_GRAY
black
BLACK
red
RED
pink
PINK
orange
ORANGE
yellow
YELLOW
green
GREEN
magenta
MAGENTA
cyan
CYAN
blue
BLUE

Convert rgb color to closest valid CSS3 color name

Here you are. The function itself is pure JS. Only test function uses jQuery.
Colors are defined in an array of structures, because you said you want to match to about 10 specific colors only. Most of the code is for presentation.

Function findClosestColorHex takes as parameter hex value such as '#FF0000', while findClosestColorRGB takes 3 separate integers for R, G, B. Both functions take the color table as parameter, so it can be swaped if needed, but if you are going to use one fixed table, you can change this.

In some combinations the result is not perfect because the colors that I have defined in array are only 16 basic colors.

var ColorTable = [
{name:'black', hex: '#000000'},
{name:'silver', hex: '#C0C0C0'},
{name:'gray', hex: '#808080'},
{name:'white', hex: '#FFFFFF'},
{name:'maroon', hex: '#800000'},
{name:'red', hex: '#FF0000'},
{name:'purple', hex: '#800080'},
{name:'fuchsia', hex: '#FF00FF'},
{name:'green', hex: '#008000'},
{name:'lime', hex: '#00FF00'},
{name:'olive', hex: '#808000'},
{name:'yellow', hex: '#FFFF00'},
{name:'navy', hex: '#000080'},
{name:'blue', hex: '#0000FF'},
{name:'teal', hex: '#008080'},
{name:'aqua', hex: '#00FFFF'}
];

Hex2RGB = function(hex) {
if (hex.lastIndexOf('#') > -1) {
hex = hex.replace(/#/, '0x');
} else {
hex = '0x' + hex;
}
var r = hex >> 16;
var g = (hex & 0x00FF00) >> 8;
var b = hex & 0x0000FF;
return {r:r, g:g, b:b};
};

function findClosestColorHex(hex, table)
{
var rgb = Hex2RGB(hex);
var delta = 3 * 256*256;
var temp = {r:0, g:0, b:0};
var nameFound = 'black';

for(i=0; i<table.length; i++)
{
temp = Hex2RGB(table[i].hex);
if(Math.pow(temp.r-rgb.r,2) + Math.pow(temp.g-rgb.g,2) + Math.pow(temp.b-rgb.b,2) < delta)
{
delta = Math.pow(temp.r-rgb.r,2) + Math.pow(temp.g-rgb.g,2) + Math.pow(temp.b-rgb.b,2);
nameFound = table[i].name;
}
}
return nameFound;
}

function findClosestColorRGB(r, g, b, table)
{
var rgb = {r:r, g:g, b:b};
var delta = 3 * 256*256;
var temp = {r:0, g:0, b:0};
var nameFound = 'black';

for(i=0; i<table.length; i++)
{
temp = Hex2RGB(table[i].hex);
if(Math.pow(temp.r-rgb.r,2) + Math.pow(temp.g-rgb.g,2) + Math.pow(temp.b-rgb.b,2) < delta)
{
delta = Math.pow(temp.r-rgb.r,2) + Math.pow(temp.g-rgb.g,2) + Math.pow(temp.b-rgb.b,2);
nameFound = table[i].name;
}
}
return nameFound;
}

//alert(findClosestColor('#884455', ColorTable));

// Example code

$('document').ready(function(){

$('#slider_r').val(0);
$('#slider_g').val(0);
$('#slider_b').val(0);

function ReCalc()
{
$('#selected_color').css('background-color', 'rgb('+$('#slider_r').val()+', '+$('#slider_g').val()+', '+$('#slider_b').val()+')');
var ret = findClosestColorRGB($('#slider_r').val(), $('#slider_g').val(), $('#slider_b').val(), ColorTable);
$('#matched_color').css('background-color', ret);
$('#color_name').html(ret);
}

$('#slider_r').change(function(){
$('#value_r').val($('#slider_r').val());
ReCalc();
});
$('#slider_g').change(function(){
$('#value_g').val($('#slider_g').val());
ReCalc();
});
$('#slider_b').change(function(){
$('#value_b').val($('#slider_b').val());
ReCalc();
});

});
.color-field {
display: inline-block;
width: 200px;
height: 50px;
background-color: #000000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
R: <input id="slider_r" type="range" min="0" max="255" step="0"/> <input type=text id="value_r" value='0'><br>
G: <input id="slider_g" type="range" min="0" max="255" step="0"/> <input type=text id="value_g" value='0'><br>
B: <input id="slider_b" type="range" min="0" max="255" step="0"/> <input type=text id="value_b" value='0'><br>
<br>
Selected: <span id='selected_color' class='color-field'> </span><br>
Matched: <span id='matched_color' class='color-field'> </span><span id="color_name"> </span>

Turning RGB Values Into The Basic Colors Of The Rainbow Using Python

The problem with this is there is, in general, no good shortcut. You have to determine the distance from each pixel to each color in the palette, and keep the smallest of those distances.

Here's one that maps to the 16 colors in the HTML4 standard set:

import math
from PIL import Image

colors = [
("black", (0, 0, 0)),
("silver", (192, 192, 192)),
("gray", (128, 128, 128)),
("white", (255, 255, 255)),
("maroon", (128, 0, 0)),
("red", (255, 0, 0)),
("purple", (128, 0, 128)),
("fuchsia", (255, 0, 255)),
("green", (0, 128, 0)),
("lime", (0, 255, 0)),
("olive", (128, 128, 0)),
("yellow", (255, 255, 0)),
("navy", (0, 0, 128)),
("blue", (0, 0, 255)),
("teal", (0, 128, 128)),
("aqua", (0, 255, 255))
]

def distance(a,b):
dx = a[0]-b[0]
dy = a[1]-b[1]
dz = a[2]-b[2]
return math.sqrt(dx*dx+dy*dy+dz*dz)

def findclosest(pixel):
mn = 999999
for name,rgb in colors:
d = distance(pixel, rgb)
if d < mn:
mn = d
color = name
return color

im = Image.open("pacmanmaze.png", 'r')
pix_val = im.getdata()

for i in pix_val:
print(findclosest(i))

From hex color code or RGB to color name using R

Approach is similar to @Richard Ambler's solution to compare distance between test rgb vector and
expansive set of colour mapping from output of colours().

The function rgb2col below with given test rgb values returns approximate matching colour name

Data:

library(scales) #for function show_col

DF = read.table(text="Color Count red green blue
ED1B24 16774 237 27 36
000000 11600 0 0 0
23B14D 5427 35 177 77
FFFFFF 5206 255 255 255
FEF200 3216 254 242 0
ED1B26 344 237 27 38",header=TRUE,stringsAsFactors=FALSE)

#from https://gist.github.com/mbannert/e9fcfa86de3b06068c83

rgb2hex <- function(r,g,b) rgb(r, g, b, maxColorValue = 255)

Function:

 rgb2col = function(r,g,b) {

#create colour name vs. rgb mapping table
colourMap = data.frame(colourNames = colours(),t(col2rgb(colours())))

#input test colours
testDF = data.frame(colourNames="testCol",red = r,green = g,blue = b)

#combine both tables
combDF = rbind(testDF,colourMap)

#convert in matrix representation
combMat= (as.matrix(combDF[,-1]))

#add row labels as colour names
rownames(combMat) = combDF[,1]

#compute euclidean distance between test rgb vector and all the colours
#from mapping table
#using dist function compute distance matrix,retain only upper matrix
#find minimum distance point from test vector

#find closest matching colour name
approxMatchCol = which.min(as.matrix(dist(combMat,upper=TRUE))[1,][-1])

#compare test colour with approximate matching colour
scales::show_col(c(rgb2hex(r,g,b),rgb2hex(colourMap[approxMatchCol,2:4])))

#return colour name
return(approxMatchCol)

}

Output:

sapply(1:nrow(DF),function(x) rgb2col(DF[x,"red"],DF[x,"green"],DF[x,"blue"]))
#firebrick2 black seagreen white yellow firebrick2
# 135 24 574 1 652 135

Plots:

Sample Image

Sample Image

Sample Image

Sample Image

Sample Image

Sample Image



Related Topics



Leave a reply



Submit