简体   繁体   English

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

[英]Color Gradient Algorithm in Lab color space

Let's say I have two colors in Lab color space- 假设我在Lab颜色空间中有两种颜色 -

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

I want generate n colors between them. 我想在它们之间生成n种颜色。 For say n=100 or as many colors possible between them. 比方说n = 100或它们之间可能有多种颜色。

I know the RGB and HSV color gradient algorithm. 我知道RGB和HSV颜色渐变算法。 But I want to generate gradient in LAB color spaces. 但我想在LAB颜色空间中生成渐变。 I don't want to convert the colors to HSV or RGB as different color models generate different gradients. 我不想将颜色转换为HSV或RGB,因为不同的颜色模型会生成不同的渐变。

This is a link i found which generates gradient in Lab and other color models: http://davidjohnstone.net/pages/lch-lab-colour-gradient-picker 这是我发现的一个链接,它在Lab和其他颜色模型中生成渐变: http//davidjohnstone.net/pages/lch-lab-colour-gradient-picker

I'm aiming to do something similar in Java but language doesn't matter, I just need to understand the logic and algorithm behind it. 我的目标是在Java中做类似的事情,但语言并不重要,我只需要理解它背后的逻辑和算法。

I'm doing this basically for matching a scanned color value with a chart of 5 colors I have. 我这样做基本上是为了将扫描的颜色值与我拥有的5种颜色的图表相匹配。 So, I have to first generate all colors in between those 5 colors (using gradient) and compare the other color to find the one which is closest to it. 因此,我必须先在这5种颜色之间生成所有颜色(使用渐变),然后比较另一种颜色以找到最接近它的颜色。 (For comparing I'm using CIEDE2000 Delta-e method). (比较我使用的是CIEDE2000 Delta-e方法)。 But that's secondary i guess. 但我觉得这是次要的。


Adding further to the last part of my question, 进一步补充我的问题的最后部分,

I suppose I'll have to generate a gradient because I want to find the exact location of the color from my sample in the sequence of chart I have. 我想我必须生成一个渐变,因为我想在我的图表序列中找到我的样本中颜色的确切位置。

For eg- I have 6 colors of green shades (light to dark) in my chart each corresponding to particular numeric data between 0 to 450 mg like below (with their LAB values) 例如 - 我的图表中有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]

Now I want to generate all colors between them and find the location of my scanned color and return the mg value. 现在我想在它们之间生成所有颜色并找到我扫描颜色的位置并返回mg值。 Say my color is exactly between Color 1 and Color 2, then it'll return 15 mg, otherwise if it is closer to Color 2 it'll return 28.5 mg and so on. 假设我的颜色正好在颜色1和颜色2之间,那么它将返回15毫克,否则如果它更接近颜色2它将返回28.5毫克,依此类推。

Hope this clears up what I'm trying to achieve. 希望这能清除我想要实现的目标。

To generate a gradient between two color values, you can just linearly interpolate between them. 要在两个颜色值之间生成渐变,您可以在它们之间进行线性插值 This will basically work in any color space, although if the transformation between two color spaces is not linear, the gradient obtained by linearly interpolating in one space will not be linear in the other. 这基本上可以在任何颜色空间中工作,但如果两个颜色空间之间的变换不是线性的,则通过在一个空间中线性插值获得的梯度在另一个空间中不是线性的。 Thus, generating gradients in Lab color space is exactly like generating them in, say, RGB space. 因此,在Lab颜色空间中生成渐变就像在RGB空间中生成它们一样。

(For color spaces like HSV or HSL which have a hue coordinate that "loops around", some extra care may be needed to choose the right direction to interpolate in; fortunately, you're not asking about those color spaces here, so I don't need to go into such details.) (对于HSV或HSL等颜色空间,其色调坐标“环绕”,可能需要特别注意选择正确的插值方向;幸运的是,你不是在这里询问这些颜色空间,所以我不喜欢我需要深入了解这些细节。)


Just as a demonstration, here's how you'd generate an n -sample gradient between the colors c1 and c2 (each given as a LabColor object with properties L , a and b ): 就像演示一样,这里是如何在颜色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;
}

This will return a gradient with n color samples, where the first color is equal to c1 , the last color is equal to c2 , and the rest are interpolated between them. 这将返回一个带有n个颜色样本的渐变,其中第一个颜色等于c1 ,最后一个颜色等于c2 ,其余颜色在它们之间进行插值。


However, based on the remark at the end of your question, I suspect you don't actually need to generate any gradients. 但是,根据您问题末尾的评论,我怀疑您实际上并不需要生成任何渐变。 Rather, to find the color in your chart that most closely matches the one in your sample, you just need to calculate the perceptual distance of each chart color from the sample (which, in the Lab color space, can be well approximated simply by their Euclidian distance) and select the closest one: 相反,为了找到图表中与样本中的颜色最匹配的颜色,您只需要计算样本中每种图表颜色的感知距离 (在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