Human-readable color names like "Navy Blue" are more intuitive than RGB tuples (0, 0, 128). Converting between them requires either exact matching against known colors or finding the mathematically closest named color.
This guide covers both approaches with practical implementations.
Exact Match with webcolors
For standard CSS3 colors, use direct lookup:
pip install webcolorsimport webcolors
def rgb_to_name_exact(rgb_tuple):
"""Get exact color name or None if no match."""
try:
return webcolors.rgb_to_name(rgb_tuple)
except ValueError:
return None
print(rgb_to_name_exact((255, 0, 0))) # red
print(rgb_to_name_exact((0, 0, 128))) # navy
print(rgb_to_name_exact((250, 5, 5))) # None (no exact match)Closest Match with Euclidean Distance
Find the nearest named color mathematically:
import webcolors
import math
def closest_color(rgb):
"""Find the closest CSS3 named color."""
min_distance = float('inf')
closest_name = None
for name in webcolors.names("css3"):
r, g, b = webcolors.name_to_rgb(name)
distance = math.sqrt(
(r - rgb[0]) ** 2 +
(g - rgb[1]) ** 2 +
(b - rgb[2]) ** 2
)
if distance < min_distance:
min_distance = distance
closest_name = name
return closest_name
print(closest_color((250, 0, 0))) # red
print(closest_color((250, 10, 10))) # red
print(closest_color((100, 50, 75))) # dimgray (or similar)Combined Approach
Try exact match first, then fall back to closest:
import webcolors
import math
def rgb_to_name(rgb):
"""Get color name: exact if available, otherwise closest."""
try:
return webcolors.rgb_to_name(rgb)
except ValueError:
pass
min_distance = float('inf')
closest_name = None
for name in webcolors.names("css3"):
r, g, b = webcolors.name_to_rgb(name)
distance = sum((a - b) ** 2 for a, b in zip(rgb, (r, g, b)))
if distance < min_distance:
min_distance = distance
closest_name = name
return closest_name
print(rgb_to_name((255, 0, 0))) # red (exact)
print(rgb_to_name((255, 10, 10))) # red (closest)Hex Code to Color Name
Common in web development:
import webcolors
import math
def rgb_to_name_with_confidence(rgb):
"""Get color name with distance score."""
try:
return {
'name': webcolors.rgb_to_name(rgb),
'distance': 0,
'exact_match': True
}
except ValueError:
pass
min_distance = float('inf')
closest_name = None
for name in webcolors.names("css3"):
r, g, b = webcolors.name_to_rgb(name)
distance = math.sqrt(sum((a - b) ** 2 for a, b in zip(rgb, (r, g, b))))
if distance < min_distance:
min_distance = distance
closest_name = name
confidence = 1 - (min_distance / 441.67)
return {
'name': closest_name,
'distance': round(min_distance, 2),
'confidence': round(confidence, 2),
'exact_match': False
}
print(rgb_to_name_with_confidence((255, 0, 0)))
print(rgb_to_name_with_confidence((200, 50, 50)))With Color Distance and Confidence
Return both name and match quality:
import webcolors
import math
def rgb_to_name_with_confidence(rgb):
"""Get color name with distance score."""
try:
return {
'name': webcolors.rgb_to_name(rgb),
'distance': 0,
'exact_match': True
}
except ValueError:
pass
min_distance = float('inf')
closest_name = None
for name in webcolors.names("css3"):
r, g, b = webcolors.name_to_rgb(name)
distance = math.sqrt(sum((a - b) ** 2 for a, b in zip(rgb, (r, g, b))))
if distance < min_distance:
min_distance = distance
closest_name = name
confidence = 1 - (min_distance / 441.67)
return {
'name': closest_name,
'distance': round(min_distance, 2),
'confidence': round(confidence, 2),
'exact_match': False
}
print(rgb_to_name_with_confidence((255, 0, 0)))
print(rgb_to_name_with_confidence((200, 50, 50)))Color Categories (Simple Grouping)
For basic color classification:
def get_basic_color(rgb):
"""Classify RGB into basic color category."""
r, g, b = rgb
if abs(r - g) < 20 and abs(g - b) < 20 and abs(r - b) < 20:
if max(r, g, b) < 50:
return "black"
elif min(r, g, b) > 200:
return "white"
return "gray"
max_val = max(r, g, b)
if r == max_val:
if g > b:
return "orange" if g > 100 else "red"
return "red" if b < 100 else "pink"
elif g == max_val:
if b > r:
return "cyan" if b > 100 else "green"
return "green" if r < 100 else "yellow"
else: # b == max_val
if r > g:
return "purple" if r > 100 else "blue"
return "blue"
print(get_basic_color((255, 0, 0))) # red
print(get_basic_color((50, 50, 50))) # gray
print(get_basic_color((255, 165, 0))) # orangeUsing scipy for Efficient Distance Calculation
For processing many colors:
import webcolors
import numpy as np
from scipy.spatial import KDTree
def build_color_tree():
colors = []
names = []
for name in webcolors.names("css3"):
colors.append(webcolors.name_to_rgb(name))
names.append(name)
return KDTree(colors), names
COLOR_TREE, COLOR_NAMES = build_color_tree()
def rgb_to_name_fast(rgb):
"""Fast color name lookup using KDTree."""
distance, index = COLOR_TREE.query(rgb)
return COLOR_NAMES[index]
print(rgb_to_name_fast((200, 50, 50))) # firebrickBatch Processing
Convert multiple colors efficiently:
import webcolors
import math
def rgb_to_name(rgb):
"""Get color name: exact if available, otherwise closest."""
try:
return webcolors.rgb_to_name(rgb)
except ValueError:
pass
min_distance = float('inf')
closest_name = None
for name in webcolors.names("css3"):
r, g, b = webcolors.name_to_rgb(name)
distance = sum((a - b) ** 2 for a, b in zip(rgb, (r, g, b)))
if distance < min_distance:
min_distance = distance
closest_name = name
return closest_name
def batch_rgb_to_names(rgb_list):
"""Convert list of RGB tuples to names."""
return [rgb_to_name(rgb) for rgb in rgb_list]
colors = [
(255, 0, 0),
(0, 255, 0),
(0, 0, 255),
(255, 165, 0),
(128, 0, 128)
]
names = batch_rgb_to_names(colors)
print(dict(zip(colors, names)))Practical Example: Image Color Analysis
from PIL import Image
from collections import Counter
def get_dominant_colors(image_path, n_colors=5):
"""Get most common color names in an image."""
img = Image.open(image_path)
img = img.convert('RGB')
img = img.resize((100, 100)) # Reduce for speed
pixels = list(img.getdata())
color_names = [rgb_to_name(pixel) for pixel in pixels]
return Counter(color_names).most_common(n_colors)Summary
| Input | Method | Use Case |
|---|---|---|
| Exact RGB | webcolors.rgb_to_name() |
Standard CSS colors |
| Any RGB | Euclidean distance | Real-world colors |
| Hex code | hex_to_rgb() + distance |
Web development |
| Bulk processing | KDTree + scipy | Image analysis |