HSV to RGB Color Conversion
Solution 1
That function expects decimal for s
(saturation) and v
(value), not percent. Divide by 100.
>>> import colorsys
# Using percent, incorrect
>>> test_color = colorsys.hsv_to_rgb(359,100,100)
>>> test_color
(100, -9900.0, -9900.0)
# Using decimal, correct
>>> test_color = colorsys.hsv_to_rgb(1,1,1)
>>> test_color
(1, 0.0, 0.0)
If you would like the non-normalized RGB tuple, here is a function to wrap the colorsys
function.
def hsv2rgb(h,s,v):
return tuple(round(i * 255) for i in colorsys.hsv_to_rgb(h,s,v))
Example functionality
>>> hsv2rgb(0.5,0.5,0.5)
(64, 128, 128)
Solution 2
If you like performance, it's best to avoid imports and use your own optimized code
Here's the exact code from colorsys slightly modified to make the byte-code slightly faster:
def hsv_to_rgb(h, s, v):
if s == 0.0: return (v, v, v)
i = int(h*6.) # XXX assume int() truncates!
f = (h*6.)-i; p,q,t = v*(1.-s), v*(1.-s*f), v*(1.-s*(1.-f)); i%=6
if i == 0: return (v, t, p)
if i == 1: return (q, v, p)
if i == 2: return (p, v, t)
if i == 3: return (p, q, v)
if i == 4: return (t, p, v)
if i == 5: return (v, p, q)
output:
>>> hsv_to_rgb(359,1,1)
[1, 0.0, 0.0]
Using an if-chain like above is actually faster than using elif
Using a wrapper, like in Cyber's answer, takes a few extra steps for the interpreter to perform.
To add, the for loop in Cyber's example is a real performance killer when used like that
If you want slightly more performance, simply do this:
(I won't say this is the best possible performance, but it's certainly better)
def hsv_to_rgb(h, s, v):
if s == 0.0: v*=255; return (v, v, v)
i = int(h*6.) # XXX assume int() truncates!
f = (h*6.)-i; p,q,t = int(255*(v*(1.-s))), int(255*(v*(1.-s*f))), int(255*(v*(1.-s*(1.-f)))); v*=255; i%=6
if i == 0: return (v, t, p)
if i == 1: return (q, v, p)
if i == 2: return (p, v, t)
if i == 3: return (p, q, v)
if i == 4: return (t, p, v)
if i == 5: return (v, p, q)
^ this guarantees int() output with a range of 255 (the input is still the same)
>>> hsv_to_rgb(359./360.,1,1)
(255, 0, 0)
TIP: stay away from 3rd-party where possible, try the direct approach if you can.
exculusions: compiled C extensions such as PIL or NumPy, or ctypes wrappers such as PyOpenGL (uses the DLL)
Solution 3
The Hue argument should also vary from 0-1.
import colorsys
test_color = colorsys.hsv_to_rgb(359/360.0, 1, 1)
Solution 4
I have prepared a vectorized version, it is cca 10x faster
def hsv_to_rgb(h, s, v):
shape = h.shape
i = int_(h*6.)
f = h*6.-i
q = f
t = 1.-f
i = ravel(i)
f = ravel(f)
i%=6
t = ravel(t)
q = ravel(q)
clist = (1-s*vstack([zeros_like(f),ones_like(f),q,t]))*v
#0:v 1:p 2:q 3:t
order = array([[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]])
rgb = clist[order[i], arange(prod(shape))[:,None]]
return rgb.reshape(shape+(3,))
Solution 5
If you are working with Numpy arrays then matplotlib.colors.hsv_to_rgb
is quite direct:
import numpy as np
from matplotlib.colors import hsv_to_rgb
# This will create a nice image of varying hue and value
hsv = np.zeros((512, 512, 3))
hsv[..., 0] = np.linspace(0, 1, 512)
hsv[..., 1] = 1.
hsv[..., 2] = np.linspace(0, 1, 512)[:, np.newaxis]
rgb = hsv_to_rgb(hsv)
Note that the input and output images have values in the range [0, 1].
AvZ
Bash has all the answers avz@PC-Linux:~$ whatis love love: nothing appropriate. Mathematics and Physics are my favourite subjects. I also like to code a little here and then (In C++, Python, or Javascript usually). I log on to Mathematics SE whenever I can to find nice problems to solve. Got first rank change for 1st Quarter 2015 quarter for Mathematics SE! Can't believe it!
Updated on July 09, 2022Comments
-
AvZ almost 2 years
Is there a way to convert HSV color arguments to RGB type color arguments using pygame modules in python? I tried the following code, but it returns ridiculous values.
import colorsys test_color = colorsys.hsv_to_rgb(359, 100, 100) print(test_color)
and this code returns the following nonsense
(100, -9900.0, -9900.0)
This obviously isn't RGB. What am I doing wrong?
-
AvZ almost 10 yearsThanks. Is there any built in function to "denormalise" the RGB function?
-
Cory Kramer almost 10 yearsI don't know about an out-of-the-box function, but you could write one. Please see my latest edit for such a function.
-
Tcll over 9 yearsso... why am I down-rated?? why is there no comment telling me what I did wrong so I can better myself??
-
sfat over 7 yearsbecause your solution takes hue values from 0 to 1, but in your examples you use values from 0 to 360.
-
Matteo Italia almost 7 yearsIf we are talking about performance, I would stay away from lists and return tuples instead.
-
Tcll almost 7 years+Matteo Italia: after growing up a bit, I actually agree with you, if anyone (I'm on a phone) would like to edit this answer to return a tuple, feel free.
-
Tcll almost 7 years
NameError: name 'ravel' is not defined
or I would upvote. -
Tomáš Odstrčil almost 7 yearsRavel is a numpy function. Add from numpy import * before the code.
-
Anand C U over 6 yearsThe Hue argument should also vary from 0-1
-
aheigins about 6 yearsexcellent comment, was wondering why i was constantly getting red!.
-
aheigins about 6 yearsYep to echo what Anand C U and Paul Beloff have said you need to divide your Hue by 360 for example 125/360 (to get green). Otherwise you constantly get red.
-
Anshul Rai about 6 yearsThank you, this saved me a lot of time!
-
TimH about 2 yearsAs @sfat mentioned... note that the first function in this answer assumes all
hsv
andrgb
values are floats from 0 to 1 (seecolorsys
docs). The example given ofhsv_to_rgb(359,1,1)
is misleading. I'm saying this here because I assumed this mistake had been fixed with the 2017 edit of this answer (and therefore disregarded sfat's comment), but the error remains.