繁体   English   中英

Lab颜色空间中的颜色梯度算法

[英]Color Gradient Algorithm in Lab color space

假设我在Lab颜色空间中有两种颜色 -

颜色1:L = 81,a = -8,b = 74
颜色2:L = 64,a = -14,b = 3

我想在它们之间生成n种颜色。 比方说n = 100或它们之间可能有多种颜色。

我知道RGB和HSV颜色渐变算法。 但我想在LAB颜色空间中生成渐变。 我不想将颜色转换为HSV或RGB,因为不同的颜色模型会生成不同的渐变。

这是我发现的一个链接,它在Lab和其他颜色模型中生成渐变: http//davidjohnstone.net/pages/lch-lab-colour-gradient-picker

我的目标是在Java中做类似的事情,但语言并不重要,我只需要理解它背后的逻辑和算法。

我这样做基本上是为了将扫描的颜色值与我拥有的5种颜色的图表相匹配。 因此,我必须先在这5种颜色之间生成所有颜色(使用渐变),然后比较另一种颜色以找到最接近它的颜色。 (比较我使用的是CIEDE2000 Delta-e方法)。 但我觉得这是次要的。


进一步补充我的问题的最后部分,

我想我必须生成一个渐变,因为我想在我的图表序列中找到我的样本中颜色的确切位置。

例如 - 我的图表中有6种颜色的绿色(浅色到深色),每种颜色对应于0到450毫克之间的特定数字数据(如下面的LAB值)

Color 1: 78, -10, -71 [0 mg]
Color 2: 73,-14,44 [30 mg]
Color 3: 71, -19, 53 [80 mg]
Color 4: 67, -18, 31 [160 mg]
Color 5: 69, -2, 29  [300 mg]
Color 6: 61, -14, 3 [450 mg]

现在我想在它们之间生成所有颜色并找到我扫描颜色的位置并返回mg值。 假设我的颜色正好在颜色1和颜色2之间,那么它将返回15毫克,否则如果它更接近颜色2它将返回28.5毫克,依此类推。

希望这能清除我想要实现的目标。

要在两个颜色值之间生成渐变,您可以在它们之间进行线性插值 这基本上可以在任何颜色空间中工作,但如果两个颜色空间之间的变换不是线性的,则通过在一个空间中线性插值获得的梯度在另一个空间中不是线性的。 因此,在Lab颜色空间中生成渐变就像在RGB空间中生成它们一样。

(对于HSV或HSL等颜色空间,其色调坐标“环绕”,可能需要特别注意选择正确的插值方向;幸运的是,你不是在这里询问这些颜色空间,所以我不喜欢我需要深入了解这些细节。)


就像演示一样,这里是如何在颜色c1c2之间生成n样本渐变(每个颜色都作为具有属性LabLabColor对象给出):

public static LabColor[] makeGradient(LabColor c1, LabColor c2, int n) {
    LabColor gradient = new LabColor[n];
    for (int i = 0; i < n; i++) {
        float alpha = (float)i / (n-1);  // 0.0 <= alpha <= 1.0 
        float L = (1-alpha) * c1.L + alpha * c2.L;
        float a = (1-alpha) * c1.a + alpha * c2.a;
        float b = (1-alpha) * c1.b + alpha * c2.b;
        gradient[i] = new LabColor(L, a, b);
    }
    return gradient;
}

这将返回一个带有n个颜色样本的渐变,其中第一个颜色等于c1 ,最后一个颜色等于c2 ,其余颜色在它们之间进行插值。


但是,根据您问题末尾的评论,我怀疑您实际上并不需要生成任何渐变。 相反,为了找到图表中与样本中的颜色最匹配的颜色,您只需要计算样本中每种图表颜色的感知距离 (在Lab颜色空间中,可以很好地近似它们的颜色)欧几里德距离)并选择最近的一个:

public static LabColor findNearest(LabColor sample, LabColor[] chart) {
    LabColor nearest = null;
    float minDistanceSquared = Float.POSITIVE_INFINITY;
    for (int i = 0; i < chart.length; i++) {
        float dL = sample.L - chart[i].L;
        float da = sample.a - chart[i].a;
        float db = sample.b - chart[i].b;
        float distanceSquared = dL*dL + da*da + db*db;
        if (distanceSquared < minDistanceSquared) {
            nearest = chart[i];
            minDistanceSquared = distanceSquared;
        }
    }
    return nearest;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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