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
HSV to RGB Color Conversion
提问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 colorsys
function.
如果你想要非标准化的 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_rgb
is 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)