【问题标题】:HSV to RGB Color ConversionHSV 到 RGB 颜色转换
【发布时间】:2014-07-20 16:06:33
【问题描述】:

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

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

这段代码返回以下废话

(100, -9900.0, -9900.0)

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

【问题讨论】:

    标签: python colors pygame rgb hsv


    【解决方案1】:

    对于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)
    

    【讨论】:

    • 谢谢。是否有任何内置函数可以“非规范化”RGB 函数?
    • 我不知道开箱即用的功能,但您可以编写一个。请参阅我对此类功能的最新编辑。
    • Hue 参数也应该在 0-1 之间变化
    • 是的,要回应 Anand C U 和 Paul Beloff 所说的,您需要将色调除以 360,例如 125/360(以获得绿色)。否则你会经常变红。
    【解决方案2】:

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

    以下是 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 链实际上比使用 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)
    

    提示:尽可能远离第 3 方,尽可能尝试直接方法。
    排除:编译的 C 扩展,如 PIL 或 NumPy,或 ctypes 包装器,如 PyOpenGL(使用 DLL)

    【讨论】:

    • 那么...为什么我的评分被降级了?为什么没有评论告诉我我做错了什么,所以我可以改善自己??
    • 因为您的解决方案采用从 0 到 1 的色调值,但在您的示例中,您使用从 0 到 360 的值。
    • 如果我们谈论性能,我会远离列表并返回元组。
    • +Matteo Italia:长大一点后,我真的同意你的看法,如果有人(我正在打电话)想编辑这个答案以返回一个元组,请随意。跨度>
    【解决方案3】:

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

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

    【讨论】:

    • 优秀的评论,想知道为什么我总是变红!。
    【解决方案4】:

    我准备了一个矢量化的版本,它的速度是 cca 的 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,))
    

    【讨论】:

    • NameError: name 'ravel' is not defined 否则我会投票。
    • Ravel 是一个 numpy 函数。在代码前添加 from numpy import *。
    【解决方案5】:

    如果您使用的是 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] 范围内。

    【讨论】:

    • 谢谢,这为我节省了很多时间!
    【解决方案6】:

    由于问题被标记为,我想提一下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()
    

    【讨论】:

      【解决方案7】:

      我发现以下代码可以处理表示为 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 之间。

      【讨论】:

        【解决方案8】:

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

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

        【讨论】:

          【解决方案9】:

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

          【讨论】:

            猜你喜欢
            • 2012-11-02
            • 2018-12-14
            • 2010-09-26
            • 2015-05-30
            • 1970-01-01
            • 2012-01-13
            • 1970-01-01
            相关资源
            最近更新 更多