mirror of
https://github.com/opencv/opencv.git
synced 2024-11-29 05:29:54 +08:00
fixed bug in cvtColor RGB(BGR) <-> Lab conversion
This commit is contained in:
parent
f9ac5e2404
commit
5f9aedbe01
@ -1344,6 +1344,9 @@ struct RGB2Lab_b
|
||||
};
|
||||
|
||||
|
||||
#define clip(value) \
|
||||
value < 0.0f ? 0.0f : value > 1.0f ? 1.0f : value;
|
||||
|
||||
struct RGB2Lab_f
|
||||
{
|
||||
typedef float channel_type;
|
||||
@ -1355,17 +1358,22 @@ struct RGB2Lab_f
|
||||
volatile int _3 = 3;
|
||||
initLabTabs();
|
||||
|
||||
if(!_coeffs) _coeffs = sRGB2XYZ_D65;
|
||||
if(!_whitept) _whitept = D65;
|
||||
float scale[] = { LabCbrtTabScale/_whitept[0], LabCbrtTabScale, LabCbrtTabScale/_whitept[2] };
|
||||
if (!_coeffs)
|
||||
_coeffs = sRGB2XYZ_D65;
|
||||
if (!_whitept)
|
||||
_whitept = D65;
|
||||
|
||||
float scale[] = { 1.0f / _whitept[0], 1.0f, 1.0f / _whitept[2] };
|
||||
|
||||
for( int i = 0; i < _3; i++ )
|
||||
{
|
||||
coeffs[i*3+(blueIdx^2)] = _coeffs[i*3]*scale[i];
|
||||
coeffs[i*3+1] = _coeffs[i*3+1]*scale[i];
|
||||
coeffs[i*3+blueIdx] = _coeffs[i*3+2]*scale[i];
|
||||
CV_Assert( coeffs[i*3] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
|
||||
coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 1.5f*LabCbrtTabScale );
|
||||
int j = i * 3;
|
||||
coeffs[j + (blueIdx ^ 2)] = _coeffs[j] * scale[i];
|
||||
coeffs[j + 1] = _coeffs[j + 1] * scale[i];
|
||||
coeffs[j + blueIdx] = _coeffs[j + 2] * scale[i];
|
||||
|
||||
CV_Assert( coeffs[j] >= 0 && coeffs[j + 1] >= 0 && coeffs[j + 2] >= 0 &&
|
||||
coeffs[j] + coeffs[j + 1] + coeffs[j + 2] < 1.5f*LabCbrtTabScale );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1379,24 +1387,39 @@ struct RGB2Lab_f
|
||||
C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
|
||||
n *= 3;
|
||||
|
||||
for( i = 0; i < n; i += 3, src += scn )
|
||||
static const float _1_3 = 1.0 / 3.0;
|
||||
static const double _a = 16.0 / 116;
|
||||
for (i = 0; i < n; i += 3, src += scn )
|
||||
{
|
||||
float R = src[0], G = src[1], B = src[2];
|
||||
if( gammaTab )
|
||||
float R = clip(src[0]);
|
||||
float G = clip(src[1]);
|
||||
float B = clip(src[2]);
|
||||
|
||||
// CV_Assert(R >= 0.0f && R <= 1.0f);
|
||||
// CV_Assert(G >= 0.0f && G <= 1.0f);
|
||||
// CV_Assert(B >= 0.0f && B <= 1.0f);
|
||||
|
||||
if (gammaTab)
|
||||
{
|
||||
R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||
G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||
B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||
R = splineInterpolate(R * gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||
G = splineInterpolate(G * gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||
B = splineInterpolate(B * gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||
}
|
||||
float fX = splineInterpolate(R*C0 + G*C1 + B*C2, LabCbrtTab, LAB_CBRT_TAB_SIZE);
|
||||
float fY = splineInterpolate(R*C3 + G*C4 + B*C5, LabCbrtTab, LAB_CBRT_TAB_SIZE);
|
||||
float fZ = splineInterpolate(R*C6 + G*C7 + B*C8, LabCbrtTab, LAB_CBRT_TAB_SIZE);
|
||||
|
||||
float L = 116.f*fY - 16.f;
|
||||
float a = 500.f*(fX - fY);
|
||||
float b = 200.f*(fY - fZ);
|
||||
|
||||
dst[i] = L; dst[i+1] = a; dst[i+2] = b;
|
||||
float X = R*C0 + G*C1 + B*C2;
|
||||
float Y = R*C3 + G*C4 + B*C5;
|
||||
float Z = R*C6 + G*C7 + B*C8;
|
||||
|
||||
float FX = X > 0.008856 ? pow(X, _1_3) : (7.787f * X + _a);
|
||||
float FY = Y > 0.008856 ? pow(Y, _1_3) : (7.787f * Y + _a);
|
||||
float FZ = Z > 0.008856 ? pow(Z, _1_3) : (7.787f * Z + _a);
|
||||
|
||||
float L = Y > 0.008856 ? (116.f * FY - 16.f) : (903.3 * Y);
|
||||
float a = 500.f * (FX - FY);
|
||||
float b = 200.f * (FY - FZ);
|
||||
|
||||
dst[i] = L;
|
||||
dst[i + 1] = a;
|
||||
dst[i + 2] = b;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1404,21 +1427,22 @@ struct RGB2Lab_f
|
||||
float coeffs[9];
|
||||
bool srgb;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct Lab2RGB_f
|
||||
{
|
||||
typedef float channel_type;
|
||||
|
||||
|
||||
Lab2RGB_f( int _dstcn, int blueIdx, const float* _coeffs,
|
||||
const float* _whitept, bool _srgb )
|
||||
: dstcn(_dstcn), srgb(_srgb)
|
||||
const float* _whitept, bool _srgb )
|
||||
: dstcn(_dstcn), srgb(_srgb), blueInd(blueIdx)
|
||||
{
|
||||
initLabTabs();
|
||||
|
||||
if(!_coeffs) _coeffs = XYZ2sRGB_D65;
|
||||
if(!_whitept) _whitept = D65;
|
||||
|
||||
|
||||
if(!_coeffs)
|
||||
_coeffs = XYZ2sRGB_D65;
|
||||
if(!_whitept)
|
||||
_whitept = D65;
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
coeffs[i+(blueIdx^2)*3] = _coeffs[i]*_whitept[i];
|
||||
@ -1426,50 +1450,76 @@ struct Lab2RGB_f
|
||||
coeffs[i+blueIdx*3] = _coeffs[i+6]*_whitept[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void operator()(const float* src, float* dst, int n) const
|
||||
{
|
||||
int i, dcn = dstcn;
|
||||
const float* gammaTab = srgb ? sRGBInvGammaTab : 0;
|
||||
float gscale = GammaTabScale;
|
||||
float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
|
||||
C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
|
||||
C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
|
||||
C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
|
||||
C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
|
||||
float alpha = ColorChannel<float>::max();
|
||||
n *= 3;
|
||||
|
||||
for( i = 0; i < n; i += 3, dst += dcn )
|
||||
|
||||
static const float lThresh = 0.008856f * 903.3f;
|
||||
static const float fThresh = 7.787f * 0.008856f + 16.0f / 116.0f;
|
||||
for (i = 0; i < n; i += 3, dst += dcn)
|
||||
{
|
||||
float L = src[i], a = src[i+1], b = src[i+2];
|
||||
float Y = (L + 16.f)*(1.f/116.f);
|
||||
float X = (Y + a*0.002f);
|
||||
float Z = (Y - b*0.005f);
|
||||
Y = Y*Y*Y;
|
||||
X = X*X*X;
|
||||
Z = Z*Z*Z;
|
||||
|
||||
float R = X*C0 + Y*C1 + Z*C2;
|
||||
float G = X*C3 + Y*C4 + Z*C5;
|
||||
float B = X*C6 + Y*C7 + Z*C8;
|
||||
|
||||
if( gammaTab )
|
||||
float li = src[i];
|
||||
float ai = src[i + 1];
|
||||
float bi = src[i + 2];
|
||||
|
||||
float y, fy;
|
||||
if (li <= lThresh)
|
||||
{
|
||||
R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||
G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||
B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||
y = li / 903.3f;
|
||||
fy = 7.787f * y + 16.0f / 116.0f;
|
||||
}
|
||||
|
||||
dst[0] = R; dst[1] = G; dst[2] = B;
|
||||
else
|
||||
{
|
||||
fy = (li + 16.0f) / 116.0f;
|
||||
y = fy * fy * fy;
|
||||
}
|
||||
|
||||
float fxz[] = { ai / 500.0f + fy, fy - bi / 200.0f };
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
if (fxz[j] <= fThresh)
|
||||
fxz[j] = (fxz[j] - 16.0f / 116.0f) / 7.787f;
|
||||
else
|
||||
fxz[j] = fxz[j] * fxz[j] * fxz[j];
|
||||
|
||||
|
||||
float x = fxz[0], z = fxz[1];
|
||||
float ro = clip(C0 * x + C1 * y + C2 * z);
|
||||
float go = clip(C3 * x + C4 * y + C5 * z);
|
||||
float bo = clip(C6 * x + C7 * y + C8 * z);
|
||||
|
||||
// CV_Assert(ro >= 0.0f && ro <= 1.0f);
|
||||
// CV_Assert(go >= 0.0f && go <= 1.0f);
|
||||
// CV_Assert(bo >= 0.0f && bo <= 1.0f);
|
||||
|
||||
if (gammaTab)
|
||||
{
|
||||
ro = splineInterpolate(ro * gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||
go = splineInterpolate(go * gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||
bo = splineInterpolate(bo * gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||
}
|
||||
|
||||
dst[0] = ro, dst[1] = go, dst[2] = bo;
|
||||
if( dcn == 4 )
|
||||
dst[3] = alpha;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int dstcn;
|
||||
float coeffs[9];
|
||||
bool srgb;
|
||||
int blueInd;
|
||||
};
|
||||
|
||||
|
||||
#undef clip
|
||||
|
||||
struct Lab2RGB_b
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user