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
|
struct RGB2Lab_f
|
||||||
{
|
{
|
||||||
typedef float channel_type;
|
typedef float channel_type;
|
||||||
@ -1355,17 +1358,22 @@ struct RGB2Lab_f
|
|||||||
volatile int _3 = 3;
|
volatile int _3 = 3;
|
||||||
initLabTabs();
|
initLabTabs();
|
||||||
|
|
||||||
if(!_coeffs) _coeffs = sRGB2XYZ_D65;
|
if (!_coeffs)
|
||||||
if(!_whitept) _whitept = D65;
|
_coeffs = sRGB2XYZ_D65;
|
||||||
float scale[] = { LabCbrtTabScale/_whitept[0], LabCbrtTabScale, LabCbrtTabScale/_whitept[2] };
|
if (!_whitept)
|
||||||
|
_whitept = D65;
|
||||||
|
|
||||||
|
float scale[] = { 1.0f / _whitept[0], 1.0f, 1.0f / _whitept[2] };
|
||||||
|
|
||||||
for( int i = 0; i < _3; i++ )
|
for( int i = 0; i < _3; i++ )
|
||||||
{
|
{
|
||||||
coeffs[i*3+(blueIdx^2)] = _coeffs[i*3]*scale[i];
|
int j = i * 3;
|
||||||
coeffs[i*3+1] = _coeffs[i*3+1]*scale[i];
|
coeffs[j + (blueIdx ^ 2)] = _coeffs[j] * scale[i];
|
||||||
coeffs[i*3+blueIdx] = _coeffs[i*3+2]*scale[i];
|
coeffs[j + 1] = _coeffs[j + 1] * scale[i];
|
||||||
CV_Assert( coeffs[i*3] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
|
coeffs[j + blueIdx] = _coeffs[j + 2] * scale[i];
|
||||||
coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 1.5f*LabCbrtTabScale );
|
|
||||||
|
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];
|
C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
|
||||||
n *= 3;
|
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];
|
float R = clip(src[0]);
|
||||||
if( gammaTab )
|
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);
|
R = splineInterpolate(R * gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||||
G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
|
G = splineInterpolate(G * gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||||
B = splineInterpolate(B*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 X = R*C0 + G*C1 + B*C2;
|
||||||
float fY = splineInterpolate(R*C3 + G*C4 + B*C5, LabCbrtTab, LAB_CBRT_TAB_SIZE);
|
float Y = R*C3 + G*C4 + B*C5;
|
||||||
float fZ = splineInterpolate(R*C6 + G*C7 + B*C8, LabCbrtTab, LAB_CBRT_TAB_SIZE);
|
float Z = R*C6 + G*C7 + B*C8;
|
||||||
|
|
||||||
float L = 116.f*fY - 16.f;
|
float FX = X > 0.008856 ? pow(X, _1_3) : (7.787f * X + _a);
|
||||||
float a = 500.f*(fX - fY);
|
float FY = Y > 0.008856 ? pow(Y, _1_3) : (7.787f * Y + _a);
|
||||||
float b = 200.f*(fY - fZ);
|
float FZ = Z > 0.008856 ? pow(Z, _1_3) : (7.787f * Z + _a);
|
||||||
|
|
||||||
dst[i] = L; dst[i+1] = a; dst[i+2] = b;
|
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];
|
float coeffs[9];
|
||||||
bool srgb;
|
bool srgb;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Lab2RGB_f
|
struct Lab2RGB_f
|
||||||
{
|
{
|
||||||
typedef float channel_type;
|
typedef float channel_type;
|
||||||
|
|
||||||
Lab2RGB_f( int _dstcn, int blueIdx, const float* _coeffs,
|
Lab2RGB_f( int _dstcn, int blueIdx, const float* _coeffs,
|
||||||
const float* _whitept, bool _srgb )
|
const float* _whitept, bool _srgb )
|
||||||
: dstcn(_dstcn), srgb(_srgb)
|
: dstcn(_dstcn), srgb(_srgb), blueInd(blueIdx)
|
||||||
{
|
{
|
||||||
initLabTabs();
|
initLabTabs();
|
||||||
|
|
||||||
if(!_coeffs) _coeffs = XYZ2sRGB_D65;
|
if(!_coeffs)
|
||||||
if(!_whitept) _whitept = D65;
|
_coeffs = XYZ2sRGB_D65;
|
||||||
|
if(!_whitept)
|
||||||
|
_whitept = D65;
|
||||||
|
|
||||||
for( int i = 0; i < 3; i++ )
|
for( int i = 0; i < 3; i++ )
|
||||||
{
|
{
|
||||||
coeffs[i+(blueIdx^2)*3] = _coeffs[i]*_whitept[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];
|
coeffs[i+blueIdx*3] = _coeffs[i+6]*_whitept[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const float* src, float* dst, int n) const
|
void operator()(const float* src, float* dst, int n) const
|
||||||
{
|
{
|
||||||
int i, dcn = dstcn;
|
int i, dcn = dstcn;
|
||||||
const float* gammaTab = srgb ? sRGBInvGammaTab : 0;
|
const float* gammaTab = srgb ? sRGBInvGammaTab : 0;
|
||||||
float gscale = GammaTabScale;
|
float gscale = GammaTabScale;
|
||||||
float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
|
float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
|
||||||
C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
|
C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
|
||||||
C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
|
C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
|
||||||
float alpha = ColorChannel<float>::max();
|
float alpha = ColorChannel<float>::max();
|
||||||
n *= 3;
|
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 li = src[i];
|
||||||
float Y = (L + 16.f)*(1.f/116.f);
|
float ai = src[i + 1];
|
||||||
float X = (Y + a*0.002f);
|
float bi = src[i + 2];
|
||||||
float Z = (Y - b*0.005f);
|
|
||||||
Y = Y*Y*Y;
|
float y, fy;
|
||||||
X = X*X*X;
|
if (li <= lThresh)
|
||||||
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 )
|
|
||||||
{
|
{
|
||||||
R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
|
y = li / 903.3f;
|
||||||
G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
|
fy = 7.787f * y + 16.0f / 116.0f;
|
||||||
B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
dst[0] = R; dst[1] = G; dst[2] = B;
|
{
|
||||||
|
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 )
|
if( dcn == 4 )
|
||||||
dst[3] = alpha;
|
dst[3] = alpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int dstcn;
|
int dstcn;
|
||||||
float coeffs[9];
|
float coeffs[9];
|
||||||
bool srgb;
|
bool srgb;
|
||||||
|
int blueInd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef clip
|
||||||
|
|
||||||
struct Lab2RGB_b
|
struct Lab2RGB_b
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user