HSV到RGB颜色转换

时间:2014-07-20 16:06:34

标签: python colors pygame rgb hsv

有没有办法在python中使用pygame模块将HSV颜色参数转换为RGB类型颜色参数?我尝试了以下代码,但它返回了荒谬的值。

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

并且此代码返回以下废话

(100, -9900.0, -9900.0)

这显然不是RGB。我做错了什么?

9 个答案:

答案 0 :(得分:21)

该函数需要s(饱和度)和v(值)的小数,而不是百分比。除以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)

如果你想要非规范化的RGB元组,这里是一个包装colorsys函数的函数。

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

示例功能

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

答案 1 :(得分:13)

如果您喜欢性能,最好避免导入并使用您自己的优化代码

这里是来自colorsys的确切代码稍加修改,以使字节代码稍微快一点:

    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)

输出:

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

使用上面的if-chain实际上比使用elif

更快

使用包装器,就像在Cyber​​的答案中一样,需要一些额外的步骤让口译员执行。
要添加,Cyber​​的示例中的for循环在使用时就是一个真正的性能杀手

如果您想要稍微提高性能,只需执行以下操作:
(我不会说这是最好的表现,但它肯定更好)

    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)

^这保证int()输出的范围为255(输入仍然相同)

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

提示:尽可能远离第三方,如果可以,请尝试直接接近。
exculus:编译的C扩展,如PIL或NumPy,或ctypes包装,如PyOpenGL(使用DLL)

答案 2 :(得分:6)

Hue参数也应该在0-1之间变化。

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

答案 3 :(得分:2)

如果您正在使用Numpy阵列,那么matplotlib.colors.hsv_to_rgb非常直接:

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)

请注意,输入和输出图像的值在[0,1]范围内。

答案 4 :(得分:1)

我准备了一个矢量化版本,它的速度提高了10倍

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

答案 5 :(得分:0)

我发现以下代码可用于表示为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)

最后一个除法可用于转换为0.0到1.0之间的浮动表示形式,因为某些原因,最后一个分量最初在0到255之间。

答案 6 :(得分:0)

OpenCV也提供了这种可能性。注意,R和B通道是反向的,即BGR。因此,请使用最适合您需求的功能:

import cv2

rgbimg = cv2.cvtColor(hsvimg, cv2.COLOR_HSV2RGB)
bgrimg = cv2.cvtColor(hsvimg, cv2.COLOR_HSV2BGR)

答案 7 :(得分:0)

由于问题被标记为,因此我想提到PyGame允许在配色方案之间进行转换。 pygame.Color对象可用于在RGB和HSL/HSV配色方案之间进行转换。

hsva属性:

获取或设置颜色的HSVA表示形式。 HSVA分量的范围为H = [0,360],S = [0,100],V = [0,100],A = [0,100]。

hsva = pygame.Color((red, green, blue, alpha)).hsva
color = pygame.Color(0)
color.hsva = (hue, saturation, value, alpha)
rgba = (color.r, color.g, color.b, color.a)

hsla属性:

获取或设置颜色的HSLA表示形式。 HSLA分量的范围为H = [0,360],S = [0,100],V = [0,100],A = [0,100]。

hsla = pygame.Color((red, green, blue, alpha)).hsla
color = pygame.Color(0)
color.hsla = (hue, saturation, lightness, alpha)
rgba = (color.r, color.g, color.b, color.a)

最小示例:

import pygame

pygame.init()

window = pygame.display.set_mode((450, 300))
clock = pygame.time.Clock()

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    window.fill((255, 255, 255))
    w, h = window.get_size()
    for i in range(6):
        color = pygame.Color(0)
        color.hsla = (i * 60, 100, 50, 100)
        pygame.draw.circle(window, color, 
            (w//6 + w//3 * (i%3), h//4 + h//2 * (i//3)), 
            round(min(window.get_width() * 0.16, window.get_height() * 0.2)))

    pygame.display.flip()

pygame.quit()
exit()

答案 8 :(得分:0)

在opencv中,使用其任何颜色转换。请注意,BGR和RGB在cv2区域中被翻转。

def convertColor(hsv, conversion):
    return tuple(int(i) for i in cv2.cvtColor(np.uint8([[hsv]]), conversion).flatten())

用法:

hsvColor = (0,255,255) #bright red
bgrColor = convertColor(hsvColor, cv2.COLOR_HSV2BGR)