本文主要是单纯分享代码,具体关于Lab色彩空间是怎么被设计出来的,相互转换公式是什么样的,这里就不做过多介绍了,相关文章很多。工作中用的比较多是yuv空间,Lab空间用的少,实际RGB与Lab转换还是挺复杂的,完全套公式的话,还是挺耗时的,因为中间还涉及到通过XYZ空间中转。下面代码并非本人逐行编写,我忘记是摘录自哪个开源工程了,不过在摘录过程中,我还是查了一些资料,也对照了opencv文档中提供的公式,做了一番去伪存真工作。下面是两个色彩空间转换代码:
const float param_13 = 1.0f / 3.0f;
const float param_16116 = 16.0f / 116.0f;
const float Xn = 0.950456f;
const float Yn = 1.0f;
const float Zn = 1.088754f;
void XYZ2RGB(float X, float Y, float Z, float *R, float *G, float *B)
{
float RR, GG, BB;
RR = 3.240479f * X - 1.537150f * Y - 0.498535f * Z;
GG = -0.969256f * X + 1.875992f * Y + 0.041556f * Z;
BB = 0.055648f * X - 0.204043f * Y + 1.057311f * Z;
*R = (float)CLAMP0255_XY(RR, 1.0f);
*G = (float)CLAMP0255_XY(GG, 1.0f);
*B = (float)CLAMP0255_XY(BB, 1.0f);
}
void Lab2XYZ(float L, float a, float b, float *X, float *Y, float *Z)
{
float fX, fY, fZ;
fY = (L + 16.0f) / 116.0f;
if (fY > 0.206893f)
*Y = fY * fY * fY;
else
*Y = (fY - param_16116) / 7.787f;
fX = a / 500.0f + fY;
if (fX > 0.206893f)
*X = fX * fX * fX;
else
*X = (fX - param_16116) / 7.787f;
fZ = fY - b / 200.0f;
if (fZ > 0.206893f)
*Z = fZ * fZ * fZ;
else
*Z = (fZ - param_16116) / 7.787f;
(*X) *= Xn;
(*Y) *= Yn;
(*Z) *= Zn;
}
void Lab2RGB(float L, float a, float b, float *R, float *G, float *B)
{
float X = 0.0f, Y = 0.0f, Z = 0.0f;
Lab2XYZ(L, a, b, &X, &Y, &Z);
XYZ2RGB(X, Y, Z, R, G, B);
}
void RGB2XYZ(float R, float G, float B, float *X, float *Y, float *Z)
{
*X = 0.412453f * R + 0.357580f * G + 0.180423f * B;
*Y = 0.212671f * R + 0.715160f * G + 0.072169f * B;
*Z = 0.019334f * R + 0.119193f * G + 0.950227f * B;
}
void XYZ2Lab(float X, float Y, float Z, float *L, float *a, float *b)
{
float fX, fY, fZ;
X /= Xn;
Y /= Yn;
Z /= Zn;
if (Y > 0.008856f)
fY = pow(Y, param_13);
else
fY = 7.787f * Y + param_16116;
*L = 116.0f * fY - 16.0f;
*L = *L > 0.0f ? *L : 0.0f;
if (X > 0.008856f)
fX = pow(X, param_13);
else
fX = 7.787f * X + param_16116;
if (Z > 0.008856)
fZ = pow(Z, param_13);
else
fZ = 7.787f * Z + param_16116;
*a = 500.0f * (fX - fY);
*b = 200.0f * (fY - fZ);
}
void RGB2Lab(float R, float G, float B, float *L, float *a, float *b)
{
float X = 0.0f, Y = 0.0f, Z = 0.0f;
RGB2XYZ(R, G, B, &X, &Y, &Z);
XYZ2Lab(X, Y, Z, L, a, b);
}
参考资料: