web-dev-qa-db-fra.com

Conversion de couleurs HSV en RVB

Est-il possible de convertir les arguments de couleur HSV en arguments de couleur de type RVB à l'aide de modules pygame en python? J'ai essayé le code suivant, mais il retourne des valeurs ridicules.

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

et ce code retourne le non-sens suivant

(100, -9900.0, -9900.0)

Ce n'est évidemment pas RVB. Qu'est-ce que je fais mal?

12
AvZ

Cette fonction attend un nombre décimal pour s (saturation) et v (valeur), pas un pourcentage. Diviser par 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 vous souhaitez le tuple RVB non normalisé, voici une fonction pour envelopper la fonction colorsys.

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

Exemple de fonctionnalité

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

Si vous aimez les performances, évitez les importations et utilisez votre propre code optimisé.

Voici le code exact de colorsys légèrement modifié pour rendre le code d'octet légèrement plus rapide:

    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)

sortie:

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

Utiliser une chaîne if comme ci-dessus est en réalité plus rapide que d'utiliser Elif

Utiliser un wrapper, comme dans la réponse de Cyber, nécessite quelques étapes supplémentaires pour l'interprète.
Pour ajouter, la boucle for dans l'exemple de Cyber ​​est un véritable tueur de performance lorsqu'elle est utilisée comme ça

Si vous voulez légèrement plus de performances, procédez comme suit:
(Je ne dirai pas que c'est la meilleure performance possible, mais c'est certainement mieux)

    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)

^ ceci garantit la sortie de int () avec une plage de 255 (l'entrée est toujours la même)

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

CONSEIL: éloignez-vous autant que possible de tiers, essayez l'approche directe si vous le pouvez.
exculusions: extensions C compilées telles que PIL ou NumPy, ou wrappers ctypes tels que PyOpenGL (utilise la DLL)

13
Tcll

L'argument Hue devrait également varier de 0 à 1.

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

Si vous travaillez avec des tableaux Numpy, alors matplotlib.colors.hsv_to_rgb est assez 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)

Notez que les images d'entrée et de sortie ont des valeurs comprises dans la plage [0, 1].

2
buzjwa

J'ai préparé une version vectorisée, cca 10x plus rapide

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

J'ai trouvé le code suivant pour travailler avec des images représentées par numpy ndarrays:

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 dernière division était utile pour convertir en une représentation flottante comprise entre 0,0 et 1,0, car pour une raison quelconque, le dernier composant se situait à l’origine entre 0 et 255.

0
YakovK