Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
822d33d6
Commit
822d33d6
authored
Sep 13, 2017
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #9374 from savuor:test_lab_bit_exact
parents
31348f8c
18ca3d1e
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
579 additions
and
99 deletions
+579
-99
color.cpp
modules/imgproc/src/color.cpp
+5
-5
test_color.cpp
modules/imgproc/test/test_color.cpp
+573
-94
test_precomp.hpp
modules/imgproc/test/test_precomp.hpp
+1
-0
No files found.
modules/imgproc/src/color.cpp
View file @
822d33d6
...
...
@@ -6771,7 +6771,10 @@ struct Lab2RGBinteger
//float fxz[] = { ai / 500.0f + fy, fy - bi / 200.0f };
int
adiv
,
bdiv
;
adiv
=
aa
*
BASE
/
500
-
128
*
BASE
/
500
,
bdiv
=
bb
*
BASE
/
200
-
128
*
BASE
/
200
;
//adiv = aa*BASE/500 - 128*BASE/500, bdiv = bb*BASE/200 - 128*BASE/200;
//approximations with reasonable precision
adiv
=
((
5
*
aa
*
53687
+
(
1
<<
7
))
>>
13
)
-
128
*
BASE
/
500
;
bdiv
=
((
bb
*
41943
+
(
1
<<
4
))
>>
9
)
-
128
*
BASE
/
200
+
1
;
int
ifxz
[]
=
{
ify
+
adiv
,
ify
-
bdiv
};
...
...
@@ -7104,8 +7107,6 @@ struct Lab2RGB_b
const
float
*
_whitept
,
bool
_srgb
)
:
fcvt
(
3
,
_blueIdx
,
_coeffs
,
_whitept
,
_srgb
),
icvt
(
_dstcn
,
_blueIdx
,
_coeffs
,
_whitept
,
_srgb
),
dstcn
(
_dstcn
)
{
useBitExactness
=
(
!
_coeffs
&&
!
_whitept
&&
_srgb
&&
enableBitExactness
);
#if CV_NEON
v_scale_inv
=
vdupq_n_f32
(
100.
f
/
255.
f
);
v_scale
=
vdupq_n_f32
(
255.
f
);
...
...
@@ -7162,7 +7163,7 @@ struct Lab2RGB_b
void
operator
()(
const
uchar
*
src
,
uchar
*
dst
,
int
n
)
const
{
if
(
us
eBitExactness
)
if
(
enabl
eBitExactness
)
{
icvt
(
src
,
dst
,
n
);
return
;
...
...
@@ -7328,7 +7329,6 @@ struct Lab2RGB_b
__m128i
v_zero
;
bool
haveSIMD
;
#endif
bool
useBitExactness
;
int
dstcn
;
};
...
...
modules/imgproc/test/test_color.cpp
View file @
822d33d6
...
...
@@ -79,6 +79,7 @@ protected:
int
fwd_code
,
inv_code
;
bool
test_cpp
;
int
hue_range
;
bool
srgb
;
};
...
...
@@ -100,6 +101,7 @@ CV_ColorCvtBaseTest::CV_ColorCvtBaseTest( bool _custom_inv_transform, bool _allo
test_cpp
=
false
;
hue_range
=
0
;
blue_idx
=
0
;
srgb
=
false
;
inplace
=
false
;
}
...
...
@@ -138,6 +140,7 @@ void CV_ColorCvtBaseTest::get_test_array_types_and_sizes( int test_case_idx,
cn
=
(
cvtest
::
randInt
(
rng
)
&
1
)
+
3
;
blue_idx
=
cvtest
::
randInt
(
rng
)
&
1
?
2
:
0
;
srgb
=
(
cvtest
::
randInt
(
rng
)
&
1
)
!=
0
;
types
[
INPUT
][
0
]
=
CV_MAKETYPE
(
depth
,
cn
);
types
[
OUTPUT
][
0
]
=
types
[
REF_OUTPUT
][
0
]
=
CV_MAKETYPE
(
depth
,
3
);
...
...
@@ -866,24 +869,42 @@ void CV_ColorHLSTest::convert_row_abc2bgr_32f_c3( const float* src_row, float* d
}
}
static
const
double
RGB2XYZ
[]
=
{
0.412453
,
0.357580
,
0.180423
,
0.212671
,
0.715160
,
0.072169
,
0.019334
,
0.119193
,
0.950227
// 0.412453, 0.357580, 0.180423,
// 0.212671, 0.715160, 0.072169,
// 0.019334, 0.119193, 0.950227
static
const
softdouble
RGB2XYZ
[]
=
{
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
double
XYZ2RGB
[]
=
{
3.240479
,
-
1.53715
,
-
0.498535
,
-
0.969256
,
1.875991
,
0.041556
,
0.055648
,
-
0.204043
,
1.057311
// 3.240479, -1.53715, -0.498535,
// -0.969256, 1.875991, 0.041556,
// 0.055648, -0.204043, 1.057311
static
const
softdouble
XYZ2RGB
[]
=
{
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
)
};
static
const
float
Xn
=
0.950456
f
;
static
const
float
Zn
=
1.088754
f
;
//0.950456
static
const
softdouble
Xn
=
softdouble
::
fromRaw
(
0x3fee6a22b3892ee8
);
//1.088754
static
const
softdouble
Zn
=
softdouble
::
fromRaw
(
0x3ff16b8950763a19
);
//// rgb <=> xyz
...
...
@@ -926,12 +947,13 @@ double CV_ColorXYZTest::get_success_error_level( int /*test_case_idx*/, int i, i
void
CV_ColorXYZTest
::
convert_row_bgr2abc_32f_c3
(
const
float
*
src_row
,
float
*
dst_row
,
int
n
)
{
int
depth
=
test_mat
[
INPUT
][
0
].
depth
();
double
scale
=
depth
==
CV_8U
?
255
:
depth
==
CV_16U
?
65535
:
1
;
softdouble
scale
(
depth
==
CV_8U
?
255
:
depth
==
CV_16U
?
65535
:
1
);
double
M
[
9
];
int
j
;
for
(
j
=
0
;
j
<
9
;
j
++
)
M
[
j
]
=
RGB2XYZ
[
j
]
*
scale
;
M
[
j
]
=
(
double
)(
RGB2XYZ
[
j
]
*
scale
)
;
for
(
j
=
0
;
j
<
n
*
3
;
j
+=
3
)
{
...
...
@@ -951,12 +973,13 @@ void CV_ColorXYZTest::convert_row_bgr2abc_32f_c3( const float* src_row, float* d
void
CV_ColorXYZTest
::
convert_row_abc2bgr_32f_c3
(
const
float
*
src_row
,
float
*
dst_row
,
int
n
)
{
int
depth
=
test_mat
[
INPUT
][
0
].
depth
();
double
scale
=
depth
==
CV_8U
?
1.
/
255
:
depth
==
CV_16U
?
1.
/
65535
:
1
;
softdouble
scale
(
depth
==
CV_8U
?
1.
/
255
:
depth
==
CV_16U
?
1.
/
65535
:
1
);
double
M
[
9
];
int
j
;
for
(
j
=
0
;
j
<
9
;
j
++
)
M
[
j
]
=
XYZ2RGB
[
j
]
*
scale
;
M
[
j
]
=
(
double
)(
XYZ2RGB
[
j
]
*
scale
)
;
for
(
j
=
0
;
j
<
n
*
3
;
j
+=
3
)
{
...
...
@@ -974,6 +997,44 @@ void CV_ColorXYZTest::convert_row_abc2bgr_32f_c3( const float* src_row, float* d
//// rgb <=> L*a*b*
//taken from color.cpp
//all constants should be presented through integers to keep bit-exactness
static
const
softdouble
gammaThreshold
=
softdouble
(
809
)
/
softdouble
(
20000
);
// 0.04045
static
const
softdouble
gammaInvThreshold
=
softdouble
(
7827
)
/
softdouble
(
2500000
);
// 0.0031308
static
const
softdouble
gammaLowScale
=
softdouble
(
323
)
/
softdouble
(
25
);
// 12.92
static
const
softdouble
gammaPower
=
softdouble
(
12
)
/
softdouble
(
5
);
// 2.4
static
const
softdouble
gammaXshift
=
softdouble
(
11
)
/
softdouble
(
200
);
// 0.055
static
inline
softfloat
applyGamma
(
softfloat
x
)
{
//return x <= 0.04045f ? x*(1.f/12.92f) : (float)std::pow((double)(x + 0.055)*(1./1.055), 2.4);
softdouble
xd
=
x
;
return
(
xd
<=
gammaThreshold
?
xd
/
gammaLowScale
:
pow
((
xd
+
gammaXshift
)
/
(
softdouble
::
one
()
+
gammaXshift
),
gammaPower
));
}
static
inline
softfloat
applyInvGamma
(
softfloat
x
)
{
//return x <= 0.0031308 ? x*12.92f : (float)(1.055*std::pow((double)x, 1./2.4) - 0.055);
softdouble
xd
=
x
;
return
(
xd
<=
gammaInvThreshold
?
xd
*
gammaLowScale
:
pow
(
xd
,
softdouble
::
one
()
/
gammaPower
)
*
(
softdouble
::
one
()
+
gammaXshift
)
-
gammaXshift
);
}
static
inline
float
applyGamma
(
float
x
)
{
return
x
<=
0.04045
f
?
x
*
(
1.
f
/
12.92
f
)
:
(
float
)
std
::
pow
((
double
)(
x
+
0.055
)
*
(
1.
/
1.055
),
2.4
);
}
static
inline
float
applyInvGamma
(
float
x
)
{
return
x
<=
0.0031308
?
x
*
12.92
f
:
(
float
)(
1.055
*
std
::
pow
((
double
)
x
,
1.
/
2.4
)
-
0.055
);
}
class
CV_ColorLabTest
:
public
CV_ColorCvtBaseTest
{
public
:
...
...
@@ -996,24 +1057,33 @@ void CV_ColorLabTest::get_test_array_types_and_sizes( int test_case_idx, vector<
{
CV_ColorCvtBaseTest
::
get_test_array_types_and_sizes
(
test_case_idx
,
sizes
,
types
);
if
(
blue_idx
==
0
)
fwd_code
=
CV_LBGR2Lab
,
inv_code
=
CV_Lab2LBGR
;
if
(
srgb
)
{
if
(
blue_idx
==
0
)
fwd_code
=
CV_BGR2Lab
,
inv_code
=
CV_Lab2BGR
;
else
fwd_code
=
CV_RGB2Lab
,
inv_code
=
CV_Lab2RGB
;
}
else
fwd_code
=
CV_LRGB2Lab
,
inv_code
=
CV_Lab2LRGB
;
{
if
(
blue_idx
==
0
)
fwd_code
=
CV_LBGR2Lab
,
inv_code
=
CV_Lab2LBGR
;
else
fwd_code
=
CV_LRGB2Lab
,
inv_code
=
CV_Lab2LRGB
;
}
}
double
CV_ColorLabTest
::
get_success_error_level
(
int
/*test_case_idx*/
,
int
i
,
int
j
)
{
int
depth
=
test_mat
[
i
][
j
].
depth
();
return
depth
==
CV_8U
?
16
:
depth
==
CV_16U
?
32
:
1e-3
;
// j == 0 is for forward code, j == 1 is for inverse code
return
(
depth
==
CV_8U
)
?
(
srgb
?
32
:
8
)
:
//(depth == CV_16U) ? 32 : // 16u is disabled
srgb
?
((
j
==
0
)
?
0.4
:
0.0055
)
:
1e-3
;
}
static
const
double
_1_3
=
0.333333333333
;
const
static
float
_1_3f
=
static_cast
<
float
>
(
_1_3
);
void
CV_ColorLabTest
::
convert_row_bgr2abc_32f_c3
(
const
float
*
src_row
,
float
*
dst_row
,
int
n
)
{
int
depth
=
test_mat
[
INPUT
][
0
].
depth
();
...
...
@@ -1021,35 +1091,44 @@ void CV_ColorLabTest::convert_row_bgr2abc_32f_c3(const float* src_row, float* ds
float
ab_bias
=
depth
==
CV_8U
?
128.
f
:
depth
==
CV_16U
?
32768.
f
:
0.
f
;
float
M
[
9
];
// 7.787f = (29/3)^3/(29*4)
static
const
float
lowScale
=
29.
f
*
29.
f
/
(
27.
f
*
4.
f
);
// 0.008856f = (6/29)^3
static
const
float
lthresh
=
6.
f
*
6.
f
*
6.
f
/
(
29.
f
*
29.
f
*
29.
f
);
// 903.3 = (29/3)^3
static
const
float
yscale
=
29.
f
*
29.
f
*
29.
f
/
27.
f
;
static
const
float
f16of116
=
16.
f
/
116.
f
;
for
(
int
j
=
0
;
j
<
9
;
j
++
)
M
[
j
]
=
(
float
)
RGB2XYZ
[
j
];
float
xn
=
(
float
)
Xn
,
zn
=
(
float
)
Zn
;
for
(
int
x
=
0
;
x
<
n
*
3
;
x
+=
3
)
{
float
R
=
src_row
[
x
+
2
];
float
G
=
src_row
[
x
+
1
];
float
B
=
src_row
[
x
];
float
X
=
(
R
*
M
[
0
]
+
G
*
M
[
1
]
+
B
*
M
[
2
])
/
Xn
;
float
Y
=
R
*
M
[
3
]
+
G
*
M
[
4
]
+
B
*
M
[
5
];
float
Z
=
(
R
*
M
[
6
]
+
G
*
M
[
7
]
+
B
*
M
[
8
])
/
Zn
;
float
fX
=
X
>
0.008856
f
?
pow
(
X
,
_1_3f
)
:
(
7.787
f
*
X
+
16.
f
/
116.
f
);
float
fZ
=
Z
>
0.008856
f
?
pow
(
Z
,
_1_3f
)
:
(
7.787
f
*
Z
+
16.
f
/
116.
f
);
float
L
=
0.0
f
,
fY
=
0.0
f
;
if
(
Y
>
0.008856
f
)
{
fY
=
pow
(
Y
,
_1_3f
);
L
=
116.
f
*
fY
-
16.
f
;
}
else
R
=
std
::
min
(
std
::
max
(
R
,
0.
f
),
1.
f
);
G
=
std
::
min
(
std
::
max
(
G
,
0.
f
),
1.
f
);
B
=
std
::
min
(
std
::
max
(
B
,
0.
f
),
1.
f
);
if
(
srgb
)
{
fY
=
7.787
f
*
Y
+
16.
f
/
116.
f
;
L
=
903.3
f
*
Y
;
R
=
applyGamma
(
R
);
G
=
applyGamma
(
G
);
B
=
applyGamma
(
B
);
}
float
X
=
(
R
*
M
[
0
]
+
G
*
M
[
1
]
+
B
*
M
[
2
])
/
xn
;
float
Y
=
R
*
M
[
3
]
+
G
*
M
[
4
]
+
B
*
M
[
5
];
float
Z
=
(
R
*
M
[
6
]
+
G
*
M
[
7
]
+
B
*
M
[
8
])
/
zn
;
float
fX
=
X
>
lthresh
?
cubeRoot
(
X
)
:
(
lowScale
*
X
+
f16of116
);
float
fY
=
Y
>
lthresh
?
cubeRoot
(
Y
)
:
(
lowScale
*
Y
+
f16of116
);
float
fZ
=
Z
>
lthresh
?
cubeRoot
(
Z
)
:
(
lowScale
*
Z
+
f16of116
);
float
L
=
Y
>
lthresh
?
(
116.
f
*
fY
-
16.
f
)
:
(
yscale
*
Y
);
float
a
=
500.
f
*
(
fX
-
fY
);
float
b
=
200.
f
*
(
fY
-
fZ
);
...
...
@@ -1059,6 +1138,7 @@ void CV_ColorLabTest::convert_row_bgr2abc_32f_c3(const float* src_row, float* ds
}
}
void
CV_ColorLabTest
::
convert_row_abc2bgr_32f_c3
(
const
float
*
src_row
,
float
*
dst_row
,
int
n
)
{
int
depth
=
test_mat
[
INPUT
][
0
].
depth
();
...
...
@@ -1069,8 +1149,17 @@ void CV_ColorLabTest::convert_row_abc2bgr_32f_c3( const float* src_row, float* d
for
(
int
j
=
0
;
j
<
9
;
j
++
)
M
[
j
]
=
(
float
)
XYZ2RGB
[
j
];
static
const
float
lthresh
=
903.3
f
*
0.008856
f
;
static
const
float
thresh
=
7.787
f
*
0.008856
f
+
16.0
f
/
116.0
f
;
// 0.008856f * 903.3f = (6/29)^3*(29/3)^3 = 8
static
const
float
lThresh
=
8.
f
;
// 7.787f * 0.008856f + 16.0f / 116.0f = 6/29
static
const
float
fThresh
=
6.
f
/
29.
f
;
static
const
float
lbias
=
16.
f
/
116.
f
;
// 7.787f = (29/3)^3/(29*4)
static
const
float
lowScale
=
29.
f
*
29.
f
/
(
27.
f
*
4.
f
);
// 903.3 = (29/3)^3
static
const
float
yscale
=
29.
f
*
29.
f
*
29.
f
/
27.
f
;
float
xn
=
(
float
)
Xn
,
zn
=
(
float
)
Zn
;
for
(
int
x
=
0
,
end
=
n
*
3
;
x
<
end
;
x
+=
3
)
{
float
L
=
src_row
[
x
]
*
Lscale
;
...
...
@@ -1078,10 +1167,10 @@ void CV_ColorLabTest::convert_row_abc2bgr_32f_c3( const float* src_row, float* d
float
b
=
src_row
[
x
+
2
]
-
ab_bias
;
float
FY
=
0.0
f
,
Y
=
0.0
f
;
if
(
L
<=
l
t
hresh
)
if
(
L
<=
l
T
hresh
)
{
Y
=
L
/
903.3
f
;
FY
=
7.787
f
*
Y
+
16.0
f
/
116.0
f
;
Y
=
L
/
yscale
;
FY
=
lowScale
*
Y
+
lbias
;
}
else
{
...
...
@@ -1095,18 +1184,28 @@ void CV_ColorLabTest::convert_row_abc2bgr_32f_c3( const float* src_row, float* d
float
FXZ
[]
=
{
FX
,
FZ
};
for
(
int
k
=
0
;
k
<
2
;
++
k
)
{
if
(
FXZ
[
k
]
<=
t
hresh
)
FXZ
[
k
]
=
(
FXZ
[
k
]
-
16.0
f
/
116.0
f
)
/
7.787
f
;
if
(
FXZ
[
k
]
<=
fT
hresh
)
FXZ
[
k
]
=
(
FXZ
[
k
]
-
lbias
)
/
lowScale
;
else
FXZ
[
k
]
=
FXZ
[
k
]
*
FXZ
[
k
]
*
FXZ
[
k
];
}
float
X
=
FXZ
[
0
]
*
X
n
;
float
Z
=
FXZ
[
1
]
*
Z
n
;
float
X
=
FXZ
[
0
]
*
x
n
;
float
Z
=
FXZ
[
1
]
*
z
n
;
float
R
=
M
[
0
]
*
X
+
M
[
1
]
*
Y
+
M
[
2
]
*
Z
;
float
G
=
M
[
3
]
*
X
+
M
[
4
]
*
Y
+
M
[
5
]
*
Z
;
float
B
=
M
[
6
]
*
X
+
M
[
7
]
*
Y
+
M
[
8
]
*
Z
;
R
=
std
::
min
(
std
::
max
(
R
,
0.
f
),
1.
f
);
G
=
std
::
min
(
std
::
max
(
G
,
0.
f
),
1.
f
);
B
=
std
::
min
(
std
::
max
(
B
,
0.
f
),
1.
f
);
if
(
srgb
)
{
R
=
applyInvGamma
(
R
);
G
=
applyInvGamma
(
G
);
B
=
applyInvGamma
(
B
);
}
dst_row
[
x
]
=
B
;
dst_row
[
x
+
1
]
=
G
;
dst_row
[
x
+
2
]
=
R
;
...
...
@@ -1137,10 +1236,20 @@ void CV_ColorLuvTest::get_test_array_types_and_sizes( int test_case_idx, vector<
{
CV_ColorCvtBaseTest
::
get_test_array_types_and_sizes
(
test_case_idx
,
sizes
,
types
);
if
(
blue_idx
==
0
)
fwd_code
=
CV_LBGR2Luv
,
inv_code
=
CV_Luv2LBGR
;
if
(
srgb
)
{
if
(
blue_idx
==
0
)
fwd_code
=
CV_BGR2Luv
,
inv_code
=
CV_Luv2BGR
;
else
fwd_code
=
CV_RGB2Luv
,
inv_code
=
CV_Luv2RGB
;
}
else
fwd_code
=
CV_LRGB2Luv
,
inv_code
=
CV_Luv2LRGB
;
{
if
(
blue_idx
==
0
)
fwd_code
=
CV_LBGR2Luv
,
inv_code
=
CV_Luv2LBGR
;
else
fwd_code
=
CV_LRGB2Luv
,
inv_code
=
CV_Luv2LRGB
;
}
}
...
...
@@ -1155,31 +1264,54 @@ void CV_ColorLuvTest::convert_row_bgr2abc_32f_c3( const float* src_row, float* d
{
int
depth
=
test_mat
[
INPUT
][
0
].
depth
();
float
Lscale
=
depth
==
CV_8U
?
255.
f
/
100.
f
:
depth
==
CV_16U
?
65535.
f
/
100.
f
:
1.
f
;
static
const
float
uLow
=
-
134.
f
,
uHigh
=
220.
f
,
uRange
=
uHigh
-
uLow
;
static
const
float
vLow
=
-
140.
f
,
vHigh
=
122.
f
,
vRange
=
vHigh
-
vLow
;
int
j
;
float
M
[
9
];
float
un
=
4.
f
*
Xn
/
(
Xn
+
15.
f
*
1.
f
+
3
*
Zn
);
float
vn
=
9.
f
*
1.
f
/
(
Xn
+
15.
f
*
1.
f
+
3
*
Zn
);
// Yn == 1
float
xn
=
(
float
)
Xn
,
zn
=
(
float
)
Zn
;
float
dd
=
xn
+
15.
f
*
1.
f
+
3.
f
*
zn
;
float
un
=
4.
f
*
13.
f
*
xn
/
dd
;
float
vn
=
9.
f
*
13.
f
/
dd
;
float
u_scale
=
1.
f
,
u_bias
=
0.
f
;
float
v_scale
=
1.
f
,
v_bias
=
0.
f
;
for
(
j
=
0
;
j
<
9
;
j
++
)
M
[
j
]
=
(
float
)
RGB2XYZ
[
j
];
//0.72033 = 255/(220+134), 96.525 = 134*255/(220+134)
//0.9732 = 255/(140+122), 136.259 = 140*255/(140+122)
if
(
depth
==
CV_8U
)
{
u_scale
=
0.720338983
f
;
u_bias
=
96.5254237
f
;
v_scale
=
0.973282442
f
;
v_bias
=
136.2595419
f
;
u_scale
=
255.
f
/
uRange
;
u_bias
=
-
uLow
*
255.
f
/
uRange
;
v_scale
=
255.
f
/
vRange
;
v_bias
=
-
vLow
*
255.
f
/
vRange
;
}
// 0.008856f = (6/29)^3
static
const
float
lthresh
=
6.
f
*
6.
f
*
6.
f
/
(
29.
f
*
29.
f
*
29.
f
);
// 903.3 = (29/3)^3
static
const
float
yscale
=
29.
f
*
29.
f
*
29.
f
/
27.
f
;
for
(
j
=
0
;
j
<
n
*
3
;
j
+=
3
)
{
float
r
=
src_row
[
j
+
2
];
float
g
=
src_row
[
j
+
1
];
float
b
=
src_row
[
j
];
r
=
std
::
min
(
std
::
max
(
r
,
0.
f
),
1.
f
);
g
=
std
::
min
(
std
::
max
(
g
,
0.
f
),
1.
f
);
b
=
std
::
min
(
std
::
max
(
b
,
0.
f
),
1.
f
);
if
(
srgb
)
{
r
=
applyGamma
(
r
);
g
=
applyGamma
(
g
);
b
=
applyGamma
(
b
);
}
float
X
=
r
*
M
[
0
]
+
g
*
M
[
1
]
+
b
*
M
[
2
];
float
Y
=
r
*
M
[
3
]
+
g
*
M
[
4
]
+
b
*
M
[
5
];
float
Z
=
r
*
M
[
6
]
+
g
*
M
[
7
]
+
b
*
M
[
8
];
...
...
@@ -1189,14 +1321,14 @@ void CV_ColorLuvTest::convert_row_bgr2abc_32f_c3( const float* src_row, float* d
L
=
u
=
v
=
0
;
else
{
if
(
Y
>
0.008856
f
)
L
=
(
float
)(
116.
*
pow
((
double
)
Y
,
_1_3
)
-
16.
)
;
if
(
Y
>
lthresh
)
L
=
116.
f
*
cubeRoot
(
Y
)
-
16.
f
;
else
L
=
903.3
f
*
Y
;
L
=
yscale
*
Y
;
d
=
1
.
f
/
d
;
u
=
13
*
L
*
(
4
*
X
*
d
-
un
);
v
=
13
*
L
*
(
9
*
Y
*
d
-
vn
);
d
=
4.
f
*
13
.
f
/
d
;
u
=
L
*
(
X
*
d
-
un
);
v
=
L
*
(
9.
f
/
4.
f
*
Y
*
d
-
vn
);
}
dst_row
[
j
]
=
L
*
Lscale
;
dst_row
[
j
+
1
]
=
u
*
u_scale
+
u_bias
;
...
...
@@ -1209,24 +1341,35 @@ void CV_ColorLuvTest::convert_row_abc2bgr_32f_c3( const float* src_row, float* d
{
int
depth
=
test_mat
[
INPUT
][
0
].
depth
();
float
Lscale
=
depth
==
CV_8U
?
100.
f
/
255.
f
:
depth
==
CV_16U
?
100.
f
/
65535.
f
:
1.
f
;
static
const
float
uLow
=
-
134.
f
,
uHigh
=
220.
f
,
uRange
=
uHigh
-
uLow
;
static
const
float
vLow
=
-
140.
f
,
vHigh
=
122.
f
,
vRange
=
vHigh
-
vLow
;
int
j
;
float
M
[
9
];
float
un
=
4.
f
*
Xn
/
(
Xn
+
15.
f
*
1.
f
+
3
*
Zn
);
float
vn
=
9.
f
*
1.
f
/
(
Xn
+
15.
f
*
1.
f
+
3
*
Zn
);
// Yn == 1
float
xn
=
(
float
)
Xn
,
zn
=
(
float
)
Zn
;
float
dd
=
xn
+
15.
f
*
1.
f
+
3.
f
*
zn
;
float
un
=
4
*
13.
f
*
xn
/
dd
;
float
vn
=
9
*
13.
f
*
1.
f
/
dd
;
float
u_scale
=
1.
f
,
u_bias
=
0.
f
;
float
v_scale
=
1.
f
,
v_bias
=
0.
f
;
for
(
j
=
0
;
j
<
9
;
j
++
)
M
[
j
]
=
(
float
)
XYZ2RGB
[
j
];
//0.72033 = 255/(220+134), 96.525 = 134*255/(220+134)
//0.9732 = 255/(140+122), 136.259 = 140*255/(140+122)
if
(
depth
==
CV_8U
)
{
u_scale
=
1.
f
/
0.720338983
f
;
u_bias
=
96.5254237
f
;
v_scale
=
1.
f
/
0.973282442
f
;
v_bias
=
136.2595419
f
;
u_scale
=
uRange
/
255.
f
;
u_bias
=
-
uLow
*
255.
f
/
uRange
;
v_scale
=
vRange
/
255.
f
;
v_bias
=
-
vLow
*
255.
f
/
vRange
;
}
// (1 / 903.3) = (3/29)^3
static
const
float
yscale
=
27.
f
/
(
29.
f
*
29.
f
*
29.
f
);
for
(
j
=
0
;
j
<
n
*
3
;
j
+=
3
)
{
float
L
=
src_row
[
j
]
*
Lscale
;
...
...
@@ -1241,21 +1384,31 @@ void CV_ColorLuvTest::convert_row_abc2bgr_32f_c3( const float* src_row, float* d
}
else
{
Y
=
L
*
(
1.
f
/
903.3
f
);
if
(
L
==
0
)
L
=
0.001
f
;
Y
=
L
*
yscale
;
}
u
=
u
/
(
13
*
L
)
+
un
;
v
=
v
/
(
13
*
L
)
+
vn
;
X
=
-
9
*
Y
*
u
/
((
u
-
4
)
*
v
-
u
*
v
);
Z
=
(
9
*
Y
-
15
*
v
*
Y
-
v
*
X
)
/
(
3
*
v
);
float
up
=
3.
f
*
(
u
+
L
*
un
);
float
vp
=
0.25
f
/
(
v
+
L
*
vn
);
if
(
vp
>
0.25
f
)
vp
=
0.25
f
;
if
(
vp
<
-
0.25
f
)
vp
=
-
0.25
f
;
X
=
Y
*
3.
f
*
up
*
vp
;
Z
=
Y
*
(((
12.
f
*
13.
f
)
*
L
-
up
)
*
vp
-
5.
f
);
float
r
=
M
[
0
]
*
X
+
M
[
1
]
*
Y
+
M
[
2
]
*
Z
;
float
g
=
M
[
3
]
*
X
+
M
[
4
]
*
Y
+
M
[
5
]
*
Z
;
float
b
=
M
[
6
]
*
X
+
M
[
7
]
*
Y
+
M
[
8
]
*
Z
;
r
=
std
::
min
(
std
::
max
(
r
,
0.
f
),
1.
f
);
g
=
std
::
min
(
std
::
max
(
g
,
0.
f
),
1.
f
);
b
=
std
::
min
(
std
::
max
(
b
,
0.
f
),
1.
f
);
if
(
srgb
)
{
r
=
applyInvGamma
(
r
);
g
=
applyInvGamma
(
g
);
b
=
applyInvGamma
(
b
);
}
dst_row
[
j
]
=
b
;
dst_row
[
j
+
1
]
=
g
;
dst_row
[
j
+
2
]
=
r
;
...
...
@@ -1898,13 +2051,15 @@ static void validateResult(const Mat& reference, const Mat& actual, const Mat& s
int
cn
=
reference
.
channels
();
ssize
.
width
*=
cn
;
bool
next
=
true
;
//RGB2Lab_f works throug LUT and brings additional error
static
const
float
maxErr
=
1.
f
/
192.
f
;
for
(
int
y
=
0
;
y
<
ssize
.
height
&&
next
;
++
y
)
{
const
float
*
rD
=
reference
.
ptr
<
float
>
(
y
);
const
float
*
D
=
actual
.
ptr
<
float
>
(
y
);
for
(
int
x
=
0
;
x
<
ssize
.
width
&&
next
;
++
x
)
if
(
fabs
(
rD
[
x
]
-
D
[
x
])
>
0.0001
f
)
if
(
fabs
(
rD
[
x
]
-
D
[
x
])
>
maxErr
)
{
next
=
false
;
ts
->
printf
(
cvtest
::
TS
::
SUMMARY
,
"Error in: (%d, %d)
\n
"
,
x
/
cn
,
y
);
...
...
@@ -1935,20 +2090,344 @@ TEST(Imgproc_ColorLab_Full, accuracy)
Size
ssize
=
src
.
size
();
CV_Assert
(
ssize
.
width
==
ssize
.
height
);
RNG
&
rng
=
cvtest
::
TS
::
ptr
()
->
get_rng
();
int
blueInd
=
rng
.
uniform
(
0.
,
1.
)
>
0.5
?
0
:
2
;
bool
srgb
=
rng
.
uniform
(
0.
,
1.
)
>
0.5
;
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
int
blueInd
=
(
i
%
2
)
>
0
?
0
:
2
;
bool
srgb
=
i
>
1
;
// Convert test image to LAB
cv
::
Mat
lab
;
int
forward_code
=
blueInd
?
srgb
?
CV_BGR2Lab
:
CV_LBGR2Lab
:
srgb
?
CV_RGB2Lab
:
CV_LRGB2Lab
;
int
inverse_code
=
blueInd
?
srgb
?
CV_Lab2BGR
:
CV_Lab2LBGR
:
srgb
?
CV_Lab2RGB
:
CV_Lab2LRGB
;
cv
::
cvtColor
(
src
,
lab
,
forward_code
);
// Convert LAB image back to BGR(RGB)
cv
::
Mat
recons
;
cv
::
cvtColor
(
lab
,
recons
,
inverse_code
);
validateResult
(
src
,
recons
,
src
,
forward_code
);
}
}
static
uint32_t
adler32
(
Mat
m
)
{
uint32_t
s1
=
1
,
s2
=
0
;
for
(
int
y
=
0
;
y
<
m
.
rows
;
y
++
)
{
uchar
*
py
=
m
.
ptr
(
y
);
for
(
size_t
x
=
0
;
x
<
m
.
cols
*
m
.
elemSize
();
x
++
)
{
s1
=
(
s1
+
py
[
x
])
%
65521
;
s2
=
(
s1
+
s2
)
%
65521
;
}
}
return
(
s2
<<
16
)
+
s1
;
}
// taken from color.cpp
static
ushort
sRGBGammaTab_b
[
256
],
linearGammaTab_b
[
256
];
enum
{
inv_gamma_shift
=
12
,
INV_GAMMA_TAB_SIZE
=
(
1
<<
inv_gamma_shift
)
};
static
ushort
sRGBInvGammaTab_b
[
INV_GAMMA_TAB_SIZE
],
linearInvGammaTab_b
[
INV_GAMMA_TAB_SIZE
];
#undef lab_shift
// #define lab_shift xyz_shift
#define lab_shift 12
#define gamma_shift 3
#define lab_shift2 (lab_shift + gamma_shift)
#define LAB_CBRT_TAB_SIZE_B (256*3/2*(1<<gamma_shift))
static
ushort
LabCbrtTab_b
[
LAB_CBRT_TAB_SIZE_B
];
enum
{
lab_base_shift
=
14
,
LAB_BASE
=
(
1
<<
lab_base_shift
),
};
#define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n))
static
ushort
LabToYF_b
[
256
*
2
];
static
const
int
minABvalue
=
-
8145
;
static
int
abToXZ_b
[
LAB_BASE
*
9
/
4
];
static
void
initLabTabs
()
{
static
bool
initialized
=
false
;
if
(
!
initialized
)
{
static
const
softfloat
lthresh
=
softfloat
(
216
)
/
softfloat
(
24389
);
// 0.008856f = (6/29)^3
static
const
softfloat
lscale
=
softfloat
(
841
)
/
softfloat
(
108
);
// 7.787f = (29/3)^3/(29*4)
static
const
softfloat
lbias
=
softfloat
(
16
)
/
softfloat
(
116
);
static
const
softfloat
f255
(
255
);
static
const
softfloat
intScale
(
255
*
(
1
<<
gamma_shift
));
for
(
int
i
=
0
;
i
<
256
;
i
++
)
{
softfloat
x
=
softfloat
(
i
)
/
f255
;
sRGBGammaTab_b
[
i
]
=
(
ushort
)(
cvRound
(
intScale
*
applyGamma
(
x
)));
linearGammaTab_b
[
i
]
=
(
ushort
)(
i
*
(
1
<<
gamma_shift
));
}
static
const
softfloat
invScale
=
softfloat
::
one
()
/
softfloat
((
int
)
INV_GAMMA_TAB_SIZE
);
for
(
int
i
=
0
;
i
<
INV_GAMMA_TAB_SIZE
;
i
++
)
{
softfloat
x
=
invScale
*
softfloat
(
i
);
sRGBInvGammaTab_b
[
i
]
=
(
ushort
)(
cvRound
(
f255
*
applyInvGamma
(
x
)));
linearInvGammaTab_b
[
i
]
=
(
ushort
)(
cvTrunc
(
f255
*
x
));
}
static
const
softfloat
cbTabScale
(
softfloat
::
one
()
/
(
f255
*
(
1
<<
gamma_shift
)));
static
const
softfloat
lshift2
(
1
<<
lab_shift2
);
for
(
int
i
=
0
;
i
<
LAB_CBRT_TAB_SIZE_B
;
i
++
)
{
softfloat
x
=
cbTabScale
*
softfloat
(
i
);
LabCbrtTab_b
[
i
]
=
(
ushort
)(
cvRound
(
lshift2
*
(
x
<
lthresh
?
mulAdd
(
x
,
lscale
,
lbias
)
:
cbrt
(
x
))));
}
//Lookup table for L to y and ify calculations
static
const
int
BASE
=
(
1
<<
14
);
for
(
int
i
=
0
;
i
<
256
;
i
++
)
{
int
y
,
ify
;
//8 * 255.0 / 100.0 == 20.4
if
(
i
<=
20
)
{
//yy = li / 903.3f;
//y = L*100/903.3f; 903.3f = (29/3)^3, 255 = 17*3*5
y
=
cvRound
(
softfloat
(
i
*
BASE
*
20
*
9
)
/
softfloat
(
17
*
29
*
29
*
29
));
//fy = 7.787f * yy + 16.0f / 116.0f; 7.787f = (29/3)^3/(29*4)
ify
=
cvRound
(
softfloat
(
BASE
)
*
(
softfloat
(
16
)
/
softfloat
(
116
)
+
softfloat
(
i
*
5
)
/
softfloat
(
3
*
17
*
29
)));
}
else
{
//fy = (li + 16.0f) / 116.0f;
softfloat
fy
=
(
softfloat
(
i
*
100
*
BASE
)
/
softfloat
(
255
*
116
)
+
softfloat
(
16
*
BASE
)
/
softfloat
(
116
));
ify
=
cvRound
(
fy
);
//yy = fy * fy * fy;
y
=
cvRound
(
fy
*
fy
*
fy
/
softfloat
(
BASE
*
BASE
));
}
LabToYF_b
[
i
*
2
]
=
(
ushort
)
y
;
// 2260 <= y <= BASE
LabToYF_b
[
i
*
2
+
1
]
=
(
ushort
)
ify
;
// 0 <= ify <= BASE
}
//Lookup table for a,b to x,z conversion
for
(
int
i
=
minABvalue
;
i
<
LAB_BASE
*
9
/
4
+
minABvalue
;
i
++
)
{
int
v
;
//6.f/29.f*BASE = 3389.730
if
(
i
<=
3390
)
{
//fxz[k] = (fxz[k] - 16.0f / 116.0f) / 7.787f;
// 7.787f = (29/3)^3/(29*4)
v
=
i
*
108
/
841
-
BASE
*
16
/
116
*
108
/
841
;
}
else
{
//fxz[k] = fxz[k] * fxz[k] * fxz[k];
v
=
i
*
i
/
BASE
*
i
/
BASE
;
}
abToXZ_b
[
i
-
minABvalue
]
=
v
;
// -1335 <= v <= 88231
}
initialized
=
true
;
}
}
static
int
row8uRGB2Lab
(
const
uchar
*
src_row
,
uchar
*
dst_row
,
int
n
,
int
cn
,
int
blue_idx
,
bool
srgb
)
{
int
coeffs
[
9
];
softdouble
whitept
[
3
]
=
{
Xn
,
softdouble
::
one
(),
Zn
};
static
const
softdouble
lshift
(
1
<<
lab_shift
);
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
coeffs
[
i
*
3
+
(
blue_idx
^
2
)]
=
cvRound
(
lshift
*
RGB2XYZ
[
i
*
3
]
/
whitept
[
i
]);
coeffs
[
i
*
3
+
1
]
=
cvRound
(
lshift
*
RGB2XYZ
[
i
*
3
+
1
]
/
whitept
[
i
]);
coeffs
[
i
*
3
+
(
blue_idx
)]
=
cvRound
(
lshift
*
RGB2XYZ
[
i
*
3
+
2
]
/
whitept
[
i
]);
}
const
int
Lscale
=
(
116
*
255
+
50
)
/
100
;
const
int
Lshift
=
-
((
16
*
255
*
(
1
<<
lab_shift2
)
+
50
)
/
100
);
const
ushort
*
tab
=
srgb
?
sRGBGammaTab_b
:
linearGammaTab_b
;
for
(
int
x
=
0
;
x
<
n
;
x
++
)
{
int
R
=
src_row
[
x
*
cn
+
0
],
G
=
src_row
[
x
*
cn
+
1
],
B
=
src_row
[
x
*
cn
+
2
];
R
=
tab
[
R
],
G
=
tab
[
G
],
B
=
tab
[
B
];
int
fX
=
LabCbrtTab_b
[
CV_DESCALE
(
R
*
coeffs
[
0
]
+
G
*
coeffs
[
1
]
+
B
*
coeffs
[
2
],
lab_shift
)];
int
fY
=
LabCbrtTab_b
[
CV_DESCALE
(
R
*
coeffs
[
3
]
+
G
*
coeffs
[
4
]
+
B
*
coeffs
[
5
],
lab_shift
)];
int
fZ
=
LabCbrtTab_b
[
CV_DESCALE
(
R
*
coeffs
[
6
]
+
G
*
coeffs
[
7
]
+
B
*
coeffs
[
8
],
lab_shift
)];
int
L
=
CV_DESCALE
(
Lscale
*
fY
+
Lshift
,
lab_shift2
);
int
a
=
CV_DESCALE
(
500
*
(
fX
-
fY
)
+
128
*
(
1
<<
lab_shift2
),
lab_shift2
);
int
b
=
CV_DESCALE
(
200
*
(
fY
-
fZ
)
+
128
*
(
1
<<
lab_shift2
),
lab_shift2
);
dst_row
[
x
*
3
]
=
saturate_cast
<
uchar
>
(
L
);
dst_row
[
x
*
3
+
1
]
=
saturate_cast
<
uchar
>
(
a
);
dst_row
[
x
*
3
+
2
]
=
saturate_cast
<
uchar
>
(
b
);
}
return
n
;
}
// Convert test image to LAB
cv
::
Mat
lab
;
int
forward_code
=
blueInd
?
srgb
?
CV_BGR2Lab
:
CV_LBGR2Lab
:
srgb
?
CV_RGB2Lab
:
CV_LRGB2Lab
;
int
inverse_code
=
blueInd
?
srgb
?
CV_Lab2BGR
:
CV_Lab2LBGR
:
srgb
?
CV_Lab2RGB
:
CV_Lab2LRGB
;
cv
::
cvtColor
(
src
,
lab
,
forward_code
);
// Convert LAB image back to BGR(RGB)
cv
::
Mat
recons
;
cv
::
cvtColor
(
lab
,
recons
,
inverse_code
);
int
row8uLab2RGB
(
const
uchar
*
src_row
,
uchar
*
dst_row
,
int
n
,
int
cn
,
int
blue_idx
,
bool
srgb
)
{
static
const
int
base_shift
=
14
;
static
const
int
BASE
=
(
1
<<
base_shift
);
static
const
int
shift
=
lab_shift
+
(
base_shift
-
inv_gamma_shift
);
int
coeffs
[
9
];
softdouble
whitept
[
3
]
=
{
Xn
,
softdouble
::
one
(),
Zn
};
static
const
softdouble
lshift
(
1
<<
lab_shift
);
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
coeffs
[
i
+
(
blue_idx
)
*
3
]
=
cvRound
(
lshift
*
XYZ2RGB
[
i
]
*
whitept
[
i
]);
coeffs
[
i
+
1
*
3
]
=
cvRound
(
lshift
*
XYZ2RGB
[
i
+
3
]
*
whitept
[
i
]);
coeffs
[
i
+
(
blue_idx
^
2
)
*
3
]
=
cvRound
(
lshift
*
XYZ2RGB
[
i
+
6
]
*
whitept
[
i
]);
}
ushort
*
tab
=
srgb
?
sRGBInvGammaTab_b
:
linearInvGammaTab_b
;
validateResult
(
src
,
recons
,
src
,
forward_code
);
for
(
int
x
=
0
;
x
<
n
;
x
++
)
{
uchar
LL
=
src_row
[
x
*
3
];
uchar
aa
=
src_row
[
x
*
3
+
1
];
uchar
bb
=
src_row
[
x
*
3
+
2
];
int
ro
,
go
,
bo
,
xx
,
yy
,
zz
,
ify
;
yy
=
LabToYF_b
[
LL
*
2
];
ify
=
LabToYF_b
[
LL
*
2
+
1
];
int
adiv
,
bdiv
;
//adiv = aa*BASE/500 - 128*BASE/500, bdiv = bb*BASE/200 - 128*BASE/200;
//approximations with reasonable precision
adiv
=
((
5
*
aa
*
53687
+
(
1
<<
7
))
>>
13
)
-
128
*
BASE
/
500
;
bdiv
=
((
bb
*
41943
+
(
1
<<
4
))
>>
9
)
-
128
*
BASE
/
200
+
1
;
int
ifxz
[]
=
{
ify
+
adiv
,
ify
-
bdiv
};
for
(
int
k
=
0
;
k
<
2
;
k
++
)
{
int
&
v
=
ifxz
[
k
];
v
=
abToXZ_b
[
v
-
minABvalue
];
}
xx
=
ifxz
[
0
];
/* yy = yy */
;
zz
=
ifxz
[
1
];
ro
=
CV_DESCALE
(
coeffs
[
0
]
*
xx
+
coeffs
[
1
]
*
yy
+
coeffs
[
2
]
*
zz
,
shift
);
go
=
CV_DESCALE
(
coeffs
[
3
]
*
xx
+
coeffs
[
4
]
*
yy
+
coeffs
[
5
]
*
zz
,
shift
);
bo
=
CV_DESCALE
(
coeffs
[
6
]
*
xx
+
coeffs
[
7
]
*
yy
+
coeffs
[
8
]
*
zz
,
shift
);
ro
=
max
(
0
,
min
((
int
)
INV_GAMMA_TAB_SIZE
-
1
,
ro
));
go
=
max
(
0
,
min
((
int
)
INV_GAMMA_TAB_SIZE
-
1
,
go
));
bo
=
max
(
0
,
min
((
int
)
INV_GAMMA_TAB_SIZE
-
1
,
bo
));
ro
=
tab
[
ro
];
go
=
tab
[
go
];
bo
=
tab
[
bo
];
dst_row
[
x
*
cn
]
=
saturate_cast
<
uchar
>
(
bo
);
dst_row
[
x
*
cn
+
1
]
=
saturate_cast
<
uchar
>
(
go
);
dst_row
[
x
*
cn
+
2
]
=
saturate_cast
<
uchar
>
(
ro
);
if
(
cn
==
4
)
dst_row
[
x
*
cn
+
3
]
=
255
;
}
return
n
;
}
int
row8uLabChoose
(
const
uchar
*
src_row
,
uchar
*
dst_row
,
int
n
,
bool
forward
,
int
blue_idx
,
bool
srgb
)
{
if
(
forward
)
return
row8uRGB2Lab
(
src_row
,
dst_row
,
n
,
3
,
blue_idx
,
srgb
);
else
return
row8uLab2RGB
(
src_row
,
dst_row
,
n
,
3
,
blue_idx
,
srgb
);
}
TEST
(
Imgproc_ColorLab_Full
,
bitExactness
)
{
int
codes
[]
=
{
CV_BGR2Lab
,
CV_RGB2Lab
,
CV_LBGR2Lab
,
CV_LRGB2Lab
,
CV_Lab2BGR
,
CV_Lab2RGB
,
CV_Lab2LBGR
,
CV_Lab2LRGB
};
string
names
[]
=
{
"CV_BGR2Lab"
,
"CV_RGB2Lab"
,
"CV_LBGR2Lab"
,
"CV_LRGB2Lab"
,
"CV_Lab2BGR"
,
"CV_Lab2RGB"
,
"CV_Lab2LBGR"
,
"CV_Lab2LRGB"
};
// need to be recalculated each time we change Lab algorithms, RNG or test system
const
int
nIterations
=
8
;
uint32_t
hashes
[]
=
{
0xca7d94c4
,
0x34aeb79a
,
0x7272c2cf
,
0x62c2efed
,
0x047cab77
,
0x5e8dfb85
,
0x10fed613
,
0x34d2f4aa
,
0x048bea9a
,
0xbbe20ef2
,
0x3274e88f
,
0x710e9272
,
0x9fd6cd59
,
0x69d67639
,
0x04742095
,
0x9ef2b60b
,
0x75b78f5b
,
0x3fda9801
,
0x374cc472
,
0x3239e8ad
,
0x94749b2d
,
0x9362ac0c
,
0xa4d7dd36
,
0xe25ef694
,
0x51d1b01d
,
0xb0f6e3f5
,
0x2b72a228
,
0xb7429fa0
,
0x799ba6bd
,
0x2141d3d2
,
0xb4dde471
,
0x813b6e0f
,
0x9c029161
,
0xb51eb5ec
,
0x460c3a09
,
0x27724f63
,
0xb446c9a8
,
0x3adf1b61
,
0xe6b0d30f
,
0xd1078779
,
0xfaa7525b
,
0x5b6ea158
,
0xdf3511f7
,
0xf01dc02d
,
0x5c663841
,
0xce611ed4
,
0x758ad851
,
0xa43c3a1c
,
0xed30f68c
,
0xcb6babd9
,
0xf38262b5
,
0x608cb3db
,
0x13425e5a
,
0x6dc5fdc7
,
0x9519090a
,
0x87aa73d0
,
0x8e9bf980
,
0x46b98728
,
0x0064591c
,
0x7e1efc9b
,
0xf0ec2465
,
0x89a75c8d
,
0x0d162fa7
,
0xffea7a2f
,
};
RNG
rng
(
0
);
// blueIdx x srgb x direction
bool
next
=
true
;
for
(
int
c
=
0
;
next
&&
c
<
8
;
c
++
)
{
int
v
=
c
;
int
blueIdx
=
(
v
%
2
!=
0
)
?
2
:
0
;
v
/=
2
;
bool
srgb
=
(
v
%
2
==
0
);
v
/=
2
;
bool
forward
=
(
v
%
2
==
0
);
for
(
int
iter
=
0
;
next
&&
iter
<
nIterations
;
iter
++
)
{
Mat
probe
(
256
,
256
,
CV_8UC3
),
result
;
rng
.
fill
(
probe
,
RNG
::
UNIFORM
,
0
,
255
,
true
);
cvtColor
(
probe
,
result
,
codes
[
c
]);
uint32_t
h
=
adler32
(
result
);
uint32_t
goodHash
=
hashes
[
c
*
nIterations
+
iter
];
if
(
h
!=
goodHash
)
{
initLabTabs
();
vector
<
uchar
>
goldBuf
(
probe
.
cols
*
4
);
uchar
*
goldRow
=
&
goldBuf
[
0
];
for
(
int
y
=
0
;
next
&&
y
<
probe
.
rows
;
y
++
)
{
uchar
*
probeRow
=
probe
.
ptr
(
y
);
uchar
*
resultRow
=
result
.
ptr
(
y
);
row8uLabChoose
(
probeRow
,
goldRow
,
probe
.
cols
,
forward
,
blueIdx
,
srgb
);
for
(
int
x
=
0
;
next
&&
x
<
probe
.
cols
;
x
++
)
{
uchar
*
px
=
probeRow
+
x
*
3
;
uchar
*
gx
=
goldRow
+
x
*
3
;
uchar
*
rx
=
resultRow
+
x
*
3
;
if
(
gx
[
0
]
!=
rx
[
0
]
||
gx
[
1
]
!=
rx
[
1
]
||
gx
[
2
]
!=
rx
[
2
])
{
next
=
false
;
FAIL
()
<<
"Bad accuracy"
<<
endl
<<
"Conversion code: "
<<
names
[
c
]
<<
endl
<<
"Iteration: "
<<
iter
<<
endl
<<
"Hash vs Correct hash: "
<<
h
<<
", "
<<
goodHash
<<
endl
<<
"Error in: ("
<<
x
<<
", "
<<
y
<<
")"
<<
endl
<<
"Reference value: "
<<
gx
[
0
]
<<
" "
<<
gx
[
1
]
<<
" "
<<
gx
[
2
]
<<
endl
<<
"Actual value: "
<<
rx
[
0
]
<<
" "
<<
rx
[
1
]
<<
" "
<<
rx
[
2
]
<<
endl
<<
"Src value: "
<<
px
[
0
]
<<
" "
<<
px
[
1
]
<<
" "
<<
px
[
2
]
<<
endl
<<
"Size: ("
<<
probe
.
rows
<<
", "
<<
probe
.
cols
<<
")"
<<
endl
;
break
;
}
}
}
if
(
next
)
// this place should never be reached
throw
std
::
runtime_error
(
"Test system error: hash function mismatch when results are the same"
);
}
}
}
}
static
void
test_Bayer2RGB_EdgeAware_8u
(
const
Mat
&
src
,
Mat
&
dst
,
int
code
)
...
...
modules/imgproc/test/test_precomp.hpp
View file @
822d33d6
...
...
@@ -14,6 +14,7 @@
#include "opencv2/core/private.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/core/softfloat.hpp"
#include "opencv2/imgproc/imgproc_c.h"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment