Python HSV 到 RGB 颜色转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24852345/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 05:20:32  来源:igfitidea点击:

HSV to RGB Color Conversion

pythoncolorspygamergbhsv

提问by AvZ

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.

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

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?

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

采纳答案by Cory Kramer

That function expects decimal for s(saturation) and v(value), not percent. Divide by 100.

该函数需要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)

If you would like the non-normalized RGB tuple, here is a function to wrap the colorsysfunction.

如果你想要非标准化的 RGB 元组,这里有一个函数来包装colorsys函数。

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)

回答by Tcll

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:

这是 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)

output:

输出:

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

Using an if-chain like above is actually faster than using elif

使用上面的 if-chain 实际上比使用 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

使用包装器,就像在 Cyber​​ 的回答中一样,解释器需要执行一些额外的步骤。
另外,Cyber​​ 示例中的 for 循环在这样使用时是一个真正的性能杀手

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)

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

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

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

回答by Tomas

I have prepared a vectorized version, it is cca 10x faster

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

回答by Paul Beloff

The Hue argument should also vary from 0-1.

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

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

回答by buzjwa

If you are working with Numpy arrays then matplotlib.colors.hsv_to_rgbis quite direct:

如果您正在使用 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)

Note that the input and output images have values in the range [0, 1].

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

回答by YakovK

I found the following code to work with images represented as numpy ndarrays:

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

The last division was useful to convert to a floating representation between 0.0 and 1.0, as for some reason the last component originally ranged between 0 and 255.

最后一个除法对于转换为 0.0 和 1.0 之间的浮动表示很有用,因为出于某种原因,最后一个分量最初的范围在 0 到 255 之间。

回答by Gabriel123

OpenCV also offers this possibility. Note that R and B channels are inverted, i.e. BGR. So uses the function that best fits your needs:

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

import cv2

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