簡體   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