簡體   English   中英

在沒有OpenCV的情況下將BGR轉換為Lab

[英]convert BGR to Lab without OpenCV

在色彩空間上經驗很少的情況下,我使用以下代碼將BGR圖像(每個通道的范圍從0到255的無符號字符數組)轉換為實驗室色彩空間:

double F(double input) // function f(...), which is used for defining L, a and b changes within [4/29,1]
{
    if (input > 0.008856)
        return (pow(input, 0.333333333)); // maximum 1
    else
        return ((841/108)*input + 4/29);  //841/108 = 29*29/36*16
}

// RGB to XYZ
void RGBtoXYZ(uchar R, uchar G, uchar B, double &X, double &Y, double &Z)
{
    // RGB Working Space: sRGB 
    // Reference White: D65
    X = 0.412453*R + 0.357580*G + 0.189423*B; // maximum value = 0.959456 * 255 = 244.66128
    Y = 0.212671*R + 0.715160*G + 0.072169*B; // maximum value = 1 * 255 = 255
    Z = 0.019334*R + 0.119193*G + 0.950227*B; //  maximum value = 1.088754 * 255 = 277.63227
}

// XYZ to CIELab
void XYZtoLab(double X, double Y, double Z, double &L, double &a, double &b)
{
    const double Xo = 244.66128; // reference white
    const double Yo = 255.0;
    const double Zo = 277.63227;
    L = 116 * F(Y / Yo) - 16; // maximum L = 100
    a = 500 * (F(X / Xo) - F(Y / Yo)); // maximum 
    b = 200 * (F(Y / Yo) - F(Z / Zo));
}

// RGB to CIELab
void RGBtoLab(double R, double G, double B, double &L, double &a, double &b)
{
    double X, Y, Z;
    RGBtoXYZ(R, G, B, X, Y, Z);
    XYZtoLab(X, Y, Z, L, a, b);
}

我已使用以下代碼將生成的實驗室圖像重新轉換為BGR(使用cvtcolor)以使用OpenCV進行顯示(我不想使用OpenCV進行轉換,我只是使用它來顯示結果。基本上,我想要了解色彩空間轉換的工作原理):

// Lchannel, Achannel, Bchannel are arrays of type double
cv::Mat temp64bitL(height, width, CV_64FC1, Lchannel);
cv::Mat temp32bitL;
temp64bitL.convertTo(temp32bitL, CV_32F);

cv::Mat temp64bitA(height, width, CV_64FC1, Achannel);
cv::Mat temp32bitA;
temp64bitA.convertTo(temp32bitA, CV_32F);
cv::Mat temp64bitB(height, width, CV_64FC1, Bchannel);
cv::Mat temp32bitB;
temp64bitB.convertTo(temp32bitB, CV_32F);
    cv::Mat chan[3] = {
    temp32bitL, temp32bitA, temp32bitB
};
cv::Mat merged;
cv::merge(chan, 3, merged);
cv::Mat BGRImage;
cv::cvtColor(merged, BGRImage, CV_Lab2BGR, 3);

但是, 計算出的圖像 與原始圖像不同。 是由於代碼中的問題嗎?

您的代碼在double F(double input)有一個錯誤。 由於您具有整數除法,因此無法正常工作。 您可能願意將功能更改為類似於以下內容。 請注意double以使除法在浮點域中起作用,並使用cbrt而不是pow

#include <cmath>

double F(double input) // function f(...), which is used for defining L, a and b
                       // changes within [4/29,1]
{
  if (input > 0.008856)
    return std::cbrt(input); // maximum 1 --- prefer cbrt to pow for cubic root
  else
    return ((double(841) / 108) * input +
            double(4) / 29); // 841/108 = 29*29/36*16
}

然后,另一個問題可能是您用於XYZ空間的參考值。 我們有以下參考值,來自D65 / CIE-1931:

double Xo = 95.047;
double Yo = 100;
double Zo = 108.883;

然后,我們的RGBtoXYZ轉換工作如下:

template <class float_t> struct Convert<XYZ<float_t>> {
  template <class real_t> static XYZ<float_t> from(const RGB<real_t> &rhs) {
    // Assume RGB has the type invariance satisfied, i.e., channels \in [0,255]
    float_t var_R = float_t(rhs.comp1()) / 255;
    float_t var_G = float_t(rhs.comp2()) / 255;
    float_t var_B = float_t(rhs.comp3()) / 255;

    var_R = (var_R > 0.04045) ? std::pow((var_R + 0.055) / 1.055, 2.4)
                              : var_R / 12.92;
    var_G = (var_G > 0.04045) ? std::pow((var_G + 0.055) / 1.055, 2.4)
                              : var_G / 12.92;
    var_B = (var_B > 0.04045) ? std::pow((var_B + 0.055) / 1.055, 2.4)
                              : var_B / 12.92;

    var_R *= 100;
    var_G *= 100;
    var_B *= 100;

    return XYZ<float_t>{var_R * float_t(0.4124) + var_G * float_t(0.3576) +
                            var_B * float_t(0.1805),
                        var_R * float_t(0.2126) + var_G * float_t(0.7152) +
                            var_B * float_t(0.0722),
                        var_R * float_t(0.0193) + var_G * float_t(0.1192) +
                            var_B * float_t(0.9505)};
  }
};

如注釋中所述,假定RGB的通道在有效范圍內。 然后,除了cbrt和參考值更改外,我們擁有的XYZtoLAB函數相同。

編輯。 以上數字是從EasyRGB的“數學”頁面獲得 您可以在頁面上找到從sRGB到XYZ的轉換以及從XYZ到Lab的轉換,以及XYZ參考值表。 我們使用的是“日光,sRGB,Adobe RGB”的設置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM