rgb空间转换为luv颜色空间opencv
rgb空间转换为luv
rgb空间先要转换为xyz空间,然后再从xyz空间转换为Luv空间
对于标准RGB空间 转换为xyz空间公式
var_R = ( R / 255 ) //R from 0 to 255
var_G = ( G / 255 ) //G from 0 to 255
var_B = ( B / 255 ) //B from 0 to 255
if ( var_R > 0.04045 ) var_R = ( ( var_R + 0.055 ) / 1.055 ) ^ 2.4
else var_R = var_R / 12.92
if ( var_G > 0.04045 ) var_G = ( ( var_G + 0.055 ) / 1.055 ) ^ 2.4
else var_G = var_G / 12.92
if ( var_B > 0.04045 ) var_B = ( ( var_B + 0.055 ) / 1.055 ) ^ 2.4
else var_B = var_B / 12.92
var_R = var_R * 100
var_G = var_G * 100
var_B = var_B * 100
X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805
Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722
Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505
inline RGB2xyzFun(float &x)
{
if(x > 0.04045) x = pow((x + 0.055) / 1.055, 2.4); //pow()函数要包含#include <math.h>
else x = x / 12.92;
}
void RGB2xyz(const unsigned char * rgb, float * xyz)
{
float var_R = rgb[0] / 255.0;
float var_G = rgb[1] / 255.0;
float var_B = rgb[2] / 255.0;
RGB2xyzFun(var_R);
RGB2xyzFun(var_G);
RGB2xyzFun(var_B);
xyz[0] = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
xyz[1] = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
xyz[2] = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
}
xyz空间转换为Luv空间公式
var_U = ( 4 * X ) / ( X + ( 15 * Y ) + ( 3 * Z ) )
var_V = ( 9 * Y ) / ( X + ( 15 * Y ) + ( 3 * Z ) )
var_Y = Y / 100
if ( var_Y > 0.008856 ) var_Y = var_Y ^ ( 1/3 )
else var_Y = ( 7.787 * var_Y ) + ( 16 / 116 )
ref_X = 95.047 //Observer= 2°, Illuminant= D65
ref_Y = 100.000
ref_Z = 108.883
ref_U = ( 4 * ref_X ) / ( ref_X + ( 15 * ref_Y ) + ( 3 * ref_Z ) )
ref_V = ( 9 * ref_Y ) / ( ref_X + ( 15 * ref_Y ) + ( 3 * ref_Z ) )
CIE-L* = ( 116 * var_Y ) - 16
CIE-u* = 13 * CIE-L* * ( var_U - ref_U )
CIE-v* = 13 * CIE-L* * ( var_V - ref_V )
inline char xyz2LuvFun(float x, char min = -100, char max = 100)
{
if(x < min) return min;
if(x > max) return max;
return (char)x;
}
inline void xyz2Luv(const float *xyz, char * Luv)
{
float temp = 1.0f / (xyz[0] + (15.0f * xyz[1] + (3.0f * xyz[2])));
float var_U = (4.0f * xyz[0]) * temp;
float var_V = (9.0f * xyz[1]) * temp;
float var_Y = xyz[1];
if(var_Y > 0.008856) var_Y = pow(var_Y, 0.3333333333);
else var_Y = (7.787f * var_Y) + 0.13793103f;
static float ref_X = 0.95047f; //Observer= 2°, Illuminant= D65
static float ref_Y = 1.00000f;
static float ref_Z = 1.08883f;
static float ref_U = (4.0f * ref_X) / (ref_X + ( 15.0f * ref_Y ) + (3.0f * ref_Z));
static float ref_V = (9.0f * ref_Y) / (ref_X + ( 15.0f * ref_Y ) + (3.0f * ref_Z));
Luv[0] = xyz2LuvFun((116.0f * var_Y -16.0), 0);
Luv[1] = xyz2LuvFun(13.0f * Luv[0] * (var_U - ref_U));
Luv[2] = xyz2LuvFun(13.0f * Luv[0] * (var_V - ref_V));
}