使用 C++ 进行 LAB 转换
LAB conversion using C++
我正在使用此函数将图像的 RGB 颜色转换为 LAB space。我不明白第 13、14 和 15 行,因为它们使用了特定的符号 (>>) 和十六进制数:
void RGB2LAB(
const vector<uint> & ubuff,
vector<double>& lvec,
vector<double>& avec,
vector<double>& bvec)
{
int sz = int(ubuff.size());
lvec.resize(sz);
avec.resize(sz);
bvec.resize(sz);
for( int j = 0; j < sz; j++ )
{
int sR = (ubuff[j]>> 16) & 0xFF; //<----
int sG = (ubuff[j] >> 8) & 0xFF; //<----
int sB = (ubuff[j] ) & 0xFF; //<----
//------------------------
// sRGB to XYZ conversion
// (D65 illuminant assumption)
//------------------------
double R = sR/255.0;
double G = sG/255.0;
double B = sB/255.0;
double r, g, b;
if(R <= 0.04045) r = R/12.92;
else r = pow((R+0.055)/1.055,2.4);
if(G <= 0.04045) g = G/12.92;
else g = pow((G+0.055)/1.055,2.4);
if(B <= 0.04045) b = B/12.92;
else b = pow((B+0.055)/1.055,2.4);
double X = r*0.4124564 + g*0.3575761 + b*0.1804375;
double Y = r*0.2126729 + g*0.7151522 + b*0.0721750;
double Z = r*0.0193339 + g*0.1191920 + b*0.9503041;
//------------------------
// XYZ to LAB conversion
//------------------------
double epsilon = 0.008856; //actual CIE standard
double kappa = 903.3; //actual CIE standard
double Xr = 0.950456; //reference white
double Yr = 1.0; //reference white
double Zr = 1.088754; //reference white
double xr = X/Xr;
double yr = Y/Yr;
double zr = Z/Zr;
double fx, fy, fz;
if(xr > epsilon) fx = pow(xr, 1.0/3.0);
else fx = (kappa*xr + 16.0)/116.0;
if(yr > epsilon) fy = pow(yr, 1.0/3.0);
else fy = (kappa*yr + 16.0)/116.0;
if(zr > epsilon) fz = pow(zr, 1.0/3.0);
else fz = (kappa*zr + 16.0)/116.0;
lvec[j] = 116.0*fy-16.0;
avec[j] = 500.0*(fx-fy);
bvec[j] = 200.0*(fy-fz);
}
}
这些符号的真正含义和收益是什么?它们对于转换是强制性的吗?
让我们分解一下:
ubuff
是 uint
-s 的向量。每个 uint
由 32 位(可能是 64 位,但对于本解释而言并不重要)或 4 个字节组成。
因此,单个值,例如ubuff[j]
在内存中看起来像这样:
|-- Byte1 --|-- Byte2 --|-- Byte3 --|-- Byte4 --|
既然我们已经解决了这个问题,让我们来谈谈运算符 >>
。这就是右移运算符,它的作用是将内存中的位向右循环。例如:
ubuff[j] >> 8 // ==> |-- ByteX --|-- Byte1 --|-- Byte2 --|-- Byte3 --|
注意所有位是如何向右移动 8 个位置(正好是一个字节)。左边的新字节根据原来的最高有效位(left-most bit)用0或1填充。
现在我们来谈谈 &
运算符。它对位执行按位与运算。例如:
(ubuff[j] >> 8) & 0xFF // ==> |-- ByteX --|-- Byte1 --|-- Byte2 --|-- Byte3 --|
// AND |-- 0x00 --|-- 0x00 --|-- 0x00 --|-- 0xFF --|
// RES |-- 0x00 --|-- 0x00 --|-- 0x00 --|-- Byte3 --|
所以,我们实际上从原来的 ubuff[j]
中剩下 Byte3
。
其他表达式也一样:
int sR = (ubuff[j] >> 16) & 0xFF; // ==> Byte2
int sG = (ubuff[j] >> 8) & 0xFF; // ==> Byte3
int sB = (ubuff[j] ) & 0xFF; // ==> Byte4
我正在使用此函数将图像的 RGB 颜色转换为 LAB space。我不明白第 13、14 和 15 行,因为它们使用了特定的符号 (>>) 和十六进制数:
void RGB2LAB(
const vector<uint> & ubuff,
vector<double>& lvec,
vector<double>& avec,
vector<double>& bvec)
{
int sz = int(ubuff.size());
lvec.resize(sz);
avec.resize(sz);
bvec.resize(sz);
for( int j = 0; j < sz; j++ )
{
int sR = (ubuff[j]>> 16) & 0xFF; //<----
int sG = (ubuff[j] >> 8) & 0xFF; //<----
int sB = (ubuff[j] ) & 0xFF; //<----
//------------------------
// sRGB to XYZ conversion
// (D65 illuminant assumption)
//------------------------
double R = sR/255.0;
double G = sG/255.0;
double B = sB/255.0;
double r, g, b;
if(R <= 0.04045) r = R/12.92;
else r = pow((R+0.055)/1.055,2.4);
if(G <= 0.04045) g = G/12.92;
else g = pow((G+0.055)/1.055,2.4);
if(B <= 0.04045) b = B/12.92;
else b = pow((B+0.055)/1.055,2.4);
double X = r*0.4124564 + g*0.3575761 + b*0.1804375;
double Y = r*0.2126729 + g*0.7151522 + b*0.0721750;
double Z = r*0.0193339 + g*0.1191920 + b*0.9503041;
//------------------------
// XYZ to LAB conversion
//------------------------
double epsilon = 0.008856; //actual CIE standard
double kappa = 903.3; //actual CIE standard
double Xr = 0.950456; //reference white
double Yr = 1.0; //reference white
double Zr = 1.088754; //reference white
double xr = X/Xr;
double yr = Y/Yr;
double zr = Z/Zr;
double fx, fy, fz;
if(xr > epsilon) fx = pow(xr, 1.0/3.0);
else fx = (kappa*xr + 16.0)/116.0;
if(yr > epsilon) fy = pow(yr, 1.0/3.0);
else fy = (kappa*yr + 16.0)/116.0;
if(zr > epsilon) fz = pow(zr, 1.0/3.0);
else fz = (kappa*zr + 16.0)/116.0;
lvec[j] = 116.0*fy-16.0;
avec[j] = 500.0*(fx-fy);
bvec[j] = 200.0*(fy-fz);
}
}
这些符号的真正含义和收益是什么?它们对于转换是强制性的吗?
让我们分解一下:
ubuff
是 uint
-s 的向量。每个 uint
由 32 位(可能是 64 位,但对于本解释而言并不重要)或 4 个字节组成。
因此,单个值,例如ubuff[j]
在内存中看起来像这样:
|-- Byte1 --|-- Byte2 --|-- Byte3 --|-- Byte4 --|
既然我们已经解决了这个问题,让我们来谈谈运算符 >>
。这就是右移运算符,它的作用是将内存中的位向右循环。例如:
ubuff[j] >> 8 // ==> |-- ByteX --|-- Byte1 --|-- Byte2 --|-- Byte3 --|
注意所有位是如何向右移动 8 个位置(正好是一个字节)。左边的新字节根据原来的最高有效位(left-most bit)用0或1填充。
现在我们来谈谈 &
运算符。它对位执行按位与运算。例如:
(ubuff[j] >> 8) & 0xFF // ==> |-- ByteX --|-- Byte1 --|-- Byte2 --|-- Byte3 --|
// AND |-- 0x00 --|-- 0x00 --|-- 0x00 --|-- 0xFF --|
// RES |-- 0x00 --|-- 0x00 --|-- 0x00 --|-- Byte3 --|
所以,我们实际上从原来的 ubuff[j]
中剩下 Byte3
。
其他表达式也一样:
int sR = (ubuff[j] >> 16) & 0xFF; // ==> Byte2
int sG = (ubuff[j] >> 8) & 0xFF; // ==> Byte3
int sB = (ubuff[j] ) & 0xFF; // ==> Byte4