[英]Issues calculating HSP color model
[介绍]
HSP 颜色 model 是 2006 年创建的合成颜色 model。它使用与 HSV 相同的色相和饱和度值,但为了计算 P(感知亮度),它使用 [R, G, B] 的加权欧几里得范数向量。 更多信息: https://alienryderflex.com/hsp.html
如您所见,在网站的底部,有我为 Python 重新格式化后计算 RGB 和 HSP 的公式。
[问题]
在某些地方,我发现为了计算感知亮度,您需要首先线性化 RGB 通道(假设它是 sRGB),但如果您这样做,那么公式将不再有效。 出于这个原因,我没有这样做,而是直接将公式应用于输入的 RGB 颜色。 此外,我在一个 js 库中发现有人制作了它,因此感知亮度在 0-255 范围内。 我不知道他们从哪里得到这个想法,但它应该在 0-100(百分比)范围内。
[哪里出了问题]
我对从 RGB 到 HSP 的计算没有任何问题。 问题是从 HSP 计算 RGB 时。 我不会用完整的代码来打扰你,因为你可以从上面的链接中获取它,但我给你的是无法正常工作的部分片段(或者我有一个我找不到的错误)。
PS:经过进一步调查,事实证明不仅仅是这个片段给出了错误的结果!
elif H < 4 / 6: # B > G > R
H = 6 * (-H + 4 / 6)
B = (P ** 2 / (Pb + Pg * H ** 2)) ** 0.5
G = B * H
R = 0
这是饱和度为 100% 的部分。 问题是,当您将这些值 HSP(253, 100, 50) 或任何类似值传递给它时,生成的蓝色超出了可接受的范围(在本例中为 356)。 我尝试将值限制为 255,但是在进行 RGB 到 HSV 转换时,值不匹配,因此问题不存在。
有任何想法吗?
因此,我在我的代码中发现了一个错误,该错误将超出范围的值从 300+ 降低到最大值 261,这可以被限制在 255(对于 8 位颜色)而无需对另一个进行任何操作值。 不需要在黑色侧限制任何值。
这是我的带有注释的计算的简化版本:
def hsp_to_rgb(HSP: tuple | list, depth: int = 8, normalized: bool = False):
"""### Takes an HSP color and returns R, G, B values.
#### N/B: All examples below are given for 8-bit color depth that has range 0-255. \
If you want to use this function with a different depth the actual range is 0-(max value for bit depth).
### Args:
`color` (tuple | list): Either int in range 0-255 or float in range 0-1
`depth` (int): The bit depth of the input RGB values. Defaults to 8-bit (range 0-255)
`normalized` (bool, optional): Returns the values in range 0-1. Defaults to False.
Reference: http://alienryderflex.com/hsp.html
### Returns:
list[int, int, int] | list[float, float, float]: (H, S, P)
"""
H, S, P = HSP[0]/360, HSP[1]/100, HSP[2]/100
max_value = 2 ** depth - 1
def wrap(HSP: tuple | list, c1: float, c2: float, c3: float, S1: bool):
"""### This is an internal helper function for the hsp_to_rgb function to lift off some of the calculations.
c1, c2, c3 - Pr, Pg, Pb in different order
### Args:
`HSP` (tuple | list): Hue, Saturation, Perceived brightness in range 0-1
`c1` (float): Constant. Either 0.299, 0.587 or 0.114
`c2` (float): Constant. Either 0.299, 0.587 or 0.114
`c3` (float): Constant. Either 0.299, 0.587 or 0.114
`S1` (bool): Whether S (Saturation) is 1 (100%). Defaults to False
### Returns:
tuple[float, float, float]: R, G, B values in different order depending on the constants.
"""
if S1:
ch1 = (HSP[2] ** 2 / (c1 + c2 * HSP[0] ** 2)) ** 0.5
ch2 = ch1 * HSP[0]
ch3 = 0
return ch3, ch1, ch2
min_over_max = 1 - HSP[1]
part = 1 + HSP[0] * (1 / min_over_max - 1)
ch1 = HSP[2] / (c1 / min_over_max ** 2 + c2 * part ** 2 + c3) ** 0.5
ch2 = ch1 / min_over_max
ch3 = ch1 + HSP[0] * (ch2 - ch1)
return ch1, ch2, ch3
# Get weights constants
Pr, Pg, Pb = 0.299, 0.587, 0.114
# Calculate R, G, B based on the Hue
if H < 1 / 6: # R > G > B
H = 6 * H
B, R, G = wrap((H, S, P), Pr, Pg, Pb, S >= 1)
elif H < 2 / 6: # G > R > B
H = 6 * (-H + 2 / 6)
B, G, R = wrap((H, S, P), Pg, Pr, Pb, S >= 1)
elif H < 3 / 6: # G > B > R
H = 6 * (H - 2 / 6)
R, G, B = wrap((H, S, P), Pg, Pb, Pr, S >= 1)
elif H < 4 / 6: # B > G > R
H = 6 * (-H + 4 / 6)
R, B, G = wrap((H, S, P), Pb, Pg, Pr, S >= 1)
elif H < 5 / 6: # B > R > G
H = 6 * (H - 4 / 6)
G, B, R = wrap((H, S, P), Pb, Pr, Pg, S >= 1)
else: # R > B > G
H = 6 * (-H + 1)
G, R, B = wrap((H, S, P), Pr, Pb, Pg, S >= 1)
return [min(i, 1.0) for i in (R, G, B)] if normalized else [min(i*max_value, 255) for i in (R, G, B)]
这非常有效,转换非常准确。 请注意,为了获得完美的转换,您需要使用精确的浮点数进行计算。 否则,由于系统的限制,您将获得许多重叠的值。 前任。 RGB = 256 * 256 * 256 = 16 777 216 colors,而 HSP = 360 * 100 * 100 = 3 600 000 个独特的 colors。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.