mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 00:03:03 +04:00
Bit-exact version of RGB2Luv_b (#9226)
* Imgproc_ColorLab_Full.accuracy test fixed * Lab and Luv tests: rewritten, constants explained * CV_ColorCvtBaseTest: added methods for 8u implementations * Lab2RGB_b: bit-exactness enabled for all modes; non-vectorized code fixed to comply with vectorized * srgb support added * XYZ constants made softdouble * bit-exact tests written for Lab * ColorLab_full test fixed * reverted: no 8u convertors for CV_ColorCvtBaseTest * added checksum-based test for Lab bit-exactness * extra declarations removed * Lab test fix: stop at first mismatch * test info output improved * error message fixed * lab_tetra squashed * initial version is almost written * unfinished work * compilation fixed, to be debugged * Lab test removed * more fixes * Luv2RGBinteger: channels order fixed * Lab structs removed * good trilinear interpolation added * several fixes * removed Luv2RGB interpolations, XYZ tables; 8-cell LUT added * no_interpolate made 8-cell * interpolations rewritten to 8-cell, minor fixes * packed interpolation added for RGB2Luv * tetra implemented * removing unnecessary code * LUT building merged * changes ported to color.cpp * minor fixes; try to suppress warnings * fixed v range of Luv * fixed incorrect src channel number * minor fixes * preliminary version of Luv2RGBinteger is done * Luv2RGB_b is in progress * XYZ color constants converted to softfloat * Luv test: precision fixed * Luv bit-exactness test added * warnings fixed * compilation fixed, error message fixed * test_lab.cpp removed
This commit is contained in:
committed by
Vadim Pisarevsky
parent
9640bbe76d
commit
4435ec5f26
+406
-152
@@ -3475,27 +3475,47 @@ struct YCrCb2RGB_i<uchar>
|
||||
|
||||
////////////////////////////////////// RGB <-> XYZ ///////////////////////////////////////
|
||||
|
||||
static const float sRGB2XYZ_D65[] =
|
||||
// 0.412453, 0.357580, 0.180423,
|
||||
// 0.212671, 0.715160, 0.072169,
|
||||
// 0.019334, 0.119193, 0.950227
|
||||
static const softdouble sRGB2XYZ_D65[] =
|
||||
{
|
||||
0.412453f, 0.357580f, 0.180423f,
|
||||
0.212671f, 0.715160f, 0.072169f,
|
||||
0.019334f, 0.119193f, 0.950227f
|
||||
softdouble::fromRaw(0x3fda65a14488c60d),
|
||||
softdouble::fromRaw(0x3fd6e297396d0918),
|
||||
softdouble::fromRaw(0x3fc71819d2391d58),
|
||||
softdouble::fromRaw(0x3fcb38cda6e75ff6),
|
||||
softdouble::fromRaw(0x3fe6e297396d0918),
|
||||
softdouble::fromRaw(0x3fb279aae6c8f755),
|
||||
softdouble::fromRaw(0x3f93cc4ac6cdaf4b),
|
||||
softdouble::fromRaw(0x3fbe836eb4e98138),
|
||||
softdouble::fromRaw(0x3fee68427418d691)
|
||||
};
|
||||
|
||||
static const float XYZ2sRGB_D65[] =
|
||||
// 3.240479, -1.53715, -0.498535,
|
||||
// -0.969256, 1.875991, 0.041556,
|
||||
// 0.055648, -0.204043, 1.057311
|
||||
static const softdouble XYZ2sRGB_D65[] =
|
||||
{
|
||||
3.240479f, -1.53715f, -0.498535f,
|
||||
-0.969256f, 1.875991f, 0.041556f,
|
||||
0.055648f, -0.204043f, 1.057311f
|
||||
softdouble::fromRaw(0x4009ec804102ff8f),
|
||||
softdouble::fromRaw(0xbff8982a9930be0e),
|
||||
softdouble::fromRaw(0xbfdfe7ff583a53b9),
|
||||
softdouble::fromRaw(0xbfef042528ae74f3),
|
||||
softdouble::fromRaw(0x3ffe040f23897204),
|
||||
softdouble::fromRaw(0x3fa546d3f9e7b80b),
|
||||
softdouble::fromRaw(0x3fac7de5082cf52c),
|
||||
softdouble::fromRaw(0xbfca1e14bdfd2631),
|
||||
softdouble::fromRaw(0x3ff0eabef06b3786)
|
||||
};
|
||||
|
||||
|
||||
template<typename _Tp> struct RGB2XYZ_f
|
||||
{
|
||||
typedef _Tp channel_type;
|
||||
|
||||
RGB2XYZ_f(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
|
||||
{
|
||||
memcpy(coeffs, _coeffs ? _coeffs : sRGB2XYZ_D65, 9*sizeof(coeffs[0]));
|
||||
for(int i = 0; i < 9; i++)
|
||||
coeffs[i] = _coeffs ? _coeffs[i] : (float)sRGB2XYZ_D65[i];
|
||||
if(blueIdx == 0)
|
||||
{
|
||||
std::swap(coeffs[0], coeffs[2]);
|
||||
@@ -3532,7 +3552,8 @@ struct RGB2XYZ_f<float>
|
||||
|
||||
RGB2XYZ_f(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
|
||||
{
|
||||
memcpy(coeffs, _coeffs ? _coeffs : sRGB2XYZ_D65, 9*sizeof(coeffs[0]));
|
||||
for(int i = 0; i < 9; i++)
|
||||
coeffs[i] = _coeffs ? _coeffs[i] : (float)sRGB2XYZ_D65[i];
|
||||
if(blueIdx == 0)
|
||||
{
|
||||
std::swap(coeffs[0], coeffs[2]);
|
||||
@@ -3603,7 +3624,8 @@ struct RGB2XYZ_f<float>
|
||||
|
||||
RGB2XYZ_f(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
|
||||
{
|
||||
memcpy(coeffs, _coeffs ? _coeffs : sRGB2XYZ_D65, 9*sizeof(coeffs[0]));
|
||||
for(int i = 0; i < 9; i++)
|
||||
coeffs[i] = _coeffs ? _coeffs[i] : (float)sRGB2XYZ_D65[i];
|
||||
if(blueIdx == 0)
|
||||
{
|
||||
std::swap(coeffs[0], coeffs[2]);
|
||||
@@ -3999,7 +4021,8 @@ template<typename _Tp> struct XYZ2RGB_f
|
||||
XYZ2RGB_f(int _dstcn, int _blueIdx, const float* _coeffs)
|
||||
: dstcn(_dstcn), blueIdx(_blueIdx)
|
||||
{
|
||||
memcpy(coeffs, _coeffs ? _coeffs : XYZ2sRGB_D65, 9*sizeof(coeffs[0]));
|
||||
for(int i = 0; i < 9; i++)
|
||||
coeffs[i] = _coeffs ? _coeffs[i] : (float)XYZ2sRGB_D65[i];
|
||||
if(blueIdx == 0)
|
||||
{
|
||||
std::swap(coeffs[0], coeffs[6]);
|
||||
@@ -4040,7 +4063,8 @@ struct XYZ2RGB_f<float>
|
||||
XYZ2RGB_f(int _dstcn, int _blueIdx, const float* _coeffs)
|
||||
: dstcn(_dstcn), blueIdx(_blueIdx)
|
||||
{
|
||||
memcpy(coeffs, _coeffs ? _coeffs : XYZ2sRGB_D65, 9*sizeof(coeffs[0]));
|
||||
for(int i = 0; i < 9; i++)
|
||||
coeffs[i] = _coeffs ? _coeffs[i] : XYZ2sRGB_D65[i];
|
||||
if(blueIdx == 0)
|
||||
{
|
||||
std::swap(coeffs[0], coeffs[6]);
|
||||
@@ -5815,7 +5839,10 @@ struct HLS2RGB_b
|
||||
|
||||
///////////////////////////////////// RGB <-> L*a*b* /////////////////////////////////////
|
||||
|
||||
static const float D65[] = { 0.950456f, 1.f, 1.088754f };
|
||||
//0.950456, 1., 1.088754
|
||||
static const softdouble D65[] = {softdouble::fromRaw(0x3fee6a22b3892ee8),
|
||||
softdouble::one(),
|
||||
softdouble::fromRaw(0x3ff16b8950763a19)};
|
||||
|
||||
enum { LAB_CBRT_TAB_SIZE = 1024, GAMMA_TAB_SIZE = 1024 };
|
||||
static float LabCbrtTab[LAB_CBRT_TAB_SIZE*4];
|
||||
@@ -5851,6 +5878,12 @@ static int16_t trilinearLUT[TRILINEAR_BASE*TRILINEAR_BASE*TRILINEAR_BASE*8];
|
||||
static ushort LabToYF_b[256*2];
|
||||
static const int minABvalue = -8145;
|
||||
static int abToXZ_b[LAB_BASE*9/4];
|
||||
// Luv constants
|
||||
static const bool enableRGB2LuvInterpolation = true;
|
||||
static const bool enablePackedRGB2Luv = true;
|
||||
static int16_t RGB2LuvLUT_s16[LAB_LUT_DIM*LAB_LUT_DIM*LAB_LUT_DIM*3*8];
|
||||
static const softfloat uLow(-134), uHigh(220), uRange(uHigh-uLow);
|
||||
static const softfloat vLow(-140), vHigh(122), vRange(vHigh-vLow);
|
||||
|
||||
#define clip(value) \
|
||||
value < 0.0f ? 0.0f : value > 1.0f ? 1.0f : value;
|
||||
@@ -5980,40 +6013,55 @@ static void initLabTabs()
|
||||
abToXZ_b[i-minABvalue] = v; // -1335 <= v <= 88231
|
||||
}
|
||||
|
||||
if(enableRGB2LabInterpolation)
|
||||
//try to suppress warning
|
||||
static const bool calcLUT = enableRGB2LabInterpolation || enableRGB2LuvInterpolation;
|
||||
if(calcLUT)
|
||||
{
|
||||
const float* _whitept = D65;
|
||||
softfloat coeffs[9];
|
||||
softfloat scaledCoeffs[9], coeffs[9];
|
||||
|
||||
//RGB2Lab coeffs
|
||||
softfloat scaleWhite[] = { softfloat::one()/softfloat(_whitept[0]),
|
||||
softfloat::one(),
|
||||
softfloat::one()/softfloat(_whitept[2]) };
|
||||
softdouble scaleWhite[] = { softdouble::one()/D65[0],
|
||||
softdouble::one(),
|
||||
softdouble::one()/D65[2] };
|
||||
|
||||
for(i = 0; i < 3; i++ )
|
||||
{
|
||||
int j = i * 3;
|
||||
coeffs[j + 2] = scaleWhite[i] * softfloat(sRGB2XYZ_D65[j ]);
|
||||
coeffs[j + 1] = scaleWhite[i] * softfloat(sRGB2XYZ_D65[j + 1]);
|
||||
coeffs[j + 0] = scaleWhite[i] * softfloat(sRGB2XYZ_D65[j + 2]);
|
||||
coeffs[i*3+2] = sRGB2XYZ_D65[i*3+0];
|
||||
coeffs[i*3+1] = sRGB2XYZ_D65[i*3+1];
|
||||
coeffs[i*3+0] = sRGB2XYZ_D65[i*3+2];
|
||||
scaledCoeffs[i*3+0] = sRGB2XYZ_D65[i*3+2] * scaleWhite[i];
|
||||
scaledCoeffs[i*3+1] = sRGB2XYZ_D65[i*3+1] * scaleWhite[i];
|
||||
scaledCoeffs[i*3+2] = sRGB2XYZ_D65[i*3+0] * scaleWhite[i];
|
||||
}
|
||||
|
||||
softfloat D0 = coeffs[0], D1 = coeffs[1], D2 = coeffs[2],
|
||||
D3 = coeffs[3], D4 = coeffs[4], D5 = coeffs[5],
|
||||
D6 = coeffs[6], D7 = coeffs[7], D8 = coeffs[8];
|
||||
softfloat S0 = scaledCoeffs[0], S1 = scaledCoeffs[1], S2 = scaledCoeffs[2],
|
||||
S3 = scaledCoeffs[3], S4 = scaledCoeffs[4], S5 = scaledCoeffs[5],
|
||||
S6 = scaledCoeffs[6], S7 = scaledCoeffs[7], S8 = scaledCoeffs[8];
|
||||
softfloat 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];
|
||||
|
||||
//903.3f = (29/3)^3
|
||||
softfloat dd = D65[0] + D65[1]*softdouble(15) + D65[2]*softdouble(3);
|
||||
dd = softfloat::one()/max(dd, softfloat(FLT_EPSILON));
|
||||
softfloat un = dd*softfloat(13*4)*D65[0];
|
||||
softfloat vn = dd*softfloat(13*9)*D65[1];
|
||||
|
||||
//u, v: [-134.0, 220.0], [-140.0, 122.0]
|
||||
static const softfloat lld(LAB_LUT_DIM - 1), f116(116), f16(16), f500(500), f200(200);
|
||||
static const softfloat f100(100), f128(128), f256(256), lbase((int)LAB_BASE);
|
||||
//903.3f = (29/3)^3
|
||||
static const softfloat f9033 = softfloat(29*29*29)/softfloat(27);
|
||||
static const softfloat f9of4 = softfloat(9)/softfloat(4);
|
||||
static const softfloat f15(15), f3(3);
|
||||
AutoBuffer<int16_t> RGB2Labprev(LAB_LUT_DIM*LAB_LUT_DIM*LAB_LUT_DIM*3);
|
||||
AutoBuffer<int16_t> RGB2Luvprev(LAB_LUT_DIM*LAB_LUT_DIM*LAB_LUT_DIM*3);
|
||||
for(int p = 0; p < LAB_LUT_DIM; p++)
|
||||
{
|
||||
for(int q = 0; q < LAB_LUT_DIM; q++)
|
||||
{
|
||||
for(int r = 0; r < LAB_LUT_DIM; r++)
|
||||
{
|
||||
//RGB 2 Lab LUT building
|
||||
int idx = p*3 + q*LAB_LUT_DIM*3 + r*LAB_LUT_DIM*LAB_LUT_DIM*3;
|
||||
softfloat R = softfloat(p)/lld;
|
||||
softfloat G = softfloat(q)/lld;
|
||||
softfloat B = softfloat(r)/lld;
|
||||
@@ -6022,22 +6070,42 @@ static void initLabTabs()
|
||||
G = applyGamma(G);
|
||||
B = applyGamma(B);
|
||||
|
||||
softfloat X = R*D0 + G*D1 + B*D2;
|
||||
softfloat Y = R*D3 + G*D4 + B*D5;
|
||||
softfloat Z = R*D6 + G*D7 + B*D8;
|
||||
//RGB 2 Lab LUT building
|
||||
{
|
||||
softfloat X = R*S0 + G*S1 + B*S2;
|
||||
softfloat Y = R*S3 + G*S4 + B*S5;
|
||||
softfloat Z = R*S6 + G*S7 + B*S8;
|
||||
|
||||
softfloat FX = X > lthresh ? cbrt(X) : mulAdd(X, lscale, lbias);
|
||||
softfloat FY = Y > lthresh ? cbrt(Y) : mulAdd(Y, lscale, lbias);
|
||||
softfloat FZ = Z > lthresh ? cbrt(Z) : mulAdd(Z, lscale, lbias);
|
||||
softfloat FX = X > lthresh ? cbrt(X) : mulAdd(X, lscale, lbias);
|
||||
softfloat FY = Y > lthresh ? cbrt(Y) : mulAdd(Y, lscale, lbias);
|
||||
softfloat FZ = Z > lthresh ? cbrt(Z) : mulAdd(Z, lscale, lbias);
|
||||
|
||||
softfloat L = Y > lthresh ? (f116*FY - f16) : (f9033*Y);
|
||||
softfloat a = f500 * (FX - FY);
|
||||
softfloat b = f200 * (FY - FZ);
|
||||
softfloat L = Y > lthresh ? (f116*FY - f16) : (f9033*Y);
|
||||
softfloat a = f500 * (FX - FY);
|
||||
softfloat b = f200 * (FY - FZ);
|
||||
|
||||
int idx = p*3 + q*LAB_LUT_DIM*3 + r*LAB_LUT_DIM*LAB_LUT_DIM*3;
|
||||
RGB2Labprev[idx] = (int16_t)(cvRound(lbase*L/f100));
|
||||
RGB2Labprev[idx+1] = (int16_t)(cvRound(lbase*(a + f128)/f256));
|
||||
RGB2Labprev[idx+2] = (int16_t)(cvRound(lbase*(b + f128)/f256));
|
||||
RGB2Labprev[idx] = (int16_t)(cvRound(lbase*L/f100));
|
||||
RGB2Labprev[idx+1] = (int16_t)(cvRound(lbase*(a + f128)/f256));
|
||||
RGB2Labprev[idx+2] = (int16_t)(cvRound(lbase*(b + f128)/f256));
|
||||
}
|
||||
|
||||
//RGB 2 Luv LUT building
|
||||
{
|
||||
softfloat X = R*C0 + G*C1 + B*C2;
|
||||
softfloat Y = R*C3 + G*C4 + B*C5;
|
||||
softfloat Z = R*C6 + G*C7 + B*C8;
|
||||
|
||||
softfloat L = Y < lthresh ? mulAdd(Y, lscale, lbias) : cbrt(Y);
|
||||
L = L*f116 - f16;
|
||||
|
||||
softfloat d = softfloat(4*13)/max(X + f15 * Y + f3 * Z, softfloat(FLT_EPSILON));
|
||||
softfloat u = L*(X*d - un);
|
||||
softfloat v = L*(f9of4*Y*d - vn);
|
||||
|
||||
RGB2Luvprev[idx ] = (int16_t)cvRound(lbase*L/f100);
|
||||
RGB2Luvprev[idx+1] = (int16_t)cvRound(lbase*(u-uLow)/uRange);
|
||||
RGB2Luvprev[idx+2] = (int16_t)cvRound(lbase*(v-vLow)/vRange);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6057,6 +6125,9 @@ static void initLabTabs()
|
||||
RGB2LabLUT_s16[idxnew] = RGB2Labprev[idxold];\
|
||||
RGB2LabLUT_s16[idxnew+8] = RGB2Labprev[idxold+1];\
|
||||
RGB2LabLUT_s16[idxnew+16] = RGB2Labprev[idxold+2];\
|
||||
RGB2LuvLUT_s16[idxnew] = RGB2Luvprev[idxold];\
|
||||
RGB2LuvLUT_s16[idxnew+8] = RGB2Luvprev[idxold+1];\
|
||||
RGB2LuvLUT_s16[idxnew+16] = RGB2Luvprev[idxold+2];\
|
||||
} while(0)
|
||||
|
||||
FILL(0, 0, 0); FILL(0, 0, 1);
|
||||
@@ -6228,17 +6299,25 @@ struct RGB2Lab_b
|
||||
static volatile int _3 = 3;
|
||||
initLabTabs();
|
||||
|
||||
if (!_coeffs)
|
||||
_coeffs = sRGB2XYZ_D65;
|
||||
if (!_whitept)
|
||||
_whitept = D65;
|
||||
softdouble whitePt[3];
|
||||
for(int i = 0; i < 3; i++)
|
||||
if(_whitept)
|
||||
whitePt[i] = softdouble(_whitept[i]);
|
||||
else
|
||||
whitePt[i] = D65[i];
|
||||
|
||||
static const softfloat lshift(1 << lab_shift);
|
||||
static const softdouble lshift(1 << lab_shift);
|
||||
for( int i = 0; i < _3; i++ )
|
||||
{
|
||||
coeffs[i*3+(blueIdx^2)] = cvRound((lshift*softfloat(_coeffs[i*3 ]))/softfloat(_whitept[i]));
|
||||
coeffs[i*3+1] = cvRound((lshift*softfloat(_coeffs[i*3+1]))/softfloat(_whitept[i]));
|
||||
coeffs[i*3+blueIdx] = cvRound((lshift*softfloat(_coeffs[i*3+2]))/softfloat(_whitept[i]));
|
||||
softdouble c[3];
|
||||
for(int j = 0; j < 3; j++)
|
||||
if(_coeffs)
|
||||
c[j] = softdouble(_coeffs[i*3+j]);
|
||||
else
|
||||
c[j] = sRGB2XYZ_D65[i*3+j];
|
||||
coeffs[i*3+(blueIdx^2)] = cvRound(lshift*c[0]/whitePt[i]);
|
||||
coeffs[i*3+1] = cvRound(lshift*c[1]/whitePt[i]);
|
||||
coeffs[i*3+blueIdx] = cvRound(lshift*c[2]/whitePt[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] < 2*(1 << lab_shift));
|
||||
@@ -6293,27 +6372,31 @@ struct RGB2Lab_f
|
||||
|
||||
useInterpolation = (!_coeffs && !_whitept && srgb && enableRGB2LabInterpolation);
|
||||
|
||||
if (!_coeffs)
|
||||
_coeffs = sRGB2XYZ_D65;
|
||||
if (!_whitept)
|
||||
_whitept = D65;
|
||||
softdouble whitePt[3];
|
||||
for(int i = 0; i < 3; i++)
|
||||
if(_whitept)
|
||||
whitePt[i] = softdouble((double)_whitept[i]);
|
||||
else
|
||||
whitePt[i] = D65[i];
|
||||
|
||||
softfloat scale[] = { softfloat::one() / softfloat(_whitept[0]),
|
||||
softfloat::one(),
|
||||
softfloat::one() / softfloat(_whitept[2]) };
|
||||
softdouble scale[] = { softdouble::one() / whitePt[0],
|
||||
softdouble::one(),
|
||||
softdouble::one() / whitePt[2] };
|
||||
|
||||
for( int i = 0; i < _3; i++ )
|
||||
{
|
||||
int j = i * 3;
|
||||
softfloat c0 = scale[i] * softfloat(_coeffs[j ]);
|
||||
softfloat c1 = scale[i] * softfloat(_coeffs[j + 1]);
|
||||
softfloat c2 = scale[i] * softfloat(_coeffs[j + 2]);
|
||||
coeffs[j + (blueIdx ^ 2)] = c0;
|
||||
coeffs[j + 1] = c1;
|
||||
coeffs[j + blueIdx] = c2;
|
||||
softfloat c[3];
|
||||
for(int k = 0; k < 3; k++)
|
||||
if(_coeffs)
|
||||
c[k] = scale[i] * softdouble((double)_coeffs[i*3 + k]);
|
||||
else
|
||||
c[k] = scale[i] * sRGB2XYZ_D65[i*3 + k];
|
||||
coeffs[i*3 + (blueIdx ^ 2)] = c[0];
|
||||
coeffs[i*3 + 1] = c[1];
|
||||
coeffs[i*3 + blueIdx] = c[2];
|
||||
|
||||
CV_Assert( c0 >= 0 && c1 >= 0 && c2 >= 0 &&
|
||||
c0 + c1 + c2 < softfloat((int)LAB_CBRT_TAB_SIZE) );
|
||||
CV_Assert( c[0] >= 0 && c[1] >= 0 && c[2] >= 0 &&
|
||||
c[0] + c[1] + c[2] < softfloat((int)LAB_CBRT_TAB_SIZE) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6481,16 +6564,25 @@ struct Lab2RGBfloat
|
||||
{
|
||||
initLabTabs();
|
||||
|
||||
if(!_coeffs)
|
||||
_coeffs = XYZ2sRGB_D65;
|
||||
if(!_whitept)
|
||||
_whitept = D65;
|
||||
softdouble whitePt[3];
|
||||
for(int i = 0; i < 3; i++)
|
||||
if(_whitept)
|
||||
whitePt[i] = softdouble((double)_whitept[i]);
|
||||
else
|
||||
whitePt[i] = D65[i];
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
coeffs[i+(blueIdx^2)*3] = (softfloat(_coeffs[i] )*softfloat(_whitept[i]));
|
||||
coeffs[i+3] = (softfloat(_coeffs[i+3])*softfloat(_whitept[i]));
|
||||
coeffs[i+blueIdx*3] = (softfloat(_coeffs[i+6])*softfloat(_whitept[i]));
|
||||
softdouble c[3];
|
||||
for(int j = 0; j < 3; j++)
|
||||
if(_coeffs)
|
||||
c[j] = softdouble(_coeffs[i+j*3]);
|
||||
else
|
||||
c[j] = XYZ2sRGB_D65[i+j*3];
|
||||
|
||||
coeffs[i+(blueIdx^2)*3] = (float)(c[0]*whitePt[i]);
|
||||
coeffs[i+3] = (float)(c[1]*whitePt[i]);
|
||||
coeffs[i+blueIdx*3] = (float)(c[2]*whitePt[i]);
|
||||
}
|
||||
|
||||
lThresh = softfloat(8); // 0.008856f * 903.3f = (6/29)^3*(29/3)^3 = 8
|
||||
@@ -6744,17 +6836,26 @@ struct Lab2RGBinteger
|
||||
const float* _whitept, bool srgb )
|
||||
: dstcn(_dstcn)
|
||||
{
|
||||
if(!_coeffs)
|
||||
_coeffs = XYZ2sRGB_D65;
|
||||
if(!_whitept)
|
||||
_whitept = D65;
|
||||
softdouble whitePt[3];
|
||||
for(int i = 0; i < 3; i++)
|
||||
if(_whitept)
|
||||
whitePt[i] = softdouble(_whitept[i]);
|
||||
else
|
||||
whitePt[i] = D65[i];
|
||||
|
||||
static const softfloat lshift(1 << lab_shift);
|
||||
static const softdouble lshift(1 << lab_shift);
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
coeffs[i+(blueIdx)*3] = cvRound(lshift*softfloat(_coeffs[i ])*softfloat(_whitept[i]));
|
||||
coeffs[i+3] = cvRound(lshift*softfloat(_coeffs[i+3])*softfloat(_whitept[i]));
|
||||
coeffs[i+(blueIdx^2)*3] = cvRound(lshift*softfloat(_coeffs[i+6])*softfloat(_whitept[i]));
|
||||
softdouble c[3];
|
||||
for(int j = 0; j < 3; j++)
|
||||
if(_coeffs)
|
||||
c[j] = softdouble(_coeffs[i+j*3]);
|
||||
else
|
||||
c[j] = XYZ2sRGB_D65[i+j*3];
|
||||
|
||||
coeffs[i+(blueIdx)*3] = cvRound(lshift*c[0]*whitePt[i]);
|
||||
coeffs[i+3] = cvRound(lshift*c[1]*whitePt[i]);
|
||||
coeffs[i+(blueIdx^2)*3] = cvRound(lshift*c[2]*whitePt[i]);
|
||||
}
|
||||
|
||||
tab = srgb ? sRGBInvGammaTab_b : linearInvGammaTab_b;
|
||||
@@ -7332,29 +7433,34 @@ struct Lab2RGB_b
|
||||
int dstcn;
|
||||
};
|
||||
|
||||
#undef clip
|
||||
|
||||
///////////////////////////////////// RGB <-> L*u*v* /////////////////////////////////////
|
||||
|
||||
struct RGB2Luv_f
|
||||
struct RGB2Luvfloat
|
||||
{
|
||||
typedef float channel_type;
|
||||
|
||||
RGB2Luv_f( int _srccn, int blueIdx, const float* _coeffs,
|
||||
RGB2Luvfloat( int _srccn, int blueIdx, const float* _coeffs,
|
||||
const float* whitept, bool _srgb )
|
||||
: srccn(_srccn), srgb(_srgb)
|
||||
{
|
||||
volatile int i;
|
||||
initLabTabs();
|
||||
|
||||
if(!_coeffs) _coeffs = sRGB2XYZ_D65;
|
||||
if(!whitept) whitept = D65;
|
||||
softdouble whitePt[3];
|
||||
for( i = 0; i < 3; i++ )
|
||||
if(whitept)
|
||||
whitePt[i] = softdouble(whitept[i]);
|
||||
else
|
||||
whitePt[i] = D65[i];
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
coeffs[i*3] = _coeffs[i*3];
|
||||
coeffs[i*3+1] = _coeffs[i*3+1];
|
||||
coeffs[i*3+2] = _coeffs[i*3+2];
|
||||
for(int j = 0; j < 3; j++)
|
||||
if(_coeffs)
|
||||
coeffs[i*3+j] = _coeffs[i*3+j];
|
||||
else
|
||||
coeffs[i*3+j] = (float)(sRGB2XYZ_D65[i*3+j]);
|
||||
|
||||
if( blueIdx == 0 )
|
||||
std::swap(coeffs[i*3], coeffs[i*3+2]);
|
||||
CV_Assert( coeffs[i*3] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
|
||||
@@ -7363,18 +7469,18 @@ struct RGB2Luv_f
|
||||
softfloat(coeffs[i*3+2]) < softfloat(1.5f) );
|
||||
}
|
||||
|
||||
softfloat d = softfloat(whitept[0]) +
|
||||
softfloat(whitept[1])*softfloat(15) +
|
||||
softfloat(whitept[2])*softfloat(3);
|
||||
softfloat d = whitePt[0] +
|
||||
whitePt[1]*softdouble(15) +
|
||||
whitePt[2]*softdouble(3);
|
||||
d = softfloat::one()/max(d, softfloat(FLT_EPSILON));
|
||||
un = d*softfloat(13*4)*softfloat(whitept[0]);
|
||||
vn = d*softfloat(13*9)*softfloat(whitept[1]);
|
||||
un = d*softfloat(13*4)*whitePt[0];
|
||||
vn = d*softfloat(13*9)*whitePt[1];
|
||||
|
||||
#if CV_SSE2
|
||||
haveSIMD = checkHardwareSupport(CV_CPU_SSE2);
|
||||
#endif
|
||||
|
||||
CV_Assert(whitept[1] == 1.f);
|
||||
CV_Assert(whitePt[1] == softdouble::one());
|
||||
}
|
||||
|
||||
#if CV_NEON
|
||||
@@ -7640,6 +7746,23 @@ struct RGB2Luv_f
|
||||
#endif
|
||||
};
|
||||
|
||||
struct RGB2Luv_f
|
||||
{
|
||||
typedef float channel_type;
|
||||
|
||||
RGB2Luv_f( int _srccn, int blueIdx, const float* _coeffs,
|
||||
const float* whitept, bool _srgb )
|
||||
: fcvt(_srccn, blueIdx, _coeffs, whitept, _srgb), srccn(_srccn)
|
||||
{ }
|
||||
|
||||
void operator()(const float* src, float* dst, int n) const
|
||||
{
|
||||
fcvt(src, dst, n);
|
||||
}
|
||||
|
||||
RGB2Luvfloat fcvt;
|
||||
int srccn;
|
||||
};
|
||||
|
||||
struct Luv2RGB_f
|
||||
{
|
||||
@@ -7651,27 +7774,38 @@ struct Luv2RGB_f
|
||||
{
|
||||
initLabTabs();
|
||||
|
||||
if(!_coeffs) _coeffs = XYZ2sRGB_D65;
|
||||
if(!whitept) whitept = D65;
|
||||
softdouble whitePt[3];
|
||||
for(int i = 0; i < 3; i++)
|
||||
if(whitept)
|
||||
whitePt[i] = softdouble(whitept[i]);
|
||||
else
|
||||
whitePt[i] = D65[i];
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
coeffs[i+(blueIdx^2)*3] = _coeffs[i];
|
||||
coeffs[i+3] = _coeffs[i+3];
|
||||
coeffs[i+blueIdx*3] = _coeffs[i+6];
|
||||
softfloat c[3];
|
||||
for(int j = 0; j < 3; j++)
|
||||
if(_coeffs)
|
||||
c[j] = softfloat(_coeffs[i+j*3]);
|
||||
else
|
||||
c[j] = XYZ2sRGB_D65[i+j*3];
|
||||
|
||||
coeffs[i+(blueIdx^2)*3] = c[0];
|
||||
coeffs[i+3] = c[1];
|
||||
coeffs[i+blueIdx*3] = c[2];
|
||||
}
|
||||
|
||||
softfloat d = softfloat(whitept[0]) +
|
||||
softfloat(whitept[1])*softfloat(15) +
|
||||
softfloat(whitept[2])*softfloat(3);
|
||||
softfloat d = whitePt[0] +
|
||||
whitePt[1]*softdouble(15) +
|
||||
whitePt[2]*softdouble(3);
|
||||
d = softfloat::one()/max(d, softfloat(FLT_EPSILON));
|
||||
un = softfloat(4*13)*d*softfloat(whitept[0]);
|
||||
vn = softfloat(9*13)*d*softfloat(whitept[1]);
|
||||
un = softfloat(4*13)*d*whitePt[0];
|
||||
vn = softfloat(9*13)*d*whitePt[1];
|
||||
#if CV_SSE2
|
||||
haveSIMD = checkHardwareSupport(CV_CPU_SSE2);
|
||||
#endif
|
||||
|
||||
CV_Assert(whitept[1] == 1.f);
|
||||
CV_Assert(whitePt[1] == softdouble::one());
|
||||
}
|
||||
|
||||
#if CV_SSE2
|
||||
@@ -7876,6 +8010,102 @@ struct Luv2RGB_f
|
||||
#endif
|
||||
};
|
||||
|
||||
struct RGB2Luvinterpolate
|
||||
{
|
||||
typedef uchar channel_type;
|
||||
|
||||
RGB2Luvinterpolate( int _srccn, int _blueIdx, const float* /* _coeffs */,
|
||||
const float* /* _whitept */, bool /*_srgb*/ )
|
||||
: srccn(_srccn), blueIdx(_blueIdx)
|
||||
{
|
||||
initLabTabs();
|
||||
}
|
||||
|
||||
void operator()(const uchar* src, uchar* dst, int n) const
|
||||
{
|
||||
int i, scn = srccn, bIdx = blueIdx;
|
||||
|
||||
i = 0; n *= 3;
|
||||
if(enablePackedRGB2Luv)
|
||||
{
|
||||
static const int nPixels = 8*2;
|
||||
for(; i < n - 3*nPixels; i += 3*nPixels, src += scn*nPixels)
|
||||
{
|
||||
/*
|
||||
int R = src[bIdx], G = src[1], B = src[bIdx^2];
|
||||
*/
|
||||
v_uint8x16 r16, g16, b16, dummy16;
|
||||
if(scn == 3)
|
||||
{
|
||||
v_load_deinterleave(src, r16, g16, b16);
|
||||
}
|
||||
else // scn == 4
|
||||
{
|
||||
v_load_deinterleave(src, r16, g16, b16, dummy16);
|
||||
}
|
||||
|
||||
if(bIdx)
|
||||
{
|
||||
dummy16 = r16; r16 = b16; b16 = dummy16;
|
||||
}
|
||||
|
||||
/*
|
||||
static const int baseDiv = LAB_BASE/256;
|
||||
R = R*baseDiv, G = G*baseDiv, B = B*baseDiv;
|
||||
*/
|
||||
v_uint16x8 r80, r81, g80, g81, b80, b81;
|
||||
v_expand(r16, r80, r81);
|
||||
v_expand(g16, g80, g81);
|
||||
v_expand(b16, b80, b81);
|
||||
r80 = r80 << (lab_base_shift - 8); r81 = r81 << (lab_base_shift - 8);
|
||||
g80 = g80 << (lab_base_shift - 8); g81 = g81 << (lab_base_shift - 8);
|
||||
b80 = b80 << (lab_base_shift - 8); b81 = b81 << (lab_base_shift - 8);
|
||||
|
||||
/*
|
||||
int L, u, v;
|
||||
trilinearInterpolate(R, G, B, RGB2LuvLUT_s16, L, u, v);
|
||||
*/
|
||||
v_uint16x8 l80, u80, v80, l81, u81, v81;
|
||||
trilinearPackedInterpolate(r80, g80, b80, RGB2LuvLUT_s16, l80, u80, v80);
|
||||
trilinearPackedInterpolate(r81, g81, b81, RGB2LuvLUT_s16, l81, u81, v81);
|
||||
|
||||
/*
|
||||
dst[i] = saturate_cast<uchar>(L/baseDiv);
|
||||
dst[i+1] = saturate_cast<uchar>(u/baseDiv);
|
||||
dst[i+2] = saturate_cast<uchar>(v/baseDiv);
|
||||
*/
|
||||
l80 = l80 >> (lab_base_shift - 8); l81 = l81 >> (lab_base_shift - 8);
|
||||
u80 = u80 >> (lab_base_shift - 8); u81 = u81 >> (lab_base_shift - 8);
|
||||
v80 = v80 >> (lab_base_shift - 8); v81 = v81 >> (lab_base_shift - 8);
|
||||
v_uint8x16 l16 = v_pack(l80, l81);
|
||||
v_uint8x16 u16 = v_pack(u80, u81);
|
||||
v_uint8x16 v16 = v_pack(v80, v81);
|
||||
v_store_interleave(dst + i, l16, u16, v16);
|
||||
}
|
||||
}
|
||||
|
||||
for(; i < n; i += 3, src += scn)
|
||||
{
|
||||
int R = src[bIdx], G = src[1], B = src[bIdx^2];
|
||||
|
||||
// (LAB_BASE/255) gives more accuracy but not very much
|
||||
static const int baseDiv = LAB_BASE/256;
|
||||
R = R*baseDiv, G = G*baseDiv, B = B*baseDiv;
|
||||
|
||||
int L, u, v;
|
||||
trilinearInterpolate(R, G, B, RGB2LuvLUT_s16, L, u, v);
|
||||
|
||||
dst[i] = saturate_cast<uchar>(L/baseDiv);
|
||||
dst[i+1] = saturate_cast<uchar>(u/baseDiv);
|
||||
dst[i+2] = saturate_cast<uchar>(v/baseDiv);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int srccn;
|
||||
int blueIdx;
|
||||
};
|
||||
|
||||
|
||||
struct RGB2Luv_b
|
||||
{
|
||||
@@ -7883,21 +8113,26 @@ struct RGB2Luv_b
|
||||
|
||||
RGB2Luv_b( int _srccn, int blueIdx, const float* _coeffs,
|
||||
const float* _whitept, bool _srgb )
|
||||
: srccn(_srccn), cvt(3, blueIdx, _coeffs, _whitept, _srgb)
|
||||
: srccn(_srccn),
|
||||
fcvt(3, blueIdx, _coeffs, _whitept, _srgb),
|
||||
icvt(_srccn, blueIdx, _coeffs, _whitept, _srgb)
|
||||
{
|
||||
//0.72033 = 255/(220+134), 96.525 = 134*255/(220+134)
|
||||
//0.9732 = 255/(140+122), 136.259 = 140*255/(140+122)
|
||||
useInterpolation = (!_coeffs && !_whitept && _srgb
|
||||
&& enableBitExactness
|
||||
&& enableRGB2LuvInterpolation);
|
||||
|
||||
static const softfloat f255(255);
|
||||
#if CV_NEON
|
||||
v_scale_inv = vdupq_n_f32(1.f/255.f);
|
||||
v_scale = vdupq_n_f32(2.55f);
|
||||
v_coeff1 = vdupq_n_f32(0.72033898305084743f);
|
||||
v_coeff2 = vdupq_n_f32(96.525423728813564f);
|
||||
v_coeff3 = vdupq_n_f32(0.9732824427480916f);
|
||||
v_coeff4 = vdupq_n_f32(136.259541984732824f);
|
||||
v_scale_inv = vdupq_n_f32(softfloat::one()/f255);
|
||||
v_scale = vdupq_n_f32(f255/softfloat(100));
|
||||
v_coeff1 = vdupq_n_f32(f255/uRange);
|
||||
v_coeff2 = vdupq_n_f32(-uLow*f255/uRange);
|
||||
v_coeff3 = vdupq_n_f32(f255/vRange);
|
||||
v_coeff4 = vdupq_n_f32(-vLow*f255/vRange);
|
||||
v_alpha = vdup_n_u8(ColorChannel<uchar>::max());
|
||||
#elif CV_SSE2
|
||||
v_zero = _mm_setzero_si128();
|
||||
v_scale_inv = _mm_set1_ps(1.f/255.f);
|
||||
v_scale_inv = _mm_set1_ps(softfloat::one()/f255);
|
||||
haveSIMD = checkHardwareSupport(CV_CPU_SSE2);
|
||||
#endif
|
||||
}
|
||||
@@ -7930,12 +8165,19 @@ struct RGB2Luv_b
|
||||
|
||||
void operator()(const uchar* src, uchar* dst, int n) const
|
||||
{
|
||||
if(useInterpolation)
|
||||
{
|
||||
icvt(src, dst, n);
|
||||
return;
|
||||
}
|
||||
|
||||
int i, j, scn = srccn;
|
||||
float CV_DECL_ALIGNED(16) buf[3*BLOCK_SIZE];
|
||||
|
||||
static const softfloat f255(255);
|
||||
#if CV_SSE2
|
||||
__m128 v_coeffs = _mm_set_ps(2.55f, 0.9732824427480916f, 0.72033898305084743f, 2.55f);
|
||||
__m128 v_res = _mm_set_ps(0.f, 136.259541984732824f, 96.525423728813564f, 0.f);
|
||||
__m128 v_coeffs = _mm_set_ps(f255/softfloat(100), f255/vRange, f255/uRange, f255/softfloat(100));
|
||||
__m128 v_res = _mm_set_ps(0.f, -vLow*f255/vRange, -uLow*f255/uRange, 0.f);
|
||||
#endif
|
||||
|
||||
for( i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE*3 )
|
||||
@@ -8015,13 +8257,14 @@ struct RGB2Luv_b
|
||||
src -= jr, j -= jr;
|
||||
}
|
||||
#endif
|
||||
static const softfloat f255inv = softfloat::one()/f255;
|
||||
for( ; j < dn*3; j += 3, src += scn )
|
||||
{
|
||||
buf[j] = src[0]*(1.f/255.f);
|
||||
buf[j+1] = (float)(src[1]*(1.f/255.f));
|
||||
buf[j+2] = (float)(src[2]*(1.f/255.f));
|
||||
buf[j ] = (float)(src[0]*((float)f255inv));
|
||||
buf[j+1] = (float)(src[1]*((float)f255inv));
|
||||
buf[j+2] = (float)(src[2]*((float)f255inv));
|
||||
}
|
||||
cvt(buf, buf, dn);
|
||||
fcvt(buf, buf, dn);
|
||||
|
||||
j = 0;
|
||||
#if CV_NEON
|
||||
@@ -8056,17 +8299,23 @@ struct RGB2Luv_b
|
||||
}
|
||||
#endif
|
||||
|
||||
static const softfloat fL = f255/softfloat(100);
|
||||
static const softfloat fu = f255/uRange;
|
||||
static const softfloat fv = f255/vRange;
|
||||
static const softfloat su = -uLow*f255/uRange;
|
||||
static const softfloat sv = -vLow*f255/vRange;
|
||||
for( ; j < dn*3; j += 3 )
|
||||
{
|
||||
dst[j] = saturate_cast<uchar>(buf[j]*2.55f);
|
||||
dst[j+1] = saturate_cast<uchar>(buf[j+1]*0.72033898305084743f + 96.525423728813564f);
|
||||
dst[j+2] = saturate_cast<uchar>(buf[j+2]*0.9732824427480916f + 136.259541984732824f);
|
||||
dst[j] = saturate_cast<uchar>(buf[j]*(float)fL);
|
||||
dst[j+1] = saturate_cast<uchar>(buf[j+1]*(float)fu + (float)su);
|
||||
dst[j+2] = saturate_cast<uchar>(buf[j+2]*(float)fv + (float)sv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int srccn;
|
||||
RGB2Luv_f cvt;
|
||||
RGB2Luvfloat fcvt;
|
||||
RGB2Luvinterpolate icvt;
|
||||
|
||||
#if CV_NEON
|
||||
float32x4_t v_scale, v_scale_inv, v_coeff1, v_coeff2, v_coeff3, v_coeff4;
|
||||
@@ -8076,6 +8325,7 @@ struct RGB2Luv_b
|
||||
__m128i v_zero;
|
||||
bool haveSIMD;
|
||||
#endif
|
||||
bool useInterpolation;
|
||||
};
|
||||
|
||||
|
||||
@@ -8316,6 +8566,7 @@ struct Luv2RGB_b
|
||||
#endif
|
||||
};
|
||||
|
||||
#undef clip
|
||||
|
||||
///////////////////////////////////// YUV420 -> RGB /////////////////////////////////////
|
||||
|
||||
@@ -9407,13 +9658,12 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
|
||||
{
|
||||
int coeffs[9];
|
||||
const float * const _coeffs = sRGB2XYZ_D65, * const _whitept = D65;
|
||||
static const softfloat lshift(1 << lab_shift);
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
coeffs[i*3+(bidx^2)] = cvRound(lshift*softfloat(_coeffs[i*3 ])/softfloat(_whitept[i]));
|
||||
coeffs[i*3+1] = cvRound(lshift*softfloat(_coeffs[i*3+1])/softfloat(_whitept[i]));
|
||||
coeffs[i*3+bidx] = cvRound(lshift*softfloat(_coeffs[i*3+2])/softfloat(_whitept[i]));
|
||||
coeffs[i*3+(bidx^2)] = cvRound(lshift*sRGB2XYZ_D65[i*3 ]/D65[i]);
|
||||
coeffs[i*3+1] = cvRound(lshift*sRGB2XYZ_D65[i*3+1]/D65[i]);
|
||||
coeffs[i*3+bidx] = cvRound(lshift*sRGB2XYZ_D65[i*3+2]/D65[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] < 2*(1 << lab_shift));
|
||||
@@ -9440,19 +9690,21 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
|
||||
{
|
||||
float coeffs[9];
|
||||
const float * const _coeffs = sRGB2XYZ_D65, * const _whitept = D65;
|
||||
softdouble whitePt[3];
|
||||
for(int i = 0; i < 3; i++)
|
||||
whitePt[i] = D65[i];
|
||||
|
||||
softfloat scale[] = { softfloat::one() / softfloat(_whitept[0]),
|
||||
softfloat::one(),
|
||||
softfloat::one() / softfloat(_whitept[2]) };
|
||||
softdouble scale[] = { softdouble::one() / whitePt[0],
|
||||
softdouble::one(),
|
||||
softdouble::one() / whitePt[2] };
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
int j = i * 3;
|
||||
|
||||
softfloat c0 = (lab ? scale[i] : softfloat::one()) * softfloat(_coeffs[j ]);
|
||||
softfloat c1 = (lab ? scale[i] : softfloat::one()) * softfloat(_coeffs[j + 1]);
|
||||
softfloat c2 = (lab ? scale[i] : softfloat::one()) * softfloat(_coeffs[j + 2]);
|
||||
softfloat c0 = (lab ? scale[i] : softdouble::one()) * sRGB2XYZ_D65[j ];
|
||||
softfloat c1 = (lab ? scale[i] : softdouble::one()) * sRGB2XYZ_D65[j + 1];
|
||||
softfloat c2 = (lab ? scale[i] : softdouble::one()) * sRGB2XYZ_D65[j + 2];
|
||||
|
||||
coeffs[j + (bidx ^ 2)] = c0;
|
||||
coeffs[j + 1] = c1;
|
||||
@@ -9462,12 +9714,12 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
c0 + c1 + c2 < (lab ? softfloat((int)LAB_CBRT_TAB_SIZE) : softfloat(3)/softfloat(2)));
|
||||
}
|
||||
|
||||
softfloat d = softfloat(_whitept[0]) +
|
||||
softfloat(_whitept[1])*softfloat(15) +
|
||||
softfloat(_whitept[2])*softfloat(3);
|
||||
softfloat d = whitePt[0] +
|
||||
whitePt[1]*softdouble(15) +
|
||||
whitePt[2]*softdouble(3);
|
||||
d = softfloat::one()/max(d, softfloat(FLT_EPSILON));
|
||||
un = d*softfloat(13*4)*softfloat(_whitept[0]);
|
||||
vn = d*softfloat(13*9)*softfloat(_whitept[1]);
|
||||
un = d*softfloat(13*4)*whitePt[0];
|
||||
vn = d*softfloat(13*9)*whitePt[1];
|
||||
|
||||
Mat(1, 9, CV_32FC1, coeffs).copyTo(ucoeffs);
|
||||
}
|
||||
@@ -9524,21 +9776,23 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
|
||||
{
|
||||
float coeffs[9];
|
||||
const float * const _coeffs = XYZ2sRGB_D65, * const _whitept = D65;
|
||||
softdouble whitePt[3];
|
||||
for(int i = 0; i < 3; i++)
|
||||
whitePt[i] = D65[i];
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
coeffs[i+(bidx^2)*3] = softfloat(_coeffs[i] )*softfloat(lab ? _whitept[i] : 1);
|
||||
coeffs[i+3] = softfloat(_coeffs[i+3])*softfloat(lab ? _whitept[i] : 1);
|
||||
coeffs[i+bidx*3] = softfloat(_coeffs[i+6])*softfloat(lab ? _whitept[i] : 1);
|
||||
coeffs[i+(bidx^2)*3] = (float)(XYZ2sRGB_D65[i ]*(lab ? whitePt[i] : softdouble::one()));
|
||||
coeffs[i+3] = (float)(XYZ2sRGB_D65[i+3]*(lab ? whitePt[i] : softdouble::one()));
|
||||
coeffs[i+bidx*3] = (float)(XYZ2sRGB_D65[i+6]*(lab ? whitePt[i] : softdouble::one()));
|
||||
}
|
||||
|
||||
softfloat d = softfloat(_whitept[0]) +
|
||||
softfloat(_whitept[1])*softfloat(15) +
|
||||
softfloat(_whitept[2])*softfloat(3);
|
||||
softfloat d = whitePt[0] +
|
||||
whitePt[1]*softdouble(15) +
|
||||
whitePt[2]*softdouble(3);
|
||||
d = softfloat::one()/max(d, softfloat(FLT_EPSILON));
|
||||
un = softfloat(4*13)*d*softfloat(_whitept[0]);
|
||||
vn = softfloat(9*13)*d*softfloat(_whitept[1]);
|
||||
un = softfloat(4*13)*d*whitePt[0];
|
||||
vn = softfloat(9*13)*d*whitePt[1];
|
||||
|
||||
Mat(1, 9, CV_32FC1, coeffs).copyTo(ucoeffs);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user