Conversión de color HSV a RGB

¿Hay una manera de convertir los argumentos de color HSV a los argumentos de color de tipo RGB usando módulos de pygame en python? Probé el siguiente código, pero devuelve valores ridículos.

import colorsys test_color = colorsys.hsv_to_rgb(359, 100, 100) print(test_color) 

y este código devuelve el siguiente disparate

 (100, -9900.0, -9900.0) 

Esto obviamente no es RGB. ¿Qué estoy haciendo mal?

Esa función espera decimal para s (saturación) v (valor), no para porcentajes. Divide por 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) 

Si desea la tupla RGB no normalizada, aquí hay una función para envolver la función colorsys .

 def hsv2rgb(h,s,v): return tuple(round(i * 255) for i in colorsys.hsv_to_rgb(h,s,v)) 

Ejemplo de funcionalidad

 >>> hsv2rgb(0.5,0.5,0.5) (64, 128, 128) 

Si le gusta el rendimiento, es mejor evitar las importaciones y usar su propio código optimizado

Aquí está el código exacto de colorsys ligeramente modificado para hacer que el código de bytes sea un poco más rápido:

  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) 

salida:

 >>> hsv_to_rgb(359,1,1) [1, 0.0, 0.0] 

Usar un if-chain como el de arriba es realmente más rápido que usar elif

Usar una envoltura, como en la respuesta de Cyber, toma algunos pasos adicionales para que el intérprete realice.
Para agregar, el bucle for en el ejemplo de Cyber ​​es un verdadero asesino de rendimiento cuando se usa así

Si quieres un poco más de rendimiento, simplemente haz esto:
(No diré que este es el mejor rendimiento posible, pero ciertamente es mejor)

  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) 

^ Esto garantiza una salida int () con un rango de 255 (la entrada sigue siendo la misma)

 >>> hsv_to_rgb(359./360.,1,1) (255, 0, 0) 

CONSEJO: manténgase alejado de terceros cuando sea posible, intente el enfoque directo si puede.
exculusions: extensiones de C comstackdas como PIL o NumPy, o envolturas de ctypes como PyOpenGL (usa la DLL)

El argumento de Hue también debe variar de 0-1.

 import colorsys test_color = colorsys.hsv_to_rgb(359/360.0, 1, 1) 

Si está trabajando con matrices matplotlib.colors.hsv_to_rgb , matplotlib.colors.hsv_to_rgb es bastante directo:

 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) 

Tenga en cuenta que las imágenes de entrada y salida tienen valores en el rango [0, 1].

He preparado una versión vectorizada, es cca 10 veces más rápida.

 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,)) 

Encontré el siguiente código para trabajar con imágenes representadas como ndarrays numpy:

 from skimage.io import imread import matplotlib.colors as mcolors img = imread( 'my_image.png' ) img_hsv = mcolors.rgb_to_hsv( img ) img_hsv = img_hsv / (1.0, 1.0, 255.0) 

La última división fue útil para convertir a una representación flotante entre 0.0 y 1.0, ya que por alguna razón el último componente originalmente osciló entre 0 y 255.