OpenVoiceOS's multilingual color parsing and formatting library
Project description
OVOS Color Parser
Turn natural-language color descriptions into color objects, and color objects back into names, in 23 languages. Pure Python, zero network, no ML model — just bundled wordlists and color math.
from ovos_color_parser import color_from_description
c = color_from_description("dark red", lang="en")
print(c.hex_str) # "#3B1315"
print(c.as_hls) # HLSColor(h=357, l=0.153..., s=0.513..., ...)
It ships as part of the OpenVoiceOS voice stack, but it is a standalone library first: nothing here imports OVOS. It is equally useful for NER over free text, describing colors for text-to-speech, and mapping color descriptions to hex for UI theming or LED control.
Installation
pip install ovos-color-parser
# or, with uv:
uv pip install ovos-color-parser
30-second quickstart
from ovos_color_parser import color_from_description, lookup_name, sRGBAColor
# text -> color
c = color_from_description("warm mustard yellow", lang="en")
print(c.hex_str, (c.r, c.g, c.b)) # #FFDA3E (255, 218, 62)
# color -> text (any supported language)
print(lookup_name(sRGBAColor.from_hex_str("#1E90FF"), lang="pt")) # "Azul furtivo"
# nothing matches -> None
print(color_from_description("qzxwv", lang="en")) # None
Features
- Color extraction —
color_from_description("light blue", lang="fr")matches bundled color wordlists (web colors, xkcd survey, crayola, RAL, Pantone, ISCC-NBS, traditional Japanese colors, ...) and object colors ("carrot", "banana"), then applies modifiers such as light/dark, vivid/muted, warm/cool and transparent/opaque. Names are matched on word boundaries and weighted by specificity, so "moss green" outweighs a bare "green" and "green" is never matched inside "evergreen". - Color naming and namespaces —
lookup_name(color, lang)returns a color's name. Every wordlist is an addressable namespace, so you can ask for the name in a specific palette (namespace="RAL_classic") or fall back to the perceptually nearest named color (nearest=True). - Color models —
sRGBAColor,HLSColor,HSVColorandSpectralColor(wavelength) dataclasses with conversions, stable hex round-trips and validation.SpectralColor.is_visibleseparates real colors from infrared, ultraviolet and beyond. - Gamut handling — choose how a computed color that leaves the sRGB gamut is resolved: clamp per
channel, map towards grey while preserving hue, or reject (
gamut=GamutPolicy.MAP). - Utilities — perceptual color distance (CIEDE2000), linear-light color averaging, Kelvin color temperature to RGB, CMYK conversion, contrasting black/white text color and hex validation.
Use it anywhere
Every snippet below is plain Python — pip install ovos-color-parser and run it. Each has a
matching runnable script in examples/.
Extract colors from free text (NER)
Pull color references out of a sentence and resolve each to a structured color — no ML model, no network. Great for tagging product copy, design briefs or support tickets.
from ovos_color_parser import color_from_description
text = "Paint the fence dark forest green and the door navy blue"
for phrase in ("dark forest green", "navy blue"):
c = color_from_description(phrase, lang="en", fuzzy=False)
print(phrase, "->", c.hex_str) # dark forest green -> #162914 ; navy blue -> #0F43BE
Full sliding-window extractor with span offsets: examples/ner_colors.py.
Describe a color out loud (TTS-adjacent)
Go the other way: a raw RGB/hex value from a color picker, sensor or smart bulb becomes a speakable name.
from ovos_color_parser import sRGBAColor, lookup_name
c = sRGBAColor.from_hex_str("#2E8B57")
print(f"The color is {lookup_name(c, lang='en').lower()}.") # "The color is sea green."
Map descriptions to hex for UI, theming and LEDs
from ovos_color_parser import color_from_description
theme = {var: color_from_description(desc, lang="en").hex_str.lower()
for var, desc in {"--accent": "vivid teal", "--bg": "very dark blue"}.items()}
print(theme) # {'--accent': '#38bfc4', '--bg': '#121a34'}
CSS variables, NeoPixel/WLED tuples and Kelvin white-balance in examples/ui_theming.py.
In an OVOS skill vs. standalone
The same call powers a voice intent and a plain script — only the surrounding code differs:
# standalone color utility
from ovos_color_parser import color_from_description
hex_str = color_from_description("moss green", lang="en").hex_str
# inside an OVOS skill handler
def handle_set_color(self, message):
utterance = message.data["utterance"]
color = color_from_description(utterance, lang=self.lang)
if color:
self.set_lamp(color.hex_str)
Supported languages
23 locales: Aragonese, Arabic, Asturian, Basque, Bulgarian, Catalan, Croatian, Czech, Danish,
Dutch, English, French, German, Italian, Kabyle, Occitan, Polish, Portuguese, Romanian, Russian,
Slovak, Spanish and West Frisian. Any BCP-47 tag resolves to the closest bundled locale (for
example en-GB → en-US). The per-language feature matrix — entry counts, modifier and object
support — is in docs/languages.md.
Documentation
- Usage guide — extraction, impossible colors, comparing colors
- Color description semantics — how hue, saturation, brightness, temperature and opacity keywords map to color math
- Color, language and color spaces — how languages carve up color space, and the color models used
- API reference
- Language support — the 23 locales and their per-language vocabulary
- Extending — custom wordlists, adding a language, integration patterns
Runnable examples
- parse_colors.py — descriptions to colors, modifiers,
cast_to_palette - describe_rgb.py — RGB/hex to a spoken color name (TTS)
- ner_colors.py — extract color spans from free text (NER)
- ui_theming.py — descriptions to CSS/LED/Kelvin values
- multilingual.py — the same colors across all languages
- color_math.py — models, conversions, distance and averaging
Usage notes
Color names are ambiguous — the same name can map to several hex values across wordlists. When several entries match, the parser blends them in linear light, weighted by match specificity. To force a known, named color from the matched candidates instead:
color = color_from_description("red", lang="en", cast_to_palette=True)
print(color.name) # a named wordlist color, e.g. "Dusty Red"
When nothing matches, color_from_description returns None.
Descriptions of impossible colors ("reddish green") still produce an output — the parser blends whatever it matches, which may not be meaningful.
Runnable scripts live in examples/ and the full API reference in docs/api.md.
Related projects
- ovos-number-parser — numbers
- ovos-date-parser — dates and times
- ovos-lang-parser — languages
Credits
Color wordlists include data derived from the xkcd color survey, crayola, RAL, Pantone, ISCC-NBS, traditional Japanese colors and Wikipedia color lists. Spectral color terms follow Wikipedia's spectral color tables.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ovos_color_parser-0.11.0.tar.gz.
File metadata
- Download URL: ovos_color_parser-0.11.0.tar.gz
- Upload date:
- Size: 835.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0fbab47e272246886a82f85eecddd2642dd155f5cf499f9c3a16b685ba407803
|
|
| MD5 |
5393fe534b2bfb0e4349372fecd6fa6a
|
|
| BLAKE2b-256 |
91fcb52a27338e25bf0a0246f4d0363b398f7d9ac24c34cfff276ee34aa7b035
|
File details
Details for the file ovos_color_parser-0.11.0-py3-none-any.whl.
File metadata
- Download URL: ovos_color_parser-0.11.0-py3-none-any.whl
- Upload date:
- Size: 883.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4f0cf6e36e7fc5d3b98b260029e79fb707f81c0857ffc722d0228630ea72351e
|
|
| MD5 |
aef5d8130cff57980396e55bbc1a52b1
|
|
| BLAKE2b-256 |
dc5cc026fd7dd3521e92ca4ce7d04c57a050446c6e3b6489d931d9a0d8146b69
|