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
80063fd4
Commit
80063fd4
authored
Aug 03, 2016
by
Maksim Shabunin
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #736 from sbokov:color_constancy
parents
159534a2
5fbc7daf
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
1923 additions
and
123 deletions
+1923
-123
xphoto.bib
modules/xphoto/doc/xphoto.bib
+8
-0
white_balance.hpp
modules/xphoto/include/opencv2/xphoto/white_balance.hpp
+64
-2
perf_learning_based_color_balance.cpp
modules/xphoto/perf/perf_learning_based_color_balance.cpp
+72
-0
color_balance_benchmark.py
modules/xphoto/samples/color_balance_benchmark.py
+264
-0
learning_based_color_balance.cpp
modules/xphoto/samples/learning_based_color_balance.cpp
+51
-0
grayworld_white_balance.cpp
modules/xphoto/src/grayworld_white_balance.cpp
+245
-121
learn_color_balance.py
modules/xphoto/src/learn_color_balance.py
+264
-0
learning_based_color_balance.cpp
modules/xphoto/src/learning_based_color_balance.cpp
+549
-0
learning_based_color_balance_model.hpp
modules/xphoto/src/learning_based_color_balance_model.hpp
+365
-0
test_grayworld.cpp
modules/xphoto/test/test_grayworld.cpp
+6
-0
test_learning_based_color_balance.cpp
modules/xphoto/test/test_learning_based_color_balance.cpp
+35
-0
No files found.
modules/xphoto/doc/xphoto.bib
View file @
80063fd4
...
...
@@ -6,3 +6,11 @@
year={2012},
publisher={Springer}
}
@inproceedings{Cheng2015,
title={Effective learning-based illuminant estimation using simple features},
author={Cheng, Dongliang and Price, Brian and Cohen, Scott and Brown, Michael S},
booktitle={Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition},
pages={1000--1008},
year={2015}
}
modules/xphoto/include/opencv2/xphoto/white_balance.hpp
View file @
80063fd4
...
...
@@ -105,7 +105,7 @@ namespace xphoto
threshold of 0 means no pixels are used. Lower thresholds are useful in
white-balancing saturated images.
Currently only works on images of type @ref CV_8UC3.
Currently only works on images of type @ref CV_8UC3
and @ref CV_16UC3
.
@param src Input array.
@param dst Output array of the same size and type as src.
...
...
@@ -117,7 +117,69 @@ namespace xphoto
CV_EXPORTS_W
void
autowbGrayworld
(
InputArray
src
,
OutputArray
dst
,
float
thresh
=
0.5
f
);
//! @}
/** @brief Implements a more sophisticated learning-based automatic color balance algorithm.
As autowbGrayworld, this function works by applying different gains to the input
image channels, but their computation is a bit more involved compared to the
simple grayworld assumption. More details about the algorithm can be found in
@cite Cheng2015 .
To mask out saturated pixels this function uses only pixels that satisfy the
following condition:
\f[ \frac{\textrm{max}(R,G,B)}{\texttt{range_max_val}} < \texttt{saturation_thresh} \f]
Currently supports images of type @ref CV_8UC3 and @ref CV_16UC3.
@param src Input three-channel image in the BGR color space.
@param dst Output image of the same size and type as src.
@param range_max_val Maximum possible value of the input image (e.g. 255 for 8 bit images, 4095 for 12 bit images)
@param saturation_thresh Threshold that is used to determine saturated pixels
@param hist_bin_num Defines the size of one dimension of a three-dimensional RGB histogram that is used internally by
the algorithm. It often makes sense to increase the number of bins for images with higher bit depth (e.g. 256 bins
for a 12 bit image)
@sa autowbGrayworld
*/
CV_EXPORTS_W
void
autowbLearningBased
(
InputArray
src
,
OutputArray
dst
,
int
range_max_val
=
255
,
float
saturation_thresh
=
0.98
f
,
int
hist_bin_num
=
64
);
/** @brief Implements the feature extraction part of the learning-based color balance algorithm.
In accordance with @cite Cheng2015 , computes the following features for the input image:
1. Chromaticity of an average (R,G,B) tuple
2. Chromaticity of the brightest (R,G,B) tuple (while ignoring saturated pixels)
3. Chromaticity of the dominant (R,G,B) tuple (the one that has the highest value in the RGB histogram)
4. Mode of the chromaticity pallete, that is constructed by taking 300 most common colors according to
the RGB histogram and projecting them on the chromaticity plane. Mode is the most high-density point
of the pallete, which is computed by a straightforward fixed-bandwidth kernel density estimator with
a Epanechnikov kernel function.
@param src Input three-channel image in the BGR color space.
@param dst An array of four (r,g) chromaticity tuples corresponding to the features listed above.
@param range_max_val Maximum possible value of the input image (e.g. 255 for 8 bit images, 4095 for 12 bit images)
@param saturation_thresh Threshold that is used to determine saturated pixels
@param hist_bin_num Defines the size of one dimension of a three-dimensional RGB histogram that is used internally by
the algorithm. It often makes sense to increase the number of bins for images with higher bit depth (e.g. 256 bins
for a 12 bit image)
@sa autowbLearningBased
*/
CV_EXPORTS_W
void
extractSimpleFeatures
(
InputArray
src
,
OutputArray
dst
,
int
range_max_val
=
255
,
float
saturation_thresh
=
0.98
f
,
int
hist_bin_num
=
64
);
/** @brief Implements an efficient fixed-point approximation for applying channel gains.
@param src Input three-channel image in the BGR color space (either CV_8UC3 or CV_16UC3)
@param dst Output image of the same size and type as src.
@param gainB gain for the B channel
@param gainG gain for the G channel
@param gainR gain for the R channel
@sa autowbGrayworld, autowbLearningBased
*/
CV_EXPORTS_W
void
applyChannelGains
(
InputArray
src
,
OutputArray
dst
,
float
gainB
,
float
gainG
,
float
gainR
);
//! @}
}
}
...
...
modules/xphoto/perf/perf_learning_based_color_balance.cpp
0 → 100644
View file @
80063fd4
/*
* By downloading, copying, installing or using the software you agree to this license.
* If you do not agree to this license, do not download, install,
* copy or use the software.
*
*
* License Agreement
* For Open Source Computer Vision Library
* (3 - clause BSD License)
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met :
*
* *Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and / or other materials provided with the distribution.
*
* * Neither the names of the copyright holders nor the names of the contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* This software is provided by the copyright holders and contributors "as is" and
* any express or implied warranties, including, but not limited to, the implied
* warranties of merchantability and fitness for a particular purpose are disclaimed.
* In no event shall copyright holders or contributors be liable for any direct,
* indirect, incidental, special, exemplary, or consequential damages
* (including, but not limited to, procurement of substitute goods or services;
* loss of use, data, or profits; or business interruption) however caused
* and on any theory of liability, whether in contract, strict liability,
* or tort(including negligence or otherwise) arising in any way out of
* the use of this software, even if advised of the possibility of such damage.
*/
#include "perf_precomp.hpp"
#include "opencv2/imgproc.hpp"
using
std
::
tr1
::
tuple
;
using
std
::
tr1
::
get
;
using
namespace
std
;
using
namespace
cv
;
using
namespace
perf
;
using
namespace
testing
;
typedef
tuple
<
Size
,
MatType
>
learningBasedWBParams
;
typedef
TestBaseWithParam
<
learningBasedWBParams
>
learningBasedWBPerfTest
;
PERF_TEST_P
(
learningBasedWBPerfTest
,
perf
,
Combine
(
SZ_ALL_HD
,
Values
(
CV_8UC3
,
CV_16UC3
)))
{
Size
size
=
get
<
0
>
(
GetParam
());
MatType
t
=
get
<
1
>
(
GetParam
());
Mat
src
(
size
,
t
);
Mat
dst
(
size
,
t
);
int
range_max_val
=
255
,
hist_bin_num
=
64
;
if
(
t
==
CV_16UC3
)
{
range_max_val
=
65535
;
hist_bin_num
=
256
;
}
Mat
src_dscl
(
Size
(
size
.
width
/
16
,
size
.
height
/
16
),
t
);
RNG
rng
(
1234
);
rng
.
fill
(
src_dscl
,
RNG
::
UNIFORM
,
0
,
range_max_val
);
resize
(
src_dscl
,
src
,
src
.
size
());
TEST_CYCLE
()
xphoto
::
autowbLearningBased
(
src
,
dst
,
range_max_val
,
0.98
f
,
hist_bin_num
);
SANITY_CHECK_NOTHING
();
}
modules/xphoto/samples/color_balance_benchmark.py
0 → 100644
View file @
80063fd4
#!/usr/bin/env python
from
__future__
import
print_function
import
os
,
sys
,
argparse
,
json
import
numpy
as
np
import
scipy.io
import
cv2
import
timeit
def
load_json
(
path
):
f
=
open
(
path
,
"r"
)
data
=
json
.
load
(
f
)
return
data
def
save_json
(
obj
,
path
):
tmp_file
=
path
+
".bak"
f
=
open
(
tmp_file
,
"w"
)
json
.
dump
(
obj
,
f
,
indent
=
2
)
f
.
flush
()
os
.
fsync
(
f
.
fileno
())
f
.
close
()
try
:
os
.
rename
(
tmp_file
,
path
)
except
:
os
.
remove
(
path
)
os
.
rename
(
tmp_file
,
path
)
def
parse_sequence
(
input_str
):
if
len
(
input_str
)
==
0
:
return
[]
else
:
return
[
o
.
strip
()
for
o
in
input_str
.
split
(
","
)
if
o
]
def
stretch_to_8bit
(
arr
,
clip_percentile
=
2.5
):
arr
=
np
.
clip
(
arr
*
(
255.0
/
np
.
percentile
(
arr
,
100
-
clip_percentile
)),
0
,
255
)
return
arr
.
astype
(
np
.
uint8
)
def
evaluate
(
im
,
algo
,
gt_illuminant
,
i
,
range_thresh
,
bin_num
,
dst_folder
):
new_im
=
None
start_time
=
timeit
.
default_timer
()
if
algo
==
"grayworld"
:
new_im
=
cv2
.
xphoto
.
autowbGrayworld
(
im
,
0.95
)
elif
algo
==
"nothing"
:
new_im
=
im
elif
algo
==
"learning_based"
:
new_im
=
cv2
.
xphoto
.
autowbLearningBased
(
im
,
None
,
range_thresh
,
0.98
,
bin_num
)
elif
algo
==
"GT"
:
gains
=
gt_illuminant
/
min
(
gt_illuminant
)
g1
=
float
(
1.0
/
gains
[
2
])
g2
=
float
(
1.0
/
gains
[
1
])
g3
=
float
(
1.0
/
gains
[
0
])
new_im
=
cv2
.
xphoto
.
applyChannelGains
(
im
,
g1
,
g2
,
g3
)
time
=
1000
*
(
timeit
.
default_timer
()
-
start_time
)
#time in ms
if
len
(
dst_folder
)
>
0
:
if
not
os
.
path
.
exists
(
dst_folder
):
os
.
makedirs
(
dst_folder
)
im_name
=
(
"
%04
d_"
%
i
)
+
algo
+
".jpg"
cv2
.
imwrite
(
os
.
path
.
join
(
dst_folder
,
im_name
),
stretch_to_8bit
(
new_im
))
#recover the illuminant from the color balancing result, assuming the standard model:
estimated_illuminant
=
[
0
,
0
,
0
]
eps
=
0.01
estimated_illuminant
[
2
]
=
np
.
percentile
((
im
[:,:,
0
]
+
eps
)
/
(
new_im
[:,:,
0
]
+
eps
),
50
)
estimated_illuminant
[
1
]
=
np
.
percentile
((
im
[:,:,
1
]
+
eps
)
/
(
new_im
[:,:,
1
]
+
eps
),
50
)
estimated_illuminant
[
0
]
=
np
.
percentile
((
im
[:,:,
2
]
+
eps
)
/
(
new_im
[:,:,
2
]
+
eps
),
50
)
res
=
np
.
arccos
(
np
.
dot
(
gt_illuminant
,
estimated_illuminant
)
/
(
np
.
linalg
.
norm
(
gt_illuminant
)
*
np
.
linalg
.
norm
(
estimated_illuminant
)))
return
(
time
,
(
res
/
np
.
pi
)
*
180
)
def
build_html_table
(
out
,
state
,
stat_list
,
img_range
):
stat_dict
=
{
'mean'
:
(
'Mean error'
,
lambda
arr
:
np
.
mean
(
arr
)),
'median'
:
(
'Median error'
,
lambda
arr
:
np
.
percentile
(
arr
,
50
)),
'p05'
:
(
'5<sup>th</sup> percentile'
,
lambda
arr
:
np
.
percentile
(
arr
,
5
)),
'p20'
:
(
'20<sup>th</sup> percentile'
,
lambda
arr
:
np
.
percentile
(
arr
,
20
)),
'p80'
:
(
'80<sup>th</sup> percentile'
,
lambda
arr
:
np
.
percentile
(
arr
,
80
)),
'p95'
:
(
'95<sup>th</sup> percentile'
,
lambda
arr
:
np
.
percentile
(
arr
,
95
))
}
html_out
=
[
'<style type="text/css">
\n
'
,
' html, body {font-family: Lucida Console, Courier New, Courier;font-size: 16px;color:#3e4758;}
\n
'
,
' .tbl{background:none repeat scroll 0 0 #FFFFFF;border-collapse:collapse;font-family:"Lucida Sans Unicode","Lucida Grande",Sans-Serif;font-size:14px;margin:20px;text-align:left;width:480px;margin-left: auto;margin-right: auto;white-space:nowrap;}
\n
'
,
' .tbl span{display:block;white-space:nowrap;}
\n
'
,
' .tbl thead tr:last-child th {padding-bottom:5px;}
\n
'
,
' .tbl tbody tr:first-child td {border-top:3px solid #6678B1;}
\n
'
,
' .tbl th{border:none;color:#003399;font-size:16px;font-weight:normal;white-space:nowrap;padding:3px 10px;}
\n
'
,
' .tbl td{border:none;border-bottom:1px solid #CCCCCC;color:#666699;padding:6px 8px;white-space:nowrap;}
\n
'
,
' .tbl tbody tr:hover td{color:#000099;}
\n
'
,
' .tbl caption{font:italic 16px "Trebuchet MS",Verdana,Arial,Helvetica,sans-serif;padding:0 0 5px;text-align:right;white-space:normal;}
\n
'
,
' .firstingroup {border-top:2px solid #6678B1;}
\n
'
,
'</style>
\n\n
'
]
html_out
+=
[
'<table class="tbl">
\n
'
,
' <thead>
\n
'
,
' <tr>
\n
'
,
' <th align="center" valign="top"> Algorithm Name </th>
\n
'
,
' <th align="center" valign="top"> Average Time </th>
\n
'
]
for
stat
in
stat_list
:
if
stat
not
in
stat_dict
.
keys
():
print
(
"Error: unsupported statistic "
+
stat
)
sys
.
exit
(
1
)
html_out
+=
[
' <th align="center" valign="top"> '
+
stat_dict
[
stat
][
0
]
+
' </th>
\n
'
]
html_out
+=
[
' </tr>
\n
'
,
' </thead>
\n
'
,
' <tbody>
\n
'
]
for
algorithm
in
state
.
keys
():
arr
=
[
state
[
algorithm
][
file
][
"angular_error"
]
for
file
in
state
[
algorithm
]
.
keys
()
if
file
>=
img_range
[
0
]
and
file
<=
img_range
[
1
]]
average_time
=
"
%.2
f ms"
%
np
.
mean
([
state
[
algorithm
][
file
][
"time"
]
for
file
in
state
[
algorithm
]
.
keys
()
if
file
>=
img_range
[
0
]
and
file
<=
img_range
[
1
]])
html_out
+=
[
' <tr>
\n
'
,
' <td>'
+
algorithm
+
'</td>
\n
'
,
' <td>'
+
average_time
+
'</td>
\n
'
]
for
stat
in
stat_list
:
html_out
+=
[
' <td> '
+
"
%.2
f°"
%
stat_dict
[
stat
][
1
](
arr
)
+
' </td>
\n
'
]
html_out
+=
[
' </tr>
\n
'
]
html_out
+=
[
' </tbody>
\n
'
,
'</table>
\n
'
]
f
=
open
(
out
,
'w'
)
f
.
writelines
(
html_out
)
f
.
close
()
if
__name__
==
'__main__'
:
parser
=
argparse
.
ArgumentParser
(
description
=
(
"A benchmarking script for color balance algorithms"
),
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
)
parser
.
add_argument
(
"-a"
,
"--algorithms"
,
metavar
=
"ALGORITHMS"
,
default
=
""
,
help
=
(
"Comma-separated list of color balance algorithms to evaluate. "
"Currently available: GT,learning_based,grayworld,nothing."
))
parser
.
add_argument
(
"-i"
,
"--input_folder"
,
metavar
=
"INPUT_FOLDER"
,
default
=
""
,
help
=
(
"Folder containing input images to evaluate on. Assumes minimally "
"processed png images like in the Gehler-Shi (http://www.cs.sfu.ca/~colour/data/shi_gehler/) "
"or NUS 8-camera (http://www.comp.nus.edu.sg/~whitebal/illuminant/illuminant.html) datasets"
))
parser
.
add_argument
(
"-g"
,
"--ground_truth"
,
metavar
=
"GROUND_TRUTH"
,
default
=
"real_illum_568..mat"
,
help
=
(
"Path to the mat file containing ground truth illuminations. Currently "
"supports formats supplied by the Gehler-Shi and NUS 8-camera datasets."
))
parser
.
add_argument
(
"-o"
,
"--out"
,
metavar
=
"OUT"
,
default
=
"./white_balance_eval_result.html"
,
help
=
"Path to the output html table"
)
parser
.
add_argument
(
"-s"
,
"--state"
,
metavar
=
"STATE_JSON"
,
default
=
"./WB_evaluation_state.json"
,
help
=
(
"Path to a json file that stores the current evaluation state"
))
parser
.
add_argument
(
"-t"
,
"--stats"
,
metavar
=
"STATS"
,
default
=
"mean,median,p05,p20,p80,p95"
,
help
=
(
"Comma-separated list of error statistics to compute and list "
"in the output table. All the available ones are used by default"
))
parser
.
add_argument
(
"-b"
,
"--input_bit_depth"
,
metavar
=
"INPUT_BIT_DEPTH"
,
default
=
""
,
help
=
(
"Assumed bit depth for input images. Should be specified in order to "
"use full bit depth for evaluation (for instance, -b 12 for 12 bit images). "
"Otherwise, input images are converted to 8 bit prior to the evaluation."
))
parser
.
add_argument
(
"-d"
,
"--dst_folder"
,
metavar
=
"DST_FOLDER"
,
default
=
""
,
help
=
(
"If specified, this folder will be used to store the color correction results"
))
parser
.
add_argument
(
"-r"
,
"--range"
,
metavar
=
"RANGE"
,
default
=
"0,0"
,
help
=
(
"Comma-separated range of images from the dataset to evaluate on (for instance: 0,568). "
"All available images are used by default."
))
args
,
other_args
=
parser
.
parse_known_args
()
if
not
os
.
path
.
exists
(
args
.
input_folder
):
print
(
"Error: "
+
args
.
input_folder
+
(
" does not exist. Please, correctly "
"specify the -i parameter"
))
sys
.
exit
(
1
)
if
not
os
.
path
.
exists
(
args
.
ground_truth
):
print
(
"Error: "
+
args
.
ground_truth
+
(
" does not exist. Please, correctly "
"specify the -g parameter"
))
sys
.
exit
(
1
)
state
=
{}
if
os
.
path
.
isfile
(
args
.
state
):
state
=
load_json
(
args
.
state
)
algorithm_list
=
parse_sequence
(
args
.
algorithms
)
img_range
=
map
(
int
,
parse_sequence
(
args
.
range
))
if
len
(
img_range
)
!=
2
:
print
(
"Error: Please specify the -r parameter in form <first_image_index>,<last_image_index>"
)
sys
.
exit
(
1
)
gt
=
scipy
.
io
.
loadmat
(
args
.
ground_truth
)
img_files
=
sorted
(
os
.
listdir
(
args
.
input_folder
))
gt_illuminants
=
[]
black_levels
=
[]
if
"groundtruth_illuminants"
in
gt
.
keys
()
and
"darkness_level"
in
gt
.
keys
():
#NUS 8-camera dataset format
gt_illuminants
=
gt
[
"groundtruth_illuminants"
]
black_levels
=
len
(
gt_illuminants
)
*
[
gt
[
"darkness_level"
][
0
][
0
]]
elif
"real_rgb"
in
gt
.
keys
():
#Gehler-Shi dataset format
gt_illuminants
=
gt
[
"real_rgb"
]
black_levels
=
87
*
[
0
]
+
(
len
(
gt_illuminants
)
-
87
)
*
[
129
]
else
:
print
(
"Error: unknown ground-truth format, only formats of Gehler-Shi and NUS 8-camera datasets are supported"
)
sys
.
exit
(
1
)
for
algorithm
in
algorithm_list
:
i
=
0
if
algorithm
not
in
state
.
keys
():
state
[
algorithm
]
=
{}
sz
=
len
(
img_files
)
for
file
in
img_files
:
if
file
not
in
state
[
algorithm
]
.
keys
()
and
\
((
i
>=
img_range
[
0
]
and
i
<
img_range
[
1
])
or
img_range
[
0
]
==
img_range
[
1
]
==
0
):
cur_path
=
os
.
path
.
join
(
args
.
input_folder
,
file
)
im
=
cv2
.
imread
(
cur_path
,
-
1
)
.
astype
(
np
.
float32
)
im
-=
black_levels
[
i
]
range_thresh
=
255
if
len
(
args
.
input_bit_depth
)
>
0
:
range_thresh
=
2
**
int
(
args
.
input_bit_depth
)
-
1
im
=
np
.
clip
(
im
,
0
,
range_thresh
)
.
astype
(
np
.
uint16
)
else
:
im
=
stretch_to_8bit
(
im
)
(
time
,
angular_err
)
=
evaluate
(
im
,
algorithm
,
gt_illuminants
[
i
],
i
,
range_thresh
,
256
if
range_thresh
>
255
else
64
,
args
.
dst_folder
)
state
[
algorithm
][
file
]
=
{
"angular_error"
:
angular_err
,
"time"
:
time
}
sys
.
stdout
.
write
(
"Algorithm:
%-20
s Done: [
%3
d/
%3
d]
\r
"
%
(
algorithm
,
i
,
sz
)),
sys
.
stdout
.
flush
()
save_json
(
state
,
args
.
state
)
i
+=
1
save_json
(
state
,
args
.
state
)
build_html_table
(
args
.
out
,
state
,
parse_sequence
(
args
.
stats
),
[
img_files
[
img_range
[
0
]],
img_files
[
img_range
[
1
]
-
1
]])
modules/xphoto/samples/learning_based_color_balance.cpp
0 → 100644
View file @
80063fd4
#include "opencv2/xphoto.hpp"
#include "opencv2/highgui.hpp"
using
namespace
cv
;
using
namespace
std
;
const
char
*
keys
=
{
"{help h usage ? | | print this message}"
"{i | | input image name }"
"{o | | output image name }"
};
int
main
(
int
argc
,
const
char
**
argv
)
{
CommandLineParser
parser
(
argc
,
argv
,
keys
);
parser
.
about
(
"OpenCV learning-based color balance demonstration sample"
);
if
(
parser
.
has
(
"help"
)
||
argc
<
2
)
{
parser
.
printMessage
();
return
0
;
}
string
inFilename
=
parser
.
get
<
string
>
(
"i"
);
string
outFilename
=
parser
.
get
<
string
>
(
"o"
);
if
(
!
parser
.
check
())
{
parser
.
printErrors
();
return
-
1
;
}
Mat
src
=
imread
(
inFilename
,
1
);
if
(
src
.
empty
())
{
printf
(
"Cannot read image file: %s
\n
"
,
inFilename
.
c_str
());
return
-
1
;
}
Mat
res
;
xphoto
::
autowbLearningBased
(
src
,
res
);
if
(
outFilename
==
""
)
{
namedWindow
(
"after white balance"
,
1
);
imshow
(
"after white balance"
,
res
);
waitKey
(
0
);
}
else
imwrite
(
outFilename
,
res
);
return
0
;
}
modules/xphoto/src/grayworld_white_balance.cpp
View file @
80063fd4
...
...
@@ -37,177 +37,301 @@
//
//M*/
#include "opencv2/xphoto.hpp"
#include "opencv2/core.hpp"
#include "opencv2/core/hal/intrin.hpp"
#include "opencv2/xphoto.hpp"
namespace
cv
{
namespace
xphoto
{
void
calculateChannelSums
(
uint
&
sumB
,
uint
&
sumG
,
uint
&
sumR
,
uchar
*
src_data
,
int
src_len
,
float
thresh
);
void
calculateChannelSums
(
uint64
&
sumB
,
uint64
&
sumG
,
uint64
&
sumR
,
ushort
*
src_data
,
int
src_len
,
float
thresh
);
namespace
cv
{
namespace
xphoto
{
/* Computes sums for each channel, while ignoring saturated pixels which are determined by thresh
* (version for CV_8UC3)
*/
void
calculateChannelSums
(
uint
&
sumB
,
uint
&
sumG
,
uint
&
sumR
,
uchar
*
src_data
,
int
src_len
,
float
thresh
)
{
sumB
=
sumG
=
sumR
=
0
;
ushort
thresh255
=
(
ushort
)
cvRound
(
thresh
*
255
);
int
i
=
0
;
#if CV_SIMD128
v_uint8x16
v_inB
,
v_inG
,
v_inR
,
v_min_val
,
v_max_val
;
v_uint16x8
v_iB1
,
v_iB2
,
v_iG1
,
v_iG2
,
v_iR1
,
v_iR2
;
v_uint16x8
v_min1
,
v_min2
,
v_max1
,
v_max2
,
v_m1
,
v_m2
;
v_uint16x8
v_255
=
v_setall_u16
(
255
),
v_thresh
=
v_setall_u16
(
thresh255
);
v_uint32x4
v_uint1
,
v_uint2
;
v_uint32x4
v_SB
=
v_setzero_u32
(),
v_SG
=
v_setzero_u32
(),
v_SR
=
v_setzero_u32
();
void
autowbGrayworld
(
InputArray
_src
,
OutputArray
_dst
,
float
thresh
)
for
(;
i
<
src_len
-
47
;
i
+=
48
)
{
// Load 3x uint8x16 and deinterleave into vectors of each channel
v_load_deinterleave
(
&
src_data
[
i
],
v_inB
,
v_inG
,
v_inR
);
Mat
src
=
_src
.
getMat
();
CV_Assert
(
!
src
.
empty
(
));
CV_Assert
(
src
.
isContinuous
(
));
// Get min and max
v_min_val
=
v_min
(
v_inB
,
v_min
(
v_inG
,
v_inR
));
v_max_val
=
v_max
(
v_inB
,
v_max
(
v_inG
,
v_inR
));
// TODO: Handle CV_8UC1
// TODO: Handle types other than CV_8U
CV_Assert
(
src
.
type
()
==
CV_8UC3
);
// Split into two ushort vectors per channel
v_expand
(
v_inB
,
v_iB1
,
v_iB2
);
v_expand
(
v_inG
,
v_iG1
,
v_iG2
);
v_expand
(
v_inR
,
v_iR1
,
v_iR2
);
v_expand
(
v_min_val
,
v_min1
,
v_min2
);
v_expand
(
v_max_val
,
v_max1
,
v_max2
);
_dst
.
create
(
src
.
size
(),
src
.
type
());
Mat
dst
=
_dst
.
getMat
(
);
CV_Assert
(
dst
.
isContinuous
()
);
// Calculate masks
v_m1
=
~
((
v_max1
-
v_min1
)
*
v_255
>
v_thresh
*
v_max1
);
v_m2
=
~
((
v_max2
-
v_min2
)
*
v_255
>
v_thresh
*
v_max2
);
int
width
=
src
.
cols
,
height
=
src
.
rows
,
N
=
width
*
height
,
N3
=
N
*
3
;
// Apply masks
v_iB1
=
(
v_iB1
&
v_m1
)
+
(
v_iB2
&
v_m2
);
v_iG1
=
(
v_iG1
&
v_m1
)
+
(
v_iG2
&
v_m2
);
v_iR1
=
(
v_iR1
&
v_m1
)
+
(
v_iR2
&
v_m2
)
;
// Calculate sum of pixel values of each channel
const
uchar
*
src_data
=
src
.
ptr
<
uchar
>
(
0
);
unsigned
long
sum1
=
0
,
sum2
=
0
,
sum3
=
0
;
unsigned
int
thresh255
=
cvRound
(
thresh
*
255
);
// Split and add to the sums:
v_expand
(
v_iB1
,
v_uint1
,
v_uint2
);
v_SB
+=
v_uint1
+
v_uint2
;
v_expand
(
v_iG1
,
v_uint1
,
v_uint2
);
v_SG
+=
v_uint1
+
v_uint2
;
v_expand
(
v_iR1
,
v_uint1
,
v_uint2
);
v_SR
+=
v_uint1
+
v_uint2
;
}
sumB
=
v_reduce_sum
(
v_SB
);
sumG
=
v_reduce_sum
(
v_SG
);
sumR
=
v_reduce_sum
(
v_SR
);
#endif
unsigned
int
minRGB
,
maxRGB
;
for
(;
i
<
src_len
;
i
+=
3
)
{
minRGB
=
min
(
src_data
[
i
],
min
(
src_data
[
i
+
1
],
src_data
[
i
+
2
]));
maxRGB
=
max
(
src_data
[
i
],
max
(
src_data
[
i
+
1
],
src_data
[
i
+
2
]));
if
((
maxRGB
-
minRGB
)
*
255
>
thresh255
*
maxRGB
)
continue
;
sumB
+=
src_data
[
i
];
sumG
+=
src_data
[
i
+
1
];
sumR
+=
src_data
[
i
+
2
];
}
}
/* Computes sums for each channel, while ignoring saturated pixels which are determined by thresh
* (version for CV_16UC3)
*/
void
calculateChannelSums
(
uint64
&
sumB
,
uint64
&
sumG
,
uint64
&
sumR
,
ushort
*
src_data
,
int
src_len
,
float
thresh
)
{
sumB
=
sumG
=
sumR
=
0
;
uint
thresh65535
=
cvRound
(
thresh
*
65535
);
int
i
=
0
;
#if CV_SIMD128
v_uint8x16
v_inB
,
v_inG
,
v_inR
;
v_uint16x8
v_s1
,
v_s2
;
v_uint32x4
v_iB1
,
v_iB2
,
v_iB3
,
v_iB4
,
v_iG1
,
v_iG2
,
v_iG3
,
v_iG4
,
v_iR1
,
v_iR2
,
v_iR3
,
v_iR4
,
v_255
=
v_setall_u32
(
255
),
v_thresh
=
v_setall_u32
(
thresh255
),
v_min1
,
v_min2
,
v_min3
,
v_min4
,
v_max1
,
v_max2
,
v_max3
,
v_max4
,
v_m1
,
v_m2
,
v_m3
,
v_m4
,
v_SB
=
v_setzero_u32
(),
v_SG
=
v_setzero_u32
(),
v_SR
=
v_setzero_u32
();
for
(
;
i
<
N3
-
47
;
i
+=
48
)
{
// NOTE: This block assumes BGR channels in naming variables
v_uint16x8
v_inB
,
v_inG
,
v_inR
,
v_min_val
,
v_max_val
;
v_uint32x4
v_iB1
,
v_iB2
,
v_iG1
,
v_iG2
,
v_iR1
,
v_iR2
;
v_uint32x4
v_min1
,
v_min2
,
v_max1
,
v_max2
,
v_m1
,
v_m2
;
v_uint32x4
v_65535
=
v_setall_u32
(
65535
),
v_thresh
=
v_setall_u32
(
thresh65535
);
v_uint64x2
v_u64_1
,
v_u64_2
;
v_uint64x2
v_SB
=
v_setzero_u64
(),
v_SG
=
v_setzero_u64
(),
v_SR
=
v_setzero_u64
();
// Load 3x uint8x16 and deinterleave into vectors of each channel
for
(;
i
<
src_len
-
23
;
i
+=
24
)
{
// Load 3x uint16x8 and deinterleave into vectors of each channel
v_load_deinterleave
(
&
src_data
[
i
],
v_inB
,
v_inG
,
v_inR
);
// Split into four int vectors per channel
v_expand
(
v_inB
,
v_s1
,
v_s2
);
v_expand
(
v_s1
,
v_iB1
,
v_iB2
);
v_expand
(
v_s2
,
v_iB3
,
v_iB4
);
// Get min and max
v_min_val
=
v_min
(
v_inB
,
v_min
(
v_inG
,
v_inR
));
v_max_val
=
v_max
(
v_inB
,
v_max
(
v_inG
,
v_inR
));
v_expand
(
v_inG
,
v_s1
,
v_s2
);
v_expand
(
v_s1
,
v_iG1
,
v_iG2
);
v_expand
(
v_s2
,
v_iG3
,
v_iG4
);
v_expand
(
v_inR
,
v_s1
,
v_s2
);
v_expand
(
v_s1
,
v_iR1
,
v_iR2
);
v_expand
(
v_s2
,
v_iR3
,
v_iR4
);
// Get mins and maxs
v_min1
=
v_min
(
v_iB1
,
v_min
(
v_iG1
,
v_iR1
));
v_min2
=
v_min
(
v_iB2
,
v_min
(
v_iG2
,
v_iR2
));
v_min3
=
v_min
(
v_iB3
,
v_min
(
v_iG3
,
v_iR3
));
v_min4
=
v_min
(
v_iB4
,
v_min
(
v_iG4
,
v_iR4
));
v_max1
=
v_max
(
v_iB1
,
v_max
(
v_iG1
,
v_iR1
));
v_max2
=
v_max
(
v_iB2
,
v_max
(
v_iG2
,
v_iR2
));
v_max3
=
v_max
(
v_iB3
,
v_max
(
v_iG3
,
v_iR3
));
v_max4
=
v_max
(
v_iB4
,
v_max
(
v_iG4
,
v_iR4
));
// Split into two uint vectors per channel
v_expand
(
v_inB
,
v_iB1
,
v_iB2
);
v_expand
(
v_inG
,
v_iG1
,
v_iG2
);
v_expand
(
v_inR
,
v_iR1
,
v_iR2
);
v_expand
(
v_min_val
,
v_min1
,
v_min2
);
v_expand
(
v_max_val
,
v_max1
,
v_max2
);
// Calculate masks
v_m1
=
~
((
v_max1
-
v_min1
)
*
v_255
>
v_thresh
*
v_max1
);
v_m2
=
~
((
v_max2
-
v_min2
)
*
v_255
>
v_thresh
*
v_max2
);
v_m3
=
~
((
v_max3
-
v_min3
)
*
v_255
>
v_thresh
*
v_max3
);
v_m4
=
~
((
v_max4
-
v_min4
)
*
v_255
>
v_thresh
*
v_max4
);
v_m1
=
~
((
v_max1
-
v_min1
)
*
v_65535
>
v_thresh
*
v_max1
);
v_m2
=
~
((
v_max2
-
v_min2
)
*
v_65535
>
v_thresh
*
v_max2
);
// Apply mask
v_SB
+=
(
v_iB1
&
v_m1
)
+
(
v_iB2
&
v_m2
)
+
(
v_iB3
&
v_m3
)
+
(
v_iB4
&
v_m4
);
v_SG
+=
(
v_iG1
&
v_m1
)
+
(
v_iG2
&
v_m2
)
+
(
v_iG3
&
v_m3
)
+
(
v_iG4
&
v_m4
);
v_SR
+=
(
v_iR1
&
v_m1
)
+
(
v_iR2
&
v_m2
)
+
(
v_iR3
&
v_m3
)
+
(
v_iR4
&
v_m4
);
// Apply masks
v_iB1
=
(
v_iB1
&
v_m1
)
+
(
v_iB2
&
v_m2
);
v_iG1
=
(
v_iG1
&
v_m1
)
+
(
v_iG2
&
v_m2
);
v_iR1
=
(
v_iR1
&
v_m1
)
+
(
v_iR2
&
v_m2
);
// Split and add to the sums:
v_expand
(
v_iB1
,
v_u64_1
,
v_u64_2
);
v_SB
+=
v_u64_1
+
v_u64_2
;
v_expand
(
v_iG1
,
v_u64_1
,
v_u64_2
);
v_SG
+=
v_u64_1
+
v_u64_2
;
v_expand
(
v_iR1
,
v_u64_1
,
v_u64_2
);
v_SR
+=
v_u64_1
+
v_u64_2
;
}
// Perform final reduction
sum1
=
v_reduce_sum
(
v_SB
);
sum2
=
v_reduce_sum
(
v_SG
);
sum3
=
v_reduce_sum
(
v_SR
);
uint64
sum_arr
[
2
];
v_store
(
sum_arr
,
v_SB
);
sumB
=
sum_arr
[
0
]
+
sum_arr
[
1
];
v_store
(
sum_arr
,
v_SG
);
sumG
=
sum_arr
[
0
]
+
sum_arr
[
1
];
v_store
(
sum_arr
,
v_SR
);
sumR
=
sum_arr
[
0
]
+
sum_arr
[
1
];
#endif
unsigned
int
minRGB
,
maxRGB
;
for
(
;
i
<
N3
;
i
+=
3
)
for
(;
i
<
src_len
;
i
+=
3
)
{
minRGB
=
min
(
src_data
[
i
],
min
(
src_data
[
i
+
1
],
src_data
[
i
+
2
]));
maxRGB
=
max
(
src_data
[
i
],
max
(
src_data
[
i
+
1
],
src_data
[
i
+
2
]));
if
(
(
maxRGB
-
minRGB
)
*
255
>
thresh255
*
maxRGB
)
continue
;
sum1
+=
src_data
[
i
];
sum2
+=
src_data
[
i
+
1
];
sum3
+=
src_data
[
i
+
2
];
if
((
maxRGB
-
minRGB
)
*
65535
>
thresh65535
*
maxRGB
)
continue
;
sumB
+=
src_data
[
i
];
sumG
+=
src_data
[
i
+
1
];
sumR
+=
src_data
[
i
+
2
];
}
}
// Find inverse of averages
double
dinv1
=
sum1
==
0
?
0.
f
:
(
double
)
N
/
(
double
)
sum1
,
dinv2
=
sum2
==
0
?
0.
f
:
(
double
)
N
/
(
double
)
sum2
,
dinv3
=
sum3
==
0
?
0.
f
:
(
double
)
N
/
(
double
)
sum3
;
// Find maximum
double
inv_max
=
max
(
dinv1
,
max
(
dinv2
,
dinv3
));
void
applyChannelGains
(
InputArray
_src
,
OutputArray
_dst
,
float
gainB
,
float
gainG
,
float
gainR
)
{
Mat
src
=
_src
.
getMat
();
CV_Assert
(
!
src
.
empty
());
CV_Assert
(
src
.
isContinuous
());
CV_Assert
(
src
.
type
()
==
CV_8UC3
||
src
.
type
()
==
CV_16UC3
);
// Convert to floats
float
inv1
=
(
float
)
dinv1
,
inv2
=
(
float
)
dinv2
,
inv3
=
(
float
)
dinv3
;
_dst
.
create
(
src
.
size
(),
src
.
type
());
Mat
dst
=
_dst
.
getMat
();
int
N3
=
3
*
src
.
cols
*
src
.
rows
;
int
i
=
0
;
// Scale by maximum
if
(
inv_max
>
0
)
// Scale gains by their maximum (fixed point approximation works only when all gains are <=1)
float
gain_max
=
max
(
gainB
,
max
(
gainG
,
gainR
));
if
(
gain_max
>
0
)
{
inv1
=
(
float
)((
double
)
inv1
/
inv_max
)
;
inv2
=
(
float
)((
double
)
inv2
/
inv_max
)
;
inv3
=
(
float
)((
double
)
inv3
/
inv_max
)
;
gainB
/=
gain_max
;
gainG
/=
gain_max
;
gainR
/=
gain_max
;
}
if
(
src
.
type
()
==
CV_8UC3
)
{
// Fixed point arithmetic, mul by 2^8 then shift back 8 bits
int
i_inv1
=
cvRound
(
inv1
*
(
1
<<
8
)),
i_inv2
=
cvRound
(
inv2
*
(
1
<<
8
)),
i_inv3
=
cvRound
(
inv3
*
(
1
<<
8
));
// Scale input pixel values
uchar
*
dst_data
=
dst
.
ptr
<
uchar
>
(
0
);
i
=
0
;
int
i_gainB
=
cvRound
(
gainB
*
(
1
<<
8
)),
i_gainG
=
cvRound
(
gainG
*
(
1
<<
8
)),
i_gainR
=
cvRound
(
gainR
*
(
1
<<
8
));
const
uchar
*
src_data
=
src
.
ptr
<
uchar
>
();
uchar
*
dst_data
=
dst
.
ptr
<
uchar
>
();
#if CV_SIMD128
v_uint8x16
v_inB
,
v_inG
,
v_inR
;
v_uint8x16
v_outB
,
v_outG
,
v_outR
;
v_uint16x8
v_sB1
,
v_sB2
,
v_sG1
,
v_sG2
,
v_sR1
,
v_sR2
,
v_invB
=
v_setall_u16
((
unsigned
short
)
i_inv1
),
v_invG
=
v_setall_u16
((
unsigned
short
)
i_inv2
),
v_invR
=
v_setall_u16
((
unsigned
short
)
i_inv3
);
v_uint16x8
v_sB1
,
v_sB2
,
v_sG1
,
v_sG2
,
v_sR1
,
v_sR2
;
v_uint16x8
v_gainB
=
v_setall_u16
((
ushort
)
i_gainB
),
v_gainG
=
v_setall_u16
((
ushort
)
i_gainG
),
v_gainR
=
v_setall_u16
((
ushort
)
i_gainR
);
for
(
;
i
<
N3
-
47
;
i
+=
48
)
for
(
;
i
<
N3
-
47
;
i
+=
48
)
{
// Load
16 x 8bit uchars
// Load
3x uint8x16 and deinterleave into vectors of each channel
v_load_deinterleave
(
&
src_data
[
i
],
v_inB
,
v_inG
,
v_inR
);
// Split into
four in
t vectors per channel
// Split into
two ushor
t vectors per channel
v_expand
(
v_inB
,
v_sB1
,
v_sB2
);
v_expand
(
v_inG
,
v_sG1
,
v_sG2
);
v_expand
(
v_inR
,
v_sR1
,
v_sR2
);
// Multiply by
scaling factor
s
v_sB1
=
(
v_sB1
*
v_
inv
B
)
>>
8
;
v_sB2
=
(
v_sB2
*
v_
inv
B
)
>>
8
;
v_sG1
=
(
v_sG1
*
v_
inv
G
)
>>
8
;
v_sG2
=
(
v_sG2
*
v_
inv
G
)
>>
8
;
v_sR1
=
(
v_sR1
*
v_
inv
R
)
>>
8
;
v_sR2
=
(
v_sR2
*
v_
inv
R
)
>>
8
;
// Multiply by
gain
s
v_sB1
=
(
v_sB1
*
v_
gain
B
)
>>
8
;
v_sB2
=
(
v_sB2
*
v_
gain
B
)
>>
8
;
v_sG1
=
(
v_sG1
*
v_
gain
G
)
>>
8
;
v_sG2
=
(
v_sG2
*
v_
gain
G
)
>>
8
;
v_sR1
=
(
v_sR1
*
v_
gain
R
)
>>
8
;
v_sR2
=
(
v_sR2
*
v_
gain
R
)
>>
8
;
// Pack into vectors of v_uint8x16
v_store_interleave
(
&
dst_data
[
i
],
v_pack
(
v_sB1
,
v_sB2
),
v_pack
(
v_sG1
,
v_sG2
),
v_pack
(
v_sR1
,
v_sR2
));
v_store_interleave
(
&
dst_data
[
i
],
v_pack
(
v_sB1
,
v_sB2
),
v_pack
(
v_sG1
,
v_sG2
),
v_pack
(
v_sR1
,
v_sR2
));
}
#endif
for
(
;
i
<
N3
;
i
+=
3
)
for
(
;
i
<
N3
;
i
+=
3
)
{
dst_data
[
i
]
=
(
uchar
)((
src_data
[
i
]
*
i_inv1
)
>>
8
);
dst_data
[
i
+
1
]
=
(
uchar
)((
src_data
[
i
+
1
]
*
i_
inv2
)
>>
8
);
dst_data
[
i
+
2
]
=
(
uchar
)((
src_data
[
i
+
2
]
*
i_
inv3
)
>>
8
);
dst_data
[
i
]
=
(
uchar
)((
src_data
[
i
]
*
i_gainB
)
>>
8
);
dst_data
[
i
+
1
]
=
(
uchar
)((
src_data
[
i
+
1
]
*
i_
gainG
)
>>
8
);
dst_data
[
i
+
2
]
=
(
uchar
)((
src_data
[
i
+
2
]
*
i_
gainR
)
>>
8
);
}
}
else
if
(
src
.
type
()
==
CV_16UC3
)
{
// Fixed point arithmetic, mul by 2^16 then shift back 16 bits
int
i_gainB
=
cvRound
(
gainB
*
(
1
<<
16
)),
i_gainG
=
cvRound
(
gainG
*
(
1
<<
16
)),
i_gainR
=
cvRound
(
gainR
*
(
1
<<
16
));
const
ushort
*
src_data
=
src
.
ptr
<
ushort
>
();
ushort
*
dst_data
=
dst
.
ptr
<
ushort
>
();
#if CV_SIMD128
v_uint16x8
v_inB
,
v_inG
,
v_inR
;
v_uint16x8
v_outB
,
v_outG
,
v_outR
;
v_uint32x4
v_sB1
,
v_sB2
,
v_sG1
,
v_sG2
,
v_sR1
,
v_sR2
;
v_uint32x4
v_gainB
=
v_setall_u32
((
uint
)
i_gainB
),
v_gainG
=
v_setall_u32
((
uint
)
i_gainG
),
v_gainR
=
v_setall_u32
((
uint
)
i_gainR
);
for
(;
i
<
N3
-
23
;
i
+=
24
)
{
// Load 3x uint16x8 and deinterleave into vectors of each channel
v_load_deinterleave
(
&
src_data
[
i
],
v_inB
,
v_inG
,
v_inR
);
// Split into two uint vectors per channel
v_expand
(
v_inB
,
v_sB1
,
v_sB2
);
v_expand
(
v_inG
,
v_sG1
,
v_sG2
);
v_expand
(
v_inR
,
v_sR1
,
v_sR2
);
// Multiply by scaling factors
v_sB1
=
(
v_sB1
*
v_gainB
)
>>
16
;
v_sB2
=
(
v_sB2
*
v_gainB
)
>>
16
;
v_sG1
=
(
v_sG1
*
v_gainG
)
>>
16
;
v_sG2
=
(
v_sG2
*
v_gainG
)
>>
16
;
v_sR1
=
(
v_sR1
*
v_gainR
)
>>
16
;
v_sR2
=
(
v_sR2
*
v_gainR
)
>>
16
;
// Pack into vectors of v_uint16x8
v_store_interleave
(
&
dst_data
[
i
],
v_pack
(
v_sB1
,
v_sB2
),
v_pack
(
v_sG1
,
v_sG2
),
v_pack
(
v_sR1
,
v_sR2
));
}
#endif
for
(;
i
<
N3
;
i
+=
3
)
{
dst_data
[
i
]
=
(
ushort
)((
src_data
[
i
]
*
i_gainB
)
>>
16
);
dst_data
[
i
+
1
]
=
(
ushort
)((
src_data
[
i
+
1
]
*
i_gainG
)
>>
16
);
dst_data
[
i
+
2
]
=
(
ushort
)((
src_data
[
i
+
2
]
*
i_gainR
)
>>
16
);
}
}
}
void
autowbGrayworld
(
InputArray
_src
,
OutputArray
_dst
,
float
thresh
)
{
Mat
src
=
_src
.
getMat
();
CV_Assert
(
!
src
.
empty
());
CV_Assert
(
src
.
isContinuous
());
CV_Assert
(
src
.
type
()
==
CV_8UC3
||
src
.
type
()
==
CV_16UC3
);
int
N
=
src
.
cols
*
src
.
rows
,
N3
=
N
*
3
;
double
dsumB
=
0.0
,
dsumG
=
0.0
,
dsumR
=
0.0
;
if
(
src
.
type
()
==
CV_8UC3
)
{
uint
sumB
=
0
,
sumG
=
0
,
sumR
=
0
;
calculateChannelSums
(
sumB
,
sumG
,
sumR
,
src
.
ptr
<
uchar
>
(),
N3
,
thresh
);
dsumB
=
(
double
)
sumB
;
dsumG
=
(
double
)
sumG
;
dsumR
=
(
double
)
sumR
;
}
else
if
(
src
.
type
()
==
CV_16UC3
)
{
uint64
sumB
=
0
,
sumG
=
0
,
sumR
=
0
;
calculateChannelSums
(
sumB
,
sumG
,
sumR
,
src
.
ptr
<
ushort
>
(),
N3
,
thresh
);
dsumB
=
(
double
)
sumB
;
dsumG
=
(
double
)
sumG
;
dsumR
=
(
double
)
sumR
;
}
// Find inverse of averages
double
max_sum
=
max
(
dsumB
,
max
(
dsumR
,
dsumG
));
const
double
eps
=
0.1
;
float
dinvB
=
dsumB
<
eps
?
0.
f
:
(
float
)(
max_sum
/
dsumB
),
dinvG
=
dsumG
<
eps
?
0.
f
:
(
float
)(
max_sum
/
dsumG
),
dinvR
=
dsumR
<
eps
?
0.
f
:
(
float
)(
max_sum
/
dsumR
);
}}
// Use the inverse of averages as channel gains:
applyChannelGains
(
src
,
_dst
,
dinvB
,
dinvG
,
dinvR
);
}
}
}
modules/xphoto/src/learn_color_balance.py
0 → 100644
View file @
80063fd4
#!/usr/bin/env python
from
__future__
import
print_function
import
os
,
sys
,
argparse
import
numpy
as
np
import
scipy.io
from
sklearn.tree
import
DecisionTreeRegressor
import
cv2
import
random
def
parse_sequence
(
input_str
):
if
len
(
input_str
)
==
0
:
return
[]
else
:
return
[
o
.
strip
()
for
o
in
input_str
.
split
(
","
)
if
o
]
def
convert_to_8bit
(
arr
,
clip_percentile
=
2.5
):
arr
=
np
.
clip
(
arr
*
(
255.0
/
np
.
percentile
(
arr
,
100
-
clip_percentile
)),
0
,
255
)
return
arr
.
astype
(
np
.
uint8
)
def
learn_regression_tree_ensemble
(
img_features
,
gt_illuminants
,
num_trees
,
max_tree_depth
):
eps
=
0.001
inst
=
[[
img_features
[
i
],
gt_illuminants
[
i
][
0
]
/
(
sum
(
gt_illuminants
[
i
])
+
eps
),
gt_illuminants
[
i
][
1
]
/
(
sum
(
gt_illuminants
[
i
])
+
eps
)]
for
i
in
range
(
len
(
img_features
))]
inst
.
sort
(
key
=
lambda
obj
:
obj
[
1
])
#sort by r chromaticity
stride
=
int
(
np
.
ceil
(
len
(
inst
)
/
float
(
num_trees
+
1
)))
sz
=
2
*
stride
dst_model
=
[]
for
tree_idx
in
range
(
num_trees
):
#local group in the training data is additionally weighted by num_trees
local_group_range
=
range
(
tree_idx
*
stride
,
min
(
tree_idx
*
stride
+
sz
,
len
(
inst
)))
X
=
num_trees
*
[
inst
[
i
][
0
]
for
i
in
local_group_range
]
y_r
=
num_trees
*
[
inst
[
i
][
1
]
for
i
in
local_group_range
]
y_g
=
num_trees
*
[
inst
[
i
][
2
]
for
i
in
local_group_range
]
#add the rest of the training data:
X
=
X
+
[
inst
[
i
][
0
]
for
i
in
range
(
len
(
inst
))
if
i
not
in
local_group_range
]
y_r
=
y_r
+
[
inst
[
i
][
1
]
for
i
in
range
(
len
(
inst
))
if
i
not
in
local_group_range
]
y_g
=
y_g
+
[
inst
[
i
][
2
]
for
i
in
range
(
len
(
inst
))
if
i
not
in
local_group_range
]
local_model
=
[]
for
feature_idx
in
range
(
len
(
X
[
0
])):
tree_r
=
DecisionTreeRegressor
(
max_depth
=
max_tree_depth
,
random_state
=
1234
)
tree_r
.
fit
([
el
[
feature_idx
][
0
]
for
el
in
X
],
y_r
)
tree_g
=
DecisionTreeRegressor
(
max_depth
=
max_tree_depth
,
random_state
=
1234
)
tree_g
.
fit
([
el
[
feature_idx
][
0
]
for
el
in
X
],
y_g
)
local_model
.
append
([
tree_r
,
tree_g
])
dst_model
.
append
(
local_model
)
return
dst_model
def
get_tree_node_lists
(
tree
,
tree_depth
):
dst_feature_idx
=
(
2
**
tree_depth
-
1
)
*
[
0
]
dst_thresh_vals
=
(
2
**
tree_depth
-
1
)
*
[
.
5
]
dst_leaf_vals
=
(
2
**
tree_depth
)
*
[
-
1
]
leaf_idx_offset
=
(
2
**
tree_depth
-
1
)
left
=
tree
.
tree_
.
children_left
right
=
tree
.
tree_
.
children_right
threshold
=
tree
.
tree_
.
threshold
value
=
tree
.
tree_
.
value
feature
=
tree
.
tree_
.
feature
def
recurse
(
left
,
right
,
threshold
,
feature
,
node
,
dst_idx
,
cur_depth
):
if
(
threshold
[
node
]
!=
-
2
):
dst_feature_idx
[
dst_idx
]
=
feature
[
node
]
dst_thresh_vals
[
dst_idx
]
=
threshold
[
node
]
if
left
[
node
]
!=
-
1
:
recurse
(
left
,
right
,
threshold
,
feature
,
left
[
node
],
2
*
dst_idx
+
1
,
cur_depth
+
1
)
if
right
[
node
]
!=
-
1
:
recurse
(
left
,
right
,
threshold
,
feature
,
right
[
node
],
2
*
dst_idx
+
2
,
cur_depth
+
1
)
else
:
range_start
=
2
**
(
tree_depth
-
cur_depth
)
*
dst_idx
+
(
2
**
(
tree_depth
-
cur_depth
)
-
1
)
-
leaf_idx_offset
range_end
=
2
**
(
tree_depth
-
cur_depth
)
*
dst_idx
+
(
2
**
(
tree_depth
-
cur_depth
+
1
)
-
2
)
-
leaf_idx_offset
+
1
dst_leaf_vals
[
range_start
:
range_end
]
=
(
range_end
-
range_start
)
*
[
value
[
node
][
0
][
0
]]
recurse
(
left
,
right
,
threshold
,
feature
,
0
,
0
,
0
)
return
(
dst_feature_idx
,
dst_thresh_vals
,
dst_leaf_vals
)
def
generate_code
(
model
,
input_params
):
feature_idx
=
[]
thresh_vals
=
[]
leaf_vals
=
[]
depth
=
int
(
input_params
[
"--max_tree_depth"
])
for
local_model
in
model
:
for
feature
in
local_model
:
(
local_feature_idx
,
local_thresh_vals
,
local_leaf_vals
)
=
get_tree_node_lists
(
feature
[
0
],
depth
)
feature_idx
+=
local_feature_idx
thresh_vals
+=
local_thresh_vals
leaf_vals
+=
local_leaf_vals
(
local_feature_idx
,
local_thresh_vals
,
local_leaf_vals
)
=
get_tree_node_lists
(
feature
[
1
],
depth
)
feature_idx
+=
local_feature_idx
thresh_vals
+=
local_thresh_vals
leaf_vals
+=
local_leaf_vals
res
=
"/* This file was automatically generated by learn_color_balance.py script
\n
"
+
\
" * using the following parameters:
\n
"
for
key
in
input_params
:
res
+=
" "
+
key
+
" "
+
input_params
[
key
]
res
+=
"
\n
*/
\n
"
res
+=
"const int num_trees = "
+
str
(
len
(
model
))
+
";
\n
"
res
+=
"const int num_features = 4;
\n
"
res
+=
"const int num_tree_nodes = "
+
str
(
2
**
depth
)
+
";
\n
"
res
+=
"unsigned char feature_idx[num_trees*num_features*2*(num_tree_nodes-1)] = {"
+
str
(
feature_idx
[
0
])
for
i
in
range
(
1
,
len
(
feature_idx
)):
res
+=
","
+
str
(
feature_idx
[
i
])
res
+=
"};
\n
"
res
+=
"float thresh_vals[num_trees*num_features*2*(num_tree_nodes-1)] = {"
+
(
"
%.3
ff"
%
thresh_vals
[
0
])[
1
:]
for
i
in
range
(
1
,
len
(
thresh_vals
)):
res
+=
","
+
(
"
%.3
ff"
%
thresh_vals
[
i
])[
1
:]
res
+=
"};
\n
"
res
+=
"float leaf_vals[num_trees*num_features*2*num_tree_nodes] = {"
+
(
"
%.3
ff"
%
leaf_vals
[
0
])[
1
:]
for
i
in
range
(
1
,
len
(
leaf_vals
)):
res
+=
","
+
(
"
%.3
ff"
%
leaf_vals
[
i
])[
1
:]
res
+=
"};
\n
"
return
res
if
__name__
==
'__main__'
:
parser
=
argparse
.
ArgumentParser
(
description
=
(
"A tool for training the learning-based "
"color balance algorithm. Currently supports "
"training only on the Gehler-Shi and NUS 8-camera datasets."
),
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
)
parser
.
add_argument
(
"-i"
,
"--input_folder"
,
metavar
=
"INPUT_FOLDER"
,
default
=
""
,
help
=
(
"Folder containing the training dataset. Assumes minimally "
"processed png images like in the Gehler-Shi (http://www.cs.sfu.ca/~colour/data/shi_gehler/) "
"or NUS 8-camera (http://www.comp.nus.edu.sg/~whitebal/illuminant/illuminant.html) datasets"
))
parser
.
add_argument
(
"-g"
,
"--ground_truth"
,
metavar
=
"GROUND_TRUTH"
,
default
=
"real_illum_568..mat"
,
help
=
(
"Path to the mat file containing ground truth illuminations. Currently "
"supports formats supplied by the Gehler-Shi and NUS 8-camera datasets."
))
parser
.
add_argument
(
"-r"
,
"--range"
,
metavar
=
"RANGE"
,
default
=
"0,0"
,
help
=
"Range of images from the input dataset to use for training"
)
parser
.
add_argument
(
"-o"
,
"--out"
,
metavar
=
"OUT"
,
default
=
"learning_based_color_balance_model.hpp"
,
help
=
"Path to the output learnt model"
)
parser
.
add_argument
(
"--hist_bin_num"
,
metavar
=
"HIST_BIN_NUM"
,
default
=
"64"
,
help
=
(
"Size of one dimension of a three-dimensional RGB histogram employed in the "
"feature extraction step."
))
parser
.
add_argument
(
"--num_trees"
,
metavar
=
"NUM_TREES"
,
default
=
"20"
,
help
=
(
"Parameter to control the size of the regression tree ensemble"
))
parser
.
add_argument
(
"--max_tree_depth"
,
metavar
=
"MAX_TREE_DEPTH"
,
default
=
"4"
,
help
=
(
"Maxmimum depth of regression trees constructed during training."
))
parser
.
add_argument
(
"-a"
,
"--num_augmented"
,
metavar
=
"NUM_AUGMENTED"
,
default
=
"2"
,
help
=
(
"Number of augmented samples per one training image. Training set "
"augmentation tends to improve the learnt model robustness."
))
args
,
other_args
=
parser
.
parse_known_args
()
if
not
os
.
path
.
exists
(
args
.
input_folder
):
print
(
"Error: "
+
args
.
input_folder
+
(
" does not exist. Please, correctly "
"specify the -i parameter"
))
sys
.
exit
(
1
)
if
not
os
.
path
.
exists
(
args
.
ground_truth
):
print
(
"Error: "
+
args
.
ground_truth
+
(
" does not exist. Please, correctly "
"specify the -g parameter"
))
sys
.
exit
(
1
)
img_range
=
map
(
int
,
parse_sequence
(
args
.
range
))
if
len
(
img_range
)
!=
2
:
print
(
"Error: Please specify the -r parameter in form <first_image_index>,<last_image_index>"
)
sys
.
exit
(
1
)
hist_bin_num
=
int
(
args
.
hist_bin_num
)
num_trees
=
int
(
args
.
num_trees
)
max_tree_depth
=
int
(
args
.
max_tree_depth
)
gt
=
scipy
.
io
.
loadmat
(
args
.
ground_truth
)
img_files
=
sorted
(
os
.
listdir
(
args
.
input_folder
))
base_gt_illuminants
=
[]
black_levels
=
[]
if
"groundtruth_illuminants"
in
gt
.
keys
()
and
"darkness_level"
in
gt
.
keys
():
#NUS 8-camera dataset format
base_gt_illuminants
=
gt
[
"groundtruth_illuminants"
]
black_levels
=
len
(
gt_illuminants
)
*
[
gt
[
"darkness_level"
][
0
][
0
]]
elif
"real_rgb"
in
gt
.
keys
():
#Gehler-Shi dataset format
base_gt_illuminants
=
gt
[
"real_rgb"
]
black_levels
=
87
*
[
0
]
+
(
len
(
base_gt_illuminants
)
-
87
)
*
[
129
]
else
:
print
(
"Error: unknown ground-truth format, only formats of Gehler-Shi and NUS 8-camera datasets are supported"
)
sys
.
exit
(
1
)
features
=
[]
gt_illuminants
=
[]
i
=
0
sz
=
len
(
img_files
)
random
.
seed
(
1234
)
for
file
in
img_files
:
if
(
i
>=
img_range
[
0
]
and
i
<
img_range
[
1
])
or
(
img_range
[
0
]
==
img_range
[
1
]
==
0
):
cur_path
=
os
.
path
.
join
(
args
.
input_folder
,
file
)
im
=
cv2
.
imread
(
cur_path
,
-
1
)
.
astype
(
np
.
float32
)
im
-=
black_levels
[
i
]
im_8bit
=
convert_to_8bit
(
im
)
cur_img_features
=
cv2
.
xphoto
.
extractSimpleFeatures
(
im_8bit
,
None
,
255
,
0.98
,
hist_bin_num
)
features
.
append
(
cur_img_features
.
tolist
())
gt_illuminants
.
append
(
base_gt_illuminants
[
i
]
.
tolist
())
for
iter
in
range
(
int
(
args
.
num_augmented
)):
R_coef
=
random
.
uniform
(
0.2
,
5.0
)
G_coef
=
random
.
uniform
(
0.2
,
5.0
)
B_coef
=
random
.
uniform
(
0.2
,
5.0
)
im_8bit
=
im
im_8bit
[:,:,
0
]
*=
B_coef
im_8bit
[:,:,
1
]
*=
G_coef
im_8bit
[:,:,
2
]
*=
R_coef
im_8bit
=
convert_to_8bit
(
im
)
cur_img_features
=
cv2
.
xphoto
.
extractSimpleFeatures
(
im_8bit
,
None
,
255
,
0.98
,
hist_bin_num
)
features
.
append
(
cur_img_features
.
tolist
())
illum
=
base_gt_illuminants
[
i
]
illum
[
0
]
*=
R_coef
illum
[
1
]
*=
G_coef
illum
[
2
]
*=
B_coef
gt_illuminants
.
append
(
illum
.
tolist
())
sys
.
stdout
.
write
(
"Computing features: [
%3
d/
%3
d]
\r
"
%
(
i
,
sz
)),
sys
.
stdout
.
flush
()
i
+=
1
print
(
"
\n
Learning the model..."
)
model
=
learn_regression_tree_ensemble
(
features
,
gt_illuminants
,
num_trees
,
max_tree_depth
)
print
(
"Generating code..."
)
str
=
generate_code
(
model
,{
"-r"
:
args
.
range
,
"--hist_bin_num"
:
args
.
hist_bin_num
,
"--num_trees"
:
args
.
num_trees
,
"--max_tree_depth"
:
args
.
max_tree_depth
,
"--num_augmented"
:
args
.
num_augmented
})
f
=
open
(
args
.
out
,
"w"
)
f
.
write
(
str
)
f
.
close
()
print
(
"Done"
)
modules/xphoto/src/learning_based_color_balance.cpp
0 → 100644
View file @
80063fd4
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "learning_based_color_balance_model.hpp"
#include "opencv2/core.hpp"
#include "opencv2/core/hal/intrin.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/xphoto.hpp"
using
namespace
std
;
#define EPS 0.00001f
namespace
cv
{
namespace
xphoto
{
inline
void
getChromaticity
(
Vec2f
&
dst
,
float
R
,
float
G
,
float
B
)
{
dst
[
0
]
=
R
/
(
R
+
G
+
B
+
EPS
);
dst
[
1
]
=
G
/
(
R
+
G
+
B
+
EPS
);
}
struct
hist_elem
{
float
hist_val
;
float
r
,
g
;
hist_elem
(
float
_hist_val
,
Vec2f
chromaticity
)
:
hist_val
(
_hist_val
),
r
(
chromaticity
[
0
]),
g
(
chromaticity
[
1
])
{}
};
bool
operator
<
(
const
hist_elem
&
a
,
const
hist_elem
&
b
);
void
getColorPalleteMode
(
Vec2f
&
dst
,
hist_elem
*
pallete
,
int
pallete_sz
,
float
bandwidth
);
void
preprocessing
(
Mat
&
dst_mask
,
int
&
dst_max_val
,
Mat
&
src
,
int
range_max_val
,
float
saturation_thresh
);
void
getAverageAndBrightestColorChromaticity
(
Vec2f
&
average_chromaticity
,
Vec2f
&
brightest_chromaticity
,
Mat
&
src
,
Mat
&
mask
);
void
getHistogramBasedFeatures
(
Vec2f
&
dominant_chromaticity
,
Vec2f
&
chromaticity_pallete_mode
,
Mat
&
src
,
Mat
&
mask
,
int
hist_bin_num
,
int
max_val
);
bool
operator
<
(
const
hist_elem
&
a
,
const
hist_elem
&
b
)
{
return
a
.
hist_val
>
b
.
hist_val
;
}
/* Returns the most high-density point (i.e. mode) of the color pallete.
* Uses a simplistic kernel density estimator with a Epanechnikov kernel and
* fixed bandwidth.
*/
void
getColorPalleteMode
(
Vec2f
&
dst
,
hist_elem
*
pallete
,
int
pallete_sz
,
float
bandwidth
)
{
float
max_density
=
-
1.0
f
;
float
denom
=
bandwidth
*
bandwidth
;
for
(
int
i
=
0
;
i
<
pallete_sz
;
i
++
)
{
float
cur_density
=
0.0
f
;
float
cur_dist_sq
;
for
(
int
j
=
0
;
j
<
pallete_sz
;
j
++
)
{
cur_dist_sq
=
(
pallete
[
i
].
r
-
pallete
[
j
].
r
)
*
(
pallete
[
i
].
r
-
pallete
[
j
].
r
)
+
(
pallete
[
i
].
g
-
pallete
[
j
].
g
)
*
(
pallete
[
i
].
g
-
pallete
[
j
].
g
);
cur_density
+=
max
((
1.0
f
-
(
cur_dist_sq
/
denom
)),
0.0
f
);
}
if
(
cur_density
>
max_density
)
{
max_density
=
cur_density
;
dst
[
0
]
=
pallete
[
i
].
r
;
dst
[
1
]
=
pallete
[
i
].
g
;
}
}
}
/* Computes a mask for non-saturated pixels and maximum pixel value
* which are then used for feature computation
*/
void
preprocessing
(
Mat
&
dst_mask
,
int
&
dst_max_val
,
Mat
&
src
,
int
range_max_val
,
float
saturation_thresh
)
{
dst_mask
=
Mat
(
src
.
size
(),
CV_8U
);
uchar
*
mask_ptr
=
dst_mask
.
ptr
<
uchar
>
();
int
src_len
=
src
.
rows
*
src
.
cols
;
int
thresh
=
(
int
)(
saturation_thresh
*
range_max_val
);
int
i
=
0
;
int
local_max
;
dst_max_val
=
-
1
;
if
(
src
.
type
()
==
CV_8UC3
)
{
uchar
*
src_ptr
=
src
.
ptr
<
uchar
>
();
#if CV_SIMD128
v_uint8x16
v_inB
,
v_inG
,
v_inR
,
v_local_max
;
v_uint8x16
v_global_max
=
v_setall_u8
(
0
),
v_mask
,
v_thresh
=
v_setall_u8
((
uchar
)
thresh
);
for
(;
i
<
src_len
-
15
;
i
+=
16
)
{
v_load_deinterleave
(
src_ptr
+
3
*
i
,
v_inB
,
v_inG
,
v_inR
);
v_local_max
=
v_max
(
v_inB
,
v_max
(
v_inG
,
v_inR
));
v_global_max
=
v_max
(
v_local_max
,
v_global_max
);
v_mask
=
(
v_local_max
<
v_thresh
);
v_store
(
mask_ptr
+
i
,
v_mask
);
}
uchar
global_max
[
16
];
v_store
(
global_max
,
v_global_max
);
for
(
int
j
=
0
;
j
<
16
;
j
++
)
{
if
(
global_max
[
j
]
>
dst_max_val
)
dst_max_val
=
global_max
[
j
];
}
#endif
for
(;
i
<
src_len
;
i
++
)
{
local_max
=
max
(
src_ptr
[
3
*
i
],
max
(
src_ptr
[
3
*
i
+
1
],
src_ptr
[
3
*
i
+
2
]));
if
(
local_max
>
dst_max_val
)
dst_max_val
=
local_max
;
if
(
local_max
<
thresh
)
mask_ptr
[
i
]
=
255
;
else
mask_ptr
[
i
]
=
0
;
}
}
else
if
(
src
.
type
()
==
CV_16UC3
)
{
ushort
*
src_ptr
=
src
.
ptr
<
ushort
>
();
#if CV_SIMD128
v_uint16x8
v_inB
,
v_inG
,
v_inR
,
v_local_max
;
v_uint16x8
v_global_max
=
v_setall_u16
(
0
),
v_mask
,
v_thresh
=
v_setall_u16
((
ushort
)
thresh
);
for
(;
i
<
src_len
-
7
;
i
+=
8
)
{
v_load_deinterleave
(
src_ptr
+
3
*
i
,
v_inB
,
v_inG
,
v_inR
);
v_local_max
=
v_max
(
v_inB
,
v_max
(
v_inG
,
v_inR
));
v_global_max
=
v_max
(
v_local_max
,
v_global_max
);
v_mask
=
(
v_local_max
<
v_thresh
);
v_pack_store
(
mask_ptr
+
i
,
v_mask
);
}
ushort
global_max
[
8
];
v_store
(
global_max
,
v_global_max
);
for
(
int
j
=
0
;
j
<
8
;
j
++
)
{
if
(
global_max
[
j
]
>
dst_max_val
)
dst_max_val
=
global_max
[
j
];
}
#endif
for
(;
i
<
src_len
;
i
++
)
{
local_max
=
max
(
src_ptr
[
3
*
i
],
max
(
src_ptr
[
3
*
i
+
1
],
src_ptr
[
3
*
i
+
2
]));
if
(
local_max
>
dst_max_val
)
dst_max_val
=
local_max
;
if
(
local_max
<
thresh
)
mask_ptr
[
i
]
=
255
;
else
mask_ptr
[
i
]
=
0
;
}
}
}
void
getAverageAndBrightestColorChromaticity
(
Vec2f
&
average_chromaticity
,
Vec2f
&
brightest_chromaticity
,
Mat
&
src
,
Mat
&
mask
)
{
int
i
=
0
;
int
src_len
=
src
.
rows
*
src
.
cols
;
uchar
*
mask_ptr
=
mask
.
ptr
<
uchar
>
();
uint
brightestB
=
0
,
brightestG
=
0
,
brightestR
=
0
;
uint
max_sum
=
0
;
if
(
src
.
type
()
==
CV_8UC3
)
{
uint
sumB
=
0
,
sumG
=
0
,
sumR
=
0
;
uchar
*
src_ptr
=
src
.
ptr
<
uchar
>
();
#if CV_SIMD128
v_uint8x16
v_inB
,
v_inG
,
v_inR
,
v_mask
;
v_uint16x8
v_sR1
,
v_sR2
,
v_sG1
,
v_sG2
,
v_sB1
,
v_sB2
,
v_sum
;
v_uint16x8
v_max_sum
=
v_setall_u16
(
0
),
v_max_mask
,
v_brightestR
,
v_brightestG
,
v_brightestB
;
v_uint32x4
v_uint1
,
v_uint2
,
v_SB
=
v_setzero_u32
(),
v_SG
=
v_setzero_u32
(),
v_SR
=
v_setzero_u32
();
for
(;
i
<
src_len
-
15
;
i
+=
16
)
{
v_load_deinterleave
(
src_ptr
+
3
*
i
,
v_inB
,
v_inG
,
v_inR
);
v_mask
=
v_load
(
mask_ptr
+
i
);
v_inB
&=
v_mask
;
v_inG
&=
v_mask
;
v_inR
&=
v_mask
;
v_expand
(
v_inB
,
v_sB1
,
v_sB2
);
v_expand
(
v_inG
,
v_sG1
,
v_sG2
);
v_expand
(
v_inR
,
v_sR1
,
v_sR2
);
// update the brightest (R,G,B) tuple (process left half):
v_sum
=
v_sB1
+
v_sG1
+
v_sR1
;
v_max_mask
=
(
v_sum
>
v_max_sum
);
v_max_sum
=
v_max
(
v_sum
,
v_max_sum
);
v_brightestB
=
(
v_sB1
&
v_max_mask
)
+
(
v_brightestB
&
(
~
v_max_mask
));
v_brightestG
=
(
v_sG1
&
v_max_mask
)
+
(
v_brightestG
&
(
~
v_max_mask
));
v_brightestR
=
(
v_sR1
&
v_max_mask
)
+
(
v_brightestR
&
(
~
v_max_mask
));
// update the brightest (R,G,B) tuple (process right half):
v_sum
=
v_sB2
+
v_sG2
+
v_sR2
;
v_max_mask
=
(
v_sum
>
v_max_sum
);
v_max_sum
=
v_max
(
v_sum
,
v_max_sum
);
v_brightestB
=
(
v_sB2
&
v_max_mask
)
+
(
v_brightestB
&
(
~
v_max_mask
));
v_brightestG
=
(
v_sG2
&
v_max_mask
)
+
(
v_brightestG
&
(
~
v_max_mask
));
v_brightestR
=
(
v_sR2
&
v_max_mask
)
+
(
v_brightestR
&
(
~
v_max_mask
));
// update sums:
v_sB1
=
v_sB1
+
v_sB2
;
v_sG1
=
v_sG1
+
v_sG2
;
v_sR1
=
v_sR1
+
v_sR2
;
v_expand
(
v_sB1
,
v_uint1
,
v_uint2
);
v_SB
+=
v_uint1
+
v_uint2
;
v_expand
(
v_sG1
,
v_uint1
,
v_uint2
);
v_SG
+=
v_uint1
+
v_uint2
;
v_expand
(
v_sR1
,
v_uint1
,
v_uint2
);
v_SR
+=
v_uint1
+
v_uint2
;
}
sumB
=
v_reduce_sum
(
v_SB
);
sumG
=
v_reduce_sum
(
v_SG
);
sumR
=
v_reduce_sum
(
v_SR
);
ushort
brightestB_arr
[
8
],
brightestG_arr
[
8
],
brightestR_arr
[
8
],
max_sum_arr
[
8
];
v_store
(
brightestB_arr
,
v_brightestB
);
v_store
(
brightestG_arr
,
v_brightestG
);
v_store
(
brightestR_arr
,
v_brightestR
);
v_store
(
max_sum_arr
,
v_max_sum
);
for
(
int
j
=
0
;
j
<
8
;
j
++
)
{
if
(
max_sum_arr
[
j
]
>
max_sum
)
{
max_sum
=
max_sum_arr
[
j
];
brightestB
=
brightestB_arr
[
j
];
brightestG
=
brightestG_arr
[
j
];
brightestR
=
brightestR_arr
[
j
];
}
}
#endif
for
(;
i
<
src_len
;
i
++
)
{
uint
sum_val
=
src_ptr
[
3
*
i
]
+
src_ptr
[
3
*
i
+
1
]
+
src_ptr
[
3
*
i
+
2
];
if
(
mask_ptr
[
i
])
{
sumB
+=
src_ptr
[
3
*
i
];
sumG
+=
src_ptr
[
3
*
i
+
1
];
sumR
+=
src_ptr
[
3
*
i
+
2
];
if
(
sum_val
>
max_sum
)
{
max_sum
=
sum_val
;
brightestB
=
src_ptr
[
3
*
i
];
brightestG
=
src_ptr
[
3
*
i
+
1
];
brightestR
=
src_ptr
[
3
*
i
+
2
];
}
}
}
double
maxRGB
=
(
double
)
max
(
sumR
,
max
(
sumG
,
sumB
));
getChromaticity
(
average_chromaticity
,
(
float
)(
sumR
/
maxRGB
),
(
float
)(
sumG
/
maxRGB
),
(
float
)(
sumB
/
maxRGB
));
getChromaticity
(
brightest_chromaticity
,
(
float
)
brightestR
,
(
float
)
brightestG
,
(
float
)
brightestB
);
}
else
if
(
src
.
type
()
==
CV_16UC3
)
{
uint64
sumB
=
0
,
sumG
=
0
,
sumR
=
0
;
ushort
*
src_ptr
=
src
.
ptr
<
ushort
>
();
#if CV_SIMD128
v_uint16x8
v_inB
,
v_inG
,
v_inR
,
v_mask
,
v_mask_lower
=
v_setall_u16
(
255
);
v_uint32x4
v_iR1
,
v_iR2
,
v_iG1
,
v_iG2
,
v_iB1
,
v_iB2
,
v_sum
;
v_uint32x4
v_max_sum
=
v_setall_u32
(
0
),
v_max_mask
,
v_brightestR
,
v_brightestG
,
v_brightestB
;
v_uint64x2
v_uint64_1
,
v_uint64_2
,
v_SB
=
v_setzero_u64
(),
v_SG
=
v_setzero_u64
(),
v_SR
=
v_setzero_u64
();
for
(;
i
<
src_len
-
7
;
i
+=
8
)
{
v_load_deinterleave
(
src_ptr
+
3
*
i
,
v_inB
,
v_inG
,
v_inR
);
v_mask
=
v_load_expand
(
mask_ptr
+
i
);
v_mask
=
v_mask
|
((
v_mask
&
v_mask_lower
)
<<
8
);
v_inB
&=
v_mask
;
v_inG
&=
v_mask
;
v_inR
&=
v_mask
;
v_expand
(
v_inB
,
v_iB1
,
v_iB2
);
v_expand
(
v_inG
,
v_iG1
,
v_iG2
);
v_expand
(
v_inR
,
v_iR1
,
v_iR2
);
// update the brightest (R,G,B) tuple (process left half):
v_sum
=
v_iB1
+
v_iG1
+
v_iR1
;
v_max_mask
=
(
v_sum
>
v_max_sum
);
v_max_sum
=
v_max
(
v_sum
,
v_max_sum
);
v_brightestB
=
(
v_iB1
&
v_max_mask
)
+
(
v_brightestB
&
(
~
v_max_mask
));
v_brightestG
=
(
v_iG1
&
v_max_mask
)
+
(
v_brightestG
&
(
~
v_max_mask
));
v_brightestR
=
(
v_iR1
&
v_max_mask
)
+
(
v_brightestR
&
(
~
v_max_mask
));
// update the brightest (R,G,B) tuple (process right half):
v_sum
=
v_iB2
+
v_iG2
+
v_iR2
;
v_max_mask
=
(
v_sum
>
v_max_sum
);
v_max_sum
=
v_max
(
v_sum
,
v_max_sum
);
v_brightestB
=
(
v_iB2
&
v_max_mask
)
+
(
v_brightestB
&
(
~
v_max_mask
));
v_brightestG
=
(
v_iG2
&
v_max_mask
)
+
(
v_brightestG
&
(
~
v_max_mask
));
v_brightestR
=
(
v_iR2
&
v_max_mask
)
+
(
v_brightestR
&
(
~
v_max_mask
));
// update sums:
v_iB1
=
v_iB1
+
v_iB2
;
v_iG1
=
v_iG1
+
v_iG2
;
v_iR1
=
v_iR1
+
v_iR2
;
v_expand
(
v_iB1
,
v_uint64_1
,
v_uint64_2
);
v_SB
+=
v_uint64_1
+
v_uint64_2
;
v_expand
(
v_iG1
,
v_uint64_1
,
v_uint64_2
);
v_SG
+=
v_uint64_1
+
v_uint64_2
;
v_expand
(
v_iR1
,
v_uint64_1
,
v_uint64_2
);
v_SR
+=
v_uint64_1
+
v_uint64_2
;
}
uint64
sum_arr
[
2
];
v_store
(
sum_arr
,
v_SB
);
sumB
=
sum_arr
[
0
]
+
sum_arr
[
1
];
v_store
(
sum_arr
,
v_SG
);
sumG
=
sum_arr
[
0
]
+
sum_arr
[
1
];
v_store
(
sum_arr
,
v_SR
);
sumR
=
sum_arr
[
0
]
+
sum_arr
[
1
];
uint
brightestB_arr
[
4
],
brightestG_arr
[
4
],
brightestR_arr
[
4
],
max_sum_arr
[
4
];
v_store
(
brightestB_arr
,
v_brightestB
);
v_store
(
brightestG_arr
,
v_brightestG
);
v_store
(
brightestR_arr
,
v_brightestR
);
v_store
(
max_sum_arr
,
v_max_sum
);
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
if
(
max_sum_arr
[
j
]
>
max_sum
)
{
max_sum
=
max_sum_arr
[
j
];
brightestB
=
brightestB_arr
[
j
];
brightestG
=
brightestG_arr
[
j
];
brightestR
=
brightestR_arr
[
j
];
}
}
#endif
for
(;
i
<
src_len
;
i
++
)
{
uint
sum_val
=
src_ptr
[
3
*
i
]
+
src_ptr
[
3
*
i
+
1
]
+
src_ptr
[
3
*
i
+
2
];
if
(
mask_ptr
[
i
])
{
sumB
+=
src_ptr
[
3
*
i
];
sumG
+=
src_ptr
[
3
*
i
+
1
];
sumR
+=
src_ptr
[
3
*
i
+
2
];
if
(
sum_val
>
max_sum
)
{
max_sum
=
sum_val
;
brightestB
=
src_ptr
[
3
*
i
];
brightestG
=
src_ptr
[
3
*
i
+
1
];
brightestR
=
src_ptr
[
3
*
i
+
2
];
}
}
}
double
maxRGB
=
(
double
)
max
(
sumR
,
max
(
sumG
,
sumB
));
getChromaticity
(
average_chromaticity
,
(
float
)(
sumR
/
maxRGB
),
(
float
)(
sumG
/
maxRGB
),
(
float
)(
sumB
/
maxRGB
));
getChromaticity
(
brightest_chromaticity
,
(
float
)
brightestR
,
(
float
)
brightestG
,
(
float
)
brightestB
);
}
}
void
getHistogramBasedFeatures
(
Vec2f
&
dominant_chromaticity
,
Vec2f
&
chromaticity_pallete_mode
,
Mat
&
src
,
Mat
&
mask
,
int
hist_bin_num
,
int
max_val
)
{
const
int
pallete_size
=
300
;
const
float
pallete_bandwidth
=
0.1
f
;
MatND
hist
;
int
channels
[]
=
{
0
,
1
,
2
};
int
histSize
[]
=
{
hist_bin_num
,
hist_bin_num
,
hist_bin_num
};
float
range
[]
=
{
0
,
(
float
)
max
(
hist_bin_num
,
max_val
)};
const
float
*
ranges
[]
=
{
range
,
range
,
range
};
calcHist
(
&
src
,
1
,
channels
,
mask
,
hist
,
3
,
histSize
,
ranges
);
int
dominant_B
=
0
,
dominant_G
=
0
,
dominant_R
=
0
;
double
max_hist_val
=
0
;
float
*
hist_ptr
=
hist
.
ptr
<
float
>
();
for
(
int
i
=
0
;
i
<
hist_bin_num
;
i
++
)
for
(
int
j
=
0
;
j
<
hist_bin_num
;
j
++
)
for
(
int
k
=
0
;
k
<
hist_bin_num
;
k
++
)
{
if
(
*
hist_ptr
>
max_hist_val
)
{
max_hist_val
=
*
hist_ptr
;
dominant_B
=
i
;
dominant_G
=
j
;
dominant_R
=
k
;
}
hist_ptr
++
;
}
getChromaticity
(
dominant_chromaticity
,
(
float
)
dominant_R
,
(
float
)
dominant_G
,
(
float
)
dominant_B
);
vector
<
hist_elem
>
pallete
;
pallete
.
reserve
(
pallete_size
);
hist_ptr
=
hist
.
ptr
<
float
>
();
// extract top pallete_size most common colors and add them to the pallete:
for
(
int
i
=
0
;
i
<
hist_bin_num
;
i
++
)
for
(
int
j
=
0
;
j
<
hist_bin_num
;
j
++
)
for
(
int
k
=
0
;
k
<
hist_bin_num
;
k
++
)
{
float
bin_count
=
*
hist_ptr
;
if
(
bin_count
<
EPS
)
{
hist_ptr
++
;
continue
;
}
Vec2f
chromaticity
;
getChromaticity
(
chromaticity
,
(
float
)
k
,
(
float
)
j
,
(
float
)
i
);
hist_elem
el
(
bin_count
,
chromaticity
);
if
(
pallete
.
size
()
<
pallete_size
)
{
pallete
.
push_back
(
el
);
if
(
pallete
.
size
()
==
pallete_size
)
make_heap
(
pallete
.
begin
(),
pallete
.
end
());
}
else
if
(
bin_count
>
pallete
.
front
().
hist_val
)
{
pop_heap
(
pallete
.
begin
(),
pallete
.
end
());
pallete
.
back
()
=
el
;
push_heap
(
pallete
.
begin
(),
pallete
.
end
());
}
hist_ptr
++
;
}
getColorPalleteMode
(
chromaticity_pallete_mode
,
(
hist_elem
*
)(
&
pallete
[
0
]),
(
int
)
pallete
.
size
(),
pallete_bandwidth
);
}
void
extractSimpleFeatures
(
InputArray
_src
,
OutputArray
_dst
,
int
range_max_val
,
float
saturation_thresh
,
int
hist_bin_num
)
{
Mat
src
=
_src
.
getMat
();
CV_Assert
(
!
src
.
empty
());
CV_Assert
(
src
.
isContinuous
());
CV_Assert
(
src
.
type
()
==
CV_8UC3
||
src
.
type
()
==
CV_16UC3
);
vector
<
Vec2f
>
dst
(
num_features
);
Mat
mask
;
int
max_val
=
0
;
preprocessing
(
mask
,
max_val
,
src
,
range_max_val
,
saturation_thresh
);
getAverageAndBrightestColorChromaticity
(
dst
[
0
],
dst
[
1
],
src
,
mask
);
getHistogramBasedFeatures
(
dst
[
2
],
dst
[
3
],
src
,
mask
,
hist_bin_num
,
max_val
);
Mat
(
dst
).
convertTo
(
_dst
,
CV_32F
);
}
inline
float
regressionTreePredict
(
Vec2f
src
,
uchar
*
tree_feature_idx
,
float
*
tree_thresh_vals
,
float
*
tree_leaf_vals
)
{
int
node_idx
=
0
;
int
depth
=
(
int
)
round
(
log
(
num_tree_nodes
)
/
log
(
2
));
for
(
int
i
=
0
;
i
<
depth
;
i
++
)
{
if
(
src
[
tree_feature_idx
[
node_idx
]]
<=
tree_thresh_vals
[
node_idx
])
node_idx
=
2
*
node_idx
+
1
;
else
node_idx
=
2
*
node_idx
+
2
;
}
return
tree_leaf_vals
[
node_idx
-
num_tree_nodes
+
1
];
}
void
autowbLearningBased
(
InputArray
_src
,
OutputArray
_dst
,
int
range_max_val
,
float
saturation_thresh
,
int
hist_bin_num
)
{
const
float
prediction_thresh
=
0.025
f
;
Mat
src
=
_src
.
getMat
();
CV_Assert
(
!
src
.
empty
());
CV_Assert
(
src
.
isContinuous
());
CV_Assert
(
src
.
type
()
==
CV_8UC3
||
src
.
type
()
==
CV_16UC3
);
vector
<
Vec2f
>
features
;
extractSimpleFeatures
(
src
,
features
,
range_max_val
,
saturation_thresh
,
hist_bin_num
);
int
feature_model_size
=
2
*
(
num_tree_nodes
-
1
);
int
local_model_size
=
num_features
*
feature_model_size
;
int
feature_model_size_leaf
=
2
*
num_tree_nodes
;
int
local_model_size_leaf
=
num_features
*
feature_model_size_leaf
;
vector
<
float
>
consensus_r
,
consensus_g
;
vector
<
float
>
all_r
,
all_g
;
for
(
int
i
=
0
;
i
<
num_trees
;
i
++
)
{
Vec2f
local_predictions
[
num_features
];
for
(
int
j
=
0
;
j
<
num_features
;
j
++
)
{
float
r
=
regressionTreePredict
(
features
[
j
],
feature_idx
+
local_model_size
*
i
+
feature_model_size
*
j
,
thresh_vals
+
local_model_size
*
i
+
feature_model_size
*
j
,
leaf_vals
+
local_model_size_leaf
*
i
+
feature_model_size_leaf
*
j
);
float
g
=
regressionTreePredict
(
features
[
j
],
feature_idx
+
local_model_size
*
i
+
feature_model_size
*
j
+
feature_model_size
/
2
,
thresh_vals
+
local_model_size
*
i
+
feature_model_size
*
j
+
feature_model_size
/
2
,
leaf_vals
+
local_model_size_leaf
*
i
+
feature_model_size_leaf
*
j
+
feature_model_size_leaf
/
2
);
local_predictions
[
j
]
=
Vec2f
(
r
,
g
);
all_r
.
push_back
(
r
);
all_g
.
push_back
(
g
);
}
int
agreement_degree
=
0
;
for
(
int
j
=
0
;
j
<
num_features
-
1
;
j
++
)
for
(
int
k
=
j
+
1
;
k
<
num_features
;
k
++
)
{
if
(
norm
(
local_predictions
[
j
]
-
local_predictions
[
k
])
<
prediction_thresh
)
agreement_degree
++
;
}
if
(
agreement_degree
>=
3
)
{
for
(
int
j
=
0
;
j
<
num_features
;
j
++
)
{
consensus_r
.
push_back
(
local_predictions
[
j
][
0
]);
consensus_g
.
push_back
(
local_predictions
[
j
][
1
]);
}
}
}
float
illuminant_r
,
illuminant_g
;
if
(
consensus_r
.
size
()
==
0
)
{
nth_element
(
all_r
.
begin
(),
all_r
.
begin
()
+
all_r
.
size
()
/
2
,
all_r
.
end
());
illuminant_r
=
all_r
[
all_r
.
size
()
/
2
];
nth_element
(
all_g
.
begin
(),
all_g
.
begin
()
+
all_g
.
size
()
/
2
,
all_g
.
end
());
illuminant_g
=
all_g
[
all_g
.
size
()
/
2
];
}
else
{
nth_element
(
consensus_r
.
begin
(),
consensus_r
.
begin
()
+
consensus_r
.
size
()
/
2
,
consensus_r
.
end
());
illuminant_r
=
consensus_r
[
consensus_r
.
size
()
/
2
];
nth_element
(
consensus_g
.
begin
(),
consensus_g
.
begin
()
+
consensus_g
.
size
()
/
2
,
consensus_g
.
end
());
illuminant_g
=
consensus_g
[
consensus_g
.
size
()
/
2
];
}
float
denom
=
1
-
illuminant_r
-
illuminant_g
;
float
gainB
=
1.0
f
;
float
gainG
=
denom
/
illuminant_g
;
float
gainR
=
denom
/
illuminant_r
;
applyChannelGains
(
src
,
_dst
,
gainB
,
gainG
,
gainR
);
}
}
}
modules/xphoto/src/learning_based_color_balance_model.hpp
0 → 100644
View file @
80063fd4
/* This file was automatically generated by learn_color_balance.py script
* using the following parameters:
--num_trees 20 --hist_bin_num 64 --max_tree_depth 4 --num_augmented 2 -r 0,0
*/
const
int
num_trees
=
20
;
const
int
num_features
=
4
;
const
int
num_tree_nodes
=
16
;
unsigned
char
feature_idx
[
num_trees
*
num_features
*
2
*
(
num_tree_nodes
-
1
)]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
1
,
1
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
1
,
0
,
0
,
0
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
1
,
0
,
0
,
1
,
1
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
1
,
1
,
0
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
1
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
1
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
0
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
1
,
0
,
0
,
0
,
1
,
1
,
0
,
1
,
0
,
0
,
0
,
1
,
0
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
1
,
1
,
0
,
1
,
0
,
1
,
0
,
1
,
0
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
1
,
0
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
1
,
0
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
0
,
0
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
1
,
0
,
0
,
0
,
1
,
0
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
0
,
1
,
1
,
1
,
0
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
1
,
1
,
0
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
1
,
1
,
0
,
1
,
0
,
1
,
0
,
1
,
0
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
1
,
0
,
1
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
1
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
0
,
1
,
0
,
1
,
0
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
1
,
1
,
0
,
0
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
0
,
1
,
0
,
0
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
1
,
0
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
0
,
1
,
0
,
0
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
0
,
1
,
1
,
1
,
0
,
1
,
0
,
0
,
1
,
0
,
1
,
0
,
0
,
0
,
1
,
0
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
0
,
1
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
0
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
1
,
0
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
1
,
1
,
1
,
0
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
1
,
0
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
1
,
0
,
0
,
0
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
0
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
0
,
0
,
1
,
0
,
1
,
0
,
0
,
0
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
};
float
thresh_vals
[
num_trees
*
num_features
*
2
*
(
num_tree_nodes
-
1
)]
=
{
.193
f
,
.098
f
,
.455
f
,
.040
f
,
.145
f
,
.316
f
,
.571
f
,
.016
f
,
.058
f
,
.137
f
,
.174
f
,
.276
f
,
.356
f
,
.515
f
,
.730
f
,
.606
f
,
.324
f
,
.794
f
,
.230
f
,
.440
f
,
.683
f
,
.878
f
,
.134
f
,
.282
f
,
.406
f
,
.532
f
,
.036
f
,
.747
f
,
.830
f
,
.931
f
,
.196
f
,
.145
f
,
.363
f
,
.047
f
,
.351
f
,
.279
f
,
.519
f
,
.013
f
,
.887
f
,
.191
f
,
.193
f
,
.361
f
,
.316
f
,
.576
f
,
.445
f
,
.524
f
,
.368
f
,
.752
f
,
.271
f
,
.477
f
,
.636
f
,
.798
f
,
.146
f
,
.249
f
,
.423
f
,
.521
f
,
.446
f
,
.023
f
,
.795
f
,
.908
f
,
.259
f
,
.026
f
,
.557
f
,
.125
f
,
.121
f
,
.432
f
,
.774
f
,
.500
f
,
.500
f
,
.984
f
,
.202
f
,
.307
f
,
.509
f
,
.038
f
,
.042
f
,
.667
f
,
.500
f
,
.000
f
,
.014
f
,
.560
f
,
.984
f
,
.000
f
,
.125
f
,
.333
f
,
.553
f
,
.333
f
,
.860
f
,
.000
f
,
.500
f
,
.000
f
,
.193
f
,
.114
f
,
.432
f
,
.032
f
,
.157
f
,
.310
f
,
.567
f
,
.013
f
,
.048
f
,
.127
f
,
.428
f
,
.271
f
,
.370
f
,
.511
f
,
.762
f
,
.615
f
,
.325
f
,
.833
f
,
.193
f
,
.440
f
,
.728
f
,
.887
f
,
.086
f
,
.230
f
,
.411
f
,
.546
f
,
.671
f
,
.009
f
,
.863
f
,
.944
f
,
.283
f
,
.174
f
,
.515
f
,
.087
f
,
.209
f
,
.356
f
,
.693
f
,
.059
f
,
.145
f
,
.344
f
,
.254
f
,
.316
f
,
.455
f
,
.571
f
,
.811
f
,
.537
f
,
.343
f
,
.751
f
,
.243
f
,
.435
f
,
.630
f
,
.813
f
,
.134
f
,
.310
f
,
.391
f
,
.487
f
,
.597
f
,
.683
f
,
.755
f
,
.878
f
,
.307
f
,
.145
f
,
.446
f
,
.063
f
,
.349
f
,
.457
f
,
.576
f
,
.021
f
,
.792
f
,
.268
f
,
.250
f
,
.421
f
,
.463
f
,
.574
f
,
.610
f
,
.478
f
,
.354
f
,
.636
f
,
.271
f
,
.423
f
,
.529
f
,
.795
f
,
.146
f
,
.257
f
,
.124
f
,
.458
f
,
.043
f
,
.022
f
,
.752
f
,
.836
f
,
.307
f
,
.026
f
,
.557
f
,
.125
f
,
.135
f
,
.435
f
,
.774
f
,
.500
f
,
.500
f
,
.984
f
,
.238
f
,
.500
f
,
.509
f
,
.038
f
,
.042
f
,
.600
f
,
.400
f
,
.000
f
,
.014
f
,
.500
f
,
.667
f
,
.000
f
,
.125
f
,
.250
f
,
.455
f
,
.097
f
,
.333
f
,
.984
f
,
.000
f
,
.000
f
,
.271
f
,
.155
f
,
.511
f
,
.078
f
,
.198
f
,
.372
f
,
.696
f
,
.059
f
,
.123
f
,
.183
f
,
.237
f
,
.310
f
,
.432
f
,
.564
f
,
.875
f
,
.546
f
,
.324
f
,
.728
f
,
.195
f
,
.423
f
,
.616
f
,
.823
f
,
.131
f
,
.281
f
,
.355
f
,
.490
f
,
.581
f
,
.677
f
,
.775
f
,
.885
f
,
.300
f
,
.192
f
,
.515
f
,
.109
f
,
.248
f
,
.374
f
,
.693
f
,
.065
f
,
.157
f
,
.580
f
,
.276
f
,
.341
f
,
.455
f
,
.571
f
,
.811
f
,
.532
f
,
.324
f
,
.679
f
,
.196
f
,
.421
f
,
.630
f
,
.804
f
,
.111
f
,
.252
f
,
.348
f
,
.447
f
,
.565
f
,
.247
f
,
.755
f
,
.866
f
,
.335
f
,
.188
f
,
.503
f
,
.104
f
,
.270
f
,
.521
f
,
.607
f
,
.021
f
,
.134
f
,
.364
f
,
.332
f
,
.421
f
,
.571
f
,
.576
f
,
.836
f
,
.458
f
,
.294
f
,
.523
f
,
.171
f
,
.413
f
,
.501
f
,
.651
f
,
.065
f
,
.273
f
,
.354
f
,
.062
f
,
.052
f
,
.489
f
,
.523
f
,
.784
f
,
.307
f
,
.026
f
,
.557
f
,
.125
f
,
.156
f
,
.432
f
,
.774
f
,
.500
f
,
.500
f
,
.984
f
,
.200
f
,
.399
f
,
.509
f
,
.038
f
,
.042
f
,
.560
f
,
.429
f
,
.000
f
,
.014
f
,
.138
f
,
.667
f
,
.000
f
,
.125
f
,
.222
f
,
.500
f
,
.522
f
,
.286
f
,
.984
f
,
.500
f
,
.000
f
,
.295
f
,
.186
f
,
.564
f
,
.104
f
,
.293
f
,
.432
f
,
.762
f
,
.059
f
,
.127
f
,
.271
f
,
.593
f
,
.353
f
,
.511
f
,
.630
f
,
.875
f
,
.538
f
,
.324
f
,
.685
f
,
.195
f
,
.423
f
,
.616
f
,
.791
f
,
.099
f
,
.281
f
,
.389
f
,
.452
f
,
.581
f
,
.293
f
,
.728
f
,
.842
f
,
.320
f
,
.211
f
,
.521
f
,
.098
f
,
.251
f
,
.403
f
,
.693
f
,
.058
f
,
.158
f
,
.580
f
,
.469
f
,
.188
f
,
.455
f
,
.571
f
,
.811
f
,
.532
f
,
.324
f
,
.717
f
,
.193
f
,
.415
f
,
.587
f
,
.791
f
,
.122
f
,
.265
f
,
.391
f
,
.457
f
,
.559
f
,
.665
f
,
.753
f
,
.835
f
,
.405
f
,
.305
f
,
.503
f
,
.135
f
,
.457
f
,
.483
f
,
.607
f
,
.044
f
,
.182
f
,
.394
f
,
.569
f
,
.156
f
,
.484
f
,
.576
f
,
.836
f
,
.455
f
,
.294
f
,
.576
f
,
.248
f
,
.376
f
,
.482
f
,
.651
f
,
.089
f
,
.273
f
,
.181
f
,
.430
f
,
.472
f
,
.500
f
,
.265
f
,
.784
f
,
.414
f
,
.228
f
,
.557
f
,
.026
f
,
.620
f
,
.476
f
,
.774
f
,
.500
f
,
.156
f
,
.595
f
,
.304
f
,
.322
f
,
.509
f
,
.038
f
,
.042
f
,
.533
f
,
.391
f
,
.683
f
,
.106
f
,
.175
f
,
.286
f
,
.010
f
,
.026
f
,
.226
f
,
.500
f
,
.429
f
,
.197
f
,
.655
f
,
.000
f
,
.800
f
,
.386
f
,
.218
f
,
.564
f
,
.082
f
,
.295
f
,
.479
f
,
.762
f
,
.043
f
,
.155
f
,
.293
f
,
.440
f
,
.432
f
,
.511
f
,
.630
f
,
.875
f
,
.544
f
,
.306
f
,
.705
f
,
.185
f
,
.412
f
,
.606
f
,
.791
f
,
.109
f
,
.263
f
,
.372
f
,
.502
f
,
.315
f
,
.685
f
,
.741
f
,
.855
f
,
.365
f
,
.221
f
,
.544
f
,
.110
f
,
.307
f
,
.455
f
,
.730
f
,
.059
f
,
.179
f
,
.276
f
,
.468
f
,
.403
f
,
.515
f
,
.678
f
,
.860
f
,
.520
f
,
.340
f
,
.683
f
,
.196
f
,
.440
f
,
.591
f
,
.754
f
,
.122
f
,
.274
f
,
.394
f
,
.464
f
,
.556
f
,
.622
f
,
.723
f
,
.835
f
,
.375
f
,
.147
f
,
.503
f
,
.055
f
,
.319
f
,
.436
f
,
.607
f
,
.018
f
,
.773
f
,
.624
f
,
.298
f
,
.467
f
,
.450
f
,
.576
f
,
.836
f
,
.454
f
,
.287
f
,
.571
f
,
.163
f
,
.376
f
,
.308
f
,
.648
f
,
.086
f
,
.236
f
,
.373
f
,
.427
f
,
.477
f
,
.496
f
,
.333
f
,
.795
f
,
.500
f
,
.307
f
,
.774
f
,
.026
f
,
.462
f
,
.557
f
,
.042
f
,
.125
f
,
.191
f
,
.406
f
,
.500
f
,
.509
f
,
.038
f
,
.000
f
,
.138
f
,
.600
f
,
.400
f
,
.000
f
,
.073
f
,
.500
f
,
.010
f
,
.000
f
,
.026
f
,
.275
f
,
.226
f
,
.588
f
,
.984
f
,
.688
f
,
.000
f
,
.000
f
,
.386
f
,
.245
f
,
.564
f
,
.097
f
,
.343
f
,
.479
f
,
.762
f
,
.048
f
,
.180
f
,
.424
f
,
.466
f
,
.432
f
,
.511
f
,
.630
f
,
.875
f
,
.541
f
,
.335
f
,
.702
f
,
.193
f
,
.413
f
,
.602
f
,
.791
f
,
.116
f
,
.296
f
,
.376
f
,
.481
f
,
.210
f
,
.641
f
,
.741
f
,
.863
f
,
.341
f
,
.145
f
,
.531
f
,
.087
f
,
.283
f
,
.455
f
,
.729
f
,
.047
f
,
.109
f
,
.189
f
,
.469
f
,
.375
f
,
.515
f
,
.571
f
,
.811
f
,
.553
f
,
.324
f
,
.683
f
,
.196
f
,
.425
f
,
.607
f
,
.761
f
,
.122
f
,
.252
f
,
.368
f
,
.499
f
,
.248
f
,
.648
f
,
.723
f
,
.848
f
,
.365
f
,
.135
f
,
.503
f
,
.082
f
,
.279
f
,
.503
f
,
.607
f
,
.044
f
,
.086
f
,
.182
f
,
.319
f
,
.395
f
,
.448
f
,
.576
f
,
.836
f
,
.454
f
,
.287
f
,
.571
f
,
.163
f
,
.389
f
,
.308
f
,
.752
f
,
.086
f
,
.250
f
,
.373
f
,
.436
f
,
.498
f
,
.496
f
,
.636
f
,
.834
f
,
.500
f
,
.307
f
,
.774
f
,
.026
f
,
.474
f
,
.557
f
,
.042
f
,
.125
f
,
.000
f
,
.414
f
,
.561
f
,
.509
f
,
.038
f
,
.000
f
,
.138
f
,
.560
f
,
.626
f
,
.000
f
,
.400
f
,
.174
f
,
.984
f
,
.000
f
,
.073
f
,
.500
f
,
.852
f
,
.226
f
,
.667
f
,
.500
f
,
.000
f
,
.000
f
,
.353
f
,
.141
f
,
.564
f
,
.073
f
,
.265
f
,
.432
f
,
.762
f
,
.032
f
,
.106
f
,
.193
f
,
.478
f
,
.470
f
,
.511
f
,
.630
f
,
.875
f
,
.605
f
,
.325
f
,
.728
f
,
.193
f
,
.437
f
,
.652
f
,
.855
f
,
.116
f
,
.264
f
,
.412
f
,
.502
f
,
.202
f
,
.685
f
,
.776
f
,
.912
f
,
.341
f
,
.161
f
,
.531
f
,
.087
f
,
.298
f
,
.455
f
,
.729
f
,
.047
f
,
.109
f
,
.185
f
,
.467
f
,
.375
f
,
.515
f
,
.571
f
,
.811
f
,
.580
f
,
.324
f
,
.685
f
,
.196
f
,
.425
f
,
.607
f
,
.824
f
,
.122
f
,
.252
f
,
.368
f
,
.512
f
,
.231
f
,
.648
f
,
.749
f
,
.885
f
,
.365
f
,
.135
f
,
.503
f
,
.082
f
,
.319
f
,
.499
f
,
.607
f
,
.044
f
,
.086
f
,
.702
f
,
.384
f
,
.439
f
,
.465
f
,
.576
f
,
.836
f
,
.478
f
,
.287
f
,
.594
f
,
.163
f
,
.454
f
,
.502
f
,
.784
f
,
.086
f
,
.250
f
,
.364
f
,
.345
f
,
.500
f
,
.370
f
,
.651
f
,
.836
f
,
.476
f
,
.295
f
,
.557
f
,
.026
f
,
.474
f
,
.509
f
,
.774
f
,
.125
f
,
.000
f
,
.333
f
,
.364
f
,
.495
f
,
.405
f
,
.038
f
,
.042
f
,
.560
f
,
.626
f
,
.000
f
,
.400
f
,
.174
f
,
.010
f
,
.000
f
,
.059
f
,
.500
f
,
.852
f
,
.226
f
,
.667
f
,
.667
f
,
.000
f
,
.000
f
,
.419
f
,
.157
f
,
.564
f
,
.078
f
,
.295
f
,
.479
f
,
.762
f
,
.043
f
,
.124
f
,
.256
f
,
.353
f
,
.432
f
,
.511
f
,
.630
f
,
.875
f
,
.605
f
,
.325
f
,
.713
f
,
.193
f
,
.423
f
,
.677
f
,
.842
f
,
.116
f
,
.264
f
,
.385
f
,
.502
f
,
.621
f
,
.177
f
,
.756
f
,
.912
f
,
.388
f
,
.174
f
,
.564
f
,
.095
f
,
.310
f
,
.456
f
,
.730
f
,
.047
f
,
.143
f
,
.276
f
,
.468
f
,
.431
f
,
.515
f
,
.682
f
,
.860
f
,
.352
f
,
.215
f
,
.591
f
,
.124
f
,
.290
f
,
.536
f
,
.723
f
,
.064
f
,
.172
f
,
.244
f
,
.318
f
,
.428
f
,
.548
f
,
.666
f
,
.825
f
,
.394
f
,
.146
f
,
.503
f
,
.055
f
,
.349
f
,
.499
f
,
.607
f
,
.018
f
,
.773
f
,
.271
f
,
.327
f
,
.439
f
,
.465
f
,
.576
f
,
.836
f
,
.464
f
,
.287
f
,
.588
f
,
.163
f
,
.377
f
,
.502
f
,
.752
f
,
.086
f
,
.250
f
,
.237
f
,
.454
f
,
.464
f
,
.370
f
,
.636
f
,
.834
f
,
.476
f
,
.000
f
,
.557
f
,
.282
f
,
.000
f
,
.509
f
,
.774
f
,
.026
f
,
.481
f
,
.000
f
,
.000
f
,
.495
f
,
.405
f
,
.038
f
,
.042
f
,
.556
f
,
.626
f
,
.000
f
,
.343
f
,
.174
f
,
.010
f
,
.000
f
,
.023
f
,
.559
f
,
.852
f
,
.226
f
,
.667
f
,
.667
f
,
.000
f
,
.000
f
,
.468
f
,
.157
f
,
.567
f
,
.078
f
,
.305
f
,
.511
f
,
.762
f
,
.043
f
,
.124
f
,
.271
f
,
.464
f
,
.511
f
,
.193
f
,
.630
f
,
.875
f
,
.351
f
,
.208
f
,
.602
f
,
.116
f
,
.302
f
,
.489
f
,
.720
f
,
.059
f
,
.164
f
,
.281
f
,
.325
f
,
.414
f
,
.282
f
,
.654
f
,
.842
f
,
.388
f
,
.174
f
,
.564
f
,
.095
f
,
.313
f
,
.456
f
,
.730
f
,
.047
f
,
.143
f
,
.279
f
,
.468
f
,
.431
f
,
.515
f
,
.682
f
,
.860
f
,
.356
f
,
.215
f
,
.591
f
,
.124
f
,
.290
f
,
.539
f
,
.753
f
,
.064
f
,
.174
f
,
.274
f
,
.318
f
,
.435
f
,
.556
f
,
.647
f
,
.848
f
,
.411
f
,
.146
f
,
.411
f
,
.055
f
,
.349
f
,
.490
f
,
.499
f
,
.018
f
,
.773
f
,
.271
f
,
.327
f
,
.181
f
,
.610
f
,
.467
f
,
.448
f
,
.287
f
,
.163
f
,
.454
f
,
.086
f
,
.262
f
,
.359
f
,
.636
f
,
.041
f
,
.476
f
,
.200
f
,
.633
f
,
.257
f
,
.428
f
,
.522
f
,
.795
f
,
.435
f
,
.000
f
,
.557
f
,
.049
f
,
.000
f
,
.509
f
,
.774
f
,
.330
f
,
.282
f
,
.500
f
,
.000
f
,
.462
f
,
.405
f
,
.038
f
,
.042
f
,
.393
f
,
.029
f
,
.000
f
,
.026
f
,
.226
f
,
.602
f
,
.000
f
,
.500
f
,
.183
f
,
.163
f
,
.337
f
,
.500
f
,
.984
f
,
.500
f
,
.000
f
,
.468
f
,
.157
f
,
.567
f
,
.078
f
,
.314
f
,
.511
f
,
.762
f
,
.043
f
,
.124
f
,
.271
f
,
.456
f
,
.511
f
,
.193
f
,
.630
f
,
.875
f
,
.355
f
,
.208
f
,
.602
f
,
.116
f
,
.296
f
,
.414
f
,
.761
f
,
.059
f
,
.179
f
,
.263
f
,
.324
f
,
.381
f
,
.502
f
,
.681
f
,
.855
f
,
.356
f
,
.174
f
,
.537
f
,
.095
f
,
.289
f
,
.455
f
,
.729
f
,
.047
f
,
.143
f
,
.186
f
,
.471
f
,
.403
f
,
.515
f
,
.588
f
,
.811
f
,
.352
f
,
.215
f
,
.568
f
,
.147
f
,
.282
f
,
.435
f
,
.723
f
,
.077
f
,
.191
f
,
.265
f
,
.318
f
,
.395
f
,
.543
f
,
.630
f
,
.824
f
,
.439
f
,
.141
f
,
.443
f
,
.051
f
,
.363
f
,
.490
f
,
.479
f
,
.018
f
,
.773
f
,
.279
f
,
.446
f
,
.223
f
,
.607
f
,
.504
f
,
.491
f
,
.298
f
,
.179
f
,
.454
f
,
.086
f
,
.264
f
,
.350
f
,
.571
f
,
.041
f
,
.122
f
,
.390
f
,
.287
f
,
.324
f
,
.431
f
,
.502
f
,
.752
f
,
.500
f
,
.307
f
,
.774
f
,
.026
f
,
.500
f
,
.557
f
,
.042
f
,
.125
f
,
.000
f
,
.434
f
,
.524
f
,
.509
f
,
.038
f
,
.000
f
,
.138
f
,
.447
f
,
.225
f
,
.000
f
,
.026
f
,
.226
f
,
.600
f
,
.000
f
,
.500
f
,
.337
f
,
.667
f
,
.333
f
,
.269
f
,
.984
f
,
.500
f
,
.000
f
,
.425
f
,
.157
f
,
.564
f
,
.078
f
,
.314
f
,
.511
f
,
.762
f
,
.043
f
,
.124
f
,
.269
f
,
.467
f
,
.479
f
,
.561
f
,
.630
f
,
.875
f
,
.372
f
,
.208
f
,
.602
f
,
.148
f
,
.296
f
,
.441
f
,
.775
f
,
.072
f
,
.179
f
,
.230
f
,
.324
f
,
.408
f
,
.516
f
,
.652
f
,
.863
f
,
.403
f
,
.179
f
,
.571
f
,
.095
f
,
.337
f
,
.456
f
,
.730
f
,
.047
f
,
.145
f
,
.267
f
,
.458
f
,
.056
f
,
.521
f
,
.682
f
,
.860
f
,
.352
f
,
.193
f
,
.568
f
,
.095
f
,
.282
f
,
.435
f
,
.696
f
,
.056
f
,
.147
f
,
.230
f
,
.318
f
,
.395
f
,
.534
f
,
.630
f
,
.808
f
,
.484
f
,
.141
f
,
.454
f
,
.051
f
,
.372
f
,
.605
f
,
.487
f
,
.018
f
,
.773
f
,
.316
f
,
.483
f
,
.490
f
,
.610
f
,
.486
f
,
.490
f
,
.298
f
,
.200
f
,
.472
f
,
.122
f
,
.275
f
,
.397
f
,
.571
f
,
.061
f
,
.174
f
,
.370
f
,
.364
f
,
.349
f
,
.435
f
,
.499
f
,
.752
f
,
.500
f
,
.307
f
,
.667
f
,
.026
f
,
.500
f
,
.661
f
,
.774
f
,
.125
f
,
.000
f
,
.398
f
,
.524
f
,
.557
f
,
.167
f
,
.760
f
,
.042
f
,
.500
f
,
.667
f
,
.000
f
,
.429
f
,
.138
f
,
.984
f
,
.000
f
,
.029
f
,
.364
f
,
.906
f
,
.226
f
,
.667
f
,
.500
f
,
.000
f
,
.000
f
,
.488
f
,
.157
f
,
.567
f
,
.078
f
,
.366
f
,
.511
f
,
.762
f
,
.043
f
,
.124
f
,
.309
f
,
.487
f
,
.511
f
,
.193
f
,
.630
f
,
.875
f
,
.376
f
,
.208
f
,
.575
f
,
.148
f
,
.302
f
,
.452
f
,
.687
f
,
.072
f
,
.182
f
,
.230
f
,
.325
f
,
.413
f
,
.516
f
,
.621
f
,
.833
f
,
.452
f
,
.179
f
,
.571
f
,
.095
f
,
.349
f
,
.515
f
,
.730
f
,
.047
f
,
.145
f
,
.244
f
,
.444
f
,
.456
f
,
.206
f
,
.682
f
,
.860
f
,
.368
f
,
.215
f
,
.568
f
,
.124
f
,
.290
f
,
.444
f
,
.689
f
,
.063
f
,
.188
f
,
.252
f
,
.343
f
,
.406
f
,
.516
f
,
.630
f
,
.804
f
,
.162
f
,
.085
f
,
.490
f
,
.044
f
,
.086
f
,
.372
f
,
.454
f
,
.015
f
,
.424
f
,
.463
f
,
.134
f
,
.262
f
,
.478
f
,
.607
f
,
.490
f
,
.462
f
,
.297
f
,
.583
f
,
.163
f
,
.349
f
,
.522
f
,
.702
f
,
.065
f
,
.237
f
,
.315
f
,
.428
f
,
.499
f
,
.397
f
,
.636
f
,
.795
f
,
.500
f
,
.310
f
,
.667
f
,
.026
f
,
.432
f
,
.661
f
,
.000
f
,
.125
f
,
.146
f
,
.500
f
,
.332
f
,
.557
f
,
.167
f
,
.774
f
,
.000
f
,
.537
f
,
.667
f
,
.000
f
,
.400
f
,
.138
f
,
.984
f
,
.000
f
,
.029
f
,
.500
f
,
.906
f
,
.226
f
,
.667
f
,
.500
f
,
.000
f
,
.000
f
,
.511
f
,
.157
f
,
.696
f
,
.078
f
,
.361
f
,
.564
f
,
.875
f
,
.043
f
,
.124
f
,
.223
f
,
.404
f
,
.561
f
,
.630
f
,
.762
f
,
.896
f
,
.376
f
,
.209
f
,
.578
f
,
.116
f
,
.296
f
,
.452
f
,
.687
f
,
.058
f
,
.179
f
,
.264
f
,
.332
f
,
.413
f
,
.516
f
,
.621
f
,
.833
f
,
.455
f
,
.189
f
,
.571
f
,
.098
f
,
.274
f
,
.515
f
,
.730
f
,
.056
f
,
.148
f
,
.244
f
,
.354
f
,
.233
f
,
.206
f
,
.682
f
,
.860
f
,
.381
f
,
.230
f
,
.565
f
,
.124
f
,
.315
f
,
.496
f
,
.673
f
,
.064
f
,
.177
f
,
.282
f
,
.351
f
,
.441
f
,
.528
f
,
.622
f
,
.804
f
,
.146
f
,
.082
f
,
.503
f
,
.044
f
,
.086
f
,
.349
f
,
.607
f
,
.015
f
,
.424
f
,
.085
f
,
.134
f
,
.262
f
,
.298
f
,
.576
f
,
.836
f
,
.349
f
,
.271
f
,
.466
f
,
.146
f
,
.297
f
,
.413
f
,
.608
f
,
.065
f
,
.200
f
,
.364
f
,
.318
f
,
.441
f
,
.291
f
,
.531
f
,
.752
f
,
.535
f
,
.000
f
,
.226
f
,
.286
f
,
.000
f
,
.000
f
,
.348
f
,
.026
f
,
.432
f
,
.000
f
,
.000
f
,
.667
f
,
.000
f
,
.333
f
,
.423
f
,
.500
f
,
.391
f
,
.000
f
,
.073
f
,
.500
f
,
.600
f
,
.000
f
,
.026
f
,
.226
f
,
.455
f
,
.551
f
,
.379
f
,
.984
f
,
.000
f
,
.000
f
,
.564
f
,
.184
f
,
.762
f
,
.089
f
,
.404
f
,
.630
f
,
.875
f
,
.044
f
,
.141
f
,
.271
f
,
.332
f
,
.614
f
,
.752
f
,
.864
f
,
.896
f
,
.385
f
,
.230
f
,
.590
f
,
.116
f
,
.332
f
,
.505
f
,
.687
f
,
.059
f
,
.185
f
,
.283
f
,
.506
f
,
.452
f
,
.546
f
,
.626
f
,
.833
f
,
.254
f
,
.161
f
,
.456
f
,
.087
f
,
.189
f
,
.300
f
,
.571
f
,
.047
f
,
.109
f
,
.179
f
,
.209
f
,
.275
f
,
.375
f
,
.521
f
,
.730
f
,
.395
f
,
.230
f
,
.565
f
,
.112
f
,
.348
f
,
.505
f
,
.751
f
,
.064
f
,
.177
f
,
.290
f
,
.387
f
,
.441
f
,
.282
f
,
.623
f
,
.848
f
,
.146
f
,
.055
f
,
.503
f
,
.018
f
,
.773
f
,
.316
f
,
.607
f
,
.011
f
,
.428
f
,
.134
f
,
.887
f
,
.236
f
,
.358
f
,
.576
f
,
.836
f
,
.349
f
,
.271
f
,
.472
f
,
.146
f
,
.364
f
,
.413
f
,
.636
f
,
.065
f
,
.200
f
,
.288
f
,
.366
f
,
.441
f
,
.398
f
,
.516
f
,
.795
f
,
.592
f
,
.000
f
,
.774
f
,
.282
f
,
.000
f
,
.735
f
,
.042
f
,
.026
f
,
.476
f
,
.000
f
,
.000
f
,
.038
f
,
.127
f
,
.000
f
,
.138
f
,
.500
f
,
.391
f
,
.000
f
,
.029
f
,
.500
f
,
.522
f
,
.000
f
,
.026
f
,
.226
f
,
.455
f
,
.535
f
,
.260
f
,
.984
f
,
.000
f
,
.000
f
,
.250
f
,
.155
f
,
.564
f
,
.078
f
,
.198
f
,
.404
f
,
.762
f
,
.043
f
,
.124
f
,
.183
f
,
.223
f
,
.295
f
,
.432
f
,
.630
f
,
.875
f
,
.385
f
,
.230
f
,
.574
f
,
.116
f
,
.330
f
,
.505
f
,
.728
f
,
.065
f
,
.173
f
,
.283
f
,
.554
f
,
.453
f
,
.546
f
,
.626
f
,
.842
f
,
.285
f
,
.161
f
,
.515
f
,
.087
f
,
.209
f
,
.441
f
,
.693
f
,
.047
f
,
.109
f
,
.184
f
,
.264
f
,
.334
f
,
.456
f
,
.571
f
,
.811
f
,
.352
f
,
.198
f
,
.555
f
,
.124
f
,
.274
f
,
.449
f
,
.723
f
,
.076
f
,
.172
f
,
.236
f
,
.318
f
,
.402
f
,
.519
f
,
.622
f
,
.824
f
,
.236
f
,
.146
f
,
.503
f
,
.055
f
,
.147
f
,
.366
f
,
.607
f
,
.018
f
,
.773
f
,
.146
f
,
.188
f
,
.280
f
,
.499
f
,
.576
f
,
.836
f
,
.329
f
,
.262
f
,
.449
f
,
.163
f
,
.364
f
,
.350
f
,
.588
f
,
.086
f
,
.200
f
,
.296
f
,
.366
f
,
.331
f
,
.412
f
,
.482
f
,
.784
f
,
.571
f
,
.000
f
,
.774
f
,
.307
f
,
.000
f
,
.234
f
,
.042
f
,
.026
f
,
.406
f
,
.000
f
,
.000
f
,
.647
f
,
.620
f
,
.000
f
,
.138
f
,
.500
f
,
.400
f
,
.000
f
,
.109
f
,
.068
f
,
.537
f
,
.000
f
,
.026
f
,
.226
f
,
.500
f
,
.447
f
,
.522
f
,
.984
f
,
.000
f
,
.000
f
,
.268
f
,
.157
f
,
.511
f
,
.078
f
,
.198
f
,
.346
f
,
.696
f
,
.043
f
,
.124
f
,
.183
f
,
.237
f
,
.313
f
,
.458
f
,
.564
f
,
.875
f
,
.351
f
,
.208
f
,
.571
f
,
.116
f
,
.265
f
,
.460
f
,
.728
f
,
.065
f
,
.164
f
,
.230
f
,
.308
f
,
.412
f
,
.516
f
,
.632
f
,
.842
f
,
.300
f
,
.161
f
,
.521
f
,
.087
f
,
.209
f
,
.360
f
,
.693
f
,
.047
f
,
.109
f
,
.184
f
,
.276
f
,
.313
f
,
.452
f
,
.571
f
,
.811
f
,
.351
f
,
.196
f
,
.558
f
,
.122
f
,
.274
f
,
.449
f
,
.723
f
,
.072
f
,
.166
f
,
.236
f
,
.318
f
,
.421
f
,
.520
f
,
.617
f
,
.824
f
,
.190
f
,
.134
f
,
.503
f
,
.051
f
,
.402
f
,
.280
f
,
.607
f
,
.018
f
,
.773
f
,
.156
f
,
.616
f
,
.389
f
,
.345
f
,
.576
f
,
.836
f
,
.326
f
,
.237
f
,
.466
f
,
.179
f
,
.294
f
,
.350
f
,
.636
f
,
.086
f
,
.407
f
,
.277
f
,
.338
f
,
.295
f
,
.415
f
,
.562
f
,
.795
f
,
.307
f
,
.026
f
,
.774
f
,
.125
f
,
.000
f
,
.543
f
,
.042
f
,
.500
f
,
.500
f
,
.205
f
,
.000
f
,
.420
f
,
.321
f
,
.000
f
,
.138
f
,
.447
f
,
.371
f
,
.560
f
,
.026
f
,
.226
f
,
.500
f
,
.000
f
,
.125
f
,
.297
f
,
.187
f
,
.304
f
,
.500
f
,
.522
f
,
.984
f
,
.000
f
,
.256
f
,
.155
f
,
.564
f
,
.078
f
,
.193
f
,
.314
f
,
.762
f
,
.043
f
,
.124
f
,
.428
f
,
.223
f
,
.258
f
,
.470
f
,
.630
f
,
.875
f
,
.338
f
,
.193
f
,
.582
f
,
.116
f
,
.264
f
,
.465
f
,
.728
f
,
.065
f
,
.164
f
,
.230
f
,
.296
f
,
.414
f
,
.531
f
,
.652
f
,
.842
f
,
.316
f
,
.174
f
,
.571
f
,
.095
f
,
.276
f
,
.433
f
,
.730
f
,
.047
f
,
.143
f
,
.209
f
,
.300
f
,
.343
f
,
.521
f
,
.682
f
,
.860
f
,
.343
f
,
.193
f
,
.587
f
,
.105
f
,
.274
f
,
.438
f
,
.751
f
,
.066
f
,
.166
f
,
.230
f
,
.318
f
,
.381
f
,
.519
f
,
.648
f
,
.848
f
,
.271
f
,
.146
f
,
.503
f
,
.055
f
,
.403
f
,
.366
f
,
.607
f
,
.018
f
,
.773
f
,
.365
f
,
.445
f
,
.444
f
,
.517
f
,
.576
f
,
.836
f
,
.324
f
,
.237
f
,
.478
f
,
.115
f
,
.287
f
,
.350
f
,
.636
f
,
.074
f
,
.405
f
,
.387
f
,
.337
f
,
.295
f
,
.431
f
,
.522
f
,
.795
f
,
.307
f
,
.026
f
,
.667
f
,
.125
f
,
.984
f
,
.426
f
,
.000
f
,
.500
f
,
.500
f
,
.156
f
,
.000
f
,
.500
f
,
.557
f
,
.972
f
,
.000
f
,
.429
f
,
.434
f
,
.000
f
,
.023
f
,
.226
f
,
.560
f
,
.000
f
,
.125
f
,
.222
f
,
.760
f
,
.500
f
,
.500
f
,
.667
f
,
.000
f
,
.000
f
,
.310
f
,
.157
f
,
.564
f
,
.078
f
,
.256
f
,
.425
f
,
.762
f
,
.043
f
,
.124
f
,
.193
f
,
.258
f
,
.350
f
,
.511
f
,
.630
f
,
.875
f
,
.337
f
,
.182
f
,
.597
f
,
.101
f
,
.264
f
,
.443
f
,
.728
f
,
.063
f
,
.161
f
,
.216
f
,
.296
f
,
.395
f
,
.522
f
,
.652
f
,
.842
f
,
.341
f
,
.174
f
,
.516
f
,
.095
f
,
.276
f
,
.431
f
,
.678
f
,
.047
f
,
.143
f
,
.209
f
,
.300
f
,
.391
f
,
.460
f
,
.571
f
,
.811
f
,
.324
f
,
.193
f
,
.543
f
,
.122
f
,
.254
f
,
.434
f
,
.689
f
,
.066
f
,
.145
f
,
.230
f
,
.431
f
,
.391
f
,
.508
f
,
.597
f
,
.808
f
,
.271
f
,
.146
f
,
.366
f
,
.055
f
,
.365
f
,
.357
f
,
.503
f
,
.018
f
,
.773
f
,
.249
f
,
.417
f
,
.316
f
,
.444
f
,
.517
f
,
.607
f
,
.308
f
,
.200
f
,
.472
f
,
.115
f
,
.264
f
,
.357
f
,
.571
f
,
.058
f
,
.138
f
,
.260
f
,
.364
f
,
.338
f
,
.431
f
,
.499
f
,
.752
f
,
.414
f
,
.049
f
,
.557
f
,
.125
f
,
.307
f
,
.438
f
,
.000
f
,
.500
f
,
.330
f
,
.984
f
,
.333
f
,
.446
f
,
.122
f
,
.014
f
,
.000
f
,
.391
f
,
.333
f
,
.518
f
,
.026
f
,
.174
f
,
.500
f
,
.000
f
,
.125
f
,
.279
f
,
.760
f
,
.299
f
,
.500
f
,
.408
f
,
.667
f
,
.000
f
,
.310
f
,
.157
f
,
.479
f
,
.078
f
,
.255
f
,
.370
f
,
.564
f
,
.043
f
,
.124
f
,
.193
f
,
.271
f
,
.483
f
,
.418
f
,
.512
f
,
.762
f
,
.335
f
,
.182
f
,
.597
f
,
.086
f
,
.265
f
,
.423
f
,
.728
f
,
.041
f
,
.129
f
,
.230
f
,
.302
f
,
.375
f
,
.522
f
,
.652
f
,
.842
f
,
.374
f
,
.184
f
,
.544
f
,
.095
f
,
.300
f
,
.455
f
,
.811
f
,
.047
f
,
.145
f
,
.254
f
,
.341
f
,
.404
f
,
.516
f
,
.569
f
,
.860
f
,
.326
f
,
.196
f
,
.584
f
,
.118
f
,
.252
f
,
.434
f
,
.751
f
,
.064
f
,
.141
f
,
.236
f
,
.290
f
,
.391
f
,
.508
f
,
.648
f
,
.848
f
,
.316
f
,
.146
f
,
.421
f
,
.055
f
,
.279
f
,
.454
f
,
.503
f
,
.018
f
,
.773
f
,
.183
f
,
.280
f
,
.347
f
,
.571
f
,
.499
f
,
.605
f
,
.294
f
,
.161
f
,
.499
f
,
.086
f
,
.225
f
,
.364
f
,
.636
f
,
.058
f
,
.476
f
,
.200
f
,
.264
f
,
.347
f
,
.454
f
,
.571
f
,
.795
f
,
.500
f
,
.520
f
,
.307
f
,
.462
f
,
.571
f
,
.000
f
,
.450
f
,
.051
f
,
.220
f
,
.557
f
,
.833
f
,
.984
f
,
.000
f
,
.655
f
,
.532
f
,
.355
f
,
.073
f
,
.556
f
,
.026
f
,
.138
f
,
.500
f
,
.000
f
,
.500
f
,
.183
f
,
.906
f
,
.299
f
,
.410
f
,
.333
f
,
.984
f
,
.000
f
,
.370
f
,
.157
f
,
.559
f
,
.078
f
,
.271
f
,
.483
f
,
.762
f
,
.043
f
,
.124
f
,
.198
f
,
.310
f
,
.418
f
,
.512
f
,
.752
f
,
.022
f
,
.308
f
,
.161
f
,
.582
f
,
.086
f
,
.230
f
,
.414
f
,
.728
f
,
.042
f
,
.116
f
,
.193
f
,
.281
f
,
.346
f
,
.489
f
,
.632
f
,
.842
f
,
.455
f
,
.184
f
,
.729
f
,
.095
f
,
.316
f
,
.579
f
,
.811
f
,
.047
f
,
.145
f
,
.276
f
,
.356
f
,
.544
f
,
.666
f
,
.806
f
,
.860
f
,
.326
f
,
.174
f
,
.584
f
,
.088
f
,
.247
f
,
.435
f
,
.751
f
,
.042
f
,
.141
f
,
.215
f
,
.290
f
,
.368
f
,
.528
f
,
.648
f
,
.848
f
,
.347
f
,
.306
f
,
.553
f
,
.146
f
,
.364
f
,
.433
f
,
.610
f
,
.055
f
,
.198
f
,
.338
f
,
.451
f
,
.445
f
,
.432
f
,
.096
f
,
.836
f
,
.294
f
,
.161
f
,
.499
f
,
.108
f
,
.204
f
,
.381
f
,
.636
f
,
.041
f
,
.474
f
,
.198
f
,
.262
f
,
.324
f
,
.362
f
,
.571
f
,
.795
f
,
.500
f
,
.569
f
,
.307
f
,
.101
f
,
.774
f
,
.000
f
,
.423
f
,
.043
f
,
.465
f
,
.121
f
,
.000
f
,
.984
f
,
.000
f
,
.500
f
,
.524
f
,
.333
f
,
.675
f
,
.560
f
,
.292
f
,
.138
f
,
.429
f
,
.000
f
,
.073
f
,
.550
f
,
.000
f
,
.195
f
,
.377
f
,
.500
f
,
.984
f
,
.000
f
,
.479
f
,
.183
f
,
.704
f
,
.082
f
,
.310
f
,
.567
f
,
.875
f
,
.043
f
,
.141
f
,
.271
f
,
.372
f
,
.511
f
,
.630
f
,
.762
f
,
.896
f
,
.325
f
,
.164
f
,
.602
f
,
.086
f
,
.230
f
,
.414
f
,
.761
f
,
.040
f
,
.131
f
,
.197
f
,
.283
f
,
.352
f
,
.516
f
,
.685
f
,
.855
f
};
float
leaf_vals
[
num_trees
*
num_features
*
2
*
num_tree_nodes
]
=
{
.011
f
,
.029
f
,
.047
f
,
.064
f
,
.075
f
,
.102
f
,
.141
f
,
.172
f
,
.212
f
,
.259
f
,
.308
f
,
.364
f
,
.443
f
,
.497
f
,
.592
f
,
.767
f
,
.069
f
,
.165
f
,
.241
f
,
.278
f
,
.357
f
,
.412
f
,
.463
f
,
.540
f
,
.562
f
,
.623
f
,
.676
f
,
.734
f
,
.797
f
,
.838
f
,
.894
f
,
.944
f
,
.014
f
,
.040
f
,
.061
f
,
.033
f
,
.040
f
,
.160
f
,
.181
f
,
.101
f
,
.123
f
,
.047
f
,
.195
f
,
.282
f
,
.374
f
,
.775
f
,
.248
f
,
.068
f
,
.064
f
,
.155
f
,
.177
f
,
.351
f
,
.409
f
,
.479
f
,
.576
f
,
.451
f
,
.677
f
,
.784
f
,
.817
f
,
.764
f
,
.823
f
,
.860
f
,
.898
f
,
.941
f
,
.154
f
,
.154
f
,
.248
f
,
.248
f
,
.050
f
,
.081
f
,
.177
f
,
.227
f
,
.252
f
,
.309
f
,
.385
f
,
.428
f
,
.441
f
,
.525
f
,
.616
f
,
.689
f
,
.435
f
,
.137
f
,
.208
f
,
.406
f
,
.457
f
,
.483
f
,
.518
f
,
.576
f
,
.669
f
,
.844
f
,
.593
f
,
.706
f
,
.853
f
,
.853
f
,
.895
f
,
.925
f
,
.012
f
,
.029
f
,
.047
f
,
.067
f
,
.111
f
,
.134
f
,
.148
f
,
.178
f
,
.214
f
,
.261
f
,
.311
f
,
.357
f
,
.420
f
,
.476
f
,
.592
f
,
.773
f
,
.057
f
,
.143
f
,
.194
f
,
.262
f
,
.358
f
,
.415
f
,
.465
f
,
.541
f
,
.602
f
,
.649
f
,
.655
f
,
.739
f
,
.808
f
,
.849
f
,
.894
f
,
.944
f
,
.050
f
,
.068
f
,
.089
f
,
.118
f
,
.146
f
,
.187
f
,
.211
f
,
.230
f
,
.263
f
,
.308
f
,
.364
f
,
.443
f
,
.497
f
,
.581
f
,
.690
f
,
.832
f
,
.079
f
,
.171
f
,
.263
f
,
.306
f
,
.356
f
,
.401
f
,
.452
f
,
.486
f
,
.538
f
,
.577
f
,
.629
f
,
.687
f
,
.722
f
,
.766
f
,
.834
f
,
.900
f
,
.046
f
,
.066
f
,
.083
f
,
.064
f
,
.090
f
,
.113
f
,
.143
f
,
.235
f
,
.289
f
,
.416
f
,
.094
f
,
.204
f
,
.454
f
,
.074
f
,
.697
f
,
.836
f
,
.067
f
,
.156
f
,
.200
f
,
.332
f
,
.266
f
,
.411
f
,
.473
f
,
.514
f
,
.627
f
,
.575
f
,
.758
f
,
.676
f
,
.775
f
,
.826
f
,
.864
f
,
.900
f
,
.162
f
,
.162
f
,
.248
f
,
.248
f
,
.079
f
,
.102
f
,
.165
f
,
.241
f
,
.281
f
,
.337
f
,
.385
f
,
.428
f
,
.441
f
,
.525
f
,
.616
f
,
.689
f
,
.397
f
,
.137
f
,
.166
f
,
.307
f
,
.421
f
,
.443
f
,
.525
f
,
.486
f
,
.527
f
,
.585
f
,
.687
f
,
.611
f
,
.767
f
,
.821
f
,
.942
f
,
.916
f
,
.055
f
,
.073
f
,
.090
f
,
.110
f
,
.165
f
,
.188
f
,
.207
f
,
.225
f
,
.261
f
,
.312
f
,
.358
f
,
.420
f
,
.475
f
,
.579
f
,
.693
f
,
.875
f
,
.079
f
,
.164
f
,
.238
f
,
.277
f
,
.325
f
,
.378
f
,
.448
f
,
.487
f
,
.527
f
,
.557
f
,
.610
f
,
.648
f
,
.716
f
,
.769
f
,
.830
f
,
.896
f
,
.038
f
,
.090
f
,
.112
f
,
.131
f
,
.206
f
,
.160
f
,
.224
f
,
.249
f
,
.286
f
,
.334
f
,
.370
f
,
.443
f
,
.497
f
,
.581
f
,
.690
f
,
.832
f
,
.056
f
,
.153
f
,
.221
f
,
.278
f
,
.311
f
,
.365
f
,
.420
f
,
.463
f
,
.524
f
,
.562
f
,
.625
f
,
.699
f
,
.696
f
,
.762
f
,
.829
f
,
.889
f
,
.024
f
,
.093
f
,
.104
f
,
.119
f
,
.104
f
,
.154
f
,
.153
f
,
.216
f
,
.273
f
,
.376
f
,
.202
f
,
.138
f
,
.609
f
,
.690
f
,
.814
f
,
.930
f
,
.027
f
,
.098
f
,
.158
f
,
.252
f
,
.304
f
,
.393
f
,
.706
f
,
.462
f
,
.630
f
,
.554
f
,
.845
f
,
.643
f
,
.852
f
,
.694
f
,
.781
f
,
.858
f
,
.169
f
,
.169
f
,
.248
f
,
.248
f
,
.105
f
,
.124
f
,
.110
f
,
.197
f
,
.308
f
,
.242
f
,
.385
f
,
.428
f
,
.441
f
,
.525
f
,
.616
f
,
.689
f
,
.375
f
,
.137
f
,
.146
f
,
.314
f
,
.412
f
,
.437
f
,
.454
f
,
.520
f
,
.510
f
,
.615
f
,
.692
f
,
.576
f
,
.701
f
,
.701
f
,
.780
f
,
.846
f
,
.039
f
,
.091
f
,
.109
f
,
.125
f
,
.209
f
,
.256
f
,
.251
f
,
.126
f
,
.295
f
,
.350
f
,
.420
f
,
.475
f
,
.568
f
,
.625
f
,
.738
f
,
.875
f
,
.055
f
,
.153
f
,
.236
f
,
.281
f
,
.338
f
,
.390
f
,
.425
f
,
.462
f
,
.522
f
,
.563
f
,
.609
f
,
.687
f
,
.674
f
,
.721
f
,
.776
f
,
.846
f
,
.034
f
,
.078
f
,
.123
f
,
.148
f
,
.201
f
,
.153
f
,
.215
f
,
.253
f
,
.239
f
,
.335
f
,
.382
f
,
.446
f
,
.502
f
,
.581
f
,
.690
f
,
.832
f
,
.063
f
,
.145
f
,
.220
f
,
.284
f
,
.340
f
,
.386
f
,
.424
f
,
.467
f
,
.520
f
,
.550
f
,
.611
f
,
.671
f
,
.718
f
,
.758
f
,
.792
f
,
.854
f
,
.065
f
,
.117
f
,
.138
f
,
.163
f
,
.225
f
,
.371
f
,
.188
f
,
.145
f
,
.457
f
,
.345
f
,
.102
f
,
.276
f
,
.609
f
,
.690
f
,
.814
f
,
.930
f
,
.032
f
,
.133
f
,
.188
f
,
.247
f
,
.268
f
,
.350
f
,
.427
f
,
.495
f
,
.538
f
,
.578
f
,
.641
f
,
.835
f
,
.700
f
,
.759
f
,
.780
f
,
.868
f
,
.187
f
,
.187
f
,
.135
f
,
.170
f
,
.218
f
,
.144
f
,
.261
f
,
.340
f
,
.416
f
,
.335
f
,
.388
f
,
.428
f
,
.441
f
,
.525
f
,
.616
f
,
.689
f
,
.367
f
,
.273
f
,
.143
f
,
.308
f
,
.382
f
,
.439
f
,
.410
f
,
.470
f
,
.524
f
,
.461
f
,
.626
f
,
.528
f
,
.583
f
,
.702
f
,
.673
f
,
.773
f
,
.031
f
,
.068
f
,
.124
f
,
.154
f
,
.217
f
,
.154
f
,
.255
f
,
.302
f
,
.358
f
,
.405
f
,
.435
f
,
.475
f
,
.568
f
,
.625
f
,
.738
f
,
.875
f
,
.061
f
,
.144
f
,
.221
f
,
.261
f
,
.325
f
,
.366
f
,
.448
f
,
.495
f
,
.538
f
,
.590
f
,
.618
f
,
.659
f
,
.686
f
,
.739
f
,
.791
f
,
.858
f
,
.034
f
,
.079
f
,
.149
f
,
.175
f
,
.198
f
,
.231
f
,
.249
f
,
.327
f
,
.353
f
,
.382
f
,
.443
f
,
.489
f
,
.570
f
,
.649
f
,
.740
f
,
.882
f
,
.076
f
,
.148
f
,
.218
f
,
.296
f
,
.357
f
,
.400
f
,
.444
f
,
.472
f
,
.516
f
,
.554
f
,
.597
f
,
.630
f
,
.678
f
,
.722
f
,
.781
f
,
.864
f
,
.021
f
,
.055
f
,
.135
f
,
.053
f
,
.180
f
,
.150
f
,
.370
f
,
.214
f
,
.331
f
,
.530
f
,
.219
f
,
.326
f
,
.609
f
,
.690
f
,
.814
f
,
.930
f
,
.049
f
,
.095
f
,
.149
f
,
.216
f
,
.370
f
,
.294
f
,
.443
f
,
.489
f
,
.526
f
,
.594
f
,
.621
f
,
.747
f
,
.656
f
,
.762
f
,
.780
f
,
.884
f
,
.216
f
,
.248
f
,
.160
f
,
.190
f
,
.197
f
,
.356
f
,
.296
f
,
.341
f
,
.391
f
,
.428
f
,
.441
f
,
.525
f
,
.593
f
,
.668
f
,
.760
f
,
.637
f
,
.388
f
,
.250
f
,
.155
f
,
.334
f
,
.419
f
,
.456
f
,
.497
f
,
.448
f
,
.591
f
,
.542
f
,
.552
f
,
.719
f
,
.656
f
,
.709
f
,
.849
f
,
.897
f
,
.034
f
,
.078
f
,
.151
f
,
.184
f
,
.211
f
,
.253
f
,
.262
f
,
.351
f
,
.358
f
,
.405
f
,
.435
f
,
.475
f
,
.568
f
,
.625
f
,
.738
f
,
.875
f
,
.076
f
,
.148
f
,
.229
f
,
.303
f
,
.341
f
,
.376
f
,
.444
f
,
.480
f
,
.548
f
,
.510
f
,
.594
f
,
.638
f
,
.685
f
,
.742
f
,
.800
f
,
.882
f
,
.028
f
,
.062
f
,
.089
f
,
.114
f
,
.174
f
,
.196
f
,
.241
f
,
.294
f
,
.335
f
,
.371
f
,
.443
f
,
.482
f
,
.511
f
,
.590
f
,
.714
f
,
.832
f
,
.075
f
,
.157
f
,
.223
f
,
.281
f
,
.342
f
,
.386
f
,
.450
f
,
.489
f
,
.542
f
,
.590
f
,
.611
f
,
.653
f
,
.682
f
,
.728
f
,
.783
f
,
.893
f
,
.041
f
,
.076
f
,
.186
f
,
.109
f
,
.175
f
,
.195
f
,
.209
f
,
.227
f
,
.274
f
,
.355
f
,
.196
f
,
.314
f
,
.609
f
,
.690
f
,
.814
f
,
.930
f
,
.049
f
,
.097
f
,
.161
f
,
.221
f
,
.415
f
,
.304
f
,
.454
f
,
.492
f
,
.527
f
,
.581
f
,
.629
f
,
.747
f
,
.685
f
,
.758
f
,
.836
f
,
.914
f
,
.225
f
,
.248
f
,
.187
f
,
.074
f
,
.228
f
,
.365
f
,
.295
f
,
.337
f
,
.391
f
,
.428
f
,
.441
f
,
.525
f
,
.593
f
,
.668
f
,
.760
f
,
.637
f
,
.413
f
,
.277
f
,
.431
f
,
.456
f
,
.115
f
,
.162
f
,
.254
f
,
.334
f
,
.503
f
,
.661
f
,
.515
f
,
.515
f
,
.696
f
,
.751
f
,
.836
f
,
.897
f
,
.023
f
,
.057
f
,
.090
f
,
.116
f
,
.180
f
,
.197
f
,
.239
f
,
.283
f
,
.338
f
,
.365
f
,
.420
f
,
.475
f
,
.568
f
,
.625
f
,
.738
f
,
.875
f
,
.074
f
,
.157
f
,
.227
f
,
.282
f
,
.365
f
,
.410
f
,
.451
f
,
.504
f
,
.577
f
,
.610
f
,
.646
f
,
.679
f
,
.728
f
,
.782
f
,
.855
f
,
.923
f
,
.028
f
,
.062
f
,
.089
f
,
.120
f
,
.165
f
,
.204
f
,
.243
f
,
.304
f
,
.335
f
,
.371
f
,
.443
f
,
.482
f
,
.511
f
,
.590
f
,
.714
f
,
.832
f
,
.073
f
,
.157
f
,
.220
f
,
.287
f
,
.343
f
,
.393
f
,
.451
f
,
.489
f
,
.567
f
,
.596
f
,
.616
f
,
.650
f
,
.711
f
,
.760
f
,
.840
f
,
.917
f
,
.041
f
,
.076
f
,
.186
f
,
.092
f
,
.203
f
,
.116
f
,
.222
f
,
.261
f
,
.330
f
,
.438
f
,
.214
f
,
.316
f
,
.609
f
,
.690
f
,
.814
f
,
.930
f
,
.049
f
,
.104
f
,
.163
f
,
.221
f
,
.414
f
,
.448
f
,
.513
f
,
.561
f
,
.566
f
,
.744
f
,
.614
f
,
.683
f
,
.721
f
,
.761
f
,
.854
f
,
.915
f
,
.228
f
,
.248
f
,
.196
f
,
.096
f
,
.300
f
,
.225
f
,
.295
f
,
.344
f
,
.466
f
,
.385
f
,
.403
f
,
.468
f
,
.441
f
,
.525
f
,
.616
f
,
.689
f
,
.414
f
,
.307
f
,
.445
f
,
.460
f
,
.115
f
,
.162
f
,
.254
f
,
.334
f
,
.459
f
,
.495
f
,
.501
f
,
.705
f
,
.680
f
,
.751
f
,
.836
f
,
.897
f
,
.031
f
,
.065
f
,
.100
f
,
.132
f
,
.201
f
,
.221
f
,
.280
f
,
.333
f
,
.374
f
,
.405
f
,
.435
f
,
.475
f
,
.568
f
,
.625
f
,
.738
f
,
.875
f
,
.073
f
,
.157
f
,
.226
f
,
.288
f
,
.349
f
,
.401
f
,
.450
f
,
.489
f
,
.589
f
,
.621
f
,
.649
f
,
.680
f
,
.718
f
,
.759
f
,
.843
f
,
.923
f
,
.029
f
,
.067
f
,
.107
f
,
.140
f
,
.207
f
,
.227
f
,
.279
f
,
.339
f
,
.369
f
,
.393
f
,
.444
f
,
.494
f
,
.575
f
,
.651
f
,
.740
f
,
.882
f
,
.042
f
,
.093
f
,
.147
f
,
.184
f
,
.220
f
,
.256
f
,
.290
f
,
.323
f
,
.402
f
,
.455
f
,
.495
f
,
.540
f
,
.619
f
,
.687
f
,
.748
f
,
.876
f
,
.021
f
,
.055
f
,
.098
f
,
.053
f
,
.206
f
,
.221
f
,
.389
f
,
.239
f
,
.343
f
,
.438
f
,
.228
f
,
.316
f
,
.609
f
,
.690
f
,
.814
f
,
.930
f
,
.049
f
,
.104
f
,
.160
f
,
.221
f
,
.235
f
,
.426
f
,
.455
f
,
.529
f
,
.623
f
,
.551
f
,
.600
f
,
.677
f
,
.697
f
,
.760
f
,
.836
f
,
.914
f
,
.232
f
,
.201
f
,
.231
f
,
.309
f
,
.117
f
,
.096
f
,
.070
f
,
.044
f
,
.466
f
,
.385
f
,
.403
f
,
.468
f
,
.441
f
,
.525
f
,
.616
f
,
.689
f
,
.418
f
,
.251
f
,
.450
f
,
.394
f
,
.115
f
,
.162
f
,
.254
f
,
.334
f
,
.460
f
,
.488
f
,
.494
f
,
.703
f
,
.680
f
,
.751
f
,
.836
f
,
.897
f
,
.031
f
,
.065
f
,
.100
f
,
.132
f
,
.207
f
,
.229
f
,
.289
f
,
.342
f
,
.435
f
,
.346
f
,
.461
f
,
.482
f
,
.568
f
,
.625
f
,
.738
f
,
.875
f
,
.043
f
,
.093
f
,
.146
f
,
.180
f
,
.241
f
,
.278
f
,
.307
f
,
.330
f
,
.391
f
,
.451
f
,
.472
f
,
.524
f
,
.610
f
,
.651
f
,
.741
f
,
.874
f
,
.029
f
,
.067
f
,
.107
f
,
.140
f
,
.212
f
,
.233
f
,
.269
f
,
.343
f
,
.369
f
,
.393
f
,
.444
f
,
.494
f
,
.575
f
,
.651
f
,
.740
f
,
.882
f
,
.042
f
,
.093
f
,
.151
f
,
.188
f
,
.238
f
,
.271
f
,
.293
f
,
.321
f
,
.408
f
,
.459
f
,
.513
f
,
.553
f
,
.609
f
,
.672
f
,
.777
f
,
.893
f
,
.021
f
,
.055
f
,
.098
f
,
.053
f
,
.210
f
,
.226
f
,
.355
f
,
.247
f
,
.439
f
,
.514
f
,
.637
f
,
.836
f
,
.333
f
,
.420
f
,
.227
f
,
.313
f
,
.019
f
,
.060
f
,
.098
f
,
.133
f
,
.147
f
,
.179
f
,
.237
f
,
.125
f
,
.196
f
,
.407
f
,
.451
f
,
.477
f
,
.572
f
,
.654
f
,
.774
f
,
.903
f
,
.239
f
,
.375
f
,
.204
f
,
.250
f
,
.150
f
,
.150
f
,
.096
f
,
.057
f
,
.426
f
,
.383
f
,
.403
f
,
.468
f
,
.441
f
,
.525
f
,
.616
f
,
.689
f
,
.407
f
,
.407
f
,
.126
f
,
.244
f
,
.134
f
,
.203
f
,
.294
f
,
.406
f
,
.449
f
,
.469
f
,
.573
f
,
.482
f
,
.751
f
,
.751
f
,
.836
f
,
.897
f
,
.031
f
,
.065
f
,
.100
f
,
.132
f
,
.212
f
,
.232
f
,
.281
f
,
.348
f
,
.435
f
,
.346
f
,
.461
f
,
.482
f
,
.568
f
,
.625
f
,
.738
f
,
.875
f
,
.043
f
,
.093
f
,
.152
f
,
.190
f
,
.235
f
,
.262
f
,
.295
f
,
.330
f
,
.354
f
,
.417
f
,
.455
f
,
.492
f
,
.620
f
,
.685
f
,
.768
f
,
.888
f
,
.029
f
,
.067
f
,
.107
f
,
.140
f
,
.167
f
,
.219
f
,
.238
f
,
.298
f
,
.352
f
,
.382
f
,
.443
f
,
.485
f
,
.532
f
,
.596
f
,
.714
f
,
.832
f
,
.056
f
,
.105
f
,
.161
f
,
.195
f
,
.230
f
,
.267
f
,
.289
f
,
.322
f
,
.367
f
,
.414
f
,
.462
f
,
.529
f
,
.579
f
,
.667
f
,
.742
f
,
.875
f
,
.021
f
,
.053
f
,
.094
f
,
.052
f
,
.214
f
,
.235
f
,
.288
f
,
.235
f
,
.451
f
,
.530
f
,
.632
f
,
.826
f
,
.316
f
,
.233
f
,
.466
f
,
.356
f
,
.019
f
,
.060
f
,
.084
f
,
.110
f
,
.192
f
,
.162
f
,
.235
f
,
.287
f
,
.418
f
,
.363
f
,
.447
f
,
.482
f
,
.573
f
,
.631
f
,
.724
f
,
.880
f
,
.243
f
,
.248
f
,
.210
f
,
.074
f
,
.237
f
,
.308
f
,
.378
f
,
.334
f
,
.391
f
,
.428
f
,
.441
f
,
.525
f
,
.593
f
,
.668
f
,
.760
f
,
.637
f
,
.398
f
,
.398
f
,
.235
f
,
.418
f
,
.105
f
,
.166
f
,
.287
f
,
.405
f
,
.458
f
,
.482
f
,
.589
f
,
.488
f
,
.630
f
,
.630
f
,
.751
f
,
.866
f
,
.031
f
,
.065
f
,
.100
f
,
.132
f
,
.218
f
,
.235
f
,
.269
f
,
.344
f
,
.400
f
,
.435
f
,
.478
f
,
.396
f
,
.568
f
,
.625
f
,
.738
f
,
.875
f
,
.056
f
,
.106
f
,
.160
f
,
.190
f
,
.215
f
,
.248
f
,
.292
f
,
.331
f
,
.383
f
,
.415
f
,
.459
f
,
.503
f
,
.594
f
,
.678
f
,
.783
f
,
.898
f
,
.029
f
,
.067
f
,
.108
f
,
.144
f
,
.226
f
,
.241
f
,
.293
f
,
.353
f
,
.275
f
,
.384
f
,
.446
f
,
.502
f
,
.579
f
,
.651
f
,
.740
f
,
.882
f
,
.038
f
,
.077
f
,
.112
f
,
.161
f
,
.202
f
,
.241
f
,
.289
f
,
.323
f
,
.362
f
,
.410
f
,
.462
f
,
.515
f
,
.582
f
,
.658
f
,
.727
f
,
.868
f
,
.021
f
,
.053
f
,
.094
f
,
.052
f
,
.227
f
,
.249
f
,
.316
f
,
.237
f
,
.483
f
,
.630
f
,
.726
f
,
.836
f
,
.583
f
,
.493
f
,
.274
f
,
.426
f
,
.034
f
,
.080
f
,
.109
f
,
.146
f
,
.210
f
,
.181
f
,
.285
f
,
.223
f
,
.385
f
,
.436
f
,
.469
f
,
.544
f
,
.576
f
,
.619
f
,
.714
f
,
.880
f
,
.250
f
,
.248
f
,
.218
f
,
.074
f
,
.241
f
,
.293
f
,
.378
f
,
.334
f
,
.408
f
,
.522
f
,
.409
f
,
.317
f
,
.547
f
,
.397
f
,
.616
f
,
.689
f
,
.410
f
,
.308
f
,
.440
f
,
.469
f
,
.111
f
,
.160
f
,
.250
f
,
.328
f
,
.516
f
,
.674
f
,
.506
f
,
.506
f
,
.685
f
,
.751
f
,
.836
f
,
.897
f
,
.031
f
,
.065
f
,
.100
f
,
.132
f
,
.229
f
,
.267
f
,
.359
f
,
.244
f
,
.442
f
,
.346
f
,
.461
f
,
.482
f
,
.568
f
,
.625
f
,
.738
f
,
.875
f
,
.056
f
,
.106
f
,
.160
f
,
.190
f
,
.219
f
,
.255
f
,
.302
f
,
.340
f
,
.392
f
,
.421
f
,
.463
f
,
.496
f
,
.578
f
,
.642
f
,
.717
f
,
.869
f
,
.029
f
,
.067
f
,
.108
f
,
.144
f
,
.223
f
,
.250
f
,
.318
f
,
.362
f
,
.400
f
,
.444
f
,
.476
f
,
.508
f
,
.579
f
,
.651
f
,
.740
f
,
.882
f
,
.032
f
,
.096
f
,
.155
f
,
.192
f
,
.227
f
,
.255
f
,
.306
f
,
.349
f
,
.381
f
,
.418
f
,
.464
f
,
.519
f
,
.589
f
,
.653
f
,
.721
f
,
.867
f
,
.018
f
,
.049
f
,
.037
f
,
.080
f
,
.201
f
,
.248
f
,
.091
f
,
.152
f
,
.229
f
,
.253
f
,
.323
f
,
.259
f
,
.632
f
,
.826
f
,
.274
f
,
.428
f
,
.028
f
,
.096
f
,
.165
f
,
.230
f
,
.434
f
,
.361
f
,
.449
f
,
.500
f
,
.554
f
,
.596
f
,
.610
f
,
.679
f
,
.678
f
,
.743
f
,
.801
f
,
.903
f
,
.260
f
,
.248
f
,
.208
f
,
.243
f
,
.259
f
,
.302
f
,
.414
f
,
.315
f
,
.408
f
,
.522
f
,
.409
f
,
.317
f
,
.535
f
,
.620
f
,
.357
f
,
.692
f
,
.405
f
,
.266
f
,
.432
f
,
.463
f
,
.111
f
,
.170
f
,
.250
f
,
.328
f
,
.535
f
,
.656
f
,
.525
f
,
.525
f
,
.693
f
,
.751
f
,
.836
f
,
.897
f
,
.031
f
,
.065
f
,
.100
f
,
.132
f
,
.211
f
,
.249
f
,
.320
f
,
.372
f
,
.478
f
,
.396
f
,
.568
f
,
.608
f
,
.647
f
,
.738
f
,
.849
f
,
.902
f
,
.032
f
,
.095
f
,
.153
f
,
.190
f
,
.237
f
,
.269
f
,
.305
f
,
.344
f
,
.390
f
,
.423
f
,
.465
f
,
.514
f
,
.581
f
,
.637
f
,
.718
f
,
.869
f
,
.033
f
,
.072
f
,
.110
f
,
.152
f
,
.214
f
,
.250
f
,
.273
f
,
.316
f
,
.419
f
,
.449
f
,
.476
f
,
.508
f
,
.579
f
,
.651
f
,
.740
f
,
.882
f
,
.039
f
,
.095
f
,
.144
f
,
.185
f
,
.250
f
,
.296
f
,
.323
f
,
.362
f
,
.416
f
,
.467
f
,
.502
f
,
.531
f
,
.589
f
,
.643
f
,
.714
f
,
.867
f
,
.018
f
,
.049
f
,
.036
f
,
.079
f
,
.095
f
,
.246
f
,
.091
f
,
.131
f
,
.233
f
,
.268
f
,
.342
f
,
.294
f
,
.609
f
,
.690
f
,
.814
f
,
.930
f
,
.037
f
,
.093
f
,
.146
f
,
.175
f
,
.270
f
,
.226
f
,
.408
f
,
.339
f
,
.448
f
,
.303
f
,
.472
f
,
.506
f
,
.580
f
,
.640
f
,
.726
f
,
.880
f
,
.273
f
,
.235
f
,
.283
f
,
.319
f
,
.117
f
,
.096
f
,
.070
f
,
.044
f
,
.475
f
,
.609
f
,
.357
f
,
.692
f
,
.414
f
,
.278
f
,
.536
f
,
.462
f
,
.374
f
,
.229
f
,
.139
f
,
.344
f
,
.414
f
,
.441
f
,
.505
f
,
.402
f
,
.496
f
,
.572
f
,
.606
f
,
.526
f
,
.680
f
,
.751
f
,
.836
f
,
.897
f
,
.031
f
,
.072
f
,
.110
f
,
.157
f
,
.239
f
,
.277
f
,
.437
f
,
.352
f
,
.565
f
,
.578
f
,
.631
f
,
.514
f
,
.748
f
,
.578
f
,
.849
f
,
.902
f
,
.039
f
,
.095
f
,
.152
f
,
.202
f
,
.252
f
,
.305
f
,
.345
f
,
.432
f
,
.423
f
,
.467
f
,
.509
f
,
.544
f
,
.592
f
,
.640
f
,
.713
f
,
.869
f
,
.028
f
,
.062
f
,
.089
f
,
.120
f
,
.152
f
,
.173
f
,
.191
f
,
.211
f
,
.252
f
,
.277
f
,
.302
f
,
.324
f
,
.446
f
,
.502
f
,
.592
f
,
.767
f
,
.043
f
,
.090
f
,
.136
f
,
.191
f
,
.256
f
,
.311
f
,
.359
f
,
.390
f
,
.424
f
,
.470
f
,
.492
f
,
.534
f
,
.593
f
,
.655
f
,
.776
f
,
.893
f
,
.012
f
,
.032
f
,
.021
f
,
.058
f
,
.093
f
,
.135
f
,
.059
f
,
.026
f
,
.228
f
,
.270
f
,
.292
f
,
.324
f
,
.609
f
,
.690
f
,
.814
f
,
.930
f
,
.042
f
,
.097
f
,
.141
f
,
.176
f
,
.218
f
,
.342
f
,
.143
f
,
.270
f
,
.446
f
,
.303
f
,
.480
f
,
.516
f
,
.580
f
,
.627
f
,
.774
f
,
.903
f
,
.292
f
,
.238
f
,
.299
f
,
.331
f
,
.117
f
,
.096
f
,
.070
f
,
.044
f
,
.430
f
,
.536
f
,
.612
f
,
.347
f
,
.593
f
,
.668
f
,
.760
f
,
.637
f
,
.386
f
,
.214
f
,
.133
f
,
.342
f
,
.405
f
,
.444
f
,
.507
f
,
.442
f
,
.464
f
,
.479
f
,
.565
f
,
.517
f
,
.680
f
,
.751
f
,
.836
f
,
.897
f
,
.031
f
,
.065
f
,
.100
f
,
.131
f
,
.165
f
,
.188
f
,
.204
f
,
.222
f
,
.275
f
,
.303
f
,
.336
f
,
.383
f
,
.568
f
,
.625
f
,
.738
f
,
.875
f
,
.046
f
,
.101
f
,
.141
f
,
.193
f
,
.256
f
,
.302
f
,
.345
f
,
.451
f
,
.425
f
,
.468
f
,
.509
f
,
.535
f
,
.586
f
,
.649
f
,
.744
f
,
.874
f
,
.028
f
,
.062
f
,
.089
f
,
.120
f
,
.155
f
,
.189
f
,
.214
f
,
.247
f
,
.310
f
,
.338
f
,
.392
f
,
.444
f
,
.497
f
,
.581
f
,
.690
f
,
.832
f
,
.049
f
,
.101
f
,
.142
f
,
.181
f
,
.211
f
,
.247
f
,
.287
f
,
.325
f
,
.377
f
,
.426
f
,
.473
f
,
.530
f
,
.587
f
,
.645
f
,
.745
f
,
.875
f
,
.021
f
,
.055
f
,
.098
f
,
.053
f
,
.280
f
,
.306
f
,
.168
f
,
.226
f
,
.257
f
,
.314
f
,
.351
f
,
.309
f
,
.609
f
,
.690
f
,
.814
f
,
.930
f
,
.048
f
,
.102
f
,
.140
f
,
.185
f
,
.274
f
,
.321
f
,
.143
f
,
.250
f
,
.443
f
,
.359
f
,
.443
f
,
.483
f
,
.542
f
,
.609
f
,
.746
f
,
.894
f
,
.317
f
,
.252
f
,
.324
f
,
.348
f
,
.117
f
,
.096
f
,
.070
f
,
.044
f
,
.594
f
,
.404
f
,
.499
f
,
.531
f
,
.593
f
,
.668
f
,
.760
f
,
.637
f
,
.402
f
,
.260
f
,
.124
f
,
.345
f
,
.382
f
,
.444
f
,
.423
f
,
.448
f
,
.473
f
,
.511
f
,
.563
f
,
.516
f
,
.680
f
,
.751
f
,
.836
f
,
.897
f
,
.031
f
,
.065
f
,
.100
f
,
.132
f
,
.166
f
,
.188
f
,
.207
f
,
.225
f
,
.301
f
,
.322
f
,
.341
f
,
.404
f
,
.475
f
,
.579
f
,
.693
f
,
.875
f
,
.048
f
,
.100
f
,
.142
f
,
.187
f
,
.216
f
,
.244
f
,
.283
f
,
.318
f
,
.378
f
,
.430
f
,
.473
f
,
.525
f
,
.586
f
,
.642
f
,
.744
f
,
.874
f
,
.028
f
,
.062
f
,
.089
f
,
.120
f
,
.155
f
,
.189
f
,
.215
f
,
.249
f
,
.274
f
,
.345
f
,
.363
f
,
.409
f
,
.502
f
,
.581
f
,
.690
f
,
.832
f
,
.053
f
,
.095
f
,
.132
f
,
.175
f
,
.211
f
,
.243
f
,
.288
f
,
.326
f
,
.399
f
,
.434
f
,
.474
f
,
.527
f
,
.579
f
,
.637
f
,
.745
f
,
.875
f
,
.021
f
,
.053
f
,
.092
f
,
.052
f
,
.054
f
,
.108
f
,
.180
f
,
.116
f
,
.204
f
,
.271
f
,
.321
f
,
.362
f
,
.609
f
,
.690
f
,
.814
f
,
.930
f
,
.054
f
,
.105
f
,
.177
f
,
.148
f
,
.216
f
,
.260
f
,
.394
f
,
.301
f
,
.226
f
,
.381
f
,
.443
f
,
.484
f
,
.588
f
,
.680
f
,
.774
f
,
.903
f
,
.339
f
,
.339
f
,
.248
f
,
.248
f
,
.222
f
,
.288
f
,
.111
f
,
.057
f
,
.352
f
,
.366
f
,
.422
f
,
.505
f
,
.593
f
,
.668
f
,
.760
f
,
.637
f
,
.387
f
,
.016
f
,
.160
f
,
.380
f
,
.113
f
,
.221
f
,
.346
f
,
.410
f
,
.442
f
,
.482
f
,
.474
f
,
.496
f
,
.563
f
,
.508
f
,
.700
f
,
.866
f
,
.031
f
,
.065
f
,
.100
f
,
.131
f
,
.148
f
,
.177
f
,
.202
f
,
.218
f
,
.338
f
,
.280
f
,
.357
f
,
.420
f
,
.568
f
,
.625
f
,
.738
f
,
.875
f
,
.053
f
,
.098
f
,
.135
f
,
.175
f
,
.212
f
,
.242
f
,
.277
f
,
.307
f
,
.384
f
,
.434
f
,
.476
f
,
.536
f
,
.594
f
,
.644
f
,
.744
f
,
.874
f
,
.029
f
,
.067
f
,
.107
f
,
.140
f
,
.184
f
,
.215
f
,
.249
f
,
.274
f
,
.335
f
,
.376
f
,
.406
f
,
.479
f
,
.579
f
,
.651
f
,
.740
f
,
.882
f
,
.056
f
,
.085
f
,
.129
f
,
.177
f
,
.209
f
,
.238
f
,
.289
f
,
.323
f
,
.361
f
,
.413
f
,
.471
f
,
.539
f
,
.601
f
,
.677
f
,
.776
f
,
.893
f
,
.021
f
,
.055
f
,
.098
f
,
.053
f
,
.138
f
,
.211
f
,
.281
f
,
.183
f
,
.345
f
,
.232
f
,
.387
f
,
.290
f
,
.609
f
,
.690
f
,
.814
f
,
.930
f
,
.057
f
,
.083
f
,
.167
f
,
.124
f
,
.232
f
,
.182
f
,
.401
f
,
.293
f
,
.226
f
,
.358
f
,
.445
f
,
.497
f
,
.581
f
,
.654
f
,
.774
f
,
.903
f
,
.353
f
,
.353
f
,
.248
f
,
.248
f
,
.112
f
,
.240
f
,
.290
f
,
.096
f
,
.354
f
,
.374
f
,
.393
f
,
.433
f
,
.595
f
,
.468
f
,
.648
f
,
.692
f
,
.378
f
,
.016
f
,
.106
f
,
.339
f
,
.119
f
,
.191
f
,
.327
f
,
.397
f
,
.446
f
,
.477
f
,
.512
f
,
.549
f
,
.680
f
,
.751
f
,
.836
f
,
.897
f
,
.031
f
,
.065
f
,
.100
f
,
.132
f
,
.172
f
,
.211
f
,
.338
f
,
.261
f
,
.349
f
,
.375
f
,
.402
f
,
.437
f
,
.568
f
,
.625
f
,
.738
f
,
.875
f
,
.057
f
,
.086
f
,
.129
f
,
.173
f
,
.199
f
,
.232
f
,
.280
f
,
.306
f
,
.366
f
,
.419
f
,
.471
f
,
.531
f
,
.592
f
,
.652
f
,
.744
f
,
.874
f
,
.029
f
,
.067
f
,
.107
f
,
.140
f
,
.184
f
,
.215
f
,
.249
f
,
.286
f
,
.371
f
,
.396
f
,
.420
f
,
.443
f
,
.477
f
,
.533
f
,
.682
f
,
.832
f
,
.047
f
,
.094
f
,
.134
f
,
.165
f
,
.205
f
,
.237
f
,
.277
f
,
.306
f
,
.366
f
,
.411
f
,
.466
f
,
.519
f
,
.558
f
,
.619
f
,
.727
f
,
.868
f
,
.021
f
,
.055
f
,
.098
f
,
.053
f
,
.115
f
,
.175
f
,
.238
f
,
.195
f
,
.305
f
,
.390
f
,
.332
f
,
.232
f
,
.424
f
,
.243
f
,
.626
f
,
.826
f
,
.030
f
,
.071
f
,
.108
f
,
.138
f
,
.195
f
,
.114
f
,
.295
f
,
.240
f
,
.320
f
,
.362
f
,
.424
f
,
.489
f
,
.542
f
,
.613
f
,
.730
f
,
.880
f
,
.385
f
,
.385
f
,
.248
f
,
.375
f
,
.172
f
,
.262
f
,
.393
f
,
.347
f
,
.364
f
,
.416
f
,
.412
f
,
.433
f
,
.448
f
,
.486
f
,
.648
f
,
.533
f
,
.354
f
,
.016
f
,
.183
f
,
.308
f
,
.111
f
,
.177
f
,
.269
f
,
.346
f
,
.414
f
,
.440
f
,
.454
f
,
.520
f
,
.507
f
,
.544
f
,
.700
f
,
.866
f
,
.031
f
,
.065
f
,
.100
f
,
.132
f
,
.172
f
,
.210
f
,
.232
f
,
.261
f
,
.323
f
,
.361
f
,
.390
f
,
.418
f
,
.444
f
,
.468
f
,
.548
f
,
.773
f
,
.030
f
,
.072
f
,
.110
f
,
.153
f
,
.205
f
,
.246
f
,
.283
f
,
.312
f
,
.355
f
,
.399
f
,
.461
f
,
.532
f
,
.594
f
,
.652
f
,
.744
f
,
.874
f
,
.029
f
,
.067
f
,
.108
f
,
.147
f
,
.206
f
,
.237
f
,
.286
f
,
.334
f
,
.358
f
,
.424
f
,
.461
f
,
.494
f
,
.522
f
,
.565
f
,
.791
f
,
.882
f
,
.039
f
,
.091
f
,
.132
f
,
.168
f
,
.214
f
,
.244
f
,
.278
f
,
.311
f
,
.373
f
,
.413
f
,
.465
f
,
.521
f
,
.596
f
,
.677
f
,
.776
f
,
.893
f
,
.021
f
,
.055
f
,
.098
f
,
.053
f
,
.166
f
,
.219
f
,
.411
f
,
.273
f
,
.379
f
,
.461
f
,
.256
f
,
.206
f
,
.501
f
,
.264
f
,
.587
f
,
.816
f
,
.031
f
,
.066
f
,
.104
f
,
.139
f
,
.154
f
,
.187
f
,
.203
f
,
.241
f
,
.318
f
,
.360
f
,
.414
f
,
.493
f
,
.621
f
,
.692
f
,
.775
f
,
.903
f
,
.429
f
,
.223
f
,
.430
f
,
.462
f
,
.480
f
,
.504
f
,
.532
f
,
.555
f
,
.170
f
,
.266
f
,
.111
f
,
.057
f
,
.327
f
,
.407
f
,
.441
f
,
.475
f
,
.307
f
,
.307
f
,
.126
f
,
.257
f
,
.091
f
,
.171
f
,
.253
f
,
.332
f
,
.390
f
,
.420
f
,
.457
f
,
.488
f
,
.573
f
,
.503
f
,
.700
f
,
.866
f
,
.031
f
,
.065
f
,
.100
f
,
.132
f
,
.176
f
,
.215
f
,
.261
f
,
.311
f
,
.386
f
,
.439
f
,
.466
f
,
.489
f
,
.562
f
,
.514
f
,
.612
f
,
.773
f
,
.033
f
,
.073
f
,
.102
f
,
.146
f
,
.177
f
,
.216
f
,
.255
f
,
.295
f
,
.323
f
,
.388
f
,
.450
f
,
.502
f
,
.580
f
,
.644
f
,
.744
f
,
.874
f
,
.029
f
,
.067
f
,
.108
f
,
.147
f
,
.210
f
,
.259
f
,
.308
f
,
.364
f
,
.503
f
,
.543
f
,
.584
f
,
.646
f
,
.723
f
,
.578
f
,
.791
f
,
.882
f
,
.028
f
,
.068
f
,
.122
f
,
.163
f
,
.194
f
,
.231
f
,
.273
f
,
.310
f
,
.357
f
,
.403
f
,
.464
f
,
.533
f
,
.596
f
,
.677
f
,
.776
f
,
.893
f
,
.048
f
,
.094
f
,
.177
f
,
.218
f
,
.307
f
,
.432
f
,
.273
f
,
.229
f
,
.500
f
,
.253
f
,
.603
f
,
.513
f
,
.754
f
,
.673
f
,
.825
f
,
.930
f
,
.018
f
,
.062
f
,
.102
f
,
.129
f
,
.142
f
,
.173
f
,
.188
f
,
.226
f
,
.391
f
,
.313
f
,
.471
f
,
.402
f
,
.621
f
,
.692
f
,
.775
f
,
.903
f
,
.489
f
,
.443
f
,
.207
f
,
.494
f
,
.541
f
,
.577
f
,
.648
f
,
.720
f
,
.175
f
,
.237
f
,
.111
f
,
.057
f
,
.287
f
,
.335
f
,
.409
f
,
.374
f
,
.264
f
,
.187
f
,
.285
f
,
.318
f
,
.156
f
,
.106
f
,
.341
f
,
.251
f
,
.380
f
,
.391
f
,
.432
f
,
.475
f
,
.584
f
,
.513
f
,
.700
f
,
.866
f
,
.031
f
,
.068
f
,
.108
f
,
.157
f
,
.212
f
,
.261
f
,
.312
f
,
.371
f
,
.483
f
,
.517
f
,
.571
f
,
.611
f
,
.665
f
,
.738
f
,
.849
f
,
.902
f
,
.028
f
,
.068
f
,
.120
f
,
.154
f
,
.188
f
,
.219
f
,
.259
f
,
.305
f
,
.338
f
,
.387
f
,
.454
f
,
.520
f
,
.609
f
,
.691
f
,
.768
f
,
.888
f
};
modules/xphoto/test/test_grayworld.cpp
View file @
80063fd4
...
...
@@ -81,7 +81,13 @@ namespace cvtest {
Mat
currentResult
;
xphoto
::
autowbGrayworld
(
src
,
currentResult
,
wb_thresh
);
ASSERT_LE
(
cv
::
norm
(
currentResult
,
referenceResult
,
NORM_INF
),
acc_thresh
);
// test the 16-bit depth:
Mat
currentResult_16U
,
src_16U
;
src
.
convertTo
(
src_16U
,
CV_16UC3
,
256.0
);
xphoto
::
autowbGrayworld
(
src_16U
,
currentResult_16U
,
wb_thresh
);
currentResult_16U
.
convertTo
(
currentResult
,
CV_8UC3
,
1
/
256.0
);
ASSERT_LE
(
cv
::
norm
(
currentResult
,
referenceResult
,
NORM_INF
),
acc_thresh
);
}
}
...
...
modules/xphoto/test/test_learning_based_color_balance.cpp
0 → 100644
View file @
80063fd4
#include "test_precomp.hpp"
using
namespace
cv
;
namespace
cvtest
{
TEST
(
xphoto_simplefeatures
,
regression
)
{
float
acc_thresh
=
0.01
f
;
// Generate a test image:
Mat
test_im
(
1000
,
1000
,
CV_8UC3
);
RNG
rng
(
1234
);
rng
.
fill
(
test_im
,
RNG
::
NORMAL
,
Scalar
(
64
,
100
,
128
),
Scalar
(
10
,
10
,
10
));
threshold
(
test_im
,
test_im
,
200.0
,
255.0
,
THRESH_TRUNC
);
test_im
.
at
<
Vec3b
>
(
0
,
0
)
=
Vec3b
(
240
,
220
,
200
);
// Which should have the following features:
Vec2f
ref1
(
128.0
f
/
(
64
+
100
+
128
),
100.0
f
/
(
64
+
100
+
128
));
Vec2f
ref2
(
200.0
f
/
(
240
+
220
+
200
),
220.0
f
/
(
240
+
220
+
200
));
vector
<
Vec2f
>
dst_features
;
xphoto
::
extractSimpleFeatures
(
test_im
,
dst_features
,
255
,
0.98
f
,
64
);
ASSERT_LE
(
cv
::
norm
(
dst_features
[
0
],
ref1
,
NORM_INF
),
acc_thresh
);
ASSERT_LE
(
cv
::
norm
(
dst_features
[
1
],
ref2
,
NORM_INF
),
acc_thresh
);
ASSERT_LE
(
cv
::
norm
(
dst_features
[
2
],
ref1
,
NORM_INF
),
acc_thresh
);
ASSERT_LE
(
cv
::
norm
(
dst_features
[
3
],
ref1
,
NORM_INF
),
acc_thresh
);
// check 16 bit depth:
test_im
.
convertTo
(
test_im
,
CV_16U
,
256.0
);
xphoto
::
extractSimpleFeatures
(
test_im
,
dst_features
,
65535
,
0.98
f
,
64
);
ASSERT_LE
(
cv
::
norm
(
dst_features
[
0
],
ref1
,
NORM_INF
),
acc_thresh
);
ASSERT_LE
(
cv
::
norm
(
dst_features
[
1
],
ref2
,
NORM_INF
),
acc_thresh
);
ASSERT_LE
(
cv
::
norm
(
dst_features
[
2
],
ref1
,
NORM_INF
),
acc_thresh
);
ASSERT_LE
(
cv
::
norm
(
dst_features
[
3
],
ref1
,
NORM_INF
),
acc_thresh
);
}
}
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