在 Python 中将 hsl 转换为 hsv 颜色代码,反之亦然

Convert hsl to hsv color codes and vice versa in Python

我目前正尝试在 Python 中将 hsl 颜色代码转换为 hsv,反之亦然,但找不到简单的方法来完成此操作。

我尝试使用 colorsys 包将 hsl 转换为 rgb 并将 rgb 转换为 hsv 来间接转换代码。不幸的是,由于某种原因这似乎不起作用。我总是得到非常小的值(< 0,所以这没有任何意义)。

这是我所做的:

import colorsys

def hsv_to_hsl(hsv):
    h, s, v = hsv
    rgb = colorsys.hsv_to_rgb(h, s, v)
    r, g, b = rgb
    hls = colorsys.rgb_to_hls(r, g, b)
    return hls

hsv = (300, 65, 40)

print(hsv)
print(hsv_to_hsl(hsv))

我也尝试根据我在 GitHub 上找到的 JavaScript 函数编写自己的函数,但我在那里得到了相同的奇怪值(请参阅下面的将 hsv 转换为 hsl 的代码)。问题是我并没有真正了解维基百科上的公式,所以老实说,我什至不知道我在下面计算的内容是否有意义。

import math

def hsv_to_hsl(hsv):
    h, sat, val = hsv
    
    # hue h stays the same
    
    # saturation s
    if (2-sat)*val < 1:
        s = sat*val / ((2-sat)*val)
    else: s = sat*val / (2-(2-sat)*val)

    # lightness l
    l = 2-sat * val/2 
    
    # return code as tuple
    return (h, s, l)

是否有一种简单的方法可以使用包来完成此操作,或者您是否知道我可以在我的函数中做些什么不同的事情?

您可以查看 colorsys 模块:

https://docs.python.org/3.7/library/colorsys.html

网站示例:

colorsys.rgb_to_yiq(r, g, b)
#Convert the color from RGB coordinates to YIQ coordinates.

colorsys.yiq_to_rgb(y, i, q)
#Convert the color from YIQ coordinates to RGB coordinates.

colorsys.rgb_to_hls(r, g, b)
#Convert the color from RGB coordinates to HLS coordinates.

colorsys.hls_to_rgb(h, l, s)
#Convert the color from HLS coordinates to RGB coordinates.

colorsys.rgb_to_hsv(r, g, b)
#Convert the color from RGB coordinates to HSV coordinates.

colorsys.hsv_to_rgb(h, s, v)
#Convert the color from HSV coordinates to RGB coordinates.

据此,您可以转换 hls -> rgb -> hsv

您需要确保根据匹配范围对值进行归一化。根据您的值(并且 this website), it seems you're using values of H in the range [0, 360] ; S and V in the range [0, 100]. On the other hand, the built-in library colorsys 中的范围提示使用所有 [0, 1] 范围。因此,一些规范化将为您提供所需的结果:

import colorsys

def hsv_to_hsl(hsv):
    h, s, v = hsv
    rgb = colorsys.hsv_to_rgb(h/360, s/100, v/100)
    r, g, b = rgb
    h, l, s = colorsys.rgb_to_hls(r, g, b)
    return h*360, s*100, l*100

hsv = (300, 65, 40)

print(hsv)
print(hsv_to_hsl(hsv))

现在给出预期:

(300, 65, 40)
(300.0, 48.148148148148145, 27.0)

如果您正在寻找手动实施,您可以使用 here 中描述的算法(现在的值是:H 在 [0, 360] 范围内,S、V 和 L 在 [0, 1]):

def hsv_to_hsl(hsv):
    h, s, v = hsv
    l = v * (1 - s/2)
    s = 0 if l in (0, 1) else (v - l)/min(l, 1-l)
    return h, s, l

def hsl_to_hsv(hsl):
    h, s, l = hsl
    v = l + s * min(l, 1-l)
    s = 0 if v == 0 else 2*(1 - l/v)
    return h, s, v

colorsys比较结果:

h, s, l = (300, 48.148, 27)

custom = hsl_to_hsv((h, s/100, l/100))
print("Custom function: ", custom[0], custom[1]*100, custom[2]*100)
expected = colorsys.rgb_to_hsv(*colorsys.hls_to_rgb(h/360, l/100, s/100))
print("Expected result: ", expected[0]*360, expected[1]*100, expected[2]*100)

确实给出了:

Custom function:  300 64.99986499986498 39.99996
Expected result:  300.0 64.999864999865 39.99996

不是本地 Python 编码员所以这很简单,但基于 formula on Wikipedia and returns accurate values according to colorizer.org:

def hsl_to_hsv(hsl):
    hue,sat,lum = hsl
    if hue < 0 or hue > 360 or sat < 0 or sat > 1 or lum < 0 or lum > 1:
        exit

    h = hue
    v = lum + sat * min(lum, 1 - lum)
    if v == 0:
        s = 0
    else:
        s = 2 * (1 - lum / v)

    return h,s,v

def hsv_to_hsl(hsv):
    hue,sat,val = hsv
    if hue < 0 or hue > 360 or sat < 0 or sat > 1 or val < 0 or val > 1:
        exit

    h = hue
    l = val * (1 - sat / 2)
    if l == 0 or l == 1:
        s = 0
    else:
        s = (val - l) / min(l, 1 - l)

    return h,s,l

print (hsl_to_hsv((36.9,0.5118,0.751)))
print (hsv_to_hsl((36.9,0.2902,0.8784)))

输出:

(36.9, 0.29014721809684496, 0.8784382)
(36.9, 0.5117560784762163, 0.75094416)

请注意,色调是一个浮点数,取值范围为 0 到 360,其他值是取值范围为 0 到 1 的浮点数,通常以百分比表示。您使用 colorsys 库的问题可能是您传递了更大的值,例如 29 而不是 0.29