繁体   English   中英

计算 HSP 颜色的问题 model

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM