在 L*a*b* 空间中线性插值会产生负 RGB 值? RGB 在 L*a*b* 中的嵌入是非凸的吗?

问题描述 投票:0回答:1

我尝试在 CIELAB 空间中的颜色之间进行线性插值,并在线性 RGB 空间中检索颜色。

我的工作流程如下:

  1. 采用线性 RGB 中的 2 种颜色,例如 (1,0,0) 和 (0,0,1)。
  2. 将它们转换为 XYZ 空间。我正在使用这个矩阵。这应该是带有 E-白点的 RGB 矩阵。
  3. 使用 公式将它们转换为 L*a*b* 维基百科。对于 Xn、Yn、Zn,我使用 RGB(1,1,1) 对应的 XYZ 坐标,对于该矩阵来说是 (1,1,1)。坐标因此被缩放,使得白点的 Y 为 1.0。
  4. 在这两者之间按分量线性插值 L*a*b* 元素。
  5. 通过反转将插值点转换为 RGB 上述过程(使用维基百科的逆变换,以及 XYZ->RGB 的逆矩阵。

问题是,这些中间颜色在我的 RGB 空间之外,尽管我显然是从其中的 2 种颜色开始的。具体来说:在 RGB(1,0,0) 和 RGB(0,0,1) 之间插值时,G 通道获得约 -0.058 的负值。

如果我使用原色和白点,即线性 sRGB 的矩阵,则会出现同样的问题。

这正常吗?在我看来,L*a*b* 颜色空间可能无法保证两个 RGB 可表示颜色之间的直线也在该可表示区域内,这似乎是合理的。如果不正常的话,错误可能出在哪里呢?如果正常的话应该怎么处理?

我的代码:

import numpy as np


mat = np.array([[0.49,0.31,0.2],[0.17697,0.81240,0.01063],[0.,0.01,0.99]])

def RGB_to_Lab(R,G,B):
    X,Y,Z = (mat@[[R],[G],[B]])[:,0]
    Xn, Yn, Zn = (mat@[[1],[1],[1]])[:,0]
    f = lambda t: t**(1/3) if t>(6/29)**3 else (1/3)*(29/6)**2*t+4/29
    L = 116*f(Y/Yn) - 16
    a = 500*(f(X/Xn)-f(Y/Yn))
    b = 200*(f(Y/Yn)-f(Z/Zn))
    return L, a, b

def Lab_to_RGB(L,a,b):
    f = lambda t:t**3 if t>6/29 else 3*(6/29)**2*(t-4/29)
    Xn, Yn, Zn = (mat@[[1],[1],[1]])[:,0]
    X = Xn*f((L+16)/116+a/500)
    Y = Yn*f((L+16)/116)
    Z = Zn*f((L+16)/116-b/200)
    R,G,B = (np.linalg.inv(mat)@[[X],[Y], [Z]])[:,0]
    return R,G,B


def steps(n):
    Lab = np.array(RGB_to_Lab(1,0,0))
    Lab2 = np.array(RGB_to_Lab(0,0,1))
    for i in range(n+1):
        r = i/n
        tmp = r*Lab2+(1-r)*Lab
        print(Lab_to_RGB(*tmp))
python colors rgb color-space cielab
1个回答
0
投票

CIE 实验室受到可见光谱的限制,即标准观察者对光的敏感度,因此在该空间中进行插值可能会生成负 RGB 值,因为实际上没有任何 RGB 颜色空间,例如sRGB,覆盖全部。

© www.soinside.com 2019 - 2024. All rights reserved.