Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv_contrib
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_contrib
Commits
4067fe81
Commit
4067fe81
authored
Sep 20, 2019
by
Alexander Alekhin
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
parents
8ae597d0
f5e493b6
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
267 additions
and
72 deletions
+267
-72
simple_color_balance.cpp
modules/xphoto/src/simple_color_balance.cpp
+35
-54
simple_color_balance.cpp
modules/xphoto/test/simple_color_balance.cpp
+232
-18
No files found.
modules/xphoto/src/simple_color_balance.cpp
View file @
4067fe81
...
...
@@ -39,7 +39,6 @@
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include "opencv2/core.hpp"
...
...
@@ -59,73 +58,55 @@ void balanceWhiteSimple(std::vector<Mat_<T> > &src, Mat &dst, const float inputM
const
float
s1
=
p
;
// low quantile
const
float
s2
=
p
;
// high quantile
int
depth
=
2
;
// depth of histogram tree
if
(
src
[
0
].
depth
()
!=
CV_8U
)
++
depth
;
int
bins
=
16
;
// number of bins at each histogram level
int
nElements
=
src
[
0
].
depth
()
==
CV_8U
?
256
:
4096
;
int
nElements
=
int
(
pow
((
float
)
bins
,
(
float
)
depth
))
;
// number of elements in histogram tree
float
minValue0
=
inputMin
;
float
maxValue0
=
inputMax
;
for
(
size_t
i
=
0
;
i
<
src
.
size
();
++
i
)
// deal with cv::calcHist (exclusive upper bound)
if
(
src
[
0
].
depth
()
==
CV_32F
||
src
[
0
].
depth
()
==
CV_64F
)
// floating
{
std
::
vector
<
int
>
hist
(
nElements
,
0
);
typename
Mat_
<
T
>::
iterator
beginIt
=
src
[
i
].
begin
();
typename
Mat_
<
T
>::
iterator
endIt
=
src
[
i
].
end
();
for
(
typename
Mat_
<
T
>::
iterator
it
=
beginIt
;
it
!=
endIt
;
++
it
)
// histogram filling
{
int
pos
=
0
;
float
minValue
=
inputMin
-
0.5
f
;
float
maxValue
=
inputMax
+
0.5
f
;
T
val
=
*
it
;
float
interval
=
float
(
maxValue
-
minValue
)
/
bins
;
maxValue0
+=
MIN
((
inputMax
-
inputMin
)
/
(
nElements
-
1
),
1
);
if
(
inputMax
==
inputMin
)
// single value
maxValue0
+=
1
;
}
else
// integer
{
maxValue0
+=
1
;
}
for
(
int
j
=
0
;
j
<
depth
;
++
j
)
{
int
currentBin
=
int
((
val
-
minValue
+
1e-4
f
)
/
interval
);
++
hist
[
pos
+
currentBin
];
float
interval
=
(
maxValue0
-
minValue0
)
/
float
(
nElements
);
pos
=
(
pos
+
currentBin
)
*
bins
;
for
(
size_t
i
=
0
;
i
<
src
.
size
();
++
i
)
{
float
minValue
=
minValue0
;
float
maxValue
=
maxValue0
;
minValue
=
minValue
+
currentBin
*
interval
;
maxValue
=
minValue
+
interval
;
Mat
img
=
src
[
i
].
reshape
(
1
);
Mat
hist
;
int
channels
[]
=
{
0
};
int
histSize
[]
=
{
nElements
};
float
inputRange
[]
=
{
minValue
,
maxValue
};
const
float
*
ranges
[]
=
{
inputRange
};
interval
/=
bins
;
}
}
calcHist
(
&
img
,
1
,
channels
,
Mat
(),
hist
,
1
,
histSize
,
ranges
,
true
,
false
);
int
total
=
int
(
src
[
i
].
total
());
int
p1
=
0
,
p2
=
bin
s
-
1
;
int
p1
=
0
,
p2
=
nElement
s
-
1
;
int
n1
=
0
,
n2
=
total
;
float
minValue
=
inputMin
-
0.5
f
;
float
maxValue
=
inputMax
+
0.5
f
;
float
interval
=
(
maxValue
-
minValue
)
/
float
(
bins
);
for
(
int
j
=
0
;
j
<
depth
;
++
j
)
// searching for s1 and s2
while
(
n1
+
hist
.
at
<
float
>
(
p1
)
<
s1
*
total
/
100.0
f
)
{
n1
+=
saturate_cast
<
int
>
(
hist
.
at
<
float
>
(
p1
++
));
minValue
+=
interval
;
}
while
(
n2
-
hist
.
at
<
float
>
(
p2
)
>
(
100.0
f
-
s2
)
*
total
/
100.0
f
)
{
while
(
n1
+
hist
[
p1
]
<
s1
*
total
/
100.0
f
)
{
n1
+=
hist
[
p1
++
];
minValue
+=
interval
;
}
p1
*=
bins
;
while
(
n2
-
hist
[
p2
]
>
(
100.0
f
-
s2
)
*
total
/
100.0
f
)
{
n2
-=
hist
[
p2
--
];
maxValue
-=
interval
;
}
p2
=
(
p2
+
1
)
*
bins
-
1
;
interval
/=
bins
;
n2
-=
saturate_cast
<
int
>
(
hist
.
at
<
float
>
(
p2
--
));
maxValue
-=
interval
;
}
src
[
i
]
=
(
outputMax
-
outputMin
)
*
(
src
[
i
]
-
minValue
)
/
(
maxValue
-
minValue
)
+
outputMin
;
...
...
modules/xphoto/test/simple_color_balance.cpp
View file @
4067fe81
...
...
@@ -5,33 +5,140 @@
namespace
opencv_test
{
namespace
{
TEST
(
xphoto_simplecolorbalance
,
regression
)
TEST
(
xphoto_simplecolorbalance
,
uchar_max_value
)
{
cv
::
String
dir
=
cvtest
::
TS
::
ptr
()
->
get_data_path
()
+
"cv/xphoto/simple_white_balance/"
;
int
nTests
=
8
;
cv
::
Ptr
<
cv
::
xphoto
::
WhiteBalancer
>
wb
=
cv
::
xphoto
::
createSimpleWB
();
const
uchar
oldMax
=
120
,
newMax
=
255
;
for
(
int
i
=
0
;
i
<
nTests
;
++
i
)
{
cv
::
String
srcName
=
dir
+
cv
::
format
(
"sources/%02d.png"
,
i
+
1
);
cv
::
Mat
src
=
cv
::
imread
(
srcName
,
1
);
ASSERT_TRUE
(
!
src
.
empty
());
Mat
test
=
Mat
::
zeros
(
3
,
3
,
CV_8UC1
);
test
.
at
<
uchar
>
(
0
,
0
)
=
oldMax
;
test
.
at
<
uchar
>
(
0
,
1
)
=
oldMax
/
2
;
test
.
at
<
uchar
>
(
0
,
2
)
=
oldMax
/
4
;
cv
::
String
previousResultName
=
dir
+
cv
::
format
(
"results/%02d.jpg"
,
i
+
1
);
cv
::
Mat
previousResult
=
cv
::
imread
(
previousResultName
,
1
);
cv
::
Ptr
<
cv
::
xphoto
::
SimpleWB
>
wb
=
cv
::
xphoto
::
createSimpleWB
();
wb
->
setInputMin
(
0
);
wb
->
setInputMax
(
oldMax
);
wb
->
setOutputMin
(
0
);
wb
->
setOutputMax
(
newMax
);
cv
::
Mat
currentResult
;
wb
->
balanceWhite
(
src
,
currentResult
);
wb
->
balanceWhite
(
test
,
test
);
double
psnr
=
cv
::
PSNR
(
currentResult
,
previousResult
);
double
minDst
,
maxDst
;
cv
::
minMaxIdx
(
test
,
&
minDst
,
&
maxDst
);
EXPECT_GE
(
psnr
,
30
);
}
ASSERT_NEAR
(
maxDst
,
newMax
,
1e-4
);
}
TEST
(
xphoto_simplecolorbalance
,
max
_value
)
TEST
(
xphoto_simplecolorbalance
,
uchar_min
_value
)
{
const
float
oldMax
=
24000.
,
newMax
=
65536.
;
const
uchar
oldMin
=
120
,
newMin
=
0
;
Mat
test
=
Mat
::
zeros
(
1
,
3
,
CV_8UC1
);
test
.
at
<
uchar
>
(
0
,
0
)
=
oldMin
;
test
.
at
<
uchar
>
(
0
,
1
)
=
(
256
+
oldMin
)
/
2
;
test
.
at
<
uchar
>
(
0
,
2
)
=
255
;
cv
::
Ptr
<
cv
::
xphoto
::
SimpleWB
>
wb
=
cv
::
xphoto
::
createSimpleWB
();
wb
->
setInputMin
(
oldMin
);
wb
->
setInputMax
(
255
);
wb
->
setOutputMin
(
newMin
);
wb
->
setOutputMax
(
255
);
wb
->
balanceWhite
(
test
,
test
);
double
minDst
,
maxDst
;
cv
::
minMaxIdx
(
test
,
&
minDst
,
&
maxDst
);
ASSERT_NEAR
(
minDst
,
newMin
,
1e-4
);
}
TEST
(
xphoto_simplecolorbalance
,
uchar_equal_range
)
{
const
int
N
=
4
;
uchar
data
[
N
]
=
{
0
,
1
,
16
,
255
};
Mat
test
=
Mat
(
1
,
N
,
CV_8UC1
,
data
);
Mat
result
=
Mat
(
1
,
N
,
CV_8UC1
,
data
);
cv
::
Ptr
<
cv
::
xphoto
::
SimpleWB
>
wb
=
cv
::
xphoto
::
createSimpleWB
();
wb
->
setInputMin
(
0
);
wb
->
setInputMax
(
255
);
wb
->
setOutputMin
(
0
);
wb
->
setOutputMax
(
255
);
wb
->
balanceWhite
(
test
,
test
);
double
err
;
cv
::
minMaxIdx
(
cv
::
abs
(
test
-
result
),
NULL
,
&
err
);
ASSERT_LE
(
err
,
1e-4
);
}
TEST
(
xphoto_simplecolorbalance
,
uchar_single_value
)
{
const
int
N
=
4
;
uchar
data0
[
N
]
=
{
51
,
51
,
51
,
51
};
uchar
data1
[
N
]
=
{
33
,
33
,
33
,
33
};
Mat
test
=
Mat
(
1
,
N
,
CV_8UC1
,
data0
);
Mat
result
=
Mat
(
1
,
N
,
CV_8UC1
,
data1
);
cv
::
Ptr
<
cv
::
xphoto
::
SimpleWB
>
wb
=
cv
::
xphoto
::
createSimpleWB
();
wb
->
setInputMin
(
51
);
wb
->
setInputMax
(
51
);
wb
->
setOutputMin
(
33
);
wb
->
setOutputMax
(
200
);
wb
->
balanceWhite
(
test
,
test
);
double
err
;
cv
::
minMaxIdx
(
cv
::
abs
(
test
-
result
),
NULL
,
&
err
);
ASSERT_LE
(
err
,
1e-4
);
}
TEST
(
xphoto_simplecolorbalance
,
uchar_p
)
{
const
int
N
=
5
;
uchar
data0
[
N
]
=
{
10
,
55
,
102
,
188
,
233
};
uchar
data1
[
N
]
=
{
0
,
1
,
90
,
254
,
255
};
Mat
test
=
Mat
(
1
,
N
,
CV_8UC1
,
data0
);
Mat
result
=
Mat
(
1
,
N
,
CV_8UC1
,
data1
);
cv
::
Ptr
<
cv
::
xphoto
::
SimpleWB
>
wb
=
cv
::
xphoto
::
createSimpleWB
();
wb
->
setInputMin
(
10
);
wb
->
setInputMax
(
233
);
wb
->
setOutputMin
(
0
);
wb
->
setOutputMax
(
255
);
wb
->
setP
(
21
);
wb
->
balanceWhite
(
test
,
test
);
double
err
;
cv
::
minMaxIdx
(
cv
::
abs
(
test
-
result
),
NULL
,
&
err
);
ASSERT_LE
(
err
,
1e-4
);
}
TEST
(
xphoto_simplecolorbalance
,
uchar_c3
)
{
const
int
N
=
15
;
uchar
data0
[
N
]
=
{
10
,
55
,
102
,
55
,
102
,
188
,
102
,
188
,
233
,
188
,
233
,
10
,
233
,
10
,
55
};
uchar
data1
[
N
]
=
{
0
,
1
,
90
,
1
,
90
,
254
,
90
,
254
,
255
,
254
,
255
,
0
,
255
,
0
,
1
};
Mat
test
=
Mat
(
1
,
N
/
3
,
CV_8UC3
,
data0
);
Mat
result
=
Mat
(
1
,
N
/
3
,
CV_8UC3
,
data1
);
cv
::
Ptr
<
cv
::
xphoto
::
SimpleWB
>
wb
=
cv
::
xphoto
::
createSimpleWB
();
wb
->
setInputMin
(
10
);
wb
->
setInputMax
(
233
);
wb
->
setOutputMin
(
0
);
wb
->
setOutputMax
(
255
);
wb
->
setP
(
21
);
wb
->
balanceWhite
(
test
,
test
);
double
err
;
cv
::
minMaxIdx
(
cv
::
abs
(
test
-
result
),
NULL
,
&
err
);
ASSERT_LE
(
err
,
1e-4
);
}
TEST
(
xphoto_simplecolorbalance
,
float_max_value
)
{
const
float
oldMax
=
24000.
f
,
newMax
=
65536.
f
;
Mat
test
=
Mat
::
zeros
(
3
,
3
,
CV_32FC1
);
test
.
at
<
float
>
(
0
,
0
)
=
oldMax
;
...
...
@@ -55,5 +162,112 @@ namespace opencv_test { namespace {
ASSERT_NEAR
(
maxDst
,
newMax
,
newMax
*
1e-4
);
}
TEST
(
xphoto_simplecolorbalance
,
float_min_value
)
{
const
float
oldMin
=
24000.
f
,
newMin
=
0.
f
;
Mat
test
=
Mat
::
zeros
(
1
,
3
,
CV_32FC1
);
test
.
at
<
float
>
(
0
,
0
)
=
oldMin
;
test
.
at
<
float
>
(
0
,
1
)
=
(
65536.
f
+
oldMin
)
/
2
;
test
.
at
<
float
>
(
0
,
2
)
=
65536.
f
;
cv
::
Ptr
<
cv
::
xphoto
::
SimpleWB
>
wb
=
cv
::
xphoto
::
createSimpleWB
();
wb
->
setInputMin
(
oldMin
);
wb
->
setInputMax
(
65536.
f
);
wb
->
setOutputMin
(
newMin
);
wb
->
setOutputMax
(
65536.
f
);
wb
->
balanceWhite
(
test
,
test
);
double
minDst
,
maxDst
;
cv
::
minMaxIdx
(
test
,
&
minDst
,
&
maxDst
);
ASSERT_NEAR
(
minDst
,
newMin
,
65536
*
1e-4
);
}
TEST
(
xphoto_simplecolorbalance
,
float_equal_range
)
{
const
int
N
=
5
;
float
data
[
N
]
=
{
0.
f
,
1.
f
,
16.2
f
,
256.3
f
,
4096.
f
};
Mat
test
=
Mat
(
1
,
N
,
CV_32FC1
,
data
);
Mat
result
=
Mat
(
1
,
N
,
CV_32FC1
,
data
);
cv
::
Ptr
<
cv
::
xphoto
::
SimpleWB
>
wb
=
cv
::
xphoto
::
createSimpleWB
();
wb
->
setInputMin
(
0
);
wb
->
setInputMax
(
4096
);
wb
->
setOutputMin
(
0
);
wb
->
setOutputMax
(
4096
);
wb
->
balanceWhite
(
test
,
test
);
double
err
;
cv
::
minMaxIdx
(
cv
::
abs
(
test
-
result
),
NULL
,
&
err
);
ASSERT_LE
(
err
,
1e-4
);
}
TEST
(
xphoto_simplecolorbalance
,
float_single_value
)
{
const
int
N
=
4
;
float
data0
[
N
]
=
{
24000.5
f
,
24000.5
f
,
24000.5
f
,
24000.5
f
};
float
data1
[
N
]
=
{
52000.25
f
,
52000.25
f
,
52000.25
f
,
52000.25
f
};
Mat
test
=
Mat
(
1
,
N
,
CV_32FC1
,
data0
);
Mat
result
=
Mat
(
1
,
N
,
CV_32FC1
,
data1
);
cv
::
Ptr
<
cv
::
xphoto
::
SimpleWB
>
wb
=
cv
::
xphoto
::
createSimpleWB
();
wb
->
setInputMin
(
24000.5
f
);
wb
->
setInputMax
(
24000.5
f
);
wb
->
setOutputMin
(
52000.25
f
);
wb
->
setOutputMax
(
65536.
f
);
wb
->
balanceWhite
(
test
,
test
);
double
err
;
cv
::
minMaxIdx
(
cv
::
abs
(
test
-
result
),
NULL
,
&
err
);
ASSERT_LE
(
err
,
65536
*
1e-4
);
}
TEST
(
xphoto_simplecolorbalance
,
float_p
)
{
const
int
N
=
5
;
float
data0
[
N
]
=
{
16000.
f
,
20000.5
f
,
24000.
f
,
36000.5
f
,
48000.
f
};
float
data1
[
N
]
=
{
-
16381.952
f
,
0.
f
,
16381.952
f
,
65536.
f
,
114685.952
f
};
Mat
test
=
Mat
(
1
,
N
,
CV_32FC1
,
data0
);
Mat
result
=
Mat
(
1
,
N
,
CV_32FC1
,
data1
);
cv
::
Ptr
<
cv
::
xphoto
::
SimpleWB
>
wb
=
cv
::
xphoto
::
createSimpleWB
();
wb
->
setInputMin
(
16000.
f
);
wb
->
setInputMax
(
48000.
f
);
wb
->
setOutputMin
(
0.
f
);
wb
->
setOutputMax
(
65536.
f
);
wb
->
setP
(
21
);
wb
->
balanceWhite
(
test
,
test
);
double
err
;
cv
::
minMaxIdx
(
cv
::
abs
(
test
-
result
),
NULL
,
&
err
);
ASSERT_LE
(
err
,
65536
*
1e-4
);
}
TEST
(
xphoto_simplecolorbalance
,
float_c3
)
{
const
int
N
=
15
;
float
data0
[
N
]
=
{
16000.
f
,
20000.5
f
,
24000.
f
,
20000.5
f
,
24000.
f
,
36000.5
f
,
24000.
f
,
36000.5
f
,
48000.
f
,
36000.5
f
,
48000.
f
,
16000.
f
,
48000.
f
,
16000.
f
,
20000.5
f
};
float
data1
[
N
]
=
{
-
16381.952
f
,
0.
f
,
16381.952
f
,
0.
f
,
16381.952
f
,
65536.
f
,
16381.952
f
,
65536.
f
,
114685.952
f
,
65536.
f
,
114685.952
f
,
-
16381.952
f
,
114685.952
f
,
-
16381.952
f
,
0.
f
};
Mat
test
=
Mat
(
1
,
N
/
3
,
CV_32FC3
,
data0
);
Mat
result
=
Mat
(
1
,
N
/
3
,
CV_32FC3
,
data1
);
cv
::
Ptr
<
cv
::
xphoto
::
SimpleWB
>
wb
=
cv
::
xphoto
::
createSimpleWB
();
wb
->
setInputMin
(
16000.
f
);
wb
->
setInputMax
(
48000.
f
);
wb
->
setOutputMin
(
0.
f
);
wb
->
setOutputMax
(
65536.
f
);
wb
->
setP
(
21
);
wb
->
balanceWhite
(
test
,
test
);
double
err
;
cv
::
minMaxIdx
(
cv
::
abs
(
test
-
result
),
NULL
,
&
err
);
ASSERT_LE
(
err
,
65536
*
1e-4
);
}
}}
// namespace
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