From 16a3773a34ec5098744271260ce70f69c0503d23 Mon Sep 17 00:00:00 2001 From: yigitsoy Date: Tue, 3 Nov 2015 15:37:49 +0100 Subject: [PATCH 001/178] Fix inlier assignment in Hungarian algorithm While checking whether a match is a real match, the index of the corresponding column (row) for a row (column) is checked. The limit should be the number of the real columns (rows) for a given row (column). --- modules/shape/src/sc_dis.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/shape/src/sc_dis.cpp b/modules/shape/src/sc_dis.cpp index 3f11e8b1bb..815c30ffc6 100644 --- a/modules/shape/src/sc_dis.cpp +++ b/modules/shape/src/sc_dis.cpp @@ -763,7 +763,7 @@ void SCDMatcher::hungarian(cv::Mat &costMatrix, std::vector &outMatc inliers1.reserve(sizeScd1); for (size_t kc = 0; kc &outMatc inliers2.reserve(sizeScd2); for (size_t kc = 0; kc Date: Thu, 11 Feb 2016 11:27:43 +0100 Subject: [PATCH 002/178] Adapted estimateNewCameraMatrix to make it work with pincushion-like distortion. --- modules/calib3d/src/fisheye.cpp | 39 +++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/modules/calib3d/src/fisheye.cpp b/modules/calib3d/src/fisheye.cpp index 3d737e7f46..3e637d7939 100644 --- a/modules/calib3d/src/fisheye.cpp +++ b/modules/calib3d/src/fisheye.cpp @@ -517,12 +517,16 @@ void cv::fisheye::estimateNewCameraMatrixForUndistortRectify(InputArray K, Input int w = image_size.width, h = image_size.height; balance = std::min(std::max(balance, 0.0), 1.0); - cv::Mat points(1, 4, CV_64FC2); + cv::Mat points(1, 8, CV_64FC2); Vec2d* pptr = points.ptr(); - pptr[0] = Vec2d(w/2, 0); - pptr[1] = Vec2d(w, h/2); - pptr[2] = Vec2d(w/2, h); - pptr[3] = Vec2d(0, h/2); + pptr[0] = Vec2d(0, 0); + pptr[1] = Vec2d(w/2, 0); + pptr[2] = Vec2d(w, 0); + pptr[3] = Vec2d(w, h/2); + pptr[4] = Vec2d(w, h); + pptr[5] = Vec2d(w/2, h); + pptr[6] = Vec2d(0, h); + pptr[7] = Vec2d(0, h/2); #if 0 const int N = 10; @@ -532,7 +536,6 @@ void cv::fisheye::estimateNewCameraMatrixForUndistortRectify(InputArray K, Input { pptr[k++] = Vec2d(w/2, 0) - Vec2d(w/8, 0) + Vec2d(w/4/N*i, 0); pptr[k++] = Vec2d(w/2, h-1) - Vec2d(w/8, h-1) + Vec2d(w/4/N*i, h-1); - pptr[k++] = Vec2d(0, h/2) - Vec2d(0, h/8) + Vec2d(0, h/4/N*i); pptr[k++] = Vec2d(w-1, h/2) - Vec2d(w-1, h/8) + Vec2d(w-1, h/4/N*i); } @@ -553,10 +556,14 @@ void cv::fisheye::estimateNewCameraMatrixForUndistortRectify(InputArray K, Input double minx = DBL_MAX, miny = DBL_MAX, maxx = -DBL_MAX, maxy = -DBL_MAX; for(size_t i = 0; i < points.total(); ++i) { - miny = std::min(miny, pptr[i][1]); - maxy = std::max(maxy, pptr[i][1]); - minx = std::min(minx, pptr[i][0]); - maxx = std::max(maxx, pptr[i][0]); + if(i!=1 && i!=5){ + minx = std::min(minx, std::abs(pptr[i][0]-cn[0])); + } + if(i!=3 && i!=7){ + miny = std::min(miny, std::abs(pptr[i][1]-cn[1])); + } + maxy = std::max(maxy, std::abs(pptr[i][1]-cn[1])); + maxx = std::max(maxx, std::abs(pptr[i][0]-cn[0])); } #if 0 @@ -570,13 +577,13 @@ void cv::fisheye::estimateNewCameraMatrixForUndistortRectify(InputArray K, Input } #endif - double f1 = w * 0.5/(cn[0] - minx); - double f2 = w * 0.5/(maxx - cn[0]); - double f3 = h * 0.5 * aspect_ratio/(cn[1] - miny); - double f4 = h * 0.5 * aspect_ratio/(maxy - cn[1]); + double f1 = w * 0.5/(minx); + double f2 = w * 0.5/(maxx); + double f3 = h * 0.5 * aspect_ratio/(miny); + double f4 = h * 0.5 * aspect_ratio/(maxy); - double fmin = std::min(f1, std::min(f2, std::min(f3, f4))); - double fmax = std::max(f1, std::max(f2, std::max(f3, f4))); + double fmax = std::max(f1, f3); + double fmin = std::min(f2, f4); double f = balance * fmin + (1.0 - balance) * fmax; f *= fov_scale > 0 ? 1.0/fov_scale : 1.0; From 9e53f03968a92ed668ca4cd7677adc8b80fc64dd Mon Sep 17 00:00:00 2001 From: Gilles Rochefort Date: Sun, 29 May 2016 17:25:02 +0200 Subject: [PATCH 003/178] Fixed BackgroundSubstractorMOG2 in opencv_video. The number of gaussians involved in a mixture is supposed to be dynamically adjusted. After being increased, the number of gaussians can't be reduced anymore. It seems to be a regression as the legacy code located in modules/legacy/src/bgfg_gaussmix.cpp allows to reduce such number of gaussians. --- modules/video/src/bgfg_gaussmix2.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index 2720e50e42..8faeb2026b 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -594,7 +594,7 @@ public: //internal: bool fitsPDF = false;//if it remains zero a new GMM mode will be added - int nmodes = modesUsed[x], nNewModes = nmodes;//current number of modes in GMM + int nmodes = modesUsed[x];//current number of modes in GMM float totalWeight = 0.f; float* mean_m = mean; @@ -700,8 +700,6 @@ public: gmm[mode].weight *= totalWeight; } - nmodes = nNewModes; - //make new mode if needed and exit if( !fitsPDF && alphaT > 0.f ) { From 617df091438f94d50dce8aa32d83392103bc3a5b Mon Sep 17 00:00:00 2001 From: MYLS Date: Tue, 19 Jul 2016 15:54:38 +0800 Subject: [PATCH 004/178] Modify Base64 functions and add test and documentation Major changes: - modify the Base64 functions to compatible with `cvWriteRawData` and so on. - add a Base64 flag for FileStorage and outputs raw data in Base64 automatically. - complete all testing and documentation. --- modules/core/include/opencv2/core/core_c.h | 58 +- .../core/include/opencv2/core/persistence.hpp | 9 +- modules/core/include/opencv2/core/types_c.h | 2 + modules/core/perf/perf_io_base64.cpp | 86 +++ modules/core/src/persistence.cpp | 711 ++++++++++++------ modules/core/test/test_io.cpp | 147 ---- modules/core/test/test_io_base64.cpp | 270 +++++++ modules/ml/test/test_save_load.cpp | 6 +- 8 files changed, 911 insertions(+), 378 deletions(-) create mode 100644 modules/core/perf/perf_io_base64.cpp create mode 100644 modules/core/test/test_io_base64.cpp diff --git a/modules/core/include/opencv2/core/core_c.h b/modules/core/include/opencv2/core/core_c.h index a0ed632642..94ba1fc034 100644 --- a/modules/core/include/opencv2/core/core_c.h +++ b/modules/core/include/opencv2/core/core_c.h @@ -1976,8 +1976,19 @@ CVAPI(void) cvSetIPLAllocators( Cv_iplCreateImageHeader create_header, The function opens file storage for reading or writing data. In the latter case, a new file is created or an existing file is rewritten. The type of the read or written file is determined by the -filename extension: .xml for XML and .yml or .yaml for YAML. The function returns a pointer to the -CvFileStorage structure. If the file cannot be opened then the function returns NULL. +filename extension: .xml for XML and .yml or .yaml for YAML. + +At the same time, it also supports adding parameters like "example.xml?base64". +@code + CvFileStorage* fs = cvOpenFileStorage( "example.yml?base64", 0, CV_STORAGE_WRITE ); +@endcode +it's exactly the same as +@code + CvFileStorage* fs = cvOpenFileStorage( "example.yml", 0, CV_STORAGE_WRITE_BASE64 ); +@endcode + +The function returns a pointer to the CvFileStorage structure. +If the file cannot be opened then the function returns NULL. @param filename Name of the file associated with the storage @param memstorage Memory storage used for temporary data and for : storing dynamic structures, such as CvSeq or CvGraph . If it is NULL, a temporary memory @@ -1985,6 +1996,7 @@ CvFileStorage structure. If the file cannot be opened then the function returns @param flags Can be one of the following: > - **CV_STORAGE_READ** the storage is open for reading > - **CV_STORAGE_WRITE** the storage is open for writing + (use **CV_STORAGE_WRITE | CV_STORAGE_WRITE_BASE64** to write rawdata in Base64) @param encoding */ CVAPI(CvFileStorage*) cvOpenFileStorage( const char* filename, CvMemStorage* memstorage, @@ -2162,7 +2174,7 @@ the file with multiple streams looks like this: @endcode The YAML file will look like this: @code{.yaml} - %YAML:1.0 + %YAML 1.0 # stream #1 data ... --- @@ -2187,6 +2199,46 @@ to a sequence rather than a map. CVAPI(void) cvWriteRawData( CvFileStorage* fs, const void* src, int len, const char* dt ); +/** @brief Writes multiple numbers in Base64. + +If either CV_STORAGE_WRITE_BASE64 or cv::FileStorage::WRITE_BASE64 is used, +this function will be the same as cvWriteRawData. If neither, the main +difference is that it outputs a sequence in Base64 encoding rather than +in plain text. + +This function can only be used to write a sequence with a type "binary". + +Consider the following two examples where their output is the same: +@code + std::vector rawdata(10, 0x00010203); + // without the flag CV_STORAGE_WRITE_BASE64. + CvFileStorage* fs = cvOpenFileStorage( "example.yml", 0, CV_STORAGE_WRITE ); + // both CV_NODE_SEQ and "binary" are necessary. + cvStartWriteStruct(fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW, "binary"); + cvWriteRawDataBase64(fs, rawdata.data(), rawdata.size(), "i"); + cvEndWriteStruct(fs); + cvReleaseFileStorage( &fs ); +@endcode +and +@code + std::vector rawdata(10, 0x00010203); + // with the flag CV_STORAGE_WRITE_BASE64. + CvFileStorage* fs = cvOpenFileStorage( "example.yml", 0, CV_STORAGE_WRITE_BASE64); + // parameter, typename "binary" could be omitted. + cvStartWriteStruct(fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW); + cvWriteRawData(fs, rawdata.data(), rawdata.size(), "i"); + cvEndWriteStruct(fs); + cvReleaseFileStorage( &fs ); +@endcode + +@param fs File storage +@param src Pointer to the written array +@param len Number of the array elements to write +@param dt Specification of each array element, see @ref format_spec "format specification" +*/ +CVAPI(void) cvWriteRawDataBase64( CvFileStorage* fs, const void* _data, + int len, const char* dt ); + /** @brief Returns a unique pointer for a given name. The function returns a unique pointer for each particular file node name. This pointer can be then diff --git a/modules/core/include/opencv2/core/persistence.hpp b/modules/core/include/opencv2/core/persistence.hpp index 65a1ff4c4c..75f0c32bd2 100644 --- a/modules/core/include/opencv2/core/persistence.hpp +++ b/modules/core/include/opencv2/core/persistence.hpp @@ -311,7 +311,10 @@ public: FORMAT_MASK = (7<<3), //!< mask for format flags FORMAT_AUTO = 0, //!< flag, auto format FORMAT_XML = (1<<3), //!< flag, XML format - FORMAT_YAML = (2<<3) //!< flag, YAML format + FORMAT_YAML = (2<<3), //!< flag, YAML format + + BASE64 = 64, //!< flag, write rawdata in Base64 by default. (consider using WRITE_BASE64) + WRITE_BASE64 = BASE64 | WRITE, //!< flag, enable both WRITE and BASE64 }; enum { @@ -354,7 +357,9 @@ public: Extension of the file (.xml or .yml/.yaml) determines its format (XML or YAML respectively). Also you can append .gz to work with compressed files, for example myHugeMatrix.xml.gz. If both FileStorage::WRITE and FileStorage::MEMORY flags are specified, source is used just to specify - the output file format (e.g. mydata.xml, .yml etc.). + the output file format (e.g. mydata.xml, .yml etc.). A file name can also contain parameters. + You can use this format, "*?base64" (e.g. "file.xml?base64"), as an alternative to + FileStorage::BASE64 flag. Note: it is case sensitive. @param flags Mode of operation. One of FileStorage::Mode @param encoding Encoding of the file. Note that UTF-16 XML encoding is not supported currently and you should use 8-bit encoding instead of it. diff --git a/modules/core/include/opencv2/core/types_c.h b/modules/core/include/opencv2/core/types_c.h index cb39587a9a..e693aa4724 100644 --- a/modules/core/include/opencv2/core/types_c.h +++ b/modules/core/include/opencv2/core/types_c.h @@ -1669,6 +1669,8 @@ typedef struct CvFileStorage CvFileStorage; #define CV_STORAGE_FORMAT_AUTO 0 #define CV_STORAGE_FORMAT_XML 8 #define CV_STORAGE_FORMAT_YAML 16 +#define CV_STORAGE_BASE64 64 +#define CV_STORAGE_WRITE_BASE64 (CV_STORAGE_BASE64 | CV_STORAGE_WRITE) /** @brief List of attributes. : diff --git a/modules/core/perf/perf_io_base64.cpp b/modules/core/perf/perf_io_base64.cpp new file mode 100644 index 0000000000..693c1cc132 --- /dev/null +++ b/modules/core/perf/perf_io_base64.cpp @@ -0,0 +1,86 @@ +#include "perf_precomp.hpp" + +using namespace std; +using namespace cv; +using namespace perf; +using std::tr1::make_tuple; +using std::tr1::get; + +typedef std::tr1::tuple Size_MatType_Str_t; +typedef TestBaseWithParam Size_Mat_StrType; + +#define MAT_SIZES ::perf::sz1080p/*, ::perf::sz4320p*/ +#define MAT_TYPES CV_8UC1, CV_32FC1 +#define FILE_EXTENSION String(".xml"), String(".yml") + +PERF_TEST_P(Size_Mat_StrType, fs_text, + testing::Combine(testing::Values(MAT_SIZES), + testing::Values(MAT_TYPES), + testing::Values(FILE_EXTENSION)) + ) +{ + Size size = get<0>(GetParam()); + int type = get<1>(GetParam()); + String ext = get<2>(GetParam()); + + Mat src(size.height, size.width, type); + Mat dst = src.clone(); + + declare.in(src, WARMUP_RNG).out(dst); + + cv::String file_name = cv::tempfile(ext.c_str()); + cv::String key = "test_mat"; + + TEST_CYCLE_MULTIRUN(4) + { + { + FileStorage fs(file_name, cv::FileStorage::WRITE); + fs << key << src; + fs.release(); + } + { + FileStorage fs(file_name, cv::FileStorage::READ); + fs[key] >> dst; + fs.release(); + } + } + + remove(file_name.c_str()); + + SANITY_CHECK(dst, 1); +} + +PERF_TEST_P(Size_Mat_StrType, fs_base64, + testing::Combine(testing::Values(MAT_SIZES), + testing::Values(MAT_TYPES), + testing::Values(FILE_EXTENSION)) + ) +{ + Size size = get<0>(GetParam()); + int type = get<1>(GetParam()); + String ext = get<2>(GetParam()); + + Mat src(size.height, size.width, type); + Mat dst = src.clone(); + + cv::String file_name = cv::tempfile(ext.c_str()); + cv::String key = "test_mat"; + + declare.in(src, WARMUP_RNG).out(dst); + TEST_CYCLE_MULTIRUN(4) + { + { + FileStorage fs(file_name, cv::FileStorage::WRITE_BASE64); + fs << key << src; + fs.release(); + } + { + FileStorage fs(file_name, cv::FileStorage::READ); + fs[key] >> dst; + fs.release(); + } + } + + remove(file_name.c_str()); + SANITY_CHECK(dst, 1); +} diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 4d99a4a275..6eb3b0c75a 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -243,6 +243,17 @@ typedef struct CvFileStorage std::deque* outbuf; base64::Base64Writer * base64_writer; + bool is_default_using_base64; + enum Base64State { + Uncertain, + NotUse, + InUse, + } state_of_writing_base64; /**< used in WriteRawData only */ + + bool is_write_struct_delayed; + char* delayed_struct_key; + int delayed_struct_flags; + char* delayed_type_name; bool is_opened; } @@ -270,21 +281,23 @@ namespace base64 bool base64_valid (uint8_t const * src, size_t off, size_t cnt); bool base64_valid ( char const * src, size_t off = 0U, size_t cnt = 0U); - size_t base64_encode_buffer_size(size_t cnt); + size_t base64_encode_buffer_size(size_t cnt, bool is_end_with_zero = true); - size_t base64_decode_buffer_size(size_t cnt); + size_t base64_decode_buffer_size(size_t cnt, bool is_end_with_zero = true); + size_t base64_decode_buffer_size(size_t cnt, char const * src, bool is_end_with_zero = true); + size_t base64_decode_buffer_size(size_t cnt, uchar const * src, bool is_end_with_zero = true); /* binary */ - template inline size_t to_binary(_uint_t val, uchar * cur); - template<> inline size_t to_binary(double val, uchar * cur); - template<> inline size_t to_binary(float val, uchar * cur); + template inline size_t to_binary(_uint_t val, uchar * cur); + template<> inline size_t to_binary(double val, uchar * cur); + template<> inline size_t to_binary(float val, uchar * cur); template inline size_t to_binary(uchar const * val, uchar * cur); - template inline size_t binary_to(uchar const * cur, _uint_t & val); - template<> inline size_t binary_to(uchar const * cur, double & val); - template<> inline size_t binary_to(uchar const * cur, float & val); - template inline size_t binary_to(uchar const * cur, uchar * val); + template inline size_t binary_to(uchar const * cur, _uint_t & val); + template<> inline size_t binary_to(uchar const * cur, double & val); + template<> inline size_t binary_to(uchar const * cur, float & val); + template inline size_t binary_to(uchar const * cur, uchar * val); class MatToBinaryConvertor; class RawDataToBinaryConvertor; @@ -313,22 +326,37 @@ namespace base64 class Base64ContextEmitter; + class Base64Writer + { + public: + Base64Writer(::CvFileStorage * fs); + ~Base64Writer(); + void write(const void* _data, size_t len, const char* dt); + template void write(_to_binary_convertor_t & convertor, const char* dt); + + private: + void check_dt(const char* dt); + + private: + + ::CvFileStorage * file_storage; + Base64ContextEmitter * emitter; + std::string data_type_string; + }; + /* other */ - std::string make_base64_header(int byte_size, const char * dt); + std::string make_base64_header(const char * dt); - bool read_base64_header(std::string const & header, int & byte_size, std::string & dt); + bool read_base64_header(std::vector const & header, std::string & dt); void make_seq(void * binary_data, int elem_cnt, const char * dt, CvSeq & seq); /* sample */ - void cvStartWriteRawData_Base64(::CvFileStorage * fs, const char* name, int len, const char* dt); - void cvWriteRawData_Base64(::CvFileStorage * fs, const void* _data, int len); - void cvEndWriteRawData_Base64(::CvFileStorage * fs); + void cvWriteRawDataBase64(::CvFileStorage* fs, const void* _data, int len, const char* dt); - void cvWriteRawData_Base64(::cv::FileStorage & fs, const void* _data, int len, const char* dt); - void cvWriteMat_Base64(CvFileStorage * fs, const char * name, ::cv::Mat const & mat); + void cvWriteMat_Base64(::CvFileStorage * fs, const char * name, ::cv::Mat const & mat); } @@ -1031,6 +1059,184 @@ static double icv_strtod( CvFileStorage* fs, char* ptr, char** endptr ) return fval; } +static std::vector analyze_file_name( std::string const & file_name ) +{ + static const char parameter_begin = '?'; + static const char parameter_separator = '&'; + std::vector result; + + size_t beg = file_name.find_last_of(parameter_begin); + size_t end = file_name.size(); + result.push_back(file_name.substr(0U, beg)); + + if ( beg != std::string::npos ) + { + beg ++; + for ( size_t param_beg = beg, param_end = beg; + param_end < end; + param_beg = param_end + 1U ) + { + param_end = file_name.find_first_of( parameter_separator, param_beg ); + if ( (param_end == std::string::npos || param_end != param_beg) && param_beg + 1U < end ) + { + result.push_back( file_name.substr( param_beg, param_end - param_beg ) ); + } + } + } + + return result; +} + +static bool is_param_exist( std::vector & const params, std::string & const param ) +{ + if ( params.size() < 2U ) + return false; + + return std::find(params.begin(), params.end(), param) != params.end(); +} + +static void switch_to_Base64_state( CvFileStorage* fs, CvFileStorage::Base64State state ) +{ + const char * err_unkonwn_state = "Unexpected error, unable to determine the Base64 state."; + const char * err_unable_to_switch = "Unexpected error, unable to switch to this state."; + + /* like a finite state machine */ + switch (fs->state_of_writing_base64) + { + case CvFileStorage::Base64State::Uncertain: + switch (state) + { + case CvFileStorage::Base64State::InUse: + CV_DbgAssert( fs->base64_writer == 0 ); + fs->base64_writer = new base64::Base64Writer( fs ); + break; + case CvFileStorage::Base64State::Uncertain: + break; + case CvFileStorage::Base64State::NotUse: + break; + default: + CV_Error( CV_StsError, err_unkonwn_state ); + break; + } + break; + case CvFileStorage::Base64State::InUse: + switch (state) + { + case CvFileStorage::Base64State::InUse: + case CvFileStorage::Base64State::NotUse: + CV_Error( CV_StsError, err_unable_to_switch ); + break; + case CvFileStorage::Base64State::Uncertain: + delete fs->base64_writer; + fs->base64_writer = 0; + break; + default: + CV_Error( CV_StsError, err_unkonwn_state ); + break; + } + break; + case CvFileStorage::Base64State::NotUse: + switch (state) + { + case CvFileStorage::Base64State::InUse: + case CvFileStorage::Base64State::NotUse: + CV_Error( CV_StsError, err_unable_to_switch ); + break; + case CvFileStorage::Base64State::Uncertain: + break; + default: + CV_Error( CV_StsError, err_unkonwn_state ); + break; + } + break; + default: + CV_Error( CV_StsError, err_unkonwn_state ); + break; + } + + fs->state_of_writing_base64 = state; +} + + +static void check_if_write_struct_is_delayed( CvFileStorage* fs, bool change_type_to_base64 = false ) +{ + if ( fs->is_write_struct_delayed ) + { + /* save data to prevent recursive call errors */ + char * struct_key = 0; + char * type_name = 0; + int struct_flags = fs->delayed_struct_flags; + + if ( fs->delayed_struct_key != 0 ) + { + struct_key = new char[strlen(fs->delayed_struct_key) + 1U]; + strcpy(struct_key, fs->delayed_struct_key); + } + if ( fs->delayed_type_name != 0 ) + { + type_name = new char[strlen(type_name) + 1U]; + strcpy(type_name, fs->delayed_type_name); + } + + /* reset */ + delete fs->delayed_struct_key; + delete fs->delayed_type_name; + fs->delayed_struct_key = 0; + fs->delayed_struct_flags = 0; + fs->delayed_type_name = 0; + + fs->is_write_struct_delayed = false; + + /* call */ + if ( change_type_to_base64 ) + { + fs->start_write_struct( fs, struct_key, struct_flags, "binary"); + if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) + switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + switch_to_Base64_state( fs, CvFileStorage::Base64State::InUse ); + } + else + { + fs->start_write_struct( fs, struct_key, struct_flags, type_name); + if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) + switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + } + + delete struct_key; + delete type_name; + } +} + + +static void make_write_struct_delayed( + CvFileStorage* fs, + const char* key, + int struct_flags, + const char* type_name ) +{ + CV_Assert( fs->is_write_struct_delayed == false ); + CV_DbgAssert( fs->delayed_struct_key == 0 ); + CV_DbgAssert( fs->delayed_struct_flags == 0 ); + CV_DbgAssert( fs->delayed_type_name == 0 ); + + fs->delayed_struct_flags = struct_flags; + + if ( key != 0 ) + { + fs->delayed_struct_key = new char[strlen(key) + 1U]; + strcpy(fs->delayed_struct_key, key); + } + + if ( type_name != 0 ) + { + fs->delayed_type_name = new char[strlen(type_name) + 1U]; + strcpy(fs->delayed_type_name, type_name); + } + + fs->is_write_struct_delayed = true; +} + /****************************************************************************************\ * YAML Parser * @@ -1119,40 +1325,41 @@ static char* icvYMLParseBase64(CvFileStorage* fs, char* ptr, int indent, CvFileN /* calc (decoded) total_byte_size from header */ std::string dt; - int total_byte_size = -1; { if (end - beg < static_cast(base64::ENCODED_HEADER_SIZE)) CV_PARSE_ERROR("Unrecognized Base64 header"); std::vector header(base64::HEADER_SIZE + 1, ' '); base64::base64_decode(beg, header.data(), 0U, base64::ENCODED_HEADER_SIZE); - std::istringstream iss(header.data()); - - if (!(iss >> total_byte_size) || total_byte_size < 0) - CV_PARSE_ERROR("Cannot parse size in Base64 header"); - if (!(iss >> dt) || dt.empty()) + if ( !base64::read_base64_header(header, dt) || dt.empty() ) CV_PARSE_ERROR("Cannot parse dt in Base64 header"); beg += base64::ENCODED_HEADER_SIZE; } - /* buffer for decoded data(exclude header) */ - std::vector buffer(total_byte_size + 4); + /* get all Base64 data */ + std::string base64_buffer; + base64_buffer.reserve( 16U * 1024U * 1024U ); + while( beg < end ) { - base64::Base64ContextParser parser(buffer.data(), total_byte_size + 4); - - /* decoding */ - while(beg < end) - { - /* save this part [beg, end) */ - parser.read((const uchar *)beg, (const uchar *)end); - - beg = end; - - /* find next part */ - icvYMLGetMultilineStringContent(fs, beg, indent, beg, end); - } + base64_buffer.append( beg, end ); + beg = end; + icvYMLGetMultilineStringContent( fs, beg, indent, beg, end ); } + if ( !base64::base64_valid(base64_buffer.data(), 0U, base64_buffer.size()) ) + CV_PARSE_ERROR( "Invalid Base64 data." ); + + /* buffer for decoded data(exclude header) */ + std::vector binary_buffer( base64::base64_decode_buffer_size(base64_buffer.size()) ); + int total_byte_size = base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false ); + { + base64::Base64ContextParser parser(binary_buffer.data(), binary_buffer.size() ); + const uchar * buffer_beg = reinterpret_cast( base64_buffer.data() ); + const uchar * buffer_end = buffer_beg + base64_buffer.size(); + parser.read( buffer_beg, buffer_end ); + parser.flush(); + } + /* save as CvSeq */ int elem_size = ::icvCalcStructSize(dt.c_str(), 0); if (total_byte_size % elem_size != 0) @@ -1160,9 +1367,10 @@ static char* icvYMLParseBase64(CvFileStorage* fs, char* ptr, int indent, CvFileN int elem_cnt = total_byte_size / elem_size; node->tag = CV_NODE_NONE; - int struct_flags = CV_NODE_FLOW + CV_NODE_SEQ; /* after icvFSCreateCollection, node->tag == struct_flags */ + int struct_flags = CV_NODE_FLOW | CV_NODE_SEQ; + /* after icvFSCreateCollection, node->tag == struct_flags */ icvFSCreateCollection(fs, struct_flags, node); - base64::make_seq(buffer.data(), elem_cnt, dt.c_str(), *node->data.seq); + base64::make_seq(binary_buffer.data(), elem_cnt, dt.c_str(), *node->data.seq); if (fs->dummy_eof) { /* end of file */ @@ -1621,6 +1829,16 @@ icvYMLParse( CvFileStorage* fs ) static void icvYMLWrite( CvFileStorage* fs, const char* key, const char* data ) { + check_if_write_struct_is_delayed( fs ); + if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) + { + switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + } + else if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + { + CV_Error( CV_StsError, "At present, output Base64 data only." ); + } + int i, keylen = 0; int datalen = 0; int struct_flags; @@ -2034,17 +2252,17 @@ static void icvXMLGetMultilineStringContent(CvFileStorage* fs, ptr = icvXMLSkipSpaces(fs, ptr, CV_XML_INSIDE_TAG); beg = ptr; end = ptr; - if (fs->dummy_eof) + if ( fs->dummy_eof ) return ; /* end of file */ - if (*beg == '<') + if ( *beg == '<' ) return; /* end of string */ /* find end */ - while(cv_isprint(*ptr)) /* no check for base64 string */ + while( cv_isprint(*ptr) ) /* no check for base64 string */ ++ ptr; - if (*ptr == '\0') - CV_PARSE_ERROR("Unexpected end of line"); + if ( *ptr == '\0' ) + CV_PARSE_ERROR( "Unexpected end of line" ); end = ptr; } @@ -2061,48 +2279,52 @@ static char* icvXMLParseBase64(CvFileStorage* fs, char* ptr, CvFileNode * node) /* calc (decoded) total_byte_size from header */ std::string dt; - int total_byte_size = -1; { if (end - beg < static_cast(base64::ENCODED_HEADER_SIZE)) CV_PARSE_ERROR("Unrecognized Base64 header"); std::vector header(base64::HEADER_SIZE + 1, ' '); base64::base64_decode(beg, header.data(), 0U, base64::ENCODED_HEADER_SIZE); - std::istringstream iss(header.data()); - if (!(iss >> total_byte_size) || total_byte_size < 0) - CV_PARSE_ERROR("Cannot parse size in Base64 header"); - if (!(iss >> dt) || dt.empty()) + if ( !base64::read_base64_header(header, dt) || dt.empty() ) CV_PARSE_ERROR("Cannot parse dt in Base64 header"); beg += base64::ENCODED_HEADER_SIZE; } - /* alloc buffer for all decoded data(include header) */ - std::vector buffer(total_byte_size + 4); + /* get all Base64 data */ + std::string base64_buffer; + base64_buffer.reserve( 16U * 1024U * 1024U ); + while( beg < end ) { - base64::Base64ContextParser parser(buffer.data(), total_byte_size + 4); + base64_buffer.append( beg, end ); + beg = end; + icvXMLGetMultilineStringContent( fs, beg, beg, end ); + } + if ( !base64::base64_valid(base64_buffer.data(), 0U, base64_buffer.size()) ) + CV_PARSE_ERROR( "Invalid Base64 data." ); - /* decoding */ - while(beg < end) - { - /* save this part [beg, end) */ - parser.read((const uchar *)beg, (const uchar *)end); - beg = end; - /* find next part */ - icvXMLGetMultilineStringContent(fs, beg, beg, end); - } + /* alloc buffer for all decoded data(include header) */ + std::vector binary_buffer( base64::base64_decode_buffer_size(base64_buffer.size()) ); + int total_byte_size = base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false ); + { + base64::Base64ContextParser parser(binary_buffer.data(), binary_buffer.size() ); + const uchar * buffer_beg = reinterpret_cast( base64_buffer.data() ); + const uchar * buffer_end = buffer_beg + base64_buffer.size(); + parser.read( buffer_beg, buffer_end ); + parser.flush(); } /* save as CvSeq */ int elem_size = ::icvCalcStructSize(dt.c_str(), 0); if (total_byte_size % elem_size != 0) - CV_PARSE_ERROR("Byte size not match elememt size"); + CV_PARSE_ERROR("data size not matches elememt size"); int elem_cnt = total_byte_size / elem_size; node->tag = CV_NODE_NONE; - int struct_flags = CV_NODE_SEQ; /* after icvFSCreateCollection, node->tag == struct_flags */ + int struct_flags = CV_NODE_SEQ; + /* after icvFSCreateCollection, node->tag == struct_flags */ icvFSCreateCollection(fs, struct_flags, node); - base64::make_seq(buffer.data(), elem_cnt, dt.c_str(), *node->data.seq); + base64::make_seq(binary_buffer.data(), elem_cnt, dt.c_str(), *node->data.seq); if (fs->dummy_eof) { /* end of file */ @@ -2757,6 +2979,16 @@ icvXMLStartNextStream( CvFileStorage* fs ) static void icvXMLWriteScalar( CvFileStorage* fs, const char* key, const char* data, int len ) { + check_if_write_struct_is_delayed( fs ); + if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) + { + switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + } + else if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + { + CV_Error( CV_StsError, "Currently only Base64 data is allowed." ); + } + if( CV_NODE_IS_MAP(fs->struct_flags) || (!CV_NODE_IS_COLLECTION(fs->struct_flags) && key) ) { @@ -2964,15 +3196,24 @@ icvXMLWriteComment( CvFileStorage* fs, const char* comment, int eol_comment ) \****************************************************************************************/ CV_IMPL CvFileStorage* -cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, const char* encoding ) +cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const char* encoding ) { CvFileStorage* fs = 0; int default_block_size = 1 << 18; bool append = (flags & 3) == CV_STORAGE_APPEND; bool mem = (flags & CV_STORAGE_MEMORY) != 0; bool write_mode = (flags & 3) != 0; + bool write_base64 = write_mode && (flags & CV_STORAGE_BASE64) != 0; bool isGZ = false; size_t fnamelen = 0; + const char * filename = 0; + + std::vector params = analyze_file_name( query ); + if ( !params.empty() ) + filename = params.begin()->c_str(); + + if (write_base64 == false && is_param_exist( params, std::string("base64") ) ) + write_base64 = true; if( !filename || filename[0] == '\0' ) { @@ -3073,6 +3314,16 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co fs->struct_flags = CV_NODE_EMPTY; fs->buffer_start = fs->buffer = (char*)cvAlloc( buf_size + 1024 ); fs->buffer_end = fs->buffer_start + buf_size; + + fs->base64_writer = 0; + fs->is_default_using_base64 = write_base64; + fs->state_of_writing_base64 = CvFileStorage::Base64State::Uncertain; + + fs->is_write_struct_delayed = false; + fs->delayed_struct_key = 0; + fs->delayed_struct_flags = 0; + fs->delayed_type_name = 0; + if( fs->fmt == CV_STORAGE_FORMAT_XML ) { size_t file_size = fs->file ? (size_t)ftell( fs->file ) : (size_t)0; @@ -3247,7 +3498,48 @@ cvStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, const char* type_name, CvAttrList /*attributes*/ ) { CV_CHECK_OUTPUT_FILE_STORAGE(fs); - fs->start_write_struct( fs, key, struct_flags, type_name ); + check_if_write_struct_is_delayed( fs ); + if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::NotUse ) + switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + + if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain + && + CV_NODE_IS_SEQ(struct_flags) + && + fs->is_default_using_base64 + && + type_name == 0 + ) + { + /* Uncertain if output Base64 data */ + make_write_struct_delayed( fs, key, struct_flags, type_name ); + } + else if ( type_name && memcmp(type_name, "binary", 6) == 0 ) + { + /* Must output Base64 data */ + if ( !CV_NODE_IS_SEQ(struct_flags) ) + CV_Error( CV_StsBadArg, "must set 'struct_flags |= CV_NODE_SEQ' if using Base64."); + else if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) + CV_Error( CV_StsError, "function \'cvStartWriteStruct\' calls cannot be nested if using Base64."); + + fs->start_write_struct( fs, key, struct_flags, type_name ); + + if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) + switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + switch_to_Base64_state( fs, CvFileStorage::Base64State::InUse ); + } + else + { + /* Won't output Base64 data */ + if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + CV_Error( CV_StsError, "At the end of the output Base64, `cvEndWriteStruct` is needed."); + + fs->start_write_struct( fs, key, struct_flags, type_name ); + + if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) + switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + } } @@ -3255,6 +3547,11 @@ CV_IMPL void cvEndWriteStruct( CvFileStorage* fs ) { CV_CHECK_OUTPUT_FILE_STORAGE(fs); + check_if_write_struct_is_delayed( fs ); + + if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) + switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + fs->end_write_struct( fs ); } @@ -3432,6 +3729,17 @@ icvDecodeSimpleFormat( const char* dt ) CV_IMPL void cvWriteRawData( CvFileStorage* fs, const void* _data, int len, const char* dt ) { + if (fs->is_default_using_base64 || + fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + { + base64::cvWriteRawDataBase64( fs, _data, len, dt ); + return; + } + else if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) + { + switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + } + const char* data0 = (const char*)_data; int offset = 0; int fmt_pairs[CV_FS_MAX_FMT_PAIRS*2], k, fmt_pair_count; @@ -3760,15 +4068,15 @@ icvWriteFileNode( CvFileStorage* fs, const char* name, const CvFileNode* node ) break; case CV_NODE_SEQ: case CV_NODE_MAP: - fs->start_write_struct( fs, name, CV_NODE_TYPE(node->tag) + + cvStartWriteStruct( fs, name, CV_NODE_TYPE(node->tag) + (CV_NODE_SEQ_IS_SIMPLE(node->data.seq) ? CV_NODE_FLOW : 0), node->info ? node->info->type_name : 0 ); icvWriteCollection( fs, node ); - fs->end_write_struct( fs ); + cvEndWriteStruct( fs ); break; case CV_NODE_NONE: - fs->start_write_struct( fs, name, CV_NODE_SEQ, 0 ); - fs->end_write_struct( fs ); + cvStartWriteStruct( fs, name, CV_NODE_SEQ, 0 ); + cvEndWriteStruct( fs ); break; default: CV_Error( CV_StsBadFlag, "Unknown type of file node" ); @@ -6226,14 +6534,29 @@ bool base64::base64_valid(char const * src, size_t off, size_t cnt) return base64_valid(reinterpret_cast(src), off, cnt); } -size_t base64::base64_encode_buffer_size(size_t cnt) +size_t base64::base64_encode_buffer_size(size_t cnt, bool is_end_with_zero) { - return size_t((cnt + 2U) / 3U * 4U + 1U); + size_t additional = static_cast(is_end_with_zero == true); + return (cnt + 2U) / 3U * 4U + additional; } -size_t base64::base64_decode_buffer_size(size_t cnt) +size_t base64::base64_decode_buffer_size(size_t cnt, bool is_end_with_zero) { - return size_t(cnt / 4U * 3U + 1U); + size_t additional = static_cast(is_end_with_zero == true); + return cnt / 4U * 3U + additional; +} + +size_t base64::base64_decode_buffer_size(size_t cnt, char const * src, bool is_end_with_zero) +{ + return base64_decode_buffer_size(cnt, reinterpret_cast(src), is_end_with_zero); +} + +size_t base64::base64_decode_buffer_size(size_t cnt, uchar const * src, bool is_end_with_zero) +{ + size_t padding_cnt = 0U; + for (uchar const * ptr = src + cnt - 1U; *ptr == base64_padding; ptr--) + padding_cnt ++; + return base64_decode_buffer_size(cnt, is_end_with_zero) - padding_cnt; } /**************************************************************************** @@ -6308,13 +6631,10 @@ binary_to(uchar const * cur, uchar * val) * others ***************************************************************************/ -std::string base64::make_base64_header(int byte_size, const char * dt) +std::string base64::make_base64_header(const char * dt) { - int size = byte_size; - std::ostringstream oss; - oss << size << ' ' - << dt << ' '; + oss << dt << ' '; std::string buffer(oss.str()); CV_Assert(buffer.size() < HEADER_SIZE); @@ -6325,10 +6645,10 @@ std::string base64::make_base64_header(int byte_size, const char * dt) return buffer; } -bool base64::read_base64_header(std::string const & header, int & byte_size, std::string & dt) +bool base64::read_base64_header(std::vector const & header, std::string & dt) { - std::istringstream iss(header); - return static_cast(iss >> byte_size >> dt); + std::istringstream iss(header.data()); + return static_cast(iss >> dt); } /**************************************************************************** @@ -6351,10 +6671,9 @@ base64::Base64ContextParser::Base64ContextParser(uchar * buffer, size_t size) base64::Base64ContextParser::~Base64ContextParser() { - if (src_cur != src_beg) { - /* encode the rest binary data to base64 buffer */ + /* encode the rest binary data to base64 buffer */ + if (src_cur != src_beg) flush(); - } } base64::Base64ContextParser & base64::Base64ContextParser:: @@ -6383,9 +6702,12 @@ read(const uchar * beg, const uchar * end) bool base64::Base64ContextParser::flush() { - if (!base64_valid(src_beg, 0U, src_cur - src_beg)) + if ( !base64_valid(src_beg, 0U, src_cur - src_beg) ) return false; + if ( src_cur == src_beg ) + return true; + uchar * buffer = binary_buffer.data(); size_t len = base64_decode(src_beg, buffer, 0U, src_cur - src_beg); src_cur = src_beg; @@ -6514,7 +6836,7 @@ public: private: /* because of Base64, we must keep its length a multiple of 3 */ - static const size_t BUFFER_LEN = 51U; + static const size_t BUFFER_LEN = 48U; // static_assert(BUFFER_LEN % 3 == 0, "BUFFER_LEN is invalid"); private: @@ -6584,17 +6906,17 @@ public: { CV_DbgAssert(*this); - /* copy to dst */ + /* [1]copy to dst */ dst += to_binary_func(row_begin + x, dst); - /* move to next */ + /* [2]move to next */ x += step; if (x >= x_max) { - /* when x arrive end, reset it and increase y */ + /* when x arrive end, reset x and increase y */ x = 0U; ++ y; if (y >= y_max) { - /* when y arrive end, reset it and increase iter */ + /* when y arrive end, reset y and increase iter */ y = 0U; ++ mat_iter; if (mat_iter == mats.end()) { @@ -6935,68 +7257,55 @@ private: * Wapper ***************************************************************************/ -class base64::Base64Writer + +base64::Base64Writer::Base64Writer(::CvFileStorage * fs) + : file_storage(fs) + , emitter(new Base64ContextEmitter(fs)) + , data_type_string() { -public: + CV_CHECK_OUTPUT_FILE_STORAGE(fs); + icvFSFlush(fs); +} - Base64Writer(::CvFileStorage * fs, const char * name, int len, const char* dt) - : file_storage(fs) - , emitter(fs) - , remaining_data_length(len) - , data_type_string(dt) - { - CV_CHECK_OUTPUT_FILE_STORAGE(fs); +void base64::Base64Writer::write(const void* _data, size_t len, const char* dt) +{ + check_dt(dt); - cvStartWriteStruct(fs, name, CV_NODE_SEQ, "binary"); - icvFSFlush(fs); + RawDataToBinaryConvertor convertor( + _data, static_cast(len), data_type_string.c_str() + ); + emitter->write(convertor); +} + +template inline +void base64::Base64Writer::write(_to_binary_convertor_t & convertor, const char* dt) +{ + check_dt(dt); + emitter->write(convertor); +} + +base64::Base64Writer::~Base64Writer() +{ + delete emitter; +} + +void base64::Base64Writer::check_dt(const char* dt) +{ + if ( dt == 0 ) + CV_Error( CV_StsBadArg, "Invalid \'dt\'." ); + else if (data_type_string.empty()) { + data_type_string = dt; /* output header */ - - /* total byte size(before encode) */ - int size = len * ::icvCalcStructSize(dt, 0); - - std::string buffer = make_base64_header(size, dt); + std::string buffer = make_base64_header(dt); const uchar * beg = reinterpret_cast(buffer.data()); const uchar * end = beg + buffer.size(); - emitter.write(beg, end); - } + emitter->write(beg, end); + } else if ( data_type_string != dt ) + CV_Error( CV_StsBadArg, "\'dt\' does not match." ); +} - void write(const void* _data, int len) - { - CV_Assert(len >= 0); - CV_Assert(remaining_data_length >= static_cast(len)); - remaining_data_length -= static_cast(len); - - RawDataToBinaryConvertor convertor(_data, len, data_type_string); - emitter.write(convertor); - } - - template inline - void write(_to_binary_convertor_t & convertor, int data_length_of_convertor) - { - CV_Assert(data_length_of_convertor >= 0); - CV_Assert(remaining_data_length >= static_cast(data_length_of_convertor)); - remaining_data_length -= static_cast(data_length_of_convertor); - - emitter.write(convertor); - } - - ~Base64Writer() - { - CV_Assert(remaining_data_length == 0U); - emitter.flush(); - cvEndWriteStruct(file_storage); - icvFSFlush(file_storage); - } - -private: - - ::CvFileStorage * file_storage; - Base64ContextEmitter emitter; - size_t remaining_data_length; - const char* data_type_string; -}; void base64::make_seq(void * binary, int elem_cnt, const char * dt, ::CvSeq & seq) { @@ -7009,51 +7318,23 @@ void base64::make_seq(void * binary, int elem_cnt, const char * dt, ::CvSeq & se } } -void base64::cvStartWriteRawData_Base64(::CvFileStorage * fs, const char* name, int len, const char* dt) +void base64::cvWriteRawDataBase64(::CvFileStorage* fs, const void* _data, int len, const char* dt) { CV_Assert(fs); CV_CHECK_OUTPUT_FILE_STORAGE(fs); - CV_Assert(fs->base64_writer == 0); - fs->base64_writer = new Base64Writer(fs, name, len, dt); -} -void base64::cvWriteRawData_Base64(::CvFileStorage * fs, const void* _data, int len) -{ - CV_Assert(fs); - CV_CHECK_OUTPUT_FILE_STORAGE(fs); - CV_Assert(fs->base64_writer != 0); - fs->base64_writer->write(_data, len); -} + check_if_write_struct_is_delayed( fs, true ); -void base64::cvEndWriteRawData_Base64(::CvFileStorage * fs) -{ - CV_Assert(fs); - CV_CHECK_OUTPUT_FILE_STORAGE(fs); - CV_Assert(fs->base64_writer != 0); - delete fs->base64_writer; - fs->base64_writer = 0; -} - -void base64::cvWriteRawData_Base64(::cv::FileStorage & fs, const void* _data, int len, const char* dt) -{ - cvStartWriteStruct(*fs, fs.elname.c_str(), CV_NODE_SEQ, "binary"); + if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) { - Base64ContextEmitter emitter(*fs); - { /* header */ - /* total byte size(before encode) */ - int size = len * ::icvCalcStructSize(dt, 0); - std::string buffer = make_base64_header(size, dt); - const uchar * beg = reinterpret_cast(buffer.data()); - const uchar * end = beg + buffer.size(); - - emitter.write(beg, end); - } - { /* body */ - RawDataToBinaryConvertor convert(_data, len, dt); - emitter.write(convert); - } + switch_to_Base64_state( fs, CvFileStorage::Base64State::InUse ); } - cvEndWriteStruct(*fs); + else if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::InUse ) + { + CV_Error( CV_StsError, "Base64 should not be used at present." ); + } + + fs->base64_writer->write(_data, len, dt); } void base64::cvWriteMat_Base64(::CvFileStorage * fs, const char * name, ::cv::Mat const & mat) @@ -7064,31 +7345,30 @@ void base64::cvWriteMat_Base64(::CvFileStorage * fs, const char * name, ::cv::Ma { /* [1]output other attr */ if (mat.dims <= 2) { - cvStartWriteStruct(fs, name, CV_NODE_MAP, CV_TYPE_NAME_MAT); + ::cvStartWriteStruct(fs, name, CV_NODE_MAP, CV_TYPE_NAME_MAT); - cvWriteInt(fs, "rows", mat.rows ); - cvWriteInt(fs, "cols", mat.cols ); + ::cvWriteInt(fs, "rows", mat.rows ); + ::cvWriteInt(fs, "cols", mat.cols ); } else { - cvStartWriteStruct(fs, name, CV_NODE_MAP, CV_TYPE_NAME_MATND); + ::cvStartWriteStruct(fs, name, CV_NODE_MAP, CV_TYPE_NAME_MATND); - cvStartWriteStruct(fs, "sizes", CV_NODE_SEQ | CV_NODE_FLOW); - cvWriteRawData(fs, mat.size.p, mat.dims, "i"); - cvEndWriteStruct(fs); + ::cvStartWriteStruct(fs, "sizes", CV_NODE_SEQ | CV_NODE_FLOW); + ::cvWriteRawData(fs, mat.size.p, mat.dims, "i"); + ::cvEndWriteStruct(fs); } - cvWriteString(fs, "dt", ::icvEncodeFormat(CV_MAT_TYPE(mat.type()), dt ), 0 ); + ::cvWriteString(fs, "dt", ::icvEncodeFormat(CV_MAT_TYPE(mat.type()), dt ), 0 ); } { /* [2]deal with matrix's data */ - int len = static_cast(mat.total()); MatToBinaryConvertor convertor(mat); - cvStartWriteRawData_Base64(fs, "data", len, dt); - fs->base64_writer->write(convertor, len); - cvEndWriteRawData_Base64(fs); + ::cvStartWriteStruct(fs, "data", CV_NODE_SEQ, "binary"); + fs->base64_writer->write(convertor, dt); + ::cvEndWriteStruct(fs); } { /* [3]output end */ - cvEndWriteStruct(fs); + ::cvEndWriteStruct(fs); } } @@ -7096,36 +7376,21 @@ void base64::cvWriteMat_Base64(::CvFileStorage * fs, const char * name, ::cv::Ma * Interface ***************************************************************************/ -namespace cv +CV_IMPL void cvWriteMatBase64(::CvFileStorage* fs, const char* name, const ::CvMat* mat) { - void cvWriteMat_Base64(::CvFileStorage* fs, const char* name, const ::CvMat* mat) - { - ::cv::Mat holder = ::cv::cvarrToMat(mat); - ::base64::cvWriteMat_Base64(fs, name, holder); - } - - void cvWriteMatND_Base64(::CvFileStorage* fs, const char* name, const ::CvMatND* mat) - { - ::cv::Mat holder = ::cv::cvarrToMat(mat); - ::base64::cvWriteMat_Base64(fs, name, holder); - } - - void cvStartWriteRawData_Base64(::CvFileStorage * fs, const char* name, int len, const char* dt) - { - ::base64::cvStartWriteRawData_Base64(fs, name, len, dt); - } - - void cvWriteRawData_Base64(::CvFileStorage * fs, const void* _data, int len) - { - ::base64::cvWriteRawData_Base64(fs, _data, len); - } - - void cvEndWriteRawData_Base64(::CvFileStorage * fs) - { - ::base64::cvEndWriteRawData_Base64(fs); - } - + ::cv::Mat holder = ::cv::cvarrToMat(mat); + ::base64::cvWriteMat_Base64(fs, name, holder); } +CV_IMPL void cvWriteMatNDBase64(::CvFileStorage* fs, const char* name, const ::CvMatND* mat) +{ + ::cv::Mat holder = ::cv::cvarrToMat(mat); + ::base64::cvWriteMat_Base64(fs, name, holder); +} + +CV_IMPL void cvWriteRawDataBase64(::CvFileStorage* fs, const void* _data, int len, const char* dt) +{ + ::base64::cvWriteRawDataBase64(fs, _data, len, dt); +} /* End of file. */ diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index f2c53dc964..1f7191a669 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -593,150 +593,3 @@ TEST(Core_InputOutput, FileStorageSpaces) ASSERT_STREQ(values[i].c_str(), valuesRead[i].c_str()); } } - -TEST(Core_InputOutput, filestorage_yml_compatibility) -{ - // TODO: -} - -class CV_Base64IOTest : public cvtest::BaseTest -{ -private: - std::string file_name; - - struct data_t - { - uchar u1, u2; - int i1, i2, i3; - double d1, d2; - int i4; - }; - -public: - CV_Base64IOTest(std::string const & test_file_name) - : file_name(test_file_name) {} - ~CV_Base64IOTest() {} -protected: - void run(int) - { - try - { - std::vector rawdata; - - cv::Mat _em_out, _em_in; - cv::Mat _2d_out, _2d_in; - cv::Mat _nd_out, _nd_in; - - { /* init */ - - /* normal mat */ - _2d_out = cv::Mat(100, 100, CV_8UC3, cvScalar(1U, 2U, 127U)); - for (int i = 0; i < _2d_out.rows; ++i) - for (int j = 0; j < _2d_out.cols; ++j) - _2d_out.at(i, j)[1] = (i + j) % 256; - - /* 4d mat */ - const int Size[] = {4, 4, 4, 4}; - cv::Mat _4d(4, Size, CV_64FC4, cvScalar(0.888, 0.111, 0.666, 0.444)); - const cv::Range ranges[] = { - cv::Range(0, 2), - cv::Range(0, 2), - cv::Range(1, 2), - cv::Range(0, 2) }; - _nd_out = _4d(ranges); - - /* raw data */ - for (int i = 0; i < 1000; i++) { - data_t tmp; - tmp.u1 = 1; - tmp.u2 = 2; - tmp.i1 = 1; - tmp.i2 = 2; - tmp.i3 = 3; - tmp.d1 = 0.1; - tmp.d2 = 0.2; - tmp.i4 = i; - rawdata.push_back(tmp); - } - } - - { /* write */ - cv::FileStorage fs(file_name, cv::FileStorage::WRITE); - CvMat holder = _2d_out; - cv::cvWriteMat_Base64(*fs, "normal_2d_mat", &holder); - CvMatND holder_nd = _nd_out; - cv::cvWriteMatND_Base64(*fs, "normal_nd_mat", &holder_nd); - holder = _em_out; - cv::cvWriteMat_Base64(*fs, "empty_2d_mat", &holder); - - cv::cvStartWriteRawData_Base64(*fs, "rawdata", static_cast(rawdata.size()), "2u3i2di"); - for (int i = 0; i < 10; i++) - cv::cvWriteRawData_Base64(*fs, rawdata.data() + i * 100, 100); - cv::cvEndWriteRawData_Base64(*fs); - - fs.release(); - } - - { /* read */ - cv::FileStorage fs(file_name, cv::FileStorage::READ); - - /* mat */ - fs["empty_2d_mat"] >> _em_in; - fs["normal_2d_mat"] >> _2d_in; - fs["normal_nd_mat"] >> _nd_in; - - /* raw data */ - std::vector(1000).swap(rawdata); - cvReadRawData(*fs, fs["rawdata"].node, rawdata.data(), "2u3i2di"); - - fs.release(); - } - - for (int i = 0; i < 1000; i++) { - // TODO: Solve this bug in `cvReadRawData` - //EXPECT_EQ(rawdata[i].u1, 1); - //EXPECT_EQ(rawdata[i].u2, 2); - //EXPECT_EQ(rawdata[i].i1, 1); - //EXPECT_EQ(rawdata[i].i2, 2); - //EXPECT_EQ(rawdata[i].i3, 3); - //EXPECT_EQ(rawdata[i].d1, 0.1); - //EXPECT_EQ(rawdata[i].d2, 0.2); - //EXPECT_EQ(rawdata[i].i4, i); - } - - EXPECT_EQ(_em_in.rows , _em_out.rows); - EXPECT_EQ(_em_in.cols , _em_out.cols); - EXPECT_EQ(_em_in.dims , _em_out.dims); - EXPECT_EQ(_em_in.depth(), _em_out.depth()); - EXPECT_TRUE(_em_in.empty()); - - EXPECT_EQ(_2d_in.rows , _2d_in.rows); - EXPECT_EQ(_2d_in.cols , _2d_in.cols); - EXPECT_EQ(_2d_in.dims , _2d_in.dims); - EXPECT_EQ(_2d_in.depth(), _2d_in.depth()); - for(int i = 0; i < _2d_in.rows; ++i) - for (int j = 0; j < _2d_in.cols; ++j) - EXPECT_EQ(_2d_in.at(i, j), _2d_out.at(i, j)); - - EXPECT_EQ(_nd_in.rows , _nd_in.rows); - EXPECT_EQ(_nd_in.cols , _nd_in.cols); - EXPECT_EQ(_nd_in.dims , _nd_in.dims); - EXPECT_EQ(_nd_in.depth(), _nd_in.depth()); - EXPECT_EQ(cv::countNonZero(cv::mean(_nd_in != _nd_out)), 0); - } - catch(...) - { - ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); - } - } -}; - -TEST(Core_InputOutput, filestorage_yml_base64) -{ - CV_Base64IOTest test("base64_test_tmp_file.yml"); test.safe_run(); -} - -TEST(Core_InputOutput, filestorage_xml_base64) -{ - CV_Base64IOTest test("base64_test_tmp_file.xml"); test.safe_run(); -} diff --git a/modules/core/test/test_io_base64.cpp b/modules/core/test/test_io_base64.cpp new file mode 100644 index 0000000000..d619106eae --- /dev/null +++ b/modules/core/test/test_io_base64.cpp @@ -0,0 +1,270 @@ +#include "test_precomp.hpp" + +using namespace cv; +using namespace std; + +struct data_t +{ + typedef uchar u; + typedef char b; + typedef ushort w; + typedef short s; + typedef int i; + typedef float f; + typedef double d; + + u u1 ;u u2 ; i i1 ; + i i2 ;i i3 ; + d d1 ; + d d2 ; + i i4 ; + + static inline const char * signature() { return "2u3i2di"; } +}; + + +TEST(Core_InputOutput_Base64, basic) +{ + char const * filenames[] = { + "core_io_base64_basic_test.yml", + "core_io_base64_basic_test.xml", + 0 + }; + + for (char const ** ptr = filenames; *ptr; ptr++) + { + char const * name = *ptr; + + std::vector rawdata; + + cv::Mat _em_out, _em_in; + cv::Mat _2d_out, _2d_in; + cv::Mat _nd_out, _nd_in; + cv::Mat _rd_out(64, 64, CV_64FC1), _rd_in; + + { /* init */ + + /* a normal mat */ + _2d_out = cv::Mat(100, 100, CV_8UC3, cvScalar(1U, 2U, 127U)); + for (int i = 0; i < _2d_out.rows; ++i) + for (int j = 0; j < _2d_out.cols; ++j) + _2d_out.at(i, j)[1] = (i + j) % 256; + + /* a 4d mat */ + const int Size[] = {4, 4, 4, 4}; + cv::Mat _4d(4, Size, CV_64FC4, cvScalar(0.888, 0.111, 0.666, 0.444)); + const cv::Range ranges[] = { + cv::Range(0, 2), + cv::Range(0, 2), + cv::Range(1, 2), + cv::Range(0, 2) }; + _nd_out = _4d(ranges); + + /* a random mat */ + cv::randu(_rd_out, cv::Scalar(0.0), cv::Scalar(1.0)); + + /* raw data */ + for (int i = 0; i < 1000; i++) { + data_t tmp; + tmp.u1 = 1; + tmp.u2 = 2; + tmp.i1 = 1; + tmp.i2 = 2; + tmp.i3 = 3; + tmp.d1 = 0.1; + tmp.d2 = 0.2; + tmp.i4 = i; + rawdata.push_back(tmp); + } + } + + { /* write */ + cv::FileStorage fs(name, cv::FileStorage::WRITE_BASE64); + fs << "normal_2d_mat" << _2d_out; + fs << "normal_nd_mat" << _nd_out; + fs << "empty_2d_mat" << _em_out; + fs << "random_mat" << _rd_out; + + cvStartWriteStruct( *fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW, "binary" ); + for (int i = 0; i < 10; i++) + cvWriteRawDataBase64(*fs, rawdata.data() + i * 100, 100, data_t::signature()); + cvEndWriteStruct( *fs ); + + fs.release(); + } + + { /* read */ + cv::FileStorage fs(name, cv::FileStorage::READ); + + /* mat */ + fs["empty_2d_mat"] >> _em_in; + fs["normal_2d_mat"] >> _2d_in; + fs["normal_nd_mat"] >> _nd_in; + fs["random_mat"] >> _rd_in; + + /* raw data */ + std::vector(1000).swap(rawdata); + cvReadRawData(*fs, fs["rawdata"].node, rawdata.data(), data_t::signature()); + + fs.release(); + } + + for (int i = 0; i < 1000; i++) { + // TODO: Solve this bug in `cvReadRawData` + //EXPECT_EQ(rawdata[i].u1, 1); + //EXPECT_EQ(rawdata[i].u2, 2); + //EXPECT_EQ(rawdata[i].i1, 1); + //EXPECT_EQ(rawdata[i].i2, 2); + //EXPECT_EQ(rawdata[i].i3, 3); + //EXPECT_EQ(rawdata[i].d1, 0.1); + //EXPECT_EQ(rawdata[i].d2, 0.2); + //EXPECT_EQ(rawdata[i].i4, i); + } + + EXPECT_EQ(_em_in.rows , _em_out.rows); + EXPECT_EQ(_em_in.cols , _em_out.cols); + EXPECT_EQ(_em_in.dims , _em_out.dims); + EXPECT_EQ(_em_in.depth(), _em_out.depth()); + EXPECT_TRUE(_em_in.empty()); + + EXPECT_EQ(_2d_in.rows , _2d_out.rows); + EXPECT_EQ(_2d_in.cols , _2d_out.cols); + EXPECT_EQ(_2d_in.dims , _2d_out.dims); + EXPECT_EQ(_2d_in.depth(), _2d_out.depth()); + for(int i = 0; i < _2d_out.rows; ++i) + for (int j = 0; j < _2d_out.cols; ++j) + EXPECT_EQ(_2d_in.at(i, j), _2d_out.at(i, j)); + + EXPECT_EQ(_nd_in.rows , _nd_out.rows); + EXPECT_EQ(_nd_in.cols , _nd_out.cols); + EXPECT_EQ(_nd_in.dims , _nd_out.dims); + EXPECT_EQ(_nd_in.depth(), _nd_out.depth()); + EXPECT_EQ(cv::countNonZero(cv::mean(_nd_in != _nd_out)), 0); + + EXPECT_EQ(_rd_in.rows , _rd_out.rows); + EXPECT_EQ(_rd_in.cols , _rd_out.cols); + EXPECT_EQ(_rd_in.dims , _rd_out.dims); + EXPECT_EQ(_rd_in.depth(), _rd_out.depth()); + EXPECT_EQ(cv::countNonZero(cv::mean(_rd_in != _rd_out)), 0); + + remove(name); + } +} + +TEST(Core_InputOutput_Base64, valid) +{ + char const * filenames[] = { + "core_io_base64_other_test.yml", + "core_io_base64_other_test.xml", + "core_io_base64_other_test.yml?base64", + "core_io_base64_other_test.xml?base64", + 0 + }; + char const * real_name[] = { + "core_io_base64_other_test.yml", + "core_io_base64_other_test.xml", + "core_io_base64_other_test.yml", + "core_io_base64_other_test.xml", + 0 + }; + + std::vector rawdata(10, static_cast(0x00010203)); + cv::String str_out = "test_string"; + + for (char const ** ptr = filenames; *ptr; ptr++) + { + char const * name = *ptr; + + EXPECT_NO_THROW( + { + cv::FileStorage fs(name, cv::FileStorage::WRITE_BASE64); + + cvStartWriteStruct(*fs, "manydata", CV_NODE_SEQ); + cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW); + for (int i = 0; i < 10; i++) + cvWriteRawData(*fs, rawdata.data(), rawdata.size(), "i"); + cvEndWriteStruct(*fs); + cvWriteString(*fs, 0, str_out.c_str(), 1); + cvEndWriteStruct(*fs); + + fs.release(); + }); + + { + cv::FileStorage fs(name, cv::FileStorage::READ); + std::vector data_in(rawdata.size()); + fs["manydata"][0].readRaw("i", (uchar *)data_in.data(), data_in.size()); + EXPECT_TRUE(fs["manydata"][0].isSeq()); + EXPECT_TRUE(std::equal(rawdata.begin(), rawdata.end(), data_in.begin())); + cv::String str_in; + fs["manydata"][1] >> str_in; + EXPECT_TRUE(fs["manydata"][1].isString()); + EXPECT_EQ(str_in, str_out); + fs.release(); + } + + EXPECT_NO_THROW( + { + cv::FileStorage fs(name, cv::FileStorage::WRITE); + + cvStartWriteStruct(*fs, "manydata", CV_NODE_SEQ); + cvWriteString(*fs, 0, str_out.c_str(), 1); + cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW, "binary"); + for (int i = 0; i < 10; i++) + cvWriteRawData(*fs, rawdata.data(), rawdata.size(), "i"); + cvEndWriteStruct(*fs); + cvEndWriteStruct(*fs); + + fs.release(); + }); + + { + cv::FileStorage fs(name, cv::FileStorage::READ); + cv::String str_in; + fs["manydata"][0] >> str_in; + EXPECT_TRUE(fs["manydata"][0].isString()); + EXPECT_EQ(str_in, str_out); + std::vector data_in(rawdata.size()); + fs["manydata"][1].readRaw("i", (uchar *)data_in.data(), data_in.size()); + EXPECT_TRUE(fs["manydata"][1].isSeq()); + EXPECT_TRUE(std::equal(rawdata.begin(), rawdata.end(), data_in.begin())); + fs.release(); + } + + remove(real_name[ptr - filenames]); + } +} + +TEST(Core_InputOutput_Base64, invalid) +{ + char const * filenames[] = { + "core_io_base64_other_test.yml", + "core_io_base64_other_test.xml", + 0 + }; + + for (char const ** ptr = filenames; *ptr; ptr++) + { + char const * name = *ptr; + + EXPECT_ANY_THROW({ + cv::FileStorage fs(name, cv::FileStorage::WRITE); + cvStartWriteStruct(*fs, "rawdata", CV_NODE_SEQ, "binary"); + cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW); + }); + + EXPECT_ANY_THROW({ + cv::FileStorage fs(name, cv::FileStorage::WRITE); + cvStartWriteStruct(*fs, "rawdata", CV_NODE_SEQ); + cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW); + cvWriteRawDataBase64(*fs, name, 1, "u"); + }); + + remove(name); + } +} + +TEST(Core_InputOutput_Base64, TODO_compatibility) +{ + // TODO: +} diff --git a/modules/ml/test/test_save_load.cpp b/modules/ml/test/test_save_load.cpp index d127471cc9..7c2a7c4a6c 100644 --- a/modules/ml/test/test_save_load.cpp +++ b/modules/ml/test/test_save_load.cpp @@ -65,11 +65,11 @@ int CV_SLMLTest::run_test_case( int testCaseIdx ) { get_test_error( testCaseIdx, &test_resps1 ); fname1 = tempfile(".yml.gz"); - save( fname1.c_str() ); + save( (fname1 + "?base64").c_str() ); load( fname1.c_str() ); get_test_error( testCaseIdx, &test_resps2 ); fname2 = tempfile(".yml.gz"); - save( fname2.c_str() ); + save( (fname2 + "?base64").c_str() ); } else ts->printf( cvtest::TS::LOG, "model can not be trained" ); @@ -280,7 +280,7 @@ TEST(DISABLED_ML_SVM, linear_save_load) svm1 = Algorithm::load("SVM45_X_38-1.xml"); svm2 = Algorithm::load("SVM45_X_38-2.xml"); string tname = tempfile("a.xml"); - svm2->save(tname); + svm2->save(tname + "?base64"); svm3 = Algorithm::load(tname); ASSERT_EQ(svm1->getVarCount(), svm2->getVarCount()); From 0823ec0ef04ffb39ba933aeafce78b2a1e944263 Mon Sep 17 00:00:00 2001 From: MYLS Date: Tue, 19 Jul 2016 16:11:20 +0800 Subject: [PATCH 005/178] modified performance test For faster test --- modules/core/perf/perf_io_base64.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/core/perf/perf_io_base64.cpp b/modules/core/perf/perf_io_base64.cpp index 693c1cc132..339d891008 100644 --- a/modules/core/perf/perf_io_base64.cpp +++ b/modules/core/perf/perf_io_base64.cpp @@ -13,6 +13,7 @@ typedef TestBaseWithParam Size_Mat_StrType; #define MAT_TYPES CV_8UC1, CV_32FC1 #define FILE_EXTENSION String(".xml"), String(".yml") + PERF_TEST_P(Size_Mat_StrType, fs_text, testing::Combine(testing::Values(MAT_SIZES), testing::Values(MAT_TYPES), @@ -31,7 +32,7 @@ PERF_TEST_P(Size_Mat_StrType, fs_text, cv::String file_name = cv::tempfile(ext.c_str()); cv::String key = "test_mat"; - TEST_CYCLE_MULTIRUN(4) + TEST_CYCLE_MULTIRUN(2) { { FileStorage fs(file_name, cv::FileStorage::WRITE); @@ -47,7 +48,7 @@ PERF_TEST_P(Size_Mat_StrType, fs_text, remove(file_name.c_str()); - SANITY_CHECK(dst, 1); + SANITY_CHECK(dst); } PERF_TEST_P(Size_Mat_StrType, fs_base64, @@ -67,7 +68,7 @@ PERF_TEST_P(Size_Mat_StrType, fs_base64, cv::String key = "test_mat"; declare.in(src, WARMUP_RNG).out(dst); - TEST_CYCLE_MULTIRUN(4) + TEST_CYCLE_MULTIRUN(2) { { FileStorage fs(file_name, cv::FileStorage::WRITE_BASE64); @@ -82,5 +83,5 @@ PERF_TEST_P(Size_Mat_StrType, fs_base64, } remove(file_name.c_str()); - SANITY_CHECK(dst, 1); + SANITY_CHECK(dst); } From 42d5b1fb3b36678854671770bd773895b37f4b9e Mon Sep 17 00:00:00 2001 From: catree Date: Mon, 18 Jul 2016 01:29:53 +0200 Subject: [PATCH 006/178] Re-add peopledetect.cpp sample. --- samples/cpp/peopledetect.cpp | 115 +++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 samples/cpp/peopledetect.cpp diff --git a/samples/cpp/peopledetect.cpp b/samples/cpp/peopledetect.cpp new file mode 100644 index 0000000000..e14d07c1b1 --- /dev/null +++ b/samples/cpp/peopledetect.cpp @@ -0,0 +1,115 @@ +#include +#include +#include +#include + +using namespace cv; +using namespace std; + + +static void help() +{ + cout << "\nThis program demonstrates the use of the HoG descriptor using\n" + " HOGDescriptor::hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());\n" + "Usage:\n" + "./peopledetect --i= | --d=\n\n" + "During execution:\n\tHit q or ESC key to quit.\n" + "\tUsing OpenCV version " << CV_VERSION << "\n" << endl; +} + +const char* keys = +{ + "{help h||}" + "{image i| ../data/basketball2.png|input image name}" + "{directory d||images directory}" +}; + +static void detectAndDraw(const HOGDescriptor &hog, Mat &img) +{ + vector found, found_filtered; + double t = (double) getTickCount(); + // Run the detector with default parameters. to get a higher hit-rate + // (and more false alarms, respectively), decrease the hitThreshold and + // groupThreshold (set groupThreshold to 0 to turn off the grouping completely). + hog.detectMultiScale(img, found, 0, Size(8,8), Size(32,32), 1.05, 2); + t = (double) getTickCount() - t; + cout << "detection time = " << (t*1000./cv::getTickFrequency()) << " ms" << endl; + + for(size_t i = 0; i < found.size(); i++ ) + { + Rect r = found[i]; + + size_t j; + // Do not add small detections inside a bigger detection. + for ( j = 0; j < found.size(); j++ ) + if ( j != i && (r & found[j]) == r ) + break; + + if ( j == found.size() ) + found_filtered.push_back(r); + } + + for (size_t i = 0; i < found_filtered.size(); i++) + { + Rect r = found_filtered[i]; + + // The HOG detector returns slightly larger rectangles than the real objects, + // so we slightly shrink the rectangles to get a nicer output. + r.x += cvRound(r.width*0.1); + r.width = cvRound(r.width*0.8); + r.y += cvRound(r.height*0.07); + r.height = cvRound(r.height*0.8); + rectangle(img, r.tl(), r.br(), cv::Scalar(0,255,0), 3); + } +} + +int main(int argc, char** argv) +{ + CommandLineParser parser(argc, argv, keys); + + if (parser.has("help")) + { + help(); + return 0; + } + + HOGDescriptor hog; + hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector()); + namedWindow("people detector", 1); + + string pattern_glob = ""; + if (parser.has("directory")) + { + pattern_glob = parser.get("directory"); + } + else if (parser.has("image")) + { + pattern_glob = parser.get("image"); + } + + if (!pattern_glob.empty()) + { + vector filenames; + String folder(pattern_glob); + glob(folder, filenames); + + for (vector::const_iterator it = filenames.begin(); it != filenames.end(); ++it) + { + cout << "\nRead: " << *it << endl; + // Read current image + Mat current_image = imread(*it); + + if (current_image.empty()) + continue; + + detectAndDraw(hog, current_image); + + imshow("people detector", current_image); + int c = waitKey(0) & 255; + if ( c == 'q' || c == 'Q' || c == 27) + break; + } + } + + return 0; +} From 78ca5ddd45a25781f931125e2eebf168178b0d2b Mon Sep 17 00:00:00 2001 From: MYLS Date: Tue, 19 Jul 2016 19:56:57 +0800 Subject: [PATCH 007/178] solve errors and warnings --- modules/core/include/opencv2/core/core_c.h | 2 +- modules/core/perf/perf_io_base64.cpp | 4 +- modules/core/src/persistence.cpp | 146 ++++++++++++--------- modules/core/test/test_io_base64.cpp | 4 +- 4 files changed, 86 insertions(+), 70 deletions(-) diff --git a/modules/core/include/opencv2/core/core_c.h b/modules/core/include/opencv2/core/core_c.h index 94ba1fc034..ecfc62aceb 100644 --- a/modules/core/include/opencv2/core/core_c.h +++ b/modules/core/include/opencv2/core/core_c.h @@ -2236,7 +2236,7 @@ and @param len Number of the array elements to write @param dt Specification of each array element, see @ref format_spec "format specification" */ -CVAPI(void) cvWriteRawDataBase64( CvFileStorage* fs, const void* _data, +CVAPI(void) cvWriteRawDataBase64( CvFileStorage* fs, const void* src, int len, const char* dt ); /** @brief Returns a unique pointer for a given name. diff --git a/modules/core/perf/perf_io_base64.cpp b/modules/core/perf/perf_io_base64.cpp index 339d891008..cf292c5478 100644 --- a/modules/core/perf/perf_io_base64.cpp +++ b/modules/core/perf/perf_io_base64.cpp @@ -48,7 +48,7 @@ PERF_TEST_P(Size_Mat_StrType, fs_text, remove(file_name.c_str()); - SANITY_CHECK(dst); + SANITY_CHECK(dst, 1); } PERF_TEST_P(Size_Mat_StrType, fs_base64, @@ -83,5 +83,5 @@ PERF_TEST_P(Size_Mat_StrType, fs_base64, } remove(file_name.c_str()); - SANITY_CHECK(dst); + SANITY_CHECK(dst, 1); } diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 6eb3b0c75a..781117323b 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -183,7 +183,17 @@ typedef struct CvXMLStackRecord } CvXMLStackRecord; -namespace base64 { class Base64Writer; } +namespace base64 +{ + class Base64Writer; + + enum Base64State + { + Uncertain, + NotUse, + InUse, + }; +} #define CV_XML_OPENING_TAG 1 #define CV_XML_CLOSING_TAG 2 @@ -244,11 +254,7 @@ typedef struct CvFileStorage base64::Base64Writer * base64_writer; bool is_default_using_base64; - enum Base64State { - Uncertain, - NotUse, - InUse, - } state_of_writing_base64; /**< used in WriteRawData only */ + base64::Base64State state_of_writing_base64; /**< used in WriteRawData only */ bool is_write_struct_delayed; char* delayed_struct_key; @@ -339,7 +345,6 @@ namespace base64 private: - ::CvFileStorage * file_storage; Base64ContextEmitter * emitter; std::string data_type_string; }; @@ -1061,10 +1066,14 @@ static double icv_strtod( CvFileStorage* fs, char* ptr, char** endptr ) static std::vector analyze_file_name( std::string const & file_name ) { + static const char not_file_name = '\n'; static const char parameter_begin = '?'; static const char parameter_separator = '&'; std::vector result; + if ( file_name.find(not_file_name, 0U) != std::string::npos ) + return result; + size_t beg = file_name.find_last_of(parameter_begin); size_t end = file_name.size(); result.push_back(file_name.substr(0U, beg)); @@ -1087,7 +1096,7 @@ static std::vector analyze_file_name( std::string const & file_name return result; } -static bool is_param_exist( std::vector & const params, std::string & const param ) +static bool is_param_exist( const std::vector & params, const std::string & param ) { if ( params.size() < 2U ) return false; @@ -1095,7 +1104,7 @@ static bool is_param_exist( std::vector & const params, std::string return std::find(params.begin(), params.end(), param) != params.end(); } -static void switch_to_Base64_state( CvFileStorage* fs, CvFileStorage::Base64State state ) +static void switch_to_Base64_state( CvFileStorage* fs, base64::Base64State state ) { const char * err_unkonwn_state = "Unexpected error, unable to determine the Base64 state."; const char * err_unable_to_switch = "Unexpected error, unable to switch to this state."; @@ -1103,30 +1112,30 @@ static void switch_to_Base64_state( CvFileStorage* fs, CvFileStorage::Base64Stat /* like a finite state machine */ switch (fs->state_of_writing_base64) { - case CvFileStorage::Base64State::Uncertain: + case base64::Base64State::Uncertain: switch (state) { - case CvFileStorage::Base64State::InUse: + case base64::Base64State::InUse: CV_DbgAssert( fs->base64_writer == 0 ); fs->base64_writer = new base64::Base64Writer( fs ); break; - case CvFileStorage::Base64State::Uncertain: + case base64::Base64State::Uncertain: break; - case CvFileStorage::Base64State::NotUse: + case base64::Base64State::NotUse: break; default: CV_Error( CV_StsError, err_unkonwn_state ); break; } break; - case CvFileStorage::Base64State::InUse: + case base64::Base64State::InUse: switch (state) { - case CvFileStorage::Base64State::InUse: - case CvFileStorage::Base64State::NotUse: + case base64::Base64State::InUse: + case base64::Base64State::NotUse: CV_Error( CV_StsError, err_unable_to_switch ); break; - case CvFileStorage::Base64State::Uncertain: + case base64::Base64State::Uncertain: delete fs->base64_writer; fs->base64_writer = 0; break; @@ -1135,14 +1144,14 @@ static void switch_to_Base64_state( CvFileStorage* fs, CvFileStorage::Base64Stat break; } break; - case CvFileStorage::Base64State::NotUse: + case base64::Base64State::NotUse: switch (state) { - case CvFileStorage::Base64State::InUse: - case CvFileStorage::Base64State::NotUse: + case base64::Base64State::InUse: + case base64::Base64State::NotUse: CV_Error( CV_StsError, err_unable_to_switch ); break; - case CvFileStorage::Base64State::Uncertain: + case base64::Base64State::Uncertain: break; default: CV_Error( CV_StsError, err_unkonwn_state ); @@ -1191,16 +1200,16 @@ static void check_if_write_struct_is_delayed( CvFileStorage* fs, bool change_typ if ( change_type_to_base64 ) { fs->start_write_struct( fs, struct_key, struct_flags, "binary"); - if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) - switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); - switch_to_Base64_state( fs, CvFileStorage::Base64State::InUse ); + if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) + switch_to_Base64_state( fs, base64::Base64State::Uncertain ); + switch_to_Base64_state( fs, base64::Base64State::InUse ); } else { fs->start_write_struct( fs, struct_key, struct_flags, type_name); - if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) - switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); - switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) + switch_to_Base64_state( fs, base64::Base64State::Uncertain ); + switch_to_Base64_state( fs, base64::Base64State::NotUse ); } delete struct_key; @@ -1351,7 +1360,9 @@ static char* icvYMLParseBase64(CvFileStorage* fs, char* ptr, int indent, CvFileN /* buffer for decoded data(exclude header) */ std::vector binary_buffer( base64::base64_decode_buffer_size(base64_buffer.size()) ); - int total_byte_size = base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false ); + int total_byte_size = static_cast( + base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false ) + ); { base64::Base64ContextParser parser(binary_buffer.data(), binary_buffer.size() ); const uchar * buffer_beg = reinterpret_cast( base64_buffer.data() ); @@ -1830,11 +1841,11 @@ static void icvYMLWrite( CvFileStorage* fs, const char* key, const char* data ) { check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) + if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) { - switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + switch_to_Base64_state( fs, base64::Base64State::NotUse ); } - else if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + else if ( fs->state_of_writing_base64 == base64::Base64State::InUse ) { CV_Error( CV_StsError, "At present, output Base64 data only." ); } @@ -2305,7 +2316,9 @@ static char* icvXMLParseBase64(CvFileStorage* fs, char* ptr, CvFileNode * node) /* alloc buffer for all decoded data(include header) */ std::vector binary_buffer( base64::base64_decode_buffer_size(base64_buffer.size()) ); - int total_byte_size = base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false ); + int total_byte_size = static_cast( + base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false ) + ); { base64::Base64ContextParser parser(binary_buffer.data(), binary_buffer.size() ); const uchar * buffer_beg = reinterpret_cast( base64_buffer.data() ); @@ -2980,11 +2993,11 @@ static void icvXMLWriteScalar( CvFileStorage* fs, const char* key, const char* data, int len ) { check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) + if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) { - switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + switch_to_Base64_state( fs, base64::Base64State::NotUse ); } - else if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + else if ( fs->state_of_writing_base64 == base64::Base64State::InUse ) { CV_Error( CV_StsError, "Currently only Base64 data is allowed." ); } @@ -3206,14 +3219,18 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const bool write_base64 = write_mode && (flags & CV_STORAGE_BASE64) != 0; bool isGZ = false; size_t fnamelen = 0; - const char * filename = 0; + const char * filename = query; - std::vector params = analyze_file_name( query ); - if ( !params.empty() ) - filename = params.begin()->c_str(); + std::vector params; + if ( !mem ) + { + params = analyze_file_name( query ); + if ( !params.empty() ) + filename = params.begin()->c_str(); - if (write_base64 == false && is_param_exist( params, std::string("base64") ) ) - write_base64 = true; + if ( write_base64 == false && is_param_exist( params, "base64" ) ) + write_base64 = true; + } if( !filename || filename[0] == '\0' ) { @@ -3317,7 +3334,7 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const fs->base64_writer = 0; fs->is_default_using_base64 = write_base64; - fs->state_of_writing_base64 = CvFileStorage::Base64State::Uncertain; + fs->state_of_writing_base64 = base64::Base64State::Uncertain; fs->is_write_struct_delayed = false; fs->delayed_struct_key = 0; @@ -3499,10 +3516,10 @@ cvStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, { CV_CHECK_OUTPUT_FILE_STORAGE(fs); check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::NotUse ) - switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + if ( fs->state_of_writing_base64 == base64::Base64State::NotUse ) + switch_to_Base64_state( fs, base64::Base64State::Uncertain ); - if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain + if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain && CV_NODE_IS_SEQ(struct_flags) && @@ -3519,26 +3536,26 @@ cvStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, /* Must output Base64 data */ if ( !CV_NODE_IS_SEQ(struct_flags) ) CV_Error( CV_StsBadArg, "must set 'struct_flags |= CV_NODE_SEQ' if using Base64."); - else if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) + else if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) CV_Error( CV_StsError, "function \'cvStartWriteStruct\' calls cannot be nested if using Base64."); fs->start_write_struct( fs, key, struct_flags, type_name ); - if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) - switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); - switch_to_Base64_state( fs, CvFileStorage::Base64State::InUse ); + if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) + switch_to_Base64_state( fs, base64::Base64State::Uncertain ); + switch_to_Base64_state( fs, base64::Base64State::InUse ); } else { /* Won't output Base64 data */ - if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + if ( fs->state_of_writing_base64 == base64::Base64State::InUse ) CV_Error( CV_StsError, "At the end of the output Base64, `cvEndWriteStruct` is needed."); fs->start_write_struct( fs, key, struct_flags, type_name ); - if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) - switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); - switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) + switch_to_Base64_state( fs, base64::Base64State::Uncertain ); + switch_to_Base64_state( fs, base64::Base64State::NotUse ); } } @@ -3549,8 +3566,8 @@ cvEndWriteStruct( CvFileStorage* fs ) CV_CHECK_OUTPUT_FILE_STORAGE(fs); check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) - switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) + switch_to_Base64_state( fs, base64::Base64State::Uncertain ); fs->end_write_struct( fs ); } @@ -3730,14 +3747,14 @@ CV_IMPL void cvWriteRawData( CvFileStorage* fs, const void* _data, int len, const char* dt ) { if (fs->is_default_using_base64 || - fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + fs->state_of_writing_base64 == base64::Base64State::InUse ) { base64::cvWriteRawDataBase64( fs, _data, len, dt ); return; } - else if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) + else if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) { - switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + switch_to_Base64_state( fs, base64::Base64State::NotUse ); } const char* data0 = (const char*)_data; @@ -7259,8 +7276,7 @@ private: base64::Base64Writer::Base64Writer(::CvFileStorage * fs) - : file_storage(fs) - , emitter(new Base64ContextEmitter(fs)) + : emitter(new Base64ContextEmitter(fs)) , data_type_string() { CV_CHECK_OUTPUT_FILE_STORAGE(fs); @@ -7325,11 +7341,11 @@ void base64::cvWriteRawDataBase64(::CvFileStorage* fs, const void* _data, int le check_if_write_struct_is_delayed( fs, true ); - if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) + if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) { - switch_to_Base64_state( fs, CvFileStorage::Base64State::InUse ); + switch_to_Base64_state( fs, base64::Base64State::InUse ); } - else if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::InUse ) + else if ( fs->state_of_writing_base64 != base64::Base64State::InUse ) { CV_Error( CV_StsError, "Base64 should not be used at present." ); } @@ -7376,13 +7392,13 @@ void base64::cvWriteMat_Base64(::CvFileStorage * fs, const char * name, ::cv::Ma * Interface ***************************************************************************/ -CV_IMPL void cvWriteMatBase64(::CvFileStorage* fs, const char* name, const ::CvMat* mat) +void cvWriteMatBase64(::CvFileStorage* fs, const char* name, const ::CvMat* mat) { ::cv::Mat holder = ::cv::cvarrToMat(mat); ::base64::cvWriteMat_Base64(fs, name, holder); } -CV_IMPL void cvWriteMatNDBase64(::CvFileStorage* fs, const char* name, const ::CvMatND* mat) +void cvWriteMatNDBase64(::CvFileStorage* fs, const char* name, const ::CvMatND* mat) { ::cv::Mat holder = ::cv::cvarrToMat(mat); ::base64::cvWriteMat_Base64(fs, name, holder); diff --git a/modules/core/test/test_io_base64.cpp b/modules/core/test/test_io_base64.cpp index d619106eae..35fb18c139 100644 --- a/modules/core/test/test_io_base64.cpp +++ b/modules/core/test/test_io_base64.cpp @@ -182,7 +182,7 @@ TEST(Core_InputOutput_Base64, valid) cvStartWriteStruct(*fs, "manydata", CV_NODE_SEQ); cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW); for (int i = 0; i < 10; i++) - cvWriteRawData(*fs, rawdata.data(), rawdata.size(), "i"); + cvWriteRawData(*fs, rawdata.data(), static_cast(rawdata.size()), "i"); cvEndWriteStruct(*fs); cvWriteString(*fs, 0, str_out.c_str(), 1); cvEndWriteStruct(*fs); @@ -211,7 +211,7 @@ TEST(Core_InputOutput_Base64, valid) cvWriteString(*fs, 0, str_out.c_str(), 1); cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW, "binary"); for (int i = 0; i < 10; i++) - cvWriteRawData(*fs, rawdata.data(), rawdata.size(), "i"); + cvWriteRawData(*fs, rawdata.data(), static_cast(rawdata.size()), "i"); cvEndWriteStruct(*fs); cvEndWriteStruct(*fs); From cf2d6f6721704e4d8e9f410f77df2f832ce748b9 Mon Sep 17 00:00:00 2001 From: MYLS Date: Tue, 19 Jul 2016 21:18:41 +0800 Subject: [PATCH 008/178] solve errors and warnings Modified performance test and solve a problem caused by an enum type. --- modules/core/perf/perf_io_base64.cpp | 5 +- modules/core/src/persistence.cpp | 117 +++++++++++++-------------- 2 files changed, 57 insertions(+), 65 deletions(-) diff --git a/modules/core/perf/perf_io_base64.cpp b/modules/core/perf/perf_io_base64.cpp index cf292c5478..a39c0cbce8 100644 --- a/modules/core/perf/perf_io_base64.cpp +++ b/modules/core/perf/perf_io_base64.cpp @@ -48,7 +48,7 @@ PERF_TEST_P(Size_Mat_StrType, fs_text, remove(file_name.c_str()); - SANITY_CHECK(dst, 1); + EXPECT_EQ( src, dst ); } PERF_TEST_P(Size_Mat_StrType, fs_base64, @@ -83,5 +83,6 @@ PERF_TEST_P(Size_Mat_StrType, fs_base64, } remove(file_name.c_str()); - SANITY_CHECK(dst, 1); + + EXPECT_EQ( src, dst ); } diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 781117323b..e4fc0c6be7 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -187,12 +187,15 @@ namespace base64 { class Base64Writer; - enum Base64State + namespace fs { - Uncertain, - NotUse, - InUse, - }; + enum State + { + Uncertain, + NotUse, + InUse, + }; + } } #define CV_XML_OPENING_TAG 1 @@ -254,7 +257,7 @@ typedef struct CvFileStorage base64::Base64Writer * base64_writer; bool is_default_using_base64; - base64::Base64State state_of_writing_base64; /**< used in WriteRawData only */ + base64::fs::State state_of_writing_base64; /**< used in WriteRawData only */ bool is_write_struct_delayed; char* delayed_struct_key; @@ -1104,7 +1107,7 @@ static bool is_param_exist( const std::vector & params, const std:: return std::find(params.begin(), params.end(), param) != params.end(); } -static void switch_to_Base64_state( CvFileStorage* fs, base64::Base64State state ) +static void switch_to_Base64_state( CvFileStorage* fs, base64::fs::State state ) { const char * err_unkonwn_state = "Unexpected error, unable to determine the Base64 state."; const char * err_unable_to_switch = "Unexpected error, unable to switch to this state."; @@ -1112,30 +1115,30 @@ static void switch_to_Base64_state( CvFileStorage* fs, base64::Base64State state /* like a finite state machine */ switch (fs->state_of_writing_base64) { - case base64::Base64State::Uncertain: + case base64::fs::Uncertain: switch (state) { - case base64::Base64State::InUse: + case base64::fs::InUse: CV_DbgAssert( fs->base64_writer == 0 ); fs->base64_writer = new base64::Base64Writer( fs ); break; - case base64::Base64State::Uncertain: + case base64::fs::Uncertain: break; - case base64::Base64State::NotUse: + case base64::fs::NotUse: break; default: CV_Error( CV_StsError, err_unkonwn_state ); break; } break; - case base64::Base64State::InUse: + case base64::fs::InUse: switch (state) { - case base64::Base64State::InUse: - case base64::Base64State::NotUse: + case base64::fs::InUse: + case base64::fs::NotUse: CV_Error( CV_StsError, err_unable_to_switch ); break; - case base64::Base64State::Uncertain: + case base64::fs::Uncertain: delete fs->base64_writer; fs->base64_writer = 0; break; @@ -1144,14 +1147,14 @@ static void switch_to_Base64_state( CvFileStorage* fs, base64::Base64State state break; } break; - case base64::Base64State::NotUse: + case base64::fs::NotUse: switch (state) { - case base64::Base64State::InUse: - case base64::Base64State::NotUse: + case base64::fs::InUse: + case base64::fs::NotUse: CV_Error( CV_StsError, err_unable_to_switch ); break; - case base64::Base64State::Uncertain: + case base64::fs::Uncertain: break; default: CV_Error( CV_StsError, err_unkonwn_state ); @@ -1200,16 +1203,16 @@ static void check_if_write_struct_is_delayed( CvFileStorage* fs, bool change_typ if ( change_type_to_base64 ) { fs->start_write_struct( fs, struct_key, struct_flags, "binary"); - if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) - switch_to_Base64_state( fs, base64::Base64State::Uncertain ); - switch_to_Base64_state( fs, base64::Base64State::InUse ); + if ( fs->state_of_writing_base64 != base64::fs::Uncertain ) + switch_to_Base64_state( fs, base64::fs::Uncertain ); + switch_to_Base64_state( fs, base64::fs::InUse ); } else { fs->start_write_struct( fs, struct_key, struct_flags, type_name); - if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) - switch_to_Base64_state( fs, base64::Base64State::Uncertain ); - switch_to_Base64_state( fs, base64::Base64State::NotUse ); + if ( fs->state_of_writing_base64 != base64::fs::Uncertain ) + switch_to_Base64_state( fs, base64::fs::Uncertain ); + switch_to_Base64_state( fs, base64::fs::NotUse ); } delete struct_key; @@ -1841,11 +1844,11 @@ static void icvYMLWrite( CvFileStorage* fs, const char* key, const char* data ) { check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) + if ( fs->state_of_writing_base64 == base64::fs::Uncertain ) { - switch_to_Base64_state( fs, base64::Base64State::NotUse ); + switch_to_Base64_state( fs, base64::fs::NotUse ); } - else if ( fs->state_of_writing_base64 == base64::Base64State::InUse ) + else if ( fs->state_of_writing_base64 == base64::fs::InUse ) { CV_Error( CV_StsError, "At present, output Base64 data only." ); } @@ -2993,11 +2996,11 @@ static void icvXMLWriteScalar( CvFileStorage* fs, const char* key, const char* data, int len ) { check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) + if ( fs->state_of_writing_base64 == base64::fs::Uncertain ) { - switch_to_Base64_state( fs, base64::Base64State::NotUse ); + switch_to_Base64_state( fs, base64::fs::NotUse ); } - else if ( fs->state_of_writing_base64 == base64::Base64State::InUse ) + else if ( fs->state_of_writing_base64 == base64::fs::InUse ) { CV_Error( CV_StsError, "Currently only Base64 data is allowed." ); } @@ -3334,7 +3337,7 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const fs->base64_writer = 0; fs->is_default_using_base64 = write_base64; - fs->state_of_writing_base64 = base64::Base64State::Uncertain; + fs->state_of_writing_base64 = base64::fs::Uncertain; fs->is_write_struct_delayed = false; fs->delayed_struct_key = 0; @@ -3516,10 +3519,10 @@ cvStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, { CV_CHECK_OUTPUT_FILE_STORAGE(fs); check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 == base64::Base64State::NotUse ) - switch_to_Base64_state( fs, base64::Base64State::Uncertain ); + if ( fs->state_of_writing_base64 == base64::fs::NotUse ) + switch_to_Base64_state( fs, base64::fs::Uncertain ); - if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain + if ( fs->state_of_writing_base64 == base64::fs::Uncertain && CV_NODE_IS_SEQ(struct_flags) && @@ -3536,26 +3539,26 @@ cvStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, /* Must output Base64 data */ if ( !CV_NODE_IS_SEQ(struct_flags) ) CV_Error( CV_StsBadArg, "must set 'struct_flags |= CV_NODE_SEQ' if using Base64."); - else if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) + else if ( fs->state_of_writing_base64 != base64::fs::Uncertain ) CV_Error( CV_StsError, "function \'cvStartWriteStruct\' calls cannot be nested if using Base64."); fs->start_write_struct( fs, key, struct_flags, type_name ); - if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) - switch_to_Base64_state( fs, base64::Base64State::Uncertain ); - switch_to_Base64_state( fs, base64::Base64State::InUse ); + if ( fs->state_of_writing_base64 != base64::fs::Uncertain ) + switch_to_Base64_state( fs, base64::fs::Uncertain ); + switch_to_Base64_state( fs, base64::fs::InUse ); } else { /* Won't output Base64 data */ - if ( fs->state_of_writing_base64 == base64::Base64State::InUse ) + if ( fs->state_of_writing_base64 == base64::fs::InUse ) CV_Error( CV_StsError, "At the end of the output Base64, `cvEndWriteStruct` is needed."); fs->start_write_struct( fs, key, struct_flags, type_name ); - if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) - switch_to_Base64_state( fs, base64::Base64State::Uncertain ); - switch_to_Base64_state( fs, base64::Base64State::NotUse ); + if ( fs->state_of_writing_base64 != base64::fs::Uncertain ) + switch_to_Base64_state( fs, base64::fs::Uncertain ); + switch_to_Base64_state( fs, base64::fs::NotUse ); } } @@ -3566,8 +3569,8 @@ cvEndWriteStruct( CvFileStorage* fs ) CV_CHECK_OUTPUT_FILE_STORAGE(fs); check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) - switch_to_Base64_state( fs, base64::Base64State::Uncertain ); + if ( fs->state_of_writing_base64 != base64::fs::Uncertain ) + switch_to_Base64_state( fs, base64::fs::Uncertain ); fs->end_write_struct( fs ); } @@ -3747,14 +3750,14 @@ CV_IMPL void cvWriteRawData( CvFileStorage* fs, const void* _data, int len, const char* dt ) { if (fs->is_default_using_base64 || - fs->state_of_writing_base64 == base64::Base64State::InUse ) + fs->state_of_writing_base64 == base64::fs::InUse ) { base64::cvWriteRawDataBase64( fs, _data, len, dt ); return; } - else if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) + else if ( fs->state_of_writing_base64 == base64::fs::Uncertain ) { - switch_to_Base64_state( fs, base64::Base64State::NotUse ); + switch_to_Base64_state( fs, base64::fs::NotUse ); } const char* data0 = (const char*)_data; @@ -7341,11 +7344,11 @@ void base64::cvWriteRawDataBase64(::CvFileStorage* fs, const void* _data, int le check_if_write_struct_is_delayed( fs, true ); - if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) + if ( fs->state_of_writing_base64 == base64::fs::Uncertain ) { - switch_to_Base64_state( fs, base64::Base64State::InUse ); + switch_to_Base64_state( fs, base64::fs::InUse ); } - else if ( fs->state_of_writing_base64 != base64::Base64State::InUse ) + else if ( fs->state_of_writing_base64 != base64::fs::InUse ) { CV_Error( CV_StsError, "Base64 should not be used at present." ); } @@ -7392,18 +7395,6 @@ void base64::cvWriteMat_Base64(::CvFileStorage * fs, const char * name, ::cv::Ma * Interface ***************************************************************************/ -void cvWriteMatBase64(::CvFileStorage* fs, const char* name, const ::CvMat* mat) -{ - ::cv::Mat holder = ::cv::cvarrToMat(mat); - ::base64::cvWriteMat_Base64(fs, name, holder); -} - -void cvWriteMatNDBase64(::CvFileStorage* fs, const char* name, const ::CvMatND* mat) -{ - ::cv::Mat holder = ::cv::cvarrToMat(mat); - ::base64::cvWriteMat_Base64(fs, name, holder); -} - CV_IMPL void cvWriteRawDataBase64(::CvFileStorage* fs, const void* _data, int len, const char* dt) { ::base64::cvWriteRawDataBase64(fs, _data, len, dt); From d06b8c4ea9d30be7f60196cdf3c9a65f64370fa4 Mon Sep 17 00:00:00 2001 From: Sergei Nosov Date: Tue, 19 Jul 2016 17:05:30 +0300 Subject: [PATCH 009/178] add test for #6836 --- .../calib3d/test/test_cameracalibration.cpp | 104 +++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/modules/calib3d/test/test_cameracalibration.cpp b/modules/calib3d/test/test_cameracalibration.cpp index 2dad0cf222..357208dd6c 100644 --- a/modules/calib3d/test/test_cameracalibration.cpp +++ b/modules/calib3d/test/test_cameracalibration.cpp @@ -1346,6 +1346,108 @@ void CV_ProjectPointsTest_CPP::project( const Mat& objectPoints, const Mat& rvec ///////////////////////////////// Stereo Calibration ///////////////////////////////////// +class CV_StereoCalibrationCornerTest : public cvtest::BaseTest +{ +public: + CV_StereoCalibrationCornerTest(); + ~CV_StereoCalibrationCornerTest(); + void clear(); +protected: + void run(int); +}; + +CV_StereoCalibrationCornerTest::CV_StereoCalibrationCornerTest() +{ +} + + +CV_StereoCalibrationCornerTest::~CV_StereoCalibrationCornerTest() +{ + clear(); +} + +void CV_StereoCalibrationCornerTest::clear() +{ + cvtest::BaseTest::clear(); +} + +static bool resizeCameraMatrix(const Mat &in_cm, Mat &dst_cm, double scale) +{ + if (in_cm.empty() || in_cm.cols != 3 || in_cm.rows != 3 || in_cm.type() != CV_64FC1) + return false; + dst_cm = in_cm * scale; + dst_cm.at(2, 2) = 1.0; + return true; +} + +// see https://github.com/opencv/opencv/pull/6836 for details +void CV_StereoCalibrationCornerTest::run(int) +{ + const Matx33d M1(906.7857732303256, 0.0, 1026.456125870669, + 0.0, 906.7857732303256, 540.0531577669913, + 0.0, 0.0, 1.0); + const Matx33d M2(906.782205162265, 0.0, 1014.619997352785, + 0.0, 906.782205162265, 561.9990018887295, + 0.0, 0.0, 1.0); + const Matx D1(0.0064836857220181504, 0.033880363848984636, 0.0, 0.0, -0.042996356352306114); + const Matx D2(0.023754068600491646, -0.02364619610835259, 0.0, 0.0, 0.0015014971456262652); + + const Size imageSize(2048, 1088); + const double scale = 0.25; + + const Matx33d Rot(0.999788461750194, -0.015696495349844446, -0.013291041528534329, + 0.015233019205877604, 0.999296086451901, -0.034282455101525826, + 0.01381980018141639, 0.03407274036010432, 0.9993238021218641); + const Matx31d T(-1.552005597952028, 0.0019508251875105093, -0.023335501616116062); + + // generate camera matrices for resized image rectification. + Mat srcM1(M1), srcM2(M2); + Mat rszM1, rszM2; + resizeCameraMatrix(srcM1, rszM1, scale); + resizeCameraMatrix(srcM2, rszM2, scale); + Size rszImageSize(cvRound(scale * imageSize.width), cvRound(scale * imageSize.height)); + Size srcImageSize = imageSize; + // apply stereoRectify + Mat srcR[2], srcP[2], srcQ; + Mat rszR[2], rszP[2], rszQ; + stereoRectify(srcM1, D1, srcM2, D2, srcImageSize, Rot, T, + srcR[0], srcR[1], srcP[0], srcP[1], srcQ, + CALIB_ZERO_DISPARITY, 0); + stereoRectify(rszM1, D1, rszM2, D2, rszImageSize, Rot, T, + rszR[0], rszR[1], rszP[0], rszP[1], rszQ, + CALIB_ZERO_DISPARITY, 0); + // generate remap maps + Mat srcRmap[2], rszRmap[2]; + initUndistortRectifyMap(srcM1, D1, srcR[0], srcP[0], srcImageSize, CV_32FC2, srcRmap[0], srcRmap[1]); + initUndistortRectifyMap(rszM1, D1, rszR[0], rszP[0], rszImageSize, CV_32FC2, rszRmap[0], rszRmap[1]); + + // generate source image + // it's an artificial pattern with white rect in the center + Mat image(imageSize, CV_8UC3); + image.setTo(0); + image(cv::Rect(imageSize.width / 3, imageSize.height / 3, imageSize.width / 3, imageSize.height / 3)).setTo(255); + + // perform remap-resize + Mat src_result; + remap(image, src_result, srcRmap[0], srcRmap[1], INTER_LINEAR); + resize(src_result, src_result, Size(), scale, scale, INTER_LINEAR); + // perform resize-remap + Mat rsz_result; + resize(image, rsz_result, Size(), scale, scale, INTER_LINEAR); + remap(rsz_result, rsz_result, rszRmap[0], rszRmap[1], INTER_LINEAR); + + // modifying the camera matrix with resizeCameraMatrix must yield the same + // result as calibrating the downscaled images + int cnz = countNonZero((cv::Mat(src_result - rsz_result) != 0)( + cv::Rect(src_result.cols / 3, src_result.rows / 3, + src_result.cols / 3.1, src_result.rows / 3.1))); + if (cnz) + { + ts->printf( cvtest::TS::LOG, "The camera matrix is wrong for downscaled image\n"); + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + } +} + class CV_StereoCalibrationTest : public cvtest::BaseTest { public: @@ -1949,7 +2051,7 @@ TEST(Calib3d_ProjectPoints_C, accuracy) { CV_ProjectPointsTest_C test; test.saf TEST(Calib3d_ProjectPoints_CPP, regression) { CV_ProjectPointsTest_CPP test; test.safe_run(); } TEST(Calib3d_StereoCalibrate_C, regression) { CV_StereoCalibrationTest_C test; test.safe_run(); } TEST(Calib3d_StereoCalibrate_CPP, regression) { CV_StereoCalibrationTest_CPP test; test.safe_run(); } - +TEST(Calib3d_StereoCalibrateCorner, regression) { CV_StereoCalibrationCornerTest test; test.safe_run(); } TEST(Calib3d_Triangulate, accuracy) { From 27b924e99e1461ccd84f2d4a74cf306c370dc5ad Mon Sep 17 00:00:00 2001 From: MYLS Date: Tue, 19 Jul 2016 22:06:21 +0800 Subject: [PATCH 010/178] remove CHECK from performance test --- modules/core/perf/perf_io_base64.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/core/perf/perf_io_base64.cpp b/modules/core/perf/perf_io_base64.cpp index a39c0cbce8..f2982b2cb0 100644 --- a/modules/core/perf/perf_io_base64.cpp +++ b/modules/core/perf/perf_io_base64.cpp @@ -47,8 +47,6 @@ PERF_TEST_P(Size_Mat_StrType, fs_text, } remove(file_name.c_str()); - - EXPECT_EQ( src, dst ); } PERF_TEST_P(Size_Mat_StrType, fs_base64, @@ -83,6 +81,4 @@ PERF_TEST_P(Size_Mat_StrType, fs_base64, } remove(file_name.c_str()); - - EXPECT_EQ( src, dst ); } From 8a65e73bfdad4aeb9ee8bbb9ca345356aa5de53c Mon Sep 17 00:00:00 2001 From: MYLS Date: Wed, 20 Jul 2016 20:18:16 +0800 Subject: [PATCH 011/178] add SANITY_CHECK_NOTHING() to perf_test --- modules/core/perf/perf_io_base64.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/core/perf/perf_io_base64.cpp b/modules/core/perf/perf_io_base64.cpp index f2982b2cb0..04a4a040a5 100644 --- a/modules/core/perf/perf_io_base64.cpp +++ b/modules/core/perf/perf_io_base64.cpp @@ -47,6 +47,7 @@ PERF_TEST_P(Size_Mat_StrType, fs_text, } remove(file_name.c_str()); + SANITY_CHECK_NOTHING(); } PERF_TEST_P(Size_Mat_StrType, fs_base64, @@ -81,4 +82,5 @@ PERF_TEST_P(Size_Mat_StrType, fs_base64, } remove(file_name.c_str()); + SANITY_CHECK_NOTHING(); } From b3d55489d3f1bd2eab0c1e3ad56d8f17d4f447e9 Mon Sep 17 00:00:00 2001 From: Sergei Nosov Date: Thu, 21 Jul 2016 10:57:58 +0300 Subject: [PATCH 012/178] fix compiler warning --- modules/calib3d/test/test_cameracalibration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/calib3d/test/test_cameracalibration.cpp b/modules/calib3d/test/test_cameracalibration.cpp index 357208dd6c..523594224d 100644 --- a/modules/calib3d/test/test_cameracalibration.cpp +++ b/modules/calib3d/test/test_cameracalibration.cpp @@ -1440,7 +1440,7 @@ void CV_StereoCalibrationCornerTest::run(int) // result as calibrating the downscaled images int cnz = countNonZero((cv::Mat(src_result - rsz_result) != 0)( cv::Rect(src_result.cols / 3, src_result.rows / 3, - src_result.cols / 3.1, src_result.rows / 3.1))); + (int)(src_result.cols / 3.1), int(src_result.rows / 3.1)))); if (cnz) { ts->printf( cvtest::TS::LOG, "The camera matrix is wrong for downscaled image\n"); From fa42a1cfc2b0fce1d807f18f0ea26ba1e5753b80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D1=83=D0=BD=20=D0=92=D0=B8=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80?= Date: Fri, 22 Jul 2016 19:02:53 +0300 Subject: [PATCH 013/178] fix calib3d changes in #6836 plus some others --- modules/calib3d/src/calibration.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/calib3d/src/calibration.cpp b/modules/calib3d/src/calibration.cpp index f2b00551a4..3d45ee1c4c 100644 --- a/modules/calib3d/src/calibration.cpp +++ b/modules/calib3d/src/calibration.cpp @@ -1210,8 +1210,8 @@ CV_IMPL void cvInitIntrinsicParams2D( const CvMat* objectPoints, matA.reset(cvCreateMat( 2*nimages, 2, CV_64F )); _b.reset(cvCreateMat( 2*nimages, 1, CV_64F )); - a[2] = (!imageSize.width) ? 0.5 : (imageSize.width - 1)*0.5; - a[5] = (!imageSize.height) ? 0.5 : (imageSize.height - 1)*0.5; + a[2] = (!imageSize.width) ? 0.5 : (imageSize.width)*0.5; + a[5] = (!imageSize.height) ? 0.5 : (imageSize.height)*0.5; _allH.reset(cvCreateMat( nimages, 9, CV_64F )); // extract vanishing points in order to obtain initial value for the focal length @@ -2494,8 +2494,8 @@ void cvGetOptimalNewCameraMatrix( const CvMat* cameraMatrix, const CvMat* distCo { double cx0 = M[0][2]; double cy0 = M[1][2]; - double cx = (newImgSize.width-1)*0.5; - double cy = (newImgSize.height-1)*0.5; + double cx = (newImgSize.width)*0.5; + double cy = (newImgSize.height)*0.5; icvGetRectangles( cameraMatrix, distCoeffs, 0, cameraMatrix, imgSize, inner, outer ); double s0 = std::max(std::max(std::max((double)cx/(cx0 - inner.x), (double)cy/(cy0 - inner.y)), @@ -2529,14 +2529,14 @@ void cvGetOptimalNewCameraMatrix( const CvMat* cameraMatrix, const CvMat* distCo icvGetRectangles( cameraMatrix, distCoeffs, 0, 0, imgSize, inner, outer ); // Projection mapping inner rectangle to viewport - double fx0 = (newImgSize.width - 1) / inner.width; - double fy0 = (newImgSize.height - 1) / inner.height; + double fx0 = (newImgSize.width) / inner.width; + double fy0 = (newImgSize.height) / inner.height; double cx0 = -fx0 * inner.x; double cy0 = -fy0 * inner.y; // Projection mapping outer rectangle to viewport - double fx1 = (newImgSize.width - 1) / outer.width; - double fy1 = (newImgSize.height - 1) / outer.height; + double fx1 = (newImgSize.width) / outer.width; + double fy1 = (newImgSize.height) / outer.height; double cx1 = -fx1 * outer.x; double cy1 = -fy1 * outer.y; @@ -2600,8 +2600,8 @@ CV_IMPL int cvStereoRectifyUncalibrated( cvGEMM( &U, &W, 1, 0, 0, &W, CV_GEMM_A_T ); cvMatMul( &W, &V, &F ); - cx = cvRound( (imgSize.width-1)*0.5 ); - cy = cvRound( (imgSize.height-1)*0.5 ); + cx = cvRound( (imgSize.width)*0.5 ); + cy = cvRound( (imgSize.height)*0.5 ); cvZero( _H1 ); cvZero( _H2 ); From 08911cbfaef9c9a3a9c203700a3380cb880a1f6d Mon Sep 17 00:00:00 2001 From: MYLS Date: Sat, 30 Jul 2016 00:35:41 +0800 Subject: [PATCH 014/178] change `code` to `snippet` and do some cleaning. - use `@snippet` instead of `@code` in docs. - remove some functions that were not used. --- modules/core/include/opencv2/core/core_c.h | 35 +---- modules/core/src/persistence.cpp | 159 ++------------------- samples/cpp/filestorage_base64.cpp | 71 +++++++++ 3 files changed, 86 insertions(+), 179 deletions(-) create mode 100644 samples/cpp/filestorage_base64.cpp diff --git a/modules/core/include/opencv2/core/core_c.h b/modules/core/include/opencv2/core/core_c.h index ecfc62aceb..dd1d93638e 100644 --- a/modules/core/include/opencv2/core/core_c.h +++ b/modules/core/include/opencv2/core/core_c.h @@ -1978,14 +1978,11 @@ The function opens file storage for reading or writing data. In the latter case, created or an existing file is rewritten. The type of the read or written file is determined by the filename extension: .xml for XML and .yml or .yaml for YAML. -At the same time, it also supports adding parameters like "example.xml?base64". -@code - CvFileStorage* fs = cvOpenFileStorage( "example.yml?base64", 0, CV_STORAGE_WRITE ); -@endcode -it's exactly the same as -@code - CvFileStorage* fs = cvOpenFileStorage( "example.yml", 0, CV_STORAGE_WRITE_BASE64 ); -@endcode +At the same time, it also supports adding parameters like "example.xml?base64". The three ways +are the same: +@snippet samples/cpp/filestorage_base64.cpp suffix_in_file_name +@snippet samples/cpp/filestorage_base64.cpp flag_write_base64 +@snippet samples/cpp/filestorage_base64.cpp flag_write_and_flag_base64 The function returns a pointer to the CvFileStorage structure. If the file cannot be opened then the function returns NULL. @@ -2209,27 +2206,9 @@ in plain text. This function can only be used to write a sequence with a type "binary". Consider the following two examples where their output is the same: -@code - std::vector rawdata(10, 0x00010203); - // without the flag CV_STORAGE_WRITE_BASE64. - CvFileStorage* fs = cvOpenFileStorage( "example.yml", 0, CV_STORAGE_WRITE ); - // both CV_NODE_SEQ and "binary" are necessary. - cvStartWriteStruct(fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW, "binary"); - cvWriteRawDataBase64(fs, rawdata.data(), rawdata.size(), "i"); - cvEndWriteStruct(fs); - cvReleaseFileStorage( &fs ); -@endcode +@snippet samples/cpp/filestorage_base64.cpp without_base64_flag and -@code - std::vector rawdata(10, 0x00010203); - // with the flag CV_STORAGE_WRITE_BASE64. - CvFileStorage* fs = cvOpenFileStorage( "example.yml", 0, CV_STORAGE_WRITE_BASE64); - // parameter, typename "binary" could be omitted. - cvStartWriteStruct(fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW); - cvWriteRawData(fs, rawdata.data(), rawdata.size(), "i"); - cvEndWriteStruct(fs); - cvReleaseFileStorage( &fs ); -@endcode +@snippet samples/cpp/filestorage_base64.cpp with_write_base64_flag @param fs File storage @param src Pointer to the written array diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index e4fc0c6be7..9f52a96cec 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -308,7 +308,6 @@ namespace base64 template<> inline size_t binary_to(uchar const * cur, float & val); template inline size_t binary_to(uchar const * cur, uchar * val); - class MatToBinaryConvertor; class RawDataToBinaryConvertor; class BinaryToCvSeqConvertor; @@ -363,8 +362,6 @@ namespace base64 /* sample */ void cvWriteRawDataBase64(::CvFileStorage* fs, const void* _data, int len, const char* dt); - - void cvWriteMat_Base64(::CvFileStorage * fs, const char * name, ::cv::Mat const & mat); } @@ -2306,7 +2303,7 @@ static char* icvXMLParseBase64(CvFileStorage* fs, char* ptr, CvFileNode * node) } /* get all Base64 data */ - std::string base64_buffer; + std::string base64_buffer; // not an efficient way. base64_buffer.reserve( 16U * 1024U * 1024U ); while( beg < end ) { @@ -3715,13 +3712,13 @@ icvCalcStructSize( const char* dt, int initial_size ) for ( const char * type = dt; *type != '\0'; type++ ) { switch ( *type ) { - case 'u': { if (elem_max_size < sizeof(uchar)) elem_max_size = sizeof(uchar); break; } - case 'c': { if (elem_max_size < sizeof(schar)) elem_max_size = sizeof(schar); break; } - case 'w': { if (elem_max_size < sizeof(ushort)) elem_max_size = sizeof(ushort); break; } - case 's': { if (elem_max_size < sizeof(short)) elem_max_size = sizeof(short); break; } - case 'i': { if (elem_max_size < sizeof(int)) elem_max_size = sizeof(int); break; } - case 'f': { if (elem_max_size < sizeof(float)) elem_max_size = sizeof(float); break; } - case 'd': { if (elem_max_size < sizeof(double)) elem_max_size = sizeof(double); break; } + case 'u': { elem_max_size = std::max( elem_max_size, sizeof(uchar ) ); break; } + case 'c': { elem_max_size = std::max( elem_max_size, sizeof(schar ) ); break; } + case 'w': { elem_max_size = std::max( elem_max_size, sizeof(ushort) ); break; } + case 's': { elem_max_size = std::max( elem_max_size, sizeof(short ) ); break; } + case 'i': { elem_max_size = std::max( elem_max_size, sizeof(int ) ); break; } + case 'f': { elem_max_size = std::max( elem_max_size, sizeof(float ) ); break; } + case 'd': { elem_max_size = std::max( elem_max_size, sizeof(double) ); break; } default: break; } } @@ -6869,111 +6866,6 @@ private: uchar * src_end; }; -class base64::MatToBinaryConvertor -{ -public: - - explicit MatToBinaryConvertor(const cv::Mat & src) - : y (0) - , y_max(0) - , x(0) - , x_max(0) - { - /* make sure each mat `mat.dims == 2` */ - if (src.dims > 2) { - const cv::Mat * arrays[] = { &src, 0 }; - cv::Mat plane; - cv::NAryMatIterator it(arrays, &plane, 1); - - CV_Assert(it.nplanes > 0U); /* make sure mats not empty */ - mats.reserve(it.nplanes); - for (size_t i = 0U; i < it.nplanes; ++i, ++it) - mats.push_back(*it.planes); - } else { - mats.push_back(src); - } - - /* set all to beginning */ - mat_iter = mats.begin(); - y_max = (mat_iter)->rows; - x_max = (mat_iter)->cols * (mat_iter)->elemSize(); - row_begin = (mat_iter)->ptr(0); - step = (mat_iter)->elemSize1(); - - /* choose a function */ - switch ((mat_iter)->depth()) - { - case CV_8U : - case CV_8S : { to_binary_func = to_binary ; break; } - case CV_16U: - case CV_16S: { to_binary_func = to_binary; break; } - case CV_32S: { to_binary_func = to_binary ; break; } - case CV_32F: { to_binary_func = to_binary ; break; } - case CV_64F: { to_binary_func = to_binary; break; } - case CV_USRTYPE1: - default: { CV_Assert(!"mat type is invalid"); break; } - }; - - /* check if empty */ - if (mats.empty() || mats.front().empty() || mats.front().data == 0) { - mat_iter = mats.end(); - CV_Assert(!(*this)); - } - - } - - inline MatToBinaryConvertor & operator >> (uchar * & dst) - { - CV_DbgAssert(*this); - - /* [1]copy to dst */ - dst += to_binary_func(row_begin + x, dst); - - /* [2]move to next */ - x += step; - if (x >= x_max) { - /* when x arrive end, reset x and increase y */ - x = 0U; - ++ y; - if (y >= y_max) { - /* when y arrive end, reset y and increase iter */ - y = 0U; - ++ mat_iter; - if (mat_iter == mats.end()) { - ;/* when iter arrive end, all done */ - } else { - /* usually x_max and y_max won't change */ - y_max = (mat_iter)->rows; - x_max = (mat_iter)->cols * (mat_iter)->elemSize(); - row_begin = (mat_iter)->ptr(static_cast(y)); - } - } else - row_begin = (mat_iter)->ptr(static_cast(y)); - } - - return *this; - } - - inline operator bool() const - { - return mat_iter != mats.end(); - } - -private: - - size_t y; - size_t y_max; - size_t x; - size_t x_max; - std::vector::iterator mat_iter; - std::vector mats; - - size_t step; - const uchar * row_begin; - - typedef size_t(*to_binary_t)(const uchar *, uchar *); - to_binary_t to_binary_func; -}; class base64::RawDataToBinaryConvertor { @@ -7356,41 +7248,6 @@ void base64::cvWriteRawDataBase64(::CvFileStorage* fs, const void* _data, int le fs->base64_writer->write(_data, len, dt); } -void base64::cvWriteMat_Base64(::CvFileStorage * fs, const char * name, ::cv::Mat const & mat) -{ - char dt[4]; - ::icvEncodeFormat(CV_MAT_TYPE(mat.type()), dt); - - { /* [1]output other attr */ - - if (mat.dims <= 2) { - ::cvStartWriteStruct(fs, name, CV_NODE_MAP, CV_TYPE_NAME_MAT); - - ::cvWriteInt(fs, "rows", mat.rows ); - ::cvWriteInt(fs, "cols", mat.cols ); - } else { - ::cvStartWriteStruct(fs, name, CV_NODE_MAP, CV_TYPE_NAME_MATND); - - ::cvStartWriteStruct(fs, "sizes", CV_NODE_SEQ | CV_NODE_FLOW); - ::cvWriteRawData(fs, mat.size.p, mat.dims, "i"); - ::cvEndWriteStruct(fs); - } - ::cvWriteString(fs, "dt", ::icvEncodeFormat(CV_MAT_TYPE(mat.type()), dt ), 0 ); - } - - { /* [2]deal with matrix's data */ - MatToBinaryConvertor convertor(mat); - - ::cvStartWriteStruct(fs, "data", CV_NODE_SEQ, "binary"); - fs->base64_writer->write(convertor, dt); - ::cvEndWriteStruct(fs); - } - - { /* [3]output end */ - ::cvEndWriteStruct(fs); - } -} - /**************************************************************************** * Interface ***************************************************************************/ diff --git a/samples/cpp/filestorage_base64.cpp b/samples/cpp/filestorage_base64.cpp new file mode 100644 index 0000000000..75e26bf362 --- /dev/null +++ b/samples/cpp/filestorage_base64.cpp @@ -0,0 +1,71 @@ +#include "opencv2/core.hpp" +#include +#include + +static CvFileStorage * three_same_ways_of_write_base64() +{ + CvFileStorage * fs = 0; + cv::RNG rng; + switch ( rng.uniform( 0, 2 ) ) + { + case 0: + //! [suffix_in_file_name] + fs = cvOpenFileStorage( "example.yml?base64", 0, CV_STORAGE_WRITE ); + //! [suffix_in_file_name] + break; + case 1: + //! [flag_write_base64] + fs = cvOpenFileStorage( "example.yml" , 0, CV_STORAGE_WRITE_BASE64 ); + //! [flag_write_base64] + break; + case 2: + //! [flag_write_and_flag_base64] + fs = cvOpenFileStorage( "example.yml" , 0, CV_STORAGE_WRITE | CV_STORAGE_BASE64 ); + //! [flag_write_and_flag_base64] + break; + default: + break; + } + return fs; +} + +static void two_ways_to_write_rawdata_in_base64() +{ + std::vector rawdata(10, 0x00010203); + + { // [1] + //! [without_base64_flag] + CvFileStorage* fs = cvOpenFileStorage( "example.xml", 0, CV_STORAGE_WRITE ); + // both CV_NODE_SEQ and "binary" are necessary. + cvStartWriteStruct(fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW, "binary"); + cvWriteRawDataBase64(fs, rawdata.data(), rawdata.size(), "i"); + cvEndWriteStruct(fs); + cvReleaseFileStorage( &fs ); + //! [without_base64_flag] + } + + { // [2] + //! [with_write_base64_flag] + CvFileStorage* fs = cvOpenFileStorage( "example.xml", 0, CV_STORAGE_WRITE_BASE64); + // parameter, typename "binary" could be omitted. + cvStartWriteStruct(fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW); + cvWriteRawData(fs, rawdata.data(), rawdata.size(), "i"); + cvEndWriteStruct(fs); + cvReleaseFileStorage( &fs ); + //! [with_write_base64_flag] + } +} + +int main(int /* argc */, char** /* argv */) +{ + { // base64 mode + CvFileStorage * fs = three_same_ways_of_write_base64(); + cvReleaseFileStorage( &fs ); + } + + { // output rawdata by `cvWriteRawdata*` + two_ways_to_write_rawdata_in_base64(); + } + + return 0; +} From 7429ed07be2c08b2fa3902fed1e42bfca6d31a96 Mon Sep 17 00:00:00 2001 From: MYLS Date: Sat, 30 Jul 2016 02:05:15 +0800 Subject: [PATCH 015/178] solve warnings in sample file --- samples/cpp/filestorage_base64.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/cpp/filestorage_base64.cpp b/samples/cpp/filestorage_base64.cpp index 75e26bf362..dcd46544f9 100644 --- a/samples/cpp/filestorage_base64.cpp +++ b/samples/cpp/filestorage_base64.cpp @@ -38,7 +38,7 @@ static void two_ways_to_write_rawdata_in_base64() CvFileStorage* fs = cvOpenFileStorage( "example.xml", 0, CV_STORAGE_WRITE ); // both CV_NODE_SEQ and "binary" are necessary. cvStartWriteStruct(fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW, "binary"); - cvWriteRawDataBase64(fs, rawdata.data(), rawdata.size(), "i"); + cvWriteRawDataBase64(fs, rawdata.data(), static_cast(rawdata.size()), "i"); cvEndWriteStruct(fs); cvReleaseFileStorage( &fs ); //! [without_base64_flag] @@ -49,7 +49,7 @@ static void two_ways_to_write_rawdata_in_base64() CvFileStorage* fs = cvOpenFileStorage( "example.xml", 0, CV_STORAGE_WRITE_BASE64); // parameter, typename "binary" could be omitted. cvStartWriteStruct(fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW); - cvWriteRawData(fs, rawdata.data(), rawdata.size(), "i"); + cvWriteRawData(fs, rawdata.data(), static_cast(rawdata.size()), "i"); cvEndWriteStruct(fs); cvReleaseFileStorage( &fs ); //! [with_write_base64_flag] From 4ae4a705d557730f64fb2948d269dcb4583f5c0a Mon Sep 17 00:00:00 2001 From: lewgate Date: Sun, 31 Jul 2016 17:13:23 +0800 Subject: [PATCH 016/178] Fix a bug for seam_finders.cpp when computing the source and destination points of the seam --- modules/stitching/src/seam_finders.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/stitching/src/seam_finders.cpp b/modules/stitching/src/seam_finders.cpp index dbed801d5b..4018127774 100644 --- a/modules/stitching/src/seam_finders.cpp +++ b/modules/stitching/src/seam_finders.cpp @@ -638,7 +638,7 @@ bool DpSeamFinder::getSeamTips(int comp1, int comp2, Point &p1, Point &p2) { double size1 = static_cast(points[i].size()), size2 = static_cast(points[j].size()); double cx1 = cvRound(sum[i].x / size1), cy1 = cvRound(sum[i].y / size1); - double cx2 = cvRound(sum[j].x / size2), cy2 = cvRound(sum[j].y / size1); + double cx2 = cvRound(sum[j].x / size2), cy2 = cvRound(sum[j].y / size2); double dist = (cx1 - cx2) * (cx1 - cx2) + (cy1 - cy2) * (cy1 - cy2); if (dist > maxDist) From 15dabc11b559c3946f3aeecb608534d826220470 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Tue, 2 Aug 2016 11:38:14 +0200 Subject: [PATCH 017/178] Mat: use row/ col instead of i0/ i1 for parameter names in 2D case this improves documentation when using an IDE and reflects that Mats are row major. --- modules/core/include/opencv2/core/mat.hpp | 44 ++++++++++++++--------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index ab2ba79734..b8b15d2db3 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -1645,10 +1645,16 @@ public: /** @overload */ const uchar* ptr(int i0=0) const; - /** @overload */ - uchar* ptr(int i0, int i1); - /** @overload */ - const uchar* ptr(int i0, int i1) const; + /** @overload + @param row Index along the dimension 0 + @param col Index along the dimension 1 + */ + uchar* ptr(int row, int col); + /** @overload + @param row Index along the dimension 0 + @param col Index along the dimension 1 + */ + const uchar* ptr(int row, int col) const; /** @overload */ uchar* ptr(int i0, int i1, int i2); @@ -1668,10 +1674,16 @@ public: template _Tp* ptr(int i0=0); /** @overload */ template const _Tp* ptr(int i0=0) const; - /** @overload */ - template _Tp* ptr(int i0, int i1); - /** @overload */ - template const _Tp* ptr(int i0, int i1) const; + /** @overload + @param row Index along the dimension 0 + @param col Index along the dimension 1 + */ + template _Tp* ptr(int row, int col); + /** @overload + @param row Index along the dimension 0 + @param col Index along the dimension 1 + */ + template const _Tp* ptr(int row, int col) const; /** @overload */ template _Tp* ptr(int i0, int i1, int i2); /** @overload */ @@ -1721,15 +1733,15 @@ public: */ template const _Tp& at(int i0=0) const; /** @overload - @param i0 Index along the dimension 0 - @param i1 Index along the dimension 1 + @param row Index along the dimension 0 + @param col Index along the dimension 1 */ - template _Tp& at(int i0, int i1); + template _Tp& at(int row, int col); /** @overload - @param i0 Index along the dimension 0 - @param i1 Index along the dimension 1 + @param row Index along the dimension 0 + @param col Index along the dimension 1 */ - template const _Tp& at(int i0, int i1) const; + template const _Tp& at(int row, int col) const; /** @overload @param i0 Index along the dimension 0 @@ -2094,9 +2106,9 @@ public: //! returns read-only reference to the specified element (1D case) const _Tp& operator ()(int idx0) const; //! returns reference to the specified element (2D case) - _Tp& operator ()(int idx0, int idx1); + _Tp& operator ()(int row, int col); //! returns read-only reference to the specified element (2D case) - const _Tp& operator ()(int idx0, int idx1) const; + const _Tp& operator ()(int row, int col) const; //! returns reference to the specified element (3D case) _Tp& operator ()(int idx0, int idx1, int idx2); //! returns read-only reference to the specified element (3D case) From 065d631f0eedad2fbb438779c57d139ebf458eaf Mon Sep 17 00:00:00 2001 From: k-shinotsuka Date: Mon, 25 Jul 2016 20:47:30 +0900 Subject: [PATCH 018/178] improve MomentsInTile_SIMD() --- modules/imgproc/src/moments.cpp | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/modules/imgproc/src/moments.cpp b/modules/imgproc/src/moments.cpp index 15c4a61039..41a9cf36c7 100644 --- a/modules/imgproc/src/moments.cpp +++ b/modules/imgproc/src/moments.cpp @@ -227,16 +227,15 @@ struct MomentsInTile_SIMD if( useSIMD ) { - __m128i qx_init = _mm_setr_epi16(0, 1, 2, 3, 4, 5, 6, 7); __m128i dx = _mm_set1_epi16(8); - __m128i z = _mm_setzero_si128(), qx0 = z, qx1 = z, qx2 = z, qx3 = z, qx = qx_init; + __m128i z = _mm_setzero_si128(), qx0 = z, qx1 = z, qx2 = z, qx3 = z, qx = _mm_setr_epi16(0, 1, 2, 3, 4, 5, 6, 7); for( ; x <= len - 8; x += 8 ) { __m128i p = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)(ptr + x)), z); __m128i sx = _mm_mullo_epi16(qx, qx); - qx0 = _mm_add_epi32(qx0, _mm_sad_epu8(p, z)); + qx0 = _mm_add_epi16(qx0, p); qx1 = _mm_add_epi32(qx1, _mm_madd_epi16(p, qx)); qx2 = _mm_add_epi32(qx2, _mm_madd_epi16(p, sx)); qx3 = _mm_add_epi32(qx3, _mm_madd_epi16( _mm_mullo_epi16(p, qx), sx)); @@ -244,14 +243,21 @@ struct MomentsInTile_SIMD qx = _mm_add_epi16(qx, dx); } - _mm_store_si128((__m128i*)buf, qx0); - x0 = buf[0] + buf[1] + buf[2] + buf[3]; - _mm_store_si128((__m128i*)buf, qx1); - x1 = buf[0] + buf[1] + buf[2] + buf[3]; - _mm_store_si128((__m128i*)buf, qx2); - x2 = buf[0] + buf[1] + buf[2] + buf[3]; - _mm_store_si128((__m128i*)buf, qx3); - x3 = buf[0] + buf[1] + buf[2] + buf[3]; + __m128i qx01_lo = _mm_unpacklo_epi32(qx0, qx1); + __m128i qx23_lo = _mm_unpacklo_epi32(qx2, qx3); + __m128i qx01_hi = _mm_unpackhi_epi32(qx0, qx1); + __m128i qx23_hi = _mm_unpackhi_epi32(qx2, qx3); + qx01_lo = _mm_add_epi32(qx01_lo, qx01_hi); + qx23_lo = _mm_add_epi32(qx23_lo, qx23_hi); + __m128i qx0123_lo = _mm_unpacklo_epi64(qx01_lo, qx23_lo); + __m128i qx0123_hi = _mm_unpackhi_epi64(qx01_lo, qx23_lo); + qx0123_lo = _mm_add_epi32(qx0123_lo, qx0123_hi); + _mm_store_si128((__m128i*)buf, qx0123_lo); + + x0 = (buf[0] & 0xffff) + (buf[0] >> 16); + x1 = buf[1]; + x2 = buf[2]; + x3 = buf[3]; } return x; From 18e7afdfd91e20b938ba885045b5537bcce1f915 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 4 Aug 2016 19:23:49 +0300 Subject: [PATCH 019/178] cmake: add OPENCV_ENABLE_NONFREE option and macro --- CMakeLists.txt | 7 +++++++ cmake/templates/opencv_modules.hpp.in | 4 ++++ modules/core/include/opencv2/core/base.hpp | 2 ++ 3 files changed, 13 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 317edbb139..5e575bd794 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,6 +164,8 @@ endif() # OpenCV cmake options # ---------------------------------------------------------------------------- +OCV_OPTION(OPENCV_ENABLE_NONFREE "Enable non-free algorithms" OFF) + # Optional 3rd party components # =================================================== OCV_OPTION(WITH_1394 "Include IEEE1394 support" ON IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) @@ -914,6 +916,11 @@ status(" Disabled:" OPENCV_MODULES_DISABLED_USER THEN ${OPENCV status(" Disabled by dependency:" OPENCV_MODULES_DISABLED_AUTO THEN ${OPENCV_MODULES_DISABLED_AUTO_ST} ELSE "-") status(" Unavailable:" OPENCV_MODULES_DISABLED_FORCE THEN ${OPENCV_MODULES_DISABLED_FORCE_ST} ELSE "-") +if(OPENCV_ENABLE_NONFREE) + status("") + status(" Non-free algorithms are enabled") +endif() + # ========================== Android details ========================== if(ANDROID) status("") diff --git a/cmake/templates/opencv_modules.hpp.in b/cmake/templates/opencv_modules.hpp.in index 1498715028..6696bb4926 100644 --- a/cmake/templates/opencv_modules.hpp.in +++ b/cmake/templates/opencv_modules.hpp.in @@ -6,4 +6,8 @@ * */ +// This definition means that OpenCV is built with enabled non-free code. +// For example, patented algorithms for non-profit/non-commercial use only. +#cmakedefine OPENCV_ENABLE_NONFREE + @OPENCV_MODULE_DEFINITIONS_CONFIGMAKE@ diff --git a/modules/core/include/opencv2/core/base.hpp b/modules/core/include/opencv2/core/base.hpp index ed633f5dcc..0432ccb842 100644 --- a/modules/core/include/opencv2/core/base.hpp +++ b/modules/core/include/opencv2/core/base.hpp @@ -49,6 +49,8 @@ # error base.hpp header must be compiled as C++ #endif +#include "opencv2/opencv_modules.hpp" + #include #include From b42288c2de6e5394e0e5c14398a0f72c99636e0c Mon Sep 17 00:00:00 2001 From: David Wolever Date: Thu, 4 Aug 2016 12:44:07 -0400 Subject: [PATCH 020/178] Cleaner fix for crash on double-stop of CvVideoCamera --- .../videoio/src/cap_ios_abstract_camera.mm | 19 ++++++++------ modules/videoio/src/cap_ios_video_camera.mm | 25 +++++++++---------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/modules/videoio/src/cap_ios_abstract_camera.mm b/modules/videoio/src/cap_ios_abstract_camera.mm index 565807cccc..328c161513 100644 --- a/modules/videoio/src/cap_ios_abstract_camera.mm +++ b/modules/videoio/src/cap_ios_abstract_camera.mm @@ -193,16 +193,19 @@ // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; - for (AVCaptureInput *input in self.captureSession.inputs) { - [self.captureSession removeInput:input]; + if (self.captureSession) { + for (AVCaptureInput *input in self.captureSession.inputs) { + [self.captureSession removeInput:input]; + } + + for (AVCaptureOutput *output in self.captureSession.outputs) { + [self.captureSession removeOutput:output]; + } + + [self.captureSession stopRunning]; + self.captureSession = nil; } - for (AVCaptureOutput *output in self.captureSession.outputs) { - [self.captureSession removeOutput:output]; - } - - [self.captureSession stopRunning]; - self.captureSession = nil; self.captureVideoPreviewLayer = nil; self.videoCaptureConnection = nil; captureSessionLoaded = NO; diff --git a/modules/videoio/src/cap_ios_video_camera.mm b/modules/videoio/src/cap_ios_video_camera.mm index 8d483092c5..ee074afdef 100644 --- a/modules/videoio/src/cap_ios_video_camera.mm +++ b/modules/videoio/src/cap_ios_video_camera.mm @@ -122,10 +122,6 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} - (void)stop; { - if (self.running == NO) { - return; - } - [super stop]; self.videoDataOutput = nil; @@ -134,21 +130,24 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} } if (self.recordVideo == YES) { - - if (self.recordAssetWriter.status == AVAssetWriterStatusWriting) { - [self.recordAssetWriter finishWriting]; - NSLog(@"[Camera] recording stopped"); - } else { - NSLog(@"[Camera] Recording Error: asset writer status is not writing"); + if (self.recordAssetWriter) { + if (self.recordAssetWriter.status == AVAssetWriterStatusWriting) { + [self.recordAssetWriter finishWriting]; + NSLog(@"[Camera] recording stopped"); + } else { + NSLog(@"[Camera] Recording Error: asset writer status is not writing"); + } + self.recordAssetWriter = nil; } - self.recordAssetWriter = nil; self.recordAssetWriterInput = nil; self.recordPixelBufferAdaptor = nil; } - [self.customPreviewLayer removeFromSuperlayer]; - self.customPreviewLayer = nil; + if (self.customPreviewLayer) { + [self.customPreviewLayer removeFromSuperlayer]; + self.customPreviewLayer = nil; + } } // TODO fix From 86238d2748c19876e10b4bc9299bc206cec0cf8a Mon Sep 17 00:00:00 2001 From: MYLS Date: Fri, 5 Aug 2016 15:17:21 +0800 Subject: [PATCH 021/178] make some changes according to the code review. - use `std::string` instead of `new char`; - reserve 1 MB for buffer; --- modules/core/src/persistence.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 1813905be7..0c062f39b4 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -1172,19 +1172,17 @@ static void check_if_write_struct_is_delayed( CvFileStorage* fs, bool change_typ if ( fs->is_write_struct_delayed ) { /* save data to prevent recursive call errors */ - char * struct_key = 0; - char * type_name = 0; + std::string struct_key; + std::string type_name; int struct_flags = fs->delayed_struct_flags; - if ( fs->delayed_struct_key != 0 ) + if ( fs->delayed_struct_key != 0 && *fs->delayed_type_name != '\0' ) { - struct_key = new char[strlen(fs->delayed_struct_key) + 1U]; - strcpy(struct_key, fs->delayed_struct_key); + struct_key.assign(fs->delayed_struct_key); } - if ( fs->delayed_type_name != 0 ) + if ( fs->delayed_type_name != 0 && *fs->delayed_type_name != '\0' ) { - type_name = new char[strlen(type_name) + 1U]; - strcpy(type_name, fs->delayed_type_name); + struct_key.assign(fs->delayed_type_name); } /* reset */ @@ -1199,21 +1197,18 @@ static void check_if_write_struct_is_delayed( CvFileStorage* fs, bool change_typ /* call */ if ( change_type_to_base64 ) { - fs->start_write_struct( fs, struct_key, struct_flags, "binary"); + fs->start_write_struct( fs, struct_key.c_str(), struct_flags, "binary"); if ( fs->state_of_writing_base64 != base64::fs::Uncertain ) switch_to_Base64_state( fs, base64::fs::Uncertain ); switch_to_Base64_state( fs, base64::fs::InUse ); } else { - fs->start_write_struct( fs, struct_key, struct_flags, type_name); + fs->start_write_struct( fs, struct_key.c_str(), struct_flags, type_name.c_str()); if ( fs->state_of_writing_base64 != base64::fs::Uncertain ) switch_to_Base64_state( fs, base64::fs::Uncertain ); switch_to_Base64_state( fs, base64::fs::NotUse ); } - - delete struct_key; - delete type_name; } } @@ -1246,6 +1241,7 @@ static void make_write_struct_delayed( fs->is_write_struct_delayed = true; } +static const size_t PARSER_BASE64_BUFFER_SIZE = 1024U * 1024U / 8U; /****************************************************************************************\ * YAML Parser * @@ -1348,7 +1344,7 @@ static char* icvYMLParseBase64(CvFileStorage* fs, char* ptr, int indent, CvFileN /* get all Base64 data */ std::string base64_buffer; - base64_buffer.reserve( 16U * 1024U * 1024U ); + base64_buffer.reserve( PARSER_BASE64_BUFFER_SIZE ); while( beg < end ) { base64_buffer.append( beg, end ); @@ -2304,7 +2300,7 @@ static char* icvXMLParseBase64(CvFileStorage* fs, char* ptr, CvFileNode * node) /* get all Base64 data */ std::string base64_buffer; // not an efficient way. - base64_buffer.reserve( 16U * 1024U * 1024U ); + base64_buffer.reserve( PARSER_BASE64_BUFFER_SIZE ); while( beg < end ) { base64_buffer.append( beg, end ); From 1da8a19af3c9d58533892473c1fcccad4321f2be Mon Sep 17 00:00:00 2001 From: MYLS Date: Fri, 5 Aug 2016 16:15:03 +0800 Subject: [PATCH 022/178] fixed two bugs that I caused. --- modules/core/src/persistence.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 0c062f39b4..6f9f992983 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -1176,13 +1176,13 @@ static void check_if_write_struct_is_delayed( CvFileStorage* fs, bool change_typ std::string type_name; int struct_flags = fs->delayed_struct_flags; - if ( fs->delayed_struct_key != 0 && *fs->delayed_type_name != '\0' ) + if ( fs->delayed_struct_key != 0 && *fs->delayed_struct_key != '\0' ) { struct_key.assign(fs->delayed_struct_key); } if ( fs->delayed_type_name != 0 && *fs->delayed_type_name != '\0' ) { - struct_key.assign(fs->delayed_type_name); + type_name.assign(fs->delayed_type_name); } /* reset */ @@ -1949,6 +1949,9 @@ icvYMLStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, char buf[CV_FS_MAX_LEN + 1024]; const char* data = 0; + if ( type_name && *type_name == '\0' ) + type_name = 0; + struct_flags = (struct_flags & (CV_NODE_TYPE_MASK|CV_NODE_FLOW)) | CV_NODE_EMPTY; if( !CV_NODE_IS_COLLECTION(struct_flags)) CV_Error( CV_StsBadArg, @@ -2914,6 +2917,9 @@ icvXMLStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, CV_Error( CV_StsBadArg, "Some collection type: CV_NODE_SEQ or CV_NODE_MAP must be specified" ); + if ( type_name && *type_name == '\0' ) + type_name = 0; + if( type_name ) { attr[idx++] = "type_id"; From 37cccf17c044e50c94039300f9bdd5a0e3676445 Mon Sep 17 00:00:00 2001 From: matze Date: Thu, 21 Jul 2016 19:59:26 +0200 Subject: [PATCH 023/178] imgproc: Prefer OCL calculation before IPP in GaussianBlur. --- modules/imgproc/src/smooth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index b5a037ec2d..f12036dad3 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -1850,7 +1850,7 @@ void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, return; #endif - CV_IPP_RUN(true, ipp_GaussianBlur( _src, _dst, ksize, sigma1, sigma2, borderType)); + CV_IPP_RUN(!(ocl::useOpenCL() && _dst.isUMat()), ipp_GaussianBlur( _src, _dst, ksize, sigma1, sigma2, borderType)); Mat kx, ky; createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2); From 2812762d6b59b46eb9c48f7f989010b6b12d5b96 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 4 Aug 2016 17:50:23 +0300 Subject: [PATCH 024/178] imgproc: disable IPP for GaussianBlur in case of ROI --- modules/imgproc/src/smooth.cpp | 3 +++ modules/imgproc/test/ocl/test_filters.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index f12036dad3..8245a62057 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -1734,6 +1734,9 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, int borderType ) { #if IPP_VERSION_X100 >= 810 + if ((borderType & BORDER_ISOLATED) == 0 && _src.isSubmatrix()) + return false; + int type = _src.type(); Size size = _src.size(); diff --git a/modules/imgproc/test/ocl/test_filters.cpp b/modules/imgproc/test/ocl/test_filters.cpp index 0c4564e5ac..f92cc785a1 100644 --- a/modules/imgproc/test/ocl/test_filters.cpp +++ b/modules/imgproc/test/ocl/test_filters.cpp @@ -225,7 +225,7 @@ OCL_TEST_P(GaussianBlurTest, Mat) OCL_OFF(cv::GaussianBlur(src_roi, dst_roi, Size(ksize, ksize), sigma1, sigma2, borderType)); OCL_ON(cv::GaussianBlur(usrc_roi, udst_roi, Size(ksize, ksize), sigma1, sigma2, borderType)); - Near(CV_MAT_DEPTH(type) >= CV_32F ? 7e-5 : 1, false); + Near(CV_MAT_DEPTH(type) >= CV_32F ? 1e-3 : 4, CV_MAT_DEPTH(type) >= CV_32F); } } From b12286329fdc8b5c840a6c310f44271240a62aca Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 4 Aug 2016 18:05:39 +0300 Subject: [PATCH 025/178] imgproc: sepFilter: update OpenCL condition Problem is observed with test_loop_times=100 in corner cases like 93x1 or similar --- modules/imgproc/src/filter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 50b38094a9..1a7f27af3b 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -5019,7 +5019,7 @@ void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, InputArray _kernelX, InputArray _kernelY, Point anchor, double delta, int borderType ) { - CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2, + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && (size_t)_src.rows() > _kernelY.total() && (size_t)_src.cols() > _kernelX.total(), ocl_sepFilter2D(_src, _dst, ddepth, _kernelX, _kernelY, anchor, delta, borderType)) Mat src = _src.getMat(), kernelX = _kernelX.getMat(), kernelY = _kernelY.getMat(); From 2db2d137ce3cc63d391fbb32a7dd808a58ce05b0 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Mon, 1 Aug 2016 18:42:09 +0900 Subject: [PATCH 026/178] follow the naming rule as other API * stop using 'CUDA' prefix * add explanation --- modules/core/include/opencv2/core/cuda.hpp | 9 ++++++++- modules/core/src/cuda/gpu_mat.cu | 2 +- modules/cudev/test/test_cvt.cu | 12 ++++++------ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/modules/core/include/opencv2/core/cuda.hpp b/modules/core/include/opencv2/core/cuda.hpp index 0f7bf01c73..295f3de85e 100644 --- a/modules/core/include/opencv2/core/cuda.hpp +++ b/modules/core/include/opencv2/core/cuda.hpp @@ -855,7 +855,14 @@ private: CV_EXPORTS void printCudaDeviceInfo(int device); CV_EXPORTS void printShortCudaDeviceInfo(int device); -CV_EXPORTS void convertFp16Cuda(InputArray _src, OutputArray _dst, Stream& stream = Stream::Null()); +/** @brief Converts an array to half precision floating number. + +@param _src input array. +@param _dst output array. +@param stream Stream for the asynchronous version. +@sa convertFp16 +*/ +CV_EXPORTS void convertFp16(InputArray _src, OutputArray _dst, Stream& stream = Stream::Null()); //! @} cudacore_init diff --git a/modules/core/src/cuda/gpu_mat.cu b/modules/core/src/cuda/gpu_mat.cu index a772e43abc..987de9e7c5 100644 --- a/modules/core/src/cuda/gpu_mat.cu +++ b/modules/core/src/cuda/gpu_mat.cu @@ -594,7 +594,7 @@ void cv::cuda::GpuMat::convertTo(OutputArray _dst, int rtype, double alpha, doub funcs[sdepth][ddepth](reshape(1), dst.reshape(1), alpha, beta, stream); } -void cv::cuda::convertFp16Cuda(InputArray _src, OutputArray _dst, Stream& stream) +void cv::cuda::convertFp16(InputArray _src, OutputArray _dst, Stream& stream) { GpuMat src = _src.getGpuMat(); int ddepth = 0; diff --git a/modules/cudev/test/test_cvt.cu b/modules/cudev/test/test_cvt.cu index 4e11b6319c..c659525971 100644 --- a/modules/cudev/test/test_cvt.cu +++ b/modules/cudev/test/test_cvt.cu @@ -101,11 +101,11 @@ public: GpuMat g_dst; // Fp32 -> Fp16 - convertFp16Cuda(g_src, g_dst); - convertFp16Cuda(g_dst.clone(), g_dst); + cuda::convertFp16(g_src, g_dst); + cv::convertFp16(src, dst); // Fp16 -> Fp32 - convertFp16(src, dst); - convertFp16(dst, ref); + cuda::convertFp16(g_dst.clone(), g_dst); + cv::convertFp16(dst, ref); g_dst.download(dst); EXPECT_MAT_NEAR(dst, ref, 0.0); @@ -127,8 +127,8 @@ public: GpuMat g_dst; // Fp32 -> Fp16 - convertFp16Cuda(g_src, g_dst); - convertFp16(src, ref); + cuda::convertFp16(g_src, g_dst); + cv::convertFp16(src, ref); g_dst.download(dst); EXPECT_MAT_NEAR(dst, ref, 0.0); From 5f30a0a076e57c412509becd1fb618170cbfa179 Mon Sep 17 00:00:00 2001 From: mschoeneck Date: Fri, 5 Aug 2016 16:20:56 +0200 Subject: [PATCH 027/178] Merge pull request #6958 from mschoeneck:Common-Canny-parallelization * Common Canny parallelization added. TBB and single thread code removed. Final pass vectorized with SSE2 intrinsics. * wrong #ifdef replaced with #if * Merged to actual Canny version * Merged common parallelized Canny with actual Canny implementation * Remove 'Mutex *mutex' and pass 'Mutex mutex' from outside to parallelCanny * Replaced extern Mutex with intern mutable Mutex. --- modules/imgproc/src/canny.cpp | 245 ++++++++++++++++++++++------------ 1 file changed, 163 insertions(+), 82 deletions(-) diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 5ba15a3ffe..8d1f20552c 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -42,6 +42,7 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" +#include #ifdef _MSC_VER #pragma warning( disable: 4127 ) // conditional expression is constant @@ -276,25 +277,22 @@ static bool ocl_Canny(InputArray _src, const UMat& dx_, const UMat& dy_, OutputA #endif -#ifdef HAVE_TBB - -// Queue with peaks that will processed serially. -static tbb::concurrent_queue borderPeaks; - -class tbbCanny +class parallelCanny : public ParallelLoopBody { -public: - tbbCanny(const Range _boundaries, const Mat& _src, uchar* _map, int _low, - int _high, int _aperture_size, bool _L2gradient) - : boundaries(_boundaries), src(_src), map(_map), low(_low), high(_high), - aperture_size(_aperture_size), L2gradient(_L2gradient) - {} - // This parallel version of Canny algorithm splits the src image in threadsNumber horizontal slices. - // The first row of each slice contains the last row of the previous slice and - // the last row of each slice contains the first row of the next slice - // so that each slice is independent and no mutexes are required. - void operator()() const +public: + parallelCanny(const Mat& _src, uchar* _map, int _low, int _high, int _aperture_size, bool _L2gradient, std::queue *borderPeaksParallel) : + src(_src), map(_map), low(_low), high(_high), aperture_size(_aperture_size), L2gradient(_L2gradient), _borderPeaksParallel(borderPeaksParallel) + { + } + + ~parallelCanny() + { + } + + parallelCanny& operator=(const parallelCanny&) { return *this; } + + void operator()(const Range &boundaries) const { #if CV_SSE2 bool haveSSE2 = checkHardwareSupport(CV_CPU_SSE2); @@ -303,13 +301,19 @@ public: const int type = src.type(), cn = CV_MAT_CN(type); Mat dx, dy; + std::queue borderPeaksLocal; ptrdiff_t mapstep = src.cols + 2; // In sobel transform we calculate ksize2 extra lines for the first and last rows of each slice // because IPPDerivSobel expects only isolated ROIs, in contrast with the opencv version which // uses the pixels outside of the ROI to form a border. - uchar ksize2 = aperture_size / 2; + int ksize2 = aperture_size / 2; + // If Scharr filter: aperture_size is 3 and ksize2 is 1 + if(aperture_size == -1) + { + ksize2 = 1; + } if (boundaries.start == 0 && boundaries.end == src.rows) { @@ -408,14 +412,20 @@ public: { __m128i v_dx = _mm_loadu_si128((const __m128i *)(_dx + j)); __m128i v_dy = _mm_loadu_si128((const __m128i *)(_dy + j)); - v_dx = _mm_max_epi16(v_dx, _mm_sub_epi16(v_zero, v_dx)); - v_dy = _mm_max_epi16(v_dy, _mm_sub_epi16(v_zero, v_dy)); - __m128i v_norm = _mm_add_epi32(_mm_unpacklo_epi16(v_dx, v_zero), _mm_unpacklo_epi16(v_dy, v_zero)); - _mm_storeu_si128((__m128i *)(_norm + j), v_norm); + __m128i v_dx_abs = _mm_max_epi16(v_dx, _mm_sub_epi16(v_zero, v_dx)); + __m128i v_dy_abs = _mm_max_epi16(v_dy, _mm_sub_epi16(v_zero, v_dy)); - v_norm = _mm_add_epi32(_mm_unpackhi_epi16(v_dx, v_zero), _mm_unpackhi_epi16(v_dy, v_zero)); - _mm_storeu_si128((__m128i *)(_norm + j + 4), v_norm); + __m128i v_dx_ml = _mm_unpacklo_epi16(v_dx_abs, v_zero); + __m128i v_dy_ml = _mm_unpacklo_epi16(v_dy_abs, v_zero); + __m128i v_dx_mh = _mm_unpackhi_epi16(v_dx_abs, v_zero); + __m128i v_dy_mh = _mm_unpackhi_epi16(v_dy_abs, v_zero); + + __m128i v_norm_ml = _mm_add_epi32(v_dx_ml, v_dy_ml); + __m128i v_norm_mh = _mm_add_epi32(v_dx_mh, v_dy_mh); + + _mm_storeu_si128((__m128i *)(_norm + j), v_norm_ml); + _mm_storeu_si128((__m128i *)(_norm + j + 4), v_norm_mh); } } #elif CV_NEON @@ -444,8 +454,10 @@ public: __m128i v_dx_dy_ml = _mm_unpacklo_epi16(v_dx, v_dy); __m128i v_dx_dy_mh = _mm_unpackhi_epi16(v_dx, v_dy); + __m128i v_norm_ml = _mm_madd_epi16(v_dx_dy_ml, v_dx_dy_ml); __m128i v_norm_mh = _mm_madd_epi16(v_dx_dy_mh, v_dx_dy_mh); + _mm_storeu_si128((__m128i *)(_norm + j), v_norm_ml); _mm_storeu_si128((__m128i *)(_norm + j + 4), v_norm_mh); } @@ -508,13 +520,13 @@ public: #define CANNY_PUSH(d) *(d) = uchar(2), *stack_top++ = (d) #define CANNY_POP(d) (d) = *--stack_top +#define CANNY_SHIFT 15 + const int TG22 = (int)(0.4142135623730950488016887242097*(1 << CANNY_SHIFT) + 0.5); + int prev_flag = 0; bool canny_push = false; for (int j = 0; j < src.cols; j++) { - #define CANNY_SHIFT 15 - const int TG22 = (int)(0.4142135623730950488016887242097*(1< low) @@ -592,7 +604,7 @@ public: // slice in a queue to be serially processed later. if ( (m < map + (boundaries.start + 2) * mapstep) || (m >= map + boundaries.end * mapstep) ) { - borderPeaks.push(m); + borderPeaksLocal.push(m); continue; } @@ -605,20 +617,103 @@ public: if (!m[mapstep]) CANNY_PUSH(m + mapstep); if (!m[mapstep+1]) CANNY_PUSH(m + mapstep + 1); } + + AutoLock lock(mutex); + while (!borderPeaksLocal.empty()) { + _borderPeaksParallel->push(borderPeaksLocal.front()); + borderPeaksLocal.pop(); + } } private: - const Range boundaries; const Mat& src; uchar* map; - int low; - int high; - int aperture_size; + int low, high, aperture_size; bool L2gradient; + std::queue *_borderPeaksParallel; + mutable Mutex mutex; }; +class finalPass : public ParallelLoopBody +{ + +public: + finalPass(const Mat & _src, Mat &_dst, uchar *_map, ptrdiff_t _mapstep) : + src(_src), dst(_dst), map(_map), mapstep(_mapstep) {} + + ~finalPass() {} + + finalPass& operator=(const finalPass&) {return *this;} + + void operator()(const Range &boundaries) const + { + // the final pass, form the final image + const uchar* pmap = map + mapstep + 1 + (ptrdiff_t)(mapstep * boundaries.start); + uchar* pdst = dst.ptr() + (ptrdiff_t)(dst.step * boundaries.start); + +#if CV_SSE2 + bool haveSSE2 = checkHardwareSupport(CV_CPU_SSE2); #endif + for (int i = boundaries.start; i < boundaries.end; i++, pmap += mapstep, pdst += dst.step) + { + int j = 0; +#if CV_SSE2 + if(haveSSE2) { + const __m128i v_zero = _mm_setzero_si128(); + + for(; j <= src.cols - 32; j += 32) { + __m128i v_pmap1 = _mm_loadu_si128((const __m128i*)(pmap + j)); + __m128i v_pmap2 = _mm_loadu_si128((const __m128i*)(pmap + j + 16)); + + __m128i v_pmaplo1 = _mm_unpacklo_epi8(v_pmap1, v_zero); + __m128i v_pmaphi1 = _mm_unpackhi_epi8(v_pmap1, v_zero); + __m128i v_pmaplo2 = _mm_unpacklo_epi8(v_pmap2, v_zero); + __m128i v_pmaphi2 = _mm_unpackhi_epi8(v_pmap2, v_zero); + + v_pmaplo1 = _mm_srli_epi16(v_pmaplo1, 1); + v_pmaphi1 = _mm_srli_epi16(v_pmaphi1, 1); + v_pmaplo2 = _mm_srli_epi16(v_pmaplo2, 1); + v_pmaphi2 = _mm_srli_epi16(v_pmaphi2, 1); + + v_pmap1 = _mm_packus_epi16(v_pmaplo1, v_pmaphi1); + v_pmap2 = _mm_packus_epi16(v_pmaplo2, v_pmaphi2); + + v_pmap1 = _mm_sub_epi8(v_zero, v_pmap1); + v_pmap2 = _mm_sub_epi8(v_zero, v_pmap2); + + _mm_storeu_si128((__m128i*)(pdst + j), v_pmap1); + _mm_storeu_si128((__m128i*)(pdst + j + 16), v_pmap2); + } + + for(; j <= src.cols - 16; j += 16) { + __m128i v_pmap = _mm_loadu_si128((const __m128i*)(pmap + j)); + + __m128i v_pmaplo = _mm_unpacklo_epi8(v_pmap, v_zero); + __m128i v_pmaphi = _mm_unpackhi_epi8(v_pmap, v_zero); + + v_pmaplo = _mm_srli_epi16(v_pmaplo, 1); + v_pmaphi = _mm_srli_epi16(v_pmaphi, 1); + + v_pmap = _mm_packus_epi16(v_pmaplo, v_pmaphi); + v_pmap = _mm_sub_epi8(v_zero, v_pmap); + + _mm_storeu_si128((__m128i*)(pdst + j), v_pmap); + } + } +#endif + for (; j < src.cols; j++) + pdst[j] = (uchar)-(pmap[j] >> 1); + } + } + +private: + const Mat &src; + Mat &dst; + uchar *map; + ptrdiff_t mapstep; +}; + void Canny( InputArray _src, OutputArray _dst, double low_thresh, double high_thresh, int aperture_size, bool L2gradient ) @@ -654,8 +749,6 @@ void Canny( InputArray _src, OutputArray _dst, CV_IPP_RUN(USE_IPP_CANNY && (aperture_size == 3 && !L2gradient && 1 == cn), ippCanny(src, Mat(), Mat(), dst, (float)low_thresh, (float)high_thresh)) -#ifdef HAVE_TBB - if (L2gradient) { low_thresh = std::min(32767.0, low_thresh); @@ -667,44 +760,49 @@ if (L2gradient) int low = cvFloor(low_thresh); int high = cvFloor(high_thresh); -ptrdiff_t mapstep = src.cols + 2; -AutoBuffer buffer((src.cols+2)*(src.rows+2)); + ptrdiff_t mapstep = src.cols + 2; + AutoBuffer buffer((src.cols+2)*(src.rows+2) + cn * mapstep * 3 * sizeof(int)); -uchar* map = (uchar*)buffer; -memset(map, 1, mapstep); -memset(map + mapstep*(src.rows + 1), 1, mapstep); + int* mag_buf[3]; + mag_buf[0] = (int*)(uchar*)buffer; + mag_buf[1] = mag_buf[0] + mapstep*cn; + mag_buf[2] = mag_buf[1] + mapstep*cn; + memset(mag_buf[0], 0, /* cn* */mapstep*sizeof(int)); -int threadsNumber = tbb::task_scheduler_init::default_num_threads(); -int grainSize = src.rows / threadsNumber; + uchar *map = (uchar*)(mag_buf[2] + mapstep*cn); + memset(map, 1, mapstep); + memset(map + mapstep*(src.rows + 1), 1, mapstep); -// Make a fallback for pictures with too few rows. -uchar ksize2 = aperture_size / 2; -int minGrainSize = 1 + ksize2; -int maxGrainSize = src.rows - 2 - 2*ksize2; -if ( !( minGrainSize <= grainSize && grainSize <= maxGrainSize ) ) -{ - threadsNumber = 1; - grainSize = src.rows; -} + // Minimum number of threads should be 1, maximum should not exceed number of CPU's, because of overhead + int numOfThreads = std::max(1, std::min(getNumThreads(), getNumberOfCPUs())); -tbb::task_group g; + // Make a fallback for pictures with too few rows. + int grainSize = src.rows / numOfThreads; + int ksize2 = aperture_size / 2; + // If Scharr filter: aperture size is 3, ksize2 is 1 + if(aperture_size == -1) + { + ksize2 = 1; + } -for (int i = 0; i < threadsNumber; ++i) -{ - if (i < threadsNumber - 1) - g.run(tbbCanny(Range(i * grainSize, (i + 1) * grainSize), src, map, low, high, aperture_size, L2gradient)); - else - g.run(tbbCanny(Range(i * grainSize, src.rows), src, map, low, high, aperture_size, L2gradient)); -} + int minGrainSize = 2 * (ksize2 + 1); + if (grainSize < minGrainSize) + { + numOfThreads = std::max(1, src.rows / minGrainSize); + } -g.wait(); + std::queue borderPeaksParallel; -#define CANNY_PUSH_SERIAL(d) *(d) = uchar(2), borderPeaks.push(d) + parallel_for_(Range(0, src.rows), parallelCanny(src, map, low, high, aperture_size, L2gradient, &borderPeaksParallel), numOfThreads); -// now track the edges (hysteresis thresholding) -uchar* m; -while (borderPeaks.try_pop(m)) -{ +#define CANNY_PUSH_SERIAL(d) *(d) = uchar(2), borderPeaksParallel.push(d) + + // now track the edges (hysteresis thresholding) + uchar* m; + while (!borderPeaksParallel.empty()) + { + m = borderPeaksParallel.front(); + borderPeaksParallel.pop(); if (!m[-1]) CANNY_PUSH_SERIAL(m - 1); if (!m[1]) CANNY_PUSH_SERIAL(m + 1); if (!m[-mapstep-1]) CANNY_PUSH_SERIAL(m - mapstep - 1); @@ -715,24 +813,7 @@ while (borderPeaks.try_pop(m)) if (!m[mapstep+1]) CANNY_PUSH_SERIAL(m + mapstep + 1); } -// the final pass, form the final image -const uchar* pmap = map + mapstep + 1; -uchar* pdst = dst.ptr(); -for (int i = 0; i < src.rows; i++, pmap += mapstep, pdst += dst.step) -{ - for (int j = 0; j < src.cols; j++) - pdst[j] = (uchar)-(pmap[j] >> 1); -} - -#else - Mat dx(src.rows, src.cols, CV_16SC(cn)); - Mat dy(src.rows, src.cols, CV_16SC(cn)); - - Sobel(src, dx, CV_16S, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE); - Sobel(src, dy, CV_16S, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE); - - CannyImpl(dx, dy, dst, low_thresh, high_thresh, L2gradient); -#endif + parallel_for_(Range(0, src.rows), finalPass(src, dst, map, mapstep), src.total()/(double)(1<<16)); } void Canny( InputArray _dx, InputArray _dy, OutputArray _dst, From c2e5418e519bdd45bf5fca71aab15c29d22e71a1 Mon Sep 17 00:00:00 2001 From: will hunt Date: Sat, 6 Aug 2016 12:24:16 +0800 Subject: [PATCH 028/178] MSER: off-by-one bug --- modules/features2d/src/mser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/features2d/src/mser.cpp b/modules/features2d/src/mser.cpp index 1143addc12..076f9e15e2 100644 --- a/modules/features2d/src/mser.cpp +++ b/modules/features2d/src/mser.cpp @@ -390,7 +390,7 @@ public: int step = cols; for( i = 1; i < rows-1; i++ ) { - Pixel* pptr = &pixbuf[i*step + 1]; + Pixel* pptr = &pixbuf[i*step]; for( j = 1; j < cols-1; j++ ) { pptr[j].val = 0; From c3d2921971551ba8cfdc63d65378cf014dfd004b Mon Sep 17 00:00:00 2001 From: will hunt Date: Sat, 6 Aug 2016 12:27:43 +0800 Subject: [PATCH 029/178] MSER: grew unnecessary histories. the merge() calls growHistory() too many times such that: 1. some CompHistory nodes not used have been created 2. some CompHistory node's val equal their parents --- modules/features2d/src/mser.cpp | 57 ++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/modules/features2d/src/mser.cpp b/modules/features2d/src/mser.cpp index 076f9e15e2..669e3877d8 100644 --- a/modules/features2d/src/mser.cpp +++ b/modules/features2d/src/mser.cpp @@ -270,12 +270,20 @@ public: if( !history || (history->size != size && size > 0 && (gray_level != history->val || force))) { - CompHistory* h = hptr++; - h->parent_ = 0; - h->child_ = history; - h->next_ = 0; - if( history ) - history->parent_ = h; + CompHistory* h; + + if (history && gray_level == history->val) + h = history; + else + { + h = hptr++; + h->parent_ = 0; + h->child_ = history; + h->next_ = 0; + if (history) + history->parent_ = h; + } + h->val = gray_level; h->size = size; h->head = head; @@ -283,7 +291,7 @@ public: history = h; h->var = FLT_MAX; h->checked = true; - if( h->size >= wp.p.minArea ) + if (h->size >= wp.p.minArea) { h->var = -1.f; h->checked = false; @@ -291,7 +299,7 @@ public: } } gray_level = new_gray_level; - if( update && history ) + if( update && history && gray_level != history->val ) history->updateTree(wp, 0, 0, final); } @@ -299,14 +307,13 @@ public: void merge( ConnectedComp* comp1, ConnectedComp* comp2, CompHistory*& hptr, WParams& wp ) { - comp1->growHistory( hptr, wp, -1, false ); - comp2->growHistory( hptr, wp, -1, false ); - if( comp1->size < comp2->size ) std::swap(comp1, comp2); if( comp2->size == 0 ) { + // only grow comp1's history + comp1->growHistory(hptr, wp, -1, false); gray_level = comp1->gray_level; head = comp1->head; tail = comp1->tail; @@ -315,21 +322,35 @@ public: return; } - CompHistory* h1 = comp1->history; - CompHistory* h2 = comp2->history; + comp1->growHistory( hptr, wp, -1, false ); + comp2->growHistory( hptr, wp, -1, false ); - gray_level = std::max(comp1->gray_level, comp2->gray_level); + if (comp1->gray_level < comp2->gray_level) + std::swap(comp1, comp2); + + gray_level = comp1->gray_level; history = comp1->history; wp.pix0[comp1->tail].setNext(comp2->head); head = comp1->head; tail = comp2->tail; size = comp1->size + comp2->size; - bool keep_2nd = h2->size > wp.p.minArea; - growHistory( hptr, wp, -1, false, keep_2nd ); - if( keep_2nd ) + + CompHistory *h1 = history->child_; + CompHistory *h2 = comp2->history; + if (h2->size > wp.p.minArea) { - h1->next_ = h2; + // the child_'s size should be the large one + if (h1 && h1->size > h2->size) + { + h2->next_ = h1->next_; + h1->next_ = h2; + } + else + { + history->child_ = h2; + h2->next_ = h1; + } h2->parent_ = history; } } From 74b899d8b0103803012f969932c485ff05d99d25 Mon Sep 17 00:00:00 2001 From: catree Date: Mon, 8 Aug 2016 03:31:31 +0200 Subject: [PATCH 030/178] Modify the figure of the pinhole camera model with pixels starting from the uv axis. --- .../calib3d/doc/pics/pinhole_camera_model.png | Bin 92095 -> 97238 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/modules/calib3d/doc/pics/pinhole_camera_model.png b/modules/calib3d/doc/pics/pinhole_camera_model.png index daa7e39d8211b255493264e2506b432f08d4e0ca..3594de9684da817e29a229a0824988872a8a5823 100644 GIT binary patch literal 97238 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 Vb*d4$tL(X~CS7rik{qQY8MY4f?l!9N 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

3Fp99sUYvJ_$Ibn*Cg2uUO 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 From d2a1994d710fa24c83b0b568ba9521a2f3d07bbb Mon Sep 17 00:00:00 2001 From: berak Date: Sun, 7 Aug 2016 15:59:11 +0200 Subject: [PATCH 031/178] python docs: fix missing output image in cv2.drawKeypoint examples --- doc/py_tutorials/py_feature2d/py_fast/py_fast.markdown | 4 ++-- doc/py_tutorials/py_feature2d/py_orb/py_orb.markdown | 4 ++-- .../py_feature2d/py_sift_intro/py_sift_intro.markdown | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/py_tutorials/py_feature2d/py_fast/py_fast.markdown b/doc/py_tutorials/py_feature2d/py_fast/py_fast.markdown index 1534c57ac7..191f42e0b5 100644 --- a/doc/py_tutorials/py_feature2d/py_fast/py_fast.markdown +++ b/doc/py_tutorials/py_feature2d/py_fast/py_fast.markdown @@ -105,7 +105,7 @@ fast = cv2.FastFeatureDetector_create() # find and draw the keypoints kp = fast.detect(img,None) -img2 = cv2.drawKeypoints(img, kp, color=(255,0,0)) +img2 = cv2.drawKeypoints(img, kp, None, color=(255,0,0)) # Print all default params print "Threshold: ", fast.getInt('threshold') @@ -121,7 +121,7 @@ kp = fast.detect(img,None) print "Total Keypoints without nonmaxSuppression: ", len(kp) -img3 = cv2.drawKeypoints(img, kp, color=(255,0,0)) +img3 = cv2.drawKeypoints(img, kp, None, color=(255,0,0)) cv2.imwrite('fast_false.png',img3) @endcode diff --git a/doc/py_tutorials/py_feature2d/py_orb/py_orb.markdown b/doc/py_tutorials/py_feature2d/py_orb/py_orb.markdown index c1917eb1a5..49c558a5ec 100644 --- a/doc/py_tutorials/py_feature2d/py_orb/py_orb.markdown +++ b/doc/py_tutorials/py_feature2d/py_orb/py_orb.markdown @@ -79,8 +79,8 @@ kp = orb.detect(img,None) kp, des = orb.compute(img, kp) # draw only keypoints location,not size and orientation -img2 = cv2.drawKeypoints(img,kp,color=(0,255,0), flags=0) -plt.imshow(img2),plt.show() +img2 = cv2.drawKeypoints(img, kp, None, color=(0,255,0), flags=0) +plt.imshow(img2), plt.show() @endcode See the result below: diff --git a/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown b/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown index da4b878db0..2b4b516c50 100644 --- a/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown +++ b/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown @@ -122,7 +122,7 @@ gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) sift = cv2.xfeatures2d.SIFT_create() kp = sift.detect(gray,None) -img=cv2.drawKeypoints(gray,kp) +img=cv2.drawKeypoints(gray,kp,img) cv2.imwrite('sift_keypoints.jpg',img) @endcode @@ -135,7 +135,7 @@ OpenCV also provides **cv2.drawKeyPoints()** function which draws the small circ of keypoints. If you pass a flag, **cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS** to it, it will draw a circle with size of keypoint and it will even show its orientation. See below example. @code{.py} -img=cv2.drawKeypoints(gray,kp,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) +img=cv2.drawKeypoints(gray,kp,img,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) cv2.imwrite('sift_keypoints.jpg',img) @endcode See the two results below: From 46c8b094530b1722bd4a56cb376a59c09c098212 Mon Sep 17 00:00:00 2001 From: Vladislav Sovrasov Date: Thu, 4 Aug 2016 14:10:15 +0300 Subject: [PATCH 032/178] Improvements in camera_calibration tutorial code --- .../camera_calibration/camera_calibration.cpp | 100 ++++++++++++------ .../calib3d/camera_calibration/in_VID5.xml | 13 ++- 2 files changed, 81 insertions(+), 32 deletions(-) diff --git a/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp b/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp index 580fe73792..b5647b5ebc 100644 --- a/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp +++ b/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp @@ -1,7 +1,8 @@ #include #include -#include -#include +#include +#include +#include #include #include @@ -11,10 +12,6 @@ #include #include -#ifndef _CRT_SECURE_NO_WARNINGS -# define _CRT_SECURE_NO_WARNINGS -#endif - using namespace cv; using namespace std; @@ -73,6 +70,12 @@ public: node["Show_UndistortedImage"] >> showUndistorsed; node["Input"] >> input; node["Input_Delay"] >> delay; + node["Fix_K1"] >> fixK1; + node["Fix_K2"] >> fixK2; + node["Fix_K3"] >> fixK3; + node["Fix_K4"] >> fixK4; + node["Fix_K5"] >> fixK5; + validate(); } void validate() @@ -127,16 +130,23 @@ public: goodInput = false; } - flag = CALIB_FIX_K4 | CALIB_FIX_K5; + flag = 0; if(calibFixPrincipalPoint) flag |= CALIB_FIX_PRINCIPAL_POINT; if(calibZeroTangentDist) flag |= CALIB_ZERO_TANGENT_DIST; if(aspectRatio) flag |= CALIB_FIX_ASPECT_RATIO; + if(fixK1) flag |= CALIB_FIX_K1; + if(fixK2) flag |= CALIB_FIX_K2; + if(fixK3) flag |= CALIB_FIX_K3; + if(fixK4) flag |= CALIB_FIX_K4; + if(fixK5) flag |= CALIB_FIX_K5; if (useFisheye) { // the fisheye model has its own enum, so overwrite the flags - flag = fisheye::CALIB_FIX_SKEW | fisheye::CALIB_RECOMPUTE_EXTRINSIC | - // fisheye::CALIB_FIX_K1 | - fisheye::CALIB_FIX_K2 | fisheye::CALIB_FIX_K3 | fisheye::CALIB_FIX_K4; + flag = fisheye::CALIB_FIX_SKEW | fisheye::CALIB_RECOMPUTE_EXTRINSIC; + if(fixK1) flag |= fisheye::CALIB_FIX_K1; + if(fixK2) flag |= fisheye::CALIB_FIX_K2; + if(fixK3) flag |= fisheye::CALIB_FIX_K3; + if(fixK4) flag |= fisheye::CALIB_FIX_K4; } calibrationPattern = NOT_EXISTING; @@ -196,6 +206,11 @@ public: bool showUndistorsed; // Show undistorted images after calibration string input; // The input -> bool useFisheye; // use fisheye camera model for calibration + bool fixK1; // fix K1 distortion coefficient + bool fixK2; // fix K2 distortion coefficient + bool fixK3; // fix K3 distortion coefficient + bool fixK4; // fix K4 distortion coefficient + bool fixK5; // fix K5 distortion coefficient int cameraID; vector imageList; @@ -369,7 +384,10 @@ int main(int argc, char* argv[]) if( mode == CALIBRATED && s.showUndistorsed ) { Mat temp = view.clone(); - undistort(temp, view, cameraMatrix, distCoeffs); + if (s.useFisheye) + cv::fisheye::undistortImage(temp, view, cameraMatrix, distCoeffs); + else + undistort(temp, view, cameraMatrix, distCoeffs); } //! [output_undistorted] //------------------------------ Show image and check for input commands ------------------- @@ -567,25 +585,31 @@ static void saveCameraParams( Settings& s, Size& imageSize, Mat& cameraMatrix, M if (s.flag) { + std::stringstream flagsStringStream; if (s.useFisheye) { - sprintf(buf, "flags:%s%s%s%s%s%s", - s.flag & fisheye::CALIB_FIX_SKEW ? " +fix_skew" : "", - s.flag & fisheye::CALIB_FIX_K1 ? " +fix_k1" : "", - s.flag & fisheye::CALIB_FIX_K2 ? " +fix_k2" : "", - s.flag & fisheye::CALIB_FIX_K3 ? " +fix_k3" : "", - s.flag & fisheye::CALIB_FIX_K4 ? " +fix_k4" : "", - s.flag & fisheye::CALIB_RECOMPUTE_EXTRINSIC ? " +recompute_extrinsic" : ""); + flagsStringStream << "flags:" + << (s.flag & fisheye::CALIB_FIX_SKEW ? " +fix_skew" : "") + << (s.flag & fisheye::CALIB_FIX_K1 ? " +fix_k1" : "") + << (s.flag & fisheye::CALIB_FIX_K2 ? " +fix_k2" : "") + << (s.flag & fisheye::CALIB_FIX_K3 ? " +fix_k3" : "") + << (s.flag & fisheye::CALIB_FIX_K4 ? " +fix_k4" : "") + << (s.flag & fisheye::CALIB_RECOMPUTE_EXTRINSIC ? " +recompute_extrinsic" : ""); } else { - sprintf(buf, "flags:%s%s%s%s", - s.flag & CALIB_USE_INTRINSIC_GUESS ? " +use_intrinsic_guess" : "", - s.flag & CALIB_FIX_ASPECT_RATIO ? " +fix_aspectRatio" : "", - s.flag & CALIB_FIX_PRINCIPAL_POINT ? " +fix_principal_point" : "", - s.flag & CALIB_ZERO_TANGENT_DIST ? " +zero_tangent_dist" : ""); + flagsStringStream << "flags:" + << (s.flag & CALIB_USE_INTRINSIC_GUESS ? " +use_intrinsic_guess" : "") + << (s.flag & CALIB_FIX_ASPECT_RATIO ? " +fix_aspectRatio" : "") + << (s.flag & CALIB_FIX_PRINCIPAL_POINT ? " +fix_principal_point" : "") + << (s.flag & CALIB_ZERO_TANGENT_DIST ? " +zero_tangent_dist" : "") + << (s.flag & CALIB_FIX_K1 ? " +fix_k1" : "") + << (s.flag & CALIB_FIX_K2 ? " +fix_k2" : "") + << (s.flag & CALIB_FIX_K3 ? " +fix_k3" : "") + << (s.flag & CALIB_FIX_K4 ? " +fix_k4" : "") + << (s.flag & CALIB_FIX_K5 ? " +fix_k5" : ""); } - cvWriteComment(*fs, buf, 0); + fs.writeComment(flagsStringStream.str()); } fs << "flags" << s.flag; @@ -602,19 +626,33 @@ static void saveCameraParams( Settings& s, Size& imageSize, Mat& cameraMatrix, M if(s.writeExtrinsics && !rvecs.empty() && !tvecs.empty() ) { CV_Assert(rvecs[0].type() == tvecs[0].type()); - Mat bigmat((int)rvecs.size(), 6, rvecs[0].type()); + Mat bigmat((int)rvecs.size(), 6, CV_MAKETYPE(rvecs[0].type(), 1)); + bool needReshapeR = rvecs[0].depth() != 1 ? true : false; + bool needReshapeT = tvecs[0].depth() != 1 ? true : false; + for( size_t i = 0; i < rvecs.size(); i++ ) { Mat r = bigmat(Range(int(i), int(i+1)), Range(0,3)); Mat t = bigmat(Range(int(i), int(i+1)), Range(3,6)); - CV_Assert(rvecs[i].rows == 3 && rvecs[i].cols == 1); - CV_Assert(tvecs[i].rows == 3 && tvecs[i].cols == 1); - //*.t() is MatExpr (not Mat) so we can use assignment operator - r = rvecs[i].t(); - t = tvecs[i].t(); + if(needReshapeR) + rvecs[i].reshape(1, 1).copyTo(r); + else + { + //*.t() is MatExpr (not Mat) so we can use assignment operator + CV_Assert(rvecs[i].rows == 3 && rvecs[i].cols == 1); + r = rvecs[i].t(); + } + + if(needReshapeT) + tvecs[i].reshape(1, 1).copyTo(t); + else + { + CV_Assert(tvecs[i].rows == 3 && tvecs[i].cols == 1); + t = tvecs[i].t(); + } } - //cvWriteComment( *fs, "a set of 6-tuples (rotation vector + translation vector) for each view", 0 ); + fs.writeComment("a set of 6-tuples (rotation vector + translation vector) for each view"); fs << "extrinsic_parameters" << bigmat; } diff --git a/samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml b/samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml index 98269ecb6e..5659651e6c 100644 --- a/samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml +++ b/samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml @@ -41,6 +41,17 @@ 1 1 - + + 0 + + 0 + + 0 + + 0 + + 1 + + 1 From 2ad411f9147479988b25ce155c89417d04e9f942 Mon Sep 17 00:00:00 2001 From: StevenPuttemans Date: Mon, 8 Aug 2016 12:12:35 +0200 Subject: [PATCH 033/178] fixing issues --- include/opencv2/opencv.hpp | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/include/opencv2/opencv.hpp b/include/opencv2/opencv.hpp index ddcadc7210..93a87bc27f 100644 --- a/include/opencv2/opencv.hpp +++ b/include/opencv2/opencv.hpp @@ -56,42 +56,6 @@ #ifdef HAVE_OPENCV_CALIB3D #include "opencv2/calib3d.hpp" #endif -#ifdef HAVE_OPENCV_CUDAARITHM -#include "opencv2/cudaarithm.hpp" -#endif -#ifdef HAVE_OPENCV_CUDABGSEGM -#include "opencv2/cudabgsegm.hpp" -#endif -#ifdef HAVE_OPENCV_CUDACODEC -#include "opencv2/cudacodec.hpp" -#endif -#ifdef HAVE_OPENCV_CUDAFEATURES2D -#include "opencv2/cudafeatures2d.hpp" -#endif -#ifdef HAVE_OPENCV_CUDAFILTERS -#include "opencv2/cudafilters.hpp" -#endif -#ifdef HAVE_OPENCV_CUDAIMGPROC -#include "opencv2/cudaimgproc.hpp" -#endif -#ifdef HAVE_OPENCV_CUDALEGACY -#include "opencv2/cudalegacy.hpp" -#endif -#ifdef HAVE_OPENCV_CUDAOBJDETECT -#include "opencv2/cudaobjdetect.hpp" -#endif -#ifdef HAVE_OPENCV_CUDAOPTFLOW -#include "opencv2/cudaoptflow.hpp" -#endif -#ifdef HAVE_OPENCV_CUDASTEREO -#include "opencv2/cudastereo.hpp" -#endif -#ifdef HAVE_OPENCV_CUDAWARPING -#include "opencv2/cudawarping.hpp" -#endif -#ifdef HAVE_OPENCV_CUDEV -#include "opencv2/cudev.hpp" -#endif #ifdef HAVE_OPENCV_FEATURES2D #include "opencv2/features2d.hpp" #endif From c61f4e8863a56ff435f279f9575e41fbeec68f1a Mon Sep 17 00:00:00 2001 From: kurenai Date: Mon, 8 Aug 2016 12:24:06 +0800 Subject: [PATCH 034/178] return false from VideoCapture::grabFrame when camera is disconneted --- modules/videoio/src/cap_dshow.cpp | 36 ++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/modules/videoio/src/cap_dshow.cpp b/modules/videoio/src/cap_dshow.cpp index 8b793ac202..8360e4318b 100644 --- a/modules/videoio/src/cap_dshow.cpp +++ b/modules/videoio/src/cap_dshow.cpp @@ -204,6 +204,7 @@ DEFINE_GUID(IID_ICreateDevEnum,0x29840822,0x5b84,0x11d0,0xbd,0x3b,0x00,0xa0,0xc9 DEFINE_GUID(IID_IGraphBuilder,0x56a868a9,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); DEFINE_GUID(IID_IMPEG2PIDMap,0xafb6c2a1,0x2c41,0x11d3,0x8a,0x60,0x00,0x00,0xf8,0x1e,0x0e,0x4a); DEFINE_GUID(IID_IMediaControl,0x56a868b1,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); +DEFINE_GUID(IID_IMediaEventEx, 0x56a868c0,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); DEFINE_GUID(IID_IMediaFilter,0x56a86899,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); DEFINE_GUID(IID_ISampleGrabber,0x6b652fff,0x11fe,0x4fce,0x92,0xad,0x02,0x66,0xb5,0xd7,0xc7,0x8f); DEFINE_GUID(LOOK_UPSTREAM_ONLY,0xac798be0,0x98e3,0x11d1,0xb3,0xf1,0x00,0xaa,0x00,0x37,0x61,0xc5); @@ -573,6 +574,8 @@ class videoInput{ int getVideoPropertyFromCV(int cv_property); int getCameraPropertyFromCV(int cv_property); + bool isDeviceDisconnected(int deviceID); + private: void setPhyCon(int deviceID, int conn); void setAttemptCaptureSize(int deviceID, int w, int h,GUID mediaType=MEDIASUBTYPE_RGB24); @@ -2309,6 +2312,27 @@ int videoInput::getCameraPropertyFromCV(int cv_property){ return -1; } +bool videoInput::isDeviceDisconnected(int deviceNumber) +{ + if (!isDeviceSetup(deviceNumber)) return true; + long evCode; + LONG_PTR param1, param2; + bool disconnected = false; + + while (S_OK == VDList[deviceNumber]->pMediaEvent->GetEvent(&evCode, ¶m1, ¶m2, 0)) + { + DebugPrintOut("Event: Code: %#04x Params: %d, %d\n", evCode, param1, param2); + + VDList[deviceNumber]->pMediaEvent->FreeEventParams(evCode, param1, param2); + if (evCode == EC_DEVICE_LOST) + { + DebugPrintOut("ERROR: Device disconnected\n"); + disconnected = true; + } + } + return disconnected; +} + void videoInput::getCameraPropertyAsString(int prop, char * propertyAsString){ char tmpStr[16]; @@ -2511,6 +2535,16 @@ int videoInput::start(int deviceID, videoDevice *VD){ return hr; } + //MEDIA EVENT// + //Used to obtain event when capture device is disconnected + hr = VD->pGraph->QueryInterface(IID_IMediaEventEx, (void**)&VD->pMediaEvent); + if (FAILED(hr)) + { + DebugPrintOut("ERROR - Could not create media event object\n"); + stopDevice(deviceID); + return hr; + } + //SET THE FILTERGRAPH// hr = VD->pCaptureGraph->SetFiltergraph(VD->pGraph); if (FAILED(hr)) @@ -3309,7 +3343,7 @@ bool VideoCapture_DShow::setProperty(int propIdx, double propVal) bool VideoCapture_DShow::grabFrame() { - return true; + return !g_VI.isDeviceDisconnected(m_index); } bool VideoCapture_DShow::retrieveFrame(int, OutputArray frame) { From e37c53d13e8dc557286a194c3c9d186cc1828abd Mon Sep 17 00:00:00 2001 From: k-shinotsuka Date: Sun, 7 Aug 2016 12:05:27 +0900 Subject: [PATCH 035/178] improve RGB2YCrCb_i() --- modules/imgproc/src/color.cpp | 188 ++++++++++++++++++---------------- 1 file changed, 99 insertions(+), 89 deletions(-) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index b08c608220..af75445e61 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -2174,54 +2174,60 @@ struct RGB2YCrCb_i if (blueIdx==0) std::swap(coeffs[0], coeffs[2]); - v_c0 = _mm_set1_epi32(coeffs[0]); - v_c1 = _mm_set1_epi32(coeffs[1]); - v_c2 = _mm_set1_epi32(coeffs[2]); - v_c3 = _mm_set1_epi32(coeffs[3]); - v_c4 = _mm_set1_epi32(coeffs[4]); - v_delta2 = _mm_set1_epi32(1 << (yuv_shift - 1)); - v_delta = _mm_set1_epi32(ColorChannel::half()*(1 << yuv_shift)); - v_delta = _mm_add_epi32(v_delta, v_delta2); - v_zero = _mm_setzero_si128(); - + short delta = 1 << (yuv_shift - 1); + v_delta_16 = _mm_set1_epi16(delta); + v_delta_32 = _mm_set1_epi32(delta); + short delta2 = 1 + ColorChannel::half() * 2; + v_coeff = _mm_set_epi16(delta2, (short)coeffs[4], delta2, (short)coeffs[3], delta2, (short)coeffs[4], delta2, (short)coeffs[3]); + v_shuffle2 = _mm_set_epi8(0x0, 0x0, 0x0, 0x0, 0xf, 0xe, 0xc, 0xb, 0xa, 0x8, 0x7, 0x6, 0x4, 0x3, 0x2, 0x0); haveSIMD = checkHardwareSupport(CV_CPU_SSE4_1); } // 16u x 8 - void process(__m128i v_r, __m128i v_g, __m128i v_b, - __m128i & v_y, __m128i & v_cr, __m128i & v_cb) const + void process(__m128i* v_rgb, __m128i & v_crgb, + __m128i* v_rb, uchar * dst) const { - __m128i v_r_p = _mm_unpacklo_epi16(v_r, v_zero); - __m128i v_g_p = _mm_unpacklo_epi16(v_g, v_zero); - __m128i v_b_p = _mm_unpacklo_epi16(v_b, v_zero); + v_rgb[0] = _mm_madd_epi16(v_rgb[0], v_crgb); + v_rgb[1] = _mm_madd_epi16(v_rgb[1], v_crgb); + v_rgb[2] = _mm_madd_epi16(v_rgb[2], v_crgb); + v_rgb[3] = _mm_madd_epi16(v_rgb[3], v_crgb); + v_rgb[0] = _mm_hadd_epi32(v_rgb[0], v_rgb[1]); + v_rgb[2] = _mm_hadd_epi32(v_rgb[2], v_rgb[3]); + v_rgb[0] = _mm_add_epi32(v_rgb[0], v_delta_32); + v_rgb[2] = _mm_add_epi32(v_rgb[2], v_delta_32); + v_rgb[0] = _mm_srai_epi32(v_rgb[0], yuv_shift); + v_rgb[2] = _mm_srai_epi32(v_rgb[2], yuv_shift); + __m128i v_y = _mm_packs_epi32(v_rgb[0], v_rgb[2]); - __m128i v_y0 = _mm_add_epi32(_mm_mullo_epi32(v_r_p, v_c0), - _mm_add_epi32(_mm_mullo_epi32(v_g_p, v_c1), - _mm_mullo_epi32(v_b_p, v_c2))); - v_y0 = _mm_srli_epi32(_mm_add_epi32(v_delta2, v_y0), yuv_shift); + v_rb[0] = _mm_cvtepu8_epi16(v_rb[0]); + v_rb[1] = _mm_cvtepu8_epi16(v_rb[1]); + v_rb[0] = _mm_sub_epi16(v_rb[0], _mm_unpacklo_epi16(v_y, v_y)); + v_rb[1] = _mm_sub_epi16(v_rb[1], _mm_unpackhi_epi16(v_y, v_y)); + v_rgb[0] = _mm_unpacklo_epi16(v_rb[0], v_delta_16); + v_rgb[1] = _mm_unpackhi_epi16(v_rb[0], v_delta_16); + v_rgb[2] = _mm_unpacklo_epi16(v_rb[1], v_delta_16); + v_rgb[3] = _mm_unpackhi_epi16(v_rb[1], v_delta_16); + v_rgb[0] = _mm_madd_epi16(v_rgb[0], v_coeff); + v_rgb[1] = _mm_madd_epi16(v_rgb[1], v_coeff); + v_rgb[2] = _mm_madd_epi16(v_rgb[2], v_coeff); + v_rgb[3] = _mm_madd_epi16(v_rgb[3], v_coeff); + v_rgb[0] = _mm_srai_epi32(v_rgb[0], yuv_shift); + v_rgb[1] = _mm_srai_epi32(v_rgb[1], yuv_shift); + v_rgb[2] = _mm_srai_epi32(v_rgb[2], yuv_shift); + v_rgb[3] = _mm_srai_epi32(v_rgb[3], yuv_shift); + v_rgb[0] = _mm_packs_epi32(v_rgb[0], v_rgb[1]); + v_rgb[2] = _mm_packs_epi32(v_rgb[2], v_rgb[3]); + v_rgb[0] = _mm_packus_epi16(v_rgb[0], v_rgb[2]); - __m128i v_cr0 = _mm_mullo_epi32(_mm_sub_epi32(blueIdx == 2 ? v_r_p : v_b_p, v_y0), v_c3); - __m128i v_cb0 = _mm_mullo_epi32(_mm_sub_epi32(blueIdx == 0 ? v_r_p : v_b_p, v_y0), v_c4); - v_cr0 = _mm_srai_epi32(_mm_add_epi32(v_delta, v_cr0), yuv_shift); - v_cb0 = _mm_srai_epi32(_mm_add_epi32(v_delta, v_cb0), yuv_shift); + v_rb[0] = _mm_unpacklo_epi16(v_y, v_rgb[0]); + v_rb[1] = _mm_unpackhi_epi16(v_y, v_rgb[0]); - v_r_p = _mm_unpackhi_epi16(v_r, v_zero); - v_g_p = _mm_unpackhi_epi16(v_g, v_zero); - v_b_p = _mm_unpackhi_epi16(v_b, v_zero); + v_rb[0] = _mm_shuffle_epi8(v_rb[0], v_shuffle2); + v_rb[1] = _mm_shuffle_epi8(v_rb[1], v_shuffle2); + v_rb[1] = _mm_alignr_epi8(v_rb[1], _mm_slli_si128(v_rb[0], 4), 12); - __m128i v_y1 = _mm_add_epi32(_mm_mullo_epi32(v_r_p, v_c0), - _mm_add_epi32(_mm_mullo_epi32(v_g_p, v_c1), - _mm_mullo_epi32(v_b_p, v_c2))); - v_y1 = _mm_srli_epi32(_mm_add_epi32(v_delta2, v_y1), yuv_shift); - - __m128i v_cr1 = _mm_mullo_epi32(_mm_sub_epi32(blueIdx == 2 ? v_r_p : v_b_p, v_y1), v_c3); - __m128i v_cb1 = _mm_mullo_epi32(_mm_sub_epi32(blueIdx == 0 ? v_r_p : v_b_p, v_y1), v_c4); - v_cr1 = _mm_srai_epi32(_mm_add_epi32(v_delta, v_cr1), yuv_shift); - v_cb1 = _mm_srai_epi32(_mm_add_epi32(v_delta, v_cb1), yuv_shift); - - v_y = _mm_packs_epi32(v_y0, v_y1); - v_cr = _mm_packs_epi32(v_cr0, v_cr1); - v_cb = _mm_packs_epi32(v_cb0, v_cb1); + _mm_storel_epi64((__m128i *)(dst), v_rb[0]); + _mm_storeu_si128((__m128i *)(dst + 8), v_rb[1]); } void operator()(const uchar * src, uchar * dst, int n) const @@ -2233,63 +2239,67 @@ struct RGB2YCrCb_i if (haveSIMD) { - for ( ; i <= n - 96; i += 96, src += scn * 32) + __m128i v_shuffle; + __m128i v_crgb; + if (scn == 4) { - __m128i v_r0 = _mm_loadu_si128((__m128i const *)(src)); - __m128i v_r1 = _mm_loadu_si128((__m128i const *)(src + 16)); - __m128i v_g0 = _mm_loadu_si128((__m128i const *)(src + 32)); - __m128i v_g1 = _mm_loadu_si128((__m128i const *)(src + 48)); - __m128i v_b0 = _mm_loadu_si128((__m128i const *)(src + 64)); - __m128i v_b1 = _mm_loadu_si128((__m128i const *)(src + 80)); - - if (scn == 4) + if (bidx == 0) { - __m128i v_a0 = _mm_loadu_si128((__m128i const *)(src + 96)); - __m128i v_a1 = _mm_loadu_si128((__m128i const *)(src + 112)); - _mm_deinterleave_epi8(v_r0, v_r1, v_g0, v_g1, - v_b0, v_b1, v_a0, v_a1); + v_shuffle = _mm_set_epi8(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xe, 0x8, 0xa, 0x4, 0x6, 0x0, 0x2); } else - _mm_deinterleave_epi8(v_r0, v_r1, v_g0, v_g1, v_b0, v_b1); + { + v_shuffle = _mm_set_epi8(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xc, 0xa, 0x8, 0x6, 0x4, 0x2, 0x0); + } + v_crgb = _mm_set_epi16(0, (short)C2, (short)C1, (short)C0, 0, (short)C2, (short)C1, (short)C0); + for ( ; i <= n - 24; i += 24, src += scn * 8) + { + __m128i v_src[2]; + v_src[0] = _mm_loadu_si128((__m128i const *)(src)); + v_src[1] = _mm_loadu_si128((__m128i const *)(src + 16)); - __m128i v_y0 = v_zero, v_cr0 = v_zero, v_cb0 = v_zero; - process(_mm_unpacklo_epi8(v_r0, v_zero), - _mm_unpacklo_epi8(v_g0, v_zero), - _mm_unpacklo_epi8(v_b0, v_zero), - v_y0, v_cr0, v_cb0); + __m128i v_rgb[4]; + v_rgb[0] = _mm_cvtepu8_epi16(v_src[0]); + v_rgb[1] = _mm_cvtepu8_epi16(_mm_srli_si128(v_src[0], 8)); + v_rgb[2] = _mm_cvtepu8_epi16(v_src[1]); + v_rgb[3] = _mm_cvtepu8_epi16(_mm_srli_si128(v_src[1], 8)); - __m128i v_y1 = v_zero, v_cr1 = v_zero, v_cb1 = v_zero; - process(_mm_unpackhi_epi8(v_r0, v_zero), - _mm_unpackhi_epi8(v_g0, v_zero), - _mm_unpackhi_epi8(v_b0, v_zero), - v_y1, v_cr1, v_cb1); + __m128i v_rb[2]; + v_rb[0] = _mm_shuffle_epi8(v_src[0], v_shuffle); + v_rb[1] = _mm_shuffle_epi8(v_src[1], v_shuffle); - __m128i v_y_0 = _mm_packus_epi16(v_y0, v_y1); - __m128i v_cr_0 = _mm_packus_epi16(v_cr0, v_cr1); - __m128i v_cb_0 = _mm_packus_epi16(v_cb0, v_cb1); + process(v_rgb, v_crgb, v_rb, dst + i); + } + } + else + { + if (bidx == 0) + { + v_shuffle = _mm_set_epi8(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xb, 0x6, 0x8, 0x3, 0x5, 0x0, 0x2); + } + else + { + v_shuffle = _mm_set_epi8(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0x9, 0x8, 0x6, 0x5, 0x3, 0x2, 0x0); + } + v_crgb = _mm_set_epi16(0, (short)C2, (short)C1, (short)C0, (short)C2, (short)C1, (short)C0, 0); + for ( ; i <= n - 24; i += 24, src += scn * 8) + { + __m128i v_src[2]; + v_src[0] = _mm_loadu_si128((__m128i const *)(src)); + v_src[1] = _mm_loadl_epi64((__m128i const *)(src + 16)); - process(_mm_unpacklo_epi8(v_r1, v_zero), - _mm_unpacklo_epi8(v_g1, v_zero), - _mm_unpacklo_epi8(v_b1, v_zero), - v_y0, v_cr0, v_cb0); + __m128i v_rgb[4]; + v_rgb[0] = _mm_cvtepu8_epi16(_mm_slli_si128(v_src[0], 1)); + v_rgb[1] = _mm_cvtepu8_epi16(_mm_srli_si128(v_src[0], 5)); + v_rgb[2] = _mm_cvtepu8_epi16(_mm_alignr_epi8(v_src[1], v_src[0], 11)); + v_rgb[3] = _mm_cvtepu8_epi16(_mm_srli_si128(v_src[1], 1)); - process(_mm_unpackhi_epi8(v_r1, v_zero), - _mm_unpackhi_epi8(v_g1, v_zero), - _mm_unpackhi_epi8(v_b1, v_zero), - v_y1, v_cr1, v_cb1); + __m128i v_rb[2]; + v_rb[0] = _mm_shuffle_epi8(v_src[0], v_shuffle); + v_rb[1] = _mm_shuffle_epi8(_mm_alignr_epi8(v_src[1], v_src[0], 12), v_shuffle); - __m128i v_y_1 = _mm_packus_epi16(v_y0, v_y1); - __m128i v_cr_1 = _mm_packus_epi16(v_cr0, v_cr1); - __m128i v_cb_1 = _mm_packus_epi16(v_cb0, v_cb1); - - _mm_interleave_epi8(v_y_0, v_y_1, v_cr_0, v_cr_1, v_cb_0, v_cb_1); - - _mm_storeu_si128((__m128i *)(dst + i), v_y_0); - _mm_storeu_si128((__m128i *)(dst + i + 16), v_y_1); - _mm_storeu_si128((__m128i *)(dst + i + 32), v_cr_0); - _mm_storeu_si128((__m128i *)(dst + i + 48), v_cr_1); - _mm_storeu_si128((__m128i *)(dst + i + 64), v_cb_0); - _mm_storeu_si128((__m128i *)(dst + i + 80), v_cb_1); + process(v_rgb, v_crgb, v_rb, dst + i); + } } } @@ -2304,10 +2314,10 @@ struct RGB2YCrCb_i } } + __m128i v_delta_16, v_delta_32; + __m128i v_coeff; + __m128i v_shuffle2; int srccn, blueIdx, coeffs[5]; - __m128i v_c0, v_c1, v_c2; - __m128i v_c3, v_c4, v_delta, v_delta2; - __m128i v_zero; bool haveSIMD; }; From 3debc78a5f9938d41dc2cee254632f07fc776e16 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Mon, 8 Aug 2016 22:13:13 +0900 Subject: [PATCH 036/178] fix build error on JetsonTK1 * avoid using vld1_f16 and vst1_f16 on gcc 4 series (Ubuntu 14.04) * guard correctly with #if * use static inline --- modules/core/src/convert.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index dc974505e5..1b7f77cb8d 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -4545,6 +4545,16 @@ static short convertFp16SW(float fp32) } #endif +#if CV_FP16 && (defined __GNUC__) && (defined __arm__ || defined __aarch64__) + #if 5 <= __GNUC__ + static inline float16x4_t load_f16(const short* p) { return vld1_f16((const float16_t*)p); } + static inline void store_f16(short* p, float16x4_t v) { vst1_f16((float16_t*)p, v); } + #else + static inline float16x4_t load_f16(const short* p) { return (float16x4_t)vld1_s16(p); } + static inline void store_f16(short* p, float16x4_t v) { vst1_s16(p, (int16x4_t)v); } + #endif +#endif + // template for FP16 HW conversion function template static void cvtScaleHalf_( const T* src, size_t sstep, DT* dst, size_t dstep, Size size); @@ -4579,7 +4589,7 @@ cvtScaleHalf_( const float* src, size_t sstep, short* dst, size_t float16x4_t v_dst = vcvt_f16_f32(v_src); - vst1_f16((float16_t*)(dst + x), v_dst); + store_f16(dst + x, v_dst); #else #error "Configuration error" #endif @@ -4631,7 +4641,7 @@ cvtScaleHalf_( const short* src, size_t sstep, float* dst, size_t _mm_storeu_ps(dst + x, v_dst); #elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) - float16x4_t v_src = vld1_f16((float16_t*)(src + x)); + float16x4_t v_src = load_f16(src+x); float32x4_t v_dst = vcvt_f32_f16(v_src); From 677f2427612f2096f46d924fcf49b30349d7c116 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Mon, 8 Aug 2016 15:43:04 +0200 Subject: [PATCH 037/178] stitching: use correct ifdef to allow compilation without cudalegacy GraphCutSeamFinderGpu requires cudalegacy. --- modules/stitching/src/stitcher.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/stitching/src/stitcher.cpp b/modules/stitching/src/stitcher.cpp index 41fe81f5fc..7226ac7479 100644 --- a/modules/stitching/src/stitcher.cpp +++ b/modules/stitching/src/stitcher.cpp @@ -56,7 +56,7 @@ Stitcher Stitcher::createDefault(bool try_use_gpu) stitcher.setFeaturesMatcher(makePtr(try_use_gpu)); stitcher.setBundleAdjuster(makePtr()); -#ifdef HAVE_CUDA +#ifdef HAVE_OPENCV_CUDALEGACY if (try_use_gpu && cuda::getCudaEnabledDeviceCount() > 0) { #ifdef HAVE_OPENCV_XFEATURES2D @@ -549,7 +549,7 @@ Ptr createStitcher(bool try_use_gpu) stitcher->setFeaturesMatcher(makePtr(try_use_gpu)); stitcher->setBundleAdjuster(makePtr()); - #ifdef HAVE_CUDA + #ifdef HAVE_OPENCV_CUDALEGACY if (try_use_gpu && cuda::getCudaEnabledDeviceCount() > 0) { #ifdef HAVE_OPENCV_NONFREE @@ -561,20 +561,20 @@ Ptr createStitcher(bool try_use_gpu) stitcher->setSeamFinder(makePtr()); } else + #endif + { + #ifdef HAVE_OPENCV_NONFREE + stitcher->setFeaturesFinder(makePtr()); + #else + stitcher->setFeaturesFinder(makePtr()); #endif - { - #ifdef HAVE_OPENCV_NONFREE - stitcher->setFeaturesFinder(makePtr()); - #else - stitcher->setFeaturesFinder(makePtr()); - #endif - stitcher->setWarper(makePtr()); - stitcher->setSeamFinder(makePtr(detail::GraphCutSeamFinderBase::COST_COLOR)); - } + stitcher->setWarper(makePtr()); + stitcher->setSeamFinder(makePtr(detail::GraphCutSeamFinderBase::COST_COLOR)); + } - stitcher->setExposureCompensator(makePtr()); - stitcher->setBlender(makePtr(try_use_gpu)); + stitcher->setExposureCompensator(makePtr()); + stitcher->setBlender(makePtr(try_use_gpu)); - return stitcher; + return stitcher; } } // namespace cv From b8e08d5d3c033cc630e00f4a532d50c87b074026 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 9 Aug 2016 12:48:06 +0300 Subject: [PATCH 038/178] ocl: fix Canny for Intel devices There is an issue with processing of abs(short) function for negative argument. Affected OpenCL devices: - iGPU: Intel(R) HD Graphics 520 (OpenCL 2.0 ) - CPU: Intel(R) Core(TM) i5-6300U CPU @ 2.40GHz (OpenCL 2.0 (Build 10094)) --- modules/imgproc/src/opencl/canny.cl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/opencl/canny.cl b/modules/imgproc/src/opencl/canny.cl index 584cf9e90b..138850424b 100644 --- a/modules/imgproc/src/opencl/canny.cl +++ b/modules/imgproc/src/opencl/canny.cl @@ -260,7 +260,7 @@ __kernel void stage1_with_sobel(__global const uchar *src, int src_step, int src #ifdef L2GRAD #define dist(x, y) ((int)(x) * (x) + (int)(y) * (y)) #else -#define dist(x, y) (abs(x) + abs(y)) +#define dist(x, y) (abs((int)(x)) + abs((int)(y))) #endif __constant int prev[4][2] = { From 042b0a584de982beddf38ffbb780c98d591eddba Mon Sep 17 00:00:00 2001 From: k-shinotsuka Date: Tue, 9 Aug 2016 18:59:29 +0900 Subject: [PATCH 039/178] improve LKTrackerInvoker::operator() --- modules/video/src/lkpyramid.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 25614d9ced..d775383af3 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -567,18 +567,14 @@ void cv::detail::LKTrackerInvoker::operator()(const Range& range) const diff0 = _mm_unpacklo_epi16(diff0, diff0); // It0 It0 It1 It1 ... v00 = _mm_loadu_si128((const __m128i*)(dIptr)); // Ix0 Iy0 Ix1 Iy1 ... v01 = _mm_loadu_si128((const __m128i*)(dIptr + 8)); - v10 = _mm_mullo_epi16(v00, diff0); - v11 = _mm_mulhi_epi16(v00, diff0); - v00 = _mm_unpacklo_epi16(v10, v11); - v10 = _mm_unpackhi_epi16(v10, v11); + v10 = _mm_unpacklo_epi16(v00, v01); + v11 = _mm_unpackhi_epi16(v00, v01); + v00 = _mm_unpacklo_epi16(diff0, diff1); + v01 = _mm_unpackhi_epi16(diff0, diff1); + v00 = _mm_madd_epi16(v00, v10); + v11 = _mm_madd_epi16(v01, v11); qb0 = _mm_add_ps(qb0, _mm_cvtepi32_ps(v00)); - qb1 = _mm_add_ps(qb1, _mm_cvtepi32_ps(v10)); - v10 = _mm_mullo_epi16(v01, diff1); - v11 = _mm_mulhi_epi16(v01, diff1); - v00 = _mm_unpacklo_epi16(v10, v11); - v10 = _mm_unpackhi_epi16(v10, v11); - qb0 = _mm_add_ps(qb0, _mm_cvtepi32_ps(v00)); - qb1 = _mm_add_ps(qb1, _mm_cvtepi32_ps(v10)); + qb1 = _mm_add_ps(qb1, _mm_cvtepi32_ps(v11)); } #endif From a0ff9f69ef11fdd22368324cf3f24c2f9174dfe1 Mon Sep 17 00:00:00 2001 From: StevenPuttemans Date: Tue, 9 Aug 2016 11:30:38 +0200 Subject: [PATCH 040/178] fix inclusion of OpenCV header opencv.hpp cudev (only for use in .cu files) & cudalegacy (only legacy code) not included --- include/opencv2/opencv.hpp | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/include/opencv2/opencv.hpp b/include/opencv2/opencv.hpp index 93a87bc27f..9037053a02 100644 --- a/include/opencv2/opencv.hpp +++ b/include/opencv2/opencv.hpp @@ -52,7 +52,6 @@ #include "opencv2/core.hpp" // Then the optional modules are checked -// REMARK: keep the includes ordened as the module order on the GitHub repo #ifdef HAVE_OPENCV_CALIB3D #include "opencv2/calib3d.hpp" #endif @@ -102,4 +101,36 @@ #include "opencv2/viz.hpp" #endif +// Finally CUDA specific entries are checked and added +#ifdef HAVE_OPENCV_CUDAARITHM +#include "opencv2/cudaarithm.hpp" +#endif +#ifdef HAVE_OPENCV_CUDABGSEGM +#include "opencv2/cudabgsegm.hpp" +#endif +#ifdef HAVE_OPENCV_CUDACODEC +#include "opencv2/cudacodec.hpp" +#endif +#ifdef HAVE_OPENCV_CUDAFEATURES2D +#include "opencv2/cudafeatures2d.hpp" +#endif +#ifdef HAVE_OPENCV_CUDAFILTERS +#include "opencv2/cudafilters.hpp" +#endif +#ifdef HAVE_OPENCV_CUDAIMGPROC +#include "opencv2/cudaimgproc.hpp" +#endif +#ifdef HAVE_OPENCV_CUDAOBJDETECT +#include "opencv2/cudaobjdetect.hpp" +#endif +#ifdef HAVE_OPENCV_CUDAOPTFLOW +#include "opencv2/cudaoptflow.hpp" +#endif +#ifdef HAVE_OPENCV_CUDASTEREO +#include "opencv2/cudastereo.hpp" +#endif +#ifdef HAVE_OPENCV_CUDAWARPING +#include "opencv2/cudawarping.hpp" +#endif + #endif From 5590421a5d85ffdd8eb7772b40db1401bb4f27ef Mon Sep 17 00:00:00 2001 From: Vladislav Sovrasov Date: Tue, 9 Aug 2016 15:29:57 +0300 Subject: [PATCH 041/178] Fix build interactive-calibration app --- apps/CMakeLists.txt | 1 + apps/interactive-calibration/main.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 497bb7d1f5..e24bd4beff 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -5,3 +5,4 @@ add_subdirectory(traincascade) add_subdirectory(createsamples) add_subdirectory(annotation) add_subdirectory(visualisation) +add_subdirectory(interactive-calibration) diff --git a/apps/interactive-calibration/main.cpp b/apps/interactive-calibration/main.cpp index 06521593f8..f41bcbc371 100644 --- a/apps/interactive-calibration/main.cpp +++ b/apps/interactive-calibration/main.cpp @@ -23,7 +23,7 @@ const std::string keys = "{v | | Input from video file }" "{ci | 0 | Default camera id }" "{flip | false | Vertical flip of input frames }" - "{t | circles | Template for calibration (circles, chessboard, dualCircles, chAruco) }" + "{t | circles | Template for calibration (circles, chessboard, dualCircles, charuco) }" "{sz | 16.3 | Distance between two nearest centers of circles or squares on calibration board}" "{dst | 295 | Distance between white and black parts of daulCircles template}" "{w | | Width of template (in corners or circles)}" From f2e41ce3916ecc53d9ffff0b34d6627b9aefeb64 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 9 Aug 2016 15:35:50 +0300 Subject: [PATCH 042/178] ocl: fix input data for Canny perf test "declare.in(img, WARMUP_RNG)" overrides input image with random values Also added support for different input sizes (via cv::resize) --- modules/imgproc/perf/opencl/perf_imgproc.cpp | 21 +++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/modules/imgproc/perf/opencl/perf_imgproc.cpp b/modules/imgproc/perf/opencl/perf_imgproc.cpp index f441bd9b32..6d9b1a0287 100644 --- a/modules/imgproc/perf/opencl/perf_imgproc.cpp +++ b/modules/imgproc/perf/opencl/perf_imgproc.cpp @@ -299,33 +299,30 @@ OCL_PERF_TEST_P(CLAHEFixture, CLAHE, OCL_TEST_SIZES) ///////////// Canny //////////////////////// -typedef tuple CannyParams; +typedef tuple CannyParams; typedef TestBaseWithParam CannyFixture; -OCL_PERF_TEST_P(CannyFixture, Canny, ::testing::Combine(OCL_PERF_ENUM(3, 5), Bool())) +OCL_PERF_TEST_P(CannyFixture, Canny, ::testing::Combine(OCL_TEST_SIZES, OCL_PERF_ENUM(3, 5), Bool())) { - const CannyParams params = GetParam(); - int apertureSize = get<0>(params); - bool L2Grad = get<1>(params); + const CannyParams& params = GetParam(); + cv::Size imgSize = get<0>(params); + int apertureSize = get<1>(params); + bool L2Grad = get<2>(params); Mat _img = imread(getDataPath("gpu/stereobm/aloe-L.png"), cv::IMREAD_GRAYSCALE); ASSERT_TRUE(!_img.empty()) << "can't open aloe-L.png"; UMat img; - _img.copyTo(img); + cv::resize(_img, img, imgSize); UMat edges(img.size(), CV_8UC1); - declare.in(img, WARMUP_RNG).out(edges); + declare.in(img).out(edges); OCL_TEST_CYCLE() cv::Canny(img, edges, 50.0, 100.0, apertureSize, L2Grad); - if (apertureSize == 3) - SANITY_CHECK(edges); - else - SANITY_CHECK_NOTHING(); + SANITY_CHECK_NOTHING(); } - } } // namespace cvtest::ocl #endif // HAVE_OPENCL From 83b36bfd79df56516dba07ce3b19d9e152c4e124 Mon Sep 17 00:00:00 2001 From: ggargov Date: Wed, 6 Jan 2016 13:46:49 -0800 Subject: [PATCH 043/178] Added comments to clarify sample code Program flow is not easily apparent so hopefully ANY comments in the code could help new users. --- samples/cpp/camshiftdemo.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/samples/cpp/camshiftdemo.cpp b/samples/cpp/camshiftdemo.cpp index 4286e253e9..22ce7f8488 100644 --- a/samples/cpp/camshiftdemo.cpp +++ b/samples/cpp/camshiftdemo.cpp @@ -20,6 +20,7 @@ Point origin; Rect selection; int vmin = 10, vmax = 256, smin = 30; +// User draws box around object to track. This triggers CAMShift to start tracking static void onMouse( int event, int x, int y, int, void* ) { if( selectObject ) @@ -42,7 +43,7 @@ static void onMouse( int event, int x, int y, int, void* ) case EVENT_LBUTTONUP: selectObject = false; if( selection.width > 0 && selection.height > 0 ) - trackObject = -1; + trackObject = -1; // Set up CAMShift properties in main() loop break; } } @@ -133,12 +134,13 @@ int main( int argc, const char** argv ) if( trackObject < 0 ) { + // Object has been selected by user, set up CAMShift search properties once Mat roi(hue, selection), maskroi(mask, selection); calcHist(&roi, 1, 0, maskroi, hist, 1, &hsize, &phranges); normalize(hist, hist, 0, 255, NORM_MINMAX); trackWindow = selection; - trackObject = 1; + trackObject = 1; // Don't set up again, unless user selects new ROI histimg = Scalar::all(0); int binW = histimg.cols / hsize; @@ -156,6 +158,7 @@ int main( int argc, const char** argv ) } } + // Perform CAMShift calcBackProject(&hue, 1, 0, hist, backproj, &phranges); backproj &= mask; RotatedRect trackBox = CamShift(backproj, trackWindow, From a113d9bcc1e36b7bceb10335ef125edd61b147dc Mon Sep 17 00:00:00 2001 From: Vladislav Sovrasov Date: Tue, 9 Aug 2016 16:28:45 +0300 Subject: [PATCH 044/178] Add MKL support --- CMakeLists.txt | 2 +- cmake/OpenCVFindLibsPerf.cmake | 14 ++++++++++++-- cmake/templates/cvconfig.h.in | 6 ++++++ modules/core/src/hal_internal.cpp | 16 ++++++++++++---- 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e575bd794..05d88544c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,7 +224,7 @@ OCV_OPTION(WITH_VA "Include VA support" OFF OCV_OPTION(WITH_VA_INTEL "Include Intel VA-API/OpenCL support" OFF IF (UNIX AND NOT ANDROID) ) OCV_OPTION(WITH_GDAL "Include GDAL Support" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_GPHOTO2 "Include gPhoto2 library support" ON IF (UNIX AND NOT ANDROID) ) -OCV_OPTION(WITH_LAPACK "Include Lapack library support" ON IF (UNIX AND NOT ANDROID) ) +OCV_OPTION(WITH_LAPACK "Include Lapack library support" ON IF (NOT ANDROID) ) # OpenCV build components # =================================================== diff --git a/cmake/OpenCVFindLibsPerf.cmake b/cmake/OpenCVFindLibsPerf.cmake index c679102d37..0364847329 100644 --- a/cmake/OpenCVFindLibsPerf.cmake +++ b/cmake/OpenCVFindLibsPerf.cmake @@ -7,11 +7,21 @@ if(WITH_LAPACK) find_package(LAPACK) if(LAPACK_FOUND) find_path(LAPACKE_INCLUDE_DIR "lapacke.h") - if(LAPACKE_INCLUDE_DIR) + find_path(MKL_LAPACKE_INCLUDE_DIR "mkl_lapack.h") + if(LAPACKE_INCLUDE_DIR OR MKL_LAPACKE_INCLUDE_DIR) find_path(CBLAS_INCLUDE_DIR "cblas.h") - if(CBLAS_INCLUDE_DIR) + find_path(MKL_CBLAS_INCLUDE_DIR "mkl_cblas.h") + + if(CBLAS_INCLUDE_DIR OR MKL_CBLAS_INCLUDE_DIR) set(HAVE_LAPACK 1) + + if(CBLAS_INCLUDE_DIR) ocv_include_directories(${LAPACKE_INCLUDE_DIR} ${CBLAS_INCLUDE_DIR}) + set(HAVE_LAPACK_GENERIC 1) + elseif(MKL_CBLAS_INCLUDE_DIR) + ocv_include_directories(${MKL_LAPACKE_INCLUDE_DIR} ${MKL_CBLAS_INCLUDE_DIR}) + set(HAVE_LAPACK_MKL 1) + endif() list(APPEND OPENCV_LINKER_LIBS ${LAPACK_LIBRARIES}) endif() endif() diff --git a/cmake/templates/cvconfig.h.in b/cmake/templates/cvconfig.h.in index 8dac1ed618..4012f69426 100644 --- a/cmake/templates/cvconfig.h.in +++ b/cmake/templates/cvconfig.h.in @@ -204,5 +204,11 @@ /* Lapack */ #cmakedefine HAVE_LAPACK +/* Lapack Generic */ +#cmakedefine HAVE_LAPACK_GENERIC + +/* Lapack MKL */ +#cmakedefine HAVE_LAPACK_MKL + /* FP16 */ #cmakedefine HAVE_FP16 diff --git a/modules/core/src/hal_internal.cpp b/modules/core/src/hal_internal.cpp index 07054f1d6c..5b83522eed 100644 --- a/modules/core/src/hal_internal.cpp +++ b/modules/core/src/hal_internal.cpp @@ -46,9 +46,17 @@ #ifdef HAVE_LAPACK +#ifdef HAVE_LAPACK_MKL + #include + #include +#endif + +#ifdef HAVE_LAPACK_GENERIC + #include + #include +#endif + #include -#include -#include #include #include #include @@ -150,7 +158,7 @@ lapack_LU(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n, int* template static inline int lapack_Cholesky(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n, bool* info) { - int lapackStatus; + int lapackStatus = 0; int lda = a_step / sizeof(fptype); char L[] = {'L', '\0'}; @@ -227,7 +235,7 @@ lapack_SVD(fptype* a, size_t a_step, fptype *w, fptype* u, size_t u_step, fptype else if(typeid(fptype) == typeid(double)) dgesdd_(mode, &m, &n, (double*)a, &lda, (double*)w, (double*)u, &ldu, (double*)vt, &ldv, (double*)&work1, &lwork, iworkBuf, info); - lwork = round(work1); //optimal buffer size + lwork = (int)round(work1); //optimal buffer size fptype* buffer = new fptype[lwork + 1]; if(typeid(fptype) == typeid(float)) From 99374598b3916e6892f603e01c13ff9582a5302d Mon Sep 17 00:00:00 2001 From: sourin Date: Wed, 10 Aug 2016 14:38:32 +0530 Subject: [PATCH 045/178] Fix modified --- modules/calib3d/src/calibration.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/modules/calib3d/src/calibration.cpp b/modules/calib3d/src/calibration.cpp index fee02f5b9d..f5f9771287 100644 --- a/modules/calib3d/src/calibration.cpp +++ b/modules/calib3d/src/calibration.cpp @@ -52,7 +52,6 @@ that is (in a large extent) based on the paper: Z. Zhang. "A flexible new technique for camera calibration". IEEE Transactions on Pattern Analysis and Machine Intelligence, 22(11):1330-1334, 2000. - The 1st initial port was done by Valery Mosyagin. */ @@ -896,9 +895,9 @@ CV_IMPL void cvProjectPoints2( const CvMat* objectPoints, double dicdist2_dt = -icdist2*icdist2*(k[5]*dr2dt + 2*k[6]*r2*dr2dt + 3*k[7]*r4*dr2dt); double da1dt = 2*(x*dydt[j] + y*dxdt[j]); double dmxdt = (dxdt[j]*cdist*icdist2 + x*dcdist_dt*icdist2 + x*cdist*dicdist2_dt + - k[2]*da1dt + k[3]*(dr2dt + 2*x*dxdt[j]) + k[8]*dr2dt + 2*r2*k[9]*dr2dt); + k[2]*da1dt + k[3]*(dr2dt + 4*x*dxdt[j]) + k[8]*dr2dt + 2*r2*k[9]*dr2dt); double dmydt = (dydt[j]*cdist*icdist2 + y*dcdist_dt*icdist2 + y*cdist*dicdist2_dt + - k[2]*(dr2dt + 2*y*dydt[j]) + k[3]*da1dt + k[10]*dr2dt + 2*r2*k[11]*dr2dt); + k[2]*(dr2dt + 4*y*dydt[j]) + k[3]*da1dt + k[10]*dr2dt + 2*r2*k[11]*dr2dt); dXdYd = dMatTilt*Vec2d(dmxdt, dmydt); dpdt_p[j] = fx*dXdYd(0); dpdt_p[dpdt_step+j] = fy*dXdYd(1); @@ -935,9 +934,9 @@ CV_IMPL void cvProjectPoints2( const CvMat* objectPoints, double dicdist2_dr = -icdist2*icdist2*(k[5] + 2*k[6]*r2 + 3*k[7]*r4)*dr2dr; double da1dr = 2*(x*dydr + y*dxdr); double dmxdr = (dxdr*cdist*icdist2 + x*dcdist_dr*icdist2 + x*cdist*dicdist2_dr + - k[2]*da1dr + k[3]*(dr2dr + 2*x*dxdr) + (k[8] + 2*r2*k[9])*dr2dr); + k[2]*da1dr + k[3]*(dr2dr + 4*x*dxdr) + (k[8] + 2*r2*k[9])*dr2dr); double dmydr = (dydr*cdist*icdist2 + y*dcdist_dr*icdist2 + y*cdist*dicdist2_dr + - k[2]*(dr2dr + 2*y*dydr) + k[3]*da1dr + (k[10] + 2*r2*k[11])*dr2dr); + k[2]*(dr2dr + 4*y*dydr) + k[3]*da1dr + (k[10] + 2*r2*k[11])*dr2dr); dXdYd = dMatTilt*Vec2d(dmxdr, dmydr); dpdr_p[j] = fx*dXdYd(0); dpdr_p[dpdr_step+j] = fy*dXdYd(1); @@ -1945,14 +1944,12 @@ double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1 /* Compute initial estimate of pose - For each image, compute: R(om) is the rotation matrix of om om(R) is the rotation vector of R R_ref = R(om_right) * R(om_left)' T_ref_list = [T_ref_list; T_right - R_ref * T_left] om_ref_list = {om_ref_list; om(R_ref)] - om = median(om_ref_list) T = median(T_ref_list) */ From ba73249dc07588ce235ac3c62663b2332f8446b3 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Wed, 10 Aug 2016 18:36:00 +0900 Subject: [PATCH 046/178] let the test of AccSqr_SIMD pass * The difference becomes too large when multiply is done in int16 * To reproduce the test failure, IPP has to be switched off --- modules/imgproc/src/accum.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/modules/imgproc/src/accum.cpp b/modules/imgproc/src/accum.cpp index e1f1ce71e8..083192bdbd 100644 --- a/modules/imgproc/src/accum.cpp +++ b/modules/imgproc/src/accum.cpp @@ -964,13 +964,15 @@ struct AccSqr_SIMD for ( ; x <= len - 8; x += 8) { __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); - __m128i v_src0 = _mm_unpacklo_epi16(v_src, v_0); - __m128i v_src1 = _mm_unpackhi_epi16(v_src, v_0); - v_src0 = _mm_mullo_epi16(v_src0, v_src0); - v_src1 = _mm_mullo_epi16(v_src1, v_src1); + __m128i v_int0 = _mm_unpacklo_epi16(v_src, v_0); + __m128i v_int1 = _mm_unpackhi_epi16(v_src, v_0); + __m128 v_src0 = _mm_cvtepi32_ps(v_int0); + __m128 v_src1 = _mm_cvtepi32_ps(v_int1); + v_src0 = _mm_mul_ps(v_src0, v_src0); + v_src1 = _mm_mul_ps(v_src1, v_src1); - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_cvtepi32_ps(v_src0))); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_cvtepi32_ps(v_src1))); + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), v_src0)); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), v_src1)); } } From 8596e82d98516c846fb67b1d7d62fb6a6dcd6a5d Mon Sep 17 00:00:00 2001 From: MYLS Date: Thu, 11 Aug 2016 00:53:15 +0800 Subject: [PATCH 047/178] Add JSON support. a JSON emitter, a parser, tests and some basic doc. --- modules/core/include/opencv2/core/core_c.h | 7 +- .../core/include/opencv2/core/persistence.hpp | 55 +- modules/core/include/opencv2/core/types_c.h | 1 + modules/core/perf/perf_io_base64.cpp | 2 +- modules/core/src/persistence.cpp | 1049 ++++++++++++++++- modules/core/test/test_io.cpp | 170 +-- modules/ml/test/test_save_load.cpp | 6 +- 7 files changed, 1151 insertions(+), 139 deletions(-) diff --git a/modules/core/include/opencv2/core/core_c.h b/modules/core/include/opencv2/core/core_c.h index dd1d93638e..f7e0bbb750 100644 --- a/modules/core/include/opencv2/core/core_c.h +++ b/modules/core/include/opencv2/core/core_c.h @@ -1976,7 +1976,7 @@ CVAPI(void) cvSetIPLAllocators( Cv_iplCreateImageHeader create_header, The function opens file storage for reading or writing data. In the latter case, a new file is created or an existing file is rewritten. The type of the read or written file is determined by the -filename extension: .xml for XML and .yml or .yaml for YAML. +filename extension: .xml for XML, .yml or .yaml for YAML and .json for JSON. At the same time, it also supports adding parameters like "example.xml?base64". The three ways are the same: @@ -2031,7 +2031,8 @@ One and only one of the two above flags must be specified @param type_name Optional parameter - the object type name. In case of XML it is written as a type_id attribute of the structure opening tag. In the case of YAML it is written after a colon following the structure name (see the example in - CvFileStorage description). Mainly it is used with user objects. When the storage is read, the + CvFileStorage description). In case of JSON it is written as a name/value pair. + Mainly it is used with user objects. When the storage is read, the encoded type name is used to determine the object type (see CvTypeInfo and cvFindType ). @param attributes This parameter is not used in the current implementation */ @@ -2499,7 +2500,7 @@ CVAPI(void) cvReadRawData( const CvFileStorage* fs, const CvFileNode* src, /** @brief Writes a file node to another file storage. The function writes a copy of a file node to file storage. Possible applications of the function are -merging several file storages into one and conversion between XML and YAML formats. +merging several file storages into one and conversion between XML, YAML and JSON formats. @param fs Destination file storage @param new_node_name New name of the file node in the destination file storage. To keep the existing name, use cvcvGetFileNodeName diff --git a/modules/core/include/opencv2/core/persistence.hpp b/modules/core/include/opencv2/core/persistence.hpp index 75f0c32bd2..01f28d57a3 100644 --- a/modules/core/include/opencv2/core/persistence.hpp +++ b/modules/core/include/opencv2/core/persistence.hpp @@ -57,8 +57,9 @@ Several functions that are described below take CvFileStorage\* as inputs and al save or to load hierarchical collections that consist of scalar values, standard CXCore objects (such as matrices, sequences, graphs), and user-defined objects. -OpenCV can read and write data in XML () or YAML () -formats. Below is an example of 3x3 floating-point identity matrix A, stored in XML and YAML files +OpenCV can read and write data in XML (), YAML () or +JSON () formats. Below is an example of 3x3 floating-point identity matrix A, +stored in XML and YAML files using CXCore functions: XML: @code{.xml} @@ -85,7 +86,8 @@ As it can be seen from the examples, XML uses nested tags to represent hierarchy indentation for that purpose (similar to the Python programming language). The same functions can read and write data in both formats; the particular format is determined by -the extension of the opened file, ".xml" for XML files and ".yml" or ".yaml" for YAML. +the extension of the opened file, ".xml" for XML files, ".yml" or ".yaml" for YAML and ".json" for +JSON. */ typedef struct CvFileStorage CvFileStorage; typedef struct CvFileNode CvFileNode; @@ -101,20 +103,20 @@ namespace cv { /** @addtogroup core_xml -XML/YAML file storages. {#xml_storage} +XML/YAML/JSON file storages. {#xml_storage} ======================= Writing to a file storage. -------------------------- -You can store and then restore various OpenCV data structures to/from XML () -or YAML () formats. Also, it is possible store and load arbitrarily complex -data structures, which include OpenCV data structures, as well as primitive data types (integer and -floating-point numbers and text strings) as their elements. +You can store and then restore various OpenCV data structures to/from XML (), +YAML () or JSON () formats. Also, it is possible store +and load arbitrarily complex data structures, which include OpenCV data structures, as well as +primitive data types (integer and floating-point numbers and text strings) as their elements. -Use the following procedure to write something to XML or YAML: +Use the following procedure to write something to XML, YAML or JSON: -# Create new FileStorage and open it for writing. It can be done with a single call to FileStorage::FileStorage constructor that takes a filename, or you can use the default constructor -and then call FileStorage::open. Format of the file (XML or YAML) is determined from the filename -extension (".xml" and ".yml"/".yaml", respectively) +and then call FileStorage::open. Format of the file (XML, YAML or JSON) is determined from the filename +extension (".xml", ".yml"/".yaml" and ".json", respectively) -# Write all the data you want using the streaming operator `<<`, just like in the case of STL streams. -# Close the file using FileStorage::release. FileStorage destructor also closes the file. @@ -177,19 +179,19 @@ features: - { x:344, y:158, lbp:[ 1, 1, 0, 0, 0, 0, 1, 0 ] } @endcode -As an exercise, you can replace ".yml" with ".xml" in the sample above and see, how the +As an exercise, you can replace ".yml" with ".xml" or ".json" in the sample above and see, how the corresponding XML file will look like. Several things can be noted by looking at the sample code and the output: -- The produced YAML (and XML) consists of heterogeneous collections that can be nested. There are 2 - types of collections: named collections (mappings) and unnamed collections (sequences). In mappings +- The produced YAML (and XML/JSON) consists of heterogeneous collections that can be nested. There are + 2 types of collections: named collections (mappings) and unnamed collections (sequences). In mappings each element has a name and is accessed by name. This is similar to structures and std::map in C/C++ and dictionaries in Python. In sequences elements do not have names, they are accessed by indices. This is similar to arrays and std::vector in C/C++ and lists, tuples in Python. "Heterogeneous" means that elements of each single collection can have different types. - Top-level collection in YAML/XML is a mapping. Each matrix is stored as a mapping, and the matrix + Top-level collection in YAML/XML/JSON is a mapping. Each matrix is stored as a mapping, and the matrix elements are stored as a sequence. Then, there is a sequence of features, where each feature is represented a mapping, and lbp value in a nested sequence. @@ -205,7 +207,7 @@ Several things can be noted by looking at the sample code and the output: - To write a sequence, you first write the special string `[`, then write the elements, then write the closing `]`. -- In YAML (but not XML), mappings and sequences can be written in a compact Python-like inline +- In YAML/JSON (but not XML), mappings and sequences can be written in a compact Python-like inline form. In the sample above matrix elements, as well as each feature, including its lbp value, is stored in such inline form. To store a mapping/sequence in a compact form, put `:` after the opening character, e.g. use `{:` instead of `{` and `[:` instead of `[`. When the @@ -213,7 +215,7 @@ Several things can be noted by looking at the sample code and the output: Reading data from a file storage. --------------------------------- -To read the previously written XML or YAML file, do the following: +To read the previously written XML, YAML or JSON file, do the following: -# Open the file storage using FileStorage::FileStorage constructor or FileStorage::open method. In the current implementation the whole file is parsed and the whole representation of file storage is built in memory as a hierarchy of file nodes (see FileNode) @@ -294,8 +296,8 @@ A complete example using the FileStorage interface class CV_EXPORTS FileNode; class CV_EXPORTS FileNodeIterator; -/** @brief XML/YAML file storage class that encapsulates all the information necessary for writing or reading -data to/from a file. +/** @brief XML/YAML/JSON file storage class that encapsulates all the information necessary for writing or +reading data to/from a file. */ class CV_EXPORTS_W FileStorage { @@ -312,6 +314,7 @@ public: FORMAT_AUTO = 0, //!< flag, auto format FORMAT_XML = (1<<3), //!< flag, XML format FORMAT_YAML = (2<<3), //!< flag, YAML format + FORMAT_JSON = (3<<3), //!< flag, JSON format BASE64 = 64, //!< flag, write rawdata in Base64 by default. (consider using WRITE_BASE64) WRITE_BASE64 = BASE64 | WRITE, //!< flag, enable both WRITE and BASE64 @@ -333,9 +336,9 @@ public: /** @overload @param source Name of the file to open or the text string to read the data from. Extension of the - file (.xml or .yml/.yaml) determines its format (XML or YAML respectively). Also you can append .gz - to work with compressed files, for example myHugeMatrix.xml.gz. If both FileStorage::WRITE and - FileStorage::MEMORY flags are specified, source is used just to specify the output file format (e.g. + file (.xml, .yml/.yaml, or .json) determines its format (XML, YAML or JSON respectively). Also you can + append .gz to work with compressed files, for example myHugeMatrix.xml.gz. If both FileStorage::WRITE + and FileStorage::MEMORY flags are specified, source is used just to specify the output file format (e.g. mydata.xml, .yml etc.). @param flags Mode of operation. See FileStorage::Mode @param encoding Encoding of the file. Note that UTF-16 XML encoding is not supported currently and @@ -354,12 +357,12 @@ public: See description of parameters in FileStorage::FileStorage. The method calls FileStorage::release before opening the file. @param filename Name of the file to open or the text string to read the data from. - Extension of the file (.xml or .yml/.yaml) determines its format (XML or YAML respectively). - Also you can append .gz to work with compressed files, for example myHugeMatrix.xml.gz. If both + Extension of the file (.xml, .yml/.yaml or .json) determines its format (XML, YAML or JSON + respectively). Also you can append .gz to work with compressed files, for example myHugeMatrix.xml.gz. If both FileStorage::WRITE and FileStorage::MEMORY flags are specified, source is used just to specify the output file format (e.g. mydata.xml, .yml etc.). A file name can also contain parameters. - You can use this format, "*?base64" (e.g. "file.xml?base64"), as an alternative to - FileStorage::BASE64 flag. Note: it is case sensitive. + You can use this format, "*?base64" (e.g. "file.json?base64" (case sensitive)), as an alternative to + FileStorage::BASE64 flag. @param flags Mode of operation. One of FileStorage::Mode @param encoding Encoding of the file. Note that UTF-16 XML encoding is not supported currently and you should use 8-bit encoding instead of it. diff --git a/modules/core/include/opencv2/core/types_c.h b/modules/core/include/opencv2/core/types_c.h index e693aa4724..a25a565df6 100644 --- a/modules/core/include/opencv2/core/types_c.h +++ b/modules/core/include/opencv2/core/types_c.h @@ -1669,6 +1669,7 @@ typedef struct CvFileStorage CvFileStorage; #define CV_STORAGE_FORMAT_AUTO 0 #define CV_STORAGE_FORMAT_XML 8 #define CV_STORAGE_FORMAT_YAML 16 +#define CV_STORAGE_FORMAT_JSON 24 #define CV_STORAGE_BASE64 64 #define CV_STORAGE_WRITE_BASE64 (CV_STORAGE_BASE64 | CV_STORAGE_WRITE) diff --git a/modules/core/perf/perf_io_base64.cpp b/modules/core/perf/perf_io_base64.cpp index 04a4a040a5..799c52c394 100644 --- a/modules/core/perf/perf_io_base64.cpp +++ b/modules/core/perf/perf_io_base64.cpp @@ -11,7 +11,7 @@ typedef TestBaseWithParam Size_Mat_StrType; #define MAT_SIZES ::perf::sz1080p/*, ::perf::sz4320p*/ #define MAT_TYPES CV_8UC1, CV_32FC1 -#define FILE_EXTENSION String(".xml"), String(".yml") +#define FILE_EXTENSION String(".xml"), String(".yml"), String(".json") PERF_TEST_P(Size_Mat_StrType, fs_text, diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 6f9f992983..4db6dc4eb9 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -117,6 +117,25 @@ static char* icv_itoa( int _val, char* buffer, int /*radix*/ ) return ptr; } +static inline bool cv_strcasecmp(const char * s1, const char * s2) +{ + if ( s1 == 0 && s2 == 0 ) + return true; + else if ( s1 == 0 || s2 == 0 ) + return false; + + size_t len1 = strlen(s1); + size_t len2 = strlen(s2); + if ( len1 != len2 ) + return false; + + for ( size_t i = 0U; i < len1; i++ ) + if ( tolower( static_cast(s1[i]) ) != tolower( static_cast(s2[i]) ) ) + return false; + + return true; +} + cv::String cv::FileStorage::getDefaultObjectName(const cv::String& _filename) { static const char* stubname = "unnamed"; @@ -621,8 +640,7 @@ icvFSFlush( CvFileStorage* fs ) if( fs->space != indent ) { - if( fs->space < indent ) - memset( fs->buffer_start + fs->space, ' ', indent - fs->space ); + memset( fs->buffer_start, ' ', indent ); fs->space = indent; } @@ -653,6 +671,8 @@ icvClose( CvFileStorage* fs, cv::String* out ) icvFSFlush(fs); if( fs->fmt == CV_STORAGE_FORMAT_XML ) icvPuts( fs, "\n" ); + else if ( fs->fmt == CV_STORAGE_FORMAT_JSON ) + icvPuts( fs, "}\n" ); } icvCloseFile(fs); @@ -1064,6 +1084,7 @@ static double icv_strtod( CvFileStorage* fs, char* ptr, char** endptr ) return fval; } +// this function will convert "aa?bb&cc&dd" to {"aa", "bb", "cc", "dd"} static std::vector analyze_file_name( std::string const & file_name ) { static const char not_file_name = '\n'; @@ -3206,6 +3227,879 @@ icvXMLWriteComment( CvFileStorage* fs, const char* comment, int eol_comment ) } +/****************************************************************************************\ +* JSON Parser * +\****************************************************************************************/ + +static char* +icvJSONSkipSpaces( CvFileStorage* fs, char* ptr ) +{ + bool is_eof = false; + bool is_completed = false; + + while ( is_eof == false && is_completed == false ) + { + switch ( *ptr ) + { + /* comment */ + case '/' : { + ptr++; + if ( *ptr == '\0' ) + { + ptr = icvGets( fs, fs->buffer_start, static_cast(fs->buffer_end - fs->buffer_start) ); + if ( !ptr ) { is_eof = true; break; } + } + + if ( *ptr == '/' ) + { + while ( *ptr != '\n' && *ptr != '\r' ) + { + if ( *ptr == '\0' ) + { + ptr = icvGets( fs, fs->buffer_start, static_cast(fs->buffer_end - fs->buffer_start) ); + if ( !ptr ) { is_eof = true; break; } + } + else + { + ptr++; + } + } + } + else if ( *ptr == '*' ) + { + ptr++; + while ( true ) + { + if ( *ptr == '\0' ) + { + ptr = icvGets( fs, fs->buffer_start, static_cast(fs->buffer_end - fs->buffer_start) ); + if ( !ptr ) { is_eof = true; break; } + } + else if ( *ptr == '*' ) + { + ptr++; + if ( *ptr == '\0' ) + { + ptr = icvGets( fs, fs->buffer_start, static_cast(fs->buffer_end - fs->buffer_start) ); + if ( !ptr ) { is_eof = true; break; } + } + if ( *ptr == '/' ) + break; + } + else + { + ptr++; + } + } + } + else + { + CV_PARSE_ERROR( "Unexpected character" ); + } + } break; + /* whitespace */ + case '\t': + case ' ' : { + ptr++; + } break; + /* newline || end mark */ + case '\0': + case '\n': + case '\r': { + ptr = icvGets( fs, fs->buffer_start, static_cast(fs->buffer_end - fs->buffer_start) ); + if ( !ptr ) { is_eof = true; break; } + } break; + /* other character */ + default: { + if ( !cv_isprint(*ptr) ) + CV_PARSE_ERROR( "Invalid character in the stream" ); + is_completed = true; + } break; + } + } + + if ( is_eof ) + { + ptr = fs->buffer_start; + *ptr = '\0'; + fs->dummy_eof = 1; + } + else if ( !is_completed ) + { + /* should not be executed */ + ptr = 0; + fs->dummy_eof = 1; + CV_PARSE_ERROR( "Abort at parse time" ); + } + return ptr; +} + + +static char* icvJSONParseKey( CvFileStorage* fs, char* ptr, CvFileNode* map, CvFileNode** value_placeholder ) +{ + if( *ptr != '"' ) + CV_PARSE_ERROR( "Key must start with \'\"\'" ); + + char * beg = ptr + 1; + char * end = beg; + + do ++ptr; + while( cv_isprint(*ptr) && *ptr != '"' ); + + if( *ptr != '"' ) + CV_PARSE_ERROR( "Key must end with \'\"\'" ); + + end = ptr; + ptr++; + ptr = icvJSONSkipSpaces( fs, ptr ); + if ( ptr == 0 || fs->dummy_eof ) + return 0; + + if( *ptr != ':' ) + CV_PARSE_ERROR( "Missing \':\'" ); + + /* [beg, end) */ + if( end <= beg ) + CV_PARSE_ERROR( "An empty key" ); + + if ( end - beg == 7u && memcmp(beg, "type_id", 7u) == 0 ) + { + *value_placeholder = 0; + } + else + { + CvStringHashNode* str_hash_node = cvGetHashedKey( fs, beg, static_cast(end - beg), 1 ); + *value_placeholder = cvGetFileNode( fs, map, str_hash_node, 1 ); + } + + ptr++; + return ptr; +} + +static char* icvJSONParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node ) +{ + ptr = icvJSONSkipSpaces( fs, ptr ); + if ( ptr == 0 || fs->dummy_eof ) + CV_PARSE_ERROR( "Unexpected End-Of-File" ); + + memset( node, 0, sizeof(*node) ); + + if ( *ptr == '"' ) + { /* must be string or Base64 string */ + ptr++; + char * beg = ptr; + size_t len = 0u; + for ( ; (cv_isalnum(*ptr) || *ptr == '$' ) && len <= 9u; ptr++ ) + len++; + + if ( len >= 8u && memcmp( beg, "$base64$", 8u ) == 0 ) + { /**************** Base64 string ****************/ + ptr = beg += 8; + + std::string base64_buffer; + base64_buffer.reserve( PARSER_BASE64_BUFFER_SIZE ); + + bool is_matching = false; + while ( !is_matching ) + { + switch ( *ptr ) + { + case '\0': + { + base64_buffer.append( beg, ptr ); + + ptr = icvGets( fs, fs->buffer_start, static_cast(fs->buffer_end - fs->buffer_start) ); + if ( !ptr ) + CV_PARSE_ERROR( "'\"' - right-quote of string is missing" ); + + beg = ptr; + break; + } + case '\"': + { + base64_buffer.append( beg, ptr ); + beg = ptr; + is_matching = true; + break; + } + case '\n': + case '\r': + { + CV_PARSE_ERROR( "'\"' - right-quote of string is missing" ); + break; + } + default: + { + ptr++; + break; + } + } + } + + if ( *ptr != '\"' ) + CV_PARSE_ERROR( "'\"' - right-quote of string is missing" ); + else + ptr++; + + if ( base64_buffer.size() >= base64::ENCODED_HEADER_SIZE ) + { + const char * base64_beg = base64_buffer.data(); + const char * base64_end = base64_beg + base64_buffer.size(); + + /* get dt from header */ + std::string dt; + { + std::vector header(base64::HEADER_SIZE + 1, ' '); + base64::base64_decode(base64_beg, header.data(), 0U, base64::ENCODED_HEADER_SIZE); + if ( !base64::read_base64_header(header, dt) || dt.empty() ) + CV_PARSE_ERROR("Cannot parse dt in Base64 header"); + } + + /* set base64_beg to beginning of base64 data */ + base64_beg = &base64_buffer.at( base64::ENCODED_HEADER_SIZE ); + + if ( base64_buffer.size() > base64::ENCODED_HEADER_SIZE ) + { + if ( !base64::base64_valid( base64_beg, 0U, base64_end - base64_beg ) ) + CV_PARSE_ERROR( "Invalid Base64 data." ); + + /* buffer for decoded data(exclude header) */ + std::vector binary_buffer( base64::base64_decode_buffer_size(base64_end - base64_beg) ); + int total_byte_size = static_cast( + base64::base64_decode_buffer_size( base64_end - base64_beg, base64_beg, false ) + ); + { + base64::Base64ContextParser parser(binary_buffer.data(), binary_buffer.size() ); + const uchar * binary_beg = reinterpret_cast( base64_beg ); + const uchar * binary_end = binary_beg + (base64_end - base64_beg); + parser.read( binary_beg, binary_end ); + parser.flush(); + } + + /* save as CvSeq */ + int elem_size = ::icvCalcStructSize(dt.c_str(), 0); + if (total_byte_size % elem_size != 0) + CV_PARSE_ERROR("Byte size not match elememt size"); + int elem_cnt = total_byte_size / elem_size; + + /* after icvFSCreateCollection, node->tag == struct_flags */ + icvFSCreateCollection(fs, CV_NODE_FLOW | CV_NODE_SEQ, node); + base64::make_seq(binary_buffer.data(), elem_cnt, dt.c_str(), *node->data.seq); + } + else + { + /* empty */ + icvFSCreateCollection(fs, CV_NODE_FLOW | CV_NODE_SEQ, node); + } + } + else if ( base64_buffer.empty() ) + { + /* empty */ + icvFSCreateCollection(fs, CV_NODE_FLOW | CV_NODE_SEQ, node); + } + else + { + CV_PARSE_ERROR("Unrecognized Base64 header"); + } + } + else + { /**************** normal string ****************/ + std::string string_buffer; + string_buffer.reserve( PARSER_BASE64_BUFFER_SIZE ); + + ptr = beg; + bool is_matching = false; + while ( !is_matching ) + { + switch ( *ptr ) + { + case '\\': + { + string_buffer.append( beg, ptr ); + ptr++; + switch ( *ptr ) + { + case '\\': + case '\"': + case '\'': { string_buffer.append( 1u, *ptr ); break; } + case 'n' : { string_buffer.append( 1u, '\n' ); break; } + case 'r' : { string_buffer.append( 1u, '\r' ); break; } + case 't' : { string_buffer.append( 1u, '\t' ); break; } + case 'b' : { string_buffer.append( 1u, '\b' ); break; } + case 'f' : { string_buffer.append( 1u, '\f' ); break; } + case 'u' : { CV_PARSE_ERROR( "'\\uXXXX' currently not supported" ); } + default : { CV_PARSE_ERROR( "Invalid escape character" ); } + break; + } + ptr++; + beg = ptr; + break; + } + case '\0': + { + string_buffer.append( beg, ptr ); + + ptr = icvGets( fs, fs->buffer_start, static_cast(fs->buffer_end - fs->buffer_start) ); + if ( !ptr ) + CV_PARSE_ERROR( "'\"' - right-quote of string is missing" ); + + beg = ptr; + break; + } + case '\"': + { + string_buffer.append( beg, ptr ); + beg = ptr; + is_matching = true; + break; + } + case '\n': + case '\r': + { + CV_PARSE_ERROR( "'\"' - right-quote of string is missing" ); + break; + } + default: + { + ptr++; + break; + } + } + } + + if ( *ptr != '\"' ) + CV_PARSE_ERROR( "'\"' - right-quote of string is missing" ); + else + ptr++; + + node->data.str = cvMemStorageAllocString( fs->memstorage, string_buffer.c_str(), string_buffer.size() ); + node->tag = CV_NODE_STRING; + } + } + else if ( cv_isdigit(*ptr) || *ptr == '-' || *ptr == '+' || *ptr == '.' ) + { /**************** number ****************/ + char * beg = ptr; + if ( *ptr == '+' || *ptr == '-' ) + ptr++; + while( cv_isdigit(*ptr) ) + ptr++; + if (*ptr == '.' || *ptr == 'e') + { + node->data.f = icv_strtod( fs, beg, &ptr ); + node->tag = CV_NODE_REAL; + } + else + { + node->data.i = static_cast(strtol( beg, &ptr, 0 )); + node->tag = CV_NODE_INT; + } + + if ( beg >= ptr ) + CV_PARSE_ERROR( "Invalid numeric value (inconsistent explicit type specification?)" ); + } + else + { /**************** other data ****************/ + const char * beg = ptr; + size_t len = 0u; + for ( ; cv_isalpha(*ptr) && len <= 6u; ptr++ ) + len++; + + if ( len >= 4u && memcmp( beg, "null", 4u ) == 0 ) + { + CV_PARSE_ERROR( "Value 'null' is not supported by this parser" ); + } + else if ( len >= 4u && memcmp( beg, "true", 4u ) == 0 ) + { + node->data.i = 1; + node->tag = CV_NODE_INT; + } + else if ( len >= 5u && memcmp( beg, "false", 5u ) == 0 ) + { + node->data.i = 0; + node->tag = CV_NODE_INT; + } + else + { + CV_PARSE_ERROR( "Unrecognized value" ); + } + ptr++; + } + + return ptr; +} + +static char* icvJSONParseSeq( CvFileStorage* fs, char* ptr, CvFileNode* node ); +static char* icvJSONParseMap( CvFileStorage* fs, char* ptr, CvFileNode* node ); + +static char* icvJSONParseSeq( CvFileStorage* fs, char* ptr, CvFileNode* node ) +{ + if ( *ptr != '[' ) + CV_PARSE_ERROR( "'[' - left-brace of seq is missing" ); + else + ptr++; + + memset( node, 0, sizeof(*node) ); + icvFSCreateCollection( fs, CV_NODE_SEQ, node ); + + while ( true ) + { + ptr = icvJSONSkipSpaces( fs, ptr ); + if ( ptr == 0 || fs->dummy_eof ) + break; + + if ( *ptr != ']' ) + { + CvFileNode* child = (CvFileNode*)cvSeqPush( node->data.seq, 0 ); + + if ( *ptr == '[' ) + ptr = icvJSONParseSeq( fs, ptr, child ); + else if ( *ptr == '{' ) + ptr = icvJSONParseMap( fs, ptr, child ); + else + ptr = icvJSONParseValue( fs, ptr, child ); + } + + ptr = icvJSONSkipSpaces( fs, ptr ); + if ( ptr == 0 || fs->dummy_eof ) + break; + + if ( *ptr == ',' ) + ptr++; + else if ( *ptr == ']' ) + break; + else + CV_PARSE_ERROR( "Unexpected character" ); + } + + if ( *ptr != ']' ) + CV_PARSE_ERROR( "']' - right-brace of seq is missing" ); + else + ptr++; + + return ptr; +} + +static char* icvJSONParseMap( CvFileStorage* fs, char* ptr, CvFileNode* node ) +{ + if ( *ptr != '{' ) + CV_PARSE_ERROR( "'{' - left-brace of map is missing" ); + else + ptr++; + + memset( node, 0, sizeof(*node) ); + icvFSCreateCollection( fs, CV_NODE_MAP, node ); + + while ( true ) + { + ptr = icvJSONSkipSpaces( fs, ptr ); + if ( ptr == 0 || fs->dummy_eof ) + break; + + if ( *ptr == '"' ) + { + CvFileNode* child = 0; + ptr = icvJSONParseKey( fs, ptr, node, &child ); + ptr = icvJSONSkipSpaces( fs, ptr ); + if ( ptr == 0 || fs->dummy_eof ) + break; + + if ( child == 0 ) + { /* type_id */ + CvFileNode tmp; + ptr = icvJSONParseValue( fs, ptr, &tmp ); + if ( CV_NODE_IS_STRING(tmp.tag) ) + { + node->info = cvFindType( tmp.data.str.ptr ); + if ( node->info ) + node->tag |= CV_NODE_USER; + // delete tmp.data.str + } + else + { + CV_PARSE_ERROR( "\"type_id\" should be of type string" ); + } + } + else + { /* normal */ + if ( *ptr == '[' ) + ptr = icvJSONParseSeq( fs, ptr, child ); + else if ( *ptr == '{' ) + ptr = icvJSONParseMap( fs, ptr, child ); + else + ptr = icvJSONParseValue( fs, ptr, child ); + } + } + + ptr = icvJSONSkipSpaces( fs, ptr ); + if ( ptr == 0 || fs->dummy_eof ) + break; + + if ( *ptr == ',' ) + ptr++; + else if ( *ptr == '}' ) + break; + else + CV_PARSE_ERROR( "Unexpected character" ); + } + + if ( *ptr != '}' ) + CV_PARSE_ERROR( "'}' - right-brace of map is missing" ); + else + ptr++; + + return ptr; +} + + +static void +icvJSONParse( CvFileStorage* fs ) +{ + char* ptr = fs->buffer_start; + ptr = icvJSONSkipSpaces( fs, ptr ); + if ( ptr == 0 || fs->dummy_eof ) + return; + + if ( *ptr == '{' ) + { + CvFileNode* root_node = (CvFileNode*)cvSeqPush( fs->roots, 0 ); + ptr = icvJSONParseMap( fs, ptr, root_node ); + } + else if ( *ptr == '[' ) + { + CvFileNode* root_node = (CvFileNode*)cvSeqPush( fs->roots, 0 ); + ptr = icvJSONParseSeq( fs, ptr, root_node ); + } + else + { + CV_PARSE_ERROR( "left-brace of top level is missing" ); + } + + if ( fs->dummy_eof != 0 ) + CV_PARSE_ERROR( "Unexpected End-Of-File" ); +} + + +/****************************************************************************************\ +* JSON Emitter * +\****************************************************************************************/ + +static void +icvJSONWrite( CvFileStorage* fs, const char* key, const char* data ) +{ + /* check write_struct */ + + check_if_write_struct_is_delayed( fs ); + if ( fs->state_of_writing_base64 == base64::fs::Uncertain ) + { + switch_to_Base64_state( fs, base64::fs::NotUse ); + } + else if ( fs->state_of_writing_base64 == base64::fs::InUse ) + { + CV_Error( CV_StsError, "At present, output Base64 data only." ); + } + + /* check parameters */ + + size_t key_len = 0u; + if( key && *key == '\0' ) + key = 0; + if ( key ) + { + key_len = strlen(key); + if ( key_len == 0u ) + CV_Error( CV_StsBadArg, "The key is an empty" ); + else if ( static_cast(key_len) > CV_FS_MAX_LEN ) + CV_Error( CV_StsBadArg, "The key is too long" ); + } + + size_t data_len = 0u; + if ( data ) + data_len = strlen(data); + + int struct_flags = fs->struct_flags; + if( CV_NODE_IS_COLLECTION(struct_flags) ) + { + if ( (CV_NODE_IS_MAP(struct_flags) ^ (key != 0)) ) + CV_Error( CV_StsBadArg, "An attempt to add element without a key to a map, " + "or add element with key to sequence" ); + } else { + fs->is_first = 0; + struct_flags = CV_NODE_EMPTY | (key ? CV_NODE_MAP : CV_NODE_SEQ); + } + + /* start to write */ + + char* ptr = 0; + + if( CV_NODE_IS_FLOW(struct_flags) ) + { + int new_offset; + ptr = fs->buffer; + if( !CV_NODE_IS_EMPTY(struct_flags) ) + *ptr++ = ','; + new_offset = static_cast(ptr - fs->buffer_start + key_len + data_len); + if( new_offset > fs->wrap_margin && new_offset - fs->struct_indent > 10 ) + { + fs->buffer = ptr; + ptr = icvFSFlush(fs); + } + else + *ptr++ = ' '; + } + else + { + if ( !CV_NODE_IS_EMPTY(struct_flags) ) + { + ptr = fs->buffer; + *ptr++ = ','; + *ptr++ = '\n'; + *ptr++ = '\0'; + ::icvPuts( fs, fs->buffer_start ); + ptr = fs->buffer = fs->buffer_start; + } + ptr = icvFSFlush(fs); + } + + if( key ) + { + if( !cv_isalpha(key[0]) && key[0] != '_' ) + CV_Error( CV_StsBadArg, "Key must start with a letter or _" ); + + ptr = icvFSResizeWriteBuffer( fs, ptr, static_cast(key_len) ); + *ptr++ = '\"'; + + for( size_t i = 0u; i < key_len; i++ ) + { + char c = key[i]; + + ptr[i] = c; + if( !cv_isalnum(c) && c != '-' && c != '_' && c != ' ' ) + CV_Error( CV_StsBadArg, "Key names may only contain alphanumeric characters [a-zA-Z0-9], '-', '_' and ' '" ); + } + + ptr += key_len; + *ptr++ = '\"'; + *ptr++ = ':'; + *ptr++ = ' '; + } + + if( data ) + { + ptr = icvFSResizeWriteBuffer( fs, ptr, static_cast(data_len) ); + memcpy( ptr, data, data_len ); + ptr += data_len; + } + + fs->buffer = ptr; + fs->struct_flags = struct_flags & ~CV_NODE_EMPTY; +} + + +static void +icvJSONStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, + const char* type_name CV_DEFAULT(0)) +{ + int parent_flags; + char data[CV_FS_MAX_LEN + 1024]; + + struct_flags = (struct_flags & (CV_NODE_TYPE_MASK|CV_NODE_FLOW)) | CV_NODE_EMPTY; + if( !CV_NODE_IS_COLLECTION(struct_flags)) + CV_Error( CV_StsBadArg, + "Some collection type - CV_NODE_SEQ or CV_NODE_MAP, must be specified" ); + + if ( type_name && *type_name == '\0' ) + type_name = 0; + + bool has_type_id = false; + bool is_real_collection = true; + if (type_name && memcmp(type_name, "binary", 6) == 0) + { + struct_flags = CV_NODE_STR; + data[0] = '\0'; + is_real_collection = false; + } + else if( type_name ) + { + has_type_id = true; + } + + if ( is_real_collection ) + { + char c = CV_NODE_IS_MAP(struct_flags) ? '{' : '['; + data[0] = c; + data[1] = '\0'; + } + + icvJSONWrite( fs, key, data ); + + parent_flags = fs->struct_flags; + cvSeqPush( fs->write_stack, &parent_flags ); + fs->struct_flags = struct_flags; + fs->struct_indent += 4; + + if ( has_type_id ) + fs->write_string( fs, "type_id", type_name, 1 ); +} + + +static void +icvJSONEndWriteStruct( CvFileStorage* fs ) +{ + if( fs->write_stack->total == 0 ) + CV_Error( CV_StsError, "EndWriteStruct w/o matching StartWriteStruct" ); + + int parent_flags = 0; + int struct_flags = fs->struct_flags; + cvSeqPop( fs->write_stack, &parent_flags ); + fs->struct_indent -= 4; + fs->struct_flags = parent_flags & ~CV_NODE_EMPTY; + assert( fs->struct_indent >= 0 ); + + if ( CV_NODE_IS_COLLECTION(struct_flags) ) + { + if ( !CV_NODE_IS_FLOW(struct_flags) ) + { + if ( fs->buffer <= fs->buffer_start + fs->space ) + { + /* some bad code for base64_writer... */ + *fs->buffer++ = '\n'; + *fs->buffer++ = '\0'; + icvPuts( fs, fs->buffer_start ); + fs->buffer = fs->buffer_start; + } + icvFSFlush(fs); + } + + char* ptr = fs->buffer; + if( ptr > fs->buffer_start + fs->struct_indent && !CV_NODE_IS_EMPTY(struct_flags) ) + *ptr++ = ' '; + *ptr++ = CV_NODE_IS_MAP(struct_flags) ? '}' : ']'; + fs->buffer = ptr; + } +} + + +static void +icvJSONStartNextStream( CvFileStorage* fs ) +{ + if( !fs->is_first ) + { + while( fs->write_stack->total > 0 ) + icvJSONEndWriteStruct(fs); + + fs->struct_indent = 4; + icvFSFlush(fs); + fs->buffer = fs->buffer_start; + } +} + + +static void +icvJSONWriteInt( CvFileStorage* fs, const char* key, int value ) +{ + char buf[128]; + icvJSONWrite( fs, key, icv_itoa( value, buf, 10 )); +} + + +static void +icvJSONWriteReal( CvFileStorage* fs, const char* key, double value ) +{ + char buf[128]; + icvJSONWrite( fs, key, icvDoubleToString( buf, value )); +} + + +static void +icvJSONWriteString( CvFileStorage* fs, const char* key, + const char* str, int quote CV_DEFAULT(0)) +{ + char buf[CV_FS_MAX_LEN*4+16]; + char* data = (char*)str; + int i, len; + + if( !str ) + CV_Error( CV_StsNullPtr, "Null string pointer" ); + + len = (int)strlen(str); + if( len > CV_FS_MAX_LEN ) + CV_Error( CV_StsBadArg, "The written string is too long" ); + + if( quote || len == 0 || str[0] != str[len-1] || (str[0] != '\"' && str[0] != '\'') ) + { + int need_quote = 1; + data = buf; + *data++ = '\"'; + for( i = 0; i < len; i++ ) + { + char c = str[i]; + + switch ( c ) + { + case '\\': + case '\"': + case '\'': { *data++ = '\\'; *data++ = c; break; } + case '\n': { *data++ = '\\'; *data++ = 'n'; break; } + case '\r': { *data++ = '\\'; *data++ = 'r'; break; } + case '\t': { *data++ = '\\'; *data++ = 't'; break; } + case '\b': { *data++ = '\\'; *data++ = 'b'; break; } + case '\f': { *data++ = '\\'; *data++ = 'f'; break; } + default : { *data++ = c; } + break; + } + } + + *data++ = '\"'; + *data++ = '\0'; + data = buf + !need_quote; + } + + icvJSONWrite( fs, key, data ); +} + + +static void +icvJSONWriteComment( CvFileStorage* fs, const char* comment, int eol_comment ) +{ + if( !comment ) + CV_Error( CV_StsNullPtr, "Null comment" ); + + int len = static_cast(strlen(comment)); + char* ptr = fs->buffer; + const char* eol = strchr(comment, '\n'); + bool multiline = eol != 0; + + if( !eol_comment || multiline || fs->buffer_end - ptr < len || ptr == fs->buffer_start ) + ptr = icvFSFlush( fs ); + else + *ptr++ = ' '; + + while( comment ) + { + *ptr++ = '/'; + *ptr++ = '/'; + *ptr++ = ' '; + if( eol ) + { + ptr = icvFSResizeWriteBuffer( fs, ptr, (int)(eol - comment) + 1 ); + memcpy( ptr, comment, eol - comment + 1 ); + fs->buffer = ptr + (eol - comment); + comment = eol + 1; + eol = strchr( comment, '\n' ); + } + else + { + len = (int)strlen(comment); + ptr = icvFSResizeWriteBuffer( fs, ptr, len ); + memcpy( ptr, comment, len ); + fs->buffer = ptr + len; + comment = 0; + } + ptr = icvFSFlush( fs ); + } +} + + /****************************************************************************************\ * Common High-Level Functions * \****************************************************************************************/ @@ -3218,7 +4112,7 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const bool append = (flags & 3) == CV_STORAGE_APPEND; bool mem = (flags & CV_STORAGE_MEMORY) != 0; bool write_mode = (flags & 3) != 0; - bool write_base64 = write_mode && (flags & CV_STORAGE_BASE64) != 0; + bool write_base64 = (write_mode || append) && (flags & CV_STORAGE_BASE64) != 0; bool isGZ = false; size_t fnamelen = 0; const char * filename = query; @@ -3231,7 +4125,7 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const filename = params.begin()->c_str(); if ( write_base64 == false && is_param_exist( params, "base64" ) ) - write_base64 = true; + write_base64 = (write_mode || append); } if( !filename || filename[0] == '\0' ) @@ -3311,13 +4205,23 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const if( fmt == CV_STORAGE_FORMAT_AUTO && filename ) { - const char* dot_pos = filename + fnamelen - (isGZ ? 7 : 4); - fs->fmt = (dot_pos >= filename && (memcmp( dot_pos, ".xml", 4) == 0 || - memcmp(dot_pos, ".XML", 4) == 0 || memcmp(dot_pos, ".Xml", 4) == 0)) ? - CV_STORAGE_FORMAT_XML : CV_STORAGE_FORMAT_YAML; + const char* dot_pos = strrchr( filename, '.' ); + fs->fmt + = cv_strcasecmp( dot_pos, ".xml" ) + ? CV_STORAGE_FORMAT_XML + : cv_strcasecmp( dot_pos, ".json" ) + ? CV_STORAGE_FORMAT_JSON + : CV_STORAGE_FORMAT_YAML + ; + } + else if ( fmt != CV_STORAGE_FORMAT_AUTO ) + { + fs->fmt = fmt; } else - fs->fmt = fmt != CV_STORAGE_FORMAT_AUTO ? fmt : CV_STORAGE_FORMAT_XML; + { + fs->fmt = CV_STORAGE_FORMAT_XML; + } // we use factor=6 for XML (the longest characters (' and ") are encoded with 6 bytes (' and ") // and factor=4 for YAML ( as we use 4 bytes for non ASCII characters (e.g. \xAB)) @@ -3415,7 +4319,7 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const fs->write_comment = icvXMLWriteComment; fs->start_next_stream = icvXMLStartNextStream; } - else + else if( fs->fmt == CV_STORAGE_FORMAT_YAML ) { if( !append ) icvPuts( fs, "%YAML 1.0\n---\n" ); @@ -3429,6 +4333,49 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const fs->write_comment = icvYMLWriteComment; fs->start_next_stream = icvYMLStartNextStream; } + else + { + // TODO: JSON func + if( !append ) + icvPuts( fs, "{\n" ); + else + { + bool valid = false; + long roffset = 0; + for ( ; + fseek( fs->file, roffset, SEEK_END ) == 0; + roffset -= 1 ) + { + const char end_mark = '}'; + if ( fgetc( fs->file ) == end_mark ) + { + fseek( fs->file, roffset, SEEK_END ); + valid = true; + break; + } + } + + if ( valid ) + { + icvCloseFile( fs ); + fs->file = fopen( fs->filename, "r+t" ); + fseek( fs->file, roffset, SEEK_END ); + fputs( ",", fs->file ); + } + else + { + CV_Error( CV_StsError, "Could not find '}' in the end of file.\n" ); + } + } + fs->struct_indent = 4; + fs->start_write_struct = icvJSONStartWriteStruct; + fs->end_write_struct = icvJSONEndWriteStruct; + fs->write_int = icvJSONWriteInt; + fs->write_real = icvJSONWriteReal; + fs->write_string = icvJSONWriteString; + fs->write_comment = icvJSONWriteComment; + fs->start_next_stream = icvJSONStartNextStream; + } } else { @@ -3440,10 +4387,16 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const size_t buf_size = 1 << 20; const char* yaml_signature = "%YAML"; + const char* json_signature = "{"; char buf[16]; icvGets( fs, buf, sizeof(buf)-2 ); - fs->fmt = strncmp( buf, yaml_signature, strlen(yaml_signature) ) == 0 ? - CV_STORAGE_FORMAT_YAML : CV_STORAGE_FORMAT_XML; + fs->fmt + = strncmp( buf, yaml_signature, strlen(yaml_signature) ) == 0 + ? CV_STORAGE_FORMAT_YAML + : strncmp( buf, json_signature, strlen(json_signature) ) == 0 + ? CV_STORAGE_FORMAT_JSON + : CV_STORAGE_FORMAT_XML + ; if( !isGZ ) { @@ -3474,10 +4427,13 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const //cvSetErrMode( CV_ErrModeSilent ); try { - if( fs->fmt == CV_STORAGE_FORMAT_XML ) - icvXMLParse( fs ); - else - icvYMLParse( fs ); + switch (fs->fmt) + { + case CV_STORAGE_FORMAT_XML : { icvXMLParse ( fs ); break; } + case CV_STORAGE_FORMAT_YAML: { icvYMLParse ( fs ); break; } + case CV_STORAGE_FORMAT_JSON: { icvJSONParse( fs ); break; } + default: break; + } } catch (...) { @@ -3530,7 +4486,7 @@ cvStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, type_name == 0 ) { - /* Uncertain if output Base64 data */ + /* Uncertain whether output Base64 data */ make_write_struct_delayed( fs, key, struct_flags, type_name ); } else if ( type_name && memcmp(type_name, "binary", 6) == 0 ) @@ -3841,8 +4797,14 @@ cvWriteRawData( CvFileStorage* fs, const void* _data, int len, const char* dt ) int buf_len = (int)strlen(ptr); icvXMLWriteScalar( fs, 0, ptr, buf_len ); } - else + else if ( fs->fmt == CV_STORAGE_FORMAT_YAML ) + { icvYMLWrite( fs, 0, ptr ); + } + else + { + icvJSONWrite( fs, 0, ptr ); + } } offset = (int)(data - data0); @@ -6770,7 +7732,19 @@ public: CV_CHECK_OUTPUT_FILE_STORAGE(fs); - ::icvFSFlush(file_storage); + if ( fs->fmt == CV_STORAGE_FORMAT_JSON ) + { + /* clean and break buffer */ + *fs->buffer++ = '\0'; + ::icvPuts( fs, fs->buffer_start ); + fs->buffer = fs->buffer_start; + memset( file_storage->buffer_start, 0, static_cast(file_storage->space) ); + ::icvPuts( fs, "\"$base64$" ); + } + else + { + ::icvFSFlush(file_storage); + } } ~Base64ContextEmitter() @@ -6778,6 +7752,16 @@ public: /* cleaning */ if (src_cur != src_beg) flush(); /* encode the rest binary data to base64 buffer */ + + if ( file_storage->fmt == CV_STORAGE_FORMAT_JSON ) + { + /* clean and break buffer */ + ::icvPuts(file_storage, "\""); + file_storage->buffer = file_storage->buffer_start; + ::icvFSFlush( file_storage ); + memset( file_storage->buffer_start, 0, static_cast(file_storage->space) ); + file_storage->buffer = file_storage->buffer_start; + } } Base64ContextEmitter & write(const uchar * beg, const uchar * end) @@ -6835,17 +7819,25 @@ public: src_cur = src_beg; { // TODO: better solutions. - const char newline[] = "\n"; - char space[80]; - int ident = file_storage->struct_indent; - memset(space, ' ', ident); - space[ident] = '\0'; + if ( file_storage->fmt == CV_STORAGE_FORMAT_JSON ) + { + ::icvPuts(file_storage, (const char*)base64_buffer.data()); + } + else + { + const char newline[] = "\n"; + char space[80]; + int ident = file_storage->struct_indent; + memset(space, ' ', static_cast(ident)); + space[ident] = '\0'; + + ::icvPuts(file_storage, space); + ::icvPuts(file_storage, (const char*)base64_buffer.data()); + ::icvPuts(file_storage, newline); + ::icvFSFlush(file_storage); + } - ::icvPuts(file_storage, space); - ::icvPuts(file_storage, (const char*)base64_buffer.data()); - ::icvPuts(file_storage, newline); - ::icvFSFlush(file_storage); } return true; @@ -7175,7 +8167,6 @@ base64::Base64Writer::Base64Writer(::CvFileStorage * fs) , data_type_string() { CV_CHECK_OUTPUT_FILE_STORAGE(fs); - icvFSFlush(fs); } void base64::Base64Writer::write(const void* _data, size_t len, const char* dt) diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index 7e2d6ec583..5ba4fd1909 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -91,9 +91,10 @@ protected: {-1000000, 1000000}, {-10, 10}, {-10, 10}}; RNG& rng = ts->get_rng(); RNG rng0; - test_case_count = 4; int progress = 0; MemStorage storage(cvCreateMemStorage(0)); + const char * suffixs[3] = {".yml", ".xml", ".json" }; + test_case_count = 6; for( int idx = 0; idx < test_case_count; idx++ ) { @@ -102,8 +103,8 @@ protected: cvClearMemStorage(storage); - bool mem = (idx % 4) >= 2; - string filename = tempfile(idx % 2 ? ".yml" : ".xml"); + bool mem = (idx % test_case_count) >= (test_case_count >> 1); + string filename = tempfile(suffixs[idx % (test_case_count >> 1)]); FileStorage fs(filename, FileStorage::WRITE + (mem ? FileStorage::MEMORY : 0)); @@ -430,82 +431,91 @@ public: protected: void run(int) { - try - { - string fname = cv::tempfile(".xml"); - vector mi, mi2, mi3, mi4; - vector mv, mv2, mv3, mv4; - vector vudt, vudt2, vudt3, vudt4; - Mat m(10, 9, CV_32F); - Mat empty; - UserDefinedType udt = { 8, 3.3f }; - randu(m, 0, 1); - mi3.push_back(5); - mv3.push_back(m); - vudt3.push_back(udt); - Point_ p1(1.1f, 2.2f), op1; - Point3i p2(3, 4, 5), op2; - Size s1(6, 7), os1; - Complex c1(9, 10), oc1; - Rect r1(11, 12, 13, 14), or1; - Vec v1(15, 16, 17, 18, 19), ov1; - Scalar sc1(20.0, 21.1, 22.2, 23.3), osc1; - Range g1(7, 8), og1; + const char * suffix[3] = { + ".yml", + ".xml", + ".json" + }; - FileStorage fs(fname, FileStorage::WRITE); - fs << "mi" << mi; - fs << "mv" << mv; - fs << "mi3" << mi3; - fs << "mv3" << mv3; - fs << "vudt" << vudt; - fs << "vudt3" << vudt3; - fs << "empty" << empty; - fs << "p1" << p1; - fs << "p2" << p2; - fs << "s1" << s1; - fs << "c1" << c1; - fs << "r1" << r1; - fs << "v1" << v1; - fs << "sc1" << sc1; - fs << "g1" << g1; - fs.release(); - - fs.open(fname, FileStorage::READ); - fs["mi"] >> mi2; - fs["mv"] >> mv2; - fs["mi3"] >> mi4; - fs["mv3"] >> mv4; - fs["vudt"] >> vudt2; - fs["vudt3"] >> vudt4; - fs["empty"] >> empty; - fs["p1"] >> op1; - fs["p2"] >> op2; - fs["s1"] >> os1; - fs["c1"] >> oc1; - fs["r1"] >> or1; - fs["v1"] >> ov1; - fs["sc1"] >> osc1; - fs["g1"] >> og1; - CV_Assert( mi2.empty() ); - CV_Assert( mv2.empty() ); - CV_Assert( cvtest::norm(Mat(mi3), Mat(mi4), CV_C) == 0 ); - CV_Assert( mv4.size() == 1 ); - double n = cvtest::norm(mv3[0], mv4[0], CV_C); - CV_Assert( vudt2.empty() ); - CV_Assert( vudt3 == vudt4 ); - CV_Assert( n == 0 ); - CV_Assert( op1 == p1 ); - CV_Assert( op2 == p2 ); - CV_Assert( os1 == s1 ); - CV_Assert( oc1 == c1 ); - CV_Assert( or1 == r1 ); - CV_Assert( ov1 == v1 ); - CV_Assert( osc1 == sc1 ); - CV_Assert( og1 == g1 ); - } - catch(...) + for ( size_t i = 0u; i < 3u; i++ ) { - ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); + try + { + string fname = cv::tempfile(suffix[i]); + vector mi, mi2, mi3, mi4; + vector mv, mv2, mv3, mv4; + vector vudt, vudt2, vudt3, vudt4; + Mat m(10, 9, CV_32F); + Mat empty; + UserDefinedType udt = { 8, 3.3f }; + randu(m, 0, 1); + mi3.push_back(5); + mv3.push_back(m); + vudt3.push_back(udt); + Point_ p1(1.1f, 2.2f), op1; + Point3i p2(3, 4, 5), op2; + Size s1(6, 7), os1; + Complex c1(9, 10), oc1; + Rect r1(11, 12, 13, 14), or1; + Vec v1(15, 16, 17, 18, 19), ov1; + Scalar sc1(20.0, 21.1, 22.2, 23.3), osc1; + Range g1(7, 8), og1; + + FileStorage fs(fname, FileStorage::WRITE); + fs << "mi" << mi; + fs << "mv" << mv; + fs << "mi3" << mi3; + fs << "mv3" << mv3; + fs << "vudt" << vudt; + fs << "vudt3" << vudt3; + fs << "empty" << empty; + fs << "p1" << p1; + fs << "p2" << p2; + fs << "s1" << s1; + fs << "c1" << c1; + fs << "r1" << r1; + fs << "v1" << v1; + fs << "sc1" << sc1; + fs << "g1" << g1; + fs.release(); + + fs.open(fname, FileStorage::READ); + fs["mi"] >> mi2; + fs["mv"] >> mv2; + fs["mi3"] >> mi4; + fs["mv3"] >> mv4; + fs["vudt"] >> vudt2; + fs["vudt3"] >> vudt4; + fs["empty"] >> empty; + fs["p1"] >> op1; + fs["p2"] >> op2; + fs["s1"] >> os1; + fs["c1"] >> oc1; + fs["r1"] >> or1; + fs["v1"] >> ov1; + fs["sc1"] >> osc1; + fs["g1"] >> og1; + CV_Assert( mi2.empty() ); + CV_Assert( mv2.empty() ); + CV_Assert( cvtest::norm(Mat(mi3), Mat(mi4), CV_C) == 0 ); + CV_Assert( mv4.size() == 1 ); + double n = cvtest::norm(mv3[0], mv4[0], CV_C); + CV_Assert( vudt2.empty() ); + CV_Assert( vudt3 == vudt4 ); + CV_Assert( n == 0 ); + CV_Assert( op1 == p1 ); + CV_Assert( op2 == p2 ); + CV_Assert( os1 == s1 ); + CV_Assert( oc1 == c1 ); + CV_Assert( or1 == r1 ); + CV_Assert( ov1 == v1 ); + CV_Assert( osc1 == sc1 ); + CV_Assert( og1 == g1 ); + } + catch(...) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); + } } } }; @@ -618,6 +628,7 @@ TEST(Core_InputOutput, filestorage_base64_basic) char const * filenames[] = { "core_io_base64_basic_test.yml", "core_io_base64_basic_test.xml", + "core_io_base64_basic_test.json", 0 }; @@ -745,15 +756,19 @@ TEST(Core_InputOutput, filestorage_base64_valid_call) char const * filenames[] = { "core_io_base64_other_test.yml", "core_io_base64_other_test.xml", + "core_io_base64_other_test.json", "core_io_base64_other_test.yml?base64", "core_io_base64_other_test.xml?base64", + "core_io_base64_other_test.json?base64", 0 }; char const * real_name[] = { "core_io_base64_other_test.yml", "core_io_base64_other_test.xml", + "core_io_base64_other_test.json", "core_io_base64_other_test.yml", "core_io_base64_other_test.xml", + "core_io_base64_other_test.json", 0 }; @@ -829,6 +844,7 @@ TEST(Core_InputOutput, filestorage_base64_invalid_call) char const * filenames[] = { "core_io_base64_other_test.yml", "core_io_base64_other_test.xml", + "core_io_base64_other_test.json", 0 }; diff --git a/modules/ml/test/test_save_load.cpp b/modules/ml/test/test_save_load.cpp index 7c2a7c4a6c..b97c8c3ab3 100644 --- a/modules/ml/test/test_save_load.cpp +++ b/modules/ml/test/test_save_load.cpp @@ -64,11 +64,11 @@ int CV_SLMLTest::run_test_case( int testCaseIdx ) if( code == cvtest::TS::OK ) { get_test_error( testCaseIdx, &test_resps1 ); - fname1 = tempfile(".yml.gz"); + fname1 = tempfile(".json.gz"); save( (fname1 + "?base64").c_str() ); load( fname1.c_str() ); get_test_error( testCaseIdx, &test_resps2 ); - fname2 = tempfile(".yml.gz"); + fname2 = tempfile(".json.gz"); save( (fname2 + "?base64").c_str() ); } else @@ -279,7 +279,7 @@ TEST(DISABLED_ML_SVM, linear_save_load) svm1 = Algorithm::load("SVM45_X_38-1.xml"); svm2 = Algorithm::load("SVM45_X_38-2.xml"); - string tname = tempfile("a.xml"); + string tname = tempfile("a.json"); svm2->save(tname + "?base64"); svm3 = Algorithm::load(tname); From d99832163a028b8452f6c0da3c53ca8aea956610 Mon Sep 17 00:00:00 2001 From: MYLS Date: Thu, 11 Aug 2016 03:31:35 +0800 Subject: [PATCH 048/178] solve warnings and do some cleaning. --- modules/core/src/persistence.cpp | 38 ++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 4db6dc4eb9..d6990779a5 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -703,8 +703,10 @@ cvReleaseFileStorage( CvFileStorage** p_fs ) cvFree( &fs->buffer_start ); cvReleaseMemStorage( &fs->memstorage ); - if( fs->outbuf ) - delete fs->outbuf; + delete fs->outbuf; + delete fs->base64_writer; + delete fs->delayed_struct_key; + delete fs->delayed_type_name; memset( fs, 0, sizeof(*fs) ); cvFree( &fs ); @@ -1358,7 +1360,7 @@ static char* icvYMLParseBase64(CvFileStorage* fs, char* ptr, int indent, CvFileN std::vector header(base64::HEADER_SIZE + 1, ' '); base64::base64_decode(beg, header.data(), 0U, base64::ENCODED_HEADER_SIZE); if ( !base64::read_base64_header(header, dt) || dt.empty() ) - CV_PARSE_ERROR("Cannot parse dt in Base64 header"); + CV_PARSE_ERROR("Invalid `dt` in Base64 header"); beg += base64::ENCODED_HEADER_SIZE; } @@ -2317,7 +2319,7 @@ static char* icvXMLParseBase64(CvFileStorage* fs, char* ptr, CvFileNode * node) std::vector header(base64::HEADER_SIZE + 1, ' '); base64::base64_decode(beg, header.data(), 0U, base64::ENCODED_HEADER_SIZE); if ( !base64::read_base64_header(header, dt) || dt.empty() ) - CV_PARSE_ERROR("Cannot parse dt in Base64 header"); + CV_PARSE_ERROR("Invalid `dt` in Base64 header"); beg += base64::ENCODED_HEADER_SIZE; } @@ -3268,7 +3270,7 @@ icvJSONSkipSpaces( CvFileStorage* fs, char* ptr ) else if ( *ptr == '*' ) { ptr++; - while ( true ) + for (;;) { if ( *ptr == '\0' ) { @@ -3294,7 +3296,7 @@ icvJSONSkipSpaces( CvFileStorage* fs, char* ptr ) } else { - CV_PARSE_ERROR( "Unexpected character" ); + CV_PARSE_ERROR( "Not supported escape character" ); } } break; /* whitespace */ @@ -3356,11 +3358,11 @@ static char* icvJSONParseKey( CvFileStorage* fs, char* ptr, CvFileNode* map, CvF return 0; if( *ptr != ':' ) - CV_PARSE_ERROR( "Missing \':\'" ); + CV_PARSE_ERROR( "Missing \':\' between key and value" ); /* [beg, end) */ if( end <= beg ) - CV_PARSE_ERROR( "An empty key" ); + CV_PARSE_ERROR( "Key is empty" ); if ( end - beg == 7u && memcmp(beg, "type_id", 7u) == 0 ) { @@ -3452,7 +3454,7 @@ static char* icvJSONParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node ) std::vector header(base64::HEADER_SIZE + 1, ' '); base64::base64_decode(base64_beg, header.data(), 0U, base64::ENCODED_HEADER_SIZE); if ( !base64::read_base64_header(header, dt) || dt.empty() ) - CV_PARSE_ERROR("Cannot parse dt in Base64 header"); + CV_PARSE_ERROR("Invalid `dt` in Base64 header"); } /* set base64_beg to beginning of base64 data */ @@ -3506,7 +3508,7 @@ static char* icvJSONParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node ) { /**************** normal string ****************/ std::string string_buffer; string_buffer.reserve( PARSER_BASE64_BUFFER_SIZE ); - + ptr = beg; bool is_matching = false; while ( !is_matching ) @@ -3572,7 +3574,12 @@ static char* icvJSONParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node ) else ptr++; - node->data.str = cvMemStorageAllocString( fs->memstorage, string_buffer.c_str(), string_buffer.size() ); + node->data.str = cvMemStorageAllocString + ( + fs->memstorage, + string_buffer.c_str(), + static_cast(string_buffer.size()) + ); node->tag = CV_NODE_STRING; } } @@ -3641,7 +3648,7 @@ static char* icvJSONParseSeq( CvFileStorage* fs, char* ptr, CvFileNode* node ) memset( node, 0, sizeof(*node) ); icvFSCreateCollection( fs, CV_NODE_SEQ, node ); - while ( true ) + for (;;) { ptr = icvJSONSkipSpaces( fs, ptr ); if ( ptr == 0 || fs->dummy_eof ) @@ -3689,7 +3696,7 @@ static char* icvJSONParseMap( CvFileStorage* fs, char* ptr, CvFileNode* node ) memset( node, 0, sizeof(*node) ); icvFSCreateCollection( fs, CV_NODE_MAP, node ); - while ( true ) + for ( ;; ) { ptr = icvJSONSkipSpaces( fs, ptr ); if ( ptr == 0 || fs->dummy_eof ) @@ -3957,7 +3964,7 @@ icvJSONEndWriteStruct( CvFileStorage* fs ) if ( CV_NODE_IS_COLLECTION(struct_flags) ) { - if ( !CV_NODE_IS_FLOW(struct_flags) ) + if ( !CV_NODE_IS_FLOW(struct_flags) ) { if ( fs->buffer <= fs->buffer_start + fs->space ) { @@ -4335,7 +4342,6 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const } else { - // TODO: JSON func if( !append ) icvPuts( fs, "{\n" ); else @@ -7818,8 +7824,6 @@ public: src_cur = src_beg; { - // TODO: better solutions. - if ( file_storage->fmt == CV_STORAGE_FORMAT_JSON ) { ::icvPuts(file_storage, (const char*)base64_buffer.data()); From 5cc1ef9022964f100f65129c553329f8a2e8ac4d Mon Sep 17 00:00:00 2001 From: daB0bby Date: Thu, 11 Aug 2016 10:15:48 +0200 Subject: [PATCH 049/178] fix code-style consistency --- modules/core/include/opencv2/core/mat.inl.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core/mat.inl.hpp b/modules/core/include/opencv2/core/mat.inl.hpp index 2ba152f375..49ea17f485 100644 --- a/modules/core/include/opencv2/core/mat.inl.hpp +++ b/modules/core/include/opencv2/core/mat.inl.hpp @@ -680,7 +680,8 @@ void Mat::addref() CV_XADD(&u->refcount, 1); } -inline void Mat::release() +inline +void Mat::release() { if( u && CV_XADD(&u->refcount, -1) == 1 ) deallocate(); From b75bac7975c525e7fda4dc3f861e99c8a250226d Mon Sep 17 00:00:00 2001 From: LaurentBerger Date: Tue, 9 Aug 2016 16:00:03 +0200 Subject: [PATCH 050/178] Solve Issue 7063 consequences of changes accuracy test Solve issue 7063 --- modules/core/src/matrix_decomp.cpp | 8 ++++++- modules/core/test/test_math.cpp | 19 ++++++++++++++++ modules/ml/src/inner_functions.cpp | 35 +++++------------------------ modules/stitching/src/autocalib.cpp | 3 --- 4 files changed, 32 insertions(+), 33 deletions(-) diff --git a/modules/core/src/matrix_decomp.cpp b/modules/core/src/matrix_decomp.cpp index dc9c014930..5b0d62a967 100644 --- a/modules/core/src/matrix_decomp.cpp +++ b/modules/core/src/matrix_decomp.cpp @@ -153,8 +153,12 @@ CholImpl(_Tp* A, size_t astep, int m, _Tp* b, size_t bstep, int n) L[i*astep + i] = (_Tp)(1./std::sqrt(s)); } - if( !b ) + if (!b) + { + for( i = 0; i < m; i++ ) + L[i*astep + i]=1/L[i*astep + i]; return true; + } // LLt x = b // 1: L y = b @@ -193,6 +197,8 @@ CholImpl(_Tp* A, size_t astep, int m, _Tp* b, size_t bstep, int n) b[i*bstep + j] = (_Tp)(s*L[i*astep + i]); } } + for( i = 0; i < m; i++ ) + L[i*astep + i]=1/L[i*astep + i]; return true; } diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index 5eb9fe267f..32888ff734 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -2977,4 +2977,23 @@ TEST(Core_Pow, special) } } +TEST(Core_Cholesky, accuracy64f) +{ + const int n = 5; + Mat A(n, n, CV_64F), refA; + Mat mean(1, 1, CV_64F); + *mean.ptr() = 10.0; + Mat dev(1, 1, CV_64F); + *dev.ptr() = 10.0; + RNG rng(10); + rng.fill(A, RNG::NORMAL, mean, dev); + A = A*A.t(); + A.copyTo(refA); + Cholesky(A.ptr(), A.step, n, NULL, 0, 0); + + for (int i = 0; i < A.rows; i++) + for (int j = i + 1; j < A.cols; j++) + A.at(i, j) = 0.0; + EXPECT_TRUE(norm(refA - A*A.t()) < 10e-5); +} /* End of file. */ diff --git a/modules/ml/src/inner_functions.cpp b/modules/ml/src/inner_functions.cpp index b39d403434..20abf7b052 100644 --- a/modules/ml/src/inner_functions.cpp +++ b/modules/ml/src/inner_functions.cpp @@ -116,35 +116,12 @@ static void Cholesky( const Mat& A, Mat& S ) { CV_Assert(A.type() == CV_32F); - int dim = A.rows; - S.create(dim, dim, CV_32F); - - int i, j, k; - - for( i = 0; i < dim; i++ ) - { - for( j = 0; j < i; j++ ) - S.at(i,j) = 0.f; - - float sum = 0.f; - for( k = 0; k < i; k++ ) - { - float val = S.at(k,i); - sum += val*val; - } - - S.at(i,i) = std::sqrt(std::max(A.at(i,i) - sum, 0.f)); - float ival = 1.f/S.at(i, i); - - for( j = i + 1; j < dim; j++ ) - { - sum = 0; - for( k = 0; k < i; k++ ) - sum += S.at(k, i) * S.at(k, j); - - S.at(i, j) = (A.at(i, j) - sum)*ival; - } - } + S = A.clone(); + cv::Cholesky ((float*)S.ptr(),S.step, S.rows,NULL, 0, 0); + S = S.t(); + for (int i=1;i(i,j)=0; } /* Generates from multivariate normal distribution, where - is an diff --git a/modules/stitching/src/autocalib.cpp b/modules/stitching/src/autocalib.cpp index 24145242c7..18b6e048d0 100644 --- a/modules/stitching/src/autocalib.cpp +++ b/modules/stitching/src/autocalib.cpp @@ -51,9 +51,6 @@ static inline bool decomposeCholesky(double* A, size_t astep, int m) { if (!hal::Cholesky64f(A, astep, m, 0, 0, 0)) return false; - astep /= sizeof(A[0]); - for (int i = 0; i < m; ++i) - A[i*astep + i] = (double)(1./A[i*astep + i]); return true; } From 1734f435f76f139b49185db2d654b1dec76146b7 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 11 Aug 2016 13:47:04 +0300 Subject: [PATCH 051/178] ios: reduce number of test configurations in precommit builds --- platforms/ios/build_framework.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platforms/ios/build_framework.py b/platforms/ios/build_framework.py index 34500d7f14..c3a048b323 100644 --- a/platforms/ios/build_framework.py +++ b/platforms/ios/build_framework.py @@ -195,6 +195,10 @@ if __name__ == "__main__": args = parser.parse_args() b = Builder(args.opencv, args.contrib, + [ + ("armv7", "iPhoneOS"), + ("arm64", "iPhoneOS"), + ] if os.environ.get('BUILD_PRECOMMIT', None) else [ ("armv7", "iPhoneOS"), ("armv7s", "iPhoneOS"), From 13d2154f9ae5eca6a7f3901764c0751d649534fa Mon Sep 17 00:00:00 2001 From: Vladislav Sovrasov Date: Wed, 10 Aug 2016 16:15:14 +0300 Subject: [PATCH 052/178] Fix HAL documentation --- modules/core/src/hal_replacement.hpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/core/src/hal_replacement.hpp b/modules/core/src/hal_replacement.hpp index 7f826b4096..2121261f6d 100644 --- a/modules/core/src/hal_replacement.hpp +++ b/modules/core/src/hal_replacement.hpp @@ -582,11 +582,11 @@ Performs \f$LU\f$ decomposition of square matrix \f$A=P*L*U\f$ (where \f$P\f$ is Function returns the \f$sign\f$ of permutation \f$P\f$ via parameter info. @param src1 pointer to input matrix \f$A\f$ stored in row major order. After finish of work src1 contains at least \f$U\f$ part of \f$LU\f$ decomposition which is appropriate for determainant calculation: \f$det(A)=sign*\prod_{j=1}^{M}a_{jj}\f$. -@param src1_step number of bytes each matrix \f$A\f$ row occupies. +@param src1_step number of bytes between two consequent rows of matrix \f$A\f$. @param m size of square matrix \f$A\f$. @param src2 pointer to \f$M\times N\f$ matrix \f$B\f$ which is the right-hand side of system \f$A*X=B\f$. \f$B\f$ stored in row major order. If src2 is null pointer only \f$LU\f$ decomposition will be performed. After finish of work src2 contains solution \f$X\f$ of system \f$A*X=B\f$. -@param src2_step number of bytes each matrix \f$B\f$ row occupies. +@param src2_step number of bytes between two consequent rows of matrix \f$B\f$. @param n number of right-hand vectors in \f$M\times N\f$ matrix \f$B\f$. @param info indicates success of decomposition. If *info is equals to zero decomposition failed, othervise *info is equals to \f$sign\f$. */ @@ -599,11 +599,11 @@ inline int hal_ni_LU64f(double* src1, size_t src1_step, int m, double* src2, siz /** Performs Cholesky decomposition of matrix \f$A = L*L^T\f$ and solves matrix equation \f$A*X=B\f$. @param src1 pointer to input matrix \f$A\f$ stored in row major order. After finish of work src1 contains lower triangular matrix \f$L\f$. -@param src1_step number of bytes each matrix \f$A\f$ row occupies. +@param src1_step number of bytes between two consequent rows of matrix \f$A\f$. @param m size of square matrix \f$A\f$. @param src2 pointer to \f$M\times N\f$ matrix \f$B\f$ which is the right-hand side of system \f$A*X=B\f$. B stored in row major order. If src2 is null pointer only Cholesky decomposition will be performed. After finish of work src2 contains solution \f$X\f$ of system \f$A*X=B\f$. -@param src2_step number of bytes each matrix \f$B\f$ row occupies. +@param src2_step number of bytes between two consequent rows of matrix \f$B\f$. @param n number of right-hand vectors in \f$M\times N\f$ matrix \f$B\f$. @param info indicates success of decomposition. If *info is false decomposition failed. */ @@ -618,12 +618,12 @@ inline int hal_ni_Cholesky64f(double* src1, size_t src1_step, int m, double* src Performs singular value decomposition of \f$M\times N\f$(\f$M>N\f$) matrix \f$A = U*\Sigma*V^T\f$. @param src pointer to input \f$M\times N\f$ matrix \f$A\f$ stored in column major order. After finish of work src will be filled with rows of \f$U\f$ or not modified (depends of flag CV_HAL_SVD_MODIFY_A). -@param src_step number of bytes each matrix \f$A\f$ column occupies. +@param src_step number of bytes between two consequent columns of matrix \f$A\f$. @param w pointer to array for singular values of matrix \f$A\f$ (i. e. first \f$N\f$ diagonal elements of matrix \f$\Sigma\f$). @param u pointer to output \f$M\times N\f$ or \f$M\times M\f$ matrix \f$U\f$ (size depends of flags). Pointer must be valid if flag CV_HAL_SVD_MODIFY_A not used. -@param u_step number of bytes each matrix \f$U\f$ row occupies. +@param u_step number of bytes between two consequent rows of matrix \f$U\f$. @param vt pointer to array for \f$N\times N\f$ matrix \f$V^T\f$. -@param vt_step number of bytes each matrix \f$V^T\f$ row occupies. +@param vt_step number of bytes between two consequent rows of matrix \f$V^T\f$. @param m number fo rows in matrix \f$A\f$. @param n number of columns in matrix \f$A\f$. @param flags algorithm options (combination of CV_HAL_SVD_FULL_UV, ...). @@ -651,15 +651,15 @@ The function performs generalized matrix multiplication similar to the gemm func \f$D = \alpha*AB+\beta*C\f$ @param src1 pointer to input \f$M\times N\f$ matrix \f$A\f$ or \f$A^T\f$ stored in row major order. -@param src1_step number of bytes each matrix \f$A\f$ or \f$A^T\f$ row occupies. +@param src1_step number of bytes between two consequent rows of matrix \f$A\f$ or \f$A^T\f$. @param src2 pointer to input \f$N\times K\f$ matrix \f$B\f$ or \f$B^T\f$ stored in row major order. -@param src2_step number of bytes each matrix \f$B\f$ or \f$B^T\f$ row occupies. +@param src2_step number of bytes between two consequent rows of matrix \f$B\f$ or \f$B^T\f$. @param alpha \f$\alpha\f$ multiplier before \f$AB\f$ @param src3 pointer to input \f$M\times K\f$ matrix \f$C\f$ or \f$C^T\f$ stored in row major order. -@param src3_step number of bytes each matrix \f$C\f$ or \f$C^T\f$ row occupies. +@param src3_step number of bytes between two consequent rows of matrix \f$C\f$ or \f$C^T\f$. @param beta \f$\beta\f$ multiplier before \f$C\f$ @param dst pointer to input \f$M\times K\f$ matrix \f$D\f$ stored in row major order. -@param dst_step number of bytes each matrix \f$D\f$ row occupies. +@param dst_step number of bytes between two consequent rows of matrix \f$D\f$. @param m number of rows in matrix \f$A\f$ or \f$A^T\f$, equals to number of rows in matrix \f$D\f$ @param n number of columns in matrix \f$A\f$ or \f$A^T\f$ @param k number of columns in matrix \f$B\f$ or \f$B^T\f$, equals to number of columns in matrix \f$D\f$ From 3ea02018b58c7b2955df259dda46837d2e5bc4d8 Mon Sep 17 00:00:00 2001 From: "PkLab.net" Date: Tue, 26 Jul 2016 16:48:30 +0200 Subject: [PATCH 053/178] Naming some enumerations in videoio --- modules/videoio/include/opencv2/videoio.hpp | 33 +++++++++++++++------ 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/modules/videoio/include/opencv2/videoio.hpp b/modules/videoio/include/opencv2/videoio.hpp index c462c67ce5..b769163cf3 100644 --- a/modules/videoio/include/opencv2/videoio.hpp +++ b/modules/videoio/include/opencv2/videoio.hpp @@ -48,6 +48,8 @@ /** @defgroup videoio Media I/O @{ + @defgroup videoio_flags_base Flags for video I/O + @defgroup videoio_flags_others Additional flags for video I/O API backends @defgroup videoio_c C API @defgroup videoio_ios iOS glue @defgroup videoio_winrt WinRT glue @@ -65,6 +67,8 @@ namespace cv //! @addtogroup videoio //! @{ +//! @addtogroup videoio_flags_base +//! @{ /** @brief Capture API backends. Select preferred API for a capture object. @@ -77,7 +81,8 @@ To enable/disable APIs, you have to: (e.g. -DWITH_MSMF=ON -DWITH_VFW=ON ... ) or checking related switch in cmake-gui 2. rebuild OpenCV itself */ -enum { CAP_ANY = 0, //!< Auto detect +enum VideoCaptureAPIs { + CAP_ANY = 0, //!< Auto detect CAP_VFW = 200, //!< Video For Windows (platform native) CAP_V4L = 200, //!< V4L/V4L2 capturing support via libv4l CAP_V4L2 = CAP_V4L, //!< Same as CAP_V4L @@ -108,7 +113,8 @@ enum { CAP_ANY = 0, //!< Auto detect }; //! generic properties (based on DC1394 properties) -enum { CAP_PROP_POS_MSEC =0, //!< Current position of the video file in milliseconds. +enum VideoCaptureProperties { + CAP_PROP_POS_MSEC =0, //!< Current position of the video file in milliseconds. CAP_PROP_POS_FRAMES =1, //!< 0-based index of the frame to be decoded/captured next. CAP_PROP_POS_AVI_RATIO =2, //!< Relative position of the video file: 0=start of the film, 1=end of the film. CAP_PROP_FRAME_WIDTH =3, //!< Width of the frames in the video stream. @@ -149,15 +155,27 @@ enum { CAP_PROP_POS_MSEC =0, //!< Current position of the video file in mi CAP_PROP_AUTOFOCUS =39 }; - //! @brief Generic camera output modes. //! @note Currently, these are supported through the libv4l interface only. -enum { CAP_MODE_BGR = 0, //!< BGR24 (default) +enum VideoCaptureModes { + CAP_MODE_BGR = 0, //!< BGR24 (default) CAP_MODE_RGB = 1, //!< RGB24 CAP_MODE_GRAY = 2, //!< Y8 CAP_MODE_YUYV = 3 //!< YUYV }; +/** @brief Generic properties identifier for VideoWriter +*/ +enum VideoWriterProperties { + VIDEOWRITER_PROP_QUALITY = 1, //!< Current quality (0..100%) of the encoded videostream. Can be adjusted dynamically in some codecs. + VIDEOWRITER_PROP_FRAMEBYTES = 2, //!< (Read-only): Size of just encoded video frame. Note that the encoding order may be different from representation order. + VIDEOWRITER_PROP_NSTRIPES = 3 //!< Number of stripes for parallel encoding. -1 for auto detection. +}; + +//! @} videoio_flags_base + +//! @addtogroup videoio_flags_others +//! @{ /** @brief DC1394 only @@ -465,11 +483,6 @@ enum { CAP_INTELPERC_DEPTH_MAP = 0, //!< Each pixel is a 16-bit int CAP_INTELPERC_IMAGE = 3 }; -enum { VIDEOWRITER_PROP_QUALITY = 1, //!< Current quality (0..100%) of the encoded videostream. Can be adjusted dynamically in some codecs. - VIDEOWRITER_PROP_FRAMEBYTES = 2, //!< (Read-only): Size of just encoded video frame. Note that the encoding order may be different from representation order. - VIDEOWRITER_PROP_NSTRIPES = 3 //!< Number of stripes for parallel encoding. -1 for auto detection. - }; - /** @brief gPhoto2 properties if propertyId is less than 0 then work on widget with that __additive inversed__ camera setting ID @@ -490,6 +503,8 @@ enum { CAP_PROP_GPHOTO2_PREVIEW = 17001, //!< Capture only preview fro //enum { +//! @} videoio_flags_others + class IVideoCapture; /** @brief Class for video capturing from video files, image sequences or cameras. The class provides C++ API From 86108012ce012571aaf7f814002ff4a4077eac3d Mon Sep 17 00:00:00 2001 From: Joe Howse Date: Thu, 11 Aug 2016 20:47:08 -0300 Subject: [PATCH 054/178] Improved cat face cascades (lower false positive rate) --- .../haarcascade_frontalcatface.xml | 12947 +++++++++------- .../haarcascade_frontalcatface_extended.xml | 12850 +++++++-------- .../lbpcascades/lbpcascade_frontalcatface.xml | 3756 +++-- 3 files changed, 15846 insertions(+), 13707 deletions(-) mode change 100644 => 100755 data/haarcascades/haarcascade_frontalcatface.xml mode change 100644 => 100755 data/haarcascades/haarcascade_frontalcatface_extended.xml diff --git a/data/haarcascades/haarcascade_frontalcatface.xml b/data/haarcascades/haarcascade_frontalcatface.xml old mode 100644 new mode 100755 index 0ec79f6ad9..cc3fb33d81 --- a/data/haarcascades/haarcascade_frontalcatface.xml +++ b/data/haarcascades/haarcascade_frontalcatface.xml @@ -22,14 +22,19 @@ KNOWN LIMITATIONS: - Sometimes, the detector mistakenly thinks that a human face is a cat face. In - situations where either a human or a cat might be encountered, use both a - human face detector and a cat face detector. Then, if a detected human face - and a detected cat face intersect, reject the cat face. - An upright subject is assumed. In situations where the cat's face might be sideways or upside down (e.g. the cat is rolling over), try various rotations of the input image. + + CHANGELOG: + + 2016-08-06: Re-trained with more negative samples and more stages. False + positives are much rarer now. If you tailored your code for the cascade's + previous version, now you should re-adjust the arguments of + CascadeClassifier::detectMultiScale. For example, decrease the value of the + minNeighbors argument. You do not need to use a human face detector to + cross-check the positives anymore. + 2014-04-25: First release (at https://bitbucket.org/Joe_Howse/angora-blue) ////////////////////////////////////////////////////////////////////////// | Contributors License Agreement @@ -39,7 +44,7 @@ | If you do not agree to this license, do not download, install, | copy or use the software. | - | Copyright (c) 2014, Joseph Howse (Nummist Media Corporation Limited, + | Copyright (c) 2014-2016, Joseph Howse (Nummist Media Corporation Limited, | Halifax, Nova Scotia, Canada). All rights reserved. | | Redistribution and use in source and binary forms, with or without @@ -77,7 +82,7 @@ 24 GAB - 9.9900001287460327e-01 + 9.9500000476837158e-01 5.0000000000000000e-01 9.4999999999999996e-01 1 @@ -86,5887 +91,6499 @@ 0 1 BASIC - 15 + 20 <_> - 25 - -1.7760953903198242e+00 + 16 + -1.4806525707244873e+00 <_> - 0 -1 445 -1.4772760681807995e-02 + 0 -1 472 -1.5126220881938934e-02 - 8.4035199880599976e-01 -1.2701500952243805e-01 + 7.5887596607208252e-01 -3.4230688214302063e-01 <_> - 0 -1 792 4.5831585302948952e-03 + 0 -1 839 3.9337221533060074e-03 - -2.3791725933551788e-01 6.1978793144226074e-01 + -3.3288389444351196e-01 5.2361363172531128e-01 <_> - 0 -1 813 -1.5044892206788063e-02 + 0 -1 858 -1.5044892206788063e-02 - 5.7160794734954834e-01 -2.0493283867835999e-01 + 5.5565774440765381e-01 -2.2505992650985718e-01 <_> - 0 -1 367 -1.2275323271751404e-02 + 0 -1 387 -1.2927042320370674e-02 - 5.7243120670318604e-01 -1.9821420311927795e-01 + 5.7442700862884521e-01 -1.9708566367626190e-01 <_> - 0 -1 842 8.3929381798952818e-04 + 0 -1 137 5.5960696190595627e-03 - -2.7865329384803772e-01 4.3508478999137878e-01 + -3.0430641770362854e-01 4.0241482853889465e-01 <_> - 0 -1 231 1.5758406370878220e-02 + 0 -1 207 1.5758406370878220e-02 - -2.2696593403816223e-01 4.9478942155838013e-01 + -1.9767063856124878e-01 4.5033392310142517e-01 <_> - 0 -1 581 5.0025805830955505e-02 + 0 -1 678 2.4262722581624985e-02 - -1.5532729029655457e-01 6.8103748559951782e-01 + -1.6931040585041046e-01 5.9707510471343994e-01 <_> - 0 -1 727 1.3194808736443520e-02 + 0 -1 267 -3.5242564976215363e-02 - -1.7704419791698456e-01 5.8701574802398682e-01 + 6.5973556041717529e-01 -1.4519356191158295e-01 <_> - 0 -1 5 2.8080096468329430e-02 + 0 -1 687 2.6568008586764336e-02 - -1.6797901690006256e-01 5.7502186298370361e-01 + -1.3476610183715820e-01 5.4296624660491943e-01 <_> - 0 -1 704 2.1941341459751129e-02 + 0 -1 228 4.7154121100902557e-02 - -1.4689344167709351e-01 5.2395468950271606e-01 + -1.7337851226329803e-01 4.6071702241897583e-01 <_> - 0 -1 279 -4.7663945704698563e-02 + 0 -1 925 -5.3081759251654148e-03 - 6.5710687637329102e-01 -1.1819842457771301e-01 + 5.4976856708526611e-01 -1.1913410574197769e-01 <_> - 0 -1 278 3.5373851656913757e-02 + 0 -1 608 5.3415738046169281e-02 - -9.7323395311832428e-02 7.4618083238601685e-01 + -1.2382411211729050e-01 6.3972741365432739e-01 <_> - 0 -1 254 1.4257467410061508e-04 + 0 -1 671 -3.0798995867371559e-03 - -2.8882622718811035e-01 2.8288537263870239e-01 + -8.2048600912094116e-01 1.0249497741460800e-01 <_> - 0 -1 253 3.8169793784618378e-02 + 0 -1 676 -2.3766520898789167e-03 - -1.4375060796737671e-01 4.9739924073219299e-01 + -7.0665025711059570e-01 6.7025005817413330e-02 <_> - 0 -1 142 6.5595638006925583e-03 + 0 -1 180 1.1965663870796561e-03 - 1.2217019498348236e-01 -6.4208990335464478e-01 + -2.4753804504871368e-01 3.0198124051094055e-01 <_> - 0 -1 753 -7.5260535813868046e-03 + 0 -1 830 -4.2106406763195992e-03 - -7.7927684783935547e-01 8.4750138223171234e-02 - <_> - - 0 -1 754 1.1342750862240791e-02 - - -2.2101284563541412e-01 3.4454554319381714e-01 - <_> - - 0 -1 645 -1.8045576289296150e-03 - - -7.8645682334899902e-01 9.7392335534095764e-02 - <_> - - 0 -1 457 -6.6228499636054039e-03 - - 3.1783181428909302e-01 -2.0665900409221649e-01 - <_> - - 0 -1 50 1.0336233302950859e-02 - - 9.1840714216232300e-02 -7.7336055040359497e-01 - <_> - - 0 -1 552 -2.4216776713728905e-02 - - 3.6742198467254639e-01 -1.9339990615844727e-01 - <_> - - 0 -1 64 1.4514809474349022e-02 - - -1.3652153313159943e-01 4.2311781644821167e-01 - <_> - - 0 -1 645 2.1728668361902237e-03 - - 7.9096116125583649e-02 -7.6427251100540161e-01 - <_> - - 0 -1 467 -3.9529249072074890e-02 - - 5.7755863666534424e-01 -1.0801278799772263e-01 - <_> - - 0 -1 640 1.5566367655992508e-02 - - -1.0259374976158142e-01 4.9773094058036804e-01 + 3.8455343246459961e-01 -1.8334107100963593e-01 <_> - 34 - -1.6417213678359985e+00 + 26 + -1.4618960618972778e+00 <_> - 0 -1 699 8.2648023962974548e-03 + 0 -1 725 1.0133055038750172e-02 - -1.0913594812154770e-01 7.7392864227294922e-01 + -2.8207325935363770e-01 6.2703561782836914e-01 <_> - 0 -1 697 1.4094283804297447e-02 + 0 -1 356 3.8468956947326660e-02 - -1.4461971819400787e-01 7.1108609437942505e-01 + -1.4483113586902618e-01 7.4971008300781250e-01 <_> - 0 -1 4 6.3192001543939114e-03 + 0 -1 2 -3.7523733917623758e-03 - -2.3035119473934174e-01 4.4546401500701904e-01 + 4.2959973216056824e-01 -2.1445912122726440e-01 <_> - 0 -1 227 2.0388111472129822e-02 + 0 -1 844 9.9978316575288773e-04 - -2.6455581188201904e-01 3.6559283733367920e-01 + -1.9259409606456757e-01 4.2325544357299805e-01 <_> - 0 -1 206 1.4826779253780842e-02 + 0 -1 387 -1.6786376014351845e-02 - -2.0881411433219910e-01 4.6142515540122986e-01 + 5.0582861900329590e-01 -1.8607729673385620e-01 <_> - 0 -1 821 2.1515905857086182e-02 + 0 -1 208 3.0330579727888107e-02 - -1.4785310626029968e-01 6.4220702648162842e-01 + -2.1100421249866486e-01 4.2819553613662720e-01 <_> - 0 -1 919 1.4720780309289694e-03 + 0 -1 206 1.5150709077715874e-02 - -2.2546350955963135e-01 3.6676284670829773e-01 + -2.1129198372364044e-01 3.6263525485992432e-01 <_> - 0 -1 814 -2.6044776663184166e-02 + 0 -1 451 -3.6349350120872259e-03 - 4.1465434432029724e-01 -1.5356495976448059e-01 + 3.9500275254249573e-01 -1.8650630116462708e-01 <_> - 0 -1 202 -1.0589402168989182e-02 + 0 -1 270 -7.2061517275869846e-03 - 4.1222676634788513e-01 -1.6899079084396362e-01 + -7.2816300392150879e-01 1.1153221875429153e-01 <_> - 0 -1 203 6.9683273322880268e-03 + 0 -1 866 -2.0212728530168533e-02 - 1.0854535549879074e-01 -7.1554762125015259e-01 + 5.6296736001968384e-01 -1.2056054919958115e-01 <_> - 0 -1 326 1.1014346033334732e-02 + 0 -1 265 2.5640423409640789e-03 - -1.7490877211093903e-01 4.4723153114318848e-01 + -2.3753854632377625e-01 3.5794413089752197e-01 <_> - 0 -1 387 -1.1037060990929604e-02 + 0 -1 230 -6.2726587057113647e-03 - 4.4173675775527954e-01 -1.3834878802299500e-01 + -6.7750877141952515e-01 1.2570948898792267e-01 <_> - 0 -1 581 6.2014400959014893e-02 + 0 -1 126 7.8710336238145828e-03 - -1.1345938593149185e-01 6.1101204156875610e-01 + 6.9211356341838837e-02 -7.6449161767959595e-01 <_> - 0 -1 318 6.0412874445319176e-03 + 0 -1 306 5.9134580194950104e-02 - 1.0154686868190765e-01 -7.2787815332412720e-01 + -1.7324967682361603e-01 3.3361187577247620e-01 <_> - 0 -1 281 -5.8582504279911518e-03 + 0 -1 185 -2.8770491480827332e-03 - -6.0382944345474243e-01 8.4109157323837280e-02 + 3.6101511120796204e-01 -1.6122241318225861e-01 <_> - 0 -1 885 7.3200068436563015e-04 + 0 -1 388 -5.7046953588724136e-03 - -1.6661356389522552e-01 3.7944686412811279e-01 + -6.7659336328506470e-01 8.4153175354003906e-02 <_> - 0 -1 702 1.9083185121417046e-02 + 0 -1 13 -7.8070178627967834e-02 - -1.2449446320533752e-01 4.2328220605850220e-01 + 6.0763663053512573e-01 -1.1037797480821609e-01 <_> - 0 -1 978 6.8236114457249641e-03 + 0 -1 321 6.5858578309416771e-03 - 1.0009460896253586e-01 -5.7412278652191162e-01 + 9.3060031533241272e-02 -7.0068693161010742e-01 <_> - 0 -1 655 -8.0357380211353302e-03 + 0 -1 796 -2.0920131355524063e-03 - 3.5114383697509766e-01 -1.5984705090522766e-01 + 2.8173315525054932e-01 -1.8406434357166290e-01 <_> - 0 -1 476 5.3236715495586395e-02 + 0 -1 578 -2.1252598613500595e-02 - -1.1999151855707169e-01 4.5052844285964966e-01 + 3.9672371745109558e-01 -1.5127600729465485e-01 <_> - 0 -1 380 -2.5083746761083603e-02 + 0 -1 770 -3.2937981188297272e-02 - 4.2925071716308594e-01 -1.3847301900386810e-01 + 3.9487251639366150e-01 -1.3228580355644226e-01 <_> - 0 -1 834 -7.7097099274396896e-03 + 0 -1 1016 4.9491915851831436e-03 - 4.2245966196060181e-01 -1.4710718393325806e-01 + 1.1234261840581894e-01 -4.7414371371269226e-01 <_> - 0 -1 22 1.1426717042922974e-02 + 0 -1 215 3.4271054901182652e-03 - 7.3091737926006317e-02 -7.6901757717132568e-01 + 7.8623600304126740e-02 -5.7828009128570557e-01 <_> - 0 -1 980 -4.7868257388472557e-03 + 0 -1 200 -6.0859560035169125e-03 - -5.4498624801635742e-01 8.9874587953090668e-02 + -5.0091904401779175e-01 9.1926425695419312e-02 <_> - 0 -1 797 9.9204876460134983e-04 + 0 -1 990 1.2116413563489914e-02 - -1.5133780241012573e-01 3.5266080498695374e-01 + -1.7154470086097717e-01 2.6759135723114014e-01 <_> - 0 -1 747 -7.3156114667654037e-03 + 0 -1 456 8.2814376801252365e-03 - -7.7262216806411743e-01 7.4858717620372772e-02 - <_> - - 0 -1 239 5.6915655732154846e-03 - - 5.7124871760606766e-02 -6.7257982492446899e-01 - <_> - - 0 -1 854 -9.5818340778350830e-03 - - 3.5280853509902954e-01 -1.5295246243476868e-01 - <_> - - 0 -1 155 2.3029895499348640e-02 - - 8.0654025077819824e-02 -6.6331261396408081e-01 - <_> - - 0 -1 63 8.3062853664159775e-03 - - -1.8261365592479706e-01 2.9241952300071716e-01 - <_> - - 0 -1 166 1.2940693646669388e-02 - - 6.2763690948486328e-02 -7.9858863353729248e-01 - <_> - - 0 -1 855 4.5793736353516579e-03 - - -1.6761651635169983e-01 2.8498283028602600e-01 - <_> - - 0 -1 639 3.1311963684856892e-03 - - 6.4963281154632568e-02 -7.1869355440139771e-01 - <_> - - 0 -1 438 6.2793528195470572e-04 - - -1.4610730111598969e-01 3.1872764229774475e-01 + -1.2938241660594940e-01 3.5665917396545410e-01 <_> - 47 - -1.8195210695266724e+00 + 26 + -1.4103703498840332e+00 <_> - 0 -1 389 2.8032548725605011e-02 + 0 -1 532 -1.0988018475472927e-02 - 3.9794921875000000e-02 7.6527571678161621e-01 + 6.4358645677566528e-01 -2.3149165511131287e-01 <_> - 0 -1 512 -1.3777698390185833e-02 + 0 -1 750 -7.8163212165236473e-03 - 4.8011425137519836e-01 -2.0891545712947845e-01 + 5.4850798845291138e-01 -1.7881108820438385e-01 <_> - 0 -1 768 -1.5191626735031605e-03 + 0 -1 289 7.1337133646011353e-02 - 4.3561527132987976e-01 -1.9825626909732819e-01 + -1.7631703615188599e-01 4.5873588323593140e-01 <_> - 0 -1 234 5.4982006549835205e-02 + 0 -1 549 5.2656695246696472e-02 - -1.9595552980899811e-01 5.1033991575241089e-01 + -1.3836050033569336e-01 5.6253266334533691e-01 <_> - 0 -1 2 -3.8968096487224102e-03 + 0 -1 8 1.5166129916906357e-02 - 3.6698764562606812e-01 -2.1704223752021790e-01 + -2.0990008115768433e-01 4.0483391284942627e-01 <_> - 0 -1 875 -1.0689822956919670e-02 + 0 -1 970 -1.4538960531353951e-03 - 5.7506144046783447e-01 -1.2323237210512161e-01 + 3.3692672848701477e-01 -2.1745139360427856e-01 <_> - 0 -1 423 -3.6211537662893534e-03 + 0 -1 875 1.1136244982481003e-02 - 3.9189809560775757e-01 -2.0496053993701935e-01 + -1.5003634989261627e-01 5.2208083868026733e-01 <_> - 0 -1 368 -5.6232484057545662e-03 + 0 -1 925 -3.3187635708600283e-03 - -7.0911335945129395e-01 8.9780956506729126e-02 + 3.9145255088806152e-01 -1.9418042898178101e-01 <_> - 0 -1 311 7.6950237154960632e-02 + 0 -1 485 4.9791105091571808e-02 - -1.6086885333061218e-01 3.9858064055442810e-01 + -1.0192432254552841e-01 5.4612094163894653e-01 <_> - 0 -1 211 -9.4812046736478806e-03 + 0 -1 828 4.3476112186908722e-02 - 4.4439849257469177e-01 -1.4388205111026764e-01 + -1.2768918275833130e-01 5.0825607776641846e-01 <_> - 0 -1 637 4.8636407591402531e-03 + 0 -1 719 -2.8149634599685669e-03 - 8.3068624138832092e-02 -7.4362516403198242e-01 + -7.0453292131423950e-01 1.2536850571632385e-01 <_> - 0 -1 616 -2.9443078674376011e-03 + 0 -1 846 1.6101204091683030e-03 - -6.1576569080352783e-01 8.1917040050029755e-02 + -2.6965174078941345e-01 2.2737979888916016e-01 <_> - 0 -1 573 -2.0938962697982788e-03 + 0 -1 715 -1.5866891480982304e-03 - -5.7727062702178955e-01 9.1147974133491516e-02 + -6.6891485452651978e-01 1.1686278134584427e-01 <_> - 0 -1 796 2.7704227250069380e-03 + 0 -1 677 -3.2338392920792103e-03 - -1.9285553693771362e-01 3.1007087230682373e-01 + -6.7284232378005981e-01 6.6228114068508148e-02 <_> - 0 -1 386 1.2979362159967422e-02 + 0 -1 479 -9.9909156560897827e-03 - -1.4128974080085754e-01 3.8875201344490051e-01 + 3.6961549520492554e-01 -1.5993835031986237e-01 <_> - 0 -1 61 -1.1832339689135551e-02 + 0 -1 350 4.8409838229417801e-02 - -7.8204095363616943e-01 7.2949714958667755e-02 + -1.0068884491920471e-01 5.0648134946823120e-01 <_> - 0 -1 265 3.3956445753574371e-02 + 0 -1 273 8.0585200339555740e-03 - -1.3892538845539093e-01 3.9772579073905945e-01 + -1.6782654821872711e-01 3.5382467508316040e-01 <_> - 0 -1 650 4.9063982442021370e-03 + 0 -1 338 -1.1718695983290672e-02 - 8.1131778657436371e-02 -7.2757917642593384e-01 + 4.3832498788833618e-01 -1.2780784070491791e-01 <_> - 0 -1 649 -2.3896694183349609e-03 + 0 -1 594 5.7147610932588577e-03 - -6.3438212871551514e-01 7.6958425343036652e-02 + 7.5814604759216309e-02 -7.2597140073776245e-01 <_> - 0 -1 27 2.7626976370811462e-02 + 0 -1 603 -2.0917234942317009e-03 - -1.7219249904155731e-01 3.7336668372154236e-01 + -6.0916984081268311e-01 8.4811411798000336e-02 <_> - 0 -1 539 3.9899977855384350e-03 + 0 -1 855 5.7651996612548828e-03 - 7.0482976734638214e-02 -6.6334074735641479e-01 + -1.9243443012237549e-01 2.8976503014564514e-01 <_> - 0 -1 503 -1.3984958641231060e-03 + 0 -1 565 -2.8093710541725159e-02 - 4.2500507831573486e-01 -1.2214981764554977e-01 + 5.4229170083999634e-01 -1.0005526244640350e-01 <_> - 0 -1 878 1.3496846659108996e-03 + 0 -1 136 8.9291334152221680e-03 - -1.1209741979837418e-01 4.0830954909324646e-01 + 8.3808921277523041e-02 -6.3219338655471802e-01 <_> - 0 -1 709 -3.9141997694969177e-03 + 0 -1 268 -5.1958961412310600e-03 - -5.3290998935699463e-01 9.4373866915702820e-02 + -5.4964137077331543e-01 7.9588212072849274e-02 <_> - 0 -1 153 4.9622595310211182e-02 + 0 -1 95 9.2318728566169739e-03 - -9.4219848513603210e-02 4.9830704927444458e-01 + -1.2818163633346558e-01 4.2056322097778320e-01 <_> - 0 -1 89 -6.2201134860515594e-02 + 0 -1 964 -2.0556427538394928e-02 - 5.1749163866043091e-01 -9.4065755605697632e-02 - <_> - - 0 -1 100 -9.0873138979077339e-03 - - -6.6816878318786621e-01 7.1877375245094299e-02 - <_> - - 0 -1 142 7.8745372593402863e-03 - - 6.2571905553340912e-02 -6.6562908887863159e-01 - <_> - - 0 -1 489 6.6907280124723911e-03 - - -1.0588129609823227e-01 4.0728682279586792e-01 - <_> - - 0 -1 811 8.9093092828989029e-03 - - -1.3461567461490631e-01 3.1837779283523560e-01 - <_> - - 0 -1 908 3.9681773632764816e-03 - - 7.1942776441574097e-02 -6.0182863473892212e-01 - <_> - - 0 -1 547 1.1530296877026558e-02 - - -1.2775546312332153e-01 3.0782708525657654e-01 - <_> - - 0 -1 497 -3.0327122658491135e-02 - - 3.6777910590171814e-01 -1.4219322800636292e-01 - <_> - - 0 -1 765 -8.5609289817512035e-04 - - 2.3868902027606964e-01 -1.7458973824977875e-01 - <_> - - 0 -1 30 -8.7312739342451096e-03 - - -5.7229250669479370e-01 6.7568361759185791e-02 - <_> - - 0 -1 515 3.6238119006156921e-02 - - -9.3856818974018097e-02 4.3806123733520508e-01 - <_> - - 0 -1 859 -1.7243899405002594e-02 - - 3.2672104239463806e-01 -1.2465524673461914e-01 - <_> - - 0 -1 571 3.0146117787808180e-03 - - 8.4438301622867584e-02 -4.7965818643569946e-01 - <_> - - 0 -1 390 -6.5812864340841770e-03 - - -6.5075701475143433e-01 5.2506592124700546e-02 - <_> - - 0 -1 379 -2.6519154198467731e-03 - - 3.9998021721839905e-01 -1.2199153006076813e-01 - <_> - - 0 -1 336 2.2568926215171814e-03 - - -1.1875165253877640e-01 3.6033150553703308e-01 - <_> - - 0 -1 342 7.8723561018705368e-03 - - 6.2930762767791748e-02 -7.2076427936553955e-01 - <_> - - 0 -1 826 5.7557085528969765e-04 - - -1.9064085185527802e-01 1.9888252019882202e-01 - <_> - - 0 -1 197 -4.9874491989612579e-02 - - 3.3844900131225586e-01 -1.0514739900827408e-01 - <_> - - 0 -1 934 -5.1496019586920738e-03 - - 2.3594251275062561e-01 -1.7097522318363190e-01 - <_> - - 0 -1 800 -4.2706914246082306e-03 - - 3.9194715023040771e-01 -9.3349114060401917e-02 - <_> - - 0 -1 493 -1.0737263411283493e-01 - - 5.6014204025268555e-01 -6.5082974731922150e-02 + 3.2048463821411133e-01 -1.3858842849731445e-01 <_> - 54 - -1.6577893495559692e+00 + 35 + -1.4265209436416626e+00 <_> - 0 -1 508 -9.3684419989585876e-03 + 0 -1 683 1.8821602687239647e-02 - 7.2173911333084106e-01 -1.8106427043676376e-02 + -1.7807419598102570e-01 5.9040957689285278e-01 <_> - 0 -1 255 1.2989062815904617e-03 + 0 -1 471 -9.5066539943218231e-03 - -2.0532198250293732e-01 4.2473095655441284e-01 + 5.0587177276611328e-01 -1.7767964303493500e-01 <_> - 0 -1 795 3.6645986139774323e-02 + 0 -1 884 1.3296608813107014e-03 - -1.6229844093322754e-01 5.1024991273880005e-01 + -1.6886346042156219e-01 3.6326614022254944e-01 <_> - 0 -1 163 7.4745947495102882e-03 + 0 -1 473 3.5266026854515076e-02 - -2.5622242689132690e-01 3.1706622242927551e-01 + -1.1824090778827667e-01 5.8951085805892944e-01 <_> - 0 -1 812 -6.4315330237150192e-03 + 0 -1 340 1.7804209142923355e-02 - 3.1292220950126648e-01 -2.2839428484439850e-01 + -1.4211210608482361e-01 5.1762068271636963e-01 <_> - 0 -1 341 3.9290782064199448e-02 + 0 -1 1001 4.7029324923641980e-04 - -1.3426035642623901e-01 5.8237910270690918e-01 + -2.4296821653842926e-01 2.5087893009185791e-01 <_> - 0 -1 459 7.8858569264411926e-02 + 0 -1 182 7.1838246658444405e-03 - -1.5872669219970703e-01 4.5478171110153198e-01 + 9.2609666287899017e-02 -6.7694115638732910e-01 <_> - 0 -1 528 -2.8797138482332230e-02 + 0 -1 390 -5.7565318420529366e-03 - 5.3397864103317261e-01 -1.1107259988784790e-01 + -7.3053181171417236e-01 8.2794629037380219e-02 <_> - 0 -1 376 -1.0816241614520550e-02 + 0 -1 203 2.0850602537393570e-02 - 4.7242766618728638e-01 -9.8347179591655731e-02 + -1.7353208363056183e-01 3.3287450671195984e-01 <_> - 0 -1 5 2.8447926044464111e-02 + 0 -1 805 3.1848326325416565e-03 - -1.5696190297603607e-01 3.9995491504669189e-01 + -2.0941653847694397e-01 2.6059800386428833e-01 <_> - 0 -1 594 -4.1472744196653366e-03 + 0 -1 234 -7.5752258300781250e-02 - -6.5492427349090576e-01 8.9378200471401215e-02 + 5.1588213443756104e-01 -1.0057342052459717e-01 <_> - 0 -1 780 3.7436613347381353e-03 + 0 -1 5 2.8725115582346916e-02 - -1.6716095805168152e-01 2.9251593351364136e-01 + -1.5012685954570770e-01 4.1436919569969177e-01 <_> - 0 -1 958 6.8116746842861176e-03 + 0 -1 175 -1.7325732856988907e-02 - 8.5507057607173920e-02 -6.0906678438186646e-01 + 3.8678762316703796e-01 -1.3586300611495972e-01 <_> - 0 -1 128 4.9823587760329247e-03 + 0 -1 47 -3.2187681645154953e-03 - 6.6678501665592194e-02 -5.8637374639511108e-01 + -5.1590150594711304e-01 1.1511231958866119e-01 <_> - 0 -1 401 4.1811540722846985e-03 + 0 -1 1020 -6.1595086008310318e-03 - -1.0231449455022812e-01 4.5615595579147339e-01 + -7.0271849632263184e-01 5.5648274719715118e-02 <_> - 0 -1 162 -1.0445066727697849e-02 + 0 -1 768 -8.7264683097600937e-03 - -7.6294642686843872e-01 5.7752605527639389e-02 + 2.6393634080886841e-01 -1.8446569144725800e-01 <_> - 0 -1 315 -6.1920420266687870e-03 + 0 -1 57 8.1868227571249008e-03 - -6.6523051261901855e-01 5.2041802555322647e-02 + 8.0838531255722046e-02 -5.5512112379074097e-01 <_> - 0 -1 925 -2.3358925245702267e-03 + 0 -1 139 -7.8468751162290573e-03 - 3.2779076695442200e-01 -1.3041152060031891e-01 + -5.7306796312332153e-01 8.3454042673110962e-02 <_> - 0 -1 314 -5.6658107787370682e-03 + 0 -1 665 2.9962153639644384e-03 - -6.8133842945098877e-01 5.6511644273996353e-02 + 6.2645487487316132e-02 -5.8123600482940674e-01 <_> - 0 -1 819 -1.0911209508776665e-02 + 0 -1 414 -4.3795984238386154e-03 - 3.3160626888275146e-01 -1.2574554979801178e-01 + 2.2211562097072601e-01 -1.9649308919906616e-01 <_> - 0 -1 765 -1.7958178650587797e-03 + 0 -1 908 -6.3172029331326485e-03 - 3.0492588877677917e-01 -1.5025834739208221e-01 + -6.6067039966583252e-01 6.4884319901466370e-02 <_> - 0 -1 961 -4.0859095752239227e-03 + 0 -1 465 1.3302030274644494e-03 - -5.3059929609298706e-01 7.3518328368663788e-02 + -1.0496762394905090e-01 4.2326071858406067e-01 <_> - 0 -1 232 -2.0980034023523331e-02 + 0 -1 951 -4.3333107605576515e-03 - 3.0610927939414978e-01 -1.2851184606552124e-01 + -4.9972066283226013e-01 8.7225496768951416e-02 <_> - 0 -1 452 -7.3018344119191170e-03 + 0 -1 244 -3.5346355289220810e-03 - 3.7514328956604004e-01 -1.2826474010944366e-01 + 3.0818134546279907e-01 -1.4765550196170807e-01 <_> - 0 -1 465 -2.9183469712734222e-02 + 0 -1 256 -8.7353587150573730e-03 - 4.8722788691520691e-01 -8.4734588861465454e-02 + -6.5214675664901733e-01 7.1881487965583801e-02 <_> - 0 -1 609 4.1865529492497444e-03 + 0 -1 491 -1.5620354562997818e-02 - 7.4395999312400818e-02 -5.8252948522567749e-01 + 3.5721915960311890e-01 -1.1427627503871918e-01 <_> - 0 -1 662 -1.3149678707122803e-02 + 0 -1 778 -3.9745438843965530e-03 - 2.9923921823501587e-01 -1.3687820732593536e-01 + -6.6090464591979980e-01 6.2067609280347824e-02 <_> - 0 -1 209 2.3594651371240616e-02 + 0 -1 689 -6.7040426656603813e-03 - 6.2197674065828323e-02 -6.3622504472732544e-01 + 2.7337384223937988e-01 -1.4059108495712280e-01 <_> - 0 -1 630 -1.7678245902061462e-02 + 0 -1 125 3.5359347239136696e-03 - 3.3281046152114868e-01 -1.2175620347261429e-01 + 6.1201948672533035e-02 -6.0017114877700806e-01 <_> - 0 -1 544 -1.0656865313649178e-02 + 0 -1 118 6.0818484053015709e-03 - 3.7733754515647888e-01 -1.0491474717855453e-01 + -1.5247075259685516e-01 2.4383027851581573e-01 <_> - 0 -1 710 5.6399200111627579e-03 + 0 -1 880 -7.2771648410707712e-04 - 5.4276369512081146e-02 -7.2659504413604736e-01 + 3.0065426230430603e-01 -1.2037902325391769e-01 <_> - 0 -1 536 5.9759367257356644e-02 + 0 -1 643 4.6168416738510132e-03 - -9.3571089208126068e-02 4.3768402934074402e-01 + 5.5311698466539383e-02 -7.5343269109725952e-01 <_> - 0 -1 836 1.5957858413457870e-03 + 0 -1 676 2.5280299596488476e-03 - -7.4856951832771301e-02 4.6114641427993774e-01 + 5.7204965502023697e-02 -5.3993463516235352e-01 <_> - 0 -1 331 -3.4797050058841705e-02 + 0 -1 878 1.5074670314788818e-02 - 4.3322169780731201e-01 -1.0314103215932846e-01 + -9.6106290817260742e-02 3.9084190130233765e-01 <_> - 0 -1 357 7.0810377597808838e-02 + 0 -1 831 -8.4932018071413040e-03 - -1.3931407034397125e-01 2.7839028835296631e-01 - <_> - - 0 -1 688 1.0995890479534864e-03 - - 8.2519724965095520e-02 -4.6114745736122131e-01 - <_> - - 0 -1 271 1.1323073413223028e-03 - - -1.1879909038543701e-01 3.1659367680549622e-01 - <_> - - 0 -1 59 2.5819817557930946e-02 - - -1.0563226789236069e-01 3.3343997597694397e-01 - <_> - - 0 -1 127 -3.0109258368611336e-03 - - -4.3363004922866821e-01 9.0100899338722229e-02 - <_> - - 0 -1 738 6.4696911722421646e-03 - - 4.3469883501529694e-02 -6.7987263202667236e-01 - <_> - - 0 -1 659 1.6815876588225365e-02 - - -9.4611480832099915e-02 3.5600626468658447e-01 - <_> - - 0 -1 642 -1.0637525469064713e-02 - - 1.9808849692344666e-01 -1.5571328997612000e-01 - <_> - - 0 -1 433 -4.1952659375965595e-03 - - -5.3476226329803467e-01 6.5039873123168945e-02 - <_> - - 0 -1 442 -1.5134566929191351e-03 - - 4.2552566528320312e-01 -8.3483003079891205e-02 - <_> - - 0 -1 375 -1.1657587019726634e-03 - - 2.4901403486728668e-01 -1.2862072885036469e-01 - <_> - - 0 -1 495 5.2369404584169388e-03 - - 5.4264735430479050e-02 -6.5448409318923950e-01 - <_> - - 0 -1 325 3.1857702415436506e-03 - - -1.0423248261213303e-01 3.4729331731796265e-01 - <_> - - 0 -1 468 3.2315873540937901e-03 - - 7.3592320084571838e-02 -4.5663174986839294e-01 - <_> - - 0 -1 61 8.1546325236558914e-03 - - 5.8343004435300827e-02 -4.7462043166160583e-01 - <_> - - 0 -1 261 1.2796278111636639e-02 - - -1.0276926308870316e-01 3.4186348319053650e-01 - <_> - - 0 -1 321 -2.3663226515054703e-02 - - 2.8974771499633789e-01 -1.2335656583309174e-01 - <_> - - 0 -1 648 -1.9080806523561478e-03 - - -7.0497012138366699e-01 5.8831237256526947e-02 - <_> - - 0 -1 633 3.0501103028655052e-03 - - 5.1351051777601242e-02 -5.2438431978225708e-01 - <_> - - 0 -1 204 -4.1300453245639801e-02 - - -4.2261663079261780e-01 6.5464369952678680e-02 + 3.4130987524986267e-01 -1.4117397367954254e-01 <_> - 66 - -1.6743642091751099e+00 + 37 + -1.3977209329605103e+00 <_> - 0 -1 699 1.3901394791901112e-02 + 0 -1 794 -2.5338861159980297e-03 - 4.2875479906797409e-02 7.1057194471359253e-01 + 5.7321399450302124e-01 -2.0396080613136292e-01 <_> - 0 -1 444 -1.0640731081366539e-02 + 0 -1 588 -6.5112011507153511e-03 - 5.9900563955307007e-01 -1.4475977420806885e-01 + 3.7378740310668945e-01 -2.5049039721488953e-01 <_> - 0 -1 763 -4.2351996526122093e-03 + 0 -1 238 1.6318978741765022e-03 - 4.9660456180572510e-01 -1.1618923395872116e-01 + -2.1858637034893036e-01 3.5027471184730530e-01 <_> - 0 -1 834 1.3073073700070381e-02 + 0 -1 189 3.3452022820711136e-02 - -1.6428959369659424e-01 5.0240677595138550e-01 + -1.4827065169811249e-01 4.7324529290199280e-01 <_> - 0 -1 879 -5.0384560599923134e-03 + 0 -1 192 -1.1114047840237617e-02 - 4.1822317242622375e-01 -1.4690572023391724e-01 + 4.1662359237670898e-01 -2.1660456061363220e-01 <_> - 0 -1 443 1.2402677675709128e-03 + 0 -1 527 -1.2996498262509704e-03 - -2.0295573770999908e-01 2.7518931031227112e-01 + 4.7613915801048279e-01 -1.6742442548274994e-01 <_> - 0 -1 688 -1.8025336321443319e-03 + 0 -1 648 -3.2986078877002001e-03 - -7.3610079288482666e-01 7.6008267700672150e-02 + -6.7662662267684937e-01 8.6653761565685272e-02 <_> - 0 -1 282 9.2999219894409180e-02 + 0 -1 4 6.6831205040216446e-03 - -1.4368277788162231e-01 3.3687326312065125e-01 + -2.0158858597278595e-01 2.6189696788787842e-01 <_> - 0 -1 293 2.1399226039648056e-02 + 0 -1 482 2.1282089874148369e-03 - -1.6605213284492493e-01 3.0147713422775269e-01 + -1.1156299710273743e-01 4.0097075700759888e-01 <_> - 0 -1 703 9.3348361551761627e-03 + 0 -1 682 -9.0472139418125153e-03 - -1.6568347811698914e-01 3.0875685811042786e-01 + 3.2078295946121216e-01 -1.6775439679622650e-01 <_> - 0 -1 382 -5.8921691961586475e-03 + 0 -1 226 -5.3160609677433968e-03 - -5.6214910745620728e-01 8.5347160696983337e-02 + -5.5567348003387451e-01 1.2950280308723450e-01 <_> - 0 -1 260 -1.4118023682385683e-03 + 0 -1 205 7.9724024981260300e-03 - 2.6530963182449341e-01 -1.8439114093780518e-01 + -2.1466700732707977e-01 2.2514854371547699e-01 <_> - 0 -1 360 -1.1060921475291252e-02 + 0 -1 920 -2.1980279125273228e-03 - 2.5005301833152771e-01 -1.7930330336093903e-01 + 2.8711742162704468e-01 -1.6561916470527649e-01 <_> - 0 -1 751 -3.8227883633226156e-03 + 0 -1 312 5.3897619247436523e-02 - -6.9963920116424561e-01 6.4229309558868408e-02 + -1.4823001623153687e-01 3.4951418638229370e-01 <_> - 0 -1 900 -8.4845684468746185e-03 + 0 -1 13 -7.6241128146648407e-02 - -6.6004335880279541e-01 5.2848633378744125e-02 + 6.0101884603500366e-01 -8.8328786194324493e-02 <_> - 0 -1 21 6.9843865931034088e-03 + 0 -1 129 -8.3202747628092766e-03 - 5.5426578968763351e-02 -6.1068946123123169e-01 + -7.2828358411788940e-01 8.7956465780735016e-02 <_> - 0 -1 952 4.8600544687360525e-04 + 0 -1 401 5.3778752684593201e-02 - -1.8981190025806427e-01 2.1059055626392365e-01 + -1.0316975414752960e-01 5.0247919559478760e-01 <_> - 0 -1 111 3.5324528813362122e-02 + 0 -1 416 -1.2401826679706573e-02 - -8.3993434906005859e-02 5.1941823959350586e-01 + 2.7538898587226868e-01 -1.5569972991943359e-01 <_> - 0 -1 97 3.9002462290227413e-03 + 0 -1 986 1.3729928061366081e-02 - 7.6367795467376709e-02 -5.7813030481338501e-01 + -1.3373774290084839e-01 3.0739122629165649e-01 <_> - 0 -1 374 -4.5398771762847900e-03 + 0 -1 905 -2.2788168862462044e-03 - 3.3430457115173340e-01 -1.2331557273864746e-01 + 2.2555501759052277e-01 -1.9497908651828766e-01 <_> - 0 -1 652 -3.1904221978038549e-03 + 0 -1 667 3.6288173869252205e-03 - -5.5545800924301147e-01 7.3627986013889313e-02 + 4.8981692641973495e-02 -7.9248648881912231e-01 <_> - 0 -1 14 -7.7975630760192871e-02 + 0 -1 85 5.2453137934207916e-02 - 4.8881098628044128e-01 -8.1377774477005005e-02 + -1.3389803469181061e-01 3.2700663805007935e-01 <_> - 0 -1 7 -1.1978685855865479e-02 + 0 -1 821 3.1685843132436275e-03 - 2.7509516477584839e-01 -1.6613669693470001e-01 + -1.4415425062179565e-01 2.8044179081916809e-01 <_> - 0 -1 29 -8.3151785656809807e-03 + 0 -1 193 8.9051481336355209e-03 - -5.9314393997192383e-01 7.2014525532722473e-02 + 6.1227656900882721e-02 -7.0277702808380127e-01 <_> - 0 -1 466 1.3827871531248093e-02 + 0 -1 837 -1.3966157566756010e-03 - -1.2803319096565247e-01 2.9465702176094055e-01 + 4.2409667372703552e-01 -1.0888981819152832e-01 <_> - 0 -1 356 2.0103808492422104e-02 + 0 -1 271 -6.7695947363972664e-03 - 6.9175720214843750e-02 -5.6205666065216064e-01 + -5.1588076353073120e-01 8.3254821598529816e-02 <_> - 0 -1 530 -4.7183044254779816e-02 + 0 -1 404 2.2157761268317699e-03 - 3.6449643969535828e-01 -1.0480687767267227e-01 + -1.3696527481079102e-01 2.8638482093811035e-01 <_> - 0 -1 613 9.7303036600351334e-03 + 0 -1 619 2.7808796148747206e-03 - -9.7578004002571106e-02 3.6821505427360535e-01 + 7.1316704154014587e-02 -6.0322999954223633e-01 <_> - 0 -1 667 -3.9133569225668907e-03 + 0 -1 515 4.5836241915822029e-03 - -5.1443296670913696e-01 7.2868466377258301e-02 + -1.2486589699983597e-01 3.2929363846778870e-01 <_> - 0 -1 666 3.0236630700528622e-03 + 0 -1 1042 -5.1459800451993942e-03 - 5.5799212306737900e-02 -5.3572463989257812e-01 + -5.3781992197036743e-01 7.6631128787994385e-02 <_> - 0 -1 304 4.3436158448457718e-03 + 0 -1 1043 2.4449056945741177e-03 - -1.5579865872859955e-01 2.0468661189079285e-01 + 8.5920669138431549e-02 -4.0670683979988098e-01 <_> - 0 -1 51 1.4063127338886261e-02 + 0 -1 71 -2.7756379917263985e-02 - 3.6827385425567627e-02 -8.5656464099884033e-01 + 3.7449231743812561e-01 -1.0538945347070694e-01 <_> - 0 -1 842 1.3388927327468991e-03 + 0 -1 809 -1.8243372440338135e-02 - -1.2769578397274017e-01 2.8884974122047424e-01 + 3.4281516075134277e-01 -9.9502928555011749e-02 <_> - 0 -1 791 -1.0684424778446555e-03 + 0 -1 372 3.8416781462728977e-03 - 3.4348404407501221e-01 -9.6543140709400177e-02 + 7.3987491428852081e-02 -4.8903524875640869e-01 <_> - 0 -1 779 -2.3754546418786049e-03 + 0 -1 376 -1.2322908267378807e-02 - -5.2730453014373779e-01 6.6801987588405609e-02 + 2.1036790311336517e-01 -1.5852701663970947e-01 <_> - 0 -1 549 -4.5106699690222740e-03 + 0 -1 391 -4.1760304011404514e-03 - -5.4066735506057739e-01 5.1074951887130737e-02 + 3.1288132071495056e-01 -1.1697492748498917e-01 <_> - 0 -1 487 5.6549627333879471e-03 + 0 -1 859 -2.8026863932609558e-02 - -9.0248994529247284e-02 3.5249757766723633e-01 - <_> - - 0 -1 494 -3.3719413913786411e-03 - - 2.8907671570777893e-01 -1.1475016921758652e-01 - <_> - - 0 -1 135 1.2221395969390869e-02 - - -1.0579165816307068e-01 3.0012521147727966e-01 - <_> - - 0 -1 79 3.2931473106145859e-03 - - 7.7675424516201019e-02 -4.1641706228256226e-01 - <_> - - 0 -1 79 -3.7331613712012768e-03 - - -4.6958047151565552e-01 7.6012723147869110e-02 - <_> - - 0 -1 15 -3.0090190470218658e-02 - - -6.2376546859741211e-01 4.4617597013711929e-02 - <_> - - 0 -1 538 -1.1998139321804047e-02 - - 3.4000751376152039e-01 -9.7472421824932098e-02 - <_> - - 0 -1 592 2.5055123493075371e-02 - - -7.5190685689449310e-02 4.1993573307991028e-01 - <_> - - 0 -1 233 9.7161782905459404e-03 - - 5.5982969701290131e-02 -6.0615026950836182e-01 - <_> - - 0 -1 198 -8.3486355841159821e-02 - - 3.7426739931106567e-01 -8.7825424969196320e-02 - <_> - - 0 -1 110 3.8952599279582500e-03 - - -1.3330259919166565e-01 2.6031884551048279e-01 - <_> - - 0 -1 648 -9.8262424580752850e-04 - - -3.9980980753898621e-01 8.2922257483005524e-02 - <_> - - 0 -1 58 8.4215197712182999e-03 - - -1.3371372222900391e-01 2.4220858514308929e-01 - <_> - - 0 -1 287 1.2292047031223774e-03 - - -7.7718295156955719e-02 3.8342806696891785e-01 - <_> - - 0 -1 682 -1.2375478632748127e-02 - - 2.3885957896709442e-01 -1.2220640480518341e-01 - <_> - - 0 -1 292 5.4268687963485718e-03 - - 5.5337987840175629e-02 -5.6287312507629395e-01 - <_> - - 0 -1 418 -5.5062575265765190e-03 - - -5.7845181226730347e-01 4.2599424719810486e-02 - <_> - - 0 -1 614 1.0439271107316017e-02 - - -8.1215575337409973e-02 3.8115817308425903e-01 - <_> - - 0 -1 296 -2.6399283669888973e-03 - - -4.5001742243766785e-01 6.7338116466999054e-02 - <_> - - 0 -1 898 2.6166734751313925e-03 - - 5.5316500365734100e-02 -4.4958963990211487e-01 - <_> - - 0 -1 759 5.4496107622981071e-03 - - -8.1449449062347412e-02 3.8300925493240356e-01 - <_> - - 0 -1 762 3.4203347750008106e-03 - - -8.8027402758598328e-02 3.0551746487617493e-01 - <_> - - 0 -1 19 9.3909027054905891e-03 - - 5.8738458901643753e-02 -4.9437648057937622e-01 - <_> - - 0 -1 276 9.6318572759628296e-03 - - -1.0816254466772079e-01 2.7723982930183411e-01 - <_> - - 0 -1 87 1.9004285335540771e-02 - - -8.2863554358482361e-02 3.1288793683052063e-01 - <_> - - 0 -1 580 -8.5283098742365837e-03 - - 2.9951119422912598e-01 -8.9406743645668030e-02 - <_> - - 0 -1 242 6.2621399760246277e-02 - - -1.0106554627418518e-01 2.6782277226448059e-01 - <_> - - 0 -1 372 1.5604515559971333e-02 - - -1.0081429034471512e-01 2.9597061872482300e-01 - <_> - - 0 -1 351 1.3034233450889587e-01 - - -8.0539934337139130e-02 3.4444472193717957e-01 - <_> - - 0 -1 53 4.5186877250671387e-02 - - 5.8131664991378784e-02 -5.4693692922592163e-01 + 3.3711743354797363e-01 -1.2294299900531769e-01 <_> - 72 - -1.6700928211212158e+00 + 42 + -1.3775455951690674e+00 <_> - 0 -1 763 -2.0017849747091532e-03 + 0 -1 725 1.3382414355874062e-02 - 6.7056620121002197e-01 1.8883759155869484e-02 + -1.7922241985797882e-01 5.0368404388427734e-01 <_> - 0 -1 508 -1.5712467953562737e-02 + 0 -1 967 1.9935802556574345e-03 - 5.8154827356338501e-01 -1.4273743331432343e-01 + -2.5249919295310974e-01 3.5295018553733826e-01 <_> - 0 -1 146 2.4972280953079462e-03 + 0 -1 891 -1.3569685397669673e-03 - -1.8454430997371674e-01 3.4281551837921143e-01 + 4.1222429275512695e-01 -1.8140394985675812e-01 <_> - 0 -1 824 5.7405559346079826e-03 + 0 -1 911 2.5418698787689209e-03 - -1.7856663465499878e-01 5.1571351289749146e-01 + -2.3195247352123260e-01 2.5945317745208740e-01 <_> - 0 -1 869 8.1182969734072685e-04 + 0 -1 362 1.1867792345583439e-03 - -2.6075574755668640e-01 2.2161382436752319e-01 + -1.1509010195732117e-01 4.0095508098602295e-01 <_> - 0 -1 889 1.9957972690463066e-03 + 0 -1 280 -4.0491363033652306e-03 - -1.6690193116664886e-01 3.1083983182907104e-01 + -7.6275551319122314e-01 8.0663219094276428e-02 <_> - 0 -1 943 7.9797822982072830e-03 + 0 -1 264 2.4698153138160706e-02 - -1.7903617024421692e-01 2.7573335170745850e-01 + -9.9053405225276947e-02 4.6469488739967346e-01 <_> - 0 -1 733 1.0206390172243118e-02 + 0 -1 832 1.3041709549725056e-02 - -9.3843363225460052e-02 5.3358590602874756e-01 + -1.3049817085266113e-01 4.7066822648048401e-01 <_> - 0 -1 388 3.4904260188341141e-02 + 0 -1 257 -2.0927201956510544e-02 - -8.6874812841415405e-02 5.0340282917022705e-01 + -7.2363191843032837e-01 7.5520738959312439e-02 <_> - 0 -1 564 -3.8090778980404139e-03 + 0 -1 41 1.6108792275190353e-02 - 2.3382174968719482e-01 -1.7857478559017181e-01 + 8.9385204017162323e-02 -5.0678378343582153e-01 <_> - 0 -1 160 2.0690055098384619e-03 + 0 -1 872 -8.6308103054761887e-03 - -1.8347945809364319e-01 2.1276330947875977e-01 + 3.1878158450126648e-01 -1.3526505231857300e-01 <_> - 0 -1 367 -1.3203858397901058e-02 + 0 -1 347 1.2651814613491297e-03 - 3.0799895524978638e-01 -1.0921970754861832e-01 + -1.2344279885292053e-01 4.0271109342575073e-01 <_> - 0 -1 91 1.6044422984123230e-02 + 0 -1 735 -3.0170590616762638e-03 - -1.2722490727901459e-01 3.5042104125022888e-01 + -5.6960099935531616e-01 7.0437252521514893e-02 <_> - 0 -1 52 -2.8435707092285156e-02 + 0 -1 538 -3.5529488231986761e-03 - -6.9257086515426636e-01 6.0832630842924118e-02 + 2.0624065399169922e-01 -1.8426756560802460e-01 <_> - 0 -1 593 -3.5719089210033417e-03 + 0 -1 735 2.8021419420838356e-03 - -6.1009460687637329e-01 5.5150210857391357e-02 + 7.2748780250549316e-02 -5.3796368837356567e-01 <_> - 0 -1 526 -3.3032532781362534e-02 + 0 -1 447 -9.9331419914960861e-04 - 3.9706656336784363e-01 -1.0905303061008453e-01 + 2.4827398359775543e-01 -1.5866567194461823e-01 <_> - 0 -1 863 -3.4918042365461588e-03 + 0 -1 440 -7.1950745768845081e-03 - 2.2872641682624817e-01 -1.6809244453907013e-01 + -5.0943744182586670e-01 7.3041573166847229e-02 <_> - 0 -1 449 -1.2281725648790598e-03 + 0 -1 906 -8.7737981230020523e-03 - 2.8336051106452942e-01 -1.2107009440660477e-01 + 2.4838714301586151e-01 -1.5162147581577301e-01 <_> - 0 -1 268 1.5130165964365005e-02 + 0 -1 608 5.6750684976577759e-02 - 7.4081726372241974e-02 -5.0906944274902344e-01 + -8.4416143596172333e-02 4.4269657135009766e-01 <_> - 0 -1 342 -5.2624624222517014e-03 + 0 -1 772 1.8110256642103195e-03 - -5.1471787691116333e-01 5.6423079222440720e-02 + -1.7787678539752960e-01 2.2753682732582092e-01 <_> - 0 -1 438 1.3198424130678177e-03 + 0 -1 117 6.1733853071928024e-02 - -9.7633212804794312e-02 3.6938476562500000e-01 + -1.4452947676181793e-01 2.6785543560981750e-01 <_> - 0 -1 194 -3.9102118462324142e-03 + 0 -1 718 1.7999792471528053e-03 - -7.5149536132812500e-01 5.1220502704381943e-02 + 5.3869031369686127e-02 -7.0216673612594604e-01 <_> - 0 -1 235 7.7746850438416004e-03 + 0 -1 718 -1.7839821521192789e-03 - -1.6232925653457642e-01 2.0670217275619507e-01 + -7.3474282026290894e-01 4.3809492141008377e-02 <_> - 0 -1 555 -1.9946731626987457e-02 + 0 -1 795 -2.2269869223237038e-03 - 3.0092230439186096e-01 -9.9984362721443176e-02 + 2.5256577134132385e-01 -1.4765015244483948e-01 <_> - 0 -1 457 -4.9132145941257477e-03 + 0 -1 845 7.7408831566572189e-04 - 2.1954736113548279e-01 -1.6271042823791504e-01 + -1.6781617701053619e-01 2.5267890095710754e-01 <_> - 0 -1 970 -6.4505757763981819e-03 + 0 -1 710 9.6316616982221603e-03 - -4.9815052747726440e-01 6.7167595028877258e-02 + 5.8525908738374710e-02 -6.3684886693954468e-01 <_> - 0 -1 581 -6.7926600575447083e-02 + 0 -1 181 -1.1892126873135567e-02 - 4.3458208441734314e-01 -7.7230423688888550e-02 + 2.6363542675971985e-01 -1.4106634259223938e-01 <_> - 0 -1 789 -3.7927636876702309e-03 + 0 -1 326 4.8407237976789474e-02 - 2.6469963788986206e-01 -1.2098944932222366e-01 + -1.0837136209011078e-01 3.6018091440200806e-01 <_> - 0 -1 38 -2.7826299890875816e-02 + 0 -1 572 -1.0315750539302826e-01 - 2.9173719882965088e-01 -1.0972167551517487e-01 + -7.3309695720672607e-01 6.4976803958415985e-02 <_> - 0 -1 332 6.0029705055058002e-03 + 0 -1 415 -2.6544972788542509e-03 - -1.0543220490217209e-01 3.6175185441970825e-01 + 2.7709859609603882e-01 -1.3764445483684540e-01 <_> - 0 -1 972 1.4797106850892305e-03 + 0 -1 1033 -4.8850756138563156e-03 - 6.5247461199760437e-02 -5.3303873538970947e-01 + -5.0026285648345947e-01 6.8797707557678223e-02 <_> - 0 -1 102 9.7709074616432190e-03 + 0 -1 299 -1.1310833506286144e-02 - 3.5595752298831940e-02 -6.8972426652908325e-01 + 2.5653550028800964e-01 -1.3755545020103455e-01 <_> - 0 -1 874 4.5413424959406257e-04 + 0 -1 152 -3.8394361734390259e-02 - -1.7233507335186005e-01 1.6001893579959869e-01 + 2.6404461264610291e-01 -1.3614650070667267e-01 <_> - 0 -1 687 -1.4395804610103369e-03 + 0 -1 486 5.8298893272876740e-03 - -5.1606172323226929e-01 5.5443800985813141e-02 + 6.0382172465324402e-02 -5.9578329324722290e-01 <_> - 0 -1 25 -2.4502794444561005e-01 + 0 -1 393 2.2631133906543255e-03 - -8.0270200967788696e-01 2.9995493590831757e-02 + -1.0302778333425522e-01 3.4782779216766357e-01 <_> - 0 -1 410 4.2062443681061268e-03 + 0 -1 629 -1.8709234893321991e-02 - 5.0134483724832535e-02 -4.9082162976264954e-01 + -7.6758313179016113e-01 4.6181913465261459e-02 <_> - 0 -1 46 1.4561998657882214e-02 + 0 -1 67 3.7359733134508133e-02 - -1.2065179646015167e-01 2.4143299460411072e-01 + -1.3407541811466217e-01 2.5607112050056458e-01 <_> - 0 -1 74 -3.3104062080383301e-02 + 0 -1 504 -5.3099328652024269e-03 - 3.6770820617675781e-01 -7.8033976256847382e-02 + -6.9016355276107788e-01 4.7683756798505783e-02 <_> - 0 -1 463 3.2625906169414520e-02 + 0 -1 527 -1.5396323287859559e-03 - -8.5231229662895203e-02 3.3994022011756897e-01 + 3.7874689698219299e-01 -9.2663109302520752e-02 <_> - 0 -1 411 -1.1897137388586998e-02 + 0 -1 470 -2.6333518326282501e-03 - 2.6476562023162842e-01 -1.0443684458732605e-01 + 2.9358446598052979e-01 -1.2460695207118988e-01 <_> - 0 -1 816 5.7352259755134583e-03 + 0 -1 171 1.6515964642167091e-02 - 5.5395182222127914e-02 -5.1973640918731689e-01 + -1.4082725346088409e-01 2.3664724826812744e-01 <_> - 0 -1 170 -1.5062794089317322e-02 + 0 -1 681 -4.4658156111836433e-03 - -7.5300645828247070e-01 3.0149688944220543e-02 - <_> - - 0 -1 661 -7.9075228422880173e-03 - - 2.8287026286125183e-01 -1.0227695107460022e-01 - <_> - - 0 -1 394 3.2159998081624508e-03 - - -6.5929308533668518e-02 3.6590230464935303e-01 - <_> - - 0 -1 987 -2.5269058533012867e-03 - - -4.7419819235801697e-01 5.8165557682514191e-02 - <_> - - 0 -1 845 -1.8206760287284851e-03 - - 2.5627982616424561e-01 -1.1308469623327255e-01 - <_> - - 0 -1 66 1.4899271540343761e-02 - - 3.6266356706619263e-02 -7.6167815923690796e-01 - <_> - - 0 -1 965 3.8532419130206108e-03 - - 2.6696149259805679e-02 -7.5058454275131226e-01 - <_> - - 0 -1 723 -6.1673661693930626e-03 - - 3.5572922229766846e-01 -8.2323268055915833e-02 - <_> - - 0 -1 822 -7.0832269266247749e-03 - - 2.1490900218486786e-01 -1.3906964659690857e-01 - <_> - - 0 -1 724 3.5079419612884521e-03 - - 4.7017443925142288e-02 -6.3156962394714355e-01 - <_> - - 0 -1 878 1.2706735869869590e-03 - - -1.0659208893775940e-01 3.1986060738563538e-01 - <_> - - 0 -1 362 -3.0069730710238218e-03 - - -7.9292476177215576e-01 3.8936499506235123e-02 - <_> - - 0 -1 3 2.5489944964647293e-03 - - -1.4662979543209076e-01 2.0257341861724854e-01 - <_> - - 0 -1 151 2.7439245022833347e-03 - - -9.1609120368957520e-02 3.0721578001976013e-01 - <_> - - 0 -1 608 -2.5972947478294373e-03 - - -4.2591169476509094e-01 6.7926779389381409e-02 - <_> - - 0 -1 717 1.4116591773927212e-03 - - -1.2321621179580688e-01 2.4072754383087158e-01 - <_> - - 0 -1 603 -2.5579232722520828e-02 - - 5.7537192106246948e-01 -4.9050308763980865e-02 - <_> - - 0 -1 407 -5.6264195591211319e-03 - - -5.2892494201660156e-01 6.0454059392213821e-02 - <_> - - 0 -1 413 -1.8926127813756466e-03 - - 2.4074989557266235e-01 -1.2150175124406815e-01 - <_> - - 0 -1 96 -1.0207362473011017e-02 - - -6.7782247066497803e-01 4.3572813272476196e-02 - <_> - - 0 -1 157 -3.1391347292810678e-03 - - 1.9982162117958069e-01 -1.3408482074737549e-01 - <_> - - 0 -1 218 -3.1065782532095909e-03 - - 2.2946853935718536e-01 -1.2754726409912109e-01 - <_> - - 0 -1 866 -5.2223210223019123e-03 - - -5.0463259220123291e-01 4.9872294068336487e-02 - <_> - - 0 -1 428 -3.4163258969783783e-03 - - 2.1628817915916443e-01 -1.1369658261537552e-01 - <_> - - 0 -1 901 5.1404302939772606e-03 - - -9.6477277576923370e-02 2.4602085351943970e-01 - <_> - - 0 -1 425 5.8603808283805847e-03 - - 4.0628310292959213e-02 -6.3314515352249146e-01 - <_> - - 0 -1 936 -1.1338826734572649e-03 - - 3.4083816409111023e-01 -7.9400509595870972e-02 - <_> - - 0 -1 936 8.0572068691253662e-04 - - -9.5763482153415680e-02 3.2283502817153931e-01 - <_> - - 0 -1 431 -4.8957285471260548e-03 - - -5.3353887796401978e-01 4.9622885882854462e-02 - <_> - - 0 -1 675 7.1027994155883789e-02 - - -6.2327813357114792e-02 4.5151355862617493e-01 - <_> - - 0 -1 911 -1.5200550667941570e-02 - - 2.5859493017196655e-01 -1.0548926889896393e-01 + -5.9253305196762085e-01 5.5994171649217606e-02 <_> - 81 - -1.5793150663375854e+00 + 50 + -1.3835698366165161e+00 <_> - 0 -1 562 -5.8624427765607834e-03 + 0 -1 898 1.5156399458646774e-03 - 6.2237185239791870e-01 -1.5120165422558784e-02 + -1.0024535655975342e-01 5.8807808160781860e-01 <_> - 0 -1 507 4.7948276624083519e-03 + 0 -1 802 -3.5168868489563465e-03 - -1.8684723973274231e-01 4.3783110380172729e-01 + 4.0972998738288879e-01 -1.6088742017745972e-01 <_> - 0 -1 870 2.4864529259502888e-03 + 0 -1 180 2.3035616613924503e-03 - -1.9763210415840149e-01 3.4098726511001587e-01 + -1.8985269963741302e-01 2.9883998632431030e-01 <_> - 0 -1 210 -7.7013596892356873e-03 + 0 -1 254 4.5840561389923096e-02 - 3.4580937027931213e-01 -2.2749660909175873e-01 + -1.4383240044116974e-01 4.7528687119483948e-01 <_> - 0 -1 768 -1.8182904459536076e-03 + 0 -1 405 5.5156396701931953e-03 - 3.7125843763351440e-01 -1.4019212126731873e-01 + -1.7356806993484497e-01 3.4583050012588501e-01 <_> - 0 -1 791 -1.4325398951768875e-03 + 0 -1 436 3.9731184951961040e-03 - 4.4040992856025696e-01 -1.0599569976329803e-01 + 7.8886620700359344e-02 -5.6442558765411377e-01 <_> - 0 -1 161 5.4927580058574677e-03 + 0 -1 412 -5.6995991617441177e-03 - 8.4835931658744812e-02 -5.3435057401657104e-01 + -4.7576662898063660e-01 9.4875656068325043e-02 <_> - 0 -1 837 -7.0448440965265036e-04 + 0 -1 539 -9.6501735970377922e-03 - 2.8704917430877686e-01 -1.4405579864978790e-01 + 2.3381656408309937e-01 -1.8310526013374329e-01 <_> - 0 -1 220 -5.7945270091295242e-03 + 0 -1 209 6.1656545847654343e-02 - -5.1373738050460815e-01 8.3974525332450867e-02 + -1.4697165787220001e-01 3.6247691512107849e-01 <_> - 0 -1 376 -1.1944295838475227e-02 + 0 -1 398 1.1418928205966949e-01 - 3.5980853438377380e-01 -1.0862441360950470e-01 + -8.8033527135848999e-02 4.4633501768112183e-01 <_> - 0 -1 385 3.4179994836449623e-03 + 0 -1 3 -1.1903396807610989e-02 - -1.2899027764797211e-01 3.3064863085746765e-01 + 3.3496665954589844e-01 -1.2121009081602097e-01 <_> - 0 -1 805 -7.2756269946694374e-03 + 0 -1 546 -4.1371315717697144e-02 - 2.3903866112232208e-01 -1.6133096814155579e-01 + 4.1400006413459778e-01 -9.7229279577732086e-02 <_> - 0 -1 647 -8.5910838097333908e-03 + 0 -1 380 7.8342631459236145e-03 - -8.4211397171020508e-01 4.1614245623350143e-02 + -1.6631671786308289e-01 2.5738984346389771e-01 <_> - 0 -1 283 -3.7941135466098785e-02 + 0 -1 304 -4.5139621943235397e-03 - 2.4674071371555328e-01 -1.4177341759204865e-01 + -4.6883803606033325e-01 8.7662570178508759e-02 <_> - 0 -1 149 -3.6782763898372650e-02 + 0 -1 929 1.5914421528577805e-03 - 3.1695553660392761e-01 -1.1061279475688934e-01 + -1.1636006087064743e-01 3.2739594578742981e-01 <_> - 0 -1 31 -1.1086702346801758e-01 + 0 -1 942 -5.2607608959078789e-03 - -7.7248167991638184e-01 4.9090590327978134e-02 + -6.7755740880966187e-01 5.1752120256423950e-02 <_> - 0 -1 23 -4.3419219553470612e-02 + 0 -1 941 3.1824512407183647e-03 - -6.3905894756317139e-01 4.7248683869838715e-02 + 5.2379645407199860e-02 -6.0918039083480835e-01 <_> - 0 -1 229 7.1155801415443420e-03 + 0 -1 939 -3.6813789047300816e-03 - 5.5369954556226730e-02 -5.6675219535827637e-01 + 4.8251116275787354e-01 -9.2318780720233917e-02 <_> - 0 -1 9 2.9427852481603622e-02 + 0 -1 622 -4.3226117268204689e-03 - -1.0744783282279968e-01 3.1137129664421082e-01 + -5.7561415433883667e-01 5.9672243893146515e-02 <_> - 0 -1 13 -5.6870315223932266e-02 + 0 -1 250 -7.1843853220343590e-03 - 4.8549285531044006e-01 -8.4140487015247345e-02 + 2.6631006598472595e-01 -1.4015418291091919e-01 <_> - 0 -1 845 -2.1800836548209190e-03 + 0 -1 871 2.1028071641921997e-03 - 3.0136430263519287e-01 -1.0869345813989639e-01 + -1.1286304146051407e-01 3.5946926474571228e-01 <_> - 0 -1 345 1.2336489744484425e-03 + 0 -1 22 8.5248583927750587e-03 - -8.9073576033115387e-02 3.3233630657196045e-01 + 6.9424033164978027e-02 -5.2462881803512573e-01 <_> - 0 -1 737 2.7930366341024637e-03 + 0 -1 147 6.9785099476575851e-03 - -1.1784177273511887e-01 2.3968270421028137e-01 + 5.6668873876333237e-02 -5.6192052364349365e-01 <_> - 0 -1 300 -1.4338749647140503e-01 + 0 -1 474 -5.2639590576291084e-03 - 4.7303047776222229e-01 -5.1608867943286896e-02 + -5.8648955821990967e-01 5.0352573394775391e-02 <_> - 0 -1 113 7.9552028328180313e-03 + 0 -1 406 2.8417459689080715e-03 - 6.0302641242742538e-02 -4.7011384367942810e-01 + -1.3425759971141815e-01 2.7325555682182312e-01 <_> - 0 -1 397 -4.6112807467579842e-03 + 0 -1 394 -1.3187457807362080e-02 - -4.2084765434265137e-01 7.6558656990528107e-02 + 4.0453648567199707e-01 -9.1843754053115845e-02 <_> - 0 -1 361 7.8915785998106003e-03 + 0 -1 722 -6.7344801500439644e-03 - -1.3884299993515015e-01 2.0495900511741638e-01 + -7.5647395849227905e-01 5.0157479941844940e-02 <_> - 0 -1 196 -2.9021099209785461e-02 + 0 -1 187 2.1363141015172005e-02 - 3.3683353662490845e-01 -8.6431317031383514e-02 + 4.7982390969991684e-02 -5.5388218164443970e-01 <_> - 0 -1 32 8.7932050228118896e-03 + 0 -1 623 1.6145884292200208e-03 - -1.2117365747690201e-01 2.3939569294452667e-01 + 7.9808227717876434e-02 -3.7233716249465942e-01 <_> - 0 -1 692 -4.3326904997229576e-03 + 0 -1 525 -2.2595757618546486e-03 - -6.3044422864913940e-01 4.8393115401268005e-02 + 2.8343635797500610e-01 -1.1216876655817032e-01 <_> - 0 -1 729 -1.6151482705026865e-03 + 0 -1 214 1.4407988637685776e-02 - 3.0203807353973389e-01 -9.2361047863960266e-02 + -1.0392460227012634e-01 3.1299999356269836e-01 <_> - 0 -1 239 -3.6242920905351639e-03 + 0 -1 476 -1.4912552433088422e-03 - -4.0946927666664124e-01 7.3978066444396973e-02 + 2.8538599610328674e-01 -1.0644508898258209e-01 <_> - 0 -1 142 -8.0828834325075150e-03 + 0 -1 195 9.8895151168107986e-03 - -6.1597609519958496e-01 4.0132850408554077e-02 + 5.0090074539184570e-02 -6.2053185701370239e-01 <_> - 0 -1 427 -1.8987425137311220e-03 + 0 -1 115 4.2754956521093845e-03 - 2.5910443067550659e-01 -1.0553860664367676e-01 + 6.5051443874835968e-02 -4.2582303285598755e-01 <_> - 0 -1 776 3.4845639020204544e-03 + 0 -1 754 -2.5489409454166889e-03 - 4.1376896202564240e-02 -6.4275610446929932e-01 + 3.1278640031814575e-01 -9.9601686000823975e-02 <_> - 0 -1 728 -1.3704899698495865e-02 + 0 -1 717 -6.0358326882123947e-03 - 2.7235555648803711e-01 -1.0047114640474319e-01 + 2.2685267031192780e-01 -1.3849361240863800e-01 <_> - 0 -1 88 -9.5059927552938461e-03 + 0 -1 875 1.1879121884703636e-02 - 2.3305405676364899e-01 -1.2722322344779968e-01 + -8.9687183499336243e-02 3.7642294168472290e-01 <_> - 0 -1 424 -1.7753308638930321e-02 + 0 -1 111 1.2982923537492752e-02 - 2.7121108770370483e-01 -9.8972275853157043e-02 + 4.3990727514028549e-02 -7.3371982574462891e-01 <_> - 0 -1 60 4.1816420853137970e-02 + 0 -1 993 -2.8599319048225880e-03 - -8.6314909160137177e-02 2.9308396577835083e-01 + -4.3102917075157166e-01 5.9561621397733688e-02 <_> - 0 -1 470 -5.2781165577471256e-03 + 0 -1 737 -3.5829999251291156e-04 - -4.3240407109260559e-01 6.6678449511528015e-02 + 1.7152757942676544e-01 -1.6511310636997223e-01 <_> - 0 -1 947 -3.5982416011393070e-03 + 0 -1 27 2.5972571223974228e-02 - -4.0664613246917725e-01 5.9939380735158920e-02 + -1.2855969369411469e-01 2.2820757329463959e-01 <_> - 0 -1 350 -3.3817887306213379e-03 + 0 -1 516 4.2565623298287392e-03 - 2.1198178827762604e-01 -1.2401402741670609e-01 + 5.7662181556224823e-02 -5.3734982013702393e-01 <_> - 0 -1 148 -8.4468610584735870e-03 + 0 -1 50 -2.9159568250179291e-02 - -5.0658410787582397e-01 5.6176334619522095e-02 + -6.3020753860473633e-01 4.0746636688709259e-02 <_> - 0 -1 522 -1.5873050317168236e-02 + 0 -1 413 3.1341956928372383e-03 - 3.0237907171249390e-01 -8.9766949415206909e-02 + -8.1374719738960266e-02 4.1371321678161621e-01 <_> - 0 -1 948 5.2925320342183113e-03 + 0 -1 935 -1.3592604082077742e-03 - 4.7194946557283401e-02 -5.8447927236557007e-01 + 3.2382342219352722e-01 -9.7880341112613678e-02 <_> - 0 -1 514 -1.4822685159742832e-02 + 0 -1 758 -6.9904811680316925e-03 - 2.7581340074539185e-01 -1.0343603044748306e-01 + -6.8850576877593994e-01 4.2428225278854370e-02 <_> - 0 -1 678 -1.2328238226473331e-02 + 0 -1 93 -8.7879784405231476e-03 - 1.9257421791553497e-01 -1.3730424642562866e-01 + -5.8945190906524658e-01 3.7613209336996078e-02 <_> - 0 -1 887 5.4736144840717316e-02 + 0 -1 491 -1.7947785556316376e-02 - -1.0764957219362259e-01 2.4070124328136444e-01 + 3.1659606099128723e-01 -8.7437197566032410e-02 <_> - 0 -1 484 -2.0030699670314789e-03 + 0 -1 490 8.0379713326692581e-03 - 2.8992170095443726e-01 -8.6155213415622711e-02 + -1.1311284452676773e-01 3.0860018730163574e-01 <_> - 0 -1 347 4.9616778269410133e-03 + 0 -1 716 3.0642822384834290e-03 - 3.7793070077896118e-02 -6.8241751194000244e-01 - <_> - - 0 -1 171 2.1582433953881264e-02 - - -9.2316769063472748e-02 2.6424714922904968e-01 - <_> - - 0 -1 131 -9.5060802996158600e-03 - - 2.0518042147159576e-01 -1.1375468224287033e-01 - <_> - - 0 -1 238 7.4238084256649017e-02 - - -7.0650860667228699e-02 3.3061835169792175e-01 - <_> - - 0 -1 567 5.8014206588268280e-03 - - 3.9557952433824539e-02 -6.0553658008575439e-01 - <_> - - 0 -1 489 8.3722146227955818e-03 - - -6.6242359578609467e-02 3.5559263825416565e-01 - <_> - - 0 -1 115 5.9322156012058258e-03 - - 5.1374353468418121e-02 -4.4348692893981934e-01 - <_> - - 0 -1 503 -1.5613199211657047e-03 - - 3.3984366059303284e-01 -7.1964941918849945e-02 - <_> - - 0 -1 201 -1.6189547255635262e-02 - - 2.0777270197868347e-01 -1.2065915018320084e-01 - <_> - - 0 -1 589 3.7794266827404499e-03 - - 4.0290340781211853e-02 -5.5574357509613037e-01 - <_> - - 0 -1 213 -9.3125496059656143e-03 - - 2.5648719072341919e-01 -9.4139434397220612e-02 - <_> - - 0 -1 927 8.9797464897856116e-04 - - -1.0596609860658646e-01 3.0083754658699036e-01 - <_> - - 0 -1 593 4.1124280542135239e-03 - - 4.3452557176351547e-02 -5.6017982959747314e-01 - <_> - - 0 -1 447 -5.7592550292611122e-03 - - -5.5715996026992798e-01 3.6530554294586182e-02 - <_> - - 0 -1 956 -1.7109992913901806e-03 - - 2.4350115656852722e-01 -9.9780716001987457e-02 - <_> - - 0 -1 975 -1.9408876076340675e-02 - - -7.3736822605133057e-01 3.4421972930431366e-02 - <_> - - 0 -1 269 -1.8505988642573357e-02 - - 2.3959811031818390e-01 -1.0179302841424942e-01 - <_> - - 0 -1 974 -3.4968159161508083e-03 - - -4.5450085401535034e-01 5.2533198148012161e-02 - <_> - - 0 -1 722 3.2340791076421738e-03 - - -9.7867593169212341e-02 2.5210717320442200e-01 - <_> - - 0 -1 853 -2.1103646140545607e-03 - - 2.7718135714530945e-01 -8.3934187889099121e-02 - <_> - - 0 -1 310 -6.0913376510143280e-03 - - -5.0269359350204468e-01 4.7654323279857635e-02 - <_> - - 0 -1 316 -1.4657910168170929e-01 - - -5.8180803060531616e-01 3.7255339324474335e-02 - <_> - - 0 -1 721 -5.7285130023956299e-02 - - -8.1681364774703979e-01 2.3416126146912575e-02 - <_> - - 0 -1 560 -1.0855928063392639e-02 - - 1.6488714516162872e-01 -1.3668881356716156e-01 - <_> - - 0 -1 511 1.4742083847522736e-02 - - 3.0842842534184456e-02 -7.8335261344909668e-01 - <_> - - 0 -1 701 -1.8798124045133591e-02 - - 3.1507465243339539e-01 -7.6406344771385193e-02 - <_> - - 0 -1 458 1.8614485859870911e-02 - - -8.0178938806056976e-02 3.0463775992393494e-01 - <_> - - 0 -1 803 -4.1011158376932144e-02 - - -6.7428815364837646e-01 3.5076040774583817e-02 - <_> - - 0 -1 260 -1.5514190308749676e-03 - - 1.9351305067539215e-01 -1.0952673852443695e-01 - <_> - - 0 -1 83 7.6966043561697006e-03 - - 3.2414216548204422e-02 -6.0751897096633911e-01 - <_> - - 0 -1 154 -1.7850721254944801e-02 - - 2.0461367070674896e-01 -1.0080502927303314e-01 - <_> - - 0 -1 298 2.3059733211994171e-03 - - -1.3565167784690857e-01 1.7179486155509949e-01 + 4.8351831734180450e-02 -6.0563534498214722e-01 <_> - 88 - -1.6158927679061890e+00 + 54 + -1.3756012916564941e+00 <_> - 0 -1 877 3.6321599036455154e-03 + 0 -1 798 -1.7431776504963636e-03 - 8.3464950323104858e-02 7.0313382148742676e-01 + 5.5538344383239746e-01 -1.0357239097356796e-01 <_> - 0 -1 450 -2.8561335057020187e-03 + 0 -1 425 4.4551412574946880e-03 - 5.3444284200668335e-01 -1.4426039159297943e-01 + -1.2460361421108246e-01 5.1942145824432373e-01 <_> - 0 -1 767 -1.6910845879465342e-03 + 0 -1 843 3.5308140795677900e-03 - 4.5417416095733643e-01 -1.4539502561092377e-01 + -2.2974169254302979e-01 2.7043044567108154e-01 <_> - 0 -1 330 2.4872912093997002e-02 + 0 -1 532 -1.5887852758169174e-02 - -1.5180622041225433e-01 4.7290563583374023e-01 + 4.1745069622993469e-01 -1.1281611770391464e-01 <_> - 0 -1 326 -1.3844612985849380e-02 + 0 -1 7 1.1611310765147209e-02 - 4.3979367613792419e-01 -1.9149754941463470e-01 + -1.9416445493698120e-01 2.5554594397544861e-01 <_> - 0 -1 223 -2.0526167005300522e-02 + 0 -1 935 1.5740045346319675e-03 - 3.5583654046058655e-01 -1.7526121437549591e-01 + -1.2263108044862747e-01 3.8852572441101074e-01 <_> - 0 -1 513 -1.0601939633488655e-02 + 0 -1 547 5.1882643252611160e-02 - 2.1787860989570618e-01 -1.8377628922462463e-01 + -7.5461924076080322e-02 5.0257563591003418e-01 <_> - 0 -1 43 1.5976445749402046e-02 + 0 -1 251 -3.8624972105026245e-02 - 8.6497880518436432e-02 -4.3799200654029846e-01 + 4.0001305937767029e-01 -9.6231088042259216e-02 <_> - 0 -1 698 -4.9493601545691490e-03 + 0 -1 272 -3.9408572018146515e-02 - 2.3401068150997162e-01 -1.5603557229042053e-01 + 3.0533725023269653e-01 -1.6677139699459076e-01 <_> - 0 -1 182 2.8549194335937500e-02 + 0 -1 29 7.5884531252086163e-03 - -1.4324828982353210e-01 2.4674744904041290e-01 + 9.8107770085334778e-02 -5.8249044418334961e-01 <_> - 0 -1 125 5.9233225882053375e-02 + 0 -1 218 7.2114326059818268e-02 - -1.0831536352634430e-01 3.3649173378944397e-01 + -1.4419755339622498e-01 2.8208708763122559e-01 <_> - 0 -1 436 9.5888428390026093e-02 + 0 -1 268 5.5582458153367043e-03 - -1.0589215904474258e-01 3.7052422761917114e-01 + 7.2843901813030243e-02 -5.5255079269409180e-01 <_> - 0 -1 453 -7.5694853439927101e-03 + 0 -1 877 -4.7345291823148727e-03 - 2.3113159835338593e-01 -1.4907826483249664e-01 + 3.3209753036499023e-01 -1.2499606609344482e-01 <_> - 0 -1 496 4.7857249155640602e-03 + 0 -1 577 5.1413839682936668e-03 - 5.1639214158058167e-02 -6.2650465965270996e-01 + 6.4787313342094421e-02 -6.4880597591400146e-01 <_> - 0 -1 145 5.4310320410877466e-04 + 0 -1 999 5.4608630016446114e-03 - -1.8886238336563110e-01 1.5287129580974579e-01 + 3.7491828203201294e-02 -7.5315922498703003e-01 <_> - 0 -1 941 2.6117763482034206e-03 + 0 -1 542 -8.6404485045932233e-05 - 6.6002741456031799e-02 -4.4275501370429993e-01 + 1.7464619874954224e-01 -1.8258170783519745e-01 <_> - 0 -1 940 -8.0328416079282761e-03 + 0 -1 442 6.1132330447435379e-03 - -5.1598960161209106e-01 5.6888539344072342e-02 + 7.5624085962772369e-02 -4.3711006641387939e-01 <_> - 0 -1 842 1.2324389535933733e-03 + 0 -1 889 -7.0670098066329956e-03 - -1.2387900799512863e-01 2.6769712567329407e-01 + 2.1796958148479462e-01 -1.4547325670719147e-01 <_> - 0 -1 830 -9.7260549664497375e-03 + 0 -1 347 9.4080460257828236e-04 - 3.5000637173652649e-01 -1.0784699767827988e-01 + -1.2536728382110596e-01 2.8143358230590820e-01 <_> - 0 -1 334 8.6696096695959568e-04 + 0 -1 580 -2.6800869964063168e-03 - -1.1435680836439133e-01 2.5563576817512512e-01 + -4.2977494001388550e-01 8.2963027060031891e-02 <_> - 0 -1 258 -3.4542869776487350e-02 + 0 -1 297 5.8945640921592712e-03 - -5.8313912153244019e-01 5.1875289529561996e-02 + 4.2834181338548660e-02 -6.0937494039535522e-01 <_> - 0 -1 342 7.5529976747930050e-03 + 0 -1 465 1.0121082887053490e-03 - 3.6179721355438232e-02 -6.9380182027816772e-01 + -1.1036285758018494e-01 2.9971688985824585e-01 <_> - 0 -1 550 4.0939049795269966e-03 + 0 -1 56 3.1157936900854111e-03 - 4.1062511503696442e-02 -5.9848028421401978e-01 + 7.3115289211273193e-02 -4.3226471543312073e-01 <_> - 0 -1 354 2.8113774023950100e-03 + 0 -1 411 -3.3052214421331882e-03 - 5.5211704224348068e-02 -4.7554171085357666e-01 + -4.9826300144195557e-01 5.1225960254669189e-02 <_> - 0 -1 353 -3.5045309923589230e-03 + 0 -1 109 8.3188470453023911e-03 - -3.9402753114700317e-01 6.9415092468261719e-02 + 5.0362452864646912e-02 -4.8688000440597534e-01 <_> - 0 -1 373 1.7898422665894032e-03 + 0 -1 393 -2.5094528682529926e-03 - -7.6636046171188354e-02 4.0437600016593933e-01 + 2.6902040839195251e-01 -1.0433372855186462e-01 <_> - 0 -1 486 4.0369415655732155e-03 + 0 -1 924 1.1217880528420210e-03 - -9.7471550107002258e-02 2.7784994244575500e-01 + -1.1188100278377533e-01 3.1254816055297852e-01 <_> - 0 -1 430 -8.5533969104290009e-03 + 0 -1 716 -2.9259414877742529e-03 - 3.3252051472663879e-01 -1.0098887234926224e-01 + -5.7495939731597900e-01 5.3564101457595825e-02 <_> - 0 -1 69 2.6041156053543091e-01 + 0 -1 733 -1.1687271296977997e-02 - -4.3942935764789581e-02 5.0610113143920898e-01 + 2.5880128145217896e-01 -1.0639669001102448e-01 <_> - 0 -1 892 1.4894269406795502e-03 + 0 -1 763 3.5054073669016361e-03 - -7.6404698193073273e-02 3.0335766077041626e-01 + 5.4045904427766800e-02 -5.5625277757644653e-01 <_> - 0 -1 101 -4.8547232151031494e-01 + 0 -1 552 1.9068794324994087e-02 - 6.1892670392990112e-01 -3.9150018244981766e-02 + -1.1246301978826523e-01 2.5745245814323425e-01 <_> - 0 -1 895 -7.6227495446801186e-04 + 0 -1 230 4.6145436353981495e-03 - 1.9151827692985535e-01 -1.2709514796733856e-01 + 6.7216314375400543e-02 -4.1385611891746521e-01 <_> - 0 -1 553 -4.8853931948542595e-03 + 0 -1 857 -8.2267355173826218e-03 - -5.6353646516799927e-01 4.4611949473619461e-02 + 2.1265375614166260e-01 -1.3443692028522491e-01 <_> - 0 -1 649 1.8246687250211835e-03 + 0 -1 149 -1.4355888590216637e-02 - 6.3832193613052368e-02 -3.6079093813896179e-01 + 2.5618723034858704e-01 -1.0785522311925888e-01 <_> - 0 -1 2 -3.7001366727054119e-03 + 0 -1 61 8.0431215465068817e-03 - 1.9149990379810333e-01 -1.3052800297737122e-01 + -1.4258129894733429e-01 2.2692860662937164e-01 <_> - 0 -1 324 -5.1008379086852074e-03 + 0 -1 170 -5.6914249435067177e-03 - 4.0633511543273926e-01 -6.6167853772640228e-02 + -4.8886317014694214e-01 6.0331270098686218e-02 <_> - 0 -1 15 -1.7046853899955750e-02 + 0 -1 133 -2.5912215933203697e-03 - -3.5266619920730591e-01 7.1908973157405853e-02 + 2.1062785387039185e-01 -1.4967896044254303e-01 <_> - 0 -1 415 7.4824336916208267e-03 + 0 -1 461 5.5204275995492935e-03 - 5.7628002017736435e-02 -4.6899631619453430e-01 + -8.1333734095096588e-02 3.8316065073013306e-01 <_> - 0 -1 955 -1.0255416855216026e-02 + 0 -1 515 5.3790090605616570e-03 - -5.3142738342285156e-01 4.1362568736076355e-02 + -9.3129634857177734e-02 3.2883483171463013e-01 <_> - 0 -1 500 2.2401358000934124e-03 + 0 -1 199 -7.2196200489997864e-03 - -7.4236951768398285e-02 3.2401573657989502e-01 + -6.6427856683731079e-01 4.4702950865030289e-02 <_> - 0 -1 893 -1.1338146403431892e-02 + 0 -1 94 -8.3873540163040161e-02 - -5.8281844854354858e-01 4.3767549097537994e-02 + -7.9910254478454590e-01 2.7107261121273041e-02 <_> - 0 -1 532 8.4229296771809459e-04 + 0 -1 513 -3.4268260933458805e-03 - -1.2624698877334595e-01 1.8474358320236206e-01 + 2.5298807024955750e-01 -1.0898132622241974e-01 <_> - 0 -1 117 2.7594935148954391e-02 + 0 -1 763 -3.7466005887836218e-03 - 4.2021647095680237e-02 -5.0711041688919067e-01 + -5.5346089601516724e-01 5.2094604820013046e-02 <_> - 0 -1 828 3.0329828150570393e-03 + 0 -1 276 1.2452949304133654e-03 - -7.0778228342533112e-02 3.3471760153770447e-01 + -8.2017965614795685e-02 3.5483068227767944e-01 <_> - 0 -1 984 -8.9767086319625378e-04 + 0 -1 1013 -6.2445802614092827e-03 - -2.8313115239143372e-01 8.4212802350521088e-02 + -5.0969594717025757e-01 5.4533429443836212e-02 <_> - 0 -1 912 -4.3688914738595486e-03 + 0 -1 276 -1.1970927007496357e-03 - -4.8104682564735413e-01 4.6536806970834732e-02 + 3.6470764875411987e-01 -7.7394872903823853e-02 <_> - 0 -1 817 -6.5738772973418236e-03 + 0 -1 757 3.0796977225691080e-03 - 1.8955506384372711e-01 -1.1803213506937027e-01 + 5.3208738565444946e-02 -5.0689512491226196e-01 <_> - 0 -1 768 1.6207897569984198e-03 + 0 -1 33 -3.9015077054500580e-02 - -6.5827853977680206e-02 3.2122904062271118e-01 + 1.9598089158535004e-01 -1.3218660652637482e-01 <_> - 0 -1 641 4.8786089755594730e-03 + 0 -1 680 -7.7085788361728191e-03 - 3.4384466707706451e-02 -7.0796263217926025e-01 + 2.2754703462123871e-01 -1.2544488906860352e-01 <_> - 0 -1 118 -7.3928516358137131e-03 + 0 -1 655 3.2509677112102509e-02 - -4.5154401659965515e-01 4.3622057884931564e-02 + -6.7099742591381073e-02 4.1469818353652954e-01 <_> - 0 -1 287 2.2087101824581623e-03 + 0 -1 569 3.0232844874262810e-03 - -4.4949851930141449e-02 4.9991622567176819e-01 + 6.6373795270919800e-02 -4.2127549648284912e-01 <_> - 0 -1 187 2.9001948423683643e-03 + 0 -1 54 2.5392756797373295e-03 - 5.1781963557004929e-02 -4.2971140146255493e-01 + -1.1576391756534576e-01 2.3464009165763855e-01 <_> - 0 -1 287 -9.9636090453714132e-04 + 0 -1 1013 6.8497275933623314e-03 - 3.0347472429275513e-01 -7.4883252382278442e-02 + 4.5596633106470108e-02 -5.8435302972793579e-01 <_> - 0 -1 121 6.3986405730247498e-03 + 0 -1 231 -4.4358119368553162e-02 - 3.8914524018764496e-02 -5.6881076097488403e-01 - <_> - - 0 -1 433 -5.2966945804655552e-03 - - -5.5442500114440918e-01 3.3734291791915894e-02 - <_> - - 0 -1 540 9.2505104839801788e-03 - - -9.5525965094566345e-02 2.2353705763816833e-01 - <_> - - 0 -1 942 3.2701031304895878e-03 - - -8.7515957653522491e-02 2.7356430888175964e-01 - <_> - - 0 -1 938 -9.0824589133262634e-03 - - 2.2333034873008728e-01 -9.6923373639583588e-02 - <_> - - 0 -1 981 -3.0515873804688454e-03 - - -4.0757030248641968e-01 5.0947520881891251e-02 - <_> - - 0 -1 518 6.3385991379618645e-03 - - -6.0888923704624176e-02 3.5273307561874390e-01 - <_> - - 0 -1 568 -3.4346987958997488e-03 - - 2.9356080293655396e-01 -8.1172131001949310e-02 - <_> - - 0 -1 141 -3.9428919553756714e-03 - - -4.9512249231338501e-01 4.4033303856849670e-02 - <_> - - 0 -1 363 -9.1780513525009155e-02 - - -3.9046007394790649e-01 5.0150144845247269e-02 - <_> - - 0 -1 259 -6.6375046968460083e-02 - - -6.0851734876632690e-01 3.0974121764302254e-02 - <_> - - 0 -1 621 -6.9266660138964653e-03 - - -7.3090195655822754e-01 2.3663638159632683e-02 - <_> - - 0 -1 105 -3.5928614437580109e-02 - - 1.8060323596000671e-01 -1.1467467248439789e-01 - <_> - - 0 -1 848 -4.6623144298791885e-03 - - 2.3666681349277496e-01 -1.0607369244098663e-01 - <_> - - 0 -1 597 6.3546001911163330e-02 - - 3.3510908484458923e-02 -6.6823011636734009e-01 - <_> - - 0 -1 303 1.0070858988910913e-03 - - -1.1336669325828552e-01 1.9138091802597046e-01 - <_> - - 0 -1 297 2.0964080467820168e-03 - - -1.3783766329288483e-01 1.6943521797657013e-01 - <_> - - 0 -1 278 -3.7955917418003082e-02 - - 4.2277663946151733e-01 -5.3925208747386932e-02 - <_> - - 0 -1 915 1.5981765463948250e-03 - - 7.2201833128929138e-02 -2.9906082153320312e-01 - <_> - - 0 -1 266 -1.0036448948085308e-03 - - 3.0661484599113464e-01 -7.1594037115573883e-02 - <_> - - 0 -1 167 -8.7398784235119820e-03 - - -4.0562248229980469e-01 5.0554409623146057e-02 - <_> - - 0 -1 132 3.8445743266493082e-03 - - 3.0860245227813721e-02 -5.6328177452087402e-01 - <_> - - 0 -1 559 2.9180462006479502e-03 - - -9.4123579561710358e-02 2.1829530596733093e-01 - <_> - - 0 -1 705 -4.4532963074743748e-03 - - 2.2356307506561279e-01 -1.0032130777835846e-01 - <_> - - 0 -1 979 2.8718812391161919e-03 - - 5.8825947344303131e-02 -3.5275349020957947e-01 - <_> - - 0 -1 392 -9.6740125445649028e-04 - - 2.2895433008670807e-01 -8.8445298373699188e-02 - <_> - - 0 -1 384 6.3862642273306847e-03 - - -7.9845495522022247e-02 2.6533949375152588e-01 - <_> - - 0 -1 739 -1.8584533827379346e-03 - - -3.5019376873970032e-01 5.8831077069044113e-02 - <_> - - 0 -1 47 -4.1777163743972778e-02 - - -7.5915527343750000e-01 2.5032732635736465e-02 - <_> - - 0 -1 798 1.7466493882238865e-03 - - -7.8535526990890503e-02 2.5856694579124451e-01 - <_> - - 0 -1 873 -1.7557941377162933e-02 - - 1.5769363939762115e-01 -1.2735258042812347e-01 - <_> - - 0 -1 622 -2.0210664719343185e-02 - - 2.4479819834232330e-01 -8.0905362963676453e-02 - <_> - - 0 -1 623 -1.2817385140806437e-03 - - 2.0145194232463837e-01 -1.1555081605911255e-01 - <_> - - 0 -1 173 -4.6622417867183685e-03 - - -5.7475388050079346e-01 3.5327285528182983e-02 - <_> - - 0 -1 624 7.2181676514446735e-03 - - -6.5562173724174500e-02 2.9846385121345520e-01 + -3.9718165993690491e-01 6.2707424163818359e-02 <_> - 91 - -1.4331817626953125e+00 + 63 + -1.4057025909423828e+00 <_> - 0 -1 508 -1.0981839150190353e-02 + 0 -1 804 5.0806580111384392e-03 - 6.4476418495178223e-01 5.4893907159566879e-02 + -7.9617008566856384e-02 5.6362086534500122e-01 <_> - 0 -1 256 4.4120610691606998e-03 + 0 -1 965 2.0602284930646420e-03 - -1.1835748702287674e-01 5.0045996904373169e-01 + -1.8717131018638611e-01 3.4062680602073669e-01 <_> - 0 -1 735 2.8575016185641289e-03 + 0 -1 495 6.1347078531980515e-02 - -1.3248406350612640e-01 4.2942702770233154e-01 + -1.3253036141395569e-01 4.0938606858253479e-01 <_> - 0 -1 326 2.0933073014020920e-02 + 0 -1 13 -6.0383215546607971e-02 - -1.2826231122016907e-01 5.0430470705032349e-01 + 4.1172346472740173e-01 -1.4447186887264252e-01 <_> - 0 -1 742 -1.4590121805667877e-02 + 0 -1 478 -3.0238348990678787e-03 - 3.1983098387718201e-01 -1.6088847815990448e-01 + 3.4262558817863464e-01 -1.0982885956764221e-01 <_> - 0 -1 581 6.0559157282114029e-02 + 0 -1 458 4.0474245324730873e-03 - -7.2834797203540802e-02 4.6935465931892395e-01 + 7.1186766028404236e-02 -5.0650447607040405e-01 <_> - 0 -1 537 3.3241603523492813e-02 + 0 -1 633 -2.0359824411571026e-03 - -1.2657077610492706e-01 3.8025194406509399e-01 + 2.2166600823402405e-01 -1.6060648858547211e-01 <_> - 0 -1 377 -1.5009621158242226e-02 + 0 -1 887 2.7303429305902682e-05 - 3.6463224887847900e-01 -9.8299026489257812e-02 + -2.6211214065551758e-01 1.2801185250282288e-01 <_> - 0 -1 888 1.5744348056614399e-03 + 0 -1 352 1.2323079630732536e-02 - -1.1195008456707001e-01 3.1572943925857544e-01 + 8.2502633333206177e-02 -4.5231887698173523e-01 <_> - 0 -1 574 -2.3936885409057140e-03 + 0 -1 878 2.2477287799119949e-02 - -4.7027668356895447e-01 7.1979902684688568e-02 + -7.7229477465152740e-02 4.5144733786582947e-01 <_> - 0 -1 263 4.7012902796268463e-03 + 0 -1 395 -1.4673802070319653e-02 - 9.1855168342590332e-02 -3.6548766493797302e-01 + 3.5660189390182495e-01 -1.1584777384996414e-01 <_> - 0 -1 899 3.9329114370048046e-03 + 0 -1 141 9.9029816687107086e-02 - 4.4214393943548203e-02 -5.6691557168960571e-01 + -1.6957059502601624e-01 2.2625257074832916e-01 <_> - 0 -1 898 -2.8009498491883278e-03 + 0 -1 144 -1.0632930323481560e-02 - -4.8461133241653442e-01 5.4654970765113831e-02 + -5.6829780340194702e-01 7.1929946541786194e-02 <_> - 0 -1 134 -4.2012645862996578e-03 + 0 -1 808 2.5341216474771500e-02 - 1.9422210752964020e-01 -1.4497868716716766e-01 + -1.2931844592094421e-01 2.6161769032478333e-01 <_> - 0 -1 61 -8.7564159184694290e-03 + 0 -1 816 5.8172484859824181e-03 - -4.9580562114715576e-01 5.6972313672304153e-02 + -1.5375703573226929e-01 2.0636843144893646e-01 <_> - 0 -1 843 3.0297664925456047e-03 + 0 -1 68 -2.0786169171333313e-01 - -1.4587514102458954e-01 2.3592919111251831e-01 + 3.9931070804595947e-01 -7.7051497995853424e-02 <_> - 0 -1 882 -1.1956840753555298e-02 + 0 -1 140 2.2137831151485443e-01 - 3.6318615078926086e-01 -8.9037798345088959e-02 + -7.2486869990825653e-02 3.9756566286087036e-01 <_> - 0 -1 267 -9.4736125320196152e-03 + 0 -1 554 3.4148676786571741e-04 - -6.6952317953109741e-01 5.2261870354413986e-02 + -1.5928100049495697e-01 1.8005076050758362e-01 <_> - 0 -1 147 -7.3966579511761665e-03 + 0 -1 307 -6.7202709615230560e-03 - -5.5038225650787354e-01 4.5135255903005600e-02 + -6.7838191986083984e-01 4.5886330306529999e-02 <_> - 0 -1 909 5.1108570769429207e-03 + 0 -1 392 1.4110710471868515e-03 - 4.1587084531784058e-02 -5.5355554819107056e-01 + -9.7257830202579498e-02 3.2224002480506897e-01 <_> - 0 -1 178 2.1153174340724945e-02 + 0 -1 266 4.2120069265365601e-02 - -9.0628616511821747e-02 2.9272273182868958e-01 + -8.8405482470989227e-02 3.2538983225822449e-01 <_> - 0 -1 690 -4.0524005889892578e-03 + 0 -1 242 -1.3846142683178186e-03 - -5.5750316381454468e-01 4.8259153962135315e-02 + 2.0695628225803375e-01 -1.5275791287422180e-01 <_> - 0 -1 208 -4.5195231214165688e-03 + 0 -1 817 3.5425978712737560e-03 - 2.4507603049278259e-01 -1.1037164181470871e-01 + -1.2709444761276245e-01 2.1816165745258331e-01 <_> - 0 -1 802 2.9709473252296448e-02 + 0 -1 959 3.3351695165038109e-03 - -9.0624623000621796e-02 3.0535447597503662e-01 + 4.8398405313491821e-02 -6.0871434211730957e-01 <_> - 0 -1 596 -2.4458598345518112e-02 + 0 -1 958 -3.3201207406818867e-03 - 3.8106867671012878e-01 -6.5381005406379700e-02 + -4.8987022042274475e-01 5.5623263120651245e-02 <_> - 0 -1 833 2.3627276532351971e-03 + 0 -1 915 1.0103111853823066e-03 - -8.9016206562519073e-02 2.7661785483360291e-01 + -1.5765775740146637e-01 1.6940611600875854e-01 <_> - 0 -1 576 2.5604534894227982e-03 + 0 -1 151 4.9717966467142105e-03 - 4.9425628036260605e-02 -5.4407423734664917e-01 + 5.1272217184305191e-02 -5.4395431280136108e-01 <_> - 0 -1 164 1.1583864688873291e-02 + 0 -1 799 1.7913591582328081e-03 - 3.7279289215803146e-02 -6.2233042716979980e-01 + -7.2745941579341888e-02 4.0087917447090149e-01 <_> - 0 -1 745 -6.5262932330369949e-03 + 0 -1 102 -1.3228422030806541e-02 - 2.2733294963836670e-01 -1.1270135641098022e-01 + -3.5441592335700989e-01 7.9325266182422638e-02 <_> - 0 -1 747 -5.5729500018060207e-03 + 0 -1 276 2.0421743392944336e-03 - -5.2463114261627197e-01 4.3969567865133286e-02 + -5.9137169271707535e-02 4.6143886446952820e-01 <_> - 0 -1 892 2.7682324871420860e-03 + 0 -1 276 -5.9784355107694864e-04 - -5.6408800184726715e-02 4.5612502098083496e-01 + 2.5433012843132019e-01 -1.0601133853197098e-01 <_> - 0 -1 683 5.3484998643398285e-03 + 0 -1 396 -5.1422840915620327e-03 - 5.1867362111806870e-02 -4.8760178685188293e-01 + -4.4627833366394043e-01 6.1951976269483566e-02 <_> - 0 -1 165 5.3632212802767754e-03 + 0 -1 86 6.4243013039231300e-03 - 4.4008553028106689e-02 -4.8531344532966614e-01 + 3.1528502702713013e-02 -7.2403544187545776e-01 <_> - 0 -1 168 -4.5866379514336586e-03 + 0 -1 1035 3.4636156633496284e-03 - -4.7415995597839355e-01 4.6904686838388443e-02 + 3.7317775189876556e-02 -5.4165351390838623e-01 <_> - 0 -1 448 -2.4732598103582859e-03 + 0 -1 14 3.2000489532947540e-02 - 3.5594299435615540e-01 -6.6797487437725067e-02 + 3.0169567093253136e-02 -7.1302002668380737e-01 <_> - 0 -1 504 -1.3544519897550344e-03 + 0 -1 498 -5.8225672692060471e-03 - 2.5692245364189148e-01 -1.0549759119749069e-01 + -4.4310861825942993e-01 4.7724053263664246e-02 <_> - 0 -1 226 2.0623015239834785e-02 + 0 -1 24 -8.4763765335083008e-03 - -1.2213230878114700e-01 1.8851162493228912e-01 + -6.0832363367080688e-01 3.6428902298212051e-02 <_> - 0 -1 106 -2.5555126368999481e-02 + 0 -1 598 2.7582058683037758e-03 - 2.1115033328533173e-01 -1.1155050992965698e-01 + -1.0180406272411346e-01 2.4450653791427612e-01 <_> - 0 -1 650 -2.6123304851353168e-03 + 0 -1 695 -3.0314538162201643e-03 - -4.3362092971801758e-01 5.9404496103525162e-02 + -5.6130182743072510e-01 4.1730970144271851e-02 <_> - 0 -1 454 -2.0256865769624710e-02 + 0 -1 691 3.8132141344249249e-03 - 2.3865076899528503e-01 -1.1111994832754135e-01 + 4.3826375156641006e-02 -4.8639413714408875e-01 <_> - 0 -1 636 -1.3834737241268158e-02 + 0 -1 799 -1.1944114230573177e-03 - 2.4716469645500183e-01 -9.9341392517089844e-02 + 1.9191412627696991e-01 -1.2599647045135498e-01 <_> - 0 -1 438 1.0408030357211828e-03 + 0 -1 751 -3.2212696969509125e-02 - -8.5192345082759857e-02 2.8685340285301208e-01 + -7.3205161094665527e-01 3.3331435173749924e-02 <_> - 0 -1 693 -7.8561680857092142e-04 + 0 -1 521 -1.0144908446818590e-03 - -3.1685733795166016e-01 7.3741830885410309e-02 + 3.0479896068572998e-01 -8.2489714026451111e-02 <_> - 0 -1 845 -3.1890799291431904e-03 + 0 -1 836 -1.4355147257447243e-02 - 2.8838813304901123e-01 -7.9454399645328522e-02 + 2.1706604957580566e-01 -1.0914804041385651e-01 <_> - 0 -1 556 -1.8864404410123825e-02 + 0 -1 574 -4.8122168518602848e-03 - -6.1039513349533081e-01 3.4549634903669357e-02 + -6.7199075222015381e-01 4.0943562984466553e-02 <_> - 0 -1 930 1.9871932454407215e-03 + 0 -1 236 3.3706519752740860e-04 - -6.4915224909782410e-02 3.3199799060821533e-01 + -1.4588885009288788e-01 1.6099508106708527e-01 <_> - 0 -1 307 -4.4487272389233112e-03 + 0 -1 43 -1.8943618983030319e-02 - -4.8411524295806885e-01 4.3471843004226685e-02 + -5.9796541929244995e-01 3.7877634167671204e-02 <_> - 0 -1 124 1.1506278999149799e-02 + 0 -1 69 1.5444982796907425e-02 - 3.4361593425273895e-02 -5.1601499319076538e-01 + 2.6846721768379211e-02 -7.2375786304473877e-01 <_> - 0 -1 299 -4.9164015799760818e-03 + 0 -1 303 1.0463559068739414e-02 - 2.8029051423072815e-01 -7.6438650488853455e-02 + 3.2184243202209473e-02 -6.0756552219390869e-01 <_> - 0 -1 937 6.8624541163444519e-03 + 0 -1 292 2.5047133676707745e-03 - -1.3434819877147675e-01 1.7164944112300873e-01 + -1.1925315856933594e-01 1.9379882514476776e-01 <_> - 0 -1 788 1.2513504363596439e-02 + 0 -1 797 -1.4791900292038918e-02 - -8.2097627222537994e-02 2.6367199420928955e-01 + 1.9981779158115387e-01 -1.2553811073303223e-01 <_> - 0 -1 144 2.5324244052171707e-02 + 0 -1 146 -6.1217732727527618e-03 - -9.8793335258960724e-02 2.1438889205455780e-01 + -4.2455345392227173e-01 5.5959124118089676e-02 <_> - 0 -1 491 4.2827110737562180e-03 + 0 -1 563 -3.5850135609507561e-03 - 4.8010587692260742e-02 -5.3329360485076904e-01 + 3.2560044527053833e-01 -7.1894593536853790e-02 <_> - 0 -1 172 -1.0588562116026878e-02 + 0 -1 1048 -3.2580485567450523e-03 - 2.0557209849357605e-01 -1.1096615344285965e-01 + -5.4515779018402100e-01 4.5138467103242874e-02 <_> - 0 -1 195 7.3749665170907974e-03 + 0 -1 367 8.5870809853076935e-03 - 4.2330745607614517e-02 -4.9726718664169312e-01 + -9.2699222266674042e-02 2.7361676096916199e-01 <_> - 0 -1 477 -1.0184315964579582e-02 + 0 -1 384 -3.5999938845634460e-03 - 2.2020325064659119e-01 -1.0080294311046600e-01 + 1.7715592682361603e-01 -1.3859097659587860e-01 <_> - 0 -1 305 -3.1706739682704210e-03 + 0 -1 650 1.5299995429813862e-03 - -4.1845852136611938e-01 5.4482847452163696e-02 + -1.0419535636901855e-01 2.1118766069412231e-01 <_> - 0 -1 670 2.5342048611491919e-03 + 0 -1 413 2.7578026056289673e-03 - -6.9553844630718231e-02 3.2299628853797913e-01 + -7.0944413542747498e-02 2.9870492219924927e-01 <_> - 0 -1 521 -8.4150061011314392e-03 + 0 -1 283 -6.1489176005125046e-03 - 2.6279926300048828e-01 -9.3804508447647095e-02 + -5.1581281423568726e-01 4.6433247625827789e-02 <_> - 0 -1 76 4.0150225162506104e-02 + 0 -1 979 8.3175086183473468e-04 - 2.9147522523999214e-02 -7.8112679719924927e-01 + -8.4185592830181122e-02 2.8132751584053040e-01 <_> - 0 -1 177 -4.3324208818376064e-03 + 0 -1 979 -6.7444925662130117e-04 - -5.2339142560958862e-01 3.6419976502656937e-02 + 2.6548036932945251e-01 -9.7815677523612976e-02 <_> - 0 -1 39 -4.0873344987630844e-02 + 0 -1 555 -5.6643221527338028e-02 - 3.7220278382301331e-01 -6.1695497483015060e-02 + 3.8170987367630005e-01 -6.2833912670612335e-02 <_> - 0 -1 13 5.9101730585098267e-02 + 0 -1 602 -7.5360340997576714e-03 - -5.1950857043266296e-02 4.1701674461364746e-01 - <_> - - 0 -1 628 -3.1048480886965990e-03 - - 2.1874889731407166e-01 -9.0781040489673615e-02 - <_> - - 0 -1 627 3.5321055911481380e-03 - - -8.2859635353088379e-02 2.9276433587074280e-01 - <_> - - 0 -1 668 -1.2976058060303330e-03 - - -4.3279412388801575e-01 4.9447599798440933e-02 - <_> - - 0 -1 176 1.1339010670781136e-02 - - 2.6531336829066277e-02 -6.9358879327774048e-01 - <_> - - 0 -1 969 8.8861025869846344e-03 - - 2.6764476671814919e-02 -6.1700969934463501e-01 - <_> - - 0 -1 659 1.1916678398847580e-02 - - -9.7341567277908325e-02 2.0659063756465912e-01 - <_> - - 0 -1 804 1.2824826873838902e-02 - - -8.5851043462753296e-02 2.6430803537368774e-01 - <_> - - 0 -1 820 -4.0587522089481354e-03 - - 1.8127168715000153e-01 -1.1241084337234497e-01 - <_> - - 0 -1 931 5.4964423179626465e-04 - - -9.1979973018169403e-02 2.1896743774414062e-01 - <_> - - 0 -1 324 1.5558412997052073e-03 - - -7.7465757727622986e-02 2.5980666279792786e-01 - <_> - - 0 -1 587 4.3281335383653641e-03 - - 3.4584067761898041e-02 -6.2342578172683716e-01 - <_> - - 0 -1 34 -1.4533417299389839e-02 - - 2.0229732990264893e-01 -1.0071664303541183e-01 - <_> - - 0 -1 644 5.6288111954927444e-03 - - 3.9174310863018036e-02 -5.0741255283355713e-01 - <_> - - 0 -1 936 7.9474167432636023e-04 - - -8.0158397555351257e-02 2.3534512519836426e-01 - <_> - - 0 -1 585 -1.0926688089966774e-02 - - -5.9471416473388672e-01 3.1198443844914436e-02 - <_> - - 0 -1 677 -8.2422709092497826e-03 - - 2.0226760208606720e-01 -1.1066834628582001e-01 - <_> - - 0 -1 923 -3.6351364105939865e-03 - - -6.4762312173843384e-01 2.9601249843835831e-02 - <_> - - 0 -1 784 -2.7860058471560478e-03 - - 4.2289113998413086e-01 -4.8328761011362076e-02 - <_> - - 0 -1 56 1.4032858889549971e-03 - - 7.7722996473312378e-02 -2.5018605589866638e-01 - <_> - - 0 -1 56 -4.9225967377424240e-03 - - -5.3430163860321045e-01 3.4801222383975983e-02 - <_> - - 0 -1 566 -1.2032099068164825e-02 - - 2.3754563927650452e-01 -8.4349773824214935e-02 - <_> - - 0 -1 464 5.9743728488683701e-03 - - -9.6527986228466034e-02 2.0883874595165253e-01 - <_> - - 0 -1 288 9.0228002518415451e-03 - - 2.6527268812060356e-02 -7.1255648136138916e-01 - <_> - - 0 -1 94 -4.3231204152107239e-02 - - -4.5857131481170654e-01 3.5763122141361237e-02 - <_> - - 0 -1 262 1.9863661378622055e-02 - - 3.8993570953607559e-02 -4.7274601459503174e-01 - <_> - - 0 -1 364 1.7278429004363716e-04 - - -1.2378288805484772e-01 1.5123386681079865e-01 - <_> - - 0 -1 81 8.4997266530990601e-03 - - 3.8503456860780716e-02 -4.7635042667388916e-01 - <_> - - 0 -1 434 -1.3840992469340563e-03 - - 2.4361917376518250e-01 -7.7643536031246185e-02 + 2.2137185931205750e-01 -1.0336405038833618e-01 <_> - 100 - -1.4933127164840698e+00 + 54 + -1.3439358472824097e+00 <_> - 0 -1 769 -2.4473592638969421e-03 + 0 -1 526 -4.8420722596347332e-03 - 6.4225250482559204e-01 1.1617031693458557e-01 + 5.7400572299957275e-01 -9.5008336007595062e-02 <_> - 0 -1 918 2.5613610632717609e-03 + 0 -1 786 -5.9993756003677845e-03 - -1.4125512540340424e-01 4.1756254434585571e-01 + 4.5479923486709595e-01 -1.5483228862285614e-01 <_> - 0 -1 450 -3.6349727306514978e-03 + 0 -1 531 -3.1531709246337414e-03 - 4.2445364594459534e-01 -1.2421201914548874e-01 + 4.2504432797431946e-01 -1.2935030460357666e-01 <_> - 0 -1 243 7.6568350195884705e-02 + 0 -1 884 1.2363551650196314e-03 - -2.0400929450988770e-01 2.4128499627113342e-01 + -1.5872104465961456e-01 3.1463247537612915e-01 <_> - 0 -1 455 4.6866592019796371e-03 + 0 -1 925 -6.7780278623104095e-03 - 7.2638466954231262e-02 -5.3155571222305298e-01 + 4.1302111744880676e-01 -1.7017546296119690e-01 <_> - 0 -1 319 -3.9937674999237061e-02 + 0 -1 259 1.3960017822682858e-03 - 4.3441477417945862e-01 -8.1894725561141968e-02 + -1.3419999182224274e-01 3.3868113160133362e-01 <_> - 0 -1 376 -1.7270710319280624e-02 + 0 -1 564 -3.5894233733415604e-03 - 4.9218431115150452e-01 -8.1687144935131073e-02 + 3.3102113008499146e-01 -1.1498286575078964e-01 <_> - 0 -1 67 1.0907177627086639e-01 + 0 -1 551 5.4187951609492302e-03 - -1.3829828798770905e-01 3.0388528108596802e-01 + -1.2790408730506897e-01 3.1275641918182373e-01 <_> - 0 -1 563 -8.6617004126310349e-03 + 0 -1 934 -3.3248444087803364e-03 - 2.4966995418071747e-01 -1.4650684595108032e-01 + -5.1654219627380371e-01 7.1216024458408356e-02 <_> - 0 -1 257 5.3433720022439957e-03 + 0 -1 49 7.9970825463533401e-03 - 5.6382026523351669e-02 -4.7699481248855591e-01 + 6.3098005950450897e-02 -5.8896148204803467e-01 <_> - 0 -1 359 -7.3083816096186638e-03 + 0 -1 124 6.0347835533320904e-03 - 1.6508759558200836e-01 -1.8176083266735077e-01 + 6.4018696546554565e-02 -4.7639665007591248e-01 <_> - 0 -1 322 -1.2855050154030323e-03 + 0 -1 124 -6.9478121586143970e-03 - 2.5566878914833069e-01 -1.1560125648975372e-01 + -6.0485291481018066e-01 7.2506561875343323e-02 <_> - 0 -1 799 1.6045335214585066e-03 + 0 -1 30 1.9063859945163131e-03 - -1.5024451911449432e-01 1.8980197608470917e-01 + -1.8492227792739868e-01 1.9994279742240906e-01 <_> - 0 -1 711 -3.2996428199112415e-03 + 0 -1 752 2.1343495696783066e-02 - -5.4483765363693237e-01 5.2060887217521667e-02 + -8.6192794144153595e-02 4.8719888925552368e-01 <_> - 0 -1 646 -2.1930811926722527e-03 + 0 -1 261 -2.2514071315526962e-03 - -5.0953930616378784e-01 4.9616143107414246e-02 + 3.5809755325317383e-01 -7.6123438775539398e-02 <_> - 0 -1 830 -1.3328871689736843e-02 + 0 -1 480 -4.4778124429285526e-03 - 3.2616052031517029e-01 -8.1101849675178528e-02 + -4.5578238368034363e-01 7.3516018688678741e-02 <_> - 0 -1 333 3.5710524767637253e-02 + 0 -1 533 3.9280336350202560e-03 - -9.0930387377738953e-02 3.1067803502082825e-01 + 6.2599055469036102e-02 -5.2695369720458984e-01 <_> - 0 -1 488 6.7417006939649582e-03 + 0 -1 365 -4.5666974037885666e-03 - -7.7294938266277313e-02 3.2216030359268188e-01 + -6.1827522516250610e-01 4.1984613984823227e-02 <_> - 0 -1 11 -8.1952005624771118e-02 + 0 -1 743 -6.1424830928444862e-03 - 5.3666585683822632e-01 -5.9473395347595215e-02 + 3.0607789754867554e-01 -9.1138295829296112e-02 <_> - 0 -1 8 9.2416517436504364e-03 + 0 -1 1019 3.4258943051099777e-03 - -1.2617717683315277e-01 2.0812577009201050e-01 + 5.5657953023910522e-02 -5.3350126743316650e-01 <_> - 0 -1 619 -2.0654057152569294e-03 + 0 -1 731 3.3122287131845951e-03 - -4.8568764328956604e-01 5.2649311721324921e-02 + -1.5935245156288147e-01 1.7000633478164673e-01 <_> - 0 -1 66 -1.3702171854674816e-02 + 0 -1 135 7.4128687381744385e-02 - -6.6060936450958252e-01 3.5181287676095963e-02 + 3.3975400030612946e-02 -6.4646822214126587e-01 <_> - 0 -1 393 -3.0807605944573879e-03 + 0 -1 496 -6.0862921178340912e-02 - -4.4769099354743958e-01 4.8634912818670273e-02 + 3.1012952327728271e-01 -9.1380268335342407e-02 <_> - 0 -1 57 -1.2945728376507759e-02 + 0 -1 575 -4.3243117630481720e-02 - -5.4323107004165649e-01 4.0633078664541245e-02 + -4.5051410794258118e-01 6.6722445189952850e-02 <_> - 0 -1 240 -1.3134386390447617e-02 + 0 -1 322 -5.4576778784394264e-03 - -4.7699347138404846e-01 4.5706178992986679e-02 + -4.8368638753890991e-01 5.5113438516855240e-02 <_> - 0 -1 434 1.6984546091407537e-03 + 0 -1 196 -2.1073617972433567e-03 - -7.0986136794090271e-02 3.2597315311431885e-01 + 2.3326623439788818e-01 -1.2007984519004822e-01 <_> - 0 -1 599 3.8461894728243351e-03 + 0 -1 252 -1.1282963678240776e-02 - 4.0658432990312576e-02 -5.7832121849060059e-01 + 2.9159554839134216e-01 -1.0025029629468918e-01 <_> - 0 -1 189 -1.7426438629627228e-02 + 0 -1 339 2.9302681796252728e-03 - -4.3611589074134827e-01 4.5463379472494125e-02 + -8.5840485990047455e-02 3.3159431815147400e-01 <_> - 0 -1 730 -2.6193801313638687e-03 + 0 -1 53 -2.8825225308537483e-03 - 2.5506833195686340e-01 -8.7045751512050629e-02 + -5.3361582756042480e-01 5.7994876056909561e-02 <_> - 0 -1 150 -1.0474737733602524e-02 + 0 -1 76 6.2230005860328674e-03 - 2.3522177338600159e-01 -9.5193855464458466e-02 + 4.4393569231033325e-02 -5.3072142601013184e-01 <_> - 0 -1 776 -2.0476649515330791e-03 + 0 -1 971 1.1437942739576101e-03 - -4.0278571844100952e-01 5.3846791386604309e-02 + -9.5763660967350006e-02 2.8212538361549377e-01 <_> - 0 -1 492 5.0511634908616543e-03 + 0 -1 1052 1.2469270732253790e-03 - 3.5829022526741028e-02 -5.8457142114639282e-01 + 6.5446242690086365e-02 -4.1902217268943787e-01 <_> - 0 -1 400 -2.6015858165919781e-03 + 0 -1 612 -1.1369751766324043e-02 - 2.8992271423339844e-01 -7.7776394784450531e-02 + -7.0747911930084229e-01 3.4916084259748459e-02 <_> - 0 -1 191 1.4678405132144690e-03 + 0 -1 35 1.0013033449649811e-01 - 4.2822040617465973e-02 -5.0615262985229492e-01 + -6.7160040140151978e-02 4.2184004187583923e-01 <_> - 0 -1 119 3.4870039671659470e-03 + 0 -1 653 -2.6742245536297560e-03 - -8.2636579871177673e-02 2.5724917650222778e-01 + 1.7217047512531281e-01 -1.6229687631130219e-01 <_> - 0 -1 104 -1.9308419525623322e-01 + 0 -1 713 -3.4254738129675388e-03 - 3.6281177401542664e-01 -6.3503719866275787e-02 + 2.9603767395019531e-01 -8.9177258312702179e-02 <_> - 0 -1 545 1.9733399152755737e-02 + 0 -1 669 1.5813322970643640e-03 - -8.6004406213760376e-02 2.5530698895454407e-01 + 4.8733744770288467e-02 -5.6422549486160278e-01 <_> - 0 -1 37 -3.2536339014768600e-02 + 0 -1 917 2.7555555789149366e-05 - -5.8808100223541260e-01 3.7802245467901230e-02 + -1.7079097032546997e-01 1.4066468179225922e-01 <_> - 0 -1 382 8.8406521826982498e-03 + 0 -1 466 -8.2116597332060337e-04 - 2.5931548327207565e-02 -6.5399199724197388e-01 + 1.8260034918785095e-01 -1.3242910802364349e-01 <_> - 0 -1 844 -1.0922113433480263e-03 + 0 -1 353 -1.0168720036745071e-02 - 2.0415900647640228e-01 -1.0292074084281921e-01 + -4.1390055418014526e-01 6.5349683165550232e-02 <_> - 0 -1 892 1.5520181041210890e-03 + 0 -1 96 2.5848036631941795e-02 - -8.4858812391757965e-02 3.0234101414680481e-01 + 4.6910341829061508e-02 -4.7531116008758545e-01 <_> - 0 -1 601 3.6752538289874792e-03 + 0 -1 75 5.9797330759465694e-03 - 3.9351969957351685e-02 -5.4435199499130249e-01 + 4.5450355857610703e-02 -4.5701387524604797e-01 <_> - 0 -1 825 -1.7198601737618446e-02 + 0 -1 81 -2.4257015902549028e-03 - -6.8883073329925537e-01 2.4503545835614204e-02 + 1.8431460857391357e-01 -1.1879430711269379e-01 <_> - 0 -1 783 -4.8199836164712906e-03 + 0 -1 346 -4.1334740817546844e-02 - 3.3481866121292114e-01 -6.0483735054731369e-02 + 3.0460721254348755e-01 -9.4910860061645508e-02 <_> - 0 -1 838 8.6327344179153442e-03 + 0 -1 537 7.5982198119163513e-02 - 2.9317237436771393e-02 -7.1339315176010132e-01 + -6.5890170633792877e-02 3.3325287699699402e-01 <_> - 0 -1 761 5.9000156819820404e-02 + 0 -1 318 -2.7852014682139270e-05 - 2.5574376806616783e-02 -6.3106632232666016e-01 + 1.4771287143230438e-01 -1.4524473249912262e-01 <_> - 0 -1 782 1.0106523986905813e-03 + 0 -1 669 -1.4885163400322199e-03 - -1.0588756203651428e-01 1.9086131453514099e-01 + -4.6987643837928772e-01 4.7233786433935165e-02 <_> - 0 -1 880 1.1946363374590874e-03 + 0 -1 897 -3.3519542776048183e-03 - -8.1224068999290466e-02 2.6191043853759766e-01 + 2.4128976464271545e-01 -9.3788638710975647e-02 <_> - 0 -1 348 8.8360151275992393e-03 + 0 -1 935 1.3348343782126904e-03 - -7.4570186436176300e-02 2.7295246720314026e-01 + -9.9509775638580322e-02 2.9368522763252258e-01 <_> - 0 -1 80 -3.8921819068491459e-03 + 0 -1 704 3.2456549815833569e-03 - -4.6577858924865723e-01 4.1507720947265625e-02 + -9.8895303905010223e-02 2.3363485932350159e-01 <_> - 0 -1 75 2.6258802972733974e-03 + 0 -1 611 4.2385179549455643e-03 - 6.9952867925167084e-02 -2.7727422118186951e-01 + 5.9986904263496399e-02 -4.5745995640754700e-01 <_> - 0 -1 600 4.6104520559310913e-02 + 0 -1 170 8.4751443937420845e-03 - 2.8723197057843208e-02 -6.4130103588104248e-01 + 3.0937874689698219e-02 -6.7139619588851929e-01 <_> - 0 -1 152 -2.3556766100227833e-03 + 0 -1 995 3.0964510515332222e-03 - 1.6910773515701294e-01 -1.2073179334402084e-01 + 3.0879957601428032e-02 -6.2686437368392944e-01 <_> - 0 -1 271 2.0879062358289957e-03 + 0 -1 212 2.3455230984836817e-03 - -6.1540558934211731e-02 3.1166607141494751e-01 - <_> - - 0 -1 726 -2.7457359246909618e-03 - - -4.3359285593032837e-01 4.4867228716611862e-02 - <_> - - 0 -1 643 -5.7035693898797035e-03 - - -6.3301932811737061e-01 2.7553720399737358e-02 - <_> - - 0 -1 272 -2.3487601429224014e-03 - - 2.7741125226020813e-01 -7.1828551590442657e-02 - <_> - - 0 -1 312 -1.2618269771337509e-02 - - -6.0198032855987549e-01 3.3369537442922592e-02 - <_> - - 0 -1 73 -1.2911427766084671e-02 - - 1.9097310304641724e-01 -9.6765249967575073e-02 - <_> - - 0 -1 241 2.5069573894143105e-02 - - 2.9379865154623985e-02 -6.2714409828186035e-01 - <_> - - 0 -1 676 7.4739558622241020e-03 - - -6.2408778816461563e-02 3.2309064269065857e-01 - <_> - - 0 -1 960 -5.5288206785917282e-03 - - -4.4652014970779419e-01 4.4482827186584473e-02 - <_> - - 0 -1 707 5.1614809781312943e-03 - - -1.0451946407556534e-01 1.8219007551670074e-01 - <_> - - 0 -1 306 -4.6268366277217865e-03 - - 2.4900399148464203e-01 -7.5879700481891632e-02 - <_> - - 0 -1 280 -5.0914911553263664e-03 - - -3.8135659694671631e-01 4.8699565231800079e-02 - <_> - - 0 -1 338 1.3252631761133671e-03 - - -8.2675725221633911e-02 2.3466596007347107e-01 - <_> - - 0 -1 989 -2.9426435939967632e-03 - - -3.2485908269882202e-01 5.8781418949365616e-02 - <_> - - 0 -1 352 7.1004321798682213e-03 - - -1.0710758715867996e-01 1.6876961290836334e-01 - <_> - - 0 -1 448 1.6454465221613646e-03 - - -6.8138562142848969e-02 2.6411062479019165e-01 - <_> - - 0 -1 335 -4.4519053772091866e-03 - - -6.5162777900695801e-01 3.1989157199859619e-02 - <_> - - 0 -1 422 -5.6191058829426765e-03 - - 2.2833730280399323e-01 -8.4053449332714081e-02 - <_> - - 0 -1 225 -5.4375766776502132e-03 - - -4.2135429382324219e-01 4.7153089195489883e-02 - <_> - - 0 -1 427 1.4303867937996984e-03 - - -8.1828169524669647e-02 2.2752483189105988e-01 - <_> - - 0 -1 579 5.3636888042092323e-03 - - 4.6839229762554169e-02 -4.3641954660415649e-01 - <_> - - 0 -1 471 6.7459633573889732e-03 - - 4.8482794314622879e-02 -3.7357741594314575e-01 - <_> - - 0 -1 888 1.8225495005026460e-03 - - -7.2007156908512115e-02 2.6155912876129150e-01 - <_> - - 0 -1 107 -6.8536788225173950e-02 - - 2.3726168274879456e-01 -8.8266216218471527e-02 - <_> - - 0 -1 806 8.4726633504033089e-03 - - 3.0765017494559288e-02 -6.1803394556045532e-01 - <_> - - 0 -1 129 1.6150671988725662e-02 - - -6.9989733397960663e-02 2.7056843042373657e-01 - <_> - - 0 -1 414 7.6075509190559387e-02 - - -6.6986277699470520e-02 2.6545816659927368e-01 - <_> - - 0 -1 713 -2.4037770926952362e-03 - - 2.0211938023567200e-01 -1.1674832552671432e-01 - <_> - - 0 -1 78 1.8187157809734344e-02 - - 3.7632372230291367e-02 -5.2273052930831909e-01 - <_> - - 0 -1 569 -1.3952046632766724e-02 - - 3.2746854424476624e-01 -6.3546165823936462e-02 - <_> - - 0 -1 18 -2.6383304595947266e-01 - - -4.4734519720077515e-01 4.3956480920314789e-02 - <_> - - 0 -1 84 3.7522446364164352e-03 - - 3.8990244269371033e-02 -4.2726546525955200e-01 - <_> - - 0 -1 287 1.4125283341854811e-03 - - -5.6341815739870071e-02 3.3222517371177673e-01 - <_> - - 0 -1 582 4.1739037260413170e-03 - - -8.1689253449440002e-02 2.1681067347526550e-01 - <_> - - 0 -1 982 -6.1572249978780746e-03 - - -4.6595495939254761e-01 4.0940407663583755e-02 - <_> - - 0 -1 482 -4.0140310302376747e-03 - - -4.4917678833007812e-01 3.6913067102432251e-02 - <_> - - 0 -1 315 5.7834591716527939e-03 - - 3.7202619016170502e-02 -4.4926682114601135e-01 - <_> - - 0 -1 375 -2.7866717427968979e-03 - - 2.3668289184570312e-01 -7.8896284103393555e-02 - <_> - - 0 -1 740 -2.0863343961536884e-03 - - -3.1535735726356506e-01 5.4699663072824478e-02 - <_> - - 0 -1 16 -3.5249911248683929e-02 - - 2.3871497809886932e-01 -7.4336178600788116e-02 - <_> - - 0 -1 12 1.9735466688871384e-02 - - -6.9253593683242798e-02 2.7050065994262695e-01 - <_> - - 0 -1 977 6.9166612811386585e-03 - - 3.9671208709478378e-02 -4.5562696456909180e-01 - <_> - - 0 -1 180 1.2886511161923409e-02 - - -5.7705853134393692e-02 3.0492311716079712e-01 - <_> - - 0 -1 680 -4.3238401412963867e-02 - - -6.9368255138397217e-01 2.5768887251615524e-02 - <_> - - 0 -1 858 5.2338346838951111e-02 - - -4.1087090969085693e-02 4.6693238615989685e-01 - <_> - - 0 -1 903 -3.8494272157549858e-03 - - 1.6975462436676025e-01 -1.2150127440690994e-01 - <_> - - 0 -1 897 1.1914474889636040e-02 - - -7.7901296317577362e-02 2.2727672755718231e-01 + -1.3303077220916748e-01 1.6908498108386993e-01 <_> - 100 - -1.5521451234817505e+00 + 72 + -1.4052674770355225e+00 <_> - 0 -1 700 1.0511254891753197e-02 + 0 -1 534 -8.4834604058414698e-04 - 7.8954458236694336e-02 6.2691432237625122e-01 + 4.6746683120727539e-01 -1.2498743087053299e-01 <_> - 0 -1 501 -4.5915953814983368e-03 + 0 -1 838 1.1534148361533880e-03 - 4.8032283782958984e-01 -1.2750500440597534e-01 + -2.1341361105442047e-01 3.0533915758132935e-01 <_> - 0 -1 920 1.5926066553220153e-03 + 0 -1 728 1.3660041615366936e-02 - -2.2285957634449005e-01 2.5022059679031372e-01 + -1.5390963852405548e-01 3.2113197445869446e-01 <_> - 0 -1 265 4.7702826559543610e-02 + 0 -1 528 -1.3363182079046965e-03 - -1.6401256620883942e-01 4.6663716435432434e-01 + 2.4346974492073059e-01 -1.8074017763137817e-01 <_> - 0 -1 801 3.6355913616716862e-03 + 0 -1 1002 5.5064354091882706e-04 - -9.0887933969497681e-02 4.3753233551979065e-01 + -1.9600959122180939e-01 2.1903340518474579e-01 <_> - 0 -1 505 -2.9029550496488810e-03 + 0 -1 340 2.8026416897773743e-02 - 3.1178581714630127e-01 -1.4401906728744507e-01 + -9.9956467747688293e-02 5.1314896345138550e-01 <_> - 0 -1 811 6.0793287120759487e-03 + 0 -1 930 -9.8200759384781122e-04 - -1.6874884068965912e-01 2.2609569132328033e-01 + 2.0671010017395020e-01 -1.9585600495338440e-01 <_> - 0 -1 200 4.1879736818373203e-04 + 0 -1 249 -1.9661948084831238e-02 - -1.9620604813098907e-01 1.5544828772544861e-01 + -5.1859843730926514e-01 7.9988524317741394e-02 <_> - 0 -1 886 2.2689576144330204e-04 + 0 -1 514 5.7550622150301933e-03 - -1.9928123056888580e-01 1.4717149734497070e-01 + -1.0230549424886703e-01 2.9102912545204163e-01 <_> - 0 -1 138 -8.1100836396217346e-02 + 0 -1 854 4.8226406797766685e-03 - -5.1434135437011719e-01 5.8547608554363251e-02 + -1.2503834068775177e-01 2.2606587409973145e-01 <_> - 0 -1 108 2.7355052530765533e-02 + 0 -1 1025 -3.5137422382831573e-03 - 6.0101613402366638e-02 -4.1557094454765320e-01 + -6.8291509151458740e-01 4.6296034008264542e-02 <_> - 0 -1 967 -2.4958662688732147e-03 + 0 -1 468 2.7717142074834555e-05 - -5.0487858057022095e-01 5.1647525280714035e-02 + -2.1390475332736969e-01 1.3291628658771515e-01 <_> - 0 -1 420 -1.5961761819198728e-03 + 0 -1 875 -2.2634968161582947e-02 - 2.1670737862586975e-01 -1.2691333889961243e-01 + 4.0156257152557373e-01 -9.0922117233276367e-02 <_> - 0 -1 369 2.1885756403207779e-02 + 0 -1 890 -2.6544253341853619e-04 - -8.3462193608283997e-02 3.1052881479263306e-01 + 2.1944612264633179e-01 -1.5686984360218048e-01 <_> - 0 -1 760 -1.3334145769476891e-02 + 0 -1 45 1.7469950020313263e-02 - 3.0464804172515869e-01 -8.8519357144832611e-02 + 5.9605021029710770e-02 -5.4529672861099243e-01 <_> - 0 -1 688 -1.9117443589493632e-03 + 0 -1 812 3.6130528897047043e-03 - -6.8484777212142944e-01 4.3931856751441956e-02 + 5.2721742540597916e-02 -4.4890201091766357e-01 <_> - 0 -1 689 2.2813947871327400e-03 + 0 -1 813 -3.8260491564869881e-03 - 4.6766888350248337e-02 -4.8588466644287109e-01 + -5.1076781749725342e-01 4.7858215868473053e-02 <_> - 0 -1 164 -8.7422672659158707e-03 + 0 -1 348 -4.6305969590321183e-04 - -4.9902194738388062e-01 4.8665110021829605e-02 + 2.0340332388877869e-01 -1.3007256388664246e-01 <_> - 0 -1 758 -4.0188119746744633e-03 + 0 -1 685 -7.3791583999991417e-03 - 2.2568543255329132e-01 -1.1153879016637802e-01 + -5.4855078458786011e-01 5.1355980336666107e-02 <_> - 0 -1 966 1.3594499323517084e-03 + 0 -1 397 -4.1331160813570023e-02 - 4.2799551039934158e-02 -5.6778526306152344e-01 + -3.7914556264877319e-01 6.2432620674371719e-02 <_> - 0 -1 718 -6.5033760620281100e-04 + 0 -1 720 -1.4983891742303967e-03 - 2.0394213497638702e-01 -1.1888848990201950e-01 + -5.2967226505279541e-01 4.2461462318897247e-02 <_> - 0 -1 473 -3.1412184238433838e-02 + 0 -1 785 -2.5054097641259432e-03 - 2.5797879695892334e-01 -9.3766883015632629e-02 + 2.0288434624671936e-01 -1.2341590225696564e-01 <_> - 0 -1 139 -9.2636439949274063e-03 + 0 -1 259 -7.1871257387101650e-04 - -5.6845456361770630e-01 4.3344158679246902e-02 + 2.4784520268440247e-01 -9.8167583346366882e-02 <_> - 0 -1 383 -4.1950333863496780e-02 + 0 -1 260 -6.8983237724751234e-04 - -3.3588516712188721e-01 6.3371837139129639e-02 + 2.7780577540397644e-01 -9.7512029111385345e-02 <_> - 0 -1 881 2.9165907762944698e-03 + 0 -1 274 4.8434769269078970e-04 - -6.9124616682529449e-02 3.5223892331123352e-01 + -1.1704409867525101e-01 2.4324342608451843e-01 <_> - 0 -1 904 -1.0271451901644468e-03 + 0 -1 508 -3.6378027871251106e-03 - 1.8418928980827332e-01 -1.1801387369632721e-01 + -5.7295501232147217e-01 4.9037151038646698e-02 <_> - 0 -1 663 2.6636901311576366e-03 + 0 -1 709 -2.6648804545402527e-02 - -1.0614035278558731e-01 2.1366043388843536e-01 + -6.0253041982650757e-01 3.6413222551345825e-02 <_> - 0 -1 629 -1.8712934106588364e-02 + 0 -1 825 -4.3416651897132397e-03 - 2.4622038006782532e-01 -9.3236625194549561e-02 + 4.7109794616699219e-01 -5.9058945626020432e-02 <_> - 0 -1 33 -4.8551969230175018e-03 + 0 -1 60 -2.7588163502514362e-03 - 3.0577266216278076e-01 -7.4214689433574677e-02 + -4.9160134792327881e-01 5.4663125425577164e-02 <_> - 0 -1 156 2.4788705632090569e-03 + 0 -1 987 4.7046472318470478e-03 - -8.6660243570804596e-02 2.9340657591819763e-01 + 3.7025094032287598e-02 -5.6842529773712158e-01 <_> - 0 -1 291 -4.3734526261687279e-03 + 0 -1 77 4.9029560759663582e-03 - -5.0270831584930420e-01 4.9233034253120422e-02 + 4.8207473009824753e-02 -4.2965477705001831e-01 <_> - 0 -1 318 -4.9623926170170307e-03 + 0 -1 837 -7.0135248824954033e-04 - -4.4072946906089783e-01 4.5711714774370193e-02 + 2.2556030750274658e-01 -9.9117368459701538e-02 <_> - 0 -1 82 3.0696424655616283e-03 + 0 -1 332 2.7165210340172052e-03 - 5.5255725979804993e-02 -3.7899428606033325e-01 + 4.3833449482917786e-02 -5.5271440744400024e-01 <_> - 0 -1 157 -8.1601645797491074e-03 + 0 -1 837 8.9941755868494511e-04 - 2.6425153017044067e-01 -8.2545064389705658e-02 + -8.9474648237228394e-02 2.6415902376174927e-01 <_> - 0 -1 137 -1.4500592369586229e-03 + 0 -1 723 -1.7575379461050034e-03 - 1.8156392872333527e-01 -1.2637530267238617e-01 + -5.7822185754776001e-01 4.4655490666627884e-02 <_> - 0 -1 339 -3.7104606162756681e-03 + 0 -1 323 2.2079560905694962e-02 - 1.9824002683162689e-01 -1.0828326642513275e-01 + -9.1862626373767853e-02 2.6927500963211060e-01 <_> - 0 -1 673 -8.7567782029509544e-03 + 0 -1 247 -2.4989219382405281e-03 - 2.8610706329345703e-01 -7.3251776397228241e-02 + 1.9282613694667816e-01 -1.4004705846309662e-01 <_> - 0 -1 317 -1.8970356322824955e-03 + 0 -1 388 4.4558709487318993e-03 - -6.0897153615951538e-01 3.7743657827377319e-02 + 5.2965965121984482e-02 -4.6530798077583313e-01 <_> - 0 -1 20 3.8996827602386475e-01 + 0 -1 345 8.9809950441122055e-03 - -5.8310892432928085e-02 3.6127504706382751e-01 + -6.9099865853786469e-02 3.5005539655685425e-01 <_> - 0 -1 396 -4.9336552619934082e-03 + 0 -1 589 -4.6078087761998177e-03 - 3.0048343539237976e-01 -6.4242139458656311e-02 + 1.5373907983303070e-01 -1.5948937833309174e-01 <_> - 0 -1 54 2.5108925998210907e-02 + 0 -1 10 -8.9063167572021484e-02 - 2.5090903043746948e-02 -8.1637203693389893e-01 + 4.8500600457191467e-01 -5.1386959850788116e-02 <_> - 0 -1 429 4.2880335822701454e-03 + 0 -1 540 4.8636873252689838e-03 - -8.1443257629871368e-02 2.6617726683616638e-01 + 5.1732856780290604e-02 -4.9787709116935730e-01 <_> - 0 -1 456 -5.6165808928199112e-05 + 0 -1 992 -5.4465518333017826e-03 - 1.4481364190578461e-01 -1.6212667524814606e-01 + 1.5584819018840790e-01 -1.4326727390289307e-01 <_> - 0 -1 406 3.0591385439038277e-03 + 0 -1 788 6.4384475350379944e-02 - 2.8733581304550171e-02 -7.0054715871810913e-01 + 3.1540591269731522e-02 -7.1331930160522461e-01 <_> - 0 -1 185 -3.0338061042129993e-03 + 0 -1 25 -9.3528348952531815e-03 - -8.2671564817428589e-01 1.9727285951375961e-02 + -5.8800560235977173e-01 3.2534934580326080e-02 <_> - 0 -1 787 -2.1344989072531462e-03 + 0 -1 374 6.5686285961419344e-04 - 1.6036525368690491e-01 -1.2014801055192947e-01 + -1.6972899436950684e-01 1.4208021759986877e-01 <_> - 0 -1 246 2.4434458464384079e-02 + 0 -1 744 -6.5707243047654629e-03 - -1.0801825672388077e-01 2.0232307910919189e-01 + 3.1901842355728149e-01 -7.0233277976512909e-02 <_> - 0 -1 214 -6.6356086172163486e-03 + 0 -1 370 7.0676081813871861e-03 - 1.9015397131443024e-01 -1.0796815156936646e-01 + 3.0735086649656296e-02 -7.6451587677001953e-01 <_> - 0 -1 781 -8.2725454121828079e-03 + 0 -1 875 -1.1614331044256687e-02 - 3.1057110428810120e-01 -8.6532585322856903e-02 + 2.0416912436485291e-01 -1.0650242120027542e-01 <_> - 0 -1 95 -7.1973735466599464e-03 + 0 -1 227 -3.0933439731597900e-02 - -5.8514142036437988e-01 3.6453813314437866e-02 + -3.5186296701431274e-01 6.3158944249153137e-02 <_> - 0 -1 461 -1.3809885131195188e-03 + 0 -1 31 8.9404191821813583e-03 - 1.6234619915485382e-01 -1.2079101055860519e-01 + 4.1301336139440536e-02 -5.2171415090560913e-01 <_> - 0 -1 408 1.2584345415234566e-02 + 0 -1 542 -3.0004943255335093e-04 - -8.4917336702346802e-02 2.3094473779201508e-01 + 1.8332102894783020e-01 -1.1965552717447281e-01 <_> - 0 -1 907 8.0425739288330078e-03 + 0 -1 753 -4.2704585939645767e-03 - 4.0869396179914474e-02 -5.2088880538940430e-01 + -4.1220253705978394e-01 5.2136015146970749e-02 <_> - 0 -1 446 4.0921196341514587e-02 + 0 -1 979 9.1349193826317787e-04 - -5.4803006350994110e-02 3.5920065641403198e-01 + -8.2035504281520844e-02 2.7817621827125549e-01 <_> - 0 -1 635 -3.6556557752192020e-03 + 0 -1 97 2.8089310973882675e-02 - 3.0303934216499329e-01 -6.9975942373275757e-02 + 6.0909613966941833e-02 -3.7705209851264954e-01 <_> - 0 -1 275 -2.6071248576045036e-03 + 0 -1 979 -1.1489203898236156e-03 - 1.7682927846908569e-01 -1.1164762824773788e-01 + 2.9547268152236938e-01 -7.8550107777118683e-02 <_> - 0 -1 289 -5.8146800845861435e-02 + 0 -1 766 -8.5876882076263428e-04 - -3.7277954816818237e-01 5.6890588253736496e-02 + 1.6158875823020935e-01 -1.3613829016685486e-01 <_> - 0 -1 120 -2.2651627659797668e-01 + 0 -1 862 3.3645064104348421e-03 - 4.0828245878219604e-01 -5.9184983372688293e-02 + 3.6055568605661392e-02 -5.5788111686706543e-01 <_> - 0 -1 738 5.7799168862402439e-03 + 0 -1 1034 -1.2699423357844353e-02 - 4.0102362632751465e-02 -5.5016636848449707e-01 + -4.2199519276618958e-01 4.3876208364963531e-02 <_> - 0 -1 302 1.6304963501170278e-03 + 0 -1 158 -1.3306856155395508e-01 - -1.2154985219240189e-01 1.5898743271827698e-01 + -7.5723612308502197e-01 2.4755204096436501e-02 <_> - 0 -1 672 2.0045600831508636e-03 + 0 -1 822 4.9831219017505646e-02 - 2.9790198430418968e-02 -5.8250021934509277e-01 + 2.5250671431422234e-02 -6.3122928142547607e-01 <_> - 0 -1 371 -2.0879322662949562e-02 + 0 -1 569 5.8193420991301537e-03 - 2.1142369508743286e-01 -8.7382547557353973e-02 + 2.2189516574144363e-02 -7.2821933031082153e-01 <_> - 0 -1 954 -7.2442064993083477e-04 + 0 -1 422 -6.3158385455608368e-03 - 2.3263402283191681e-01 -8.1574723124504089e-02 + 1.9480472803115845e-01 -1.0275462269783020e-01 <_> - 0 -1 971 -7.4541047215461731e-03 + 0 -1 58 -2.6879269629716873e-02 - -4.5152980089187622e-01 4.5829907059669495e-02 + -4.3909311294555664e-01 4.5222271233797073e-02 <_> - 0 -1 930 -8.5284758824855089e-04 + 0 -1 900 -1.6478844918310642e-03 - 2.1253970265388489e-01 -9.1697148978710175e-02 + 2.7425831556320190e-01 -7.7650256454944611e-02 <_> - 0 -1 193 2.0642249728552997e-04 + 0 -1 947 4.4362144544720650e-03 - -1.3943105936050415e-01 1.3452273607254028e-01 + 3.2876692712306976e-02 -6.0907542705535889e-01 <_> - 0 -1 922 3.2144919969141483e-03 + 0 -1 760 -1.5154483262449503e-03 - 2.8089782223105431e-02 -6.4253503084182739e-01 + 2.2985421121120453e-01 -8.5810013115406036e-02 <_> - 0 -1 964 -4.6502160839736462e-03 + 0 -1 157 7.0627350360155106e-03 - 2.4156840145587921e-01 -7.5992465019226074e-02 + 3.4827440977096558e-02 -5.9273594617843628e-01 <_> - 0 -1 391 -7.9781133681535721e-03 + 0 -1 393 4.5482232235372066e-03 - -6.4584964513778687e-01 2.7661839500069618e-02 + -5.2113339304924011e-02 4.0603092312812805e-01 <_> - 0 -1 535 5.7130996137857437e-03 + 0 -1 183 -3.9095789194107056e-02 - 3.4437701106071472e-02 -4.5668947696685791e-01 + 2.5562492012977600e-01 -8.1410482525825500e-02 <_> - 0 -1 625 5.4299971088767052e-03 + 0 -1 718 -1.9122204976156354e-03 - -8.4557615220546722e-02 2.4553726613521576e-01 + -6.5523076057434082e-01 3.1964879482984543e-02 <_> - 0 -1 949 2.3061740212142467e-03 + 0 -1 622 5.1604928448796272e-03 - 3.6576978862285614e-02 -5.1891702413558960e-01 - <_> - - 0 -1 815 5.0157017540186644e-04 - - -1.1976727843284607e-01 1.6033935546875000e-01 - <_> - - 0 -1 525 -1.9801128655672073e-04 - - 1.5492685139179230e-01 -1.1399404704570770e-01 - <_> - - 0 -1 840 2.1493299864232540e-03 - - -8.7143458425998688e-02 2.1080201864242554e-01 - <_> - - 0 -1 45 -1.0518108028918505e-03 - - 1.7875078320503235e-01 -9.7399607300758362e-02 - <_> - - 0 -1 590 9.2383408918976784e-03 - - 3.2961033284664154e-02 -5.5265057086944580e-01 - <_> - - 0 -1 41 3.6674018949270248e-02 - - -5.6394163519144058e-02 3.2619351148605347e-01 - <_> - - 0 -1 725 1.8489698413759470e-03 - - -7.7260658144950867e-02 2.3810040950775146e-01 - <_> - - 0 -1 723 -3.9793262258172035e-03 - - 2.3499612510204315e-01 -8.8490329682826996e-02 - <_> - - 0 -1 619 3.7299278192222118e-03 - - 3.1517989933490753e-02 -6.3558888435363770e-01 - <_> - - 0 -1 916 4.9755964428186417e-03 - - 2.8343016281723976e-02 -5.1388341188430786e-01 - <_> - - 0 -1 77 2.8308688197284937e-03 - - -1.1687427759170532e-01 1.4075778424739838e-01 - <_> - - 0 -1 72 -4.3399848043918610e-02 - - 3.3840376138687134e-01 -6.5363220870494843e-02 - <_> - - 0 -1 174 4.4767763465642929e-03 - - 5.3890492767095566e-02 -3.8843661546707153e-01 - <_> - - 0 -1 443 1.4579682610929012e-03 - - -9.5170073211193085e-02 1.7093485593795776e-01 - <_> - - 0 -1 217 4.3643731623888016e-03 - - -1.0353569686412811e-01 1.9202291965484619e-01 - <_> - - 0 -1 416 -6.4208358526229858e-03 - - -5.2469170093536377e-01 3.1174579635262489e-02 - <_> - - 0 -1 399 -1.0310811921954155e-03 - - 2.1713955700397491e-01 -8.0816701054573059e-02 - <_> - - 0 -1 924 -4.0359990671277046e-03 - - -5.2423858642578125e-01 3.4388832747936249e-02 - <_> - - 0 -1 750 -5.9410361573100090e-03 - - 2.1114565432071686e-01 -8.0375924706459045e-02 - <_> - - 0 -1 720 -4.7730140388011932e-02 - - -6.6018968820571899e-01 2.6816543191671371e-02 - <_> - - 0 -1 777 -6.1359764076769352e-03 - - 2.6270267367362976e-01 -7.4918255209922791e-02 - <_> - - 0 -1 370 -3.2268161885440350e-03 - - -3.3210110664367676e-01 5.3716354072093964e-02 - <_> - - 0 -1 872 2.7645970694720745e-03 - - 2.4829804897308350e-02 -6.3309198617935181e-01 - <_> - - 0 -1 460 6.1914063990116119e-03 - - -7.9355642199516296e-02 2.0996589958667755e-01 - <_> - - 0 -1 890 -6.0850339941680431e-03 - - 1.8700407445430756e-01 -9.2255704104900360e-02 - <_> - - 0 -1 847 3.8954569026827812e-03 - - -6.2000993639230728e-02 2.9947289824485779e-01 - <_> - - 0 -1 559 7.9390443861484528e-03 - - -4.7935441136360168e-02 3.3055123686790466e-01 - <_> - - 0 -1 136 -7.4474988505244255e-03 - - -2.7902829647064209e-01 5.9020437300205231e-02 + 2.8228869661688805e-02 -6.0336226224899292e-01 <_> - 100 - -1.5058170557022095e+00 + 63 + -1.2550007104873657e+00 <_> - 0 -1 764 6.6398456692695618e-03 + 0 -1 532 -1.3708438724279404e-02 - 1.5219502151012421e-01 7.0482629537582397e-01 + 4.5314663648605347e-01 -1.2558805942535400e-01 <_> - 0 -1 451 -7.4103027582168579e-03 + 0 -1 32 1.2687301263213158e-02 - 4.4995731115341187e-01 -1.0949239879846573e-01 + -1.5584127604961395e-01 3.8753288984298706e-01 <_> - 0 -1 509 -1.2679899111390114e-02 + 0 -1 254 3.3966779708862305e-02 - 3.1908708810806274e-01 -1.3895240426063538e-01 + -1.1772038787603378e-01 4.0628942847251892e-01 <_> - 0 -1 221 1.0303283110260963e-02 + 0 -1 756 8.0258902162313461e-03 - -1.7546384036540985e-01 2.9695376753807068e-01 + -1.4661933481693268e-01 4.0369525551795959e-01 <_> - 0 -1 331 -4.7976471483707428e-02 + 0 -1 2 -4.2836386710405350e-03 - 4.4112482666969299e-01 -1.1231642961502075e-01 + 2.2167153656482697e-01 -1.9662868976593018e-01 <_> - 0 -1 810 3.2145732548087835e-03 + 0 -1 164 -2.7807329315692186e-03 - -1.8380118906497955e-01 2.3316045105457306e-01 + -4.6929144859313965e-01 6.9577261805534363e-02 <_> - 0 -1 793 2.4557339493185282e-03 + 0 -1 172 1.9090694840997458e-03 - -1.4323309063911438e-01 2.3558256030082703e-01 + 5.9488739818334579e-02 -6.3101488351821899e-01 <_> - 0 -1 595 -5.2055031061172485e-02 + 0 -1 426 3.1442400068044662e-03 - -4.4221264123916626e-01 7.0444636046886444e-02 + -1.1149841547012329e-01 3.0095639824867249e-01 <_> - 0 -1 51 7.7533419243991375e-03 + 0 -1 324 -2.8418585658073425e-02 - 5.6696638464927673e-02 -5.1518803834915161e-01 + 3.6157062649726868e-01 -9.6387691795825958e-02 <_> - 0 -1 534 4.7272985102608800e-04 + 0 -1 449 -4.4032465666532516e-03 - -1.5081474184989929e-01 1.8353472650051117e-01 + 3.2977014780044556e-01 -9.8187342286109924e-02 <_> - 0 -1 43 -1.7044700682163239e-02 + 0 -1 400 -2.6041134260594845e-03 - -4.3840527534484863e-01 6.8837635219097137e-02 + 2.8221642971038818e-01 -1.0142992436885834e-01 <_> - 0 -1 883 -3.5762921907007694e-03 + 0 -1 357 -5.8917067945003510e-03 - 2.4851283431053162e-01 -1.0779865086078644e-01 + -5.8254349231719971e-01 6.0040380805730820e-02 <_> - 0 -1 839 -2.4369158782064915e-03 + 0 -1 998 1.3956660404801369e-03 - 3.0688673257827759e-01 -8.9006565511226654e-02 + -1.6574928164482117e-01 1.7746162414550781e-01 <_> - 0 -1 933 -3.6047215107828379e-03 + 0 -1 1022 -1.7630932852625847e-03 - 2.7542102336883545e-01 -1.0634675621986389e-01 + -5.7597070932388306e-01 6.2388133257627487e-02 <_> - 0 -1 36 -1.1534212157130241e-02 + 0 -1 697 -1.3517161132767797e-03 - -5.5281609296798706e-01 4.9770243465900421e-02 + -5.1934504508972168e-01 4.7232870012521744e-02 <_> - 0 -1 405 2.7643658686429262e-03 + 0 -1 507 -3.8743610493838787e-03 - 2.9803691431879997e-02 -7.3425543308258057e-01 + 2.9165247082710266e-01 -9.9355563521385193e-02 <_> - 0 -1 849 -2.6033269241452217e-03 + 0 -1 765 1.0973589494824409e-02 - -4.4093501567840576e-01 5.0419628620147705e-02 + -7.7571205794811249e-02 3.4312543272972107e-01 <_> - 0 -1 245 4.8673897981643677e-02 + 0 -1 128 -3.5274624824523926e-03 - 5.8146391063928604e-02 -3.7859597802162170e-01 + -6.7513287067413330e-01 3.6897819489240646e-02 <_> - 0 -1 898 -4.4065229594707489e-03 + 0 -1 605 -2.4239125195890665e-03 - -6.9404369592666626e-01 3.1734105199575424e-02 + 2.5701349973678589e-01 -1.0465545207262039e-01 <_> - 0 -1 973 1.6997805796563625e-03 + 0 -1 727 -8.3098262548446655e-03 - 3.6800261586904526e-02 -5.4090088605880737e-01 + 2.6842510700225830e-01 -9.9635124206542969e-02 <_> - 0 -1 484 1.8069827929139137e-03 + 0 -1 269 -2.7831714600324631e-02 - -8.9325174689292908e-02 2.5629612803459167e-01 + -3.9901316165924072e-01 6.5086022019386292e-02 <_> - 0 -1 487 -4.4371248222887516e-03 + 0 -1 399 8.1690559163689613e-03 - 2.3971243202686310e-01 -1.0280106216669083e-01 + -1.1402101069688797e-01 2.2761905193328857e-01 <_> - 0 -1 973 -2.2968063130974770e-03 + 0 -1 368 2.8635351918637753e-03 - -5.8439761400222778e-01 4.1789893060922623e-02 + -1.4034478366374969e-01 1.8733198940753937e-01 <_> - 0 -1 950 1.4388319104909897e-03 + 0 -1 286 -2.1204156801104546e-03 - -1.2928913533687592e-01 1.6424950957298279e-01 + -5.9949654340744019e-01 4.9501683562994003e-02 <_> - 0 -1 685 -6.5411212854087353e-03 + 0 -1 669 -9.4446074217557907e-04 - 1.7306149005889893e-01 -1.3702909648418427e-01 + -3.8145086169242859e-01 5.9254929423332214e-02 <_> - 0 -1 414 -9.8783060908317566e-02 + 0 -1 686 2.1901372820138931e-03 - 4.2455860972404480e-01 -5.3996428847312927e-02 + 3.6901079118251801e-02 -5.6260800361633301e-01 <_> - 0 -1 533 -1.5466672182083130e-01 + 0 -1 103 4.2550573125481606e-03 - -4.6163687109947205e-01 5.4335389286279678e-02 + -9.8831087350845337e-02 2.3313422501087189e-01 <_> - 0 -1 626 -2.3389626294374466e-03 + 0 -1 281 4.2771790176630020e-03 - -6.5777504444122314e-01 2.6686858385801315e-02 + 4.2207289487123489e-02 -5.6859022378921509e-01 <_> - 0 -1 397 5.0454838201403618e-03 + 0 -1 422 -7.8792609274387360e-03 - 4.9083609133958817e-02 -3.7508815526962280e-01 + 2.2428077459335327e-01 -9.9518932402133942e-02 <_> - 0 -1 326 2.5655250996351242e-02 + 0 -1 561 -3.5514549817889929e-03 - -5.0410125404596329e-02 4.6358433365821838e-01 + -5.6150603294372559e-01 3.9242122322320938e-02 <_> - 0 -1 402 2.6888975407928228e-03 + 0 -1 738 -6.8606354761868715e-04 - -8.7988443672657013e-02 2.4659486114978790e-01 + 2.1056549251079559e-01 -1.2413132935762405e-01 <_> - 0 -1 455 -3.9576226845383644e-03 + 0 -1 433 5.2483025938272476e-03 - -3.4467720985412598e-01 6.0443773865699768e-02 + 3.4256864339113235e-02 -7.2566890716552734e-01 <_> - 0 -1 396 3.9240214973688126e-03 + 0 -1 658 -3.6910744383931160e-03 - -7.2165921330451965e-02 3.6404970288276672e-01 + 2.6440864801406860e-01 -8.9745096862316132e-02 <_> - 0 -1 988 1.3846965739503503e-03 + 0 -1 127 2.0369128324091434e-03 - 5.7182963937520981e-02 -3.8552245497703552e-01 + 4.6990364789962769e-02 -5.3132331371307373e-01 <_> - 0 -1 945 -8.4817763417959213e-03 + 0 -1 662 3.8735207635909319e-03 - 1.8708378076553345e-01 -1.1441195011138916e-01 + -9.1540865600109100e-02 2.7486115694046021e-01 <_> - 0 -1 944 2.6850812137126923e-03 + 0 -1 126 6.0556940734386444e-03 - 3.1117379665374756e-02 -6.2151008844375610e-01 + 5.3909529000520706e-02 -4.6437451243400574e-01 <_> - 0 -1 688 1.8728687427937984e-03 + 0 -1 912 4.8301572678610682e-04 - 2.9517510905861855e-02 -5.8275890350341797e-01 + -1.6165176033973694e-01 1.3917934894561768e-01 <_> - 0 -1 448 -1.4214152470231056e-03 + 0 -1 101 -1.4880476519465446e-02 - 2.1085265278816223e-01 -8.4942653775215149e-02 + -5.9634107351303101e-01 3.9811171591281891e-02 <_> - 0 -1 186 -1.4164925087243319e-03 + 0 -1 609 2.9731846880167723e-03 - -5.0255894660949707e-01 3.4562669694423676e-02 + 3.0903076753020287e-02 -6.2935864925384521e-01 <_> - 0 -1 572 2.7755820192396641e-03 + 0 -1 90 -1.1181155219674110e-02 - -8.5956700146198273e-02 2.1839313209056854e-01 + 3.5473996400833130e-01 -6.4499482512474060e-02 <_> - 0 -1 517 6.0641965828835964e-03 + 0 -1 1009 -9.8370900377631187e-04 - 3.4184314310550690e-02 -5.6067311763763428e-01 + 2.9858112335205078e-01 -8.4500424563884735e-02 <_> - 0 -1 773 -2.9663506429642439e-03 + 0 -1 975 -1.0228222236037254e-03 - 2.6388403773307800e-01 -7.4524797499179840e-02 + 2.7100124955177307e-01 -1.0033085197210312e-01 <_> - 0 -1 986 -1.7851786687970161e-02 + 0 -1 913 2.0134919323027134e-03 - -3.5538297891616821e-01 5.5470395833253860e-02 + 4.3533660471439362e-02 -5.4969471693038940e-01 <_> - 0 -1 62 -7.7814348042011261e-03 + 0 -1 881 -3.1473359558731318e-03 - 2.5654977560043335e-01 -7.7634811401367188e-02 + 3.1102818250656128e-01 -8.0141142010688782e-02 <_> - 0 -1 140 6.2794378027319908e-04 + 0 -1 991 -2.9232497327029705e-03 - -1.1543263494968414e-01 1.7257589101791382e-01 + -6.7808300256729126e-01 3.5025410354137421e-02 <_> - 0 -1 845 -2.0482162944972515e-03 + 0 -1 494 -3.8992143236100674e-03 - 2.0133562386035919e-01 -9.2291958630084991e-02 + 2.5711989402770996e-01 -8.4509201347827911e-02 <_> - 0 -1 852 -2.0528757013380527e-03 + 0 -1 547 -3.8403570652008057e-02 - 2.4054610729217529e-01 -9.5314949750900269e-02 + 2.8463324904441833e-01 -7.5673028826713562e-02 <_> - 0 -1 894 1.9264804432168603e-03 + 0 -1 700 -2.2210094612091780e-03 - -8.8165275752544403e-02 2.1321870386600494e-01 + -5.6876182556152344e-01 4.0759250521659851e-02 <_> - 0 -1 116 1.0841939598321915e-02 + 0 -1 989 6.9615743122994900e-03 - 3.4955434501171112e-02 -5.3944343328475952e-01 + -7.8118488192558289e-02 2.8128826618194580e-01 <_> - 0 -1 224 -7.5648901984095573e-03 + 0 -1 948 -1.8219950143247843e-03 - -7.1435016393661499e-01 2.2735377773642540e-02 + 1.8647159636020660e-01 -1.3465921580791473e-01 <_> - 0 -1 503 -7.4579543434083462e-04 + 0 -1 697 1.0106971021741629e-03 - 2.0245671272277832e-01 -9.3201741576194763e-02 + 5.7168632745742798e-02 -4.1419604420661926e-01 <_> - 0 -1 274 -1.2499685399234295e-03 + 0 -1 945 -3.3746981061995029e-03 - 1.4646218717098236e-01 -1.3543428480625153e-01 + -5.2892911434173584e-01 4.0065344423055649e-02 <_> - 0 -1 270 5.8323808480054140e-04 + 0 -1 1030 -8.5245687514543533e-03 - -9.3358881771564484e-02 2.0619191229343414e-01 + -5.0935691595077515e-01 3.8823168724775314e-02 <_> - 0 -1 439 1.9810695201158524e-02 + 0 -1 1012 -2.2426969371736050e-03 - 2.7015892788767815e-02 -7.5727492570877075e-01 + 2.5891116261482239e-01 -8.8167145848274231e-02 <_> - 0 -1 175 5.9376070275902748e-03 + 0 -1 402 -5.9730862267315388e-03 - -1.2178353220224380e-01 1.6173928976058960e-01 + -4.3465223908424377e-01 4.9864508211612701e-02 <_> - 0 -1 914 1.5689490828663111e-03 + 0 -1 452 -5.5482299067080021e-03 - 3.1975947320461273e-02 -6.0493367910385132e-01 + 2.5288850069046021e-01 -9.3322932720184326e-02 <_> - 0 -1 575 2.5749076157808304e-03 + 0 -1 51 3.7344563007354736e-01 - -9.0526103973388672e-02 2.2666496038436890e-01 + -4.9019347876310349e-02 4.3872711062431335e-01 <_> - 0 -1 90 7.9413484781980515e-03 + 0 -1 615 -4.0881419554352760e-03 - 5.1273416727781296e-02 -3.9284336566925049e-01 + 3.1952694058418274e-01 -7.7735908329486847e-02 <_> - 0 -1 15 3.2074376940727234e-02 + 0 -1 202 3.1661842949688435e-03 - 2.7649452909827232e-02 -6.5098905563354492e-01 + -1.0995075106620789e-01 1.7701222002506256e-01 <_> - 0 -1 891 -4.8892917111515999e-03 + 0 -1 17 -2.1666671335697174e-01 - -4.7998306155204773e-01 3.3806797116994858e-02 + -4.5134860277175903e-01 4.9127347767353058e-02 <_> - 0 -1 475 -5.4039997048676014e-03 + 0 -1 241 -3.1139418482780457e-02 - 2.8928443789482117e-01 -6.7743733525276184e-02 + 2.5138390064239502e-01 -9.4933450222015381e-02 <_> - 0 -1 531 6.3710450194776058e-03 + 0 -1 459 9.1597874416038394e-04 - -9.2935405671596527e-02 1.9695936143398285e-01 + -7.4231699109077454e-02 3.1368830800056458e-01 <_> - 0 -1 578 -1.8336625071242452e-03 + 0 -1 747 -6.1164153739809990e-03 - -3.5492643713951111e-01 5.1711678504943848e-02 - <_> - - 0 -1 917 2.1252036094665527e-03 - - 2.0353749394416809e-02 -7.2820025682449341e-01 - <_> - - 0 -1 233 1.1279534548521042e-02 - - 2.5639204308390617e-02 -5.8714842796325684e-01 - <_> - - 0 -1 679 -1.1507571488618851e-01 - - -7.1453052759170532e-01 2.0069327205419540e-02 - <_> - - 0 -1 757 -1.9626193679869175e-03 - - 1.6723833978176117e-01 -1.0802425444126129e-01 - <_> - - 0 -1 756 4.7044735401868820e-03 - - -5.0709329545497894e-02 3.6821383237838745e-01 - <_> - - 0 -1 951 1.8476420082151890e-03 - - 2.8631281107664108e-02 -6.8395125865936279e-01 - <_> - - 0 -1 546 -5.4538771510124207e-03 - - -6.8269199132919312e-01 2.0947692915797234e-02 - <_> - - 0 -1 130 -1.0074324905872345e-02 - - -5.0528079271316528e-01 2.8627410531044006e-02 - <_> - - 0 -1 207 -3.2069636508822441e-03 - - 1.8038518726825714e-01 -9.3303814530372620e-02 - <_> - - 0 -1 327 3.5637444816529751e-03 - - -6.5284818410873413e-02 3.2510238885879517e-01 - <_> - - 0 -1 247 2.1060477010905743e-03 - - 3.0474457889795303e-02 -5.9379291534423828e-01 - <_> - - 0 -1 568 4.2934687808156013e-03 - - -7.1521542966365814e-02 2.4279323220252991e-01 - <_> - - 0 -1 809 8.2498760893940926e-03 - - 3.7760157138109207e-02 -4.5278856158256531e-01 - <_> - - 0 -1 606 2.5047136005014181e-03 - - -7.9689919948577881e-02 2.0523649454116821e-01 - <_> - - 0 -1 651 -1.7786353128030896e-03 - - -6.7214471101760864e-01 2.7108855545520782e-02 - <_> - - 0 -1 93 5.6851857900619507e-01 - - -2.9719989746809006e-02 6.2848883867263794e-01 - <_> - - 0 -1 1 -3.9951098151504993e-03 - - 1.6902630031108856e-01 -9.6066430211067200e-02 - <_> - - 0 -1 790 -1.1912260204553604e-02 - - 1.8001109361648560e-01 -1.0152278095483780e-01 - <_> - - 0 -1 13 -3.2837040722370148e-02 - - 2.2790163755416870e-01 -7.5773715972900391e-02 - <_> - - 0 -1 714 -9.5821768045425415e-03 - - 2.8319683670997620e-01 -6.0501150786876678e-02 - <_> - - 0 -1 584 -7.0154434069991112e-03 - - 3.7711927294731140e-01 -4.5414235442876816e-02 - <_> - - 0 -1 598 2.2930791601538658e-03 - - -9.7957342863082886e-02 1.8666461110115051e-01 - <_> - - 0 -1 409 3.6181495524942875e-03 - - -8.5584357380867004e-02 2.1272744238376617e-01 - <_> - - 0 -1 169 -3.5851418506354094e-03 - - -3.2166537642478943e-01 5.0518564879894257e-02 - <_> - - 0 -1 736 2.0358990877866745e-03 - - -9.0195730328559875e-02 1.7850238084793091e-01 - <_> - - 0 -1 328 3.0855672433972359e-02 - - 7.0852726697921753e-02 -2.3407098650932312e-01 - <_> - - 0 -1 543 -2.8650071471929550e-03 - - 2.5149047374725342e-01 -7.0797137916088104e-02 - <_> - - 0 -1 658 6.9189509376883507e-03 - - -7.6844424009323120e-02 2.2756692767143250e-01 - <_> - - 0 -1 831 3.2940365374088287e-02 - - -6.0664962977170944e-02 2.7875399589538574e-01 - <_> - - 0 -1 835 8.9268945157527924e-03 - - -8.5170723497867584e-02 2.3205895721912384e-01 - <_> - - 0 -1 645 -7.8886147821322083e-04 - - -2.9130771756172180e-01 6.2974251806735992e-02 - <_> - - 0 -1 71 -5.6759864091873169e-03 - - -4.1244068741798401e-01 3.6539580672979355e-02 - <_> - - 0 -1 273 1.2777841184288263e-03 - - -8.5783556103706360e-02 1.8866100907325745e-01 - <_> - - 0 -1 887 3.7156887352466583e-02 - - -1.0894140601158142e-01 1.4975252747535706e-01 - <_> - - 0 -1 92 -5.7424330711364746e-01 - - 7.2750979661941528e-01 -2.4812746793031693e-02 - <_> - - 0 -1 222 -1.3634916394948959e-03 - - 2.2405619919300079e-01 -6.9666981697082520e-02 - <_> - - 0 -1 814 3.3075414597988129e-02 - - -5.6832231581211090e-02 3.0118697881698608e-01 + -7.0417582988739014e-01 3.4018490463495255e-02 <_> - 100 - -1.5318367481231689e+00 + 77 + -1.3230814933776855e+00 <_> - 0 -1 770 -2.2907990496605635e-03 + 0 -1 522 -3.3400340471416712e-03 - 5.9861046075820923e-01 8.8971912860870361e-02 + 4.2352598905563354e-01 -1.2572944164276123e-01 <_> - 0 -1 256 3.1865492928773165e-03 + 0 -1 799 -2.3890279699116945e-03 - -1.5604956448078156e-01 3.8612595200538635e-01 + 3.8169610500335693e-01 -1.4501731097698212e-01 <_> - 0 -1 561 -8.0397585406899452e-03 + 0 -1 448 -2.4045775644481182e-03 - 2.8996115922927856e-01 -1.8175528943538666e-01 + 3.4690696001052856e-01 -1.2821178138256073e-01 <_> - 0 -1 850 4.3595694005489349e-03 + 0 -1 524 1.2546034995466471e-03 - -8.0427564680576324e-02 5.0874835252761841e-01 + -1.4823316037654877e-01 2.9894015192985535e-01 <_> - 0 -1 264 2.8643116354942322e-02 + 0 -1 752 -1.8236635252833366e-02 - -1.7203453183174133e-01 3.2913634181022644e-01 + 3.0641126632690430e-01 -1.2427721172571182e-01 <_> - 0 -1 896 -3.1282915733754635e-03 + 0 -1 229 4.1921215597540140e-04 - 3.7550333142280579e-01 -9.1347120702266693e-02 + -1.8449674546718597e-01 1.7403297126293182e-01 <_> - 0 -1 778 1.4058926608413458e-03 + 0 -1 914 -3.0837533995509148e-03 - -1.9007267057895660e-01 1.6663856804370880e-01 + -6.2562137842178345e-01 3.4162398427724838e-02 <_> - 0 -1 230 1.0209476575255394e-02 + 0 -1 587 -3.4897932782769203e-03 - -1.2146373838186264e-01 2.3719595372676849e-01 + 2.0127655565738678e-01 -1.4677318930625916e-01 <_> - 0 -1 313 6.0191084630787373e-03 + 0 -1 882 -3.4818234853446484e-03 - 5.1051452755928040e-02 -5.5820345878601074e-01 + 2.9465374350547791e-01 -1.0961814969778061e-01 <_> - 0 -1 395 -4.7453744336962700e-03 + 0 -1 13 6.2356598675251007e-02 - 1.6992042958736420e-01 -1.6199907660484314e-01 + -9.8056003451347351e-02 3.1733244657516479e-01 <_> - 0 -1 771 1.5875545796006918e-03 + 0 -1 607 -1.8334560096263885e-02 - -1.0143589228391647e-01 2.6255446672439575e-01 + 3.1992998719215393e-01 -7.8213296830654144e-02 <_> - 0 -1 183 -2.7861427515745163e-03 + 0 -1 885 3.7803263403475285e-03 - -4.0354993939399719e-01 6.7644119262695312e-02 + 5.3678415715694427e-02 -5.0315982103347778e-01 <_> - 0 -1 56 4.0722191333770752e-03 + 0 -1 1027 -3.6906298249959946e-02 - 4.1441403329372406e-02 -5.5184590816497803e-01 + -6.3056147098541260e-01 3.8218058645725250e-02 <_> - 0 -1 953 1.0626179864630103e-03 + 0 -1 923 4.6968068927526474e-03 - -1.4222721755504608e-01 1.7192882299423218e-01 + -1.1338837444782257e-01 2.6388064026832581e-01 <_> - 0 -1 280 4.7259610146284103e-03 + 0 -1 708 -1.1566210538148880e-02 - 5.1823709160089493e-02 -3.9256933331489563e-01 + 1.6388712823390961e-01 -1.6043519973754883e-01 <_> - 0 -1 766 -2.6500346139073372e-03 + 0 -1 489 3.1895786523818970e-03 - -3.5642188787460327e-01 6.6784784197807312e-02 + 6.0215596109628677e-02 -4.7157511115074158e-01 <_> - 0 -1 375 3.9345081895589828e-03 + 0 -1 50 -2.5480750948190689e-02 - -6.1840496957302094e-02 3.9278426766395569e-01 + -5.5096846818923950e-01 3.9257630705833435e-02 <_> - 0 -1 334 8.9293124619871378e-04 + 0 -1 480 3.9267786778509617e-03 - -1.0518563538789749e-01 2.3271512985229492e-01 + 6.1174295842647552e-02 -4.1686600446701050e-01 <_> - 0 -1 381 5.7920545339584351e-02 + 0 -1 874 4.2923549190163612e-03 - -6.8776324391365051e-02 3.3801963925361633e-01 + -6.9901801645755768e-02 3.6233785748481750e-01 <_> - 0 -1 529 -6.6577367484569550e-02 + 0 -1 929 1.5720827504992485e-03 - 4.2277967929840088e-01 -6.3239939510822296e-02 + -9.2891335487365723e-02 2.6970732212066650e-01 <_> - 0 -1 184 -5.5271089076995850e-03 + 0 -1 937 4.2968937195837498e-03 - -4.1861197352409363e-01 6.0344558209180832e-02 + 4.5402236282825470e-02 -6.1771476268768311e-01 <_> - 0 -1 355 3.3537389244884253e-03 + 0 -1 223 5.8442405425012112e-03 - -1.5910768508911133e-01 1.7853063344955444e-01 + 3.4459017217159271e-02 -6.2251347303390503e-01 <_> - 0 -1 427 -2.3959013633430004e-03 + 0 -1 663 2.6888614520430565e-03 - 2.5072932243347168e-01 -8.5364922881126404e-02 + 3.6230482161045074e-02 -5.7353609800338745e-01 <_> - 0 -1 244 -2.1867034956812859e-03 + 0 -1 424 4.4175283983349800e-03 - -5.6374865770339966e-01 3.5474341362714767e-02 + -6.4959764480590820e-02 3.7311050295829773e-01 <_> - 0 -1 602 2.4597872979938984e-03 + 0 -1 138 1.4900951646268368e-03 - 3.1019955873489380e-02 -5.5415368080139160e-01 + -1.0781793296337128e-01 2.0226408541202545e-01 <_> - 0 -1 577 -2.9149088077247143e-03 + 0 -1 373 2.4665119126439095e-03 - -4.6299308538436890e-01 3.7638399749994278e-02 + 5.7804334908723831e-02 -4.1689205169677734e-01 <_> - 0 -1 905 -1.5585927758365870e-03 + 0 -1 441 9.3985523562878370e-04 - 1.4355151355266571e-01 -1.3060651719570160e-01 + -1.4865192770957947e-01 1.3861793279647827e-01 <_> - 0 -1 70 -3.1853761523962021e-02 + 0 -1 132 -5.3606871515512466e-03 - -4.6954944729804993e-01 3.7520393729209900e-02 + 1.8524695932865143e-01 -1.1567704379558563e-01 <_> - 0 -1 472 -5.1449546590447426e-03 + 0 -1 636 -4.6638157218694687e-03 - 2.7591976523399353e-01 -6.6930308938026428e-02 + 1.6163532435894012e-01 -1.3586524128913879e-01 <_> - 0 -1 55 -1.7139092087745667e-03 + 0 -1 120 3.7256032228469849e-03 - -3.8028663396835327e-01 4.9521040171384811e-02 + 5.2170656621456146e-02 -4.2538973689079285e-01 <_> - 0 -1 98 -1.0931883752346039e-01 + 0 -1 106 -8.9184641838073730e-03 - -4.1068795323371887e-01 4.0003888309001923e-02 + -5.0052535533905029e-01 4.7540370374917984e-02 <_> - 0 -1 158 -2.5099035352468491e-02 + 0 -1 474 5.6020710617303848e-03 - 4.3478006124496460e-01 -5.5282033979892731e-02 + 3.4621786326169968e-02 -5.4071390628814697e-01 <_> - 0 -1 435 8.1472359597682953e-03 + 0 -1 475 -3.7551699206233025e-03 - -4.5095365494489670e-02 3.9842218160629272e-01 + -3.9268767833709717e-01 5.2867397665977478e-02 <_> - 0 -1 765 -1.9677784293889999e-03 + 0 -1 567 4.0759481489658356e-03 - 1.8696348369121552e-01 -1.1214685440063477e-01 + 3.7209436297416687e-02 -4.7708320617675781e-01 <_> - 0 -1 656 -2.6076552458107471e-03 + 0 -1 413 4.1836635209619999e-03 - 2.2791831195354462e-01 -8.7665997445583344e-02 + -5.8815345168113708e-02 3.6573976278305054e-01 <_> - 0 -1 490 -4.1761510074138641e-03 + 0 -1 477 -9.3902507796883583e-04 - -6.8348854780197144e-01 2.8925698250532150e-02 + 1.9424098730087280e-01 -1.1125016957521439e-01 <_> - 0 -1 774 1.3159511610865593e-02 + 0 -1 985 -9.9178254604339600e-03 - 2.1792927756905556e-02 -7.0727092027664185e-01 + -5.9317117929458618e-01 3.3418238162994385e-02 <_> - 0 -1 548 -5.1895831711590290e-03 + 0 -1 646 3.3355036284774542e-03 - -6.6959971189498901e-01 2.1171124652028084e-02 + -8.7399490177631378e-02 2.4422888457775116e-01 <_> - 0 -1 323 -1.5662111341953278e-02 + 0 -1 646 -3.4440397284924984e-03 - -3.6895245313644409e-01 4.1785925626754761e-02 + 2.9363137483596802e-01 -7.5259201228618622e-02 <_> - 0 -1 0 -2.4020818527787924e-03 + 0 -1 42 2.1378418896347284e-03 - 1.7773237824440002e-01 -1.0461435467004776e-01 + 5.6551665067672729e-02 -3.9630606770515442e-01 <_> - 0 -1 631 1.9489541649818420e-02 + 0 -1 1005 -4.5215697027742863e-03 - 3.1142184510827065e-02 -5.4499447345733643e-01 + 1.6443158686161041e-01 -1.1997994035482407e-01 <_> - 0 -1 143 4.9672335386276245e-01 + 0 -1 47 -1.2263706885278225e-03 - -2.4833207949995995e-02 7.6724356412887573e-01 + -2.6839572191238403e-01 7.8797832131385803e-02 <_> - 0 -1 403 3.2806373201310635e-03 + 0 -1 926 -7.3856199160218239e-03 - -6.8504363298416138e-02 2.2050221264362335e-01 + -7.5282222032546997e-01 2.3323338478803635e-02 <_> - 0 -1 638 2.1590515971183777e-03 + 0 -1 1044 1.1934632435441017e-02 - 2.5587400421500206e-02 -6.2128585577011108e-01 + 3.9068166166543961e-02 -4.3301787972450256e-01 <_> - 0 -1 604 5.2638887427747250e-04 + 0 -1 826 -4.2066089808940887e-03 - -9.3414209783077240e-02 1.7369781434535980e-01 + 3.1933805346488953e-01 -6.1786398291587830e-02 <_> - 0 -1 510 -2.1490573417395353e-03 + 0 -1 779 -1.5679887728765607e-03 - -4.4394543766975403e-01 3.9975218474864960e-02 + 2.1744215488433838e-01 -9.4651907682418823e-02 <_> - 0 -1 605 1.9845911301672459e-03 + 0 -1 78 2.5083343498408794e-03 - -8.5414819419384003e-02 2.0132684707641602e-01 + 5.7137917727231979e-02 -3.3361336588859558e-01 <_> - 0 -1 565 -3.2773464918136597e-03 + 0 -1 660 3.6224797368049622e-03 - 2.4408425390720367e-01 -7.3116399347782135e-02 + 3.1345754861831665e-02 -5.7247912883758545e-01 <_> - 0 -1 523 2.1245577372610569e-03 + 0 -1 870 -7.7814143151044846e-03 - 2.9403384774923325e-02 -5.7607394456863403e-01 + 2.9652404785156250e-01 -6.6501826047897339e-02 <_> - 0 -1 286 1.4500851975753903e-03 + 0 -1 800 -4.1631370550021529e-04 - -6.6218085587024689e-02 2.4264883995056152e-01 + 2.2159980237483978e-01 -1.0610108822584152e-01 <_> - 0 -1 939 -4.5542549341917038e-03 + 0 -1 596 4.7841453924775124e-03 - -5.8058720827102661e-01 2.8668973594903946e-02 + 3.3327136188745499e-02 -5.7043993473052979e-01 <_> - 0 -1 343 4.7045715153217316e-02 + 0 -1 347 1.2740758247673512e-03 - 3.6376014351844788e-02 -4.1573047637939453e-01 + -7.9592645168304443e-02 2.4728350341320038e-01 <_> - 0 -1 349 7.7028926461935043e-03 + 0 -1 59 -2.0162630826234818e-02 - -7.7403679490089417e-02 2.1597269177436829e-01 + -7.0677626132965088e-01 2.7118822559714317e-02 <_> - 0 -1 53 -4.1527286171913147e-02 + 0 -1 165 -2.5762226432561874e-02 - -3.4835410118103027e-01 4.8530772328376770e-02 + -5.9367066621780396e-01 2.7015525847673416e-02 <_> - 0 -1 748 -9.1361545491963625e-04 + 0 -1 255 -1.1241633910685778e-03 - 1.8357329070568085e-01 -9.0061083436012268e-02 + 2.9121127724647522e-01 -6.5690472722053528e-02 <_> - 0 -1 674 -5.0414498895406723e-02 + 0 -1 818 2.9669383540749550e-02 - 2.5009948015213013e-01 -6.4314760267734528e-02 + 3.4585461020469666e-02 -5.4837781190872192e-01 <_> - 0 -1 398 7.4737053364515305e-03 + 0 -1 501 -6.3295168802142143e-03 - -5.7431813329458237e-02 2.8318390250205994e-01 + 2.3453639447689056e-01 -8.5172846913337708e-02 <_> - 0 -1 654 2.3173280060291290e-03 + 0 -1 1046 4.0143523365259171e-03 - 3.7970397621393204e-02 -5.6861978769302368e-01 + 3.5306803882122040e-02 -5.4817456007003784e-01 <_> - 0 -1 874 4.5855477219447494e-04 + 0 -1 949 -2.4633856955915689e-03 - -1.3554716110229492e-01 1.1426483094692230e-01 + 1.6164709627628326e-01 -1.1111633479595184e-01 <_> - 0 -1 103 1.8236173782497644e-03 + 0 -1 38 -2.6468174532055855e-02 - 2.6509260758757591e-02 -5.5975830554962158e-01 + 2.5775042176246643e-01 -7.2721429169178009e-02 <_> - 0 -1 732 -1.3565555214881897e-02 + 0 -1 1047 -2.5992670562118292e-03 - 3.5292169451713562e-01 -4.7534435987472534e-02 + -3.1405648589134216e-01 5.9779226779937744e-02 <_> - 0 -1 285 -1.2756066862493753e-03 + 0 -1 809 -2.2960878908634186e-02 - 2.5920400023460388e-01 -5.7072717696428299e-02 + 2.8405818343162537e-01 -6.8080194294452667e-02 <_> - 0 -1 746 6.7418040707707405e-03 + 0 -1 437 -1.6940593719482422e-02 - 3.2604463398456573e-02 -4.5861816406250000e-01 + 3.0056476593017578e-01 -6.7668616771697998e-02 <_> - 0 -1 827 6.5548229031264782e-04 + 0 -1 528 1.7171052750200033e-03 - -8.4788605570793152e-02 1.8131427466869354e-01 + -6.5253980457782745e-02 2.9430890083312988e-01 <_> - 0 -1 929 2.1027602255344391e-02 + 0 -1 142 -5.2873874083161354e-03 - -6.9927647709846497e-02 2.4611653387546539e-01 + -4.5413893461227417e-01 4.3044254183769226e-02 <_> - 0 -1 695 1.8613610416650772e-02 + 0 -1 14 -1.8073642626404762e-02 - -3.6128688603639603e-02 4.4170859456062317e-01 + -3.4945023059844971e-01 5.2509855479001999e-02 <_> - 0 -1 99 -4.9805632233619690e-01 + 0 -1 627 -2.0803229417651892e-03 - 5.9478044509887695e-01 -2.6719097048044205e-02 + -4.0171647071838379e-01 4.5229051262140274e-02 <_> - 0 -1 620 -3.2723334152251482e-03 + 0 -1 918 -1.1218651343369856e-04 - 2.2165246307849884e-01 -6.8788610398769379e-02 + 1.2830497324466705e-01 -1.4649079740047455e-01 <_> - 0 -1 583 -3.5375617444515228e-03 + 0 -1 84 -6.6526420414447784e-03 - -6.1987191438674927e-01 2.6597078889608383e-02 + -3.4429419040679932e-01 5.4524090141057968e-02 <_> - 0 -1 632 3.9524696767330170e-03 + 0 -1 162 -4.1576132178306580e-02 - -7.5478851795196533e-02 2.1777774393558502e-01 + -5.5132204294204712e-01 3.2239176332950592e-02 <_> - 0 -1 681 -9.3436334282159805e-03 + 0 -1 659 -3.2582432031631470e-03 - -8.0256491899490356e-01 2.2864339873194695e-02 + 2.1904261410236359e-01 -9.0739406645298004e-02 <_> - 0 -1 671 -1.0151248425245285e-03 + 0 -1 711 -4.4706808403134346e-03 - -3.1884235143661499e-01 4.3938383460044861e-02 + 2.2556288540363312e-01 -9.5258384943008423e-02 <_> - 0 -1 516 -7.0278989151120186e-03 + 0 -1 177 -6.5750535577535629e-03 - 1.4721503853797913e-01 -1.1400235444307327e-01 + -4.8511472344398499e-01 4.1734144091606140e-02 <_> - 0 -1 611 -9.1165518388152122e-03 + 0 -1 251 -3.7532784044742584e-02 - 2.6830977201461792e-01 -6.4460486173629761e-02 + 2.0968079566955566e-01 -8.8354945182800293e-02 <_> - 0 -1 35 3.3993504941463470e-02 + 0 -1 530 -1.2600638438016176e-03 - 2.7748649939894676e-02 -5.5171352624893188e-01 + 2.2111406922340393e-01 -9.0988010168075562e-02 <_> - 0 -1 557 -2.6347138918936253e-03 + 0 -1 28 -2.3967802524566650e-02 - 1.7853704094886780e-01 -8.4178321063518524e-02 + -6.2524855136871338e-01 3.0603738501667976e-02 <_> - 0 -1 712 -1.3291095383465290e-03 + 0 -1 225 -3.1747903674840927e-02 - -2.8526228666305542e-01 5.6452732533216476e-02 - <_> - - 0 -1 719 1.2167419772595167e-03 - - -7.7132880687713623e-02 1.9538262486457825e-01 - <_> - - 0 -1 856 1.9806078635156155e-03 - - 2.6976436376571655e-02 -5.4301941394805908e-01 - <_> - - 0 -1 617 5.0783145707100630e-04 - - -9.5295064151287079e-02 1.5398529171943665e-01 - <_> - - 0 -1 440 -5.0868269056081772e-02 - - -6.3152486085891724e-01 2.3585954681038857e-02 - <_> - - 0 -1 503 -1.4806092949584126e-03 - - 2.6132494211196899e-01 -6.3322558999061584e-02 - <_> - - 0 -1 28 -1.8584117293357849e-02 - - 1.6097819805145264e-01 -1.1777820438146591e-01 - <_> - - 0 -1 250 2.7171591296792030e-02 - - -8.3719044923782349e-02 1.9814659655094147e-01 - <_> - - 0 -1 390 -6.8197408691048622e-03 - - -5.4431658983230591e-01 2.8722483664751053e-02 - <_> - - 0 -1 696 -9.1905370354652405e-03 - - 1.5037034451961517e-01 -1.0166583955287933e-01 - <_> - - 0 -1 192 -9.7952038049697876e-04 - - -2.9014238715171814e-01 4.9301091581583023e-02 - <_> - - 0 -1 884 -2.1513784304261208e-03 - - 2.4622270464897156e-01 -6.0794923454523087e-02 - <_> - - 0 -1 881 -2.0869732834398746e-03 - - 2.0386496186256409e-01 -8.8516488671302795e-02 - <_> - - 0 -1 42 -1.2946429662406445e-02 - - -5.2757191658020020e-01 2.9759777709841728e-02 - <_> - - 0 -1 985 -3.5145760048180819e-03 - - -4.7929930686950684e-01 2.8995612636208534e-02 - <_> - - 0 -1 212 2.4212854914367199e-03 - - -6.4840331673622131e-02 2.4126507341861725e-01 - <_> - - 0 -1 199 2.1736249327659607e-03 - - 2.2003039717674255e-02 -7.0873755216598511e-01 - <_> - - 0 -1 365 -3.5567809827625751e-03 - - 2.9770645499229431e-01 -5.5486857891082764e-02 - <_> - - 0 -1 249 -1.9639974460005760e-02 - - -7.8722274303436279e-01 2.1807981655001640e-02 - <_> - - 0 -1 653 8.1145912408828735e-03 - - 2.0471598953008652e-02 -5.9867942333221436e-01 - <_> - - 0 -1 706 1.2241180054843426e-02 - - 1.6892330721020699e-02 -7.4894833564758301e-01 - <_> - - 0 -1 794 3.2565161585807800e-02 - - 1.8086636438965797e-02 -6.3382810354232788e-01 - <_> - - 0 -1 498 1.2451345100998878e-02 - - -6.6715493798255920e-02 2.1516454219818115e-01 - <_> - - 0 -1 284 -2.9989825561642647e-02 - - 2.0229698717594147e-01 -6.8314045667648315e-02 + -6.2007570266723633e-01 2.5801742449402809e-02 <_> - 100 - -1.6178516149520874e+00 + 84 + -1.3265128135681152e+00 <_> - 0 -1 499 -3.4503117203712463e-03 + 0 -1 801 -2.4247136898338795e-03 - 6.1788332462310791e-01 1.1437324434518814e-01 + 4.3507692217826843e-01 -1.1363404244184494e-01 <_> - 0 -1 876 4.8226695507764816e-03 + 0 -1 239 3.6287805996835232e-03 - -1.0551112145185471e-01 4.8962607979774475e-01 + -1.5781879425048828e-01 3.3899685740470886e-01 <_> - 0 -1 772 5.1433052867650986e-03 + 0 -1 591 -4.2556263506412506e-03 - -1.1823723465204239e-01 4.1509538888931274e-01 + 2.2901295125484467e-01 -2.0403152704238892e-01 <_> - 0 -1 786 1.8649311736226082e-02 + 0 -1 847 1.6322638839483261e-03 - -1.4054079353809357e-01 4.4154295325279236e-01 + -1.9230945408344269e-01 2.0004445314407349e-01 <_> - 0 -1 133 -2.9543964192271233e-03 + 0 -1 338 1.4746835455298424e-02 - 2.5874784588813782e-01 -1.4265626668930054e-01 + -1.2184409052133560e-01 3.9130899310112000e-01 <_> - 0 -1 851 3.1133145093917847e-03 + 0 -1 192 -1.5139304101467133e-02 - -8.1695765256881714e-02 3.6735343933105469e-01 + 2.6918080449104309e-01 -1.4086124300956726e-01 <_> - 0 -1 49 -3.0071800574660301e-03 + 0 -1 21 -7.4753491207957268e-03 - -3.8455182313919067e-01 7.1067951619625092e-02 + 2.1792158484458923e-01 -1.6056208312511444e-01 <_> - 0 -1 219 -1.9453115761280060e-02 + 0 -1 287 2.3232740350067616e-03 - 2.1075683832168579e-01 -1.2884819507598877e-01 + -1.6489887237548828e-01 1.7108000814914703e-01 <_> - 0 -1 462 -4.8584998585283756e-03 + 0 -1 899 -2.7532558888196945e-03 - 1.6113398969173431e-01 -1.7580857872962952e-01 + -5.3275841474533081e-01 5.2368167787790298e-02 <_> - 0 -1 474 8.2634367048740387e-02 + 0 -1 896 -3.9793960750102997e-03 - -5.9177018702030182e-02 4.0204021334648132e-01 + 3.4057796001434326e-01 -8.0085732042789459e-02 <_> - 0 -1 340 4.5589236542582512e-03 + 0 -1 608 7.1728855371475220e-02 - -1.5169224143028259e-01 2.1497711539268494e-01 + -7.2147607803344727e-02 4.0667375922203064e-01 <_> - 0 -1 810 5.7522351853549480e-03 + 0 -1 883 -5.3792679682374001e-04 - -1.0400034487247467e-01 2.3692265152931213e-01 + 1.7865169048309326e-01 -1.4902706444263458e-01 <_> - 0 -1 30 1.0916464030742645e-02 + 0 -1 248 6.0019297525286674e-03 - 3.2482013106346130e-02 -6.6799944639205933e-01 + 7.1029536426067352e-02 -3.9921376109123230e-01 <_> - 0 -1 334 1.2513624969869852e-03 + 0 -1 369 6.9427289068698883e-02 - -9.2966683208942413e-02 2.5203207135200500e-01 + -9.5279395580291748e-02 2.6865223050117493e-01 <_> - 0 -1 24 8.5552372038364410e-03 + 0 -1 130 -8.8401548564434052e-03 - 4.2838018387556076e-02 -5.4950177669525146e-01 + -5.3491175174713135e-01 5.0447739660739899e-02 <_> - 0 -1 365 1.9793706014752388e-03 + 0 -1 699 -1.4551014639437199e-02 - -1.0328737646341324e-01 2.2137698531150818e-01 + 1.9883459806442261e-01 -1.1586152762174606e-01 <_> - 0 -1 308 -2.3129612207412720e-02 + 0 -1 754 -1.7498439410701394e-03 - -5.9918802976608276e-01 3.7120997905731201e-02 + 2.2214990854263306e-01 -9.8238572478294373e-02 <_> - 0 -1 347 -2.5169795844703913e-03 + 0 -1 246 -2.1636944264173508e-02 - -4.0429180860519409e-01 4.7458905726671219e-02 + 2.8814041614532471e-01 -8.2750618457794189e-02 <_> - 0 -1 290 -2.7680140919983387e-03 + 0 -1 833 1.2786949053406715e-02 - -4.1959136724472046e-01 4.7375876456499100e-02 + -8.7337315082550049e-02 2.6530647277832031e-01 <_> - 0 -1 394 4.4881463982164860e-03 + 0 -1 57 -8.7271071970462799e-03 - -5.3955338895320892e-02 4.0468615293502808e-01 + -5.3538525104522705e-01 5.0595279783010483e-02 <_> - 0 -1 648 1.1571742361411452e-03 + 0 -1 1039 3.3185956999659538e-03 - 6.1304513365030289e-02 -3.6215540766716003e-01 + 4.5733701437711716e-02 -4.4758048653602600e-01 <_> - 0 -1 731 3.6775614134967327e-03 + 0 -1 795 -1.2216938193887472e-03 - 3.5641182214021683e-02 -5.1911950111389160e-01 + 1.5257745981216431e-01 -1.4963941276073456e-01 <_> - 0 -1 828 2.4001342244446278e-03 + 0 -1 562 3.9857804775238037e-02 - -8.0022528767585754e-02 2.6706510782241821e-01 + -8.5655666887760162e-02 2.6823255419731140e-01 <_> - 0 -1 823 -1.4416232006624341e-03 + 0 -1 764 2.4454984813928604e-03 - 2.5601235032081604e-01 -8.7470635771751404e-02 + 4.6102020889520645e-02 -5.0574064254760742e-01 <_> - 0 -1 382 5.0148535519838333e-03 + 0 -1 98 -4.2114150524139404e-01 - 5.7711403816938400e-02 -3.5666841268539429e-01 + 6.9476419687271118e-01 -3.2907195389270782e-02 <_> - 0 -1 399 2.9201959259808064e-03 + 0 -1 558 2.3470625281333923e-02 - -7.3214575648307800e-02 2.7563962340354919e-01 + -8.6790844798088074e-02 2.2723633050918579e-01 <_> - 0 -1 741 -2.8012858820147812e-05 + 0 -1 253 -1.1454307474195957e-02 - 1.3044390082359314e-01 -1.5220497548580170e-01 + 2.5413584709167480e-01 -8.8991768658161163e-02 <_> - 0 -1 962 2.6261559687554836e-03 + 0 -1 624 5.0260839052498341e-03 - 6.3371658325195312e-02 -2.9989096522331238e-01 + 3.8961157202720642e-02 -5.9463697671890259e-01 <_> - 0 -1 114 -1.9985539838671684e-02 + 0 -1 873 1.6196466749534011e-03 - -7.0204716920852661e-01 2.5756308808922768e-02 + -9.0231269598007202e-02 2.6204809546470642e-01 <_> - 0 -1 277 4.0448461659252644e-03 + 0 -1 408 8.1676244735717773e-02 - -9.9051415920257568e-02 2.0554924011230469e-01 + -8.0785289406776428e-02 2.5112318992614746e-01 <_> - 0 -1 294 7.6400241814553738e-03 + 0 -1 483 -5.4313270375132561e-03 - 4.8610400408506393e-02 -4.0662041306495667e-01 + 1.6463221609592438e-01 -1.3186016678810120e-01 <_> - 0 -1 252 1.5262419357895851e-02 + 0 -1 291 5.7006161659955978e-03 - -9.2194251716136932e-02 2.0623819530010223e-01 + -1.3998855650424957e-01 1.4326113462448120e-01 <_> - 0 -1 752 -6.1596641317009926e-03 + 0 -1 221 -7.5926873832941055e-03 - -5.0260418653488159e-01 3.7245232611894608e-02 + -5.5559343099594116e-01 3.7072587758302689e-02 <_> - 0 -1 785 -2.5804866105318069e-02 + 0 -1 618 7.5261802412569523e-03 - -5.2190864086151123e-01 3.0063979327678680e-02 + 2.8434989973902702e-02 -5.8689045906066895e-01 <_> - 0 -1 368 -4.6107484959065914e-03 + 0 -1 869 -6.3516031950712204e-03 - -4.2041480541229248e-01 3.7473026663064957e-02 + 1.4447389543056488e-01 -1.4542055130004883e-01 <_> - 0 -1 936 -1.6811741515994072e-03 + 0 -1 980 -7.6800247188657522e-04 - 3.3520191907882690e-01 -5.3664822131395340e-02 + 1.8556322157382965e-01 -1.0404425859451294e-01 <_> - 0 -1 936 1.0210975306108594e-03 + 0 -1 941 -4.4167470186948776e-03 - -7.0165649056434631e-02 2.7230393886566162e-01 + -7.0306748151779175e-01 3.0874395743012428e-02 <_> - 0 -1 519 -2.7257478795945644e-03 + 0 -1 1010 3.3405693247914314e-03 - -3.7600108981132507e-01 4.8897936940193176e-02 + -6.6534630954265594e-02 3.4018290042877197e-01 <_> - 0 -1 645 1.7022072570398450e-03 + 0 -1 114 1.1457607150077820e-02 - 3.2578211277723312e-02 -4.8195156455039978e-01 + 3.3658623695373535e-02 -6.1056423187255859e-01 <_> - 0 -1 237 2.0580790005624294e-03 + 0 -1 1000 -1.8547235522419214e-03 - -1.1316970735788345e-01 1.4754198491573334e-01 + -7.4722522497177124e-01 2.2372998297214508e-02 <_> - 0 -1 520 1.9031974952667952e-03 + 0 -1 9 -1.9720013439655304e-01 - 6.1289772391319275e-02 -2.7776253223419189e-01 + -5.9932583570480347e-01 2.9283462092280388e-02 <_> - 0 -1 65 -4.5437026768922806e-02 + 0 -1 544 -2.6251156814396381e-03 - 2.8187385201454163e-01 -6.1310045421123505e-02 + -3.0683135986328125e-01 5.5391944944858551e-02 <_> - 0 -1 10 -2.0433391630649567e-01 + 0 -1 17 -2.7104711532592773e-01 - -4.8491853475570679e-01 3.7197910249233246e-02 + -6.4121168851852417e-01 2.6428909972310066e-02 <_> - 0 -1 902 -2.2007026709616184e-03 + 0 -1 349 1.0233232751488686e-02 - -4.8433649539947510e-01 2.8523173183202744e-02 + 4.5153360813856125e-02 -3.6883556842803955e-01 <_> - 0 -1 506 2.4706670083105564e-03 + 0 -1 363 4.0971953421831131e-03 - -8.0774910748004913e-02 2.0636586844921112e-01 + 4.1385501623153687e-02 -4.3035930395126343e-01 <_> - 0 -1 337 -1.1496900115162134e-03 + 0 -1 464 -8.8650803081691265e-04 - 2.0466096699237823e-01 -7.8325189650058746e-02 + 1.6314724087715149e-01 -1.1271495372056961e-01 <_> - 0 -1 390 -4.3232389725744724e-03 + 0 -1 721 -4.1144760325551033e-03 - -3.4593367576599121e-01 4.9537312239408493e-02 + -5.5176359415054321e-01 3.3540870994329453e-02 <_> - 0 -1 112 -9.3772150576114655e-03 + 0 -1 940 -9.8663510289043188e-04 - -5.5802655220031738e-01 2.5828598067164421e-02 + 2.1676342189311981e-01 -8.5408315062522888e-02 <_> - 0 -1 755 -1.6863006167113781e-03 + 0 -1 428 6.0831783339381218e-03 - 1.9700750708580017e-01 -8.0926463007926941e-02 + -8.7310679256916046e-02 2.3208071291446686e-01 <_> - 0 -1 759 5.5908015929162502e-03 + 0 -1 789 -1.4624604955315590e-02 - -5.8355998247861862e-02 3.0854061245918274e-01 + -5.9713214635848999e-01 3.0128041282296181e-02 <_> - 0 -1 483 -4.9319159006699920e-04 + 0 -1 787 1.3654056005179882e-02 - 1.3386693596839905e-01 -1.1287388950586319e-01 + 2.4816744029521942e-02 -6.2301605939865112e-01 <_> - 0 -1 551 -5.3560961037874222e-02 + 0 -1 820 4.2229411192238331e-03 - 3.3912947773933411e-01 -4.4598836451768875e-02 + -7.3886208236217499e-02 2.4938605725765228e-01 <_> - 0 -1 542 -2.4220649152994156e-02 + 0 -1 168 1.3268929906189442e-03 - -4.5232787728309631e-01 4.1364260017871857e-02 + 4.0760166943073273e-02 -4.3510803580284119e-01 <_> - 0 -1 798 1.2709838338196278e-03 + 0 -1 275 -9.6903974190354347e-04 - -8.8080756366252899e-02 1.8180713057518005e-01 + 2.2486831247806549e-01 -7.8642837703227997e-02 <_> - 0 -1 236 -4.4361655600368977e-03 + 0 -1 274 1.0329007636755705e-03 - -4.2694598436355591e-01 3.6063931882381439e-02 + -7.3648050427436829e-02 2.6808246970176697e-01 <_> - 0 -1 791 -6.5719988197088242e-04 + 0 -1 474 -4.2711962014436722e-03 - 1.8804629147052765e-01 -8.5146181285381317e-02 + -4.0931078791618347e-01 4.7851666808128357e-02 <_> - 0 -1 715 1.8579278141260147e-02 + 0 -1 983 -3.7627927958965302e-03 - 4.4604945927858353e-02 -3.7216106057167053e-01 + -5.0520634651184082e-01 3.0405685305595398e-02 <_> - 0 -1 857 3.0188630335032940e-03 + 0 -1 979 -1.7928264569491148e-03 - -9.7823068499565125e-02 1.5584464371204376e-01 + 3.3886525034904480e-01 -5.3929597139358521e-02 <_> - 0 -1 868 1.6309421043843031e-03 + 0 -1 148 3.9475625380873680e-03 - 3.5910408943891525e-02 -4.3541318178176880e-01 + 3.4511350095272064e-02 -5.2250456809997559e-01 <_> - 0 -1 139 1.3791467994451523e-02 + 0 -1 827 -4.4537894427776337e-03 - 1.7177715897560120e-02 -7.7653616666793823e-01 + 2.2575919330120087e-01 -7.4650920927524567e-02 <_> - 0 -1 248 1.0393885895609856e-03 + 0 -1 774 -2.9974281787872314e-02 - -1.2292464822530746e-01 1.1997509002685547e-01 + -6.0629475116729736e-01 3.4456655383110046e-02 <_> - 0 -1 417 -1.8992213299497962e-03 + 0 -1 123 2.6775486767292023e-02 - -5.8449220657348633e-01 2.3935828357934952e-02 + -8.8883727788925171e-02 2.0147153735160828e-01 <_> - 0 -1 366 -4.4655447709374130e-04 + 0 -1 302 -4.4971965253353119e-03 - 1.8246568739414215e-01 -8.1576324999332428e-02 + -5.3158396482467651e-01 3.3491309732198715e-02 <_> - 0 -1 85 1.1696915607899427e-03 + 0 -1 620 -1.5196309424936771e-02 - 4.1298836469650269e-02 -3.7100258469581604e-01 + 2.8140705823898315e-01 -6.4074374735355377e-02 <_> - 0 -1 906 -8.9874223340302706e-04 + 0 -1 560 -2.1833679638803005e-03 - 1.3932932913303375e-01 -1.0641934722661972e-01 + 2.1953551471233368e-01 -8.5029341280460358e-02 <_> - 0 -1 862 5.9534879401326180e-03 + 0 -1 317 -5.4325433447957039e-03 - 2.6781413704156876e-02 -6.1212611198425293e-01 + -4.8182886838912964e-01 3.8184959441423416e-02 <_> - 0 -1 861 -8.0954860895872116e-03 + 0 -1 463 -3.9055421948432922e-03 - 2.6603493094444275e-01 -5.9750139713287354e-02 + -3.5678783059120178e-01 4.5511916279792786e-02 <_> - 0 -1 287 -8.2374701742082834e-04 + 0 -1 1017 -5.0043486990034580e-03 - 2.1638387441635132e-01 -6.4249947667121887e-02 + -3.5324424505233765e-01 4.9539435654878616e-02 <_> - 0 -1 271 -7.6250307029113173e-04 + 0 -1 595 4.2052613571286201e-03 - 2.0882584154605865e-01 -8.5345618426799774e-02 + -7.6765090227127075e-02 2.4410718679428101e-01 <_> - 0 -1 959 2.3917213547974825e-03 + 0 -1 642 -2.9198043048381805e-03 - 2.9081748798489571e-02 -5.5320137739181519e-01 + 2.8657916188240051e-01 -9.1479435563087463e-02 <_> - 0 -1 957 -5.6062731891870499e-03 + 0 -1 116 1.4442477375268936e-02 - -3.1231331825256348e-01 4.6577330678701401e-02 + 2.2604020312428474e-02 -7.7516084909439087e-01 <_> - 0 -1 807 1.2068089097738266e-02 + 0 -1 956 1.0879908688366413e-02 - -6.9983117282390594e-02 2.1360129117965698e-01 + -8.9434660971164703e-02 1.8898591399192810e-01 <_> - 0 -1 664 -6.1361752450466156e-03 + 0 -1 707 1.2304648756980896e-01 - 1.5866123139858246e-01 -8.9951172471046448e-02 + 2.9145279899239540e-02 -5.6789475679397583e-01 <_> - 0 -1 686 2.7342736721038818e-03 + 0 -1 301 5.4486069828271866e-02 - 4.6424146741628647e-02 -3.2302507758140564e-01 + -8.0465197563171387e-02 2.1073351800441742e-01 <_> - 0 -1 190 2.5015277788043022e-02 + 0 -1 37 -1.0112209245562553e-02 - -9.2339992523193359e-02 1.6995115578174591e-01 + 2.5688818097114563e-01 -7.3113977909088135e-02 <_> - 0 -1 6 3.6676183342933655e-02 + 0 -1 145 -4.3551158159971237e-03 - -8.1868082284927368e-02 2.0542381703853607e-01 + -4.0537205338478088e-01 5.1149621605873108e-02 <_> - 0 -1 641 2.9560746625065804e-03 + 0 -1 377 2.8712721541523933e-03 - 4.2714115232229233e-02 -3.9473703503608704e-01 + -8.9186541736125946e-02 2.0391693711280823e-01 <_> - 0 -1 478 -5.4626376368105412e-04 + 0 -1 220 2.4744076654314995e-02 - 1.7010760307312012e-01 -9.1078221797943115e-02 + 3.1359996646642685e-02 -5.9586691856384277e-01 <_> - 0 -1 479 3.5485455300658941e-03 + 0 -1 19 6.0209888033568859e-03 - -7.2080396115779877e-02 2.2900597751140594e-01 + -8.2612000405788422e-02 2.1787849068641663e-01 <_> - 0 -1 485 -3.1973507720977068e-03 + 0 -1 852 6.0595902614295483e-03 - 2.0531810820102692e-01 -8.5912480950355530e-02 + 4.7610606998205185e-02 -3.5010379552841187e-01 <_> - 0 -1 867 -2.5095739401876926e-03 + 0 -1 324 -2.1957855671644211e-02 - -3.3782237768173218e-01 5.3629480302333832e-02 + 2.2477181255817413e-01 -7.5377546250820160e-02 <_> - 0 -1 312 1.2365024536848068e-02 + 0 -1 385 -3.9967135526239872e-03 - 2.7145428583025932e-02 -5.5763113498687744e-01 + 4.3043723702430725e-01 -3.9885677397251129e-02 <_> - 0 -1 910 2.0736612379550934e-02 + 0 -1 745 -2.0381226204335690e-03 - -6.0063906013965607e-02 2.5700190663337708e-01 + -5.8131587505340576e-01 3.2071832567453384e-02 <_> - 0 -1 15 2.6504596695303917e-02 + 0 -1 337 3.8902673404663801e-03 - 3.4878112375736237e-02 -4.7980275750160217e-01 - <_> - - 0 -1 976 -9.5798689872026443e-03 - - -6.1055964231491089e-01 2.1064205095171928e-02 - <_> - - 0 -1 615 1.9744917750358582e-02 - - -4.9393177032470703e-02 3.0676594376564026e-01 - <_> - - 0 -1 865 3.0523580498993397e-03 - - 4.1798073798418045e-02 -3.5442468523979187e-01 - <_> - - 0 -1 612 -4.3955976143479347e-03 - - 2.5482681393623352e-01 -5.6209251284599304e-02 - <_> - - 0 -1 469 2.2425290662795305e-03 - - -9.7824580967426300e-02 1.7274166643619537e-01 - <_> - - 0 -1 541 7.1967259049415588e-02 - - -3.9488561451435089e-02 3.6034339666366577e-01 - <_> - - 0 -1 181 8.4581580013036728e-03 - - 3.5755772143602371e-02 -4.4762039184570312e-01 - <_> - - 0 -1 665 3.3080112189054489e-03 - - 2.2785754874348640e-02 -5.3823727369308472e-01 - <_> - - 0 -1 437 -1.1890231398865581e-03 - - 1.7143265902996063e-01 -8.1015840172767639e-02 - <_> - - 0 -1 434 -1.7523975111544132e-03 - - 2.5996673107147217e-01 -6.9269210100173950e-02 - <_> - - 0 -1 921 5.4229743545874953e-04 - - -7.4078343808650970e-02 2.0903676748275757e-01 - <_> - - 0 -1 963 3.9791758172214031e-03 - - 4.0985044091939926e-02 -3.6837655305862427e-01 - <_> - - 0 -1 829 -6.9316523149609566e-03 - - -4.1581609845161438e-01 3.2475329935550690e-02 - <_> - - 0 -1 17 4.1018679738044739e-02 - - -6.6409081220626831e-02 2.3296032845973969e-01 - <_> - - 0 -1 86 3.3051387872546911e-03 - - -8.2739837467670441e-02 1.9939082860946655e-01 - <_> - - 0 -1 179 -1.3641032390296459e-02 - - 1.6623613238334656e-01 -8.6717613041400909e-02 + -6.0279250144958496e-02 2.9424437880516052e-01 <_> - 100 - -1.6119387149810791e+00 + 82 + -1.2607949972152710e+00 <_> - 0 -1 508 -1.0795817710459232e-02 + 0 -1 798 -1.9003680208697915e-03 - 5.7589554786682129e-01 9.1795757412910461e-02 + 4.8600798845291138e-01 -7.5834542512893677e-02 <_> - 0 -1 844 -1.4518407406285405e-03 + 0 -1 238 1.5605278313159943e-03 - 3.8668358325958252e-01 -1.4567533135414124e-01 + -1.9763922691345215e-01 2.5329649448394775e-01 <_> - 0 -1 205 1.2619893066585064e-02 + 0 -1 584 -4.8138713464140892e-03 - -1.3285328447818756e-01 3.8423144817352295e-01 + 3.5302931070327759e-01 -1.2585695087909698e-01 <_> - 0 -1 812 -8.6567001417279243e-03 + 0 -1 870 5.7447804138064384e-03 - 2.0455244183540344e-01 -1.9482232630252838e-01 + -1.5453046560287476e-01 3.5572248697280884e-01 <_> - 0 -1 329 8.7269591167569160e-03 + 0 -1 806 3.2787662930786610e-03 - -9.0128563344478607e-02 4.0668380260467529e-01 + -1.8419209122657776e-01 1.6216333210468292e-01 <_> - 0 -1 846 -4.8108389601111412e-03 + 0 -1 423 2.8142044320702553e-03 - 4.0858918428421021e-01 -7.6686508953571320e-02 + -9.4009101390838623e-02 2.7667456865310669e-01 <_> - 0 -1 441 2.7277414119453169e-05 + 0 -1 259 1.8096582498401403e-03 - -2.1661256253719330e-01 1.3865883648395538e-01 + -8.9050479233264923e-02 2.9622453451156616e-01 <_> - 0 -1 426 -9.6549151930958033e-04 + 0 -1 988 7.2106244042515755e-03 - 1.9036890566349030e-01 -1.3512735068798065e-01 + -1.0854976624250412e-01 2.2157947719097137e-01 <_> - 0 -1 215 -1.1629101354628801e-03 + 0 -1 342 1.3368867337703705e-02 - 2.7597144246101379e-01 -8.5875771939754486e-02 + 5.8126326650381088e-02 -3.8564166426658630e-01 <_> - 0 -1 708 3.2347193919122219e-03 + 0 -1 276 1.6755410470068455e-03 - -1.4792887866497040e-01 1.6230462491512299e-01 + -6.9541916251182556e-02 3.6275833845138550e-01 <_> - 0 -1 344 -6.0261571779847145e-03 + 0 -1 198 -4.5782830566167831e-03 - -5.2146345376968384e-01 3.9669245481491089e-02 + -5.6317430734634399e-01 3.9351724088191986e-02 <_> - 0 -1 502 3.7499368190765381e-03 + 0 -1 729 3.6364984698593616e-03 - 4.7719169408082962e-02 -4.2560356855392456e-01 + -1.5140864253044128e-01 1.4790520071983337e-01 <_> - 0 -1 432 -2.2638911381363869e-02 + 0 -1 928 -1.1279541999101639e-02 - 2.7776387333869934e-01 -8.2894414663314819e-02 + -4.8907181620597839e-01 5.1109701395034790e-02 <_> - 0 -1 375 2.8850757516920567e-03 + 0 -1 867 -1.2224027886986732e-02 - -7.3187254369258881e-02 3.4045669436454773e-01 + -6.0496371984481812e-01 3.5609807819128036e-02 <_> - 0 -1 743 9.2617822811007500e-03 + 0 -1 769 -2.8662174940109253e-02 - -6.1159532517194748e-02 3.4422287344932556e-01 + 2.4556699395179749e-01 -9.9369116127490997e-02 <_> - 0 -1 419 4.7564059495925903e-03 + 0 -1 496 6.7924216389656067e-02 - 4.2927626520395279e-02 -5.0712525844573975e-01 + -7.8038521111011505e-02 3.3691942691802979e-01 <_> - 0 -1 588 1.0375332832336426e-01 + 0 -1 962 2.2719642147421837e-03 - 3.7820540368556976e-02 -5.4858410358428955e-01 + 5.8022607117891312e-02 -4.7124773263931274e-01 <_> - 0 -1 527 -1.1948650702834129e-02 + 0 -1 210 8.5627539083361626e-03 - 3.0298843979835510e-01 -7.0214085280895233e-02 + 3.4671626985073090e-02 -4.6883812546730042e-01 <_> - 0 -1 346 1.7851736396551132e-02 + 0 -1 362 1.1866856366395950e-03 - -8.9291095733642578e-02 2.2659333050251007e-01 + -8.0339640378952026e-02 2.5030750036239624e-01 <_> - 0 -1 928 1.7700281459838152e-03 + 0 -1 979 8.1023329403251410e-04 - -9.0894356369972229e-02 2.3938187956809998e-01 + -8.0605715513229370e-02 2.5741192698478699e-01 <_> - 0 -1 42 1.0000608861446381e-02 + 0 -1 281 -4.0647285059094429e-03 - 5.4091196507215500e-02 -4.5715424418449402e-01 + -5.0938653945922852e-01 4.0403041988611221e-02 <_> - 0 -1 554 5.1841903477907181e-03 + 0 -1 309 -1.9617568701505661e-02 - 4.4081535190343857e-02 -4.0113139152526855e-01 + -5.4703706502914429e-01 3.5078343003988266e-02 <_> - 0 -1 216 1.9869320094585419e-03 + 0 -1 233 6.9989012554287910e-03 - -8.6456976830959320e-02 2.3278492689132690e-01 + 2.6246270164847374e-02 -6.0453557968139648e-01 <_> - 0 -1 29 7.3318472132086754e-03 + 0 -1 450 -6.2460554763674736e-03 - 4.4677142053842545e-02 -4.3628835678100586e-01 + 2.3062629997730255e-01 -8.3763726055622101e-02 <_> - 0 -1 224 5.3855171427130699e-03 + 0 -1 529 7.5731135439127684e-04 - 3.1241770833730698e-02 -5.7641702890396118e-01 + -9.5188923180103302e-02 2.3367822170257568e-01 <_> - 0 -1 287 -5.8841239660978317e-04 + 0 -1 462 -3.2256892882287502e-03 - 2.1748071908950806e-01 -9.8720036447048187e-02 + 2.1003848314285278e-01 -1.2173316627740860e-01 <_> - 0 -1 48 -4.6296482905745506e-03 + 0 -1 941 -2.8797222767025232e-03 - -5.0439667701721191e-01 3.9307218044996262e-02 + -4.8621371388435364e-01 4.3998546898365021e-02 <_> - 0 -1 159 1.0425396263599396e-02 + 0 -1 740 5.9399371966719627e-03 - -6.9303810596466064e-02 2.8114342689514160e-01 + 2.7645273134112358e-02 -6.2591820955276489e-01 <_> - 0 -1 821 3.4709304571151733e-02 + 0 -1 742 -5.4768389090895653e-03 - -4.4065892696380615e-02 4.7260922193527222e-01 + 2.5695452094078064e-01 -8.1276804208755493e-02 <_> - 0 -1 913 -1.9787646830081940e-02 + 0 -1 107 -2.2785080596804619e-02 - -6.3054060935974121e-01 3.7138473242521286e-02 + -6.7479509115219116e-01 2.9845010489225388e-02 <_> - 0 -1 832 -1.0857213288545609e-02 + 0 -1 240 -6.0453559271991253e-03 - -3.4433662891387939e-01 4.5778658241033554e-02 + -4.5132589340209961e-01 4.0413774549961090e-02 <_> - 0 -1 228 -3.3750114962458611e-03 + 0 -1 216 5.9022027999162674e-03 - -4.4760662317276001e-01 3.7368919700384140e-02 + 4.6321801841259003e-02 -3.9377251267433167e-01 <_> - 0 -1 799 7.1516213938593864e-04 + 0 -1 775 -1.1740738991647959e-03 - -1.4026457071304321e-01 1.2475384026765823e-01 + 2.2063454985618591e-01 -8.9038714766502380e-02 <_> - 0 -1 694 -3.0070471111685038e-03 + 0 -1 835 -3.7963264621794224e-03 - -5.2588617801666260e-01 3.0897416174411774e-02 + 1.7901860177516937e-01 -1.0518371313810349e-01 <_> - 0 -1 634 -3.0869825277477503e-03 + 0 -1 871 2.4132090620696545e-03 - 2.8596574068069458e-01 -6.7343741655349731e-02 + -9.3182116746902466e-02 2.9489630460739136e-01 <_> - 0 -1 358 -4.3112646788358688e-02 + 0 -1 543 4.5318575575947762e-04 - -7.0135027170181274e-01 2.6632267981767654e-02 + -1.4386458694934845e-01 1.3717848062515259e-01 <_> - 0 -1 672 -1.2020026333630085e-03 + 0 -1 1029 1.8930386751890182e-02 - -3.8874247670173645e-01 4.1288472712039948e-02 + 3.3168405294418335e-02 -5.5337232351303101e-01 <_> - 0 -1 716 -3.8164458237588406e-04 + 0 -1 652 -2.6878318749368191e-03 - 1.3130629062652588e-01 -1.3220198452472687e-01 + -5.4439735412597656e-01 3.1048862263560295e-02 <_> - 0 -1 412 -4.4994866475462914e-03 + 0 -1 672 -3.9407592266798019e-03 - -2.8277575969696045e-01 6.8065464496612549e-02 + -6.5507227182388306e-01 2.4424355477094650e-02 <_> - 0 -1 586 -4.2400006204843521e-03 + 0 -1 599 2.1629813127219677e-03 - -5.7234168052673340e-01 2.4768881499767303e-02 + -1.0160741209983826e-01 1.8277852237224579e-01 <_> - 0 -1 610 3.3328742720186710e-03 + 0 -1 222 -2.9370808042585850e-03 - -6.9700233638286591e-02 2.3259970545768738e-01 + -4.7847637534141541e-01 3.8538910448551178e-02 <_> - 0 -1 26 -1.4152936637401581e-02 + 0 -1 6 3.8221649825572968e-02 - -6.5485191345214844e-01 2.5028359144926071e-02 + -7.6206430792808533e-02 2.3375664651393890e-01 <_> - 0 -1 331 -3.3239413052797318e-02 + 0 -1 393 -3.1483019702136517e-03 - 2.1122130751609802e-01 -8.0384172499179840e-02 + 2.5192636251449585e-01 -7.3695883154869080e-02 <_> - 0 -1 40 3.9529884234070778e-03 + 0 -1 613 -4.5907422900199890e-03 - -7.4974447488784790e-02 2.7394378185272217e-01 + -6.2766075134277344e-01 2.8896089643239975e-02 <_> - 0 -1 657 2.0498572848737240e-03 + 0 -1 26 -9.5378428697586060e-02 - 3.5124473273754120e-02 -5.0805884599685669e-01 + -7.4559724330902100e-01 2.1207747980952263e-02 <_> - 0 -1 670 1.3978367205709219e-03 + 0 -1 639 2.0872952882200480e-03 - -8.5583955049514771e-02 1.9296622276306152e-01 + -8.7810918688774109e-02 2.0629811286926270e-01 <_> - 0 -1 983 3.1700683757662773e-03 + 0 -1 635 -6.9244997575879097e-03 - 4.6254437416791916e-02 -3.5503390431404114e-01 + 1.8590562045574188e-01 -9.8790608346462250e-02 <_> - 0 -1 946 -1.0263657895848155e-03 + 0 -1 590 2.4594084825366735e-03 - 1.3199952244758606e-01 -1.2064760923385620e-01 + -1.0049589723348618e-01 2.2963477671146393e-01 <_> - 0 -1 109 -4.1109144687652588e-02 + 0 -1 1021 -5.2931695245206356e-03 - 1.7420990765094757e-01 -9.8242506384849548e-02 + -4.5924744009971619e-01 4.3104480952024460e-02 <_> - 0 -1 618 1.5759501606225967e-02 + 0 -1 994 4.8847724683582783e-03 - -7.5842045247554779e-02 2.3157498240470886e-01 + 4.6008609235286713e-02 -4.4277390837669373e-01 <_> - 0 -1 449 -9.5934671116992831e-04 + 0 -1 454 1.4400177169591188e-03 - 1.8444137275218964e-01 -9.2052407562732697e-02 + -5.9334080666303635e-02 3.0132320523262024e-01 <_> - 0 -1 864 5.4162740707397461e-03 + 0 -1 156 -8.6052305996417999e-03 - 3.1357165426015854e-02 -5.3519624471664429e-01 + 1.9737368822097778e-01 -8.9747570455074310e-02 <_> - 0 -1 866 3.4875022247433662e-03 + 0 -1 193 -6.1248587444424629e-03 - 4.8432532697916031e-02 -3.3630362153053284e-01 + -4.5141929388046265e-01 3.8760874420404434e-02 <_> - 0 -1 660 1.3441047631204128e-03 + 0 -1 464 -1.8148655071854591e-03 - -8.3214677870273590e-02 2.0162117481231689e-01 + 2.2768247127532959e-01 -8.2637414336204529e-02 <_> - 0 -1 684 -2.3109107278287411e-03 + 0 -1 330 -8.5119507275521755e-04 - 1.8354012072086334e-01 -8.8427804410457611e-02 + 1.9616322219371796e-01 -1.0013028979301453e-01 <_> - 0 -1 481 5.1613273099064827e-03 + 0 -1 417 1.4472046867012978e-02 - -6.8671047687530518e-02 2.2440080344676971e-01 + -8.8336527347564697e-02 1.9660694897174835e-01 <_> - 0 -1 251 -2.3844663053750992e-02 + 0 -1 628 1.4135142788290977e-02 - -6.2796258926391602e-01 2.7813719585537910e-02 + -6.4112767577171326e-02 3.1887489557266235e-01 <_> - 0 -1 421 3.7013965193182230e-03 + 0 -1 390 4.8004039563238621e-03 - -6.7407652735710144e-02 2.7093955874443054e-01 + 4.8681098967790604e-02 -4.6234726905822754e-01 <_> - 0 -1 633 3.9885155856609344e-03 + 0 -1 279 -3.3503584563732147e-02 - 3.4067343920469284e-02 -5.4420226812362671e-01 + 2.5094386935234070e-01 -8.0808885395526886e-02 <_> - 0 -1 309 1.8910076469182968e-02 + 0 -1 943 2.4153569247573614e-03 - 4.2769759893417358e-02 -3.3686736226081848e-01 + -7.2777584195137024e-02 2.6076248288154602e-01 <_> - 0 -1 808 1.2143498286604881e-02 + 0 -1 34 -1.3153228908777237e-02 - 1.9569551572203636e-02 -7.1214914321899414e-01 + 2.3979008197784424e-01 -7.6283767819404602e-02 <_> - 0 -1 188 -5.6570172309875488e-03 + 0 -1 718 -8.5048296023160219e-04 - -3.6661344766616821e-01 3.4494820982217789e-02 + -3.2108953595161438e-01 5.7150222361087799e-02 <_> - 0 -1 570 2.1571468096226454e-03 + 0 -1 511 2.0031477324664593e-03 - -8.9639738202095032e-02 1.5742646157741547e-01 + -7.5618073344230652e-02 2.3024985194206238e-01 <_> - 0 -1 565 1.8860616255551577e-03 + 0 -1 505 -3.9609652012586594e-03 - -8.5441410541534424e-02 1.7696820199489594e-01 + -4.3856775760650635e-01 3.7756573408842087e-02 <_> - 0 -1 669 1.0152467293664813e-03 + 0 -1 311 5.9846425428986549e-03 - 3.8969900459051132e-02 -3.7170857191085815e-01 + 3.5378426313400269e-02 -4.7760033607482910e-01 <_> - 0 -1 775 -7.2436146438121796e-03 + 0 -1 83 2.0205255597829819e-02 - 1.7777322232723236e-01 -8.3921253681182861e-02 + -8.0130979418754578e-02 2.2919151186943054e-01 <_> - 0 -1 860 -3.7075001746416092e-03 + 0 -1 927 -2.7492402587085962e-03 - 1.8386960029602051e-01 -9.2291206121444702e-02 + 2.1395626664161682e-01 -7.6452419161796570e-02 <_> - 0 -1 607 -1.4369469135999680e-03 + 0 -1 506 -8.3101191557943821e-04 - -2.7023202180862427e-01 5.5822439491748810e-02 + 1.6961804032325745e-01 -9.9106967449188232e-02 <_> - 0 -1 926 -1.7798715271055698e-03 + 0 -1 604 -1.8657972104847431e-03 - 1.4900380373001099e-01 -9.8068036139011383e-02 + -3.8131290674209595e-01 4.6056091785430908e-02 <_> - 0 -1 558 1.9487005192786455e-03 + 0 -1 74 2.0824437960982323e-03 - -7.6331101357936859e-02 1.8935331702232361e-01 + 6.4966239035129547e-02 -2.3824627697467804e-01 <_> - 0 -1 871 2.8823004104197025e-03 + 0 -1 70 -4.4267112389206886e-03 - 4.2902354151010513e-02 -3.5214039683341980e-01 + -3.5809823870658875e-01 4.6749643981456757e-02 <_> - 0 -1 378 -5.6123267859220505e-03 + 0 -1 211 1.3552411692216992e-03 - -4.7632521390914917e-01 2.6048270985484123e-02 + -1.2307690829038620e-01 1.3934792578220367e-01 <_> - 0 -1 301 1.6383089125156403e-02 + 0 -1 213 -4.4114869087934494e-03 - -8.9606925845146179e-02 1.4743074774742126e-01 + 2.6617470383644104e-01 -7.4502207338809967e-02 <_> - 0 -1 44 3.4455281496047974e-01 + 0 -1 432 5.2309304010123014e-04 - -2.0530648529529572e-02 7.2817444801330566e-01 + -1.0876630991697311e-01 1.5687976777553558e-01 <_> - 0 -1 448 2.7680541388690472e-03 + 0 -1 976 6.4505764748901129e-04 - -3.8598377257585526e-02 3.5294523835182190e-01 + -8.0842182040214539e-02 2.0263716578483582e-01 <_> - 0 -1 480 3.8404709193855524e-03 + 0 -1 975 2.0405012182891369e-03 - -8.0346472561359406e-02 1.8624457716941833e-01 + -6.2390543520450592e-02 3.3067914843559265e-01 <_> - 0 -1 11 -4.3602049350738525e-02 + 0 -1 888 1.9838459789752960e-02 - 2.4986675381660461e-01 -7.1408227086067200e-02 + 2.3488542065024376e-02 -8.1695795059204102e-01 <_> - 0 -1 2 -3.6010099574923515e-03 + 0 -1 953 2.3998366668820381e-03 - 1.6942474246025085e-01 -1.0419391095638275e-01 + 4.1017178446054459e-02 -3.7197592854499817e-01 <_> - 0 -1 320 -6.1740418896079063e-03 + 0 -1 664 -1.1092903092503548e-02 - -4.6275594830513000e-01 3.1903993338346481e-02 + -5.5750596523284912e-01 2.9520254582166672e-02 <_> - 0 -1 898 3.4251257311552763e-03 + 0 -1 981 1.4876715838909149e-02 - 2.5748182088136673e-02 -4.8371604084968567e-01 + -6.5797492861747742e-02 2.5957426428794861e-01 <_> - 0 -1 841 -3.9031119085848331e-03 + 0 -1 621 -3.0385032296180725e-02 - 1.6738632321357727e-01 -8.4549814462661743e-02 + 2.2640630602836609e-01 -7.6991938054561615e-02 <_> - 0 -1 935 -7.3322677053511143e-04 + 0 -1 666 1.2216348201036453e-02 - 2.1091395616531372e-01 -7.2518013417720795e-02 + -7.0106968283653259e-02 2.4013392627239227e-01 + + <_> + 94 + -1.2798616886138916e+00 + <_> - 0 -1 932 2.7150693349540234e-03 + 0 -1 801 -3.8322431501001120e-03 - -5.7143334299325943e-02 2.7224695682525635e-01 + 4.8065602779388428e-01 -4.9388073384761810e-02 <_> - 0 -1 937 1.7057932913303375e-02 + 0 -1 966 2.5449637323617935e-03 - -6.3262723386287689e-02 2.4493633210659027e-01 + -1.7564620077610016e-01 2.5865191221237183e-01 <_> - 0 -1 968 2.2439109161496162e-03 + 0 -1 448 -5.4743299260735512e-03 - 6.1605937778949738e-02 -2.5090345740318298e-01 + 4.9321442842483521e-01 -7.0596724748611450e-02 <_> - 0 -1 122 9.2767914757132530e-03 + 0 -1 294 1.5188493765890598e-02 - 3.9061944931745529e-02 -3.7177914381027222e-01 + -1.8555639684200287e-01 1.5278494358062744e-01 <_> - 0 -1 930 -1.3303438900038600e-03 + 0 -1 954 7.5815798481926322e-04 - 2.2685268521308899e-01 -6.3722826540470123e-02 + -1.5043407678604126e-01 1.8612807989120483e-01 <_> - 0 -1 818 -2.8938084840774536e-02 + 0 -1 963 -3.4232349134981632e-03 - -6.6085141897201538e-01 2.1666957065463066e-02 + -4.5882478356361389e-01 4.3279532343149185e-02 <_> - 0 -1 744 -5.0926357507705688e-03 + 0 -1 842 2.4103666655719280e-03 - 1.7695400118827820e-01 -7.9500846564769745e-02 + -8.4217190742492676e-02 2.6687353849411011e-01 <_> - 0 -1 749 5.3870421834290028e-03 + 0 -1 340 -2.3144368082284927e-02 - -5.5856045335531235e-02 2.7346748113632202e-01 + 2.9155749082565308e-01 -9.9449791014194489e-02 <_> - 0 -1 524 -8.0796808470040560e-04 + 0 -1 419 -4.2331898584961891e-03 - -2.2386504709720612e-01 6.8852454423904419e-02 + -3.7696760892868042e-01 8.0511704087257385e-02 <_> - 0 -1 591 3.9214566349983215e-03 + 0 -1 282 4.9294121563434601e-03 - 2.2929171100258827e-02 -5.9076148271560669e-01 + -1.3016121089458466e-01 1.8470372259616852e-01 <_> - 0 -1 691 -6.5161995589733124e-03 + 0 -1 481 -2.7466980100143701e-05 - -5.5175542831420898e-01 2.0790172740817070e-02 + 1.4074377715587616e-01 -1.7928679287433624e-01 <_> - 0 -1 295 -1.6703434521332383e-03 + 0 -1 724 2.2430901881307364e-03 - -3.5234490036964417e-01 3.4917417913675308e-02 + -1.4674974977970123e-01 1.5197925269603729e-01 <_> - 0 -1 126 -3.2307719811797142e-03 + 0 -1 849 7.5493026524782181e-03 - 1.5907490253448486e-01 -7.8541077673435211e-02 + 2.4894557893276215e-02 -6.5740859508514404e-01 <_> - 0 -1 123 5.0736088305711746e-03 + 0 -1 245 -3.3066330943256617e-03 - -7.3796175420284271e-02 1.7231710255146027e-01 + 1.8501703441143036e-01 -1.1837758123874664e-01 <_> - 0 -1 68 -1.9738268107175827e-02 + 0 -1 345 6.9540860131382942e-03 - 2.4731338024139404e-01 -5.3791344165802002e-02 + -7.3770649731159210e-02 2.9017251729965210e-01 <_> - 0 -1 404 6.9891922175884247e-03 + 0 -1 790 -8.6210696026682854e-03 - -6.1806734651327133e-02 2.1923109889030457e-01 + 2.0990766584873199e-01 -1.0644201189279556e-01 <_> - 0 -1 851 -2.6465239934623241e-03 + 0 -1 978 -6.0504255816340446e-04 - 2.8577965497970581e-01 -6.6506840288639069e-02 + 2.2373022139072418e-01 -9.6104651689529419e-02 <_> - 0 -1 734 3.3399839885532856e-03 + 0 -1 46 -4.5433510094881058e-03 - 3.4735739231109619e-02 -3.9448723196983337e-01 + -5.4173427820205688e-01 4.7511249780654907e-02 + <_> + + 0 -1 694 -2.2248399909585714e-03 + + -4.6854707598686218e-01 3.8701556622982025e-02 + <_> + + 0 -1 10 -5.3389102220535278e-02 + + 2.9293462634086609e-01 -7.2517670691013336e-02 + <_> + + 0 -1 13 4.6098522841930389e-02 + + -1.0042577981948853e-01 2.3779328167438507e-01 + <_> + + 0 -1 243 7.7845109626650810e-03 + + 3.7205196917057037e-02 -4.9194374680519104e-01 + <_> + + 0 -1 182 6.0175172984600067e-03 + + 4.4034618884325027e-02 -4.3780878186225891e-01 + <_> + + 0 -1 876 4.8966710455715656e-03 + + -1.0375351458787918e-01 1.9480220973491669e-01 + <_> + + 0 -1 494 -3.1284091528505087e-03 + + 2.3669239878654480e-01 -9.6020378172397614e-02 + <_> + + 0 -1 190 -1.3859109021723270e-03 + + 2.8487151861190796e-01 -7.2190955281257629e-02 + <_> + + 0 -1 191 2.6260318700224161e-03 + + -8.5511997342109680e-02 3.0152606964111328e-01 + <_> + + 0 -1 65 1.7782470583915710e-01 + + -6.4100205898284912e-02 3.3825826644897461e-01 + <_> + + 0 -1 50 1.7538113519549370e-02 + + 5.9994459152221680e-02 -3.5529783368110657e-01 + <_> + + 0 -1 946 -3.2135979272425175e-03 + + 1.3668337464332581e-01 -1.3979049026966095e-01 + <_> + + 0 -1 461 6.1371903866529465e-03 + + -6.2439329922199249e-02 3.0614212155342102e-01 + <_> + + 0 -1 467 -4.6563488431274891e-03 + + -4.3073609471321106e-01 4.9068968743085861e-02 + <_> + + 0 -1 668 -4.0680947713553905e-03 + + -4.6810126304626465e-01 3.7441805005073547e-02 + <_> + + 0 -1 696 1.4199400320649147e-03 + + -8.7975829839706421e-02 2.1591611206531525e-01 + <_> + + 0 -1 851 3.5254685208201408e-03 + + 4.6650484204292297e-02 -4.3687531352043152e-01 + <_> + + 0 -1 487 1.8623860552906990e-02 + + -7.6216101646423340e-02 2.3812168836593628e-01 + <_> + + 0 -1 314 -2.6926528662443161e-02 + + -6.7117422819137573e-01 2.9464269056916237e-02 + <_> + + 0 -1 632 2.2593191824853420e-03 + + 2.8521748259663582e-02 -5.4787307977676392e-01 + <_> + + 0 -1 919 1.7519816174171865e-04 + + -1.6111046075820923e-01 1.0367503762245178e-01 + <_> + + 0 -1 493 1.0614154860377312e-02 + + 4.5461904257535934e-02 -3.8087964057922363e-01 + <_> + + 0 -1 20 -4.4702589511871338e-03 + + 1.4304992556571960e-01 -1.3372300565242767e-01 + <_> + + 0 -1 557 6.2367701902985573e-03 + + -7.7783808112144470e-02 2.1545551717281342e-01 + <_> + + 0 -1 76 4.6502514742314816e-03 + + 4.6132039278745651e-02 -3.7130251526832581e-01 + <_> + + 0 -1 544 -4.3315230868756771e-03 + + -4.1549521684646606e-01 3.8484618067741394e-02 + <_> + + 0 -1 764 -1.6567837446928024e-03 + + -3.4637498855590820e-01 4.6623144298791885e-02 + <_> + + 0 -1 415 4.7653233632445335e-03 + + -5.0808548927307129e-02 3.4609997272491455e-01 + <_> + + 0 -1 413 -3.2579647377133369e-03 + + 2.6948198676109314e-01 -8.5287831723690033e-02 + <_> + + 0 -1 614 2.3307730443775654e-03 + + -7.4774339795112610e-02 2.3053503036499023e-01 + <_> + + 0 -1 176 -2.7928136289119720e-02 + + 1.9429244101047516e-01 -8.7820984423160553e-02 + <_> + + 0 -1 366 -9.8205050453543663e-03 + + -5.9664642810821533e-01 3.1795132905244827e-02 + <_> + + 0 -1 767 4.9811266362667084e-03 + + -1.1911241710186005e-01 1.5268225967884064e-01 + <_> + + 0 -1 508 -2.4869772605597973e-03 + + -3.8041505217552185e-01 4.4293139129877090e-02 + <_> + + 0 -1 780 5.4475376382470131e-03 + + -4.6219147741794586e-02 3.9531415700912476e-01 + <_> + + 0 -1 277 -2.1438062191009521e-02 + + -5.2191144227981567e-01 3.4259662032127380e-02 + <_> + + 0 -1 566 -4.1901203803718090e-03 + + -5.2377271652221680e-01 2.8632357716560364e-02 + <_> + + 0 -1 262 -4.7237933613359928e-03 + + 1.8694585561752319e-01 -8.3333678543567657e-02 + <_> + + 0 -1 845 1.2320578098297119e-03 + + -9.6744544804096222e-02 1.8287587165832520e-01 + <_> + + 0 -1 617 2.0271677523851395e-02 + + -6.4628154039382935e-02 2.7641129493713379e-01 + <_> + + 0 -1 375 -1.0729704797267914e-01 + + 4.3015307188034058e-01 -3.8674801588058472e-02 + <_> + + 0 -1 166 -4.0820333361625671e-01 + + 5.0520670413970947e-01 -3.0450601130723953e-02 + <_> + + 0 -1 305 4.4355981051921844e-02 + + -9.2204704880714417e-02 1.7342080175876617e-01 + <_> + + 0 -1 879 -1.0999260703101754e-03 + + 2.0996508002281189e-01 -7.7222190797328949e-02 + <_> + + 0 -1 325 -3.2928451895713806e-02 + + 2.7598264813423157e-01 -6.4115919172763824e-02 + <_> + + 0 -1 52 2.3981094360351562e-02 + + 2.5229524821043015e-02 -6.9560426473617554e-01 + <_> + + 0 -1 961 4.1703339666128159e-03 + + 2.9712976887822151e-02 -4.8132696747779846e-01 + <_> + + 0 -1 776 -1.4920771354809403e-03 + + 1.6165184974670410e-01 -9.6420668065547943e-02 + <_> + + 0 -1 652 1.8172110430896282e-03 + + 4.2247310280799866e-02 -3.5703054070472717e-01 + <_> + + 0 -1 739 -2.5937356986105442e-03 + + 2.2665317356586456e-01 -6.9081544876098633e-02 + <_> + + 0 -1 706 -2.4995308369398117e-02 + + -6.3855916261672974e-01 2.8458235785365105e-02 + <_> + + 0 -1 909 1.2001263909041882e-02 + + 1.4999576844274998e-02 -7.8175085783004761e-01 + <_> + + 0 -1 640 2.2153530735522509e-03 + + -8.8839285075664520e-02 1.8819671869277954e-01 + <_> + + 0 -1 179 2.7237991162110120e-05 + + -1.4949426054954529e-01 9.8739065229892731e-02 + <_> + + 0 -1 91 -2.6735704392194748e-02 + + -4.5522138476371765e-01 3.2516691833734512e-02 + <_> + + 0 -1 644 -2.3417242337018251e-03 + + -3.1453001499176025e-01 4.7598775476217270e-02 + <_> + + 0 -1 72 4.7831580042839050e-02 + + 2.1954061463475227e-02 -6.1162966489791870e-01 + <_> + + 0 -1 160 -5.7228151708841324e-03 + + -6.3381904363632202e-01 2.0299639552831650e-02 + <_> + + 0 -1 163 3.4780064597725868e-03 + + 3.1021401286125183e-02 -4.2342424392700195e-01 + <_> + + 0 -1 385 -5.4140854626893997e-03 + + 4.7739461064338684e-01 -3.4031655639410019e-02 + <_> + + 0 -1 383 1.5283382963389158e-03 + + -9.6935935318470001e-02 1.9429819285869598e-01 + <_> + + 0 -1 428 -8.6789112538099289e-03 + + 2.4826894700527191e-01 -6.0082063078880310e-02 + <_> + + 0 -1 901 3.0333681497722864e-03 + + -7.4087560176849365e-02 2.6165533065795898e-01 + <_> + + 0 -1 684 6.5222466364502907e-03 + + 3.0176062136888504e-02 -5.5570882558822632e-01 + <_> + + 0 -1 902 5.9719551354646683e-03 + + 2.3057831451296806e-02 -5.7078248262405396e-01 + <_> + + 0 -1 155 -1.3977952767163515e-03 + + 1.5342144668102264e-01 -9.8401337862014771e-02 + <_> + + 0 -1 897 5.9919534251093864e-03 + + -3.9796624332666397e-02 3.5881185531616211e-01 + <_> + + 0 -1 354 2.6286500506103039e-03 + + -9.3140766024589539e-02 1.6334943473339081e-01 + <_> + + 0 -1 296 -4.4777179136872292e-03 + + -4.8081240057945251e-01 3.2935630530118942e-02 + <_> + + 0 -1 333 5.2724601700901985e-03 + + 3.0787551775574684e-02 -4.5133110880851746e-01 + <_> + + 0 -1 1049 -3.2540475949645042e-03 + + -4.7695344686508179e-01 2.8554188087582588e-02 + <_> + + 0 -1 736 1.8083681166172028e-01 + + 2.7366345748305321e-02 -4.9431446194648743e-01 + <_> + + 0 -1 431 2.7535988483577967e-03 + + 1.9968675449490547e-02 -6.4471620321273804e-01 + <_> + + 0 -1 15 -1.4123708009719849e-02 + + -5.2748751640319824e-01 2.4596616625785828e-02 + <_> + + 0 -1 421 -3.2076485455036163e-02 + + -7.2171974182128906e-01 1.6940405592322350e-02 + <_> + + 0 -1 434 -3.2569766044616699e-02 + + 2.2400286793708801e-01 -6.3403561711311340e-02 + + <_> + 100 + -1.2990239858627319e+00 + + <_> + + 0 -1 728 1.1235726065933704e-02 + + -1.2534695863723755e-01 3.9147180318832397e-01 + <_> + + 0 -1 922 5.0947451964020729e-03 + + -1.2666413187980652e-01 4.0618515014648438e-01 + <_> + + 0 -1 891 -1.5323986299335957e-03 + + 2.8940162062644958e-01 -1.4350101351737976e-01 + <_> + + 0 -1 284 3.7766513414680958e-03 + + -1.9189934432506561e-01 1.4756591618061066e-01 + <_> + + 0 -1 514 4.8757870681583881e-03 + + -1.2341982126235962e-01 2.3298588395118713e-01 + <_> + + 0 -1 344 3.1278211623430252e-02 + + -7.6286941766738892e-02 3.4027433395385742e-01 + <_> + + 0 -1 63 6.3753505237400532e-03 + + 7.3992513120174408e-02 -3.2609656453132629e-01 + <_> + + 0 -1 936 -9.8742637783288956e-04 + + 2.4873960018157959e-01 -9.0153135359287262e-02 + <_> + + 0 -1 217 -3.0144110321998596e-02 + + -5.1088541746139526e-01 5.0071869045495987e-02 + <_> + + 0 -1 268 4.7727730125188828e-03 + + 5.1353454589843750e-02 -4.1142973303794861e-01 + <_> + + 0 -1 420 6.4554966986179352e-02 + + 4.5133572071790695e-02 -4.8264691233634949e-01 + <_> + + 0 -1 744 8.0438675358891487e-03 + + -6.3803412020206451e-02 3.0405151844024658e-01 + <_> + + 0 -1 1051 1.0576066561043262e-03 + + 4.9984093755483627e-02 -3.3949175477027893e-01 + <_> + + 0 -1 938 6.8522170186042786e-03 + + 3.5091523081064224e-02 -6.7847234010696411e-01 + <_> + + 0 -1 860 -1.7977621406316757e-02 + + -3.7503832578659058e-01 4.0370170027017593e-02 + <_> + + 0 -1 748 -2.9955487698316574e-02 + + -4.2023807764053345e-01 4.2222321033477783e-02 + <_> + + 0 -1 14 2.0934976637363434e-02 + + 4.3809924274682999e-02 -4.1159108281135559e-01 + <_> + + 0 -1 499 -1.0348223149776459e-03 + + 1.7594149708747864e-01 -1.0171056538820267e-01 + <_> + + 0 -1 15 1.1026043444871902e-02 + + 3.7518307566642761e-02 -4.9795153737068176e-01 + <_> + + 0 -1 201 4.1434396989643574e-03 + + -7.7400334179401398e-02 2.3505100607872009e-01 + <_> + + 0 -1 423 -1.4838734641671181e-03 + + 2.9909220337867737e-01 -9.2648021876811981e-02 + <_> + + 0 -1 1025 4.0641101077198982e-03 + + 3.8187902420759201e-02 -5.9566622972488403e-01 + <_> + + 0 -1 108 -2.6055248454213142e-03 + + 1.4647382497787476e-01 -1.1769902706146240e-01 + <_> + + 0 -1 834 -1.8873009830713272e-02 + + 2.0791313052177429e-01 -9.1127894818782806e-02 + <_> + + 0 -1 960 1.0428125038743019e-02 + + 4.3083548545837402e-02 -4.1407048702239990e-01 + <_> + + 0 -1 460 1.9560819491744041e-03 + + -6.5898597240447998e-02 2.6488196849822998e-01 + <_> + + 0 -1 402 6.1143590137362480e-03 + + 4.7718580812215805e-02 -4.3339842557907104e-01 + <_> + + 0 -1 411 3.9817169308662415e-03 + + 2.8663935139775276e-02 -5.4472506046295166e-01 + <_> + + 0 -1 497 -9.0858177281916142e-04 + + 1.2656490504741669e-01 -1.3804104924201965e-01 + <_> + + 0 -1 548 -5.1833119243383408e-02 + + 2.9838389158248901e-01 -6.4876683056354523e-02 + <_> + + 0 -1 550 -6.1461031436920166e-02 + + 2.2751982510089874e-01 -7.7075794339179993e-02 + <_> + + 0 -1 771 -3.8890805444680154e-04 + + 1.4823918044567108e-01 -1.2443733215332031e-01 + <_> + + 0 -1 819 6.3632195815443993e-03 + + 3.3928975462913513e-02 -5.5825293064117432e-01 + <_> + + 0 -1 929 2.3877150379121304e-03 + + -6.0555700212717056e-02 2.9875907301902771e-01 + <_> + + 0 -1 718 2.1584378555417061e-03 + + 2.6707226410508156e-02 -6.5327596664428711e-01 + <_> + + 0 -1 972 1.3073299778625369e-03 + + -6.5057143568992615e-02 2.8509995341300964e-01 + <_> + + 0 -1 1023 2.7173646230949089e-05 + + -1.4736446738243103e-01 1.1435943096876144e-01 + <_> + + 0 -1 630 2.5558518245816231e-03 + + 2.2957315668463707e-02 -6.1825275421142578e-01 + <_> + + 0 -1 435 4.4789682142436504e-03 + + 3.6877695471048355e-02 -4.1827708482742310e-01 + <_> + + 0 -1 335 -4.0298998355865479e-02 + + -6.8164646625518799e-01 2.1755648776888847e-02 + <_> + + 0 -1 782 -3.2729938626289368e-02 + + -5.4164266586303711e-01 2.6013873517513275e-02 + <_> + + 0 -1 1011 -1.6982981469482183e-03 + + 3.5175332427024841e-01 -4.7216285020112991e-02 + <_> + + 0 -1 331 3.6859638057649136e-03 + + 4.9838334321975708e-02 -3.0565607547760010e-01 + <_> + + 0 -1 235 1.8905990291386843e-03 + + 2.3341298103332520e-02 -6.6700172424316406e-01 + <_> + + 0 -1 714 4.9954187124967575e-03 + + 2.5513354688882828e-02 -5.4635345935821533e-01 + <_> + + 0 -1 336 -5.5998284369707108e-03 + + 2.9532432556152344e-01 -5.9350244700908661e-02 + <_> + + 0 -1 1008 -1.0907559189945459e-03 + + 1.8265166878700256e-01 -9.8137028515338898e-02 + <_> + + 0 -1 975 -7.4323470471426845e-04 + + 1.9020494818687439e-01 -8.7386451661586761e-02 + <_> + + 0 -1 914 2.7787161525338888e-03 + + 3.2241951674222946e-02 -4.8055323958396912e-01 + <_> + + 0 -1 153 2.4344769772142172e-03 + + 4.6477138996124268e-02 -2.9923307895660400e-01 + <_> + + 0 -1 293 2.8132982552051544e-03 + + -9.0026579797267914e-02 1.6738441586494446e-01 + <_> + + 0 -1 73 3.2191604375839233e-02 + + -6.3697919249534607e-02 2.8380525112152100e-01 + <_> + + 0 -1 656 -1.8642821814864874e-03 + + 2.0616722106933594e-01 -7.4722714722156525e-02 + <_> + + 0 -1 657 4.0091956034302711e-03 + + -7.1015752851963043e-02 2.5589218735694885e-01 + <_> + + 0 -1 150 -5.1108514890074730e-03 + + -4.8940917849540710e-01 3.4555420279502869e-02 + <_> + + 0 -1 600 -1.9523575901985168e-02 + + 3.1921747326850891e-01 -5.1439035683870316e-02 + <_> + + 0 -1 298 -1.4431261457502842e-02 + + 1.4213174581527710e-01 -1.1113181710243225e-01 + <_> + + 0 -1 732 4.5302580110728741e-04 + + -1.0926237702369690e-01 1.4363190531730652e-01 + <_> + + 0 -1 78 -5.4108840413391590e-03 + + -4.6926099061965942e-01 3.1095381826162338e-02 + <_> + + 0 -1 259 1.6963672824203968e-03 + + -6.7337587475776672e-02 2.2115154564380646e-01 + <_> + + 0 -1 190 1.8719944637268782e-03 + + -5.8433420956134796e-02 2.7830049395561218e-01 + <_> + + 0 -1 1014 -8.3780642598867416e-03 + + -4.6290600299835205e-01 3.3701810985803604e-02 + <_> + + 0 -1 510 1.0720299184322357e-01 + + 2.6600774377584457e-02 -5.0957643985748291e-01 + <_> + + 0 -1 670 -1.5523867914453149e-03 + + -5.7974040508270264e-01 2.2188233211636543e-02 + <_> + + 0 -1 649 -1.0537400841712952e-02 + + -4.3835061788558960e-01 2.9434528201818466e-02 + <_> + + 0 -1 1038 3.1337797641754150e-02 + + 2.0445786416530609e-02 -6.3010692596435547e-01 + <_> + + 0 -1 1004 -5.1124744117259979e-02 + + -6.7282766103744507e-01 1.8230145797133446e-02 + <_> + + 0 -1 362 -6.0091790510341525e-04 + + 2.0237097144126892e-01 -7.2557553648948669e-02 + <_> + + 0 -1 409 1.6933252336457372e-03 + + -5.9000160545110703e-02 2.4010565876960754e-01 + <_> + + 0 -1 18 5.7134744711220264e-03 + + 2.9386352747678757e-02 -5.1309728622436523e-01 + <_> + + 0 -1 429 -9.6922749653458595e-03 + + -5.4907989501953125e-01 2.3704739287495613e-02 + <_> + + 0 -1 308 -1.2504560872912407e-02 + + -6.1863696575164795e-01 1.9876839593052864e-02 + <_> + + 0 -1 382 -9.1812955215573311e-03 + + -4.7697570919990540e-01 2.5203671306371689e-02 + <_> + + 0 -1 570 2.8069302439689636e-02 + + -5.5565606802701950e-02 2.5318285822868347e-01 + <_> + + 0 -1 573 4.6324366703629494e-03 + + 2.5273589417338371e-02 -5.9603255987167358e-01 + <_> + + 0 -1 784 2.9409723356366158e-03 + + -5.1576137542724609e-02 2.9322555661201477e-01 + <_> + + 0 -1 159 -1.6009721904993057e-02 + + 2.9389014840126038e-01 -4.7874812036752701e-02 + <_> + + 0 -1 355 -2.0468614995479584e-02 + + 1.4383009076118469e-01 -1.0160042345523834e-01 + <_> + + 0 -1 868 2.3338340222835541e-02 + + -5.7301126420497894e-02 2.9121819138526917e-01 + <_> + + 0 -1 921 -2.1875634789466858e-02 + + -6.4106851816177368e-01 2.4203805252909660e-02 + <_> + + 0 -1 427 1.1228370480239391e-02 + + -5.2143514156341553e-02 2.8465506434440613e-01 + <_> + + 0 -1 197 -4.3659657239913940e-03 + + -6.0558545589447021e-01 2.5440702214837074e-02 + <_> + + 0 -1 824 1.1577639961615205e-03 + + -8.9793093502521515e-02 1.6500258445739746e-01 + <_> + + 0 -1 781 1.1090341955423355e-02 + + 2.4472476914525032e-02 -6.1380225419998169e-01 + <_> + + 0 -1 1015 4.7660744749009609e-03 + + 4.1726417839527130e-02 -3.2548862695693970e-01 + <_> + + 0 -1 864 2.4865168597898446e-05 + + -1.2436556816101074e-01 1.1702288687229156e-01 + <_> + + 0 -1 823 -7.6379198580980301e-03 + + -4.9008071422576904e-01 2.9381709173321724e-02 + <_> + + 0 -1 445 -3.2750256359577179e-03 + + 1.7950019240379333e-01 -8.0592408776283264e-02 + <_> + + 0 -1 448 1.3944536913186312e-03 + + -8.0001771450042725e-02 2.2785140573978424e-01 + <_> + + 0 -1 444 1.9776031840592623e-03 + + 3.4109916538000107e-02 -4.8504865169525146e-01 + <_> + + 0 -1 39 -3.9329148828983307e-02 + + -6.8790251016616821e-01 1.7370922490954399e-02 + <_> + + 0 -1 645 -2.8447234071791172e-03 + + 2.3028372228145599e-01 -6.6618286073207855e-02 + <_> + + 0 -1 232 3.2375190407037735e-02 + + -7.5743824243545532e-02 1.7864570021629333e-01 + <_> + + 0 -1 5 5.1314428448677063e-02 + + -5.3142681717872620e-02 2.8643575310707092e-01 + <_> + + 0 -1 79 4.6999715268611908e-03 + + 3.5749543458223343e-02 -4.0437424182891846e-01 + <_> + + 0 -1 173 -2.0850417204201221e-03 + + -3.0815458297729492e-01 4.2763352394104004e-02 + <_> + + 0 -1 455 -9.1223767958581448e-04 + + 2.1245715022087097e-01 -6.7729450762271881e-02 + <_> + + 0 -1 690 -2.2479293693322688e-04 + + 1.3159312307834625e-01 -1.0141336172819138e-01 + <_> + + 0 -1 974 3.1234124675393105e-02 + + -8.9100256562232971e-02 1.5734429657459259e-01 + <_> + + 0 -1 465 -1.5079543227329850e-03 + + 3.2412421703338623e-01 -4.4387526810169220e-02 + + <_> + 100 + -1.2500010728836060e+00 + + <_> + + 0 -1 803 -5.5631361901760101e-03 + + 4.5343571901321411e-01 -5.2330773323774338e-02 + <_> + + 0 -1 426 4.1911248117685318e-03 + + -1.2266161292791367e-01 3.6830583214759827e-01 + <_> + + 0 -1 424 -1.8559540621936321e-03 + + 2.4044598639011383e-01 -1.5207393467426300e-01 + <_> + + 0 -1 532 -1.1846812441945076e-02 + + 2.7016878128051758e-01 -1.1934488266706467e-01 + <_> + + 0 -1 180 1.0401019826531410e-03 + + -2.3527304828166962e-01 9.5964968204498291e-02 + <_> + + 0 -1 462 9.3873767182230949e-03 + + -5.6923847645521164e-02 4.2236638069152832e-01 + <_> + + 0 -1 13 9.0843521058559418e-02 + + -6.3625380396842957e-02 3.8295668363571167e-01 + <_> + + 0 -1 439 -1.6221515834331512e-03 + + 1.8148291110992432e-01 -1.3424767553806305e-01 + <_> + + 0 -1 875 -1.8008962273597717e-02 + + 2.7346464991569519e-01 -7.6283894479274750e-02 + <_> + + 0 -1 278 8.6509017273783684e-03 + + 5.8148156851530075e-02 -5.2620184421539307e-01 + <_> + + 0 -1 726 2.8817038983106613e-03 + + 2.6940831914544106e-02 -4.7911167144775391e-01 + <_> + + 0 -1 263 -6.1017833650112152e-03 + + 1.7878855764865875e-01 -1.2378337979316711e-01 + <_> + + 0 -1 403 -5.9294269885867834e-04 + + -2.7179723978042603e-01 8.0951526761054993e-02 + <_> + + 0 -1 996 3.1696190126240253e-04 + + -1.7311862111091614e-01 1.0296358913183212e-01 + <_> + + 0 -1 519 6.6280784085392952e-03 + + -5.8870136737823486e-02 2.9477587342262268e-01 + <_> + + 0 -1 916 -4.5112203806638718e-03 + + -5.9672296047210693e-01 2.7053238824009895e-02 + <_> + + 0 -1 679 -4.3381296098232269e-02 + + -4.2040801048278809e-01 4.0890187025070190e-02 + <_> + + 0 -1 813 2.0323593635112047e-03 + + 5.5178079754114151e-02 -3.0439695715904236e-01 + <_> + + 0 -1 973 1.8127080984413624e-03 + + -8.2048252224922180e-02 2.1907366812229156e-01 + <_> + + 0 -1 359 -6.6424394026398659e-03 + + -4.7840338945388794e-01 4.4878169894218445e-02 + <_> + + 0 -1 903 -8.5755460895597935e-04 + + 1.3301849365234375e-01 -1.2699788808822632e-01 + <_> + + 0 -1 904 3.4769098274409771e-03 + + -7.1578972041606903e-02 2.5448271632194519e-01 + <_> + + 0 -1 950 -1.8520625308156013e-03 + + 1.5127970278263092e-01 -1.2349219620227814e-01 + <_> + + 0 -1 777 5.4582338780164719e-03 + + 3.5001352429389954e-02 -4.8021456599235535e-01 + <_> + + 0 -1 894 -6.4206691458821297e-03 + + -5.6509351730346680e-01 2.6883032172918320e-02 + <_> + + 0 -1 895 8.2498416304588318e-03 + + 4.3442543596029282e-02 -3.7965279817581177e-01 + <_> + + 0 -1 825 3.0813394114375114e-03 + + -5.6544844061136246e-02 3.2101437449455261e-01 + <_> + + 0 -1 865 2.8121876530349255e-03 + + -7.1444042026996613e-02 2.8035575151443481e-01 + <_> + + 0 -1 418 -1.1791236698627472e-02 + + 2.0067863166332245e-01 -1.0047248005867004e-01 + <_> + + 0 -1 476 1.4931729529052973e-03 + + -6.6428750753402710e-02 2.6187655329704285e-01 + <_> + + 0 -1 364 -2.8772680088877678e-03 + + -4.5838123559951782e-01 4.2477916926145554e-02 + <_> + + 0 -1 592 -4.5857336372137070e-03 + + 1.2718579173088074e-01 -1.3642288744449615e-01 + <_> + + 0 -1 585 -1.3770985417068005e-02 + + -6.4000308513641357e-01 2.7297915890812874e-02 + <_> + + 0 -1 746 -3.6472730338573456e-02 + + -5.1465278863906860e-01 3.1265191733837128e-02 + <_> + + 0 -1 378 1.0626764036715031e-02 + + 2.4199636653065681e-02 -6.3441967964172363e-01 + <_> + + 0 -1 509 -3.6817211657762527e-03 + + -4.4575414061546326e-01 3.1119547784328461e-02 + <_> + + 0 -1 856 -3.4752404317259789e-03 + + 1.4008119702339172e-01 -1.0539831966161728e-01 + <_> + + 0 -1 815 -4.7973562031984329e-03 + + 2.8762820363044739e-01 -6.0662355273962021e-02 + <_> + + 0 -1 773 6.4153699204325676e-03 + + -1.1230263859033585e-01 1.4087037742137909e-01 + <_> + + 0 -1 814 -1.0156400967389345e-03 + + -3.3441004157066345e-01 4.3477565050125122e-02 + <_> + + 0 -1 968 3.3057793043553829e-03 + + 1.9609324634075165e-02 -7.0060092210769653e-01 + <_> + + 0 -1 100 -5.3275022655725479e-03 + + 2.4580952525138855e-01 -6.0118518769741058e-02 + <_> + + 0 -1 469 1.5886269975453615e-03 + + -7.7446170151233673e-02 1.9878011941909790e-01 + <_> + + 0 -1 520 4.7287968918681145e-03 + + 3.0098341405391693e-02 -5.0950014591217041e-01 + <_> + + 0 -1 741 -1.9788878853432834e-04 + + 1.5142950415611267e-01 -9.6688762307167053e-02 + <_> + + 0 -1 389 -4.9208370037376881e-03 + + -4.5343187451362610e-01 3.7627156823873520e-02 + <_> + + 0 -1 361 4.5094583183526993e-02 + + -8.5510566830635071e-02 1.7849470674991608e-01 + <_> + + 0 -1 944 1.4799998607486486e-03 + + -6.4638271927833557e-02 2.3496921360492706e-01 + <_> + + 0 -1 517 1.0061380267143250e-01 + + -3.0139762908220291e-02 4.9012109637260437e-01 + <_> + + 0 -1 688 -5.2844230085611343e-03 + + 1.7104546725749969e-01 -8.7710574269294739e-02 + <_> + + 0 -1 626 -8.3214940968900919e-04 + + -2.6654696464538574e-01 5.3875535726547241e-02 + <_> + + 0 -1 190 -8.8889291509985924e-04 + + 1.8824113905429840e-01 -8.0119885504245758e-02 + <_> + + 0 -1 191 2.2177316714078188e-03 + + -6.9703146815299988e-02 2.0391084253787994e-01 + <_> + + 0 -1 674 -1.1522162239998579e-03 + + -3.6508113145828247e-01 3.9048090577125549e-02 + <_> + + 0 -1 1036 -1.0836161673069000e-02 + + -5.8106678724288940e-01 2.1713526919484138e-02 + <_> + + 0 -1 82 -1.6731536388397217e-01 + + -4.7344669699668884e-01 2.6662701740860939e-02 + <_> + + 0 -1 515 -9.5267388969659805e-03 + + 2.7732986211776733e-01 -5.6512769311666489e-02 + <_> + + 0 -1 329 6.6450019367039204e-03 + + 2.9381312429904938e-02 -5.3565382957458496e-01 + <_> + + 0 -1 104 -2.1554589271545410e-02 + + -6.2839144468307495e-01 1.8782904371619225e-02 + <_> + + 0 -1 892 1.4288825332187116e-04 + + -1.2763719260692596e-01 1.0616952925920486e-01 + <_> + + 0 -1 319 1.8068919889628887e-03 + + 4.2757544666528702e-02 -3.2102146744728088e-01 + <_> + + 0 -1 979 1.2280542869120836e-03 + + -5.7478122413158417e-02 2.5948432087898254e-01 + <_> + + 0 -1 89 2.6250675320625305e-02 + + -9.5928788185119629e-02 1.4502045512199402e-01 + <_> + + 0 -1 336 1.8192850984632969e-03 + + -6.8028703331947327e-02 2.3167446255683899e-01 + <_> + + 0 -1 44 -4.8545510508120060e-03 + + -4.3374514579772949e-01 3.6196250468492508e-02 + <_> + + 0 -1 762 2.8766903560608625e-03 + + 3.8431353867053986e-02 -3.3900904655456543e-01 + <_> + + 0 -1 793 4.4511677697300911e-03 + + -4.8704307526350021e-02 2.9764902591705322e-01 + <_> + + 0 -1 545 -9.9098179489374161e-03 + + 2.5863200426101685e-01 -5.7418409734964371e-02 + <_> + + 0 -1 2 -2.6503708213567734e-03 + + 1.3571591675281525e-01 -1.1608450859785080e-01 + <_> + + 0 -1 1 -3.0543167144060135e-02 + + 2.8910955786705017e-01 -5.1689133048057556e-02 + <_> + + 0 -1 698 -2.6757145300507545e-02 + + 1.8446540832519531e-01 -7.7666454017162323e-02 + <_> + + 0 -1 131 -2.2985447198152542e-02 + + -3.5471677780151367e-01 4.1345477104187012e-02 + <_> + + 0 -1 536 9.5467511564493179e-03 + + -5.5719308555126190e-02 2.4589607119560242e-01 + <_> + + 0 -1 730 2.6181992143392563e-03 + + -1.0256808251142502e-01 1.3319683074951172e-01 + <_> + + 0 -1 1031 -3.5491142421960831e-02 + + -5.9519535303115845e-01 2.2935084998607635e-02 + <_> + + 0 -1 703 1.5474080573767424e-03 + + -8.4649838507175446e-02 1.6198579967021942e-01 + <_> + + 0 -1 861 -3.4878745209425688e-03 + + -5.0121647119522095e-01 2.6359066367149353e-02 + <_> + + 0 -1 601 3.6612942349165678e-03 + + -7.2178244590759277e-02 1.8415448069572449e-01 + <_> + + 0 -1 692 -2.1762652322649956e-03 + + 2.1102276444435120e-01 -6.4692504703998566e-02 + <_> + + 0 -1 66 -6.9864131510257721e-03 + + -4.3104550242424011e-01 3.3448409289121628e-02 + <_> + + 0 -1 64 4.7067347913980484e-03 + + 4.7681909054517746e-02 -3.1132212281227112e-01 + <_> + + 0 -1 1054 -7.0012239739298820e-03 + + -3.4665238857269287e-01 3.6263268440961838e-02 + <_> + + 0 -1 36 1.0144514963030815e-02 + + 3.3140499144792557e-02 -3.7149414420127869e-01 + <_> + + 0 -1 927 2.5893552228808403e-03 + + -5.6186988949775696e-02 2.3859155178070068e-01 + <_> + + 0 -1 877 -3.8091647438704967e-03 + + 1.8803173303604126e-01 -9.0667806565761566e-02 + <_> + + 0 -1 559 -2.5004068017005920e-01 + + -5.7437247037887573e-01 2.3015361279249191e-02 + <_> + + 0 -1 651 -8.5459719412028790e-04 + + -3.0019384622573853e-01 4.1898671537637711e-02 + <_> + + 0 -1 556 -1.5604835003614426e-02 + + -5.8520871400833130e-01 2.1410541608929634e-02 + <_> + + 0 -1 654 -1.9794562458992004e-01 + + -6.7963910102844238e-01 1.6488522291183472e-02 + <_> + + 0 -1 896 -1.9824346527457237e-03 + + 1.4493939280509949e-01 -8.7999224662780762e-02 + <_> + + 0 -1 582 -2.1158650517463684e-02 + + -6.4664304256439209e-01 2.4590896442532539e-02 + <_> + + 0 -1 837 -9.3553803162649274e-04 + + 1.8229192495346069e-01 -7.2682343423366547e-02 + <_> + + 0 -1 610 -1.1120189446955919e-03 + + 1.5188181400299072e-01 -8.6225852370262146e-02 + <_> + + 0 -1 316 1.1543033272027969e-01 + + -4.7091111540794373e-02 3.5574361681938171e-01 + <_> + + 0 -1 568 -5.2959467284381390e-03 + + 2.0496748387813568e-01 -6.1289250850677490e-02 + <_> + + 0 -1 310 -2.6194794103503227e-02 + + 1.7320305109024048e-01 -1.1094193905591965e-01 + <_> + + 0 -1 167 1.4183738268911839e-02 + + -9.7011148929595947e-02 1.4372280240058899e-01 + <_> + + 0 -1 1032 -3.6340979859232903e-03 + + -4.0951785445213318e-01 3.0991807579994202e-02 + <_> + + 0 -1 1028 1.4448106288909912e-02 + + -6.1627220362424850e-02 2.0916682481765747e-01 + <_> + + 0 -1 982 -1.1399465613067150e-02 + + 1.8926219642162323e-01 -8.7004892528057098e-02 + + <_> + 100 + -1.2953979969024658e+00 + + <_> + + 0 -1 725 1.6048721969127655e-02 + + -9.5187164843082428e-02 3.7635341286659241e-01 + <_> + + 0 -1 239 4.1785854846239090e-03 + + -1.4184002578258514e-01 3.1887301802635193e-01 + <_> + + 0 -1 526 -6.7659835331141949e-03 + + 3.7005490064620972e-01 -8.9318118989467621e-02 + <_> + + 0 -1 186 1.4478694647550583e-02 + + -1.3418816030025482e-01 2.8370034694671631e-01 + <_> + + 0 -1 411 -1.8653089646250010e-03 + + -3.5015934705734253e-01 6.9187328219413757e-02 + <_> + + 0 -1 901 3.7634610198438168e-03 + + -7.7612839639186859e-02 3.0384179949760437e-01 + <_> + + 0 -1 353 8.9913085103034973e-03 + + 6.0584690421819687e-02 -4.7271341085433960e-01 + <_> + + 0 -1 121 -3.0867164023220539e-03 + + 1.6870087385177612e-01 -1.3231597840785980e-01 + <_> + + 0 -1 388 -4.0246914140880108e-03 + + -4.1840493679046631e-01 6.4627721905708313e-02 + <_> + + 0 -1 896 4.8679644241929054e-03 + + -5.6233335286378860e-02 4.2156839370727539e-01 + <_> + + 0 -1 480 5.5472417734563351e-03 + + 3.7891130894422531e-02 -5.1408857107162476e-01 + <_> + + 0 -1 1003 6.5884483046829700e-04 + + -1.6457377374172211e-01 1.1204792559146881e-01 + <_> + + 0 -1 1050 -1.0980388615280390e-03 + + -3.3544427156448364e-01 4.6025454998016357e-02 + <_> + + 0 -1 583 -2.8328509069979191e-03 + + 2.3426958918571472e-01 -7.2758100926876068e-02 + <_> + + 0 -1 56 1.5504788607358932e-03 + + 6.2664858996868134e-02 -2.5632002949714661e-01 + <_> + + 0 -1 348 -6.2153179896995425e-04 + + 1.7485393583774567e-01 -9.9982917308807373e-02 + <_> + + 0 -1 675 -1.4540781266987324e-02 + + -4.4969236850738525e-01 3.7324137985706329e-02 + <_> + + 0 -1 792 -1.6624422278255224e-03 + + 1.4047256112098694e-01 -1.1892398446798325e-01 + <_> + + 0 -1 893 1.6246617306023836e-03 + + 6.1172962188720703e-02 -2.7449882030487061e-01 + <_> + + 0 -1 87 -1.1364535987377167e-01 + + -4.3175131082534790e-01 3.8861453533172607e-02 + <_> + + 0 -1 29 6.3355863094329834e-03 + + 4.3615639209747314e-02 -3.7530297040939331e-01 + <_> + + 0 -1 88 -7.9950205981731415e-03 + + -5.6157833337783813e-01 2.7148496359586716e-02 + <_> + + 0 -1 825 -6.0972268693149090e-03 + + 4.7499263286590576e-01 -3.5678520798683167e-02 + <_> + + 0 -1 933 1.3845593202859163e-03 + + -1.1575383692979813e-01 1.3405258953571320e-01 + <_> + + 0 -1 351 8.5432223975658417e-02 + + -5.6930482387542725e-02 3.1373351812362671e-01 + <_> + + 0 -1 661 -1.2029780447483063e-01 + + -4.7989824414253235e-01 3.8594469428062439e-02 + <_> + + 0 -1 829 -8.3766942843794823e-03 + + -2.0806340873241425e-01 7.6934777200222015e-02 + <_> + + 0 -1 673 -4.6590538695454597e-03 + + -5.0349289178848267e-01 3.0419014394283295e-02 + <_> + + 0 -1 453 -3.2761119306087494e-02 + + 3.2354715466499329e-01 -5.6276485323905945e-02 + <_> + + 0 -1 783 8.3009023219347000e-03 + + -8.3831317722797394e-02 2.3335608839988708e-01 + <_> + + 0 -1 848 5.7156109251081944e-03 + + -8.6484365165233612e-02 1.8363620340824127e-01 + <_> + + 0 -1 518 -1.0080671310424805e-01 + + 3.8774350285530090e-01 -4.0828518569469452e-02 + <_> + + 0 -1 14 -2.5552421808242798e-02 + + -5.0166463851928711e-01 3.8269419223070145e-02 + <_> + + 0 -1 23 -6.1748407781124115e-02 + + -3.5811841487884521e-01 4.6544160693883896e-02 + <_> + + 0 -1 702 -1.2269845232367516e-02 + + 2.0786920189857483e-01 -7.8518457710742950e-02 + <_> + + 0 -1 11 2.8048269450664520e-02 + + -5.6248739361763000e-02 2.8977242112159729e-01 + <_> + + 0 -1 523 -7.2269486263394356e-03 + + -7.2842431068420410e-01 2.3379294201731682e-02 + <_> + + 0 -1 952 4.7771912068128586e-03 + + 2.3226773366332054e-02 -5.6412339210510254e-01 + <_> + + 0 -1 276 2.8181755915284157e-03 + + -3.3893339335918427e-02 4.3989458680152893e-01 + <_> + + 0 -1 194 -8.4437360055744648e-04 + + 1.9623728096485138e-01 -7.8485630452632904e-02 + <_> + + 0 -1 407 -4.3037505820393562e-03 + + -3.6311796307563782e-01 4.0526941418647766e-02 + <_> + + 0 -1 105 4.9789976328611374e-03 + + 4.8658054322004318e-02 -3.1162264943122864e-01 + <_> + + 0 -1 1041 -5.0353109836578369e-03 + + -5.5396872758865356e-01 2.3420164361596107e-02 + <_> + + 0 -1 837 -1.3716940302401781e-03 + + 2.2532704472541809e-01 -6.2741614878177643e-02 + <_> + + 0 -1 910 3.3456790260970592e-03 + + 3.8516163825988770e-02 -3.6224716901779175e-01 + <_> + + 0 -1 476 1.9023896893486381e-03 + + -5.4677281528711319e-02 2.5294607877731323e-01 + <_> + + 0 -1 1037 -1.4274399727582932e-03 + + -3.7934723496437073e-01 3.8707002997398376e-02 + <_> + + 0 -1 512 1.1010284069925547e-03 + + -9.5659099519252777e-02 1.4958517253398895e-01 + <_> + + 0 -1 219 -4.4154529459774494e-03 + + -5.1156622171401978e-01 2.5640288367867470e-02 + <_> + + 0 -1 448 3.7023271434009075e-03 + + -4.3221119791269302e-02 3.2581970095634460e-01 + <_> + + 0 -1 237 -5.4480084218084812e-03 + + -4.7611567378044128e-01 3.5773757845163345e-02 + <_> + + 0 -1 313 -3.1974539160728455e-04 + + 1.1916244029998779e-01 -1.1832383275032043e-01 + <_> + + 0 -1 381 -2.8494147583842278e-02 + + -6.5004557371139526e-01 2.0599177107214928e-02 + <_> + + 0 -1 941 -2.7449331246316433e-03 + + -3.9275056123733521e-01 3.3223718404769897e-02 + <_> + + 0 -1 937 4.1362000629305840e-03 + + 2.7191400527954102e-02 -4.7952741384506226e-01 + <_> + + 0 -1 638 3.3568721264600754e-03 + + -6.0983922332525253e-02 2.2964073717594147e-01 + <_> + + 0 -1 571 -5.7129040360450745e-03 + + -5.9052920341491699e-01 2.3388050496578217e-02 + <_> + + 0 -1 477 -1.1567326728254557e-03 + + 1.5093772113323212e-01 -9.1553181409835815e-02 + <_> + + 0 -1 143 -8.9379055425524712e-03 + + -3.5481104254722595e-01 3.6294396966695786e-02 + <_> + + 0 -1 811 3.6097350530326366e-03 + + 3.2780081033706665e-02 -3.8517734408378601e-01 + <_> + + 0 -1 975 2.0727193914353848e-03 + + -5.3627125918865204e-02 2.5666573643684387e-01 + <_> + + 0 -1 977 -1.8177125602960587e-03 + + 2.0363596081733704e-01 -7.0555560290813446e-02 + <_> + + 0 -1 932 -3.3223466016352177e-03 + + -4.8926571011543274e-01 2.8675178065896034e-02 + <_> + + 0 -1 553 -4.4222660362720490e-03 + + -4.0920063853263855e-01 3.0863059684634209e-02 + <_> + + 0 -1 705 -7.8024319373071194e-04 + + 1.2166435271501541e-01 -1.0897941887378693e-01 + <_> + + 0 -1 850 7.9855127260088921e-03 + + 2.5865448638796806e-02 -4.8917418718338013e-01 + <_> + + 0 -1 99 -2.7752606911235489e-05 + + 1.1611134558916092e-01 -1.1225233227014542e-01 + <_> + + 0 -1 641 3.0770362354815006e-03 + + -6.4753420650959015e-02 1.9632078707218170e-01 + <_> + + 0 -1 593 -2.1007210016250610e-03 + + 1.9681814312934875e-01 -9.4167068600654602e-02 + <_> + + 0 -1 112 -6.1383144930005074e-03 + + -3.9225277304649353e-01 3.5275831818580627e-02 + <_> + + 0 -1 119 1.1184177361428738e-02 + + 2.9410628601908684e-02 -4.3673589825630188e-01 + <_> + + 0 -1 1007 1.0432782582938671e-03 + + -6.7393802106380463e-02 1.9237922132015228e-01 + <_> + + 0 -1 931 8.5366604616865516e-04 + + -8.4067851305007935e-02 1.6720806062221527e-01 + <_> + + 0 -1 55 -3.3059090375900269e-02 + + 2.6451063156127930e-01 -5.2662543952465057e-02 + <_> + + 0 -1 161 -8.7435375899076462e-03 + + -3.0780994892120361e-01 4.8419766128063202e-02 + <_> + + 0 -1 907 -1.1587596964091063e-03 + + 1.4863640069961548e-01 -9.4251774251461029e-02 + <_> + + 0 -1 295 -2.2717786952853203e-02 + + -4.2414310574531555e-01 3.5150803625583649e-02 + <_> + + 0 -1 810 -8.4660220891237259e-03 + + 2.5765278935432434e-01 -5.4796367883682251e-02 + <_> + + 0 -1 492 -1.4943551504984498e-03 + + -2.7729934453964233e-01 4.9375709146261215e-02 + <_> + + 0 -1 0 -7.5480109080672264e-04 + + 1.2197802960872650e-01 -1.0845532268285751e-01 + <_> + + 0 -1 853 2.9903287068009377e-03 + + -8.4785357117652893e-02 1.5424512326717377e-01 + <_> + + 0 -1 1040 1.7600806895643473e-03 + + 7.0044547319412231e-02 -1.9795240461826324e-01 + <_> + + 0 -1 154 1.2243577279150486e-02 + + -7.8472696244716644e-02 1.7095038294792175e-01 + <_> + + 0 -1 80 -2.7739753946661949e-02 + + 2.0475350320339203e-01 -6.9862313568592072e-02 + <_> + + 0 -1 300 -6.4486754126846790e-03 + + -3.7651637196540833e-01 3.3540505915880203e-02 + <_> + + 0 -1 341 -1.3427068479359150e-02 + + 1.5320046246051788e-01 -8.3272159099578857e-02 + <_> + + 0 -1 360 8.2654636353254318e-03 + + -8.1395141780376434e-02 1.9696740806102753e-01 + <_> + + 0 -1 616 3.0615129508078098e-03 + + -5.8534789830446243e-02 2.1799990534782410e-01 + <_> + + 0 -1 616 -1.4359520282596350e-03 + + 1.8553669750690460e-01 -7.9428143799304962e-02 + <_> + + 0 -1 488 2.8793164528906345e-03 + + 3.7499722093343735e-02 -3.5483118891716003e-01 + <_> + + 0 -1 631 -9.0899681672453880e-03 + + -5.9031629562377930e-01 2.0012531429529190e-02 + <_> + + 0 -1 896 1.6797243151813745e-03 + + -6.8868115544319153e-02 1.8992543220520020e-01 + <_> + + 0 -1 581 -1.1759581044316292e-02 + + 3.6288693547248840e-01 -3.3578243106603622e-02 + <_> + + 0 -1 749 3.8305222988128662e-03 + + -6.6793553531169891e-02 1.9304293394088745e-01 + <_> + + 0 -1 1018 1.2506111524999142e-03 + + -8.1618689000606537e-02 1.5481384098529816e-01 + <_> + + 0 -1 379 -1.6119323670864105e-02 + + 1.4024992287158966e-01 -9.3965478241443634e-02 + <_> + + 0 -1 576 -7.2789913974702358e-04 + + 1.9554650783538818e-01 -7.2329640388488770e-02 + <_> + + 0 -1 178 1.4888901496306062e-03 + + 3.3372651785612106e-02 -4.0691211819648743e-01 + <_> + + 0 -1 984 -4.9822013825178146e-03 + + -3.3125448226928711e-01 3.6899805068969727e-02 + <_> + + 0 -1 1053 9.4443336129188538e-03 + + 3.1763385981321335e-02 -3.7651473283767700e-01 + + <_> + 100 + -1.3101767301559448e+00 + + <_> + + 0 -1 535 -1.2652185745537281e-02 + + 4.0350878238677979e-01 -8.6829073727130890e-02 + <_> + + 0 -1 386 4.8778904601931572e-03 + + -9.1208808124065399e-02 4.8882400989532471e-01 + <_> + + 0 -1 875 -2.4099014699459076e-02 + + 3.6089360713958740e-01 -1.1495783179998398e-01 + <_> + + 0 -1 955 1.7244052141904831e-03 + + -1.5974776446819305e-01 1.6197346150875092e-01 + <_> + + 0 -1 478 -3.6334272008389235e-03 + + 2.7575418353080750e-01 -9.4314105808734894e-02 + <_> + + 0 -1 874 -3.4076566807925701e-03 + + 2.2806543111801147e-01 -1.1266379803419113e-01 + <_> + + 0 -1 343 8.8951038196682930e-03 + + -6.6720969974994659e-02 3.3090111613273621e-01 + <_> + + 0 -1 886 -2.4365000426769257e-03 + + -4.6264356374740601e-01 5.9559248387813568e-02 + <_> + + 0 -1 134 1.6330357640981674e-02 + + 6.1187297105789185e-02 -4.2252638936042786e-01 + <_> + + 0 -1 92 8.4438512567430735e-04 + + -1.6640183329582214e-01 1.1608948558568954e-01 + <_> + + 0 -1 841 2.9493896290659904e-03 + + -9.1952294111251831e-02 2.0670032501220703e-01 + <_> + + 0 -1 40 3.4696407616138458e-02 + + -8.0334044992923737e-02 2.8779104351997375e-01 + <_> + + 0 -1 893 -3.3343117684125900e-03 + + -5.9474521875381470e-01 3.6547001451253891e-02 + <_> + + 0 -1 761 9.3975086929276586e-04 + + -1.5703736245632172e-01 1.1884722858667374e-01 + <_> + + 0 -1 174 -3.4337402321398258e-03 + + -5.6122291088104248e-01 3.2535579055547714e-02 + <_> + + 0 -1 1010 2.6463428512215614e-03 + + -7.0756055414676666e-02 2.5195503234863281e-01 + <_> + + 0 -1 334 -5.4167490452528000e-04 + + 1.2782673537731171e-01 -1.3642209768295288e-01 + <_> + + 0 -1 219 2.6469756849110126e-03 + + 4.3448049575090408e-02 -4.2012536525726318e-01 + <_> + + 0 -1 467 -3.8945327978581190e-03 + + -3.4613665938377380e-01 4.6863511204719543e-02 + <_> + + 0 -1 258 1.0849055834114552e-03 + + -7.2841711342334747e-02 2.2674085199832916e-01 + <_> + + 0 -1 258 -9.8655023612082005e-04 + + 2.5967630743980408e-01 -8.0196425318717957e-02 + <_> + + 0 -1 204 4.3801497668027878e-03 + + 2.8548270463943481e-02 -6.2486541271209717e-01 + <_> + + 0 -1 554 3.1944573856890202e-04 + + -1.4062304794788361e-01 1.1761485785245895e-01 + <_> + + 0 -1 300 6.6440929658710957e-03 + + 3.2654736191034317e-02 -4.6211913228034973e-01 + <_> + + 0 -1 42 7.0357543881982565e-04 + + 7.5751155614852905e-02 -1.9804775714874268e-01 + <_> + + 0 -1 446 5.4024737328290939e-03 + + -6.1951220035552979e-02 2.4502439796924591e-01 + <_> + + 0 -1 502 7.2796619497239590e-03 + + -5.9379905462265015e-02 2.5588110089302063e-01 + <_> + + 0 -1 169 -1.5059831552207470e-02 + + -6.6548824310302734e-01 2.2492453455924988e-02 + <_> + + 0 -1 270 -4.6248016878962517e-03 + + -3.4483894705772400e-01 4.2247168719768524e-02 + <_> + + 0 -1 290 1.4736279845237732e-03 + + 3.3624436706304550e-02 -4.1066497564315796e-01 + <_> + + 0 -1 110 4.0667224675416946e-03 + + -8.6238399147987366e-02 1.6550070047378540e-01 + <_> + + 0 -1 113 -1.2728295987471938e-03 + + 1.9737298786640167e-01 -9.5425128936767578e-02 + <_> + + 0 -1 957 -1.5297440811991692e-02 + + -5.9287589788436890e-01 2.3890895769000053e-02 + <_> + + 0 -1 969 -2.9415758326649666e-03 + + -4.8744291067123413e-01 2.8945079073309898e-02 + <_> + + 0 -1 840 9.3173712957650423e-04 + + -8.9065223932266235e-02 1.6721877455711365e-01 + <_> + + 0 -1 791 2.1161064505577087e-03 + + -5.8501452207565308e-02 2.7767315506935120e-01 + <_> + + 0 -1 579 -3.7564497906714678e-03 + + 2.6502594351768494e-01 -5.3400754928588867e-02 + <_> + + 0 -1 224 1.9215289503335953e-02 + + 3.6197379231452942e-02 -3.9996260404586792e-01 + <_> + + 0 -1 276 -5.8480387087911367e-04 + + 1.7670612037181854e-01 -8.0434471368789673e-02 + <_> + + 0 -1 62 1.7193648964166641e-02 + + 2.1810308098793030e-02 -6.6349571943283081e-01 + <_> + + 0 -1 394 -1.5182361006736755e-02 + + 2.4825552105903625e-01 -6.3092373311519623e-02 + <_> + + 0 -1 712 3.0793007463216782e-03 + + 2.4977168068289757e-02 -5.3303867578506470e-01 + <_> + + 0 -1 410 -2.4421955458819866e-03 + + -3.6828973889350891e-01 3.3543743193149567e-02 + <_> + + 0 -1 1011 7.0760864764451981e-04 + + -7.0839107036590576e-02 1.9299270212650299e-01 + <_> + + 0 -1 280 -2.9198618140071630e-03 + + -4.2773759365081787e-01 3.4788779914379120e-02 + <_> + + 0 -1 77 4.9937088042497635e-03 + + 3.5642433911561966e-02 -3.7421676516532898e-01 + <_> + + 0 -1 701 3.1980490311980247e-03 + + -6.5103210508823395e-02 2.1381905674934387e-01 + <_> + + 0 -1 320 -1.1253832839429379e-02 + + 1.9790579378604889e-01 -7.1859836578369141e-02 + <_> + + 0 -1 496 -3.6279223859310150e-02 + + 1.7960831522941589e-01 -9.7373597323894501e-02 + <_> + + 0 -1 606 2.5160997174680233e-03 + + 4.7910790890455246e-02 -2.7035105228424072e-01 + <_> + + 0 -1 597 1.2429051566869020e-03 + + -7.8723609447479248e-02 1.7209371924400330e-01 + <_> + + 0 -1 600 -1.6120750457048416e-02 + + 2.6868200302124023e-01 -5.0688084214925766e-02 + <_> + + 0 -1 676 1.9487962126731873e-03 + + 4.2773328721523285e-02 -3.2401460409164429e-01 + <_> + + 0 -1 371 7.1887858211994171e-04 + + -9.3979224562644958e-02 1.4450067281723022e-01 + <_> + + 0 -1 315 2.4896476417779922e-02 + + 3.0655095353722572e-02 -4.5330229401588440e-01 + <_> + + 0 -1 1026 -3.9382722228765488e-02 + + -7.5473642349243164e-01 1.4460344798862934e-02 + <_> + + 0 -1 16 1.6916246712207794e-01 + + 1.8219815567135811e-02 -6.0212779045104980e-01 + <_> + + 0 -1 327 2.6912155590252951e-05 + + -1.3110430538654327e-01 1.0080647468566895e-01 + <_> + + 0 -1 720 -1.1350987479090691e-03 + + -3.5285457968711853e-01 3.5424951463937759e-02 + <_> + + 0 -1 275 -5.3854554425925016e-04 + + 1.6519539058208466e-01 -8.5205554962158203e-02 + <_> + + 0 -1 1006 -7.9703063238412142e-04 + + 1.2170238047838211e-01 -1.1191177368164062e-01 + <_> + + 0 -1 1055 6.4357938244938850e-03 + + 2.3892326280474663e-02 -5.2907115221023560e-01 + <_> + + 0 -1 184 3.5384115763008595e-03 + + 1.5895446762442589e-02 -7.3063355684280396e-01 + <_> + + 0 -1 503 -5.9715351089835167e-03 + + -4.9897637963294983e-01 2.2720154374837875e-02 + <_> + + 0 -1 500 -1.3486531376838684e-01 + + 4.7622504830360413e-01 -3.0212458223104477e-02 + <_> + + 0 -1 824 1.5813487116247416e-03 + + -6.4366899430751801e-02 1.9106543064117432e-01 + <_> + + 0 -1 438 1.2239011703059077e-03 + + 3.5654775798320770e-02 -3.6865225434303284e-01 + <_> + + 0 -1 871 1.5586249064654112e-03 + + -7.6894849538803101e-02 1.7627324163913727e-01 + <_> + + 0 -1 807 8.1224087625741959e-03 + + -9.0349502861499786e-02 1.4695085585117340e-01 + <_> + + 0 -1 693 -1.1717316228896379e-03 + + -4.2172068357467651e-01 3.2626960426568985e-02 + <_> + + 0 -1 863 3.1573872547596693e-03 + + 1.6080003231763840e-02 -7.3708915710449219e-01 + <_> + + 0 -1 328 -6.0417165514081717e-04 + + 1.3188406825065613e-01 -1.0221557319164276e-01 + <_> + + 0 -1 870 5.9989960864186287e-03 + + -5.6194521486759186e-02 2.4262723326683044e-01 + <_> + + 0 -1 285 9.2063043266534805e-03 + + -7.4052155017852783e-02 1.9847218692302704e-01 + <_> + + 0 -1 759 5.9181386604905128e-03 + + 2.7928760275244713e-02 -5.3380137681961060e-01 + <_> + + 0 -1 637 2.2121241781860590e-03 + + -7.4788182973861694e-02 1.9799898564815521e-01 + <_> + + 0 -1 634 1.5453733503818512e-03 + + -8.1615962088108063e-02 1.7845135927200317e-01 + <_> + + 0 -1 48 -2.7309993747621775e-03 + + -2.9415401816368103e-01 4.8099983483552933e-02 + <_> + + 0 -1 288 1.5755122527480125e-02 + + -8.2719191908836365e-02 1.5387716889381409e-01 + <_> + + 0 -1 358 -5.5120363831520081e-02 + + -2.7076271176338196e-01 5.2753895521163940e-02 + <_> + + 0 -1 188 2.9593750834465027e-01 + + -2.5313137099146843e-02 5.3404790163040161e-01 + <_> + + 0 -1 755 -1.1218986473977566e-03 + + 1.1400944739580154e-01 -1.1270149052143097e-01 + <_> + + 0 -1 12 -3.7802509963512421e-02 + + 3.1571185588836670e-01 -4.9672659486532211e-02 + <_> + + 0 -1 122 7.6384171843528748e-03 + + -1.0544487833976746e-01 1.6579298675060272e-01 + <_> + + 0 -1 586 6.8679507821798325e-03 + + -6.0160953551530838e-02 2.2640766203403473e-01 + <_> + + 0 -1 443 5.1510091871023178e-02 + + 2.6919802650809288e-02 -5.1188707351684570e-01 + <_> + + 0 -1 997 -1.7317479476332664e-02 + + 2.8218811750411987e-01 -4.4739942997694016e-02 + <_> + + 0 -1 430 8.3876429125666618e-03 + + -5.7016383856534958e-02 2.2617760300636292e-01 + <_> + + 0 -1 625 9.2909142374992371e-02 + + 3.1283479183912277e-02 -4.9390810728073120e-01 + <_> + + 0 -1 457 4.8232711851596832e-03 + + 2.4896934628486633e-02 -4.5571261644363403e-01 + <_> + + 0 -1 484 2.3969253525137901e-03 + + 2.3365976288914680e-02 -4.8319596052169800e-01 + <_> + + 0 -1 599 -3.8546645082533360e-03 + + 2.0274488627910614e-01 -5.8264043182134628e-02 + <_> + + 0 -1 647 -1.2048919452354312e-03 + + -3.4361392259597778e-01 3.4746967256069183e-02 + <_> + + 0 -1 734 -1.6053356230258942e-02 + + 1.8685258924961090e-01 -6.7979305982589722e-02 + <_> + + 0 -1 1045 -2.1703056991100311e-02 + + -5.0804340839385986e-01 2.5113353505730629e-02 + <_> + + 0 -1 541 -1.9719875417649746e-03 + + -2.7325069904327393e-01 4.3638698756694794e-02 + <_> + + 0 -1 465 -1.3189280871301889e-03 + + 2.5198838114738464e-01 -4.8170279711484909e-02 + <_> + + 0 -1 465 1.3257672544568777e-03 + + -6.6290155053138733e-02 2.6572498679161072e-01 + <_> + + 0 -1 1024 -2.5993511080741882e-03 + + -7.1209841966629028e-01 1.9255550578236580e-02 + <_> + + 0 -1 926 4.0416182018816471e-03 + + 2.4820772930979729e-02 -4.3810126185417175e-01 <_> <_> - 0 0 6 1 -1. + 0 0 2 4 -1. <_> - 3 0 3 1 2. + 0 2 2 2 2. 0 <_> <_> - 0 0 6 2 -1. + 0 0 6 14 -1. <_> - 3 0 3 2 2. + 0 0 3 7 2. + <_> + 3 7 3 7 2. 0 <_> @@ -5978,11 +6595,9 @@ <_> <_> - 0 0 8 4 -1. + 0 0 8 2 -1. <_> - 0 0 4 2 2. - <_> - 4 2 4 2 2. + 4 0 4 2 2. 0 <_> @@ -6005,18 +6620,11 @@ <_> <_> - 0 0 8 16 -1. + 0 0 8 14 -1. <_> - 0 0 4 8 2. + 0 0 4 7 2. <_> - 4 8 4 8 2. - 0 - <_> - - <_> - 0 0 10 3 -1. - <_> - 5 0 5 3 2. + 4 7 4 7 2. 0 <_> @@ -6030,18 +6638,18 @@ <_> <_> - 0 0 10 10 -1. + 0 0 10 8 -1. <_> - 0 0 5 5 2. + 0 0 5 4 2. <_> - 5 5 5 5 2. + 5 4 5 4 2. 0 <_> <_> - 0 0 18 14 -1. + 0 0 18 13 -1. <_> - 6 0 6 14 3. + 6 0 6 13 3. 0 <_> @@ -6062,11 +6670,11 @@ <_> <_> - 0 0 16 8 -1. + 0 0 16 6 -1. <_> - 0 0 8 4 2. + 0 0 8 3 2. <_> - 8 4 8 4 2. + 8 3 8 3 2. 0 <_> @@ -6087,25 +6695,53 @@ <_> <_> - 0 1 24 2 -1. + 0 0 24 2 -1. <_> - 8 1 8 2 3. + 0 0 12 1 2. + <_> + 12 1 12 1 2. 0 <_> <_> - 0 1 16 8 -1. + 0 0 12 12 -1. <_> - 0 1 8 4 2. - <_> - 8 5 8 4 2. + 0 6 12 6 2. 0 <_> <_> - 0 1 16 18 -1. + 0 0 15 18 -1. <_> - 0 7 16 6 3. + 0 6 15 6 3. + 0 + <_> + + <_> + 0 1 1 6 -1. + <_> + 0 3 1 2 3. + 0 + <_> + + <_> + 0 1 4 6 -1. + <_> + 2 1 2 6 2. + 0 + <_> + + <_> + 0 1 15 1 -1. + <_> + 5 1 5 1 3. + 0 + <_> + + <_> + 0 1 10 2 -1. + <_> + 5 1 5 2 2. 0 <_> @@ -6119,16 +6755,18 @@ <_> <_> - 0 2 24 19 -1. + 0 2 24 10 -1. <_> - 12 2 12 19 2. + 0 2 12 5 2. + <_> + 12 7 12 5 2. 0 <_> <_> - 0 3 8 3 -1. + 0 3 7 3 -1. <_> - 0 4 8 1 3. + 0 4 7 1 3. 0 <_> @@ -6142,46 +6780,23 @@ <_> <_> - 0 4 6 9 -1. + 0 4 6 12 -1. <_> - 0 7 6 3 3. + 0 8 6 4 3. 0 <_> <_> - 0 4 24 2 -1. + 0 4 24 6 -1. <_> - 0 4 12 1 2. - <_> - 12 5 12 1 2. + 0 6 24 2 3. 0 <_> <_> - 0 4 13 15 -1. + 0 5 2 9 -1. <_> - 0 9 13 5 3. - 0 - <_> - - <_> - 0 4 14 3 -1. - <_> - 0 5 14 1 3. - 0 - <_> - - <_> - 0 4 23 6 -1. - <_> - 0 6 23 2 3. - 0 - <_> - - <_> - 0 5 9 9 -1. - <_> - 0 8 9 3 3. + 0 8 2 3 3. 0 <_> @@ -6192,6 +6807,13 @@ <_> 12 6 12 1 2. 0 + <_> + + <_> + 0 6 6 3 -1. + <_> + 0 7 6 1 3. + 0 <_> <_> @@ -6204,41 +6826,30 @@ <_> <_> - 0 6 18 8 -1. + 0 6 22 3 -1. <_> - 0 10 18 4 2. + 0 7 22 1 3. 0 <_> <_> - 0 6 24 3 -1. + 0 6 24 9 -1. <_> - 0 7 24 1 3. + 0 9 24 3 3. 0 <_> <_> - 0 7 8 2 -1. + 0 7 16 1 -1. <_> - 0 7 4 1 2. - <_> - 4 8 4 1 2. + 8 7 8 1 2. 0 <_> <_> - 0 7 9 6 -1. + 0 7 24 3 -1. <_> - 0 9 9 2 3. - 0 - <_> - - <_> - 0 7 22 4 -1. - <_> - 0 7 11 2 2. - <_> - 11 9 11 2 2. + 8 7 8 3 3. 0 <_> @@ -6252,34 +6863,23 @@ <_> <_> - 0 7 24 4 -1. + 0 8 4 6 -1. <_> - 0 7 12 2 2. - <_> - 12 9 12 2 2. + 2 8 2 6 2. 0 <_> <_> - 0 7 20 6 -1. + 0 8 6 15 -1. <_> - 0 9 20 2 3. + 3 8 3 15 2. 0 <_> <_> - 0 8 6 14 -1. + 0 8 4 9 -1. <_> - 3 8 3 14 2. - 0 - <_> - - <_> - 0 8 8 2 -1. - <_> - 0 8 4 1 2. - <_> - 4 9 4 1 2. + 0 11 4 3 3. 0 <_> @@ -6288,15 +6888,6 @@ <_> 8 8 8 1 3. 0 - <_> - - <_> - 0 8 24 2 -1. - <_> - 0 8 12 1 2. - <_> - 12 9 12 1 2. - 0 <_> <_> @@ -6309,32 +6900,30 @@ <_> <_> - 0 8 24 9 -1. + 0 9 2 3 -1. <_> - 12 8 12 9 2. + 0 10 2 1 3. 0 <_> <_> - 0 9 4 1 -1. + 0 9 2 9 -1. <_> - 2 9 2 1 2. + 0 12 2 3 3. 0 <_> <_> - 0 9 6 12 -1. + 0 9 5 3 -1. <_> - 0 9 3 6 2. - <_> - 3 15 3 6 2. + 0 10 5 1 3. 0 <_> <_> - 0 9 4 9 -1. + 0 9 5 6 -1. <_> - 0 12 4 3 3. + 0 11 5 2 3. 0 <_> @@ -6346,9 +6935,16 @@ <_> <_> - 0 9 11 2 -1. + 0 9 8 2 -1. <_> - 0 10 11 1 2. + 0 10 8 1 2. + 0 + <_> + + <_> + 0 9 10 2 -1. + <_> + 0 10 10 1 2. 0 <_> @@ -6359,15 +6955,6 @@ <_> 11 10 11 1 2. 0 - <_> - - <_> - 0 9 24 2 -1. - <_> - 0 9 12 1 2. - <_> - 12 10 12 1 2. - 0 <_> <_> @@ -6380,11 +6967,9 @@ <_> <_> - 0 9 24 6 -1. + 0 9 24 15 -1. <_> - 0 9 12 3 2. - <_> - 12 12 12 3 2. + 12 9 12 15 2. 0 <_> @@ -6396,48 +6981,30 @@ <_> <_> - 0 10 2 2 -1. + 0 10 2 3 -1. <_> - 0 11 2 1 2. + 0 11 2 1 3. 0 <_> <_> - 0 10 3 3 -1. + 0 10 6 1 -1. <_> - 0 11 3 1 3. + 3 10 3 1 2. 0 <_> <_> - 0 10 3 6 -1. + 0 10 6 14 -1. <_> - 0 12 3 2 3. + 3 10 3 14 2. 0 <_> <_> - 0 10 6 8 -1. + 0 10 4 3 -1. <_> - 0 10 3 4 2. - <_> - 3 14 3 4 2. - 0 - <_> - - <_> - 0 10 8 10 -1. - <_> - 0 10 4 5 2. - <_> - 4 15 4 5 2. - 0 - <_> - - <_> - 0 10 8 11 -1. - <_> - 4 10 4 11 2. + 0 11 4 1 3. 0 <_> @@ -6451,9 +7018,25 @@ <_> <_> - 0 11 6 2 -1. + 0 10 24 4 -1. <_> - 3 11 3 2 2. + 0 10 12 2 2. + <_> + 12 12 12 2 2. + 0 + <_> + + <_> + 0 10 13 3 -1. + <_> + 0 11 13 1 3. + 0 + <_> + + <_> + 0 11 2 3 -1. + <_> + 0 12 2 1 3. 0 <_> @@ -6467,18 +7050,9 @@ <_> <_> - 0 11 8 8 -1. + 0 11 10 3 -1. <_> - 0 11 4 4 2. - <_> - 4 15 4 4 2. - 0 - <_> - - <_> - 0 11 8 13 -1. - <_> - 4 11 4 13 2. + 0 12 10 1 3. 0 <_> @@ -6492,55 +7066,53 @@ <_> <_> - 0 11 21 10 -1. + 0 12 3 10 -1. <_> - 0 16 21 5 2. + 1 12 1 10 3. 0 <_> <_> - 0 12 8 4 -1. + 0 12 22 10 -1. <_> - 4 12 4 4 2. + 11 12 11 10 2. 0 <_> <_> - 0 12 24 9 -1. + 0 13 3 9 -1. <_> - 12 12 12 9 2. + 1 13 1 9 3. 0 <_> <_> - 0 13 24 4 -1. + 0 13 12 10 -1. <_> - 0 13 12 2 2. - <_> - 12 15 12 2 2. + 6 13 6 10 2. 0 <_> <_> - 0 14 3 7 -1. + 0 13 24 10 -1. <_> - 1 14 1 7 3. + 12 13 12 10 2. 0 <_> <_> - 0 14 10 8 -1. + 0 14 24 2 -1. <_> - 5 14 5 8 2. + 0 14 12 1 2. + <_> + 12 15 12 1 2. 0 <_> <_> - 0 15 8 8 -1. + 0 15 3 8 -1. <_> - 0 15 4 4 2. - <_> - 4 19 4 4 2. + 1 15 1 8 3. 0 <_> @@ -6554,58 +7126,39 @@ <_> <_> - 0 16 3 8 -1. + 0 15 10 6 -1. <_> - 1 16 1 8 3. + 0 17 10 2 3. 0 <_> <_> - 0 16 8 6 -1. + 0 16 12 8 -1. <_> - 0 18 8 2 3. + 0 16 6 4 2. + <_> + 6 20 6 4 2. 0 <_> <_> - 0 17 6 3 -1. + 0 17 3 7 -1. <_> - 3 17 3 3 2. + 1 17 1 7 3. 0 <_> <_> - 0 17 4 6 -1. + 0 18 6 3 -1. <_> - 0 19 4 2 3. + 0 19 6 1 3. 0 <_> <_> - 0 18 3 6 -1. + 0 19 6 3 -1. <_> - 1 18 1 6 3. - 0 - <_> - - <_> - 0 19 3 4 -1. - <_> - 1 19 1 4 3. - 0 - <_> - - <_> - 0 19 9 3 -1. - <_> - 0 20 9 1 3. - 0 - <_> - - <_> - 0 20 4 3 -1. - <_> - 0 21 4 1 3. + 0 20 6 1 3. 0 <_> @@ -6617,23 +7170,37 @@ <_> <_> - 0 21 3 3 -1. + 0 21 4 3 -1. <_> - 0 22 3 1 3. + 0 22 4 1 3. 0 <_> <_> - 0 22 1 2 -1. + 0 21 5 3 -1. <_> - 0 23 1 1 2. + 0 22 5 1 3. 0 <_> <_> - 1 0 10 1 -1. + 0 22 22 2 -1. <_> - 6 0 5 1 2. + 11 22 11 2 2. + 0 + <_> + + <_> + 1 0 6 1 -1. + <_> + 4 0 3 1 2. + 0 + <_> + + <_> + 1 0 15 13 -1. + <_> + 6 0 5 13 3. 0 <_> @@ -6647,156 +7214,103 @@ <_> <_> - 1 0 7 9 -1. + 1 1 22 2 -1. <_> - 1 3 7 3 3. + 1 1 11 1 2. + <_> + 12 2 11 1 2. 0 <_> <_> - 1 0 14 10 -1. + 1 2 23 9 -1. <_> - 1 0 7 5 2. - <_> - 8 5 7 5 2. + 1 5 23 3 3. 0 <_> <_> - 1 0 22 2 -1. + 1 3 4 3 -1. <_> - 1 0 11 1 2. - <_> - 12 1 11 1 2. + 1 4 4 1 3. 0 <_> <_> - 1 2 6 10 -1. + 1 3 12 18 -1. <_> - 1 2 3 5 2. - <_> - 4 7 3 5 2. + 5 3 4 18 3. 0 <_> <_> - 1 2 22 20 -1. + 1 4 8 3 -1. <_> - 12 2 11 20 2. + 1 5 8 1 3. 0 <_> <_> - 1 2 22 21 -1. + 1 4 23 6 -1. <_> - 12 2 11 21 2. + 1 6 23 2 3. 0 <_> <_> - 1 3 15 3 -1. + 1 6 6 4 -1. <_> - 6 3 5 3 3. + 1 6 3 2 2. + <_> + 4 8 3 2 2. 0 <_> <_> - 1 3 6 3 -1. + 1 6 3 9 -1. <_> - 1 4 6 1 3. + 1 9 3 3 3. 0 <_> <_> - 1 3 22 2 -1. + 1 6 4 3 -1. <_> - 1 3 11 1 2. - <_> - 12 4 11 1 2. + 1 7 4 1 3. 0 <_> <_> - 1 4 4 3 -1. + 1 6 22 2 -1. <_> - 1 5 4 1 3. + 1 6 11 1 2. + <_> + 12 7 11 1 2. 0 <_> <_> - 1 4 12 17 -1. + 1 6 12 8 -1. <_> - 5 4 4 17 3. + 1 10 12 4 2. 0 <_> <_> - 1 4 20 20 -1. + 1 7 8 4 -1. <_> - 11 4 10 20 2. + 1 7 4 2 2. + <_> + 5 9 4 2 2. 0 <_> <_> - 1 4 22 2 -1. + 1 7 20 4 -1. <_> - 1 4 11 1 2. + 1 7 10 2 2. <_> - 12 5 11 1 2. - 0 - <_> - - <_> - 1 4 22 19 -1. - <_> - 12 4 11 19 2. - 0 - <_> - - <_> - 1 5 22 2 -1. - <_> - 1 5 11 1 2. - <_> - 12 6 11 1 2. - 0 - <_> - - <_> - 1 6 2 2 -1. - <_> - 1 6 1 1 2. - <_> - 2 7 1 1 2. - 0 - <_> - - <_> - 1 6 16 17 -1. - <_> - 9 6 8 17 2. - 0 - <_> - - <_> - 1 6 21 9 -1. - <_> - 1 9 21 3 3. - 0 - <_> - - <_> - 1 6 22 6 -1. - <_> - 1 8 22 2 3. - 0 - <_> - - <_> - 1 6 23 9 -1. - <_> - 1 9 23 3 3. + 11 9 10 2 2. 0 <_> @@ -6810,30 +7324,85 @@ <_> <_> - 1 8 19 12 -1. + 1 7 22 14 -1. <_> - 1 12 19 4 3. + 12 7 11 14 2. 0 <_> <_> - 1 9 6 2 -1. + 1 8 1 2 -1. <_> - 4 9 3 2 2. + 1 9 1 1 2. 0 <_> <_> - 1 9 12 3 -1. + 1 8 8 2 -1. <_> - 5 9 4 3 3. + 1 8 4 1 2. + <_> + 5 9 4 1 2. 0 <_> <_> - 1 10 3 8 -1. + 1 8 7 4 -1. <_> - 2 10 1 8 3. + 1 10 7 2 2. + 0 + <_> + + <_> + 1 8 22 4 -1. + <_> + 1 8 11 2 2. + <_> + 12 10 11 2 2. + 0 + <_> + + <_> + 1 9 4 3 -1. + <_> + 3 9 2 3 2. + 0 + <_> + + <_> + 1 9 4 6 -1. + <_> + 1 11 4 2 3. + 0 + <_> + + <_> + 1 9 20 2 -1. + <_> + 1 9 10 1 2. + <_> + 11 10 10 1 2. + 0 + <_> + + <_> + 1 10 3 13 -1. + <_> + 2 10 1 13 3. + 0 + <_> + + <_> + 1 10 4 6 -1. + <_> + 1 12 4 2 3. + 0 + <_> + + <_> + 1 10 8 3 -1. + <_> + 1 11 8 1 3. 0 <_> @@ -6847,147 +7416,85 @@ <_> <_> - 1 10 12 3 -1. + 1 11 6 2 -1. <_> - 1 11 12 1 3. + 4 11 3 2 2. 0 <_> <_> - 1 11 3 8 -1. + 1 11 22 2 -1. <_> - 2 11 1 8 3. + 1 11 11 1 2. + <_> + 12 12 11 1 2. 0 <_> <_> - 1 11 20 2 -1. + 1 12 3 8 -1. <_> - 1 11 10 1 2. - <_> - 11 12 10 1 2. + 2 12 1 8 3. 0 <_> <_> - 1 11 22 4 -1. + 1 12 4 1 -1. <_> - 1 11 11 2 2. - <_> - 12 13 11 2 2. + 3 12 2 1 2. 0 <_> <_> - 1 12 3 11 -1. + 1 12 20 2 -1. <_> - 2 12 1 11 3. + 1 12 10 1 2. + <_> + 11 13 10 1 2. 0 <_> <_> - 1 12 6 1 -1. + 1 13 3 8 -1. <_> - 4 12 3 1 2. + 2 13 1 8 3. 0 <_> <_> - 1 12 20 12 -1. + 1 13 9 3 -1. <_> - 11 12 10 12 2. + 1 14 9 1 3. 0 <_> <_> - 1 13 3 5 -1. + 1 13 21 8 -1. <_> - 2 13 1 5 3. + 1 17 21 4 2. 0 <_> <_> - 1 13 22 2 -1. + 1 15 8 2 -1. <_> - 1 13 11 1 2. - <_> - 12 14 11 1 2. + 5 15 4 2 2. 0 <_> <_> - 1 14 4 4 -1. + 1 17 22 2 -1. <_> - 3 14 2 4 2. + 1 17 11 1 2. + <_> + 12 18 11 1 2. 0 <_> <_> - 1 14 22 2 -1. + 1 18 3 6 -1. <_> - 1 14 11 1 2. - <_> - 12 15 11 1 2. - 0 - <_> - - <_> - 1 14 23 6 -1. - <_> - 1 17 23 3 2. - 0 - <_> - - <_> - 1 15 14 2 -1. - <_> - 1 15 7 1 2. - <_> - 8 16 7 1 2. - 0 - <_> - - <_> - 1 17 3 5 -1. - <_> - 2 17 1 5 3. - 0 - <_> - - <_> - 1 17 3 7 -1. - <_> - 2 17 1 7 3. - 0 - <_> - - <_> - 1 18 10 6 -1. - <_> - 1 18 5 3 2. - <_> - 6 21 5 3 2. - 0 - <_> - - <_> - 1 18 9 3 -1. - <_> - 1 19 9 1 3. - 0 - <_> - - <_> - 1 21 12 3 -1. - <_> - 7 21 6 3 2. - 0 - <_> - - <_> - 2 0 3 2 -1. - <_> - 3 0 1 2 3. + 2 18 1 6 3. 0 <_> @@ -6999,55 +7506,27 @@ <_> <_> - 2 0 9 2 -1. + 2 0 8 6 -1. <_> - 5 0 3 2 3. + 2 0 4 3 2. + <_> + 6 3 4 3 2. 0 <_> <_> - 2 0 21 1 -1. + 2 0 12 5 -1. <_> - 9 0 7 1 3. + 8 0 6 5 2. 0 <_> <_> - 2 1 3 23 -1. + 2 3 20 2 -1. <_> - 3 1 1 23 3. - 0 - <_> - + 2 3 10 1 2. <_> - 2 1 4 2 -1. - <_> - 4 1 2 2 2. - 0 - <_> - - <_> - 2 2 22 10 -1. - <_> - 2 2 11 5 2. - <_> - 13 7 11 5 2. - 0 - <_> - - <_> - 2 3 22 2 -1. - <_> - 2 3 11 1 2. - <_> - 13 4 11 1 2. - 0 - <_> - - <_> - 2 4 6 1 -1. - <_> - 5 4 3 1 2. + 12 4 10 1 2. 0 <_> @@ -7068,39 +7547,25 @@ <_> <_> - 2 4 22 16 -1. + 2 5 1 3 -1. <_> - 13 4 11 16 2. + 2 6 1 1 3. 0 <_> <_> - 2 4 18 6 -1. + 2 5 2 3 -1. <_> - 2 6 18 2 3. + 2 6 2 1 3. 0 <_> <_> - 2 6 3 3 -1. + 2 5 20 2 -1. <_> - 2 7 3 1 3. - 0 - <_> - + 2 5 10 1 2. <_> - 2 6 4 3 -1. - <_> - 2 7 4 1 3. - 0 - <_> - - <_> - 2 6 20 2 -1. - <_> - 2 6 10 1 2. - <_> - 12 7 10 1 2. + 12 6 10 1 2. 0 <_> @@ -7114,101 +7579,43 @@ <_> <_> - 2 7 21 6 -1. + 2 6 22 4 -1. <_> - 2 9 21 2 3. + 2 6 11 2 2. + <_> + 13 8 11 2 2. 0 <_> <_> - 2 7 22 2 -1. + 2 7 15 3 -1. <_> - 2 8 22 1 2. + 2 8 15 1 3. 0 <_> <_> - 2 8 6 2 -1. + 2 8 8 3 -1. <_> - 2 8 3 1 2. - <_> - 5 9 3 1 2. + 2 9 8 1 3. 0 <_> <_> - 2 8 6 3 -1. + 2 8 20 4 -1. <_> - 2 9 6 1 3. + 2 8 10 2 2. + <_> + 12 10 10 2 2. 0 <_> <_> - 2 8 21 2 -1. + 2 9 20 8 -1. <_> - 9 8 7 2 3. - 0 - <_> - + 2 9 10 4 2. <_> - 2 8 7 9 -1. - <_> - 2 11 7 3 3. - 0 - <_> - - <_> - 2 8 22 4 -1. - <_> - 2 8 11 2 2. - <_> - 13 10 11 2 2. - 0 - <_> - - <_> - 2 9 4 1 -1. - <_> - 4 9 2 1 2. - 0 - <_> - - <_> - 2 9 9 1 -1. - <_> - 5 9 3 1 3. - 0 - <_> - - <_> - 2 9 9 2 -1. - <_> - 5 9 3 2 3. - 0 - <_> - - <_> - 2 9 6 4 -1. - <_> - 2 9 3 2 2. - <_> - 5 11 3 2 2. - 0 - <_> - - <_> - 2 9 7 3 -1. - <_> - 2 10 7 1 3. - 0 - <_> - - <_> - 2 9 18 2 -1. - <_> - 2 9 9 1 2. - <_> - 11 10 9 1 2. + 12 13 10 4 2. 0 <_> @@ -7222,9 +7629,16 @@ <_> <_> - 2 9 21 3 -1. + 2 9 19 3 -1. <_> - 2 10 21 1 3. + 2 10 19 1 3. + 0 + <_> + + <_> + 2 10 4 1 -1. + <_> + 4 10 2 1 2. 0 <_> @@ -7238,16 +7652,32 @@ <_> <_> - 2 11 3 6 -1. + 2 10 22 14 -1. <_> - 3 11 1 6 3. + 13 10 11 14 2. 0 <_> <_> - 2 11 3 13 -1. + 2 10 20 12 -1. <_> - 3 11 1 13 3. + 2 16 20 6 2. + 0 + <_> + + <_> + 2 11 3 5 -1. + <_> + 3 11 1 5 3. + 0 + <_> + + <_> + 2 11 20 2 -1. + <_> + 2 11 10 1 2. + <_> + 12 12 10 1 2. 0 <_> @@ -7258,13 +7688,6 @@ <_> 13 12 11 1 2. 0 - <_> - - <_> - 2 12 3 4 -1. - <_> - 3 12 1 4 3. - 0 <_> <_> @@ -7275,82 +7698,95 @@ <_> <_> - 2 12 22 2 -1. + 2 12 3 9 -1. <_> - 2 12 11 1 2. - <_> - 13 13 11 1 2. + 3 12 1 9 3. 0 <_> <_> - 2 13 10 10 -1. + 2 12 3 11 -1. <_> - 2 13 5 5 2. - <_> - 7 18 5 5 2. + 3 12 1 11 3. 0 <_> <_> - 2 14 6 10 -1. + 2 14 3 3 -1. <_> - 2 14 3 5 2. - <_> - 5 19 3 5 2. + 3 14 1 3 3. 0 <_> <_> - 2 15 2 6 -1. + 2 14 8 8 -1. <_> - 2 15 1 3 2. + 2 14 4 4 2. <_> - 3 18 1 3 2. + 6 18 4 4 2. 0 <_> <_> - 2 15 3 9 -1. + 2 17 3 5 -1. <_> - 3 15 1 9 3. + 3 17 1 5 3. 0 <_> <_> - 2 15 6 4 -1. + 2 17 3 6 -1. <_> - 5 15 3 4 2. + 3 17 1 6 3. 0 <_> <_> - 2 15 7 3 -1. + 2 17 21 4 -1. <_> - 2 16 7 1 3. + 9 17 7 4 3. 0 <_> <_> - 2 17 3 4 -1. + 2 18 3 5 -1. <_> - 3 17 1 4 3. + 3 18 1 5 3. 0 <_> <_> - 2 17 12 6 -1. + 2 18 10 4 -1. <_> - 2 17 6 3 2. - <_> - 8 20 6 3 2. + 7 18 5 4 2. 0 <_> <_> - 2 21 14 3 -1. + 2 20 6 2 -1. <_> - 9 21 7 3 2. + 5 20 3 2 2. + 0 + <_> + + <_> + 2 21 12 2 -1. + <_> + 8 21 6 2 2. + 0 + <_> + + <_> + 3 0 3 5 -1. + <_> + 4 0 1 5 3. + 0 + <_> + + <_> + 3 0 9 22 -1. + <_> + 6 0 3 22 3. 0 <_> @@ -7364,18 +7800,30 @@ <_> <_> - 3 1 18 2 -1. + 3 1 3 3 -1. <_> - 3 1 9 1 2. - <_> - 12 2 9 1 2. + 4 1 1 3 3. 0 <_> <_> - 3 2 17 6 -1. + 3 1 3 20 -1. <_> - 3 5 17 3 2. + 4 1 1 20 3. + 0 + <_> + + <_> + 3 1 6 20 -1. + <_> + 5 1 2 20 3. + 0 + <_> + + <_> + 3 2 3 3 -1. + <_> + 4 2 1 3 3. 0 <_> @@ -7387,11 +7835,23 @@ <_> <_> - 3 3 18 2 -1. + 3 3 3 9 -1. <_> - 3 3 9 1 2. + 3 6 3 3 3. + 0 + <_> + <_> - 12 4 9 1 2. + 3 3 20 19 -1. + <_> + 13 3 10 19 2. + 0 + <_> + + <_> + 3 3 19 4 -1. + <_> + 3 5 19 2 2. 0 <_> @@ -7403,18 +7863,9 @@ <_> <_> - 3 4 2 2 -1. + 3 4 6 3 -1. <_> - 3 4 1 1 2. - <_> - 4 5 1 1 2. - 0 - <_> - - <_> - 3 4 3 3 -1. - <_> - 3 5 3 1 3. + 5 4 2 3 3. 0 <_> @@ -7428,39 +7879,23 @@ <_> <_> - 3 4 18 4 -1. + 3 4 16 6 -1. <_> - 3 4 9 2 2. - <_> - 12 6 9 2 2. + 3 6 16 2 3. 0 <_> <_> - 3 4 20 6 -1. + 3 5 3 1 -1. <_> - 3 6 20 2 3. + 4 5 1 1 3. 0 <_> <_> - 3 5 2 1 -1. + 3 5 3 2 -1. <_> - 4 5 1 1 2. - 0 - <_> - - <_> - 3 5 1 3 -1. - <_> - 3 6 1 1 3. - 0 - <_> - - <_> - 3 5 2 2 -1. - <_> - 3 6 2 1 2. + 4 5 1 2 3. 0 <_> @@ -7472,62 +7907,53 @@ <_> <_> - 3 5 20 2 -1. + 3 5 10 3 -1. <_> - 3 5 10 1 2. - <_> - 13 6 10 1 2. + 8 5 5 3 2. 0 <_> <_> - 3 5 17 6 -1. + 3 5 18 3 -1. <_> - 3 7 17 2 3. + 9 5 6 3 3. 0 <_> <_> - 3 5 17 9 -1. + 3 5 18 2 -1. <_> - 3 8 17 3 3. + 3 5 9 1 2. + <_> + 12 6 9 1 2. 0 <_> <_> - 3 5 19 9 -1. + 3 6 2 1 -1. <_> - 3 8 19 3 3. + 4 6 1 1 2. 0 <_> <_> - 3 6 2 2 -1. + 3 6 1 3 -1. <_> - 3 6 1 1 2. - <_> - 4 7 1 1 2. + 3 7 1 1 3. 0 <_> <_> - 3 6 2 3 -1. + 3 6 3 3 -1. <_> - 3 7 2 1 3. + 3 7 3 1 3. 0 <_> <_> - 3 6 9 6 -1. + 3 6 6 6 -1. <_> - 6 6 3 6 3. - 0 - <_> - - <_> - 3 6 5 6 -1. - <_> - 3 8 5 2 3. + 3 8 6 2 3. 0 <_> @@ -7541,41 +7967,30 @@ <_> <_> - 3 6 20 8 -1. + 3 6 17 6 -1. <_> - 3 6 10 4 2. - <_> - 13 10 10 4 2. + 3 8 17 2 3. 0 <_> <_> - 3 6 18 3 -1. + 3 7 3 1 -1. <_> - 3 7 18 1 3. + 4 7 1 1 3. 0 <_> <_> - 3 7 6 10 -1. + 3 7 4 2 -1. <_> - 3 7 3 5 2. - <_> - 6 12 3 5 2. + 3 8 4 1 2. 0 <_> <_> - 3 7 5 2 -1. + 3 7 6 6 -1. <_> - 3 8 5 1 2. - 0 - <_> - - <_> - 3 7 6 3 -1. - <_> - 3 8 6 1 3. + 3 9 6 2 3. 0 <_> @@ -7589,37 +8004,16 @@ <_> <_> - 3 7 17 3 -1. + 3 7 20 11 -1. <_> - 3 8 17 1 3. + 13 7 10 11 2. 0 <_> <_> - 3 7 18 2 -1. + 3 7 17 6 -1. <_> - 3 8 18 1 2. - 0 - <_> - - <_> - 3 8 2 3 -1. - <_> - 4 8 1 3 2. - 0 - <_> - - <_> - 3 8 18 3 -1. - <_> - 3 9 18 1 3. - 0 - <_> - - <_> - 3 8 20 3 -1. - <_> - 3 9 20 1 3. + 3 9 17 2 3. 0 <_> @@ -7638,64 +8032,53 @@ <_> <_> - 3 9 4 6 -1. + 3 9 9 2 -1. <_> - 3 9 2 3 2. - <_> - 5 12 2 3 2. + 6 9 3 2 3. 0 <_> <_> - 3 9 6 4 -1. + 3 9 18 2 -1. <_> - 3 11 6 2 2. + 3 9 9 1 2. + <_> + 12 10 9 1 2. 0 <_> <_> - 3 9 8 9 -1. + 3 10 3 1 -1. <_> - 3 12 8 3 3. + 4 10 1 1 3. 0 <_> <_> - 3 9 20 2 -1. + 3 10 3 13 -1. <_> - 3 9 10 1 2. - <_> - 13 10 10 1 2. + 4 10 1 13 3. 0 <_> <_> - 3 9 19 3 -1. + 3 10 6 2 -1. <_> - 3 10 19 1 3. + 3 11 6 1 2. 0 <_> <_> - 3 10 4 2 -1. + 3 11 3 2 -1. <_> - 3 10 2 1 2. - <_> - 5 11 2 1 2. + 4 11 1 2 3. 0 <_> <_> - 3 10 18 6 -1. + 3 11 3 3 -1. <_> - 3 12 18 2 3. - 0 - <_> - - <_> - 3 11 3 4 -1. - <_> - 4 11 1 4 3. + 4 11 1 3 3. 0 <_> @@ -7707,30 +8090,39 @@ <_> <_> - 3 11 4 10 -1. + 3 11 3 13 -1. <_> - 3 16 4 5 2. + 4 11 1 13 3. 0 <_> <_> - 3 11 7 8 -1. + 3 11 6 2 -1. <_> - 3 15 7 4 2. + 3 11 3 1 2. + <_> + 6 12 3 1 2. 0 <_> <_> - 3 12 3 2 -1. + 3 11 3 4 -1. <_> - 4 12 1 2 3. + 3 13 3 2 2. 0 <_> <_> - 3 12 3 10 -1. + 3 11 4 8 -1. <_> - 4 12 1 10 3. + 3 15 4 4 2. + 0 + <_> + + <_> + 3 12 3 3 -1. + <_> + 4 12 1 3 3. 0 <_> @@ -7739,6 +8131,13 @@ <_> 3 15 3 3 2. 0 + <_> + + <_> + 3 12 9 7 -1. + <_> + 6 12 3 7 3. + 0 <_> <_> @@ -7749,169 +8148,230 @@ <_> <_> - 3 12 10 8 -1. + 3 12 8 8 -1. <_> - 3 12 5 4 2. - <_> - 8 16 5 4 2. + 3 16 8 4 2. 0 <_> <_> - 3 12 18 2 -1. + 3 12 19 6 -1. <_> - 3 12 9 1 2. - <_> - 12 13 9 1 2. + 3 15 19 3 2. 0 <_> <_> - 3 13 19 6 -1. + 3 13 18 2 -1. <_> - 3 16 19 3 2. + 3 13 9 1 2. + <_> + 12 14 9 1 2. 0 <_> <_> - 3 14 4 9 -1. + 3 15 4 2 -1. <_> - 3 17 4 3 3. + 5 15 2 2 2. 0 <_> <_> - 3 16 3 4 -1. + 3 15 4 3 -1. <_> - 4 16 1 4 3. + 5 15 2 3 2. 0 <_> <_> - 3 16 4 3 -1. + 3 15 6 2 -1. <_> - 5 16 2 3 2. + 6 15 3 2 2. 0 <_> <_> - 3 16 21 7 -1. + 3 16 8 8 -1. <_> - 10 16 7 7 3. + 3 16 4 4 2. + <_> + 7 20 4 4 2. 0 <_> <_> - 3 18 3 6 -1. + 3 20 3 4 -1. <_> - 4 18 1 6 3. + 4 20 1 4 3. 0 <_> <_> - 4 0 3 23 -1. + 4 1 3 8 -1. <_> - 5 0 1 23 3. + 5 1 1 8 3. 0 <_> <_> - 4 0 6 5 -1. + 4 1 3 12 -1. <_> - 6 0 2 5 3. + 4 5 3 4 3. 0 <_> <_> - 4 0 17 12 -1. + 4 1 15 10 -1. <_> - 4 4 17 4 3. + 4 6 15 5 2. 0 <_> <_> - 4 1 16 12 -1. + 4 2 3 3 -1. <_> - 4 7 16 6 2. + 5 2 1 3 3. 0 <_> <_> - 4 3 3 1 -1. + 4 2 6 5 -1. <_> - 5 3 1 1 3. + 6 2 2 5 3. 0 <_> <_> - 4 3 16 10 -1. + 4 2 16 2 -1. <_> - 4 3 8 5 2. + 4 2 8 1 2. <_> - 12 8 8 5 2. + 12 3 8 1 2. 0 <_> <_> - 4 3 14 6 -1. + 4 3 3 2 -1. <_> - 4 6 14 3 2. + 5 3 1 2 3. 0 <_> <_> - 4 4 1 3 -1. + 4 3 6 1 -1. <_> - 4 5 1 1 3. + 6 3 2 1 3. 0 <_> <_> - 4 4 2 4 -1. + 4 3 6 5 -1. <_> - 4 6 2 2 2. + 6 3 2 5 3. 0 <_> <_> - 4 4 6 2 -1. + 4 3 9 3 -1. <_> - 7 4 3 2 2. + 7 3 3 3 3. 0 <_> <_> - 4 4 13 6 -1. + 4 3 16 2 -1. <_> - 4 7 13 3 2. + 4 3 8 1 2. + <_> + 12 4 8 1 2. 0 <_> <_> - 4 5 6 4 -1. + 4 3 16 8 -1. <_> - 6 5 2 4 3. + 4 3 8 4 2. + <_> + 12 7 8 4 2. 0 <_> <_> - 4 5 14 6 -1. + 4 3 17 8 -1. <_> - 4 7 14 2 3. + 4 7 17 4 2. 0 <_> <_> - 4 5 16 6 -1. + 4 4 1 4 -1. <_> - 4 8 16 3 2. + 4 6 1 2 2. 0 <_> <_> - 4 6 1 3 -1. + 4 4 16 2 -1. <_> - 4 7 1 1 3. + 4 4 8 1 2. + <_> + 12 5 8 1 2. + 0 + <_> + + <_> + 4 4 16 10 -1. + <_> + 4 4 8 5 2. + <_> + 12 9 8 5 2. + 0 + <_> + + <_> + 4 4 20 6 -1. + <_> + 4 6 20 2 3. + 0 + <_> + + <_> + 4 5 16 2 -1. + <_> + 4 5 8 1 2. + <_> + 12 6 8 1 2. + 0 + <_> + + <_> + 4 5 16 9 -1. + <_> + 4 8 16 3 3. + 0 + <_> + + <_> + 4 6 2 2 -1. + <_> + 4 6 1 1 2. + <_> + 5 7 1 1 2. + 0 + <_> + + <_> + 4 6 2 2 -1. + <_> + 4 7 2 1 2. + 0 + <_> + + <_> + 4 6 6 1 -1. + <_> + 6 6 2 1 3. 0 <_> @@ -7939,18 +8399,9 @@ <_> <_> - 4 6 16 6 -1. + 4 6 15 6 -1. <_> - 4 6 8 3 2. - <_> - 12 9 8 3 2. - 0 - <_> - - <_> - 4 6 10 8 -1. - <_> - 4 10 10 4 2. + 4 8 15 2 3. 0 <_> @@ -7959,6 +8410,27 @@ <_> 4 8 2 1 3. 0 + <_> + + <_> + 4 7 4 3 -1. + <_> + 6 7 2 3 2. + 0 + <_> + + <_> + 4 7 4 3 -1. + <_> + 4 8 4 1 3. + 0 + <_> + + <_> + 4 7 5 3 -1. + <_> + 4 8 5 1 3. + 0 <_> <_> @@ -7969,11 +8441,9 @@ <_> <_> - 4 7 16 4 -1. + 4 7 7 3 -1. <_> - 4 7 8 2 2. - <_> - 12 9 8 2 2. + 4 8 7 1 3. 0 <_> @@ -7984,6 +8454,22 @@ <_> 13 8 9 1 2. 0 + <_> + + <_> + 4 7 18 4 -1. + <_> + 4 7 9 2 2. + <_> + 13 9 9 2 2. + 0 + <_> + + <_> + 4 7 16 3 -1. + <_> + 4 8 16 1 3. + 0 <_> <_> @@ -7991,6 +8477,20 @@ <_> 4 9 16 2 3. 0 + <_> + + <_> + 4 7 17 2 -1. + <_> + 4 8 17 1 2. + 0 + <_> + + <_> + 4 7 17 3 -1. + <_> + 4 8 17 1 3. + 0 <_> <_> @@ -8019,18 +8519,11 @@ <_> <_> - 4 8 16 4 -1. + 4 8 18 4 -1. <_> - 4 8 8 2 2. + 4 8 9 2 2. <_> - 12 10 8 2 2. - 0 - <_> - - <_> - 4 8 15 6 -1. - <_> - 4 10 15 2 3. + 13 10 9 2 2. 0 <_> @@ -8049,18 +8542,18 @@ <_> <_> - 4 9 3 2 -1. + 4 9 2 2 -1. <_> - 5 9 1 2 3. + 4 9 1 1 2. + <_> + 5 10 1 1 2. 0 <_> <_> - 4 9 2 4 -1. + 4 9 2 2 -1. <_> - 4 9 1 2 2. - <_> - 5 11 1 2 2. + 5 9 1 2 2. 0 <_> @@ -8072,18 +8565,16 @@ <_> <_> - 4 9 2 6 -1. + 4 9 2 9 -1. <_> - 4 11 2 2 3. + 4 12 2 3 3. 0 <_> <_> - 4 9 8 6 -1. + 4 9 15 1 -1. <_> - 4 9 4 3 2. - <_> - 8 12 4 3 2. + 9 9 5 1 3. 0 <_> @@ -8102,9 +8593,9 @@ <_> <_> - 4 9 15 4 -1. + 4 9 15 3 -1. <_> - 9 9 5 4 3. + 9 9 5 3 3. 0 <_> @@ -8115,6 +8606,15 @@ <_> 12 10 8 1 2. 0 + <_> + + <_> + 4 9 16 6 -1. + <_> + 4 9 8 3 2. + <_> + 12 12 8 3 2. + 0 <_> <_> @@ -8127,9 +8627,11 @@ <_> <_> - 4 9 15 15 -1. + 4 9 20 2 -1. <_> - 4 14 15 5 3. + 4 9 10 1 2. + <_> + 14 10 10 1 2. 0 <_> @@ -8141,9 +8643,9 @@ <_> <_> - 4 9 20 6 -1. + 4 9 18 3 -1. <_> - 4 11 20 2 3. + 4 10 18 1 3. 0 <_> @@ -8171,18 +8673,25 @@ <_> <_> - 4 10 3 5 -1. + 4 10 6 3 -1. <_> - 5 10 1 5 3. + 7 10 3 3 2. 0 <_> <_> - 4 10 16 10 -1. + 4 10 18 2 -1. <_> - 4 10 8 5 2. + 4 10 9 1 2. <_> - 12 15 8 5 2. + 13 11 9 1 2. + 0 + <_> + + <_> + 4 10 17 6 -1. + <_> + 4 12 17 2 3. 0 <_> @@ -8201,25 +8710,30 @@ <_> <_> - 4 11 3 5 -1. + 4 11 1 8 -1. <_> - 5 11 1 5 3. + 4 15 1 4 2. 0 <_> <_> - 4 11 3 10 -1. + 4 11 3 6 -1. <_> - 4 16 3 5 2. + 5 11 1 6 3. 0 <_> <_> - 4 11 16 2 -1. + 4 11 6 3 -1. <_> - 4 11 8 1 2. + 6 11 2 3 3. + 0 + <_> + <_> - 12 12 8 1 2. + 4 11 15 2 -1. + <_> + 4 12 15 1 2. 0 <_> @@ -8228,20 +8742,6 @@ <_> 5 12 1 1 3. 0 - <_> - - <_> - 4 12 3 2 -1. - <_> - 5 12 1 2 3. - 0 - <_> - - <_> - 4 12 1 6 -1. - <_> - 4 15 1 3 2. - 0 <_> <_> @@ -8252,23 +8752,30 @@ <_> <_> - 4 12 4 4 -1. + 4 12 3 8 -1. <_> - 4 14 4 2 2. + 4 16 3 4 2. 0 <_> <_> - 4 12 18 8 -1. + 4 12 17 12 -1. <_> - 13 12 9 8 2. + 4 16 17 4 3. 0 <_> <_> - 4 13 9 5 -1. + 4 13 3 1 -1. <_> - 7 13 3 5 3. + 5 13 1 1 3. + 0 + <_> + + <_> + 4 13 3 9 -1. + <_> + 4 16 3 3 3. 0 <_> @@ -8280,30 +8787,69 @@ <_> <_> - 4 16 4 1 -1. + 4 15 4 2 -1. <_> - 6 16 2 1 2. + 6 15 2 2 2. 0 <_> <_> - 4 16 9 2 -1. + 4 15 9 4 -1. <_> - 7 16 3 2 3. + 7 15 3 4 3. 0 <_> <_> - 4 19 3 4 -1. + 4 15 16 4 -1. <_> - 5 19 1 4 3. + 4 15 8 2 2. + <_> + 12 17 8 2 2. 0 <_> <_> - 4 22 12 2 -1. + 4 18 3 5 -1. <_> - 4 23 12 1 2. + 5 18 1 5 3. + 0 + <_> + + <_> + 4 18 3 6 -1. + <_> + 5 18 1 6 3. + 0 + <_> + + <_> + 4 18 15 5 -1. + <_> + 9 18 5 5 3. + 0 + <_> + + <_> + 4 18 9 6 -1. + <_> + 4 21 9 3 2. + 0 + <_> + + <_> + 5 1 14 2 -1. + <_> + 5 1 7 1 2. + <_> + 12 2 7 1 2. + 0 + <_> + + <_> + 5 1 11 8 -1. + <_> + 5 5 11 4 2. 0 <_> @@ -8315,18 +8861,9 @@ <_> <_> - 5 2 4 12 -1. + 5 2 6 2 -1. <_> - 5 2 2 6 2. - <_> - 7 8 2 6 2. - 0 - <_> - - <_> - 5 2 4 12 -1. - <_> - 7 2 2 12 2. + 7 2 2 2 3. 0 <_> @@ -8337,6 +8874,13 @@ <_> 12 3 7 1 2. 0 + <_> + + <_> + 5 2 14 8 -1. + <_> + 5 6 14 4 2. + 0 <_> <_> @@ -8344,6 +8888,13 @@ <_> 5 7 16 5 2. 0 + <_> + + <_> + 5 3 6 1 -1. + <_> + 7 3 2 1 3. + 0 <_> <_> @@ -8351,6 +8902,22 @@ <_> 7 3 2 2 3. 0 + <_> + + <_> + 5 3 4 10 -1. + <_> + 5 3 2 5 2. + <_> + 7 8 2 5 2. + 0 + <_> + + <_> + 5 3 9 12 -1. + <_> + 8 3 3 12 3. + 0 <_> <_> @@ -8363,9 +8930,39 @@ <_> <_> - 5 4 5 3 -1. + 5 3 15 8 -1. <_> - 5 5 5 1 3. + 5 7 15 4 2. + 0 + <_> + + <_> + 5 4 2 4 -1. + <_> + 5 4 1 2 2. + <_> + 6 6 1 2 2. + 0 + <_> + + <_> + 5 4 6 4 -1. + <_> + 7 4 2 4 3. + 0 + <_> + + <_> + 5 4 4 12 -1. + <_> + 7 4 2 12 2. + 0 + <_> + + <_> + 5 4 12 8 -1. + <_> + 9 4 4 8 3. 0 <_> @@ -8376,15 +8973,6 @@ <_> 12 5 7 1 2. 0 - <_> - - <_> - 5 4 16 18 -1. - <_> - 5 4 8 9 2. - <_> - 13 13 8 9 2. - 0 <_> <_> @@ -8394,6 +8982,22 @@ <_> 6 6 1 1 2. 0 + <_> + + <_> + 5 5 2 4 -1. + <_> + 5 5 1 2 2. + <_> + 6 7 1 2 2. + 0 + <_> + + <_> + 5 5 6 6 -1. + <_> + 5 7 6 2 3. + 0 <_> <_> @@ -8403,6 +9007,22 @@ <_> 12 6 7 1 2. 0 + <_> + + <_> + 5 5 16 2 -1. + <_> + 5 5 8 1 2. + <_> + 13 6 8 1 2. + 0 + <_> + + <_> + 5 5 13 6 -1. + <_> + 5 7 13 2 3. + 0 <_> <_> @@ -8410,6 +9030,50 @@ <_> 5 7 14 2 3. 0 + <_> + + <_> + 5 5 15 6 -1. + <_> + 5 7 15 2 3. + 0 + <_> + + <_> + 5 5 15 9 -1. + <_> + 5 8 15 3 3. + 0 + <_> + + <_> + 5 6 1 2 -1. + <_> + 5 7 1 1 2. + 0 + <_> + + <_> + 5 6 2 4 -1. + <_> + 5 6 1 2 2. + <_> + 6 8 1 2 2. + 0 + <_> + + <_> + 5 6 6 1 -1. + <_> + 7 6 2 1 3. + 0 + <_> + + <_> + 5 6 4 3 -1. + <_> + 5 7 4 1 3. + 0 <_> <_> @@ -8422,23 +9086,32 @@ <_> <_> - 5 6 19 6 -1. + 5 7 2 2 -1. <_> - 5 8 19 2 3. + 6 7 1 2 2. 0 <_> <_> - 5 7 1 3 -1. + 5 7 2 6 -1. <_> - 5 8 1 1 3. + 5 7 1 3 2. + <_> + 6 10 1 3 2. 0 <_> <_> - 5 7 4 6 -1. + 5 7 4 1 -1. <_> - 7 7 2 6 2. + 7 7 2 1 2. + 0 + <_> + + <_> + 5 7 6 5 -1. + <_> + 7 7 2 5 3. 0 <_> @@ -8447,6 +9120,20 @@ <_> 5 8 3 1 2. 0 + <_> + + <_> + 5 7 3 3 -1. + <_> + 5 8 3 1 3. + 0 + <_> + + <_> + 5 7 3 6 -1. + <_> + 5 9 3 2 3. + 0 <_> <_> @@ -8464,18 +9151,18 @@ <_> <_> - 5 7 5 2 -1. + 5 7 5 6 -1. <_> - 5 8 5 1 2. + 5 9 5 2 3. 0 <_> <_> - 5 7 14 10 -1. + 5 7 14 4 -1. <_> - 5 7 7 5 2. + 5 7 7 2 2. <_> - 12 12 7 5 2. + 12 9 7 2 2. 0 <_> @@ -8487,9 +9174,16 @@ <_> <_> - 5 7 15 4 -1. + 5 7 14 4 -1. <_> - 5 9 15 2 2. + 5 9 14 2 2. + 0 + <_> + + <_> + 5 7 15 2 -1. + <_> + 5 8 15 1 2. 0 <_> @@ -8498,20 +9192,6 @@ <_> 5 9 15 2 3. 0 - <_> - - <_> - 5 7 16 2 -1. - <_> - 5 8 16 1 2. - 0 - <_> - - <_> - 5 7 16 6 -1. - <_> - 5 9 16 2 3. - 0 <_> <_> @@ -8522,46 +9202,64 @@ <_> <_> - 5 8 2 4 -1. + 5 8 2 2 -1. <_> - 5 8 1 2 2. + 5 8 1 1 2. <_> - 6 10 1 2 2. + 6 9 1 1 2. 0 <_> <_> - 5 8 3 2 -1. + 5 8 4 5 -1. <_> - 5 9 3 1 2. + 7 8 2 5 2. 0 <_> <_> - 5 9 3 1 -1. + 5 8 12 4 -1. <_> - 6 9 1 1 3. + 9 8 4 4 3. 0 <_> <_> - 5 9 1 3 -1. + 5 8 15 3 -1. <_> - 5 10 1 1 3. + 10 8 5 3 3. 0 <_> <_> - 5 9 1 9 -1. + 5 8 14 4 -1. <_> - 5 12 1 3 3. + 5 8 7 2 2. + <_> + 12 10 7 2 2. 0 <_> <_> - 5 9 8 1 -1. + 5 9 4 4 -1. <_> - 9 9 4 1 2. + 7 9 2 4 2. + 0 + <_> + + <_> + 5 9 4 3 -1. + <_> + 5 10 4 1 3. + 0 + <_> + + <_> + 5 9 8 8 -1. + <_> + 5 9 4 4 2. + <_> + 9 13 4 4 2. 0 <_> @@ -8582,20 +9280,34 @@ <_> <_> - 5 9 14 8 -1. + 5 9 14 12 -1. <_> - 5 9 7 4 2. + 5 9 7 6 2. <_> - 12 13 7 4 2. + 12 15 7 6 2. 0 <_> <_> - 5 9 16 2 -1. + 5 9 18 2 -1. <_> - 5 9 8 1 2. + 5 9 9 1 2. <_> - 13 10 8 1 2. + 14 10 9 1 2. + 0 + <_> + + <_> + 5 9 13 3 -1. + <_> + 5 10 13 1 3. + 0 + <_> + + <_> + 5 9 15 6 -1. + <_> + 5 12 15 3 2. 0 <_> @@ -8609,9 +9321,9 @@ <_> <_> - 5 10 15 1 -1. + 5 10 3 3 -1. <_> - 10 10 5 1 3. + 6 10 1 3 3. 0 <_> @@ -8620,6 +9332,20 @@ <_> 6 11 1 2 3. 0 + <_> + + <_> + 5 11 3 3 -1. + <_> + 6 11 1 3 3. + 0 + <_> + + <_> + 5 11 3 13 -1. + <_> + 6 11 1 13 3. + 0 <_> <_> @@ -8630,39 +9356,37 @@ <_> <_> - 5 12 17 2 -1. + 5 12 1 6 -1. <_> - 5 13 17 1 2. + 5 15 1 3 2. 0 <_> <_> - 5 13 4 6 -1. + 5 13 15 8 -1. <_> - 5 13 2 3 2. - <_> - 7 16 2 3 2. + 5 17 15 4 2. 0 <_> <_> - 5 13 18 10 -1. + 5 14 3 3 -1. <_> - 14 13 9 10 2. + 5 15 3 1 3. 0 <_> <_> - 5 15 9 3 -1. + 5 15 2 2 -1. <_> - 8 15 3 3 3. + 6 15 1 2 2. 0 <_> <_> - 5 17 3 7 -1. + 5 19 3 5 -1. <_> - 6 17 1 7 3. + 6 19 1 5 3. 0 <_> @@ -8674,44 +9398,44 @@ <_> <_> - 6 0 3 6 -1. + 6 0 1 6 -1. <_> - 6 3 3 3 2. + 6 3 1 3 2. 0 <_> <_> - 6 0 12 2 -1. + 6 0 11 10 -1. <_> - 12 0 6 2 2. + 6 5 11 5 2. 0 <_> <_> - 6 0 14 12 -1. + 6 1 6 12 -1. <_> - 6 6 14 6 2. + 8 1 2 12 3. 0 <_> <_> - 6 1 6 7 -1. + 6 2 3 6 -1. <_> - 8 1 2 7 3. + 7 2 1 6 3. 0 <_> <_> - 6 1 6 11 -1. + 6 2 6 2 -1. <_> - 8 1 2 11 3. + 8 2 2 2 3. 0 <_> <_> - 6 2 6 12 -1. + 6 2 6 10 -1. <_> - 8 2 2 12 3. + 8 2 2 10 3. 0 <_> @@ -8723,25 +9447,16 @@ <_> <_> - 6 3 2 2 -1. + 6 3 6 4 -1. <_> - 6 4 2 1 2. + 8 3 2 4 3. 0 <_> <_> - 6 3 14 18 -1. + 6 3 9 1 -1. <_> - 6 3 7 9 2. - <_> - 13 12 7 9 2. - 0 - <_> - - <_> - 6 4 1 2 -1. - <_> - 6 5 1 1 2. + 9 3 3 1 3. 0 <_> @@ -8753,9 +9468,23 @@ <_> <_> - 6 5 2 1 -1. + 6 4 6 4 -1. <_> - 7 5 1 1 2. + 8 4 2 4 3. + 0 + <_> + + <_> + 6 5 3 2 -1. + <_> + 7 5 1 2 3. + 0 + <_> + + <_> + 6 5 3 3 -1. + <_> + 7 5 1 3 3. 0 <_> @@ -8776,39 +9505,18 @@ <_> <_> - 6 5 12 6 -1. + 6 6 4 1 -1. <_> - 6 7 12 2 3. + 8 6 2 1 2. 0 <_> <_> - 6 6 10 2 -1. + 6 6 12 2 -1. <_> - 6 6 5 1 2. + 6 6 6 1 2. <_> - 11 7 5 1 2. - 0 - <_> - - <_> - 6 6 12 6 -1. - <_> - 6 8 12 2 3. - 0 - <_> - - <_> - 6 6 14 4 -1. - <_> - 6 8 14 2 2. - 0 - <_> - - <_> - 6 7 1 3 -1. - <_> - 6 8 1 1 3. + 12 7 6 1 2. 0 <_> @@ -8817,6 +9525,13 @@ <_> 6 9 1 2 3. 0 + <_> + + <_> + 6 7 2 2 -1. + <_> + 6 8 2 1 2. + 0 <_> <_> @@ -8841,23 +9556,39 @@ <_> <_> - 6 8 2 4 -1. + 6 7 12 2 -1. <_> - 7 8 1 4 2. + 6 7 6 1 2. + <_> + 12 8 6 1 2. 0 <_> <_> - 6 8 2 3 -1. + 6 7 8 12 -1. <_> - 6 9 2 1 3. + 6 13 8 6 2. 0 <_> <_> - 6 8 9 6 -1. + 6 7 12 15 -1. <_> - 9 8 3 6 3. + 6 12 12 5 3. + 0 + <_> + + <_> + 6 8 2 6 -1. + <_> + 6 11 2 3 2. + 0 + <_> + + <_> + 6 8 3 2 -1. + <_> + 6 9 3 1 2. 0 <_> @@ -8878,16 +9609,23 @@ <_> <_> - 6 8 8 12 -1. + 6 9 2 2 -1. <_> - 6 14 8 6 2. + 6 10 2 1 2. 0 <_> <_> - 6 9 2 6 -1. + 6 9 2 3 -1. <_> - 6 11 2 2 3. + 6 10 2 1 3. + 0 + <_> + + <_> + 6 9 6 1 -1. + <_> + 9 9 3 1 2. 0 <_> @@ -8896,36 +9634,6 @@ <_> 6 10 3 1 3. 0 - <_> - - <_> - 6 9 3 6 -1. - <_> - 6 12 3 3 2. - 0 - <_> - - <_> - 6 9 6 6 -1. - <_> - 6 9 3 3 2. - <_> - 9 12 3 3 2. - 0 - <_> - - <_> - 6 9 12 2 -1. - <_> - 10 9 4 2 3. - 0 - <_> - - <_> - 6 9 12 3 -1. - <_> - 10 9 4 3 3. - 0 <_> <_> @@ -8938,11 +9646,9 @@ <_> <_> - 6 9 14 2 -1. + 6 9 13 12 -1. <_> - 6 9 7 1 2. - <_> - 13 10 7 1 2. + 6 13 13 4 3. 0 <_> @@ -8951,6 +9657,13 @@ <_> 6 11 1 1 3. 0 + <_> + + <_> + 6 10 2 2 -1. + <_> + 7 10 1 2 2. + 0 <_> <_> @@ -8958,6 +9671,13 @@ <_> 7 10 1 3 2. 0 + <_> + + <_> + 6 10 3 14 -1. + <_> + 7 10 1 14 3. + 0 <_> <_> @@ -8979,6 +9699,29 @@ <_> 6 11 3 1 3. 0 + <_> + + <_> + 6 10 9 5 -1. + <_> + 9 10 3 5 3. + 0 + <_> + + <_> + 6 10 12 1 -1. + <_> + 10 10 4 1 3. + 0 + <_> + + <_> + 6 10 8 4 -1. + <_> + 6 10 4 2 2. + <_> + 10 12 4 2 2. + 0 <_> <_> @@ -8988,6 +9731,22 @@ <_> 12 11 6 1 2. 0 + <_> + + <_> + 6 10 12 12 -1. + <_> + 6 10 6 6 2. + <_> + 12 16 6 6 2. + 0 + <_> + + <_> + 6 10 18 1 -1. + <_> + 15 10 9 1 2. + 0 <_> <_> @@ -9026,16 +9785,32 @@ <_> <_> - 6 11 4 3 -1. + 6 11 12 3 -1. <_> - 6 12 4 1 3. + 6 12 12 1 3. 0 <_> <_> - 6 11 16 3 -1. + 6 11 13 3 -1. <_> - 6 12 16 1 3. + 6 12 13 1 3. + 0 + <_> + + <_> + 6 12 14 2 -1. + <_> + 6 12 7 1 2. + <_> + 13 13 7 1 2. + 0 + <_> + + <_> + 6 12 13 2 -1. + <_> + 6 13 13 1 2. 0 <_> @@ -9047,30 +9822,30 @@ <_> <_> - 6 16 1 3 -1. + 6 14 2 2 -1. <_> - 6 17 1 1 3. + 7 14 1 2 2. 0 <_> <_> - 6 17 3 6 -1. + 6 15 2 3 -1. <_> - 7 17 1 6 3. + 6 16 2 1 3. 0 <_> <_> - 6 17 11 4 -1. + 6 17 10 6 -1. <_> - 6 19 11 2 2. + 6 20 10 3 2. 0 <_> <_> - 6 18 12 2 -1. + 6 18 3 6 -1. <_> - 6 19 12 1 2. + 7 18 1 6 3. 0 <_> @@ -9082,9 +9857,25 @@ <_> <_> - 6 20 14 4 -1. + 6 20 9 4 -1. <_> - 6 22 14 2 2. + 6 22 9 2 2. + 0 + <_> + + <_> + 6 23 3 1 -1. + <_> + 7 23 1 1 3. + 0 + <_> + + <_> + 7 0 2 8 -1. + <_> + 7 0 1 4 2. + <_> + 8 4 1 4 2. 0 <_> @@ -9096,16 +9887,9 @@ <_> <_> - 7 0 7 2 -1. + 7 1 2 4 -1. <_> - 7 1 7 1 2. - 0 - <_> - - <_> - 7 0 11 10 -1. - <_> - 7 5 11 5 2. + 7 3 2 2 2. 0 <_> @@ -9117,82 +9901,30 @@ <_> <_> - 7 1 10 2 -1. + 7 2 4 21 -1. <_> - 7 1 5 1 2. - <_> - 12 2 5 1 2. + 9 2 2 21 2. 0 <_> <_> - 7 2 2 2 -1. + 7 3 1 3 -1. <_> - 7 2 1 1 2. - <_> - 8 3 1 1 2. + 7 4 1 1 3. 0 <_> <_> - 7 2 10 2 -1. + 7 3 3 5 -1. <_> - 7 2 5 1 2. - <_> - 12 3 5 1 2. + 8 3 1 5 3. 0 <_> <_> - 7 3 10 2 -1. + 7 4 3 10 -1. <_> - 7 3 5 1 2. - <_> - 12 4 5 1 2. - 0 - <_> - - <_> - 7 4 2 4 -1. - <_> - 8 4 1 4 2. - 0 - <_> - - <_> - 7 4 3 4 -1. - <_> - 8 4 1 4 3. - 0 - <_> - - <_> - 7 4 3 7 -1. - <_> - 8 4 1 7 3. - 0 - <_> - - <_> - 7 4 2 8 -1. - <_> - 8 4 1 8 2. - 0 - <_> - - <_> - 7 4 9 7 -1. - <_> - 10 4 3 7 3. - 0 - <_> - - <_> - 7 4 10 2 -1. - <_> - 7 4 5 1 2. - <_> - 12 5 5 1 2. + 8 4 1 10 3. 0 <_> @@ -9208,6 +9940,13 @@ <_> 8 5 1 2 3. 0 + <_> + + <_> + 7 5 3 3 -1. + <_> + 8 5 1 3 3. + 0 <_> <_> @@ -9218,25 +9957,16 @@ <_> <_> - 7 5 3 7 -1. + 7 5 2 7 -1. <_> - 8 5 1 7 3. + 8 5 1 7 2. 0 <_> <_> - 7 5 3 6 -1. + 7 5 2 6 -1. <_> - 7 7 3 2 3. - 0 - <_> - - <_> - 7 5 10 2 -1. - <_> - 7 5 5 1 2. - <_> - 12 6 5 1 2. + 7 7 2 2 3. 0 <_> @@ -9245,6 +9975,27 @@ <_> 7 7 11 2 3. 0 + <_> + + <_> + 7 6 3 1 -1. + <_> + 8 6 1 1 3. + 0 + <_> + + <_> + 7 6 1 3 -1. + <_> + 7 7 1 1 3. + 0 + <_> + + <_> + 7 6 4 6 -1. + <_> + 9 6 2 6 2. + 0 <_> <_> @@ -9254,6 +10005,22 @@ <_> 12 7 5 1 2. 0 + <_> + + <_> + 7 6 12 2 -1. + <_> + 7 6 6 1 2. + <_> + 13 7 6 1 2. + 0 + <_> + + <_> + 7 7 1 2 -1. + <_> + 7 8 1 1 2. + 0 <_> <_> @@ -9271,9 +10038,18 @@ <_> <_> - 7 7 12 15 -1. + 7 7 2 4 -1. <_> - 7 12 12 5 3. + 7 9 2 2 2. + 0 + <_> + + <_> + 7 7 10 2 -1. + <_> + 7 7 5 1 2. + <_> + 12 8 5 1 2. 0 <_> @@ -9294,16 +10070,20 @@ <_> <_> - 7 8 3 16 -1. + 7 8 2 4 -1. <_> - 8 8 1 16 3. + 7 8 1 2 2. + <_> + 8 10 1 2 2. 0 <_> <_> - 7 8 4 16 -1. + 7 8 10 2 -1. <_> - 9 8 2 16 2. + 7 8 5 1 2. + <_> + 12 9 5 1 2. 0 <_> @@ -9315,18 +10095,16 @@ <_> <_> - 7 9 2 2 -1. + 7 9 1 3 -1. <_> - 7 9 1 1 2. - <_> - 8 10 1 1 2. + 7 10 1 1 3. 0 <_> <_> - 7 9 2 3 -1. + 7 9 3 3 -1. <_> - 7 10 2 1 3. + 8 9 1 3 3. 0 <_> @@ -9362,6 +10140,15 @@ <_> 12 10 5 1 2. 0 + <_> + + <_> + 7 9 12 2 -1. + <_> + 7 9 6 1 2. + <_> + 13 10 6 1 2. + 0 <_> <_> @@ -9386,32 +10173,9 @@ <_> <_> - 7 10 4 4 -1. + 7 10 6 4 -1. <_> - 7 10 2 2 2. - <_> - 9 12 2 2 2. - 0 - <_> - - <_> - 7 10 4 4 -1. - <_> - 9 10 2 4 2. - 0 - <_> - - <_> - 7 10 6 5 -1. - <_> - 9 10 2 5 3. - 0 - <_> - - <_> - 7 10 9 7 -1. - <_> - 10 10 3 7 3. + 9 10 2 4 3. 0 <_> @@ -9429,6 +10193,13 @@ <_> 8 11 1 1 2. 0 + <_> + + <_> + 7 11 2 2 -1. + <_> + 7 12 2 1 2. + 0 <_> <_> @@ -9439,72 +10210,37 @@ <_> <_> - 7 13 12 3 -1. + 7 14 1 3 -1. <_> - 11 13 4 3 3. + 7 15 1 1 3. 0 <_> <_> - 7 13 13 10 -1. + 7 16 10 8 -1. <_> - 7 18 13 5 2. + 7 20 10 4 2. 0 <_> <_> - 7 15 6 3 -1. + 7 18 3 6 -1. <_> - 9 15 2 3 3. - 0 - <_> - - <_> - 7 16 1 6 -1. - <_> - 7 19 1 3 2. - 0 - <_> - - <_> - 7 16 9 2 -1. - <_> - 10 16 3 2 3. - 0 - <_> - - <_> - 7 17 11 6 -1. - <_> - 7 20 11 3 2. - 0 - <_> - - <_> - 7 18 5 6 -1. - <_> - 7 20 5 2 3. + 8 18 1 6 3. 0 <_> <_> 7 18 9 6 -1. <_> - 7 21 9 3 2. + 7 20 9 2 3. 0 <_> <_> - 7 18 10 6 -1. + 7 19 3 3 -1. <_> - 7 20 10 2 3. - 0 - <_> - - <_> - 7 18 11 6 -1. - <_> - 7 21 11 3 2. + 8 19 1 3 3. 0 <_> @@ -9516,23 +10252,30 @@ <_> <_> - 7 20 9 3 -1. + 7 20 7 4 -1. <_> - 7 21 9 1 3. + 7 22 7 2 2. 0 <_> <_> - 8 0 8 1 -1. + 7 20 11 4 -1. <_> - 12 0 4 1 2. + 7 22 11 2 2. 0 <_> <_> - 8 0 10 1 -1. + 7 22 3 2 -1. <_> - 13 0 5 1 2. + 8 22 1 2 3. + 0 + <_> + + <_> + 8 0 8 2 -1. + <_> + 12 0 4 2 2. 0 <_> @@ -9544,11 +10287,9 @@ <_> <_> - 8 0 16 8 -1. + 8 0 8 10 -1. <_> - 8 0 8 4 2. - <_> - 16 4 8 4 2. + 8 5 8 5 2. 0 <_> @@ -9562,51 +10303,88 @@ <_> <_> - 8 0 9 2 -1. + 8 0 10 3 -1. <_> - 8 1 9 1 2. + 8 1 10 1 3. 0 <_> <_> - 8 1 9 10 -1. + 8 1 8 1 -1. <_> - 8 6 9 5 2. + 12 1 4 1 2. 0 <_> <_> - 8 3 6 10 -1. + 8 2 3 2 -1. <_> - 10 3 2 10 3. + 9 2 1 2 3. 0 <_> <_> - 8 4 3 1 -1. + 8 2 8 20 -1. <_> - 9 4 1 1 3. + 12 2 4 20 2. 0 <_> <_> - 8 4 3 5 -1. + 8 3 3 8 -1. <_> - 9 4 1 5 3. + 9 3 1 8 3. 0 <_> <_> - 8 4 2 7 -1. + 8 3 3 9 -1. <_> - 9 4 1 7 2. + 9 3 1 9 3. 0 <_> <_> - 8 4 3 9 -1. + 8 3 6 1 -1. <_> - 9 4 1 9 3. + 11 3 3 1 2. + 0 + <_> + + <_> + 8 3 4 3 -1. + <_> + 8 4 4 1 3. + 0 + <_> + + <_> + 8 3 8 2 -1. + <_> + 8 3 4 1 2. + <_> + 12 4 4 1 2. + 0 + <_> + + <_> + 8 4 3 2 -1. + <_> + 9 4 1 2 3. + 0 + <_> + + <_> + 8 4 2 8 -1. + <_> + 9 4 1 8 2. + 0 + <_> + + <_> + 8 4 3 3 -1. + <_> + 8 5 3 1 3. 0 <_> @@ -9620,9 +10398,9 @@ <_> <_> - 8 5 1 4 -1. + 8 4 7 15 -1. <_> - 8 7 1 2 2. + 8 9 7 5 3. 0 <_> @@ -9631,6 +10409,13 @@ <_> 9 5 1 2 3. 0 + <_> + + <_> + 8 5 2 3 -1. + <_> + 9 5 1 3 2. + 0 <_> <_> @@ -9645,20 +10430,6 @@ <_> 9 5 1 6 2. 0 - <_> - - <_> - 8 5 3 6 -1. - <_> - 9 5 1 6 3. - 0 - <_> - - <_> - 8 5 2 7 -1. - <_> - 9 5 1 7 2. - 0 <_> <_> @@ -9666,13 +10437,6 @@ <_> 9 5 1 7 3. 0 - <_> - - <_> - 8 5 2 3 -1. - <_> - 8 6 2 1 3. - 0 <_> <_> @@ -9683,11 +10447,9 @@ <_> <_> - 8 5 8 2 -1. + 8 5 8 12 -1. <_> - 8 5 4 1 2. - <_> - 12 6 4 1 2. + 12 5 4 12 2. 0 <_> @@ -9703,15 +10465,6 @@ <_> 9 6 1 5 3. 0 - <_> - - <_> - 8 6 8 2 -1. - <_> - 8 6 4 1 2. - <_> - 12 7 4 1 2. - 0 <_> <_> @@ -9724,16 +10477,11 @@ <_> <_> - 8 7 12 6 -1. + 8 8 2 2 -1. <_> - 12 7 4 6 3. - 0 - <_> - + 8 8 1 1 2. <_> - 8 7 16 1 -1. - <_> - 16 7 8 1 2. + 9 9 1 1 2. 0 <_> @@ -9745,11 +10493,23 @@ <_> <_> - 8 9 2 4 -1. + 8 8 3 3 -1. <_> - 8 9 1 2 2. + 8 9 3 1 3. + 0 + <_> + <_> - 9 11 1 2 2. + 8 9 1 3 -1. + <_> + 8 10 1 1 3. + 0 + <_> + + <_> + 8 9 3 2 -1. + <_> + 9 9 1 2 3. 0 <_> @@ -9760,15 +10520,6 @@ <_> 9 12 1 3 2. 0 - <_> - - <_> - 8 9 8 2 -1. - <_> - 8 9 4 1 2. - <_> - 12 10 4 1 2. - 0 <_> <_> @@ -9783,6 +10534,22 @@ <_> 9 10 1 1 3. 0 + <_> + + <_> + 8 10 2 2 -1. + <_> + 8 10 1 1 2. + <_> + 9 11 1 1 2. + 0 + <_> + + <_> + 8 10 2 2 -1. + <_> + 9 10 1 2 2. + 0 <_> <_> @@ -9790,22 +10557,6 @@ <_> 9 10 1 2 3. 0 - <_> - - <_> - 8 10 2 8 -1. - <_> - 8 10 1 4 2. - <_> - 9 14 1 4 2. - 0 - <_> - - <_> - 8 10 4 2 -1. - <_> - 10 10 2 2 2. - 0 <_> <_> @@ -9815,6 +10566,24 @@ <_> 10 14 2 4 2. 0 + <_> + + <_> + 8 10 8 2 -1. + <_> + 8 10 4 1 2. + <_> + 12 11 4 1 2. + 0 + <_> + + <_> + 8 11 2 2 -1. + <_> + 8 11 1 1 2. + <_> + 9 12 1 1 2. + 0 <_> <_> @@ -9827,16 +10596,25 @@ <_> <_> - 8 14 1 3 -1. + 8 11 4 10 -1. <_> - 8 15 1 1 3. + 8 11 2 5 2. + <_> + 10 16 2 5 2. 0 <_> <_> - 8 14 3 10 -1. + 8 13 9 10 -1. <_> - 9 14 1 10 3. + 8 18 9 5 2. + 0 + <_> + + <_> + 8 15 4 4 -1. + <_> + 10 15 2 4 2. 0 <_> @@ -9845,34 +10623,6 @@ <_> 11 16 3 3 3. 0 - <_> - - <_> - 8 16 9 4 -1. - <_> - 11 16 3 4 3. - 0 - <_> - - <_> - 8 17 10 6 -1. - <_> - 8 19 10 2 3. - 0 - <_> - - <_> - 8 17 10 6 -1. - <_> - 8 20 10 3 2. - 0 - <_> - - <_> - 8 18 9 6 -1. - <_> - 11 18 3 6 3. - 0 <_> <_> @@ -9880,13 +10630,6 @@ <_> 9 19 1 5 3. 0 - <_> - - <_> - 8 19 7 3 -1. - <_> - 8 20 7 1 3. - 0 <_> <_> @@ -9894,41 +10637,6 @@ <_> 9 20 1 3 3. 0 - <_> - - <_> - 8 20 3 4 -1. - <_> - 9 20 1 4 3. - 0 - <_> - - <_> - 8 20 7 4 -1. - <_> - 8 22 7 2 2. - 0 - <_> - - <_> - 8 20 12 4 -1. - <_> - 8 22 12 2 2. - 0 - <_> - - <_> - 8 22 3 1 -1. - <_> - 9 22 1 1 3. - 0 - <_> - - <_> - 8 22 3 2 -1. - <_> - 9 22 1 2 3. - 0 <_> <_> @@ -9939,23 +10647,39 @@ <_> <_> - 9 0 5 10 -1. + 9 0 2 4 -1. <_> - 9 5 5 5 2. + 10 0 1 4 2. 0 <_> <_> - 9 0 6 4 -1. + 9 0 6 1 -1. <_> - 9 2 6 2 2. + 12 0 3 1 2. 0 <_> <_> - 9 0 6 8 -1. + 9 0 5 4 -1. <_> - 9 4 6 4 2. + 9 2 5 2 2. + 0 + <_> + + <_> + 9 0 6 10 -1. + <_> + 9 5 6 5 2. + 0 + <_> + + <_> + 9 0 14 8 -1. + <_> + 9 0 7 4 2. + <_> + 16 4 7 4 2. 0 <_> @@ -9976,23 +10700,32 @@ <_> <_> - 9 0 8 4 -1. + 9 0 14 12 -1. <_> - 9 2 8 2 2. + 9 0 7 6 2. + <_> + 16 6 7 6 2. 0 <_> <_> - 9 1 2 3 -1. + 9 1 3 12 -1. <_> - 10 1 1 3 2. + 10 1 1 12 3. 0 <_> <_> - 9 1 15 15 -1. + 9 1 4 15 -1. <_> - 9 6 15 5 3. + 11 1 2 15 2. + 0 + <_> + + <_> + 9 1 6 1 -1. + <_> + 12 1 3 1 2. 0 <_> @@ -10004,72 +10737,74 @@ <_> <_> - 9 2 6 1 -1. + 9 2 6 18 -1. <_> - 12 2 3 1 2. + 12 2 3 18 2. 0 <_> <_> - 9 2 6 22 -1. + 9 2 15 3 -1. <_> - 12 2 3 22 2. + 9 3 15 1 3. 0 <_> <_> - 9 2 6 8 -1. + 9 3 3 9 -1. <_> - 9 6 6 4 2. + 10 3 1 9 3. 0 <_> <_> - 9 4 4 9 -1. + 9 3 8 6 -1. <_> - 11 4 2 9 2. + 9 6 8 3 2. 0 <_> <_> - 9 4 3 3 -1. + 9 3 15 15 -1. <_> - 9 5 3 1 3. + 9 8 15 5 3. 0 <_> <_> - 9 4 3 6 -1. + 9 4 3 4 -1. <_> - 9 7 3 3 2. + 10 4 1 4 3. 0 <_> <_> - 9 4 6 18 -1. + 9 4 6 2 -1. <_> - 12 4 3 18 2. + 9 4 3 1 2. + <_> + 12 5 3 1 2. 0 <_> <_> - 9 4 12 2 -1. + 9 4 14 5 -1. <_> - 13 4 4 2 3. + 16 4 7 5 2. 0 <_> <_> - 9 5 2 6 -1. + 9 5 2 5 -1. <_> - 10 5 1 6 2. + 10 5 1 5 2. 0 <_> <_> - 9 5 6 5 -1. + 9 5 3 6 -1. <_> - 11 5 2 5 3. + 10 5 1 6 3. 0 <_> @@ -10088,9 +10823,16 @@ <_> <_> - 9 6 4 9 -1. + 9 5 4 3 -1. <_> - 11 6 2 9 2. + 9 6 4 1 3. + 0 + <_> + + <_> + 9 6 4 4 -1. + <_> + 11 6 2 4 2. 0 <_> @@ -10099,6 +10841,13 @@ <_> 9 7 3 1 3. 0 + <_> + + <_> + 9 6 6 7 -1. + <_> + 12 6 3 7 2. + 0 <_> <_> @@ -10106,6 +10855,13 @@ <_> 9 7 4 1 3. 0 + <_> + + <_> + 9 6 15 10 -1. + <_> + 9 11 15 5 2. + 0 <_> <_> @@ -10118,37 +10874,62 @@ <_> <_> - 9 7 8 6 -1. + 9 8 3 3 -1. <_> - 13 7 4 6 2. + 9 9 3 1 3. 0 <_> <_> - 9 8 9 9 -1. + 9 8 7 10 -1. <_> - 12 8 3 9 3. + 9 13 7 5 2. 0 <_> <_> - 9 8 4 3 -1. + 9 9 2 2 -1. <_> - 9 9 4 1 3. + 10 9 1 2 2. 0 <_> <_> - 9 9 5 3 -1. + 9 9 3 3 -1. <_> - 9 10 5 1 3. + 9 10 3 1 3. 0 <_> <_> - 9 10 9 5 -1. + 9 9 9 6 -1. <_> - 12 10 3 5 3. + 12 9 3 6 3. + 0 + <_> + + <_> + 9 10 2 4 -1. + <_> + 9 10 1 2 2. + <_> + 10 12 1 2 2. + 0 + <_> + + <_> + 9 10 6 2 -1. + <_> + 9 10 3 1 2. + <_> + 12 11 3 1 2. + 0 + <_> + + <_> + 9 10 8 1 -1. + <_> + 13 10 4 1 2. 0 <_> @@ -10160,37 +10941,41 @@ <_> <_> - 9 11 3 5 -1. + 9 11 2 4 -1. <_> - 10 11 1 5 3. + 9 11 1 2 2. + <_> + 10 13 1 2 2. 0 <_> <_> - 9 15 6 1 -1. + 9 11 2 6 -1. <_> - 11 15 2 1 3. + 9 11 1 3 2. + <_> + 10 14 1 3 2. 0 <_> <_> - 9 15 6 2 -1. + 9 13 2 11 -1. <_> - 11 15 2 2 3. + 10 13 1 11 2. 0 <_> <_> - 9 15 9 9 -1. + 9 14 6 3 -1. <_> - 12 15 3 9 3. + 11 14 2 3 3. 0 <_> <_> - 9 16 6 3 -1. + 9 16 4 3 -1. <_> - 11 16 2 3 3. + 11 16 2 3 2. 0 <_> @@ -10202,30 +10987,37 @@ <_> <_> - 9 16 6 7 -1. + 9 16 6 8 -1. <_> - 11 16 2 7 3. + 11 16 2 8 3. 0 <_> <_> - 9 17 6 4 -1. + 9 16 6 3 -1. <_> - 11 17 2 4 3. + 9 17 6 1 3. 0 <_> <_> - 9 17 5 3 -1. + 9 17 6 2 -1. <_> - 9 18 5 1 3. + 11 17 2 2 3. 0 <_> <_> - 9 18 8 6 -1. + 9 17 6 7 -1. <_> - 9 20 8 2 3. + 11 17 2 7 3. + 0 + <_> + + <_> + 9 18 5 3 -1. + <_> + 9 19 5 1 3. 0 <_> @@ -10237,23 +11029,9 @@ <_> <_> - 9 19 6 3 -1. + 9 19 7 3 -1. <_> - 9 20 6 1 3. - 0 - <_> - - <_> - 9 19 6 4 -1. - <_> - 9 21 6 2 2. - 0 - <_> - - <_> - 9 19 8 3 -1. - <_> - 9 20 8 1 3. + 9 20 7 1 3. 0 <_> @@ -10262,6 +11040,13 @@ <_> 10 20 1 4 3. 0 + <_> + + <_> + 9 20 3 2 -1. + <_> + 9 21 3 1 2. + 0 <_> <_> @@ -10269,6 +11054,34 @@ <_> 9 21 5 1 3. 0 + <_> + + <_> + 9 20 6 3 -1. + <_> + 9 21 6 1 3. + 0 + <_> + + <_> + 9 20 6 4 -1. + <_> + 9 22 6 2 2. + 0 + <_> + + <_> + 9 20 7 3 -1. + <_> + 9 21 7 1 3. + 0 + <_> + + <_> + 9 20 8 4 -1. + <_> + 9 22 8 2 2. + 0 <_> <_> @@ -10276,20 +11089,6 @@ <_> 10 21 1 2 3. 0 - <_> - - <_> - 9 21 3 3 -1. - <_> - 10 21 1 3 3. - 0 - <_> - - <_> - 9 21 6 2 -1. - <_> - 9 22 6 1 2. - 0 <_> <_> @@ -10300,34 +11099,23 @@ <_> <_> - 10 0 4 1 -1. + 10 0 1 6 -1. <_> - 12 0 2 1 2. + 10 3 1 3 2. 0 <_> <_> - 10 0 4 2 -1. + 10 0 6 1 -1. <_> - 10 0 2 1 2. - <_> - 12 1 2 1 2. + 13 0 3 1 2. 0 <_> <_> - 10 0 4 4 -1. + 10 0 4 8 -1. <_> - 10 0 2 2 2. - <_> - 12 2 2 2 2. - 0 - <_> - - <_> - 10 0 3 6 -1. - <_> - 10 3 3 3 2. + 10 4 4 4 2. 0 <_> @@ -10338,13 +11126,6 @@ <_> 17 5 7 5 2. 0 - <_> - - <_> - 10 1 2 9 -1. - <_> - 11 1 1 9 2. - 0 <_> <_> @@ -10357,9 +11138,16 @@ <_> <_> - 10 3 2 9 -1. + 10 2 1 6 -1. <_> - 11 3 1 9 2. + 10 5 1 3 2. + 0 + <_> + + <_> + 10 3 6 1 -1. + <_> + 13 3 3 1 2. 0 <_> @@ -10371,39 +11159,44 @@ <_> <_> - 10 3 6 2 -1. + 10 3 3 3 -1. <_> - 10 3 3 1 2. - <_> - 13 4 3 1 2. + 10 4 3 1 3. 0 <_> <_> 10 4 3 3 -1. <_> - 10 5 3 1 3. + 11 4 1 3 3. 0 <_> <_> - 10 4 7 15 -1. + 10 4 2 8 -1. <_> - 10 9 7 5 3. + 11 4 1 8 2. 0 <_> <_> 10 5 3 3 -1. <_> - 10 6 3 1 3. + 11 5 1 3 3. 0 <_> <_> - 10 6 7 3 -1. + 10 5 4 11 -1. <_> - 10 7 7 1 3. + 12 5 2 11 2. + 0 + <_> + + <_> + 10 6 6 3 -1. + <_> + 10 7 6 1 3. 0 <_> @@ -10415,16 +11208,16 @@ <_> <_> - 10 7 4 14 -1. + 10 7 4 7 -1. <_> - 12 7 2 14 2. + 12 7 2 7 2. 0 <_> <_> - 10 7 3 3 -1. + 10 7 9 6 -1. <_> - 10 8 3 1 3. + 13 7 3 6 3. 0 <_> @@ -10436,53 +11229,65 @@ <_> <_> - 10 7 8 12 -1. + 10 8 2 3 -1. <_> - 10 13 8 6 2. + 10 9 2 1 3. 0 <_> <_> - 10 9 10 8 -1. + 10 8 4 2 -1. <_> - 10 9 5 4 2. - <_> - 15 13 5 4 2. + 10 9 4 1 2. 0 <_> <_> - 10 9 6 8 -1. + 10 8 8 10 -1. <_> - 10 13 6 4 2. + 10 13 8 5 2. 0 <_> <_> - 10 10 2 6 -1. + 10 9 1 3 -1. <_> - 11 10 1 6 2. + 10 10 1 1 3. 0 <_> <_> - 10 10 2 3 -1. + 10 9 2 3 -1. <_> - 10 11 2 1 3. + 10 10 2 1 3. 0 <_> <_> - 10 10 14 4 -1. + 10 9 6 4 -1. <_> - 10 12 14 2 2. + 13 9 3 4 2. 0 <_> <_> - 10 11 2 3 -1. + 10 10 14 3 -1. <_> - 10 12 2 1 3. + 10 11 14 1 3. + 0 + <_> + + <_> + 10 11 1 3 -1. + <_> + 10 12 1 1 3. + 0 + <_> + + <_> + 10 11 4 3 -1. + <_> + 10 12 4 1 3. 0 <_> @@ -10494,16 +11299,48 @@ <_> <_> - 10 15 8 3 -1. + 10 12 2 8 -1. <_> - 14 15 4 3 2. + 10 12 1 4 2. + <_> + 11 16 1 4 2. 0 <_> <_> - 10 16 3 2 -1. + 10 15 4 3 -1. <_> - 11 16 1 2 3. + 10 16 4 1 3. + 0 + <_> + + <_> + 10 15 6 6 -1. + <_> + 10 17 6 2 3. + 0 + <_> + + <_> + 10 16 6 8 -1. + <_> + 10 16 3 4 2. + <_> + 13 20 3 4 2. + 0 + <_> + + <_> + 10 16 4 2 -1. + <_> + 10 17 4 1 2. + 0 + <_> + + <_> + 10 16 4 3 -1. + <_> + 10 17 4 1 3. 0 <_> @@ -10515,18 +11352,23 @@ <_> <_> - 10 18 12 2 -1. + 10 17 5 3 -1. <_> - 10 18 6 1 2. - <_> - 16 19 6 1 2. + 10 18 5 1 3. 0 <_> <_> - 10 20 3 2 -1. + 10 18 5 3 -1. <_> - 11 20 1 2 3. + 10 19 5 1 3. + 0 + <_> + + <_> + 10 19 5 3 -1. + <_> + 10 20 5 1 3. 0 <_> @@ -10549,13 +11391,6 @@ <_> 10 21 4 1 3. 0 - <_> - - <_> - 10 20 4 4 -1. - <_> - 10 22 4 2 2. - 0 <_> <_> @@ -10566,27 +11401,9 @@ <_> <_> - 10 20 5 4 -1. + 10 21 3 1 -1. <_> - 10 22 5 2 2. - 0 - <_> - - <_> - 10 20 10 4 -1. - <_> - 10 20 5 2 2. - <_> - 15 22 5 2 2. - 0 - <_> - - <_> - 10 20 14 4 -1. - <_> - 10 20 7 2 2. - <_> - 17 22 7 2 2. + 11 21 1 1 3. 0 <_> @@ -10598,16 +11415,23 @@ <_> <_> - 10 21 2 2 -1. + 10 21 6 3 -1. <_> - 10 22 2 1 2. + 12 21 2 3 3. 0 <_> <_> - 10 21 14 2 -1. + 10 21 5 2 -1. <_> - 17 21 7 2 2. + 10 22 5 1 2. + 0 + <_> + + <_> + 10 22 3 1 -1. + <_> + 11 22 1 1 3. 0 <_> @@ -10619,51 +11443,30 @@ <_> <_> - 11 1 3 7 -1. + 11 0 2 12 -1. <_> - 12 1 1 7 3. + 11 4 2 4 3. 0 <_> <_> - 11 1 6 1 -1. + 11 0 12 19 -1. <_> - 13 1 2 1 3. + 15 0 4 19 3. 0 <_> <_> - 11 1 4 15 -1. + 11 2 4 20 -1. <_> - 13 1 2 15 2. + 13 2 2 20 2. 0 <_> <_> - 11 2 3 4 -1. + 11 3 3 3 -1. <_> - 12 2 1 4 3. - 0 - <_> - - <_> - 11 2 2 12 -1. - <_> - 12 2 1 12 2. - 0 - <_> - - <_> - 11 2 2 13 -1. - <_> - 12 2 1 13 2. - 0 - <_> - - <_> - 11 3 1 3 -1. - <_> - 11 4 1 1 3. + 12 3 1 3 3. 0 <_> @@ -10672,6 +11475,13 @@ <_> 12 3 1 5 3. 0 + <_> + + <_> + 11 3 3 6 -1. + <_> + 12 3 1 6 3. + 0 <_> <_> @@ -10682,23 +11492,16 @@ <_> <_> - 11 3 6 12 -1. + 11 3 2 3 -1. <_> - 13 3 2 12 3. + 11 4 2 1 3. 0 <_> <_> - 11 3 4 13 -1. + 11 3 12 14 -1. <_> - 13 3 2 13 2. - 0 - <_> - - <_> - 11 3 9 2 -1. - <_> - 14 3 3 2 3. + 15 3 4 14 3. 0 <_> @@ -10707,6 +11510,20 @@ <_> 12 4 1 5 3. 0 + <_> + + <_> + 11 4 2 3 -1. + <_> + 11 5 2 1 3. + 0 + <_> + + <_> + 11 4 9 1 -1. + <_> + 14 4 3 1 3. + 0 <_> <_> @@ -10717,37 +11534,9 @@ <_> <_> - 11 5 3 3 -1. + 11 5 8 4 -1. <_> - 12 5 1 3 3. - 0 - <_> - - <_> - 11 5 3 4 -1. - <_> - 12 5 1 4 3. - 0 - <_> - - <_> - 11 5 4 10 -1. - <_> - 13 5 2 10 2. - 0 - <_> - - <_> - 11 5 4 3 -1. - <_> - 11 6 4 1 3. - 0 - <_> - - <_> - 11 6 1 3 -1. - <_> - 11 7 1 1 3. + 11 7 8 2 2. 0 <_> @@ -10756,27 +11545,6 @@ <_> 11 7 2 1 3. 0 - <_> - - <_> - 11 6 6 5 -1. - <_> - 13 6 2 5 3. - 0 - <_> - - <_> - 11 6 3 3 -1. - <_> - 11 7 3 1 3. - 0 - <_> - - <_> - 11 6 9 11 -1. - <_> - 14 6 3 11 3. - 0 <_> <_> @@ -10784,13 +11552,6 @@ <_> 11 7 4 1 3. 0 - <_> - - <_> - 11 6 5 3 -1. - <_> - 11 7 5 1 3. - 0 <_> <_> @@ -10798,6 +11559,15 @@ <_> 11 8 1 1 3. 0 + <_> + + <_> + 11 7 2 2 -1. + <_> + 11 7 1 1 2. + <_> + 12 8 1 1 2. + 0 <_> <_> @@ -10808,9 +11578,18 @@ <_> <_> - 11 7 5 3 -1. + 11 7 4 2 -1. <_> - 11 8 5 1 3. + 11 7 2 1 2. + <_> + 13 8 2 1 2. + 0 + <_> + + <_> + 11 7 4 3 -1. + <_> + 11 8 4 1 3. 0 <_> @@ -10819,6 +11598,13 @@ <_> 11 9 1 1 3. 0 + <_> + + <_> + 11 8 1 10 -1. + <_> + 11 13 1 5 2. + 0 <_> <_> @@ -10836,18 +11622,25 @@ <_> <_> - 11 9 2 2 -1. + 11 8 8 8 -1. <_> - 11 9 1 1 2. + 11 8 4 4 2. <_> - 12 10 1 1 2. + 15 12 4 4 2. 0 <_> <_> - 11 9 3 3 -1. + 11 8 7 10 -1. <_> - 11 10 3 1 3. + 11 13 7 5 2. + 0 + <_> + + <_> + 11 9 6 6 -1. + <_> + 13 9 2 6 3. 0 <_> @@ -10856,13 +11649,6 @@ <_> 11 10 4 1 3. 0 - <_> - - <_> - 11 10 1 3 -1. - <_> - 11 11 1 1 3. - 0 <_> <_> @@ -10873,11 +11659,25 @@ <_> <_> - 11 10 8 2 -1. + 11 10 6 8 -1. <_> - 11 10 4 1 2. + 11 10 3 4 2. <_> - 15 11 4 1 2. + 14 14 3 4 2. + 0 + <_> + + <_> + 11 10 4 3 -1. + <_> + 11 11 4 1 3. + 0 + <_> + + <_> + 11 10 5 3 -1. + <_> + 11 11 5 1 3. 0 <_> @@ -10889,69 +11689,32 @@ <_> <_> - 11 12 6 3 -1. + 11 11 10 10 -1. <_> - 13 12 2 3 3. + 11 11 5 5 2. + <_> + 16 16 5 5 2. 0 <_> <_> - 11 14 9 3 -1. + 11 13 6 2 -1. <_> - 14 14 3 3 3. + 13 13 2 2 3. 0 <_> <_> - 11 16 3 3 -1. + 11 14 2 9 -1. <_> - 11 17 3 1 3. + 11 17 2 3 3. 0 <_> <_> - 11 18 5 6 -1. + 11 15 1 2 -1. <_> - 11 20 5 2 3. - 0 - <_> - - <_> - 11 18 12 6 -1. - <_> - 11 18 6 3 2. - <_> - 17 21 6 3 2. - 0 - <_> - - <_> - 11 19 2 4 -1. - <_> - 11 21 2 2 2. - 0 - <_> - - <_> - 11 19 12 4 -1. - <_> - 11 19 6 2 2. - <_> - 17 21 6 2 2. - 0 - <_> - - <_> - 11 20 3 2 -1. - <_> - 12 20 1 2 3. - 0 - <_> - - <_> - 11 20 3 3 -1. - <_> - 12 20 1 3 3. + 11 16 1 1 2. 0 <_> @@ -10963,18 +11726,30 @@ <_> <_> - 11 21 3 1 -1. + 11 20 3 3 -1. <_> - 12 21 1 1 3. + 11 21 3 1 3. 0 <_> <_> - 11 21 2 2 -1. + 11 21 2 1 -1. <_> - 11 21 1 1 2. + 12 21 1 1 2. + 0 + <_> + <_> - 12 22 1 1 2. + 11 21 3 2 -1. + <_> + 12 21 1 2 3. + 0 + <_> + + <_> + 11 21 2 3 -1. + <_> + 12 21 1 3 2. 0 <_> @@ -10983,13 +11758,6 @@ <_> 11 22 3 1 2. 0 - <_> - - <_> - 11 22 3 1 -1. - <_> - 12 22 1 1 3. - 0 <_> <_> @@ -11000,106 +11768,127 @@ <_> <_> - 12 0 12 1 -1. + 12 0 8 12 -1. <_> - 18 0 6 1 2. + 12 0 4 6 2. + <_> + 16 6 4 6 2. 0 <_> <_> - 12 0 12 10 -1. + 12 0 12 6 -1. <_> - 12 0 6 5 2. + 12 0 6 3 2. <_> - 18 5 6 5 2. + 18 3 6 3 2. 0 <_> <_> - 12 0 12 12 -1. + 12 1 1 3 -1. <_> - 12 0 6 6 2. - <_> - 18 6 6 6 2. + 12 2 1 1 3. 0 <_> <_> - 12 1 2 12 -1. + 12 1 2 7 -1. <_> - 13 1 1 12 2. + 13 1 1 7 2. 0 <_> <_> - 12 1 6 7 -1. + 12 1 12 4 -1. <_> - 14 1 2 7 3. + 12 1 6 2 2. + <_> + 18 3 6 2 2. 0 <_> <_> - 12 1 6 15 -1. + 12 2 3 3 -1. <_> - 14 1 2 15 3. + 13 2 1 3 3. 0 <_> <_> - 12 1 9 13 -1. + 12 2 3 7 -1. <_> - 15 1 3 13 3. + 13 2 1 7 3. 0 <_> <_> - 12 2 9 4 -1. + 12 2 6 1 -1. <_> - 15 2 3 4 3. + 14 2 2 1 3. 0 <_> <_> - 12 3 6 1 -1. + 12 2 6 4 -1. <_> - 14 3 2 1 3. + 14 2 2 4 3. 0 <_> <_> - 12 3 6 9 -1. + 12 2 6 18 -1. <_> - 14 3 2 9 3. + 12 8 6 6 3. 0 <_> <_> - 12 3 6 3 -1. + 12 3 6 11 -1. <_> - 12 4 6 1 3. + 14 3 2 11 3. 0 <_> <_> - 12 4 2 6 -1. + 12 3 9 3 -1. <_> - 13 4 1 6 2. + 15 3 3 3 3. 0 <_> <_> - 12 4 8 6 -1. + 12 3 12 3 -1. <_> - 12 4 4 3 2. - <_> - 16 7 4 3 2. + 12 4 12 1 3. 0 <_> <_> - 12 5 3 3 -1. + 12 4 2 12 -1. <_> - 12 6 3 1 3. + 13 4 1 12 2. + 0 + <_> + + <_> + 12 4 2 3 -1. + <_> + 12 5 2 1 3. + 0 + <_> + + <_> + 12 5 3 5 -1. + <_> + 13 5 1 5 3. + 0 + <_> + + <_> + 12 5 4 3 -1. + <_> + 12 6 4 1 3. 0 <_> @@ -11108,6 +11897,22 @@ <_> 12 7 1 1 3. 0 + <_> + + <_> + 12 6 2 3 -1. + <_> + 12 7 2 1 3. + 0 + <_> + + <_> + 12 6 8 4 -1. + <_> + 12 6 4 2 2. + <_> + 16 8 4 2 2. + 0 <_> <_> @@ -11125,16 +11930,9 @@ <_> <_> - 12 7 3 3 -1. + 12 8 1 3 -1. <_> - 12 8 3 1 3. - 0 - <_> - - <_> - 12 7 4 3 -1. - <_> - 12 8 4 1 3. + 12 9 1 1 3. 0 <_> @@ -11143,6 +11941,13 @@ <_> 12 9 3 1 3. 0 + <_> + + <_> + 12 8 4 3 -1. + <_> + 12 9 4 1 3. + 0 <_> <_> @@ -11153,41 +11958,11 @@ <_> <_> - 12 9 2 3 -1. + 12 10 2 12 -1. <_> - 12 10 2 1 3. - 0 - <_> - + 12 10 1 6 2. <_> - 12 9 4 6 -1. - <_> - 12 9 2 3 2. - <_> - 14 12 2 3 2. - 0 - <_> - - <_> - 12 9 6 7 -1. - <_> - 14 9 2 7 3. - 0 - <_> - - <_> - 12 9 6 6 -1. - <_> - 12 9 3 3 2. - <_> - 15 12 3 3 2. - 0 - <_> - - <_> - 12 10 6 2 -1. - <_> - 14 10 2 2 3. + 13 16 1 6 2. 0 <_> @@ -11198,6 +11973,20 @@ <_> 14 15 2 5 2. 0 + <_> + + <_> + 12 11 2 3 -1. + <_> + 12 12 2 1 3. + 0 + <_> + + <_> + 12 11 4 4 -1. + <_> + 14 11 2 4 2. + 0 <_> <_> @@ -11210,61 +11999,18 @@ <_> <_> - 12 11 6 10 -1. + 12 15 6 5 -1. <_> - 12 11 3 5 2. - <_> - 15 16 3 5 2. + 14 15 2 5 3. 0 <_> <_> - 12 11 8 8 -1. + 12 15 10 4 -1. <_> - 12 11 4 4 2. + 12 15 5 2 2. <_> - 16 15 4 4 2. - 0 - <_> - - <_> - 12 12 9 3 -1. - <_> - 15 12 3 3 3. - 0 - <_> - - <_> - 12 12 10 8 -1. - <_> - 12 12 5 4 2. - <_> - 17 16 5 4 2. - 0 - <_> - - <_> - 12 13 4 8 -1. - <_> - 12 13 2 4 2. - <_> - 14 17 2 4 2. - 0 - <_> - - <_> - 12 14 3 7 -1. - <_> - 13 14 1 7 3. - 0 - <_> - - <_> - 12 14 8 4 -1. - <_> - 12 14 4 2 2. - <_> - 16 16 4 2 2. + 17 17 5 2 2. 0 <_> @@ -11276,16 +12022,27 @@ <_> <_> - 12 19 3 5 -1. + 12 17 3 3 -1. <_> - 13 19 1 5 3. + 13 17 1 3 3. 0 <_> <_> - 12 20 3 4 -1. + 12 17 8 6 -1. <_> - 13 20 1 4 3. + 12 17 4 3 2. + <_> + 16 20 4 3 2. + 0 + <_> + + <_> + 12 18 12 6 -1. + <_> + 12 18 6 3 2. + <_> + 18 21 6 3 2. 0 <_> @@ -11297,30 +12054,9 @@ <_> <_> - 12 22 3 2 -1. + 13 0 11 14 -1. <_> - 13 22 1 2 3. - 0 - <_> - - <_> - 13 0 1 10 -1. - <_> - 13 5 1 5 2. - 0 - <_> - - <_> - 13 1 2 12 -1. - <_> - 14 1 1 12 2. - 0 - <_> - - <_> - 13 1 6 8 -1. - <_> - 15 1 2 8 3. + 13 7 11 7 2. 0 <_> @@ -11329,15 +12065,6 @@ <_> 14 2 1 3 2. 0 - <_> - - <_> - 13 2 2 6 -1. - <_> - 13 2 1 3 2. - <_> - 14 5 1 3 2. - 0 <_> <_> @@ -11348,32 +12075,37 @@ <_> <_> - 13 3 2 4 -1. + 13 3 3 3 -1. <_> - 13 3 1 2 2. - <_> - 14 5 1 2 2. + 14 3 1 3 3. 0 <_> <_> - 13 3 6 8 -1. + 13 3 6 1 -1. <_> - 15 3 2 8 3. + 15 3 2 1 3. 0 <_> <_> - 13 4 6 9 -1. + 13 4 1 2 -1. <_> - 15 4 2 9 3. + 13 5 1 1 2. 0 <_> <_> - 13 5 3 5 -1. + 13 4 3 7 -1. <_> - 14 5 1 5 3. + 14 4 1 7 3. + 0 + <_> + + <_> + 13 4 3 8 -1. + <_> + 14 4 1 8 3. 0 <_> @@ -11385,32 +12117,51 @@ <_> <_> - 13 6 2 3 -1. + 13 6 1 3 -1. <_> - 13 7 2 1 3. + 13 7 1 1 3. 0 <_> <_> - 13 7 2 4 -1. + 13 7 6 6 -1. <_> - 14 7 1 4 2. + 15 7 2 6 3. 0 <_> <_> - 13 8 2 3 -1. + 13 7 3 3 -1. <_> - 13 9 2 1 3. + 13 8 3 1 3. 0 <_> <_> 13 8 6 8 -1. <_> - 13 8 3 4 2. + 15 8 2 8 3. + 0 + <_> + <_> - 16 12 3 4 2. + 13 9 3 4 -1. + <_> + 14 9 1 4 3. + 0 + <_> + + <_> + 13 9 4 3 -1. + <_> + 15 9 2 3 2. + 0 + <_> + + <_> + 13 9 6 4 -1. + <_> + 15 9 2 4 3. 0 <_> @@ -11422,9 +12173,9 @@ <_> <_> - 13 10 3 1 -1. + 13 9 9 2 -1. <_> - 14 10 1 1 3. + 13 10 9 1 2. 0 <_> @@ -11436,25 +12187,18 @@ <_> <_> - 13 10 2 3 -1. + 13 10 4 1 -1. <_> - 13 11 2 1 3. + 15 10 2 1 2. 0 <_> <_> - 13 10 4 8 -1. + 13 10 4 4 -1. <_> - 13 10 2 4 2. + 13 10 2 2 2. <_> - 15 14 2 4 2. - 0 - <_> - - <_> - 13 10 9 1 -1. - <_> - 16 10 3 1 3. + 15 12 2 2 2. 0 <_> @@ -11466,53 +12210,76 @@ <_> <_> - 13 11 4 2 -1. + 13 11 3 3 -1. <_> - 13 11 2 1 2. - <_> - 15 12 2 1 2. + 13 12 3 1 3. 0 <_> <_> - 13 15 6 1 -1. + 13 12 3 3 -1. <_> - 15 15 2 1 3. + 13 13 3 1 3. 0 <_> <_> - 13 17 8 1 -1. + 13 13 2 6 -1. <_> - 17 17 4 1 2. + 13 13 1 3 2. + <_> + 14 16 1 3 2. 0 <_> <_> - 13 19 3 5 -1. + 13 15 2 5 -1. <_> - 14 19 1 5 3. + 14 15 1 5 2. 0 <_> <_> - 13 20 3 2 -1. + 13 19 3 3 -1. <_> - 14 20 1 2 3. + 14 19 1 3 3. 0 <_> <_> - 13 21 3 3 -1. + 13 20 3 3 -1. <_> - 14 21 1 3 3. + 14 20 1 3 3. 0 <_> <_> - 14 0 1 2 -1. + 13 22 3 2 -1. <_> - 14 1 1 1 2. + 14 22 1 2 3. + 0 + <_> + + <_> + 14 0 1 10 -1. + <_> + 14 5 1 5 2. + 0 + <_> + + <_> + 14 0 2 7 -1. + <_> + 15 0 1 7 2. + 0 + <_> + + <_> + 14 0 2 22 -1. + <_> + 14 0 1 11 2. + <_> + 15 11 1 11 2. 0 <_> @@ -11526,58 +12293,71 @@ <_> <_> - 14 1 1 8 -1. + 14 0 10 8 -1. <_> - 14 5 1 4 2. + 14 0 5 4 2. + <_> + 19 4 5 4 2. 0 <_> <_> - 14 2 3 8 -1. + 14 0 10 12 -1. <_> - 15 2 1 8 3. + 14 0 5 6 2. + <_> + 19 6 5 6 2. 0 <_> <_> - 14 2 3 12 -1. + 14 1 2 2 -1. <_> - 15 2 1 12 3. + 15 1 1 2 2. 0 <_> <_> - 14 2 7 3 -1. + 14 1 4 4 -1. <_> - 14 3 7 1 3. + 14 3 4 2 2. 0 <_> <_> - 14 3 6 3 -1. + 14 1 10 2 -1. <_> - 14 4 6 1 3. + 19 1 5 2 2. 0 <_> <_> - 14 4 1 4 -1. + 14 2 6 7 -1. <_> - 14 6 1 2 2. + 16 2 2 7 3. 0 <_> <_> - 14 4 3 6 -1. + 14 3 2 4 -1. <_> - 15 4 1 6 3. + 14 3 1 2 2. + <_> + 15 5 1 2 2. 0 <_> <_> - 14 4 3 7 -1. + 14 4 3 3 -1. <_> - 15 4 1 7 3. + 15 4 1 3 3. + 0 + <_> + + <_> + 14 4 6 1 -1. + <_> + 16 4 2 1 3. 0 <_> @@ -11586,27 +12366,6 @@ <_> 14 5 3 1 3. 0 - <_> - - <_> - 14 4 7 3 -1. - <_> - 14 5 7 1 3. - 0 - <_> - - <_> - 14 4 8 3 -1. - <_> - 14 5 8 1 3. - 0 - <_> - - <_> - 14 4 10 6 -1. - <_> - 14 6 10 2 3. - 0 <_> <_> @@ -11624,46 +12383,95 @@ <_> <_> - 14 5 3 4 -1. + 14 5 4 2 -1. <_> - 15 5 1 4 3. + 16 5 2 2 2. 0 <_> <_> - 14 5 2 6 -1. + 14 5 3 10 -1. <_> - 15 5 1 6 2. + 14 10 3 5 2. 0 <_> <_> - 14 5 3 6 -1. + 14 5 4 6 -1. <_> - 15 5 1 6 3. + 14 7 4 2 3. 0 <_> <_> - 14 5 5 6 -1. + 14 6 3 2 -1. <_> - 14 7 5 2 3. + 15 6 1 2 3. 0 <_> <_> - 14 7 6 16 -1. + 14 6 3 4 -1. <_> - 16 7 2 16 3. + 15 6 1 4 3. 0 <_> <_> - 14 8 2 6 -1. + 14 6 2 6 -1. <_> - 14 8 1 3 2. + 15 6 1 6 2. + 0 + <_> + <_> - 15 11 1 3 2. + 14 6 6 2 -1. + <_> + 16 6 2 2 3. + 0 + <_> + + <_> + 14 6 6 17 -1. + <_> + 16 6 2 17 3. + 0 + <_> + + <_> + 14 8 2 13 -1. + <_> + 15 8 1 13 2. + 0 + <_> + + <_> + 14 8 4 6 -1. + <_> + 14 10 4 2 3. + 0 + <_> + + <_> + 14 9 2 2 -1. + <_> + 15 9 1 2 2. + 0 + <_> + + <_> + 14 9 3 2 -1. + <_> + 15 9 1 2 3. + 0 + <_> + + <_> + 14 9 2 4 -1. + <_> + 14 9 1 2 2. + <_> + 15 11 1 2 2. 0 <_> @@ -11672,15 +12480,6 @@ <_> 15 9 1 3 2. 0 - <_> - - <_> - 14 9 2 8 -1. - <_> - 14 9 1 4 2. - <_> - 15 13 1 4 2. - 0 <_> <_> @@ -11691,9 +12490,16 @@ <_> <_> - 14 9 9 2 -1. + 14 9 6 1 -1. <_> - 14 10 9 1 2. + 16 9 2 1 3. + 0 + <_> + + <_> + 14 9 9 9 -1. + <_> + 14 12 9 3 3. 0 <_> @@ -11709,6 +12515,15 @@ <_> 15 10 1 1 3. 0 + <_> + + <_> + 14 10 2 2 -1. + <_> + 14 10 1 1 2. + <_> + 15 11 1 1 2. + 0 <_> <_> @@ -11726,9 +12541,9 @@ <_> <_> - 14 10 2 3 -1. + 14 10 3 3 -1. <_> - 15 10 1 3 2. + 15 10 1 3 3. 0 <_> @@ -11742,69 +12557,143 @@ <_> <_> - 14 10 2 8 -1. + 14 12 6 2 -1. <_> - 14 10 1 4 2. - <_> - 15 14 1 4 2. + 16 12 2 2 3. 0 <_> <_> - 14 13 3 8 -1. + 14 12 6 5 -1. <_> - 15 13 1 8 3. + 16 12 2 5 3. 0 <_> <_> - 14 18 8 6 -1. + 14 14 8 6 -1. <_> - 14 18 4 3 2. + 14 14 4 3 2. <_> - 18 21 4 3 2. + 18 17 4 3 2. 0 <_> <_> - 14 22 3 2 -1. + 14 14 10 10 -1. <_> - 15 22 1 2 3. + 14 14 5 5 2. + <_> + 19 19 5 5 2. 0 <_> <_> - 15 0 3 11 -1. + 14 16 10 8 -1. <_> - 16 0 1 11 3. + 14 16 5 4 2. + <_> + 19 20 5 4 2. 0 <_> <_> - 15 2 4 4 -1. + 14 18 8 4 -1. <_> - 15 4 4 2 2. + 14 18 4 2 2. + <_> + 18 20 4 2 2. 0 <_> <_> - 15 3 2 3 -1. + 14 19 3 4 -1. <_> - 15 4 2 1 3. + 15 19 1 4 3. 0 <_> <_> - 15 4 2 9 -1. + 14 19 3 5 -1. <_> - 16 4 1 9 2. + 15 19 1 5 3. 0 <_> <_> - 15 4 6 6 -1. + 14 20 3 4 -1. <_> - 15 6 6 2 3. + 15 20 1 4 3. + 0 + <_> + + <_> + 14 23 3 1 -1. + <_> + 15 23 1 1 3. + 0 + <_> + + <_> + 15 0 8 1 -1. + <_> + 19 0 4 1 2. + 0 + <_> + + <_> + 15 0 8 2 -1. + <_> + 19 0 4 2 2. + 0 + <_> + + <_> + 15 2 2 10 -1. + <_> + 16 2 1 10 2. + 0 + <_> + + <_> + 15 2 6 7 -1. + <_> + 17 2 2 7 3. + 0 + <_> + + <_> + 15 2 5 3 -1. + <_> + 15 3 5 1 3. + 0 + <_> + + <_> + 15 4 2 6 -1. + <_> + 16 4 1 6 2. + 0 + <_> + + <_> + 15 4 2 8 -1. + <_> + 16 4 1 8 2. + 0 + <_> + + <_> + 15 4 6 8 -1. + <_> + 18 4 3 8 2. + 0 + <_> + + <_> + 15 4 8 3 -1. + <_> + 15 5 8 1 3. 0 <_> @@ -11813,6 +12702,13 @@ <_> 16 5 1 2 2. 0 + <_> + + <_> + 15 5 3 2 -1. + <_> + 16 5 1 2 3. + 0 <_> <_> @@ -11823,30 +12719,53 @@ <_> <_> - 15 6 3 1 -1. + 15 5 3 6 -1. <_> - 16 6 1 1 3. + 16 5 1 6 3. 0 <_> <_> - 15 6 3 8 -1. + 15 6 3 18 -1. <_> - 15 10 3 4 2. + 15 12 3 6 3. 0 <_> <_> - 15 7 4 6 -1. + 15 6 6 7 -1. <_> - 15 9 4 2 3. + 18 6 3 7 2. 0 <_> <_> - 15 7 6 3 -1. + 15 6 8 4 -1. <_> - 15 8 6 1 3. + 15 6 4 2 2. + <_> + 19 8 4 2 2. + 0 + <_> + + <_> + 15 7 3 6 -1. + <_> + 15 9 3 2 3. + 0 + <_> + + <_> + 15 7 5 4 -1. + <_> + 15 9 5 2 2. + 0 + <_> + + <_> + 15 7 5 6 -1. + <_> + 15 9 5 2 3. 0 <_> @@ -11881,37 +12800,48 @@ <_> <_> - 15 9 1 10 -1. + 15 8 2 4 -1. <_> - 15 14 1 5 2. + 15 8 1 2 2. + <_> + 16 10 1 2 2. 0 <_> <_> - 15 9 3 5 -1. + 15 8 1 12 -1. <_> - 16 9 1 5 3. + 15 14 1 6 2. 0 <_> <_> - 15 9 6 4 -1. + 15 9 2 2 -1. <_> - 18 9 3 4 2. + 15 9 1 1 2. + <_> + 16 10 1 1 2. 0 <_> <_> - 15 9 3 15 -1. + 15 9 3 4 -1. <_> - 15 14 3 5 3. + 16 9 1 4 3. 0 <_> <_> - 15 9 6 3 -1. + 15 9 2 3 -1. <_> - 15 10 6 1 3. + 15 10 2 1 3. + 0 + <_> + + <_> + 15 9 7 3 -1. + <_> + 15 10 7 1 3. 0 <_> @@ -11937,67 +12867,39 @@ <_> <_> - 15 10 3 3 -1. + 15 10 3 5 -1. <_> - 15 11 3 1 3. + 16 10 1 5 3. 0 <_> <_> - 15 11 3 2 -1. + 15 12 4 8 -1. <_> - 15 12 3 1 2. + 15 12 2 4 2. + <_> + 17 16 2 4 2. 0 <_> <_> - 15 11 3 12 -1. + 15 15 4 3 -1. <_> - 15 15 3 4 3. + 15 16 4 1 3. 0 <_> <_> - 15 11 9 6 -1. + 15 16 5 3 -1. <_> - 15 13 9 2 3. + 15 17 5 1 3. 0 <_> <_> - 15 14 2 10 -1. + 15 19 3 4 -1. <_> - 15 19 2 5 2. - 0 - <_> - - <_> - 15 14 8 3 -1. - <_> - 19 14 4 3 2. - 0 - <_> - - <_> - 15 14 5 3 -1. - <_> - 15 15 5 1 3. - 0 - <_> - - <_> - 15 16 6 8 -1. - <_> - 15 16 3 4 2. - <_> - 18 20 3 4 2. - 0 - <_> - - <_> - 15 17 7 3 -1. - <_> - 15 18 7 1 3. + 16 19 1 4 3. 0 <_> @@ -12006,6 +12908,13 @@ <_> 15 20 9 1 3. 0 + <_> + + <_> + 15 20 6 3 -1. + <_> + 18 20 3 3 2. + 0 <_> <_> @@ -12020,6 +12929,15 @@ <_> 20 0 4 2 2. 0 + <_> + + <_> + 16 0 8 4 -1. + <_> + 16 0 4 2 2. + <_> + 20 2 4 2 2. + 0 <_> <_> @@ -12050,50 +12968,60 @@ <_> <_> - 16 3 2 4 -1. + 16 1 4 13 -1. <_> - 16 3 1 2 2. - <_> - 17 5 1 2 2. + 18 1 2 13 2. 0 <_> <_> - 16 3 7 3 -1. + 16 2 3 2 -1. <_> - 16 4 7 1 3. + 17 2 1 2 3. 0 <_> <_> - 16 4 2 9 -1. + 16 3 2 3 -1. <_> - 16 7 2 3 3. + 16 4 2 1 3. 0 <_> <_> - 16 5 4 10 -1. + 16 4 1 3 -1. <_> - 16 5 2 5 2. - <_> - 18 10 2 5 2. + 16 5 1 1 3. 0 <_> <_> - 16 5 8 6 -1. + 16 4 2 2 -1. <_> - 16 5 4 3 2. + 16 4 1 1 2. <_> - 20 8 4 3 2. + 17 5 1 1 2. 0 <_> <_> - 16 6 2 6 -1. + 16 5 2 3 -1. <_> - 16 8 2 2 3. + 17 5 1 3 2. + 0 + <_> + + <_> + 16 6 2 9 -1. + <_> + 16 9 2 3 3. + 0 + <_> + + <_> + 16 6 4 4 -1. + <_> + 18 6 2 4 2. 0 <_> @@ -12105,16 +13033,9 @@ <_> <_> - 16 6 6 6 -1. + 16 6 7 6 -1. <_> - 16 8 6 2 3. - 0 - <_> - - <_> - 16 7 1 3 -1. - <_> - 16 8 1 1 3. + 16 8 7 2 3. 0 <_> @@ -12123,27 +13044,6 @@ <_> 16 9 1 2 3. 0 - <_> - - <_> - 16 7 3 16 -1. - <_> - 17 7 1 16 3. - 0 - <_> - - <_> - 16 7 4 1 -1. - <_> - 18 7 2 1 2. - 0 - <_> - - <_> - 16 7 2 2 -1. - <_> - 16 8 2 1 2. - 0 <_> <_> @@ -12151,13 +13051,6 @@ <_> 16 8 2 1 3. 0 - <_> - - <_> - 16 7 4 2 -1. - <_> - 18 7 2 2 2. - 0 <_> <_> @@ -12168,16 +13061,9 @@ <_> <_> - 16 7 2 15 -1. + 16 7 3 2 -1. <_> - 16 12 2 5 3. - 0 - <_> - - <_> - 16 7 4 6 -1. - <_> - 18 7 2 6 2. + 16 8 3 1 2. 0 <_> @@ -12193,6 +13079,22 @@ <_> 16 9 3 2 3. 0 + <_> + + <_> + 16 7 6 4 -1. + <_> + 16 7 3 2 2. + <_> + 19 9 3 2 2. + 0 + <_> + + <_> + 16 7 4 3 -1. + <_> + 16 8 4 1 3. + 0 <_> <_> @@ -12216,13 +13118,6 @@ <_> 17 9 1 1 2. 0 - <_> - - <_> - 16 8 2 5 -1. - <_> - 17 8 1 5 2. - 0 <_> <_> @@ -12233,18 +13128,18 @@ <_> <_> - 16 8 6 2 -1. + 16 8 8 2 -1. <_> - 16 8 3 1 2. + 16 8 4 1 2. <_> - 19 9 3 1 2. + 20 9 4 1 2. 0 <_> <_> - 16 8 6 3 -1. + 16 9 3 1 -1. <_> - 16 9 6 1 3. + 17 9 1 1 3. 0 <_> @@ -12256,9 +13151,46 @@ <_> <_> - 16 9 6 3 -1. + 16 9 2 3 -1. <_> - 16 10 6 1 3. + 17 9 1 3 2. + 0 + <_> + + <_> + 16 9 4 1 -1. + <_> + 18 9 2 1 2. + 0 + <_> + + <_> + 16 9 2 2 -1. + <_> + 16 10 2 1 2. + 0 + <_> + + <_> + 16 9 4 4 -1. + <_> + 18 9 2 4 2. + 0 + <_> + + <_> + 16 9 6 6 -1. + <_> + 16 9 3 3 2. + <_> + 19 12 3 3 2. + 0 + <_> + + <_> + 16 10 1 2 -1. + <_> + 16 11 1 1 2. 0 <_> @@ -12267,6 +13199,36 @@ <_> 16 11 1 1 3. 0 + <_> + + <_> + 16 10 2 2 -1. + <_> + 16 10 1 1 2. + <_> + 17 11 1 1 2. + 0 + <_> + + <_> + 16 10 2 2 -1. + <_> + 17 10 1 2 2. + 0 + <_> + + <_> + 16 10 2 5 -1. + <_> + 17 10 1 5 2. + 0 + <_> + + <_> + 16 10 3 13 -1. + <_> + 17 10 1 13 3. + 0 <_> <_> @@ -12277,25 +13239,16 @@ <_> <_> - 16 10 6 2 -1. + 16 10 3 3 -1. <_> - 16 10 3 1 2. - <_> - 19 11 3 1 2. + 16 11 3 1 3. 0 <_> <_> - 16 10 4 2 -1. + 16 11 1 2 -1. <_> - 16 11 4 1 2. - 0 - <_> - - <_> - 16 10 6 4 -1. - <_> - 16 12 6 2 2. + 16 12 1 1 2. 0 <_> @@ -12321,138 +13274,65 @@ <_> <_> - 16 11 3 3 -1. + 16 13 3 3 -1. <_> - 16 12 3 1 3. + 16 14 3 1 3. 0 <_> <_> - 16 11 4 2 -1. + 16 14 4 1 -1. <_> - 16 12 4 1 2. + 18 14 2 1 2. 0 <_> <_> - 16 11 8 6 -1. + 16 15 4 3 -1. <_> - 16 11 4 3 2. - <_> - 20 14 4 3 2. + 18 15 2 3 2. 0 <_> <_> - 16 12 4 8 -1. + 16 15 6 2 -1. <_> - 16 12 2 4 2. - <_> - 18 16 2 4 2. + 19 15 3 2 2. 0 <_> <_> - 16 13 2 2 -1. + 16 15 8 3 -1. <_> - 16 13 1 1 2. - <_> - 17 14 1 1 2. + 20 15 4 3 2. 0 <_> <_> - 16 13 4 6 -1. + 16 16 4 1 -1. <_> - 16 13 2 3 2. - <_> - 18 16 2 3 2. + 18 16 2 1 2. 0 <_> <_> - 16 13 8 8 -1. + 16 17 3 7 -1. <_> - 20 13 4 8 2. + 17 17 1 7 3. 0 <_> <_> - 16 14 8 5 -1. + 16 17 6 3 -1. <_> - 20 14 4 5 2. + 16 18 6 1 3. 0 <_> <_> - 16 15 4 4 -1. + 16 19 3 4 -1. <_> - 18 15 2 4 2. - 0 - <_> - - <_> - 16 15 4 8 -1. - <_> - 16 15 2 4 2. - <_> - 18 19 2 4 2. - 0 - <_> - - <_> - 16 15 3 3 -1. - <_> - 16 16 3 1 3. - 0 - <_> - - <_> - 16 15 6 3 -1. - <_> - 19 15 3 3 2. - 0 - <_> - - <_> - 16 16 3 3 -1. - <_> - 16 17 3 1 3. - 0 - <_> - - <_> - 16 18 3 3 -1. - <_> - 17 18 1 3 3. - 0 - <_> - - <_> - 16 18 3 6 -1. - <_> - 17 18 1 6 3. - 0 - <_> - - <_> - 16 20 3 4 -1. - <_> - 17 20 1 4 3. - 0 - <_> - - <_> - 16 22 3 1 -1. - <_> - 17 22 1 1 3. - 0 - <_> - - <_> - 17 0 1 8 -1. - <_> - 17 4 1 4 2. + 17 19 1 4 3. 0 <_> @@ -12464,9 +13344,9 @@ <_> <_> - 17 2 3 3 -1. + 17 2 1 4 -1. <_> - 18 2 1 3 3. + 17 4 1 2 2. 0 <_> @@ -12478,9 +13358,39 @@ <_> <_> - 17 3 4 15 -1. + 17 3 3 2 -1. <_> - 17 8 4 5 3. + 18 3 1 2 3. + 0 + <_> + + <_> + 17 3 2 8 -1. + <_> + 17 3 1 4 2. + <_> + 18 7 1 4 2. + 0 + <_> + + <_> + 17 3 3 3 -1. + <_> + 17 4 3 1 3. + 0 + <_> + + <_> + 17 4 1 3 -1. + <_> + 17 5 1 1 3. + 0 + <_> + + <_> + 17 4 2 2 -1. + <_> + 18 4 1 2 2. 0 <_> @@ -12494,9 +13404,18 @@ <_> <_> - 17 5 1 9 -1. + 17 6 1 6 -1. <_> - 17 8 1 3 3. + 17 8 1 2 3. + 0 + <_> + + <_> + 17 6 4 8 -1. + <_> + 17 6 2 4 2. + <_> + 19 10 2 4 2. 0 <_> @@ -12508,9 +13427,9 @@ <_> <_> - 17 6 4 3 -1. + 17 6 5 3 -1. <_> - 17 7 4 1 3. + 17 7 5 1 3. 0 <_> @@ -12529,9 +13448,11 @@ <_> <_> - 17 7 2 2 -1. + 17 7 2 6 -1. <_> - 17 8 2 1 2. + 17 7 1 3 2. + <_> + 18 10 1 3 2. 0 <_> @@ -12543,46 +13464,9 @@ <_> <_> - 17 7 2 6 -1. + 17 8 6 4 -1. <_> - 17 9 2 2 3. - 0 - <_> - - <_> - 17 7 3 3 -1. - <_> - 17 8 3 1 3. - 0 - <_> - - <_> - 17 8 1 3 -1. - <_> - 17 9 1 1 3. - 0 - <_> - - <_> - 17 8 2 2 -1. - <_> - 17 8 1 1 2. - <_> - 18 9 1 1 2. - 0 - <_> - - <_> - 17 8 1 4 -1. - <_> - 17 10 1 2 2. - 0 - <_> - - <_> - 17 8 5 14 -1. - <_> - 17 15 5 7 2. + 17 10 6 2 2. 0 <_> @@ -12594,16 +13478,34 @@ <_> <_> - 17 9 1 4 -1. + 17 9 2 6 -1. <_> - 17 11 1 2 2. + 17 9 1 3 2. + <_> + 18 12 1 3 2. 0 <_> <_> - 17 9 4 6 -1. + 17 9 4 2 -1. <_> - 17 11 4 2 3. + 17 9 2 1 2. + <_> + 19 10 2 1 2. + 0 + <_> + + <_> + 17 9 3 2 -1. + <_> + 17 10 3 1 2. + 0 + <_> + + <_> + 17 9 5 3 -1. + <_> + 17 10 5 1 3. 0 <_> @@ -12622,23 +13524,25 @@ <_> <_> - 17 10 3 14 -1. + 17 10 2 2 -1. <_> - 18 10 1 14 3. + 17 10 1 1 2. + <_> + 18 11 1 1 2. 0 <_> <_> - 17 10 4 1 -1. + 17 10 2 4 -1. <_> - 19 10 2 1 2. + 18 10 1 4 2. 0 <_> <_> - 17 10 2 3 -1. + 17 10 3 4 -1. <_> - 17 11 2 1 3. + 18 10 1 4 3. 0 <_> @@ -12652,9 +13556,9 @@ <_> <_> - 17 10 6 5 -1. + 17 11 1 3 -1. <_> - 20 10 3 5 2. + 17 12 1 1 3. 0 <_> @@ -12673,23 +13577,25 @@ <_> <_> - 17 11 3 11 -1. + 17 11 2 2 -1. <_> - 18 11 1 11 3. + 17 12 2 1 2. 0 <_> <_> - 17 11 3 4 -1. + 17 11 4 2 -1. <_> - 17 13 3 2 2. + 17 11 2 1 2. + <_> + 19 12 2 1 2. 0 <_> <_> - 17 12 3 1 -1. + 17 12 3 2 -1. <_> - 18 12 1 1 3. + 18 12 1 2 3. 0 <_> @@ -12701,85 +13607,107 @@ <_> <_> - 17 15 4 1 -1. + 17 14 2 3 -1. <_> - 19 15 2 1 2. + 17 15 2 1 3. 0 <_> <_> - 17 15 4 3 -1. + 17 14 4 2 -1. <_> - 19 15 2 3 2. + 19 14 2 2 2. 0 <_> <_> - 17 16 4 1 -1. + 17 15 4 2 -1. <_> - 19 16 2 1 2. + 19 15 2 2 2. 0 <_> <_> - 17 18 7 3 -1. + 17 16 4 3 -1. <_> - 17 19 7 1 3. + 19 16 2 3 2. 0 <_> <_> - 17 20 3 4 -1. + 17 17 3 7 -1. <_> - 18 20 1 4 3. + 18 17 1 7 3. 0 <_> <_> - 18 0 3 4 -1. + 17 19 3 4 -1. <_> - 19 0 1 4 3. + 18 19 1 4 3. 0 <_> <_> - 18 0 6 12 -1. + 17 21 3 3 -1. <_> - 18 0 3 6 2. - <_> - 21 6 3 6 2. + 18 21 1 3 3. 0 <_> <_> - 18 0 6 14 -1. + 18 0 4 1 -1. <_> - 18 0 3 7 2. - <_> - 21 7 3 7 2. + 20 0 2 1 2. 0 <_> <_> - 18 3 3 3 -1. + 18 0 6 1 -1. <_> - 19 3 1 3 3. + 21 0 3 1 2. 0 <_> <_> - 18 3 2 9 -1. + 18 0 6 4 -1. <_> - 18 6 2 3 3. + 21 0 3 4 2. 0 <_> <_> - 18 4 2 2 -1. + 18 1 1 12 -1. <_> - 18 4 1 1 2. + 18 5 1 4 3. + 0 + <_> + <_> - 19 5 1 1 2. + 18 2 3 3 -1. + <_> + 19 2 1 3 3. + 0 + <_> + + <_> + 18 3 3 2 -1. + <_> + 19 3 1 2 3. + 0 + <_> + + <_> + 18 3 1 9 -1. + <_> + 18 6 1 3 3. + 0 + <_> + + <_> + 18 3 3 4 -1. + <_> + 19 3 1 4 3. 0 <_> @@ -12791,18 +13719,16 @@ <_> <_> - 18 4 4 3 -1. + 18 4 3 4 -1. <_> - 18 5 4 1 3. + 19 4 1 4 3. 0 <_> <_> - 18 5 2 2 -1. + 18 5 6 15 -1. <_> - 18 5 1 1 2. - <_> - 19 6 1 1 2. + 21 5 3 15 2. 0 <_> @@ -12821,16 +13747,9 @@ <_> <_> - 18 6 5 3 -1. + 18 6 4 3 -1. <_> - 18 7 5 1 3. - 0 - <_> - - <_> - 18 7 1 2 -1. - <_> - 18 8 1 1 2. + 18 7 4 1 3. 0 <_> @@ -12851,21 +13770,7 @@ <_> 18 7 3 2 -1. <_> - 19 7 1 2 3. - 0 - <_> - - <_> - 18 7 2 3 -1. - <_> - 18 8 2 1 3. - 0 - <_> - - <_> - 18 7 3 3 -1. - <_> - 18 8 3 1 3. + 18 8 3 1 2. 0 <_> @@ -12874,6 +13779,15 @@ <_> 18 9 1 1 3. 0 + <_> + + <_> + 18 8 2 2 -1. + <_> + 18 8 1 1 2. + <_> + 19 9 1 1 2. + 0 <_> <_> @@ -12884,9 +13798,9 @@ <_> <_> - 18 8 6 8 -1. + 18 8 3 14 -1. <_> - 21 8 3 8 2. + 18 15 3 7 2. 0 <_> @@ -12911,20 +13825,6 @@ <_> 19 9 1 2 3. 0 - <_> - - <_> - 18 9 4 2 -1. - <_> - 20 9 2 2 2. - 0 - <_> - - <_> - 18 9 3 9 -1. - <_> - 18 12 3 3 3. - 0 <_> <_> @@ -12944,9 +13844,9 @@ <_> <_> - 18 10 2 8 -1. + 18 10 2 2 -1. <_> - 18 14 2 4 2. + 18 11 2 1 2. 0 <_> @@ -12955,6 +13855,13 @@ <_> 21 10 3 4 2. 0 + <_> + + <_> + 18 10 6 5 -1. + <_> + 21 10 3 5 2. + 0 <_> <_> @@ -12965,72 +13872,102 @@ <_> <_> - 18 11 3 12 -1. + 18 11 3 6 -1. <_> - 19 11 1 12 3. + 19 11 1 6 3. 0 <_> <_> - 18 12 3 3 -1. + 18 11 3 9 -1. <_> - 19 12 1 3 3. + 19 11 1 9 3. 0 <_> <_> - 18 12 6 1 -1. + 18 11 3 8 -1. <_> - 21 12 3 1 2. + 18 15 3 4 2. 0 <_> <_> - 18 12 3 6 -1. + 18 12 3 4 -1. <_> - 18 15 3 3 2. + 19 12 1 4 3. 0 <_> <_> - 18 15 1 3 -1. + 18 12 2 6 -1. <_> - 18 16 1 1 3. + 18 15 2 3 2. 0 <_> <_> - 18 15 6 5 -1. + 18 12 6 2 -1. <_> - 21 15 3 5 2. + 21 12 3 2 2. 0 <_> <_> - 18 16 4 2 -1. + 18 12 3 12 -1. <_> - 20 16 2 2 2. + 18 16 3 4 3. 0 <_> <_> - 18 17 3 6 -1. + 18 13 3 1 -1. <_> - 19 17 1 6 3. + 19 13 1 1 3. 0 <_> <_> - 18 18 3 5 -1. + 18 14 6 6 -1. <_> - 19 18 1 5 3. + 21 14 3 6 2. 0 <_> <_> - 19 0 3 1 -1. + 18 20 3 4 -1. <_> - 20 0 1 1 3. + 19 20 1 4 3. + 0 + <_> + + <_> + 18 20 6 3 -1. + <_> + 18 21 6 1 3. + 0 + <_> + + <_> + 19 2 2 4 -1. + <_> + 19 2 1 2 2. + <_> + 20 4 1 2 2. + 0 + <_> + + <_> + 19 4 1 4 -1. + <_> + 19 6 1 2 2. + 0 + <_> + + <_> + 19 4 1 20 -1. + <_> + 19 14 1 10 2. 0 <_> @@ -13039,6 +13976,13 @@ <_> 19 6 2 2 2. 0 + <_> + + <_> + 19 4 4 3 -1. + <_> + 19 5 4 1 3. + 0 <_> <_> @@ -13062,6 +14006,48 @@ <_> 19 7 2 1 3. 0 + <_> + + <_> + 19 6 5 3 -1. + <_> + 19 7 5 1 3. + 0 + <_> + + <_> + 19 6 5 9 -1. + <_> + 19 9 5 3 3. + 0 + <_> + + <_> + 19 7 1 12 -1. + <_> + 19 11 1 4 3. + 0 + <_> + + <_> + 19 7 2 3 -1. + <_> + 19 8 2 1 3. + 0 + <_> + + <_> + 19 8 1 3 -1. + <_> + 19 9 1 1 3. + 0 + <_> + + <_> + 19 8 2 3 -1. + <_> + 20 8 1 3 2. + 0 <_> <_> @@ -13072,9 +14058,18 @@ <_> <_> - 19 10 3 14 -1. + 19 9 3 2 -1. <_> - 20 10 1 14 3. + 20 9 1 2 3. + 0 + <_> + + <_> + 19 10 2 2 -1. + <_> + 19 10 1 1 2. + <_> + 20 11 1 1 2. 0 <_> @@ -13086,37 +14081,51 @@ <_> <_> - 19 11 3 12 -1. + 19 11 3 7 -1. <_> - 20 11 1 12 3. + 20 11 1 7 3. 0 <_> <_> - 19 12 3 10 -1. + 19 11 3 10 -1. <_> - 20 12 1 10 3. + 20 11 1 10 3. 0 <_> <_> - 19 13 3 1 -1. + 19 11 3 11 -1. <_> - 20 13 1 1 3. + 20 11 1 11 3. 0 <_> <_> - 19 17 3 7 -1. + 19 11 3 13 -1. <_> - 20 17 1 7 3. + 20 11 1 13 3. 0 <_> <_> - 19 18 3 5 -1. + 19 14 3 10 -1. <_> - 20 18 1 5 3. + 20 14 1 10 3. + 0 + <_> + + <_> + 19 15 3 2 -1. + <_> + 19 16 3 1 2. + 0 + <_> + + <_> + 19 18 3 3 -1. + <_> + 20 18 1 3 3. 0 <_> @@ -13128,32 +14137,30 @@ <_> <_> - 19 20 4 3 -1. + 19 20 5 3 -1. <_> - 19 21 4 1 3. + 19 21 5 1 3. 0 <_> <_> - 20 1 4 4 -1. + 20 4 1 3 -1. <_> - 22 1 2 4 2. + 20 5 1 1 3. 0 <_> <_> - 20 4 2 3 -1. + 20 5 1 2 -1. <_> - 20 5 2 1 3. + 20 6 1 1 2. 0 <_> <_> - 20 5 2 2 -1. + 20 5 1 3 -1. <_> - 20 5 1 1 2. - <_> - 21 6 1 1 2. + 20 6 1 1 3. 0 <_> @@ -13165,93 +14172,107 @@ <_> <_> - 20 11 4 3 -1. + 20 5 3 9 -1. <_> - 20 12 4 1 3. + 20 8 3 3 3. 0 <_> <_> - 20 12 3 8 -1. + 20 6 4 9 -1. <_> - 21 12 1 8 3. + 20 9 4 3 3. 0 <_> <_> - 20 12 3 11 -1. + 20 8 4 16 -1. <_> - 21 12 1 11 3. + 22 8 2 16 2. 0 <_> <_> - 20 12 3 12 -1. + 20 9 4 6 -1. <_> - 21 12 1 12 3. + 20 11 4 2 3. 0 <_> <_> - 20 18 3 1 -1. + 20 10 3 10 -1. <_> - 21 18 1 1 3. + 21 10 1 10 3. 0 <_> <_> - 21 4 1 3 -1. + 20 10 3 9 -1. <_> - 21 5 1 1 3. + 20 13 3 3 3. 0 <_> <_> - 21 9 3 3 -1. + 20 16 3 3 -1. <_> - 21 10 3 1 3. + 21 16 1 3 3. 0 <_> <_> - 21 9 3 6 -1. + 20 17 3 7 -1. <_> - 21 11 3 2 3. + 21 17 1 7 3. 0 <_> <_> - 21 10 2 4 -1. + 20 17 4 6 -1. <_> - 21 12 2 2 2. + 20 19 4 2 3. 0 <_> <_> - 21 12 3 9 -1. + 20 18 3 3 -1. <_> - 22 12 1 9 3. + 21 18 1 3 3. 0 <_> <_> - 21 13 3 11 -1. + 21 1 2 4 -1. <_> - 22 13 1 11 3. + 21 3 2 2 2. 0 <_> <_> - 21 15 3 4 -1. + 21 5 1 3 -1. <_> - 22 15 1 4 3. + 21 6 1 1 3. 0 <_> <_> - 21 15 3 9 -1. + 21 6 3 9 -1. <_> - 22 15 1 9 3. + 21 9 3 3 3. + 0 + <_> + + <_> + 21 10 3 3 -1. + <_> + 21 11 3 1 3. + 0 + <_> + + <_> + 21 13 3 7 -1. + <_> + 22 13 1 7 3. 0 <_> @@ -13263,23 +14284,44 @@ <_> <_> - 21 16 3 8 -1. + 21 16 3 7 -1. <_> - 22 16 1 8 3. + 22 16 1 7 3. 0 <_> <_> - 21 20 3 4 -1. + 21 17 3 5 -1. <_> - 22 20 1 4 3. + 22 17 1 5 3. 0 <_> <_> - 21 22 3 2 -1. + 21 17 3 6 -1. <_> - 22 22 1 2 3. + 21 19 3 2 3. + 0 + <_> + + <_> + 21 17 3 6 -1. + <_> + 21 20 3 3 2. + 0 + <_> + + <_> + 21 19 3 3 -1. + <_> + 22 19 1 3 3. + 0 + <_> + + <_> + 21 19 3 5 -1. + <_> + 22 19 1 5 3. 0 <_> @@ -13291,16 +14333,23 @@ <_> <_> - 22 12 2 12 -1. + 22 11 2 3 -1. <_> - 22 16 2 4 3. + 22 12 2 1 3. 0 <_> <_> - 22 20 2 3 -1. + 23 7 1 3 -1. <_> - 22 21 2 1 3. + 23 8 1 1 3. + 0 + <_> + + <_> + 23 9 1 3 -1. + <_> + 23 10 1 1 3. 0 <_> @@ -13312,8 +14361,22 @@ <_> <_> - 23 17 1 6 -1. + 23 14 1 9 -1. <_> - 23 19 1 2 3. + 23 17 1 3 3. + 0 + <_> + + <_> + 23 15 1 9 -1. + <_> + 23 18 1 3 3. + 0 + <_> + + <_> + 23 18 1 6 -1. + <_> + 23 20 1 2 3. 0 diff --git a/data/haarcascades/haarcascade_frontalcatface_extended.xml b/data/haarcascades/haarcascade_frontalcatface_extended.xml old mode 100644 new mode 100755 index 0777644517..5c4a0a62f6 --- a/data/haarcascades/haarcascade_frontalcatface_extended.xml +++ b/data/haarcascades/haarcascade_frontalcatface_extended.xml @@ -22,14 +22,19 @@ KNOWN LIMITATIONS: - Sometimes, the detector mistakenly thinks that a human face is a cat face. In - situations where either a human or a cat might be encountered, use both a - human face detector and a cat face detector. Then, if a detected human face - and a detected cat face intersect, reject the cat face. - An upright subject is assumed. In situations where the cat's face might be sideways or upside down (e.g. the cat is rolling over), try various rotations of the input image. + + CHANGELOG: + + 2016-08-06: Re-trained with more negative samples and more stages. False + positives are much rarer now. If you tailored your code for the cascade's + previous version, now you should re-adjust the arguments of + CascadeClassifier::detectMultiScale. For example, decrease the value of the + minNeighbors argument. You do not need to use a human face detector to + cross-check the positives anymore. + 2014-04-25: First release (at https://bitbucket.org/Joe_Howse/angora-blue) ////////////////////////////////////////////////////////////////////////// | Contributors License Agreement @@ -39,7 +44,7 @@ | If you do not agree to this license, do not download, install, | copy or use the software. | - | Copyright (c) 2014, Joseph Howse (Nummist Media Corporation Limited, + | Copyright (c) 2014-2016, Joseph Howse (Nummist Media Corporation Limited, | Halifax, Nova Scotia, Canada). All rights reserved. | | Redistribution and use in source and binary forms, with or without @@ -77,7 +82,7 @@ 24 GAB - 9.9900001287460327e-01 + 9.9500000476837158e-01 5.0000000000000000e-01 9.4999999999999996e-01 1 @@ -86,5564 +91,6036 @@ 0 1 ALL - 15 + 20 <_> - 28 - -2.0972909927368164e+00 + 13 + -1.4294912815093994e+00 <_> - 0 -1 388 -1.4772760681807995e-02 + 0 -1 394 -1.5126220881938934e-02 - 8.4035199880599976e-01 -1.2701500952243805e-01 + 7.5887596607208252e-01 -3.4230688214302063e-01 <_> - 0 -1 736 4.5831585302948952e-03 + 0 -1 737 3.9337221533060074e-03 - -2.3791725933551788e-01 6.1978793144226074e-01 + -3.3288389444351196e-01 5.2361363172531128e-01 <_> - 0 -1 754 -1.5044892206788063e-02 + 0 -1 757 -1.5044892206788063e-02 - 5.7160794734954834e-01 -2.0493283867835999e-01 + 5.5565774440765381e-01 -2.2505992650985718e-01 <_> - 0 -1 437 -1.5646889805793762e-02 + 0 -1 450 -1.5777055174112320e-02 - 7.6283878087997437e-01 -1.6358052194118500e-01 + 7.2692525386810303e-01 -1.6206762194633484e-01 <_> - 0 -1 432 3.0781796202063560e-02 + 0 -1 443 3.0781796202063560e-02 - -1.8158669769763947e-01 7.5050812959671021e-01 + -1.8173390626907349e-01 7.3483395576477051e-01 <_> - 0 -1 238 1.8483418971300125e-02 + 0 -1 220 1.8483418971300125e-02 - -2.0087972283363342e-01 5.2843624353408813e-01 + -1.8690711259841919e-01 5.0116515159606934e-01 <_> - 0 -1 680 1.3191045261919498e-02 + 0 -1 681 1.3474167324602604e-02 - -1.5244702994823456e-01 5.8166426420211792e-01 + -1.5681208670139313e-01 5.8611637353897095e-01 <_> - 0 -1 531 5.3334265947341919e-02 + 0 -1 554 5.3415738046169281e-02 - -1.6860350966453552e-01 7.1358704566955566e-01 + -1.6418528556823730e-01 6.8128466606140137e-01 <_> - 0 -1 782 8.3916599396616220e-04 + 0 -1 741 5.4243900813162327e-03 - -2.1746076643466949e-01 4.2143425345420837e-01 + -1.8231739103794098e-01 4.6716138720512390e-01 <_> - 0 -1 333 1.7697989940643311e-02 + 0 -1 336 1.7689792439341545e-02 - -1.3514791429042816e-01 6.1385941505432129e-01 + -1.3713267445564270e-01 6.0434049367904663e-01 <_> - 0 -1 290 -2.8310909867286682e-02 + 0 -1 187 2.2149257711134851e-04 - 5.3606474399566650e-01 -1.5554395318031311e-01 + -2.7738124132156372e-01 2.8165665268898010e-01 <_> - 0 -1 147 4.1034919559024274e-04 + 0 -1 288 -2.8517641127109528e-02 - -2.8903219103813171e-01 3.1018218398094177e-01 + 5.5257320404052734e-01 -1.2970162928104401e-01 <_> - 0 -1 537 3.9831817150115967e-02 + 0 -1 369 4.3854981660842896e-02 - -1.8419378995895386e-01 4.3500679731369019e-01 - <_> - - 0 -1 558 -5.2749719470739365e-03 - - -8.7773287296295166e-01 1.1703799664974213e-01 - <_> - - 0 -1 811 -3.6777660250663757e-02 - - 4.1285938024520874e-01 -2.1606418490409851e-01 - <_> - - 0 -1 324 9.4376102089881897e-02 - - -1.0109311342239380e-01 6.0879749059677124e-01 - <_> - - 0 -1 564 -1.6132533550262451e-02 - - 5.1245921850204468e-01 -1.5503944456577301e-01 - <_> - - 0 -1 507 -6.9251265376806259e-03 - - 4.2284211516380310e-01 -1.5949958562850952e-01 - <_> - - 0 -1 882 -8.4776207804679871e-03 - - 4.0007081627845764e-01 -1.6089719533920288e-01 - <_> - - 0 -1 110 -9.0452972799539566e-03 - - -7.6785671710968018e-01 9.3979701399803162e-02 - <_> - - 0 -1 246 3.0019454658031464e-02 - - -1.3505084812641144e-01 4.7249373793601990e-01 - <_> - - 0 -1 804 3.6142929457128048e-03 - - 8.1217512488365173e-02 -7.7168470621109009e-01 - <_> - - 0 -1 806 -4.7642881982028484e-03 - - -7.8209573030471802e-01 6.2777772545814514e-02 - <_> - - 0 -1 816 3.0351843684911728e-02 - - -1.1295587569475174e-01 5.8056473731994629e-01 - <_> - - 0 -1 146 -5.9288680553436279e-02 - - 5.5029523372650146e-01 -1.1994160711765289e-01 - <_> - - 0 -1 11 2.2238820791244507e-02 - - -1.4121483266353607e-01 4.5770901441574097e-01 - <_> - - 0 -1 294 -4.1477128863334656e-02 - - 5.7035386562347412e-01 -1.0164763778448105e-01 - <_> - - 0 -1 710 -1.1866136919707060e-03 - - 3.4064662456512451e-01 -1.6186751425266266e-01 + -1.9231440126895905e-01 4.2093500494956970e-01 <_> - 30 - -1.5367478132247925e+00 + 27 + -1.5509251356124878e+00 <_> - 0 -1 654 8.4006171673536301e-03 + 0 -1 337 2.4014184251427650e-02 - -1.0249307751655579e-01 7.6660197973251343e-01 + -2.1038578450679779e-01 7.3892170190811157e-01 <_> - 0 -1 443 -1.0703811421990395e-02 + 0 -1 475 -5.5319909006357193e-03 - 6.9929075241088867e-01 -1.6515852510929108e-01 + 4.4344031810760498e-01 -2.8907662630081177e-01 <_> - 0 -1 1 6.3192001543939114e-03 + 0 -1 4 2.7481060475111008e-02 - -2.2415910661220551e-01 4.3903940916061401e-01 + -1.9128543138504028e-01 5.1661676168441772e-01 <_> - 0 -1 651 2.0642649382352829e-02 + 0 -1 457 -1.1628001928329468e-02 - -1.8032769858837128e-01 5.8923733234405518e-01 + 5.1978123188018799e-01 -1.7051684856414795e-01 <_> - 0 -1 378 4.0111690759658813e-03 + 0 -1 393 1.5159824397414923e-03 - -2.4117745459079742e-01 5.4825514554977417e-01 + -2.9784303903579712e-01 3.9050224423408508e-01 <_> - 0 -1 173 2.0640484988689423e-02 + 0 -1 901 1.3662670738995075e-02 - -2.4204613268375397e-01 4.0820708870887756e-01 + -1.4316783845424652e-01 4.4111710786819458e-01 <_> - 0 -1 116 -9.2923976480960846e-03 + 0 -1 780 -3.6911026109009981e-03 - 3.6315548419952393e-01 -2.0153710246086121e-01 + 3.2185173034667969e-01 -2.3853960633277893e-01 <_> - 0 -1 851 3.5129714757204056e-02 + 0 -1 769 3.3176485449075699e-02 - -1.3475686311721802e-01 6.5953320264816284e-01 + -7.4603199958801270e-02 7.5860917568206787e-01 <_> - 0 -1 333 2.0278891548514366e-02 + 0 -1 317 -5.7046953588724136e-03 - -1.0143157839775085e-01 5.9142571687698364e-01 + -7.5004047155380249e-01 1.0240622609853745e-01 <_> - 0 -1 737 6.4985908102244139e-04 + 0 -1 73 7.9660946503281593e-03 - -1.9716840982437134e-01 3.4134888648986816e-01 + 9.8882928490638733e-02 -7.3491615056991577e-01 <_> - 0 -1 287 -6.6223340108990669e-03 + 0 -1 739 3.0965393409132957e-02 - -6.9885939359664917e-01 9.7095526754856110e-02 + -1.6046196222305298e-01 4.5570060610771179e-01 <_> - 0 -1 82 7.4231177568435669e-03 + 0 -1 612 -4.0078125894069672e-03 - 9.8552420735359192e-02 -6.5358603000640869e-01 + -7.1539020538330078e-01 6.9276176393032074e-02 <_> - 0 -1 692 -3.0081106349825859e-02 + 0 -1 647 -8.2283765077590942e-03 - 4.5352721214294434e-01 -1.4968612790107727e-01 + 3.2576236128807068e-01 -1.8509653210639954e-01 <_> - 0 -1 62 -6.0633812099695206e-02 + 0 -1 170 3.4253271296620369e-03 - 6.5072047710418701e-01 -9.9382333457469940e-02 + 1.0964145511388779e-01 -5.8205413818359375e-01 <_> - 0 -1 814 -5.1941806450486183e-03 + 0 -1 434 9.0980646200478077e-04 - 3.9397239685058594e-01 -1.6142791509628296e-01 + -2.0425215363502502e-01 2.7488732337951660e-01 <_> - 0 -1 261 6.0986238531768322e-03 + 0 -1 427 5.9772443026304245e-02 - 8.6411900818347931e-02 -7.3878693580627441e-01 + -1.3786207139492035e-01 4.0762668848037720e-01 <_> - 0 -1 108 -8.2402750849723816e-03 + 0 -1 209 -4.1712004691362381e-02 - -7.4236625432968140e-01 6.7853815853595734e-02 + 4.9409377574920654e-01 -1.1713714897632599e-01 <_> - 0 -1 908 -3.0396101996302605e-02 + 0 -1 248 -3.0311278998851776e-02 - 4.9337482452392578e-01 -1.3200622797012329e-01 + 5.1191121339797974e-01 -1.0507214814424515e-01 <_> - 0 -1 188 5.1566954702138901e-02 + 0 -1 339 -6.5785087645053864e-03 - -1.3631668686866760e-01 4.2621469497680664e-01 + -7.6472043991088867e-01 8.0923363566398621e-02 <_> - 0 -1 150 -9.3598978128284216e-04 + 0 -1 37 1.1685060337185860e-02 - 3.2463693618774414e-01 -2.0737074315547943e-01 + 5.0379037857055664e-02 -7.9744982719421387e-01 <_> - 0 -1 905 7.0394594222307205e-03 + 0 -1 423 6.5714016556739807e-02 - 8.9326366782188416e-02 -6.1088448762893677e-01 + -1.1398456245660782e-01 4.9489131569862366e-01 <_> - 0 -1 396 -6.5201576799154282e-03 + 0 -1 755 9.7422497346997261e-03 - 3.7555626034736633e-01 -1.5273806452751160e-01 + -1.4347794651985168e-01 3.6561754345893860e-01 <_> - 0 -1 103 3.9127394556999207e-03 + 0 -1 870 4.9857441335916519e-03 - 8.3254240453243256e-02 -7.3406547307968140e-01 + 7.9834438860416412e-02 -7.2391557693481445e-01 <_> - 0 -1 39 9.5308097079396248e-03 + 0 -1 735 -1.1547822505235672e-03 - -1.7045913636684418e-01 3.2230368256568909e-01 + 4.1867440938949585e-01 -1.2869183719158173e-01 <_> - 0 -1 796 1.5843525528907776e-02 + 0 -1 519 -4.4658007100224495e-03 - -1.4033445715904236e-01 3.9502236247062683e-01 + -6.7933702468872070e-01 8.2867160439491272e-02 <_> - 0 -1 555 5.9641832485795021e-03 + 0 -1 862 3.6325352266430855e-03 - 6.4340040087699890e-02 -8.5145986080169678e-01 + 6.6807270050048828e-02 -6.0182958841323853e-01 <_> - 0 -1 601 -4.8106643371284008e-03 + 0 -1 127 7.4123376980423927e-03 - -6.9040679931640625e-01 6.5658122301101685e-02 - <_> - - 0 -1 731 -9.3304895563051105e-04 - - 4.1242164373397827e-01 -1.4879603683948517e-01 - <_> - - 0 -1 779 4.1272714734077454e-03 - - -1.2624038755893707e-01 4.6513134241104126e-01 - <_> - - 0 -1 184 2.2929732222110033e-03 - - 1.0915581136941910e-01 -5.1519250869750977e-01 + -1.5108695626258850e-01 3.2046884298324585e-01 <_> - 44 - -1.6336240768432617e+00 + 26 + -1.3890913724899292e+00 <_> - 0 -1 334 2.5117650628089905e-02 + 0 -1 619 1.7836617305874825e-02 - 3.5861257463693619e-02 8.1681501865386963e-01 + -2.1508488059043884e-01 6.6796410083770752e-01 <_> - 0 -1 459 -6.6137146204710007e-03 + 0 -1 457 -8.5781915113329887e-03 - 4.6177890896797180e-01 -2.3009553551673889e-01 + 5.0962758064270020e-01 -2.2129471600055695e-01 <_> - 0 -1 394 -3.1423813197761774e-03 + 0 -1 165 3.1586211174726486e-02 - 4.0471413731575012e-01 -2.0868653059005737e-01 + -2.1485456824302673e-01 4.2591696977615356e-01 <_> - 0 -1 0 -3.7308693863451481e-03 + 0 -1 518 2.5690056383609772e-02 - 3.2831424474716187e-01 -2.6703229546546936e-01 + -1.5910078585147858e-01 6.7842948436737061e-01 <_> - 0 -1 178 7.8482955694198608e-02 + 0 -1 768 -2.2857591509819031e-02 - -1.5199472010135651e-01 4.6242395043373108e-01 + 5.7221925258636475e-01 -1.3710150122642517e-01 <_> - 0 -1 772 -2.6338286697864532e-03 + 0 -1 741 4.7176675871014595e-03 - 3.1739279627799988e-01 -2.3944588005542755e-01 + -2.3617559671401978e-01 3.9870622754096985e-01 <_> - 0 -1 75 9.2347152531147003e-02 + 0 -1 615 -2.3281413596123457e-03 - -1.5557752549648285e-01 6.0793381929397583e-01 + -7.0095318555831909e-01 1.3746888935565948e-01 <_> - 0 -1 315 -1.6786376014351845e-02 + 0 -1 139 1.0266102617606521e-03 - 5.2824962139129639e-01 -1.1138658970594406e-01 + -2.6873087882995605e-01 2.6495781540870667e-01 <_> - 0 -1 755 -3.8150474429130554e-02 + 0 -1 2 -7.6808528974652290e-03 - 4.3382674455642700e-01 -1.4826944470405579e-01 + 3.6925876140594482e-01 -2.1339643001556396e-01 <_> - 0 -1 318 4.3135927990078926e-03 + 0 -1 454 6.4357556402683258e-02 - 1.1878431588411331e-01 -5.8886390924453735e-01 + -1.1779088526964188e-01 5.5030888319015503e-01 <_> - 0 -1 412 7.1479372680187225e-02 + 0 -1 296 8.9486092329025269e-02 - -1.0972832888364792e-01 5.7183718681335449e-01 + -1.4395782351493835e-01 5.3468054533004761e-01 <_> - 0 -1 104 7.3613431304693222e-03 + 0 -1 253 -5.6334878318011761e-03 - 9.7729764878749847e-02 -6.5627050399780273e-01 + -6.5704786777496338e-01 1.3971389830112457e-01 <_> - 0 -1 414 5.1306895911693573e-02 + 0 -1 834 -8.0200601369142532e-03 - -1.6079875826835632e-01 4.0451571345329285e-01 + 3.6956611275672913e-01 -1.8284171819686890e-01 <_> - 0 -1 367 -4.7303801402449608e-03 + 0 -1 732 8.3984360098838806e-03 - -6.5826851129531860e-01 8.7291486561298370e-02 + -1.3507588207721710e-01 4.4903004169464111e-01 <_> - 0 -1 712 -1.8283914541825652e-03 + 0 -1 246 -5.7764705270528793e-03 - 3.7762144207954407e-01 -1.4564067125320435e-01 + -6.5459579229354858e-01 1.1050829291343689e-01 <_> - 0 -1 131 5.1737688481807709e-03 + 0 -1 630 3.9896301925182343e-02 - 8.7748050689697266e-02 -6.2685465812683105e-01 + -1.5822732448577881e-01 3.6069712042808533e-01 <_> - 0 -1 647 -3.2173446379601955e-03 + 0 -1 11 -6.8376958370208740e-02 - -7.3641878366470337e-01 5.7915702462196350e-02 + 6.2642019987106323e-01 -8.3647280931472778e-02 <_> - 0 -1 819 -5.4384516552090645e-03 + 0 -1 696 -2.7075063437223434e-02 - 4.2479231953620911e-01 -1.2763169407844543e-01 + 4.0549215674400330e-01 -1.4247153699398041e-01 <_> - 0 -1 159 2.6621888391673565e-03 + 0 -1 933 6.8107023835182190e-03 - -2.1836103498935699e-01 3.1271252036094666e-01 + 7.7754773199558258e-02 -6.4665120840072632e-01 <_> - 0 -1 125 1.2338031083345413e-02 + 0 -1 131 3.6659452598541975e-03 - 7.9128213226795197e-02 -8.1891500949859619e-01 + 7.9356946051120758e-02 -5.4679936170578003e-01 <_> - 0 -1 639 -1.0976660996675491e-02 + 0 -1 182 2.3308303207159042e-02 - 2.9887822270393372e-01 -1.8205311894416809e-01 + -1.4383231103420258e-01 3.4179633855819702e-01 <_> - 0 -1 646 1.4158659614622593e-03 + 0 -1 389 -3.2547116279602051e-02 - 8.9180864393711090e-02 -5.9163159132003784e-01 + 3.6395668983459473e-01 -1.2551946938037872e-01 <_> - 0 -1 141 -2.0067330449819565e-02 + 0 -1 471 1.6501296311616898e-02 - 2.6213398575782776e-01 -1.7981344461441040e-01 + -1.0674661397933960e-01 4.2714300751686096e-01 <_> - 0 -1 95 3.1120348721742630e-03 + 0 -1 616 -2.9296698048710823e-03 - 8.4207154810428619e-02 -5.7088595628738403e-01 + -5.7476091384887695e-01 8.5429534316062927e-02 <_> - 0 -1 121 -9.9351592361927032e-03 + 0 -1 828 1.3306898763403296e-03 - -7.2243571281433105e-01 5.1867216825485229e-02 + -1.2303277105093002e-01 3.7224721908569336e-01 <_> - 0 -1 198 1.3314767275005579e-03 + 0 -1 18 9.8933260887861252e-03 - -1.7091234028339386e-01 2.5805294513702393e-01 - <_> - - 0 -1 211 3.5102412104606628e-02 - - -1.1150742322206497e-01 4.2247176170349121e-01 - <_> - - 0 -1 780 2.4332102388143539e-02 - - -1.2760649621486664e-01 3.5613566637039185e-01 - <_> - - 0 -1 913 3.4916624426841736e-03 - - 7.4707798659801483e-02 -6.2106835842132568e-01 - <_> - - 0 -1 554 3.1960286200046539e-02 - - -8.5123799741268158e-02 5.5780071020126343e-01 - <_> - - 0 -1 210 2.5646466761827469e-02 - - 9.6616283059120178e-02 -4.8778736591339111e-01 - <_> - - 0 -1 65 4.8584854230284691e-03 - - 5.4295353591442108e-02 -6.2732213735580444e-01 - <_> - - 0 -1 525 -4.3544219806790352e-03 - - -5.7990497350692749e-01 5.8335512876510620e-02 - <_> - - 0 -1 818 1.5392700443044305e-03 - - -1.0273179411888123e-01 4.0286800265312195e-01 - <_> - - 0 -1 625 -3.5907807759940624e-03 - - -5.7972615957260132e-01 7.4733175337314606e-02 - <_> - - 0 -1 742 -2.6264857500791550e-02 - - 3.9446443319320679e-01 -1.1581628769636154e-01 - <_> - - 0 -1 458 1.6059044748544693e-02 - - -1.0167770087718964e-01 3.6267307400703430e-01 - <_> - - 0 -1 233 -4.1905373334884644e-02 - - 4.7364938259124756e-01 -8.8032789528369904e-02 - <_> - - 0 -1 42 2.0880695432424545e-02 - - -1.2106557935476303e-01 3.8552695512771606e-01 - <_> - - 0 -1 959 3.2229241915047169e-03 - - 6.9974288344383240e-02 -6.0391223430633545e-01 - <_> - - 0 -1 830 7.0135584101080894e-03 - - -1.0977950692176819e-01 3.7435680627822876e-01 - <_> - - 0 -1 798 -6.5330024808645248e-03 - - -6.9873285293579102e-01 5.8301825076341629e-02 - <_> - - 0 -1 766 -6.3728205859661102e-03 - - 2.4119727313518524e-01 -1.5554191172122955e-01 - <_> - - 0 -1 598 -3.9798039942979813e-03 - - 3.2675772905349731e-01 -1.1990765482187271e-01 + 6.7675270140171051e-02 -6.7935848236083984e-01 <_> - 48 - -1.6315091848373413e+00 + 31 + -1.4026626348495483e+00 <_> - 0 -1 398 -1.6997709870338440e-02 + 0 -1 876 -1.4927964657545090e-02 - 7.5603079795837402e-01 1.9442643970251083e-03 + 6.3834953308105469e-01 -1.8698258697986603e-01 <_> - 0 -1 858 -1.5086915343999863e-02 + 0 -1 467 -1.1759694665670395e-02 - 6.3829183578491211e-01 -1.4418891072273254e-01 + 5.0763273239135742e-01 -2.0944127440452576e-01 <_> - 0 -1 734 7.5988154858350754e-03 + 0 -1 775 1.1289508081972599e-02 - -1.6574914753437042e-01 4.6998679637908936e-01 + -1.4533838629722595e-01 5.3039866685867310e-01 <_> - 0 -1 440 -7.5363442301750183e-03 + 0 -1 335 1.3691024854779243e-02 - 4.4424122571945190e-01 -1.8298716843128204e-01 + -1.3143934309482574e-01 5.9853446483612061e-01 <_> - 0 -1 441 1.0129272937774658e-02 + 0 -1 399 -8.6051290854811668e-03 - -2.0301033556461334e-01 5.5256271362304688e-01 + 3.1604155898094177e-01 -2.2497664391994476e-01 <_> - 0 -1 732 3.0099015682935715e-02 + 0 -1 898 1.1611104011535645e-02 - -9.0159557759761810e-02 5.2430152893066406e-01 + -1.7180299758911133e-01 3.6340636014938354e-01 <_> - 0 -1 880 1.0154332034289837e-02 + 0 -1 919 5.4911419283598661e-04 - -2.1865487098693848e-01 3.7318554520606995e-01 + -2.0625770092010498e-01 3.0243906378746033e-01 <_> - 0 -1 753 -5.7211541570723057e-03 + 0 -1 448 -1.1997690424323082e-02 - 2.9541808366775513e-01 -2.3727707564830780e-01 + 6.7541980743408203e-01 -1.0784135758876801e-01 <_> - 0 -1 609 -2.3081460967659950e-03 + 0 -1 610 -2.0809918642044067e-03 - -6.5867960453033447e-01 8.6644835770130157e-02 + -5.7404327392578125e-01 1.1769672483205795e-01 <_> - 0 -1 892 3.4120366908609867e-03 + 0 -1 277 6.8656861782073975e-02 - 7.3793835937976837e-02 -6.1988431215286255e-01 + -1.4633083343505859e-01 4.1269731521606445e-01 <_> - 0 -1 423 1.1280932230874896e-03 + 0 -1 215 -4.5645810663700104e-02 - -1.7844060063362122e-01 2.9092252254486084e-01 + 5.4341620206832886e-01 -1.1726979166269302e-01 <_> - 0 -1 252 3.4356258809566498e-02 + 0 -1 890 -1.8052812665700912e-02 - -1.4515927433967590e-01 3.3726382255554199e-01 + 3.6646232008934021e-01 -1.3256482779979706e-01 <_> - 0 -1 583 4.2802840471267700e-02 + 0 -1 897 9.2329997569322586e-03 - -1.0719767957925797e-01 4.7673487663269043e-01 + 9.1808989644050598e-02 -6.4987671375274658e-01 <_> - 0 -1 395 -2.2776997648179531e-03 + 0 -1 142 -2.9587259050458670e-03 - 3.6087805032730103e-01 -1.2924250960350037e-01 + 2.4805040657520294e-01 -2.0830279588699341e-01 <_> - 0 -1 390 6.0573252849280834e-03 + 0 -1 151 -7.1467030793428421e-03 - 6.6139653325080872e-02 -7.4114394187927246e-01 + -6.6564339399337769e-01 8.8065519928932190e-02 <_> - 0 -1 271 -1.0843809694051743e-02 + 0 -1 756 -5.7738199830055237e-03 - 4.1086801886558533e-01 -1.3518220186233521e-01 + 2.4252247810363770e-01 -2.1394193172454834e-01 <_> - 0 -1 265 2.5435941293835640e-02 + 0 -1 207 6.4636822789907455e-03 - -1.2997664511203766e-01 3.8705968856811523e-01 + 8.4821723401546478e-02 -6.4125812053680420e-01 <_> - 0 -1 649 1.6918467590585351e-03 + 0 -1 527 -2.8782974928617477e-02 - 9.5908589661121368e-02 -6.5462106466293335e-01 + 3.5874211788177490e-01 -1.4370997250080109e-01 <_> - 0 -1 690 2.5078756734728813e-03 + 0 -1 715 -1.8174832221120596e-03 - 5.6727513670921326e-02 -6.1011266708374023e-01 + 3.7480926513671875e-01 -1.2761794030666351e-01 <_> - 0 -1 77 -1.0462226346135139e-02 + 0 -1 590 -1.9234847277402878e-03 - 3.6109340190887451e-01 -1.2214753031730652e-01 + -5.6678783893585205e-01 9.0299606323242188e-02 <_> - 0 -1 157 -1.6778277233242989e-02 + 0 -1 588 2.8048637323081493e-03 - -5.3534448146820068e-01 8.2928635179996490e-02 + 8.5870750248432159e-02 -5.8541411161422729e-01 <_> - 0 -1 831 -1.5040259808301926e-02 + 0 -1 178 7.0693701505661011e-02 - 2.8428143262863159e-01 -1.4685547351837158e-01 + -1.2318307906389236e-01 3.9827430248260498e-01 <_> - 0 -1 907 -6.6617773845791817e-03 + 0 -1 554 6.2659628689289093e-02 - -5.6624877452850342e-01 7.8970976173877716e-02 + -9.1229990124702454e-02 5.0639665126800537e-01 <_> - 0 -1 695 8.1638405099511147e-03 + 0 -1 321 -3.7420655135065317e-03 - -1.6379712522029877e-01 2.6822853088378906e-01 + 3.5059738159179688e-01 -1.2444343417882919e-01 <_> - 0 -1 52 1.9468305632472038e-02 + 0 -1 273 6.8388320505619049e-03 - -1.2091565877199173e-01 3.3373209834098816e-01 + -1.0419095307588577e-01 4.5085826516151428e-01 <_> - 0 -1 164 -6.4643016085028648e-03 + 0 -1 76 7.1193519979715347e-03 - -6.3222587108612061e-01 6.6180422902107239e-02 + 9.1205865144729614e-02 -5.2279585599899292e-01 <_> - 0 -1 284 3.5924967378377914e-02 + 0 -1 791 -9.8787562455981970e-04 - -1.0186699032783508e-01 4.2578670382499695e-01 + 2.8105542063713074e-01 -1.5169830620288849e-01 <_> - 0 -1 354 1.6905765980482101e-02 + 0 -1 639 1.8099821172654629e-03 - -1.3217522203922272e-01 3.3241125941276550e-01 + 6.5428622066974640e-02 -6.9196063280105591e-01 <_> - 0 -1 515 5.7176817208528519e-03 + 0 -1 726 -6.0212425887584686e-03 - 6.6569112241268158e-02 -6.5681034326553345e-01 + -6.2636482715606689e-01 5.1543414592742920e-02 <_> - 0 -1 276 -1.0900674387812614e-03 + 0 -1 818 5.1644006744027138e-03 - 3.9689606428146362e-01 -1.1235479265451431e-01 + 6.3040286302566528e-02 -6.3455927371978760e-01 <_> - 0 -1 760 -2.3833939805626869e-02 + 0 -1 205 9.4506526365876198e-03 - 3.8570886850357056e-01 -1.0193232446908951e-01 - <_> - - 0 -1 344 -1.4802538789808750e-02 - - 3.4205844998359680e-01 -1.4262656867504120e-01 - <_> - - 0 -1 448 3.9707131683826447e-02 - - -9.5635637640953064e-02 4.4075250625610352e-01 - <_> - - 0 -1 547 6.4531993120908737e-03 - - 5.7593464851379395e-02 -7.0275545120239258e-01 - <_> - - 0 -1 922 -4.7811353579163551e-03 - - 2.7453303337097168e-01 -1.3652370870113373e-01 - <_> - - 0 -1 896 3.3349171280860901e-03 - - 5.8540347963571548e-02 -7.1738266944885254e-01 - <_> - - 0 -1 127 -1.0832921601831913e-02 - - -6.2031352519989014e-01 4.7055520117282867e-02 - <_> - - 0 -1 696 -3.5385387018322945e-03 - - 2.7126258611679077e-01 -1.3402579724788666e-01 - <_> - - 0 -1 785 -2.1408915519714355e-02 - - 3.6707195639610291e-01 -1.0640451312065125e-01 - <_> - - 0 -1 617 6.6339373588562012e-02 - - -1.0504902899265289e-01 3.3936560153961182e-01 - <_> - - 0 -1 581 2.2766939364373684e-03 - - 7.2598882019519806e-02 -5.3970605134963989e-01 - <_> - - 0 -1 626 1.6875732690095901e-03 - - 8.7735749781131744e-02 -4.0284165740013123e-01 - <_> - - 0 -1 623 8.4530832245945930e-03 - - -9.3997113406658173e-02 4.1698867082595825e-01 - <_> - - 0 -1 429 5.5649573914706707e-03 - - -8.7597280740737915e-02 3.8827970623970032e-01 - <_> - - 0 -1 429 -3.5470342263579369e-03 - - 3.3585703372955322e-01 -1.3658957183361053e-01 - <_> - - 0 -1 954 4.2132395319640636e-03 - - 7.2930902242660522e-02 -5.1745194196701050e-01 - <_> - - 0 -1 527 3.4532562131062150e-04 - - -1.7970138788223267e-01 2.1011430025100708e-01 - <_> - - 0 -1 828 -4.0376763790845871e-03 - - 2.7334249019622803e-01 -1.3640886545181274e-01 + -1.3443979620933533e-01 3.1506177783012390e-01 <_> - 57 - -1.5859905481338501e+00 + 38 + -1.4621645212173462e+00 <_> - 0 -1 376 -1.5983805060386658e-02 + 0 -1 383 -1.5925668179988861e-02 - 7.4085760116577148e-01 5.4202862083911896e-02 + 6.2127149105072021e-01 -1.8520653247833252e-01 <_> - 0 -1 654 1.4518834650516510e-02 + 0 -1 648 1.0260052047669888e-02 - -1.6582691669464111e-01 5.1249128580093384e-01 + -2.4736632406711578e-01 4.2336893081665039e-01 <_> - 0 -1 820 -1.0167414322495461e-02 + 0 -1 3 5.7025998830795288e-03 - 4.5000806450843811e-01 -1.3064502179622650e-01 + -2.3670144379138947e-01 3.3228391408920288e-01 <_> - 0 -1 493 2.7079641819000244e-02 + 0 -1 264 9.3164276331663132e-03 - -1.6735902428627014e-01 6.3848841190338135e-01 + -1.7946784198284149e-01 4.6311038732528687e-01 <_> - 0 -1 774 1.9515088060870767e-03 + 0 -1 830 -5.0438079051673412e-03 - -1.1798944324254990e-01 3.9749121665954590e-01 + 4.4613519310951233e-01 -1.6072992980480194e-01 <_> - 0 -1 332 1.3693260028958321e-02 + 0 -1 793 2.8381291776895523e-03 - -8.5312500596046448e-02 5.4718613624572754e-01 + -1.8486896157264709e-01 3.5892590880393982e-01 <_> - 0 -1 254 6.0192337259650230e-03 + 0 -1 455 6.7377656698226929e-02 - 5.7217631489038467e-02 -6.6589832305908203e-01 + -1.7760114371776581e-01 3.9539518952369690e-01 <_> - 0 -1 139 -5.6810788810253143e-03 + 0 -1 44 -8.7916189804673195e-03 - -5.7089996337890625e-01 8.1808418035507202e-02 + -5.9182339906692505e-01 1.1145308613777161e-01 <_> - 0 -1 898 4.8240914475172758e-04 + 0 -1 874 1.3353329151868820e-02 - -2.2115968167781830e-01 2.1608626842498779e-01 + -1.1993711441755295e-01 4.8862439393997192e-01 <_> - 0 -1 699 -6.6948928870260715e-03 + 0 -1 324 -1.0008489713072777e-02 - -6.5513664484024048e-01 7.3252275586128235e-02 + 4.1768664121627808e-01 -1.2453128397464752e-01 <_> - 0 -1 607 -1.4181779697537422e-02 + 0 -1 795 -1.4410717412829399e-03 - 3.2152280211448669e-01 -1.5524932742118835e-01 + 3.4100320935249329e-01 -1.6849595308303833e-01 <_> - 0 -1 172 1.6027893871068954e-02 + 0 -1 123 1.1647527664899826e-01 - -1.3886103034019470e-01 3.2296729087829590e-01 + -9.7596585750579834e-02 4.2289251089096069e-01 <_> - 0 -1 379 3.8102023303508759e-02 + 0 -1 301 -9.8112244158983231e-03 - -8.4586337208747864e-02 5.0823771953582764e-01 + 2.6155915856361389e-01 -2.0234876871109009e-01 <_> - 0 -1 627 -6.8796845152974129e-03 + 0 -1 425 6.3042029738426208e-02 - 2.8458747267723083e-01 -1.6626659035682678e-01 + -1.2662252783775330e-01 3.6811619997024536e-01 <_> - 0 -1 316 -5.7869823649525642e-03 + 0 -1 553 -1.7675247043371201e-02 - -6.7561829090118408e-01 6.7125916481018066e-02 + 4.1690909862518311e-01 -1.1987055838108063e-01 <_> - 0 -1 84 -1.0403458960354328e-02 + 0 -1 105 4.0485346689820290e-03 - -6.8244606256484985e-01 5.5120140314102173e-02 + 7.0249855518341064e-02 -7.3556905984878540e-01 <_> - 0 -1 253 7.2765655815601349e-02 + 0 -1 675 8.2748252898454666e-03 - -1.2289700657129288e-01 3.4603855013847351e-01 + -1.6168670356273651e-01 2.8835350275039673e-01 <_> - 0 -1 145 -5.2832886576652527e-02 + 0 -1 313 -5.0843162462115288e-03 - 3.6294373869895935e-01 -1.1915811896324158e-01 + -5.8562570810317993e-01 8.9675068855285645e-02 <_> - 0 -1 791 -2.0185699686408043e-03 + 0 -1 249 6.0826279222965240e-03 - 3.0245268344879150e-01 -1.5617357194423676e-01 + 4.7766357660293579e-02 -6.8612217903137207e-01 <_> - 0 -1 606 -2.8552478179335594e-03 + 0 -1 48 8.5826087743043900e-03 - -6.5382599830627441e-01 6.9692179560661316e-02 + -1.6963686048984528e-01 2.6875671744346619e-01 <_> - 0 -1 167 -3.6076260730624199e-03 + 0 -1 38 2.4908576160669327e-02 - -5.5573904514312744e-01 6.0684457421302795e-02 + 8.5034154355525970e-02 -5.7059210538864136e-01 <_> - 0 -1 85 -1.2505692429840565e-03 + 0 -1 879 2.0448346622288227e-03 - 2.2487366199493408e-01 -1.7713856697082520e-01 + -1.8642950057983398e-01 2.3178242146968842e-01 <_> - 0 -1 643 1.6213182359933853e-02 + 0 -1 16 2.4130716919898987e-02 - 6.7865289747714996e-02 -5.5539685487747192e-01 + -1.2823060154914856e-01 3.4394741058349609e-01 <_> - 0 -1 24 -2.7728214859962463e-02 + 0 -1 154 -4.7494415193796158e-03 - -5.8333241939544678e-01 5.7263575494289398e-02 + -7.1827727556228638e-01 6.8053275346755981e-02 <_> - 0 -1 267 -1.2375607620924711e-03 + 0 -1 199 -1.7751917243003845e-02 - 2.9786622524261475e-01 -1.2998357415199280e-01 + -5.5972510576248169e-01 5.2141726016998291e-02 <_> - 0 -1 622 2.4766498245298862e-03 + 0 -1 339 5.5826390162110329e-03 - 8.8138826191425323e-02 -4.3225872516632080e-01 + 4.8266090452671051e-02 -5.9813541173934937e-01 <_> - 0 -1 382 1.0034437291324139e-03 + 0 -1 387 1.4416726771742105e-03 - -1.1115902662277222e-01 3.2714295387268066e-01 + -9.2707693576812744e-02 4.1495534777641296e-01 <_> - 0 -1 374 -6.4956350252032280e-03 + 0 -1 192 -2.1779362577944994e-03 - -7.0529288053512573e-01 6.1914756894111633e-02 + 2.7112621068954468e-01 -1.5071788430213928e-01 <_> - 0 -1 409 -1.2748142704367638e-02 + 0 -1 607 3.0656920280307531e-03 - 3.6699298024177551e-01 -1.0546508431434631e-01 + 6.0340058058500290e-02 -6.5465551614761353e-01 <_> - 0 -1 494 -5.6289080530405045e-03 + 0 -1 469 1.9947460293769836e-01 - -8.3690512180328369e-01 4.8901058733463287e-02 + -9.5098674297332764e-02 3.9016976952552795e-01 <_> - 0 -1 846 -3.0219005420804024e-03 + 0 -1 857 -2.0255323499441147e-02 - 2.2210697829723358e-01 -1.6297030448913574e-01 + 4.3044877052307129e-01 -8.8302992284297943e-02 <_> - 0 -1 938 2.9230308718979359e-03 + 0 -1 446 5.4685659706592560e-03 - 8.0248229205608368e-02 -4.7586214542388916e-01 + -8.7241113185882568e-02 3.9513549208641052e-01 <_> - 0 -1 620 -1.6901228576898575e-02 + 0 -1 463 -1.0883151553571224e-03 - 3.2134863734245300e-01 -1.1946766823530197e-01 + 2.9802373051643372e-01 -1.3696449995040894e-01 <_> - 0 -1 452 -1.6434368444606662e-03 + 0 -1 655 -5.0911568105220795e-03 - 3.5056352615356445e-01 -1.0065372288227081e-01 + -6.2439930438995361e-01 6.2544539570808411e-02 <_> - 0 -1 104 6.0744080692529678e-03 + 0 -1 221 -5.2395770326256752e-03 - 7.7158488333225250e-02 -5.0687175989151001e-01 + -6.9036418199539185e-01 4.5142117887735367e-02 <_> - 0 -1 677 -6.2521770596504211e-02 + 0 -1 955 4.0486194193363190e-02 - 3.5145899653434753e-01 -1.0493072122335434e-01 + -7.5753845274448395e-02 5.2426725625991821e-01 <_> - 0 -1 738 1.4936760999262333e-03 + 0 -1 300 4.1610337793827057e-03 - -1.1596123874187469e-01 3.1784045696258545e-01 + 6.6071115434169769e-02 -5.8079534769058228e-01 <_> - 0 -1 935 -4.6554272994399071e-03 + 0 -1 272 -6.4253048039972782e-03 - -5.8499008417129517e-01 6.5426386892795563e-02 - <_> - - 0 -1 718 5.1631154492497444e-03 - - 4.6380143612623215e-02 -6.5920770168304443e-01 - <_> - - 0 -1 431 5.7699503377079964e-03 - - -1.0032630711793900e-01 3.4062737226486206e-01 - <_> - - 0 -1 306 -9.6255233511328697e-03 - - 2.2360336780548096e-01 -1.5362788736820221e-01 - <_> - - 0 -1 372 -2.8061982244253159e-02 - - 2.5125834345817566e-01 -1.2988410890102386e-01 - <_> - - 0 -1 807 7.1229478344321251e-03 - - 5.3426012396812439e-02 -6.4893049001693726e-01 - <_> - - 0 -1 46 1.4473337680101395e-02 - - -1.2796792387962341e-01 2.5788536667823792e-01 - <_> - - 0 -1 240 -4.4487215578556061e-02 - - 4.8267531394958496e-01 -7.5288593769073486e-02 - <_> - - 0 -1 408 3.3553102985024452e-03 - - 6.5222866833209991e-02 -5.3387296199798584e-01 - <_> - - 0 -1 6 2.6522833853960037e-02 - - 4.7097213566303253e-02 -5.7117742300033569e-01 - <_> - - 0 -1 407 5.3791850805282593e-03 - - 4.9663346260786057e-02 -5.0957924127578735e-01 - <_> - - 0 -1 684 -8.8640749454498291e-03 - - 3.3878505229949951e-01 -8.6965307593345642e-02 - <_> - - 0 -1 78 2.7605522423982620e-02 - - 4.4678669422864914e-02 -6.9978964328765869e-01 - <_> - - 0 -1 944 -1.1171739548444748e-02 - - -7.3840415477752686e-01 3.0841451138257980e-02 - <_> - - 0 -1 731 -1.0616163490340114e-03 - - 3.0718466639518738e-01 -9.7260892391204834e-02 - <_> - - 0 -1 169 -7.2728879749774933e-03 - - -7.1966600418090820e-01 4.3096855282783508e-02 - <_> - - 0 -1 924 -1.1083125136792660e-02 - - 3.8436344265937805e-01 -8.1930950284004211e-02 - <_> - - 0 -1 674 -7.1662524715065956e-03 - - 2.0970225334167480e-01 -1.5484949946403503e-01 - <_> - - 0 -1 20 8.2661323249340057e-03 - - 5.9242360293865204e-02 -5.1503551006317139e-01 - <_> - - 0 -1 748 7.3844827711582184e-03 - - 3.3728431910276413e-02 -7.2390365600585938e-01 + 3.0481830239295959e-01 -1.1435022950172424e-01 <_> - 61 - -1.5647197961807251e+00 + 44 + -1.4235107898712158e+00 <_> - 0 -1 443 -7.5000515207648277e-03 + 0 -1 716 -2.2738082334399223e-03 - 6.9735616445541382e-01 -7.0126228965818882e-03 + 5.9519726037979126e-01 -1.6779936850070953e-01 <_> - 0 -1 713 -2.5447460357099771e-03 + 0 -1 457 -1.2204157188534737e-02 - 5.4742383956909180e-01 -1.3766847550868988e-01 + 4.6985983848571777e-01 -1.7339397966861725e-01 <_> - 0 -1 278 6.3486215658485889e-03 + 0 -1 754 3.1242824625223875e-03 - -1.5121677517890930e-01 6.0269719362258911e-01 + -2.2488421201705933e-01 3.4029743075370789e-01 <_> - 0 -1 860 2.5572092272341251e-03 + 0 -1 777 -3.9868438616394997e-03 - -2.1577885746955872e-01 3.9897701144218445e-01 + 3.8314539194107056e-01 -1.8952924013137817e-01 <_> - 0 -1 510 -6.5959235653281212e-03 + 0 -1 538 -5.4737669415771961e-03 - 3.2995587587356567e-01 -2.0266638696193695e-01 + 2.4583901464939117e-01 -2.3114782571792603e-01 <_> - 0 -1 857 1.5824008733034134e-02 + 0 -1 453 1.5154287219047546e-02 - -1.4384938776493073e-01 5.4570239782333374e-01 + -1.0675037652254105e-01 5.8347207307815552e-01 <_> - 0 -1 335 3.4904260188341141e-02 + 0 -1 397 -1.4294658321887255e-03 - -1.0439507663249969e-01 5.3645384311676025e-01 + 3.8292840123176575e-01 -1.2911921739578247e-01 <_> - 0 -1 2 7.4804951436817646e-03 + 0 -1 750 -7.4405185878276825e-03 - -1.7777608335018158e-01 3.0247840285301208e-01 + 2.8356546163558960e-01 -1.7810684442520142e-01 <_> - 0 -1 61 -5.1247365772724152e-02 + 0 -1 786 -4.0357224643230438e-03 - 5.7459318637847900e-01 -1.0999230295419693e-01 + 2.6303085684776306e-01 -1.6862161457538605e-01 <_> - 0 -1 629 -5.0416901707649231e-02 + 0 -1 618 -5.8342106640338898e-03 - 4.6202743053436279e-01 -8.9995197951793671e-02 + 3.2040205597877502e-01 -1.4103877544403076e-01 <_> - 0 -1 177 1.2860384769737720e-02 + 0 -1 161 1.7279960215091705e-02 - -1.5580976009368896e-01 2.6711037755012512e-01 + -1.7433850467205048e-01 2.7985212206840515e-01 <_> - 0 -1 645 2.3457493633031845e-02 + 0 -1 292 2.2125110030174255e-02 - 5.4399158805608749e-02 -7.5605469942092896e-01 + -1.1797516793012619e-01 4.0373948216438293e-01 <_> - 0 -1 775 -3.4703868441283703e-03 + 0 -1 958 -4.4059187173843384e-02 - 2.3663245141506195e-01 -1.6793093085289001e-01 + 5.2820503711700439e-01 -7.0916719734668732e-02 <_> - 0 -1 256 4.2368983849883080e-03 + 0 -1 194 -3.8316637277603149e-02 - 6.2613829970359802e-02 -6.2294322252273560e-01 + 3.8833045959472656e-01 -1.0811555385589600e-01 <_> - 0 -1 727 -8.7803313508629799e-03 + 0 -1 178 4.5704744756221771e-02 - 3.0670607089996338e-01 -1.2937802076339722e-01 + -1.7566929757595062e-01 3.4665411710739136e-01 <_> - 0 -1 38 7.3221437633037567e-03 + 0 -1 434 1.1523386929184198e-03 - 8.7675094604492188e-02 -4.8196199536323547e-01 + -1.7257389426231384e-01 2.5989890098571777e-01 <_> - 0 -1 176 5.7109566405415535e-03 + 0 -1 121 -1.0491746477782726e-02 - -1.6586679220199585e-01 2.4693855643272400e-01 + -6.1285555362701416e-01 7.1230083703994751e-02 <_> - 0 -1 393 -1.0330275399610400e-03 + 0 -1 395 -4.5014433562755585e-03 - 2.8573888540267944e-01 -1.2924034893512726e-01 + -5.7712453603744507e-01 5.8887075632810593e-02 <_> - 0 -1 558 -4.1551878675818443e-03 + 0 -1 950 -3.7281280383467674e-03 - -6.7751622200012207e-01 5.5871110409498215e-02 + -6.7359894514083862e-01 5.2957162261009216e-02 <_> - 0 -1 770 -8.7040066719055176e-03 + 0 -1 331 3.4461893141269684e-02 - 2.6861536502838135e-01 -1.4459304511547089e-01 + -1.0375578701496124e-01 3.7974634766578674e-01 <_> - 0 -1 196 3.9226360619068146e-02 + 0 -1 462 -1.3906960375607014e-03 - -1.0390799492597580e-01 3.5152482986450195e-01 + 3.9171192049980164e-01 -1.0048408061265945e-01 <_> - 0 -1 115 -4.7440445050597191e-03 + 0 -1 85 1.6332454979419708e-02 - 2.5985953211784363e-01 -1.4647118747234344e-01 + 8.6256101727485657e-02 -4.5887523889541626e-01 <_> - 0 -1 375 -3.9255903102457523e-03 + 0 -1 356 -6.0738036409020424e-03 - -5.1697838306427002e-01 7.4196860194206238e-02 + -5.2265202999114990e-01 6.5308839082717896e-02 <_> - 0 -1 273 -1.0538822039961815e-02 + 0 -1 486 -3.3630726393312216e-03 - 3.7007546424865723e-01 -1.1099486052989960e-01 + -5.6505429744720459e-01 5.5844355374574661e-02 <_> - 0 -1 336 -6.4126476645469666e-03 + 0 -1 418 -1.5329496003687382e-02 - -6.8768596649169922e-01 6.5695002675056458e-02 + 3.4475114941596985e-01 -1.0086353123188019e-01 <_> - 0 -1 614 -6.6444426774978638e-03 + 0 -1 587 -9.0496204793453217e-03 - 2.3941572010517120e-01 -1.5043427050113678e-01 + 2.9553902149200439e-01 -1.1406829208135605e-01 <_> - 0 -1 784 3.6154527217149734e-02 + 0 -1 794 -3.1109917908906937e-03 - -9.1301433742046356e-02 4.3764653801918030e-01 + -4.4897687435150146e-01 7.3615357279777527e-02 <_> - 0 -1 321 2.0614354871213436e-03 + 0 -1 939 3.3499556593596935e-03 - -1.0028914362192154e-01 3.4935840964317322e-01 + 5.4718658328056335e-02 -5.4810231924057007e-01 <_> - 0 -1 937 -2.6316416915506124e-03 + 0 -1 188 1.8374501960352063e-03 - -4.7376596927642822e-01 7.9684391617774963e-02 + -1.3522666692733765e-01 2.4655479192733765e-01 <_> - 0 -1 136 -6.9046420976519585e-03 + 0 -1 908 2.6134990621358156e-03 - -5.4207211732864380e-01 5.3584035485982895e-02 + 6.6369861364364624e-02 -4.7342041134834290e-01 <_> - 0 -1 792 -7.9165250062942505e-03 + 0 -1 65 -7.4155852198600769e-03 - 2.3244017362594604e-01 -1.4517860114574432e-01 + 2.0866124331951141e-01 -1.5775154531002045e-01 <_> - 0 -1 285 6.6963117569684982e-03 + 0 -1 515 3.9352793246507645e-03 - 5.6810487061738968e-02 -6.3260114192962646e-01 + 5.1660846918821335e-02 -6.2589824199676514e-01 <_> - 0 -1 810 -1.8640372902154922e-02 + 0 -1 735 -1.0450070258229971e-03 - 2.3912836611270905e-01 -1.4180511236190796e-01 + 3.3525371551513672e-01 -1.0084854811429977e-01 <_> - 0 -1 451 -1.2744618579745293e-03 + 0 -1 784 1.2639444321393967e-03 - 3.5026183724403381e-01 -9.4078496098518372e-02 + -1.2103077769279480e-01 2.7691018581390381e-01 <_> - 0 -1 385 -6.6458717919886112e-03 + 0 -1 479 7.7577251940965652e-03 - -6.4737498760223389e-01 5.4980348795652390e-02 + 4.6813234686851501e-02 -7.3385792970657349e-01 <_> - 0 -1 759 5.5033955723047256e-03 + 0 -1 18 -1.0632604360580444e-02 - 3.6262378096580505e-02 -7.0103096961975098e-01 + -7.1024382114410400e-01 3.3777639269828796e-02 <_> - 0 -1 371 -6.0990457423031330e-03 + 0 -1 183 1.8631946295499802e-02 - 3.1506294012069702e-01 -1.0298713296651840e-01 + -1.4613701403141022e-01 2.1491082012653351e-01 <_> - 0 -1 955 -9.5215532928705215e-04 + 0 -1 608 4.9128942191600800e-03 - -3.3243876695632935e-01 9.4536833465099335e-02 + 5.3445268422365189e-02 -6.3314527273178101e-01 <_> - 0 -1 133 -4.8709083348512650e-03 + 0 -1 473 -9.8230186849832535e-03 - -5.5286788940429688e-01 4.8858009278774261e-02 + 2.6917773485183716e-01 -1.1376978456974030e-01 <_> - 0 -1 476 -1.9530812278389931e-03 + 0 -1 910 -3.0754944309592247e-03 - 2.6475632190704346e-01 -1.2214422971010208e-01 + -5.0787961483001709e-01 6.1582125723361969e-02 <_> - 0 -1 852 -1.6108162701129913e-02 + 0 -1 659 -6.7374799400568008e-03 - 2.4747616052627563e-01 -1.4181286096572876e-01 + 2.3871047794818878e-01 -1.2552142143249512e-01 <_> - 0 -1 747 -3.3051617443561554e-02 + 0 -1 507 -1.1759715154767036e-02 - 4.7526669502258301e-01 -6.3493676483631134e-02 + 3.3646693825721741e-01 -9.4460532069206238e-02 <_> - 0 -1 465 -2.0969051867723465e-02 + 0 -1 318 -4.1377237066626549e-03 - 3.7475255131721497e-01 -8.7978623807430267e-02 + -5.0522220134735107e-01 6.2668189406394958e-02 <_> - 0 -1 862 -1.1976938694715500e-03 + 0 -1 320 1.7267453949898481e-03 - 2.8161275386810303e-01 -1.0515356063842773e-01 - <_> - - 0 -1 937 3.0867555178701878e-03 - - 6.1260223388671875e-02 -5.0152593851089478e-01 - <_> - - 0 -1 261 5.4881181567907333e-03 - - 5.0317917019128799e-02 -5.4196691513061523e-01 - <_> - - 0 -1 302 -3.6943652667105198e-03 - - -5.8759558200836182e-01 4.4150535017251968e-02 - <_> - - 0 -1 91 2.3760091513395309e-02 - - -1.0199809074401855e-01 3.0310767889022827e-01 - <_> - - 0 -1 86 -2.1728422492742538e-02 - - 3.1364366412162781e-01 -1.0069291293621063e-01 - <_> - - 0 -1 36 -2.5134570896625519e-02 - - -5.1455682516098022e-01 5.5909216403961182e-02 - <_> - - 0 -1 17 2.5713320821523666e-02 - - -1.2262356281280518e-01 2.5486063957214355e-01 - <_> - - 0 -1 600 3.4806665498763323e-03 - - 4.3244410306215286e-02 -7.0197206735610962e-01 - <_> - - 0 -1 96 -3.8689947687089443e-03 - - -5.8558273315429688e-01 4.0547560900449753e-02 - <_> - - 0 -1 787 -1.0773935355246067e-03 - - 3.0767098069190979e-01 -9.5467783510684967e-02 - <_> - - 0 -1 789 2.9714959673583508e-03 - - -7.1951679885387421e-02 3.9655500650405884e-01 - <_> - - 0 -1 67 -8.8994875550270081e-03 - - -6.3042962551116943e-01 4.7020766884088516e-02 - <_> - - 0 -1 588 6.7773810587823391e-03 - - -7.5779460370540619e-02 3.6968868970870972e-01 - <_> - - 0 -1 508 -8.9795496314764023e-03 - - 2.2023639082908630e-01 -1.3685037195682526e-01 - <_> - - 0 -1 258 -1.4680022373795509e-02 - - 2.9656830430030823e-01 -9.4061806797981262e-02 - <_> - - 0 -1 208 -9.5530468970537186e-03 - - 2.9208987951278687e-01 -1.0542043298482895e-01 - <_> - - 0 -1 847 -1.4967216411605477e-03 - - 2.1045146882534027e-01 -1.3942880928516388e-01 + -8.0607026815414429e-02 3.8304185867309570e-01 <_> - 67 - -1.5504211187362671e+00 + 47 + -1.4313566684722900e+00 <_> - 0 -1 454 -1.0960219427943230e-02 + 0 -1 882 -1.1920252814888954e-02 - 6.5447217226028442e-01 5.0713799893856049e-02 + 5.6617152690887451e-01 -1.5811842679977417e-01 <_> - 0 -1 864 -1.1516783386468887e-02 + 0 -1 568 -4.3085627257823944e-03 - 4.6027910709381104e-01 -1.5864185988903046e-01 + 4.4759327173233032e-01 -1.6846470534801483e-01 <_> - 0 -1 751 3.3400617539882660e-03 + 0 -1 883 1.1177745182067156e-03 - -2.1552324295043945e-01 3.4321418404579163e-01 + -1.5351393818855286e-01 4.3508940935134888e-01 <_> - 0 -1 154 -3.8353595882654190e-03 + 0 -1 798 3.5418532788753510e-02 - 3.3496814966201782e-01 -2.3464411497116089e-01 + -1.2973460555076599e-01 3.6943939328193665e-01 <_> - 0 -1 57 -5.9523088857531548e-03 + 0 -1 393 2.2405586205422878e-03 - 2.8272038698196411e-01 -2.0106634497642517e-01 + -1.8800468742847443e-01 3.2498928904533386e-01 <_> - 0 -1 788 -1.3916005846112967e-03 + 0 -1 265 -1.7982896417379379e-02 - 3.4103384613990784e-01 -1.5115562081336975e-01 + 4.5607218146324158e-01 -1.0459473729133606e-01 <_> - 0 -1 325 -2.2318472620099783e-03 + 0 -1 152 -4.9088716506958008e-02 - 3.1695351004600525e-01 -1.6021527349948883e-01 + 3.4279289841651917e-01 -1.5114119648933411e-01 <_> - 0 -1 677 8.3244532346725464e-02 + 0 -1 275 7.1780886501073837e-03 - -8.9079469442367554e-02 5.3136157989501953e-01 + 6.3825756311416626e-02 -6.2449872493743896e-01 <_> - 0 -1 832 4.8591636121273041e-02 + 0 -1 849 3.9123920723795891e-03 - -1.0279218852519989e-01 3.9601847529411316e-01 + 7.1502417325973511e-02 -6.3956946134567261e-01 <_> - 0 -1 921 9.5052458345890045e-03 + 0 -1 689 -4.1980943642556667e-03 - 5.5167526006698608e-02 -7.4528604745864868e-01 + 2.1998657286167145e-01 -1.9890366494655609e-01 <_> - 0 -1 612 -3.7635704502463341e-03 + 0 -1 660 -4.5476644299924374e-03 - -6.5434825420379639e-01 5.7055845856666565e-02 + 2.1866278350353241e-01 -1.9852560758590698e-01 <_> - 0 -1 809 1.7548685718793422e-04 + 0 -1 944 -4.4158436357975006e-03 - -2.3401582241058350e-01 1.6428647935390472e-01 + 2.3959043622016907e-01 -1.7090958356857300e-01 <_> - 0 -1 156 -5.4875545203685760e-02 + 0 -1 281 -4.7058244235813618e-03 - 2.5605452060699463e-01 -1.5396752953529358e-01 + -5.1537507772445679e-01 9.0310461819171906e-02 <_> - 0 -1 5 -6.1811439692974091e-02 + 0 -1 116 -8.7488889694213867e-03 - 4.2922756075859070e-01 -8.8362246751785278e-02 + 2.2937677800655365e-01 -1.8315380811691284e-01 <_> - 0 -1 229 1.3979763025417924e-03 + 0 -1 645 -3.1655649654567242e-03 - -7.3071695864200592e-02 4.5563563704490662e-01 + -7.3091191053390503e-01 6.5193220973014832e-02 <_> - 0 -1 229 -5.5876211263239384e-04 + 0 -1 267 6.4696683548390865e-03 - 2.9506489634513855e-01 -1.2031728774309158e-01 + -1.1077737808227539e-01 3.7207809090614319e-01 <_> - 0 -1 31 -4.3148966506123543e-03 + 0 -1 615 2.2985613904893398e-03 - -5.7403188943862915e-01 6.6134005784988403e-02 + 7.7800542116165161e-02 -5.1104581356048584e-01 <_> - 0 -1 228 -5.3551131859421730e-03 + 0 -1 359 4.5809363946318626e-03 - -5.2288484573364258e-01 6.9182172417640686e-02 + 5.7778771966695786e-02 -5.7898092269897461e-01 <_> - 0 -1 117 -3.6877401173114777e-02 + 0 -1 188 1.1279166210442781e-03 - 3.3143782615661621e-01 -1.2777587771415710e-01 + -1.7981146275997162e-01 1.9939005374908447e-01 <_> - 0 -1 364 4.1612848639488220e-02 + 0 -1 347 -1.2820301577448845e-02 - -1.4963860809803009e-01 2.9361200332641602e-01 + 5.1867282390594482e-01 -6.9989629089832306e-02 <_> - 0 -1 423 6.6619878634810448e-04 + 0 -1 810 4.4866472482681274e-02 - -1.8005952239036560e-01 2.1171462535858154e-01 + -1.4253044128417969e-01 3.0062338709831238e-01 <_> - 0 -1 155 2.2130949422717094e-02 + 0 -1 412 -3.5413210280239582e-03 - 5.7936761528253555e-02 -5.9410941600799561e-01 + -5.7618641853332520e-01 6.0328345745801926e-02 <_> - 0 -1 469 1.2182788923382759e-02 + 0 -1 362 -7.4678594246506691e-03 - -1.1940150707960129e-01 2.9696035385131836e-01 + -5.0187259912490845e-01 6.1294022947549820e-02 <_> - 0 -1 182 2.8001153841614723e-03 + 0 -1 678 1.8058011308312416e-02 - -1.4503511786460876e-01 2.2681860625743866e-01 + 5.3603217005729675e-02 -5.8919399976730347e-01 <_> - 0 -1 945 2.8729443438351154e-03 + 0 -1 935 -6.8098572082817554e-03 - 6.5800048410892487e-02 -4.9987852573394775e-01 + -5.4100829362869263e-01 5.5898215621709824e-02 <_> - 0 -1 63 -5.0598740577697754e-01 + 0 -1 307 3.6491458304226398e-03 - 6.1999630928039551e-01 -5.6771270930767059e-02 + 4.7378763556480408e-02 -5.9323132038116455e-01 <_> - 0 -1 219 -9.6983816474676132e-03 + 0 -1 284 1.4524955768138170e-03 - 3.2087686657905579e-01 -9.7375035285949707e-02 + -8.8994570076465607e-02 3.8729071617126465e-01 <_> - 0 -1 497 3.0797901563346386e-03 + 0 -1 219 -6.2408884987235069e-03 - -1.2448154389858246e-01 2.5827226042747498e-01 + -6.6442847251892090e-01 5.1082015037536621e-02 <_> - 0 -1 451 -1.5816848026588559e-03 + 0 -1 744 -9.9360430613160133e-04 - 4.1313612461090088e-01 -9.0998791158199310e-02 + 3.2972389459609985e-01 -1.0494423657655716e-01 <_> - 0 -1 101 -9.5680113881826401e-03 + 0 -1 285 3.9777760393917561e-03 - -7.0231872797012329e-01 5.5185325443744659e-02 + 5.4083213210105896e-02 -6.2114214897155762e-01 <_> - 0 -1 94 3.1543439254164696e-03 + 0 -1 380 -1.4884659089148045e-02 - 4.8739165067672729e-02 -5.4295998811721802e-01 + 2.4066454172134399e-01 -1.2317410856485367e-01 <_> - 0 -1 224 -7.8436743933707476e-04 + 0 -1 436 3.3154981210827827e-03 - 3.0286926031112671e-01 -1.0217373818159103e-01 + -1.1744727939367294e-01 2.9429042339324951e-01 <_> - 0 -1 143 4.3993473052978516e-01 + 0 -1 976 -4.7508114948868752e-03 - -4.0746804326772690e-02 7.4451828002929688e-01 + -4.5763325691223145e-01 6.7066885530948639e-02 <_> - 0 -1 565 -3.5277460701763630e-03 + 0 -1 779 -1.1973761022090912e-02 - -4.5241990685462952e-01 7.3149621486663818e-02 + 2.5750914216041565e-01 -1.1354148387908936e-01 <_> - 0 -1 468 8.3879064768552780e-03 + 0 -1 740 4.9072699621319771e-03 - 3.3294096589088440e-02 -7.2618806362152100e-01 + -1.1266437917947769e-01 3.0022394657135010e-01 <_> - 0 -1 818 9.9020544439554214e-04 + 0 -1 56 6.5630510449409485e-02 - -1.0716802626848221e-01 2.8766462206840515e-01 + -1.0180503129959106e-01 3.0517497658729553e-01 <_> - 0 -1 825 -2.9110300820320845e-03 + 0 -1 354 -2.3393325507640839e-02 - 2.8586754202842712e-01 -1.1559913307428360e-01 + 3.2443770766258240e-01 -9.5363102853298187e-02 <_> - 0 -1 242 -5.1425592973828316e-03 + 0 -1 834 -3.8902116939425468e-03 - -6.1106848716735840e-01 4.6430643647909164e-02 + 2.0148487389087677e-01 -1.4944279193878174e-01 <_> - 0 -1 69 1.7738080024719238e-01 + 0 -1 185 -2.5926973670721054e-02 - -7.0887565612792969e-02 4.1917768120765686e-01 + -4.4917497038841248e-01 6.9752328097820282e-02 <_> - 0 -1 389 -1.1850059032440186e-02 + 0 -1 173 -7.1825529448688030e-03 - 3.1747487187385559e-01 -1.0234380513429642e-01 + -5.6838059425354004e-01 4.9584377557039261e-02 <_> - 0 -1 529 -1.0039219632744789e-02 + 0 -1 548 -9.9399685859680176e-03 - 2.0376846194267273e-01 -1.4407536387443542e-01 + 3.0747908353805542e-01 -1.1064232140779495e-01 <_> - 0 -1 676 1.9497467204928398e-02 + 0 -1 978 -3.6286246031522751e-03 - 4.7855406999588013e-02 -5.7639378309249878e-01 + -6.0276371240615845e-01 5.2405584603548050e-02 <_> - 0 -1 193 5.5466167628765106e-02 + 0 -1 820 1.5756220091134310e-03 - -7.4624486267566681e-02 4.1103851795196533e-01 + -1.1615782976150513e-01 2.6717522740364075e-01 <_> - 0 -1 893 -3.9324127137660980e-03 + 0 -1 426 3.5662509500980377e-02 - -5.5429047346115112e-01 5.0012629479169846e-02 + -1.0885569453239441e-01 2.9044550657272339e-01 <_> - 0 -1 662 -8.9037272846326232e-04 + 0 -1 554 5.3282946348190308e-02 - 2.0536813139915466e-01 -1.3225764036178589e-01 + -8.1855505704879761e-02 4.0298762917518616e-01 <_> - 0 -1 3 4.6562731266021729e-02 + 0 -1 988 3.3901704009622335e-03 - -9.1293826699256897e-02 2.9735872149467468e-01 + 5.5047694593667984e-02 -5.4021596908569336e-01 <_> - 0 -1 548 -1.5474244952201843e-01 + 0 -1 384 1.3204356655478477e-03 - -8.6353981494903564e-01 3.4763321280479431e-02 - <_> - - 0 -1 893 2.4359119124710560e-03 - - 5.9721726924180984e-02 -4.1146609187126160e-01 - <_> - - 0 -1 402 1.3576634228229523e-02 - - -9.4201639294624329e-02 3.0719256401062012e-01 - <_> - - 0 -1 456 -9.8991915583610535e-03 - - 2.6257899403572083e-01 -9.5683693885803223e-02 - <_> - - 0 -1 479 -3.0812243930995464e-03 - - 2.1774919331073761e-01 -1.1509665846824646e-01 - <_> - - 0 -1 275 -1.9958070479333401e-03 - - 3.5399836301803589e-01 -7.2066798806190491e-02 - <_> - - 0 -1 919 3.0025159940123558e-03 - - 4.2854189872741699e-02 -6.0343819856643677e-01 - <_> - - 0 -1 836 -1.1377423070371151e-03 - - 2.0119668543338776e-01 -1.2889184057712555e-01 - <_> - - 0 -1 661 3.7626659031957388e-03 - - 4.6901285648345947e-02 -5.7279956340789795e-01 - <_> - - 0 -1 724 -3.9297584444284439e-03 - - 3.5875543951988220e-01 -7.3908790946006775e-02 - <_> - - 0 -1 885 -2.5286607444286346e-02 - - 3.5751584172248840e-01 -6.7418299615383148e-02 - <_> - - 0 -1 749 -3.9539579302072525e-03 - - 2.0609807968139648e-01 -1.4521332085132599e-01 - <_> - - 0 -1 911 -5.7711899280548096e-03 - - -5.2898341417312622e-01 4.7179169952869415e-02 - <_> - - 0 -1 701 -3.3264106605201960e-03 - - 2.2409056127071381e-01 -1.1467082053422928e-01 - <_> - - 0 -1 703 6.1332453042268753e-02 - - 3.7662509828805923e-02 -7.1230965852737427e-01 - <_> - - 0 -1 251 -1.4834193512797356e-02 - - -5.5149120092391968e-01 3.9850924164056778e-02 - <_> - - 0 -1 7 -1.0773484408855438e-01 - - -4.9263399839401245e-01 4.9221854656934738e-02 - <_> - - 0 -1 648 -6.5140398219227791e-03 - - -6.7663580179214478e-01 3.3736269921064377e-02 - <_> - - 0 -1 30 -2.4242542684078217e-02 - - -6.9796782732009888e-01 2.7110328897833824e-02 - <_> - - 0 -1 393 -1.7814380116760731e-03 - - 2.9062062501907349e-01 -8.0135107040405273e-02 - <_> - - 0 -1 801 4.7076190821826458e-03 - - 3.7101462483406067e-02 -6.7659527063369751e-01 + -9.4643965363502502e-02 3.0430349707603455e-01 <_> - 80 - -1.5639265775680542e+00 + 48 + -1.3744181394577026e+00 <_> - 0 -1 561 -4.3974462896585464e-03 + 0 -1 788 3.9594387635588646e-03 - 7.1587848663330078e-01 8.4948554635047913e-02 + -1.5454453229904175e-01 4.9922767281532288e-01 <_> - 0 -1 198 1.8174322322010994e-03 + 0 -1 467 -1.6322813928127289e-02 - -1.7691791057586670e-01 4.3212845921516418e-01 + 4.2537182569503784e-01 -1.5276345610618591e-01 <_> - 0 -1 735 -5.5131856352090836e-03 + 0 -1 746 1.6230947803705931e-03 - 4.5490756630897522e-01 -1.4189453423023224e-01 + -2.2640861570835114e-01 2.5220483541488647e-01 <_> - 0 -1 282 1.1955455876886845e-02 + 0 -1 115 -6.0441931709647179e-03 - -2.0918996632099152e-01 4.3714949488639832e-01 + 2.2711095213890076e-01 -2.1762822568416595e-01 <_> - 0 -1 819 -3.4246121067553759e-03 + 0 -1 6 1.1688062921166420e-02 - 3.5878163576126099e-01 -1.5395726263523102e-01 + -1.6991630196571350e-01 2.8343129158020020e-01 <_> - 0 -1 187 -4.3844994157552719e-02 + 0 -1 624 -3.1942571513354778e-03 - 4.3700152635574341e-01 -1.2767519056797028e-01 + -6.2475329637527466e-01 7.3184341192245483e-02 <_> - 0 -1 839 -6.3555962406098843e-03 + 0 -1 11 -7.6569117605686188e-02 - 2.9515129327774048e-01 -1.6441816091537476e-01 + 5.5236744880676270e-01 -7.7832877635955811e-02 <_> - 0 -1 534 -2.6965860743075609e-03 + 0 -1 306 1.8717286875471473e-03 - 1.9414065778255463e-01 -2.0237676799297333e-01 + 8.4293909370899200e-02 -5.2716743946075439e-01 <_> - 0 -1 460 -1.3908351771533489e-02 + 0 -1 351 3.5880310460925102e-03 - 2.5903883576393127e-01 -1.5587335824966431e-01 + -1.2907223403453827e-01 3.3967444300651550e-01 <_> - 0 -1 343 -1.4053133316338062e-02 + 0 -1 176 -5.7136151008307934e-03 - 5.4957073926925659e-01 -8.1244736909866333e-02 + -5.9208476543426514e-01 7.7793844044208527e-02 <_> - 0 -1 918 -5.3004794754087925e-03 + 0 -1 150 -1.9309867173433304e-02 - -5.8528614044189453e-01 7.3730856180191040e-02 + 2.5386241078376770e-01 -1.7397734522819519e-01 <_> - 0 -1 491 -3.1702318228781223e-03 + 0 -1 327 -2.4289516732096672e-03 - 1.9391658902168274e-01 -1.8859483301639557e-01 + 3.2221227884292603e-01 -1.2751287221908569e-01 <_> - 0 -1 474 -4.5197797007858753e-03 + 0 -1 25 -8.5500031709671021e-02 - -5.4193162918090820e-01 5.9990171343088150e-02 + -7.7962499856948853e-01 5.0715133547782898e-02 <_> - 0 -1 956 -5.4979130625724792e-02 + 0 -1 770 5.7447291910648346e-03 - 4.7812277078628540e-01 -6.7818723618984222e-02 + -1.1523491144180298e-01 3.6400210857391357e-01 <_> - 0 -1 876 8.1017805496230721e-04 + 0 -1 781 5.8936916291713715e-02 - -9.5595575869083405e-02 3.1569144129753113e-01 + -8.7829843163490295e-02 4.1893997788429260e-01 <_> - 0 -1 841 -2.8012446127831936e-03 + 0 -1 984 -4.1379006579518318e-03 - -4.9929830431938171e-01 6.8443782627582550e-02 + -6.3083720207214355e-01 6.4935714006423950e-02 <_> - 0 -1 833 -6.0123754665255547e-03 + 0 -1 565 -4.6407114714384079e-03 - 3.8719713687896729e-01 -8.9717194437980652e-02 + -6.5650087594985962e-01 5.4394256323575974e-02 <_> - 0 -1 842 3.6350139416754246e-03 + 0 -1 877 1.5865347813814878e-03 - 6.6413506865501404e-02 -4.8185935616493225e-01 + -1.7255148291587830e-01 2.3248092830181122e-01 <_> - 0 -1 452 -1.3544321991503239e-03 + 0 -1 624 2.8971401043236256e-03 - 2.5372084975242615e-01 -1.2267075479030609e-01 + 6.0526229441165924e-02 -5.4368048906326294e-01 <_> - 0 -1 827 -3.1020103488117456e-03 + 0 -1 773 1.5737174544483423e-03 - 2.7389132976531982e-01 -1.1379010230302811e-01 + -1.1744406074285507e-01 3.0534917116165161e-01 <_> - 0 -1 767 1.5349574387073517e-03 + 0 -1 609 1.6838097944855690e-03 - -1.0861707478761673e-01 2.8958576917648315e-01 + 6.6153712570667267e-02 -5.9224641323089600e-01 <_> - 0 -1 170 6.4284317195415497e-03 + 0 -1 912 3.2287575304508209e-03 - 5.9735804796218872e-02 -5.6773471832275391e-01 + 5.2678912878036499e-02 -5.7474386692047119e-01 <_> - 0 -1 280 -8.9295972138643265e-03 + 0 -1 850 -3.1512752175331116e-03 - -6.7040807008743286e-01 3.8283705711364746e-02 + 3.7773844599723816e-01 -8.7322145700454712e-02 <_> - 0 -1 764 -1.7896143253892660e-03 + 0 -1 894 8.2073279190808535e-04 - 2.1716582775115967e-01 -1.4856858551502228e-01 + -1.0513201355934143e-01 3.4025487303733826e-01 <_> - 0 -1 523 6.2072295695543289e-03 + 0 -1 603 2.8983387164771557e-03 - -8.8489770889282227e-02 3.3571973443031311e-01 + 5.1720291376113892e-02 -6.5431916713714600e-01 <_> - 0 -1 526 1.9034199649468064e-03 + 0 -1 852 -5.7246205396950245e-03 - 6.7696519196033478e-02 -4.5386880636215210e-01 + -7.8483843803405762e-01 3.5195719450712204e-02 <_> - 0 -1 524 -2.1953256800770760e-03 + 0 -1 44 -1.1572695337235928e-02 - -4.2716285586357117e-01 6.5683454275131226e-02 + -6.7286187410354614e-01 3.5210411995649338e-02 <_> - 0 -1 215 5.3394897840917110e-03 + 0 -1 80 -1.4562263153493404e-02 - -1.0160661488771439e-01 2.9586192965507507e-01 + 2.4655815958976746e-01 -1.2278749793767929e-01 <_> - 0 -1 763 2.0328685641288757e-03 + 0 -1 269 7.8490225132554770e-04 - -9.5586851239204407e-02 3.0505907535552979e-01 + -1.4652141928672791e-01 3.0276218056678772e-01 <_> - 0 -1 160 4.3488927185535431e-03 + 0 -1 725 -1.4289810787886381e-03 - 7.9764112830162048e-02 -3.8651520013809204e-01 + 1.8906314671039581e-01 -1.5791040658950806e-01 <_> - 0 -1 518 -4.0209172293543816e-03 + 0 -1 108 -9.4615388661623001e-03 - 3.0502754449844360e-01 -8.9127995073795319e-02 + -6.9036215543746948e-01 3.9911076426506042e-02 <_> - 0 -1 234 -4.8844739794731140e-02 + 0 -1 21 2.3225568234920502e-02 - 4.2813199758529663e-01 -6.7647248506546021e-02 + 5.0278317183256149e-02 -5.2323836088180542e-01 <_> - 0 -1 360 6.9915860891342163e-02 + 0 -1 959 1.4046948403120041e-02 - -8.3985306322574615e-02 3.2602414488792419e-01 + -7.9005211591720581e-02 4.0158179402351379e-01 <_> - 0 -1 535 4.9919363111257553e-02 + 0 -1 126 3.7851710803806782e-03 - -7.2998367249965668e-02 4.6169292926788330e-01 + -1.3530673086643219e-01 2.1973098814487457e-01 <_> - 0 -1 606 3.0068659689277411e-03 + 0 -1 142 -3.6725951358675957e-03 - 5.5069219321012497e-02 -6.1965858936309814e-01 + 1.9924460351467133e-01 -1.5001934766769409e-01 <_> - 0 -1 158 1.7419853247702122e-03 + 0 -1 963 -3.1669549643993378e-03 - -8.2020215690135956e-02 3.6006987094879150e-01 + -4.2041611671447754e-01 7.4019186198711395e-02 <_> - 0 -1 168 -4.1090780869126320e-03 + 0 -1 695 -1.3667810708284378e-02 - -5.2174150943756104e-01 5.6436747312545776e-02 + 2.5204744935035706e-01 -1.2807497382164001e-01 <_> - 0 -1 665 -4.5902859419584274e-03 + 0 -1 214 -3.5862527787685394e-02 - 2.2742575407028198e-01 -1.2061754614114761e-01 + 3.2997950911521912e-01 -8.9863941073417664e-02 <_> - 0 -1 27 -2.8690489009022713e-02 + 0 -1 946 -6.2667285092175007e-03 - -3.5808193683624268e-01 7.5659923255443573e-02 + -5.5024039745330811e-01 5.7369034737348557e-02 <_> - 0 -1 926 4.1000463068485260e-02 + 0 -1 438 -6.4383493736386299e-03 - -6.2531292438507080e-02 4.5491513609886169e-01 + 3.3817592263221741e-01 -9.3247875571250916e-02 <_> - 0 -1 126 -4.2531453073024750e-03 + 0 -1 439 5.4173925891518593e-03 - -6.1825770139694214e-01 4.9510892480611801e-02 + -1.0427469760179520e-01 2.9482829570770264e-01 <_> - 0 -1 670 -1.4550488442182541e-02 + 0 -1 400 -1.5132453292608261e-02 - -7.7191162109375000e-01 2.5961024686694145e-02 + 3.2000914216041565e-01 -9.8272062838077545e-02 <_> - 0 -1 288 -7.4881664477288723e-04 + 0 -1 606 -1.2513613328337669e-02 - 2.8547286987304688e-01 -8.8079601526260376e-02 + 2.8962445259094238e-01 -1.2084391713142395e-01 <_> - 0 -1 337 1.3214498758316040e-03 + 0 -1 91 -9.8966564983129501e-03 - -7.6633729040622711e-02 3.7057441473007202e-01 + -5.8358079195022583e-01 5.1291342824697495e-02 <_> - 0 -1 455 5.3907292895019054e-03 + 0 -1 932 1.3835988938808441e-02 - 4.9379035830497742e-02 -5.7583230733871460e-01 + -9.0702146291732788e-02 3.2527267932891846e-01 <_> - 0 -1 838 -2.4113813415169716e-03 + 0 -1 92 3.6492943763732910e-03 - 2.0829583704471588e-01 -1.3430447876453400e-01 + 8.4720104932785034e-02 -3.4649613499641418e-01 <_> - 0 -1 87 1.1464932933449745e-02 + 0 -1 478 -1.3878188095986843e-02 - 4.9434442073106766e-02 -6.5971946716308594e-01 + 2.9309025406837463e-01 -9.6585884690284729e-02 <_> - 0 -1 486 -1.3421529904007912e-02 + 0 -1 580 2.8816664125770330e-03 - -7.4524301290512085e-01 2.5121277198195457e-02 - <_> - - 0 -1 910 2.8626890853047371e-03 - - 6.1505425721406937e-02 -3.5306212306022644e-01 - <_> - - 0 -1 416 1.1442219838500023e-02 - - 5.3547207266092300e-02 -4.0409806370735168e-01 - <_> - - 0 -1 538 5.7390062138438225e-03 - - -9.7106143832206726e-02 2.4726873636245728e-01 - <_> - - 0 -1 485 -1.3369014486670494e-02 - - 3.4151887893676758e-01 -9.5434606075286865e-02 - <_> - - 0 -1 611 3.3499381970614195e-03 - - 4.9335762858390808e-02 -4.9601793289184570e-01 - <_> - - 0 -1 281 1.2374855577945709e-02 - - -5.7205036282539368e-02 5.0581747293472290e-01 - <_> - - 0 -1 500 2.7577474713325500e-02 - - -8.7777808308601379e-02 2.9972809553146362e-01 - <_> - - 0 -1 43 2.1137124300003052e-01 - - -6.2023047357797623e-02 4.0350961685180664e-01 - <_> - - 0 -1 221 -3.5103857517242432e-02 - - 2.9696103930473328e-01 -8.2776337862014771e-02 - <_> - - 0 -1 292 -2.8949903789907694e-03 - - -3.7250569462776184e-01 6.6616289317607880e-02 - <_> - - 0 -1 511 3.6181407049298286e-03 - - -9.3407385051250458e-02 2.5402054190635681e-01 - <_> - - 0 -1 445 1.1848636902868748e-02 - - -8.2135058939456940e-02 2.9939675331115723e-01 - <_> - - 0 -1 438 -1.0207802988588810e-02 - - 2.1719035506248474e-01 -1.1622364073991776e-01 - <_> - - 0 -1 257 3.0942540615797043e-02 - - 4.5177377760410309e-02 -5.0523322820663452e-01 - <_> - - 0 -1 16 -3.1778869032859802e-01 - - -8.8358139991760254e-01 2.1195204928517342e-02 - <_> - - 0 -1 513 -1.0037058964371681e-02 - - -5.8986192941665649e-01 3.0863022431731224e-02 - <_> - - 0 -1 888 9.1691948473453522e-03 - - -6.4322948455810547e-02 3.7386918067932129e-01 - <_> - - 0 -1 658 1.3658402487635612e-02 - - -1.0158041864633560e-01 2.6782375574111938e-01 - <_> - - 0 -1 309 2.7183804195374250e-03 - - 5.5635135620832443e-02 -3.9148023724555969e-01 - <_> - - 0 -1 310 1.3893332798033953e-03 - - -1.2399668246507645e-01 1.7072468996047974e-01 - <_> - - 0 -1 283 -1.8156928941607475e-02 - - -6.3868224620819092e-01 3.4263785928487778e-02 - <_> - - 0 -1 408 6.4471308141946793e-03 - - 1.8927905708551407e-02 -8.5299736261367798e-01 - <_> - - 0 -1 44 1.4844031073153019e-02 - - -1.2482391297817230e-01 1.7663741111755371e-01 - <_> - - 0 -1 50 -1.9531816244125366e-02 - - 3.1519362330436707e-01 -8.2499116659164429e-02 - <_> - - 0 -1 90 2.2133110091090202e-02 - - -9.0632885694503784e-02 2.2813312709331512e-01 - <_> - - 0 -1 119 -5.8851181529462337e-03 - - 2.0633347332477570e-01 -1.1403661221265793e-01 - <_> - - 0 -1 773 1.4685674104839563e-03 - - -6.8528242409229279e-02 3.6765024065971375e-01 - <_> - - 0 -1 856 -5.6167589500546455e-03 - - 2.1468248963356018e-01 -1.1975194513797760e-01 - <_> - - 0 -1 530 -1.0915055871009827e-01 - - 4.9222618341445923e-01 -4.6790093183517456e-02 - <_> - - 0 -1 638 -4.3774135410785675e-03 - - 2.6555654406547546e-01 -8.1355758011341095e-02 - <_> - - 0 -1 97 -5.5184490047395229e-03 - - -4.7854590415954590e-01 4.9387764185667038e-02 - <_> - - 0 -1 646 -1.8072805833071470e-03 - - -6.4401823282241821e-01 3.1085403636097908e-02 + -1.0839603841304779e-01 2.5134062767028809e-01 <_> - 91 - -1.5610778331756592e+00 + 57 + -1.3757541179656982e+00 <_> - 0 -1 821 -1.1308195069432259e-02 + 0 -1 742 -4.1507836431264877e-03 - 6.4171379804611206e-01 6.3050843775272369e-02 + 4.7857573628425598e-01 -1.5079282224178314e-01 <_> - 0 -1 454 -1.6007030382752419e-02 + 0 -1 539 -4.2431484907865524e-03 - 4.6389564871788025e-01 -1.2460056692361832e-01 + 2.7976706624031067e-01 -2.1182695031166077e-01 <_> - 0 -1 782 1.5086517669260502e-03 + 0 -1 422 7.2727665305137634e-02 - -1.4270767569541931e-01 3.3293032646179199e-01 + -1.1322361230850220e-01 4.6931907534599304e-01 <_> - 0 -1 207 -5.5297352373600006e-02 + 0 -1 120 7.3349894955754280e-03 - 4.7708284854888916e-01 -1.1913372576236725e-01 + -2.2507375478744507e-01 2.3486614227294922e-01 <_> - 0 -1 209 1.3316229917109013e-02 + 0 -1 79 -1.3757663965225220e-01 - -1.6993317008018494e-01 3.8821667432785034e-01 + 5.5153369903564453e-01 -8.4895148873329163e-02 <_> - 0 -1 752 8.1390906125307083e-03 + 0 -1 592 6.8098353222012520e-04 - -1.5329377353191376e-01 2.8196957707405090e-01 + -1.7585472762584686e-01 2.2849111258983612e-01 <_> - 0 -1 313 -1.5794128412380815e-03 + 0 -1 110 2.7579340338706970e-01 - -4.3692907691001892e-01 1.1585860699415207e-01 + -1.1671220511198044e-01 3.2674804329872131e-01 <_> - 0 -1 346 -7.4164522811770439e-03 + 0 -1 921 5.4910051403567195e-04 - -7.0102095603942871e-01 3.1883224844932556e-02 + -2.0603717863559723e-01 1.8896938860416412e-01 <_> - 0 -1 347 2.9237023554742336e-03 + 0 -1 155 -5.5065844208002090e-03 - -1.2032959610223770e-01 3.1826072931289673e-01 + -5.7701790332794189e-01 6.9212622940540314e-02 <_> - 0 -1 412 8.3931483328342438e-02 + 0 -1 824 -8.3996364846825600e-03 - -7.1062639355659485e-02 5.1401311159133911e-01 + 4.6683028340339661e-01 -7.4202880263328552e-02 <_> - 0 -1 879 5.1326253451406956e-03 + 0 -1 843 -1.1010931339114904e-03 - -1.5315851569175720e-01 2.3686404526233673e-01 + 1.9711431860923767e-01 -1.7736457288265228e-01 <_> - 0 -1 10 1.2808490544557571e-02 + 0 -1 217 -4.4837296009063721e-03 - -1.2817305326461792e-01 2.8131189942359924e-01 + -6.0108631849288940e-01 4.9327563494443893e-02 <_> - 0 -1 327 5.5591724812984467e-02 + 0 -1 211 2.5086081586778164e-03 - -9.7707554697990417e-02 3.7602767348289490e-01 + 6.9480538368225098e-02 -4.8671180009841919e-01 <_> - 0 -1 650 -2.4632480926811695e-03 + 0 -1 201 1.5808893367648125e-03 - -5.5093276500701904e-01 6.5490268170833588e-02 + -1.0519328713417053e-01 3.2050549983978271e-01 <_> - 0 -1 661 -3.1798938289284706e-03 + 0 -1 210 1.4971228083595634e-03 - -5.6288594007492065e-01 5.3227964788675308e-02 + -8.4364958107471466e-02 4.3016371130943298e-01 <_> - 0 -1 652 -1.4345918316394091e-03 + 0 -1 343 -2.6089220773428679e-03 - -5.1232701539993286e-01 5.7506360113620758e-02 + -4.2146065831184387e-01 8.8990658521652222e-02 <_> - 0 -1 861 1.9692238420248032e-03 + 0 -1 42 -7.7147269621491432e-03 - -1.6736923158168793e-01 1.8856795132160187e-01 + -6.6330111026763916e-01 5.0671890377998352e-02 <_> - 0 -1 261 -5.5519137531518936e-03 + 0 -1 85 -1.7141735181212425e-02 - -5.2823477983474731e-01 5.2204202860593796e-02 + -4.8750495910644531e-01 5.6981299072504044e-02 <_> - 0 -1 342 3.1600738875567913e-03 + 0 -1 146 1.3850606046617031e-02 - -8.0669216811656952e-02 3.6808264255523682e-01 + 7.4964463710784912e-02 -4.4079580903053284e-01 <_> - 0 -1 144 7.3207332752645016e-03 + 0 -1 341 -1.4932476915419102e-03 - 5.4134551435709000e-02 -5.3350186347961426e-01 + 3.1057041883468628e-01 -1.0369800031185150e-01 <_> - 0 -1 303 3.5804554354399443e-03 + 0 -1 382 -8.3094676956534386e-03 - 4.3425790965557098e-02 -5.3225243091583252e-01 + 2.2514784336090088e-01 -1.4621259272098541e-01 <_> - 0 -1 368 -3.4314931835979223e-03 + 0 -1 462 -7.2969077154994011e-04 - 3.3590000867843628e-01 -7.8590616583824158e-02 + 2.6934301853179932e-01 -1.2512375414371490e-01 <_> - 0 -1 958 6.8407682701945305e-03 + 0 -1 430 -1.3652374967932701e-02 - 4.5175880193710327e-02 -6.1210322380065918e-01 + -4.9215099215507507e-01 7.3141731321811676e-02 <_> - 0 -1 957 -4.1379006579518318e-03 + 0 -1 20 9.4011947512626648e-03 - -5.3888756036758423e-01 4.4202055782079697e-02 + 4.1364993900060654e-02 -6.5001028776168823e-01 <_> - 0 -1 350 1.3155659660696983e-02 + 0 -1 657 4.0921592153608799e-03 - -7.9103693366050720e-02 3.3573821187019348e-01 + 4.0478449314832687e-02 -5.9830683469772339e-01 <_> - 0 -1 356 3.1921269837766886e-03 + 0 -1 847 1.5591707779094577e-03 - 5.7063572108745575e-02 -5.0549602508544922e-01 + -9.3049824237823486e-02 3.1007137894630432e-01 <_> - 0 -1 906 2.3588772863149643e-02 + 0 -1 973 3.4408085048198700e-03 - -8.3102487027645111e-02 3.0777907371520996e-01 + 4.7337688505649567e-02 -6.5880972146987915e-01 <_> - 0 -1 464 -6.1599123291671276e-03 + 0 -1 847 -1.3411687687039375e-03 - 1.6074487566947937e-01 -1.5700389444828033e-01 + 2.8307750821113586e-01 -1.0693576931953430e-01 <_> - 0 -1 830 6.4594233408570290e-03 + 0 -1 534 -5.7181939482688904e-03 - -9.5241472125053406e-02 3.0516397953033447e-01 + -4.7754487395286560e-01 6.3519261777400970e-02 <_> - 0 -1 581 -2.0677673164755106e-03 + 0 -1 374 -5.0096530467271805e-03 - -5.0822901725769043e-01 5.9834387153387070e-02 + -6.1091655492782593e-01 3.9555240422487259e-02 <_> - 0 -1 872 2.0666117779910564e-03 + 0 -1 1 -4.1508115828037262e-03 - -7.2401538491249084e-02 3.5851547122001648e-01 + 2.1694649755954742e-01 -1.3193054497241974e-01 <_> - 0 -1 231 5.3266487084329128e-03 + 0 -1 844 -1.6968715935945511e-02 - 5.4928623139858246e-02 -4.8396179080009460e-01 + 2.7644789218902588e-01 -1.0202119499444962e-01 <_> - 0 -1 930 -7.7358852140605450e-03 + 0 -1 103 1.0276203043758869e-02 - -4.8261037468910217e-01 4.4207476079463959e-02 + -9.0598084032535553e-02 2.9703584313392639e-01 <_> - 0 -1 909 7.9007837921380997e-03 + 0 -1 350 -1.8649294506758451e-03 - -9.4954080879688263e-02 2.7517431974411011e-01 + 2.8791305422782898e-01 -9.2735975980758667e-02 <_> - 0 -1 470 4.0566008538007736e-03 + 0 -1 942 3.3354205079376698e-03 - 4.3646700680255890e-02 -5.8921122550964355e-01 + 5.3746312856674194e-02 -5.0940161943435669e-01 <_> - 0 -1 245 3.5946490243077278e-03 + 0 -1 396 -1.4105688314884901e-03 - -1.3110473752021790e-01 1.8304315209388733e-01 + 2.4489782750606537e-01 -1.1008579283952713e-01 <_> - 0 -1 206 -2.6677086949348450e-02 + 0 -1 611 2.3928448557853699e-02 - 2.8980365395545959e-01 -8.3346247673034668e-02 + 5.2839644253253937e-02 -4.9896511435508728e-01 <_> - 0 -1 213 5.4062507115304470e-03 + 0 -1 807 -3.8580424152314663e-03 - -9.1766953468322754e-02 2.9673796892166138e-01 + -4.8197838664054871e-01 5.3767576813697815e-02 <_> - 0 -1 230 -5.1793372258543968e-03 + 0 -1 679 -3.0590491369366646e-03 - -6.1112493276596069e-01 4.3332517147064209e-02 + -5.2978992462158203e-01 4.6741079539060593e-02 <_> - 0 -1 397 -9.1262701898813248e-03 + 0 -1 468 -2.9391471762210131e-03 - 2.1878185868263245e-01 -1.1105874925851822e-01 + -3.4711557626724243e-01 6.9464050233364105e-02 <_> - 0 -1 387 9.5943324267864227e-03 + 0 -1 667 -7.0184348151087761e-03 - -8.7977558374404907e-02 3.2010060548782349e-01 + 3.1962895393371582e-01 -8.3362981677055359e-02 <_> - 0 -1 668 -5.0256419926881790e-03 + 0 -1 664 1.0384586639702320e-03 - 2.1040959656238556e-01 -1.0872460156679153e-01 + -1.0797444730997086e-01 2.4896475672721863e-01 <_> - 0 -1 681 3.0062482692301273e-03 + 0 -1 628 -8.0418614670634270e-03 - -1.0699967294931412e-01 2.9316556453704834e-01 + -7.3527222871780396e-01 3.6740459501743317e-02 <_> - 0 -1 744 1.1852329596877098e-02 + 0 -1 193 -3.1738542020320892e-02 - 3.9550069719552994e-02 -6.0533910989761353e-01 + 2.6166516542434692e-01 -1.0992183536291122e-01 <_> - 0 -1 533 -5.2753865718841553e-02 + 0 -1 194 3.6780342459678650e-02 - 2.6370123028755188e-01 -9.2691496014595032e-02 + -8.7741106748580933e-02 3.7106978893280029e-01 <_> - 0 -1 446 3.8847257383167744e-03 + 0 -1 494 -6.4193591475486755e-02 - 6.4825706183910370e-02 -4.1523045301437378e-01 + 3.1807181239128113e-01 -8.8648937642574310e-02 <_> - 0 -1 556 -2.6287192013114691e-03 + 0 -1 46 3.4801474213600159e-01 - -5.0846499204635620e-01 4.2991567403078079e-02 + -5.5967021733522415e-02 5.3631168603897095e-01 <_> - 0 -1 330 2.2053448483347893e-03 + 0 -1 490 7.5712919235229492e-02 - -1.0581049323081970e-01 2.3079065978527069e-01 + -5.9786085039377213e-02 4.1973164677619934e-01 <_> - 0 -1 552 -3.7466879002749920e-03 + 0 -1 983 7.8374873846769333e-03 - -5.2957397699356079e-01 4.6158149838447571e-02 + -6.8252839148044586e-02 3.9001336693763733e-01 <_> - 0 -1 501 -2.9029445722699165e-03 + 0 -1 867 3.3967243507504463e-03 - -4.1290035843849182e-01 5.1479596644639969e-02 + 5.7270396500825882e-02 -4.7492286562919617e-01 <_> - 0 -1 13 3.7801317870616913e-02 + 0 -1 158 3.2095968723297119e-02 - -1.0680335760116577e-01 2.2418104112148285e-01 + 3.0982470139861107e-02 -7.2973543405532837e-01 <_> - 0 -1 73 -8.4752835333347321e-02 + 0 -1 939 4.1734268888831139e-03 - -7.8421443700790405e-01 3.0642487108707428e-02 + 3.0397623777389526e-02 -6.8009066581726074e-01 <_> - 0 -1 619 9.6596507355570793e-03 + 0 -1 545 3.2336891163140535e-03 - -9.7389675676822662e-02 2.4497544765472412e-01 + -9.4194613397121429e-02 2.5351443886756897e-01 <_> - 0 -1 519 7.2564175352454185e-03 + 0 -1 55 -3.8070861250162125e-02 - -9.8195895552635193e-02 2.9686492681503296e-01 + 2.7447724342346191e-01 -8.3862110972404480e-02 <_> - 0 -1 33 -1.0029030963778496e-02 + 0 -1 358 4.6657784841954708e-03 - -5.6505876779556274e-01 4.1911888867616653e-02 + 3.7179920822381973e-02 -6.7654901742935181e-01 <_> - 0 -1 540 -9.7039304673671722e-03 + 0 -1 247 -3.9379103109240532e-03 - 2.1148304641246796e-01 -1.0376640409231186e-01 + -5.9923279285430908e-01 3.2963614910840988e-02 <_> - 0 -1 425 -1.8890092615038157e-03 + 0 -1 699 -4.8031057231128216e-03 - 2.2384525835514069e-01 -1.0597650706768036e-01 - <_> - - 0 -1 587 -1.4225458726286888e-03 - - 2.1189780533313751e-01 -1.1053096503019333e-01 - <_> - - 0 -1 301 4.3249968439340591e-03 - - 4.1859358549118042e-02 -5.3136503696441650e-01 - <_> - - 0 -1 418 -2.5746987666934729e-03 - - -3.3480682969093323e-01 6.2653385102748871e-02 - <_> - - 0 -1 822 1.9772505387663841e-02 - - -5.8535441756248474e-02 3.9204162359237671e-01 - <_> - - 0 -1 255 -9.6579845994710922e-03 - - 2.2001895308494568e-01 -9.4623439013957977e-02 - <_> - - 0 -1 320 1.5255061443895102e-03 - - -8.3463013172149658e-02 3.1410121917724609e-01 - <_> - - 0 -1 136 6.2276879325509071e-03 - - 5.6847181171178818e-02 -4.1030114889144897e-01 - <_> - - 0 -1 214 9.0132874902337790e-04 - - -8.4593303501605988e-02 2.7151137590408325e-01 - <_> - - 0 -1 953 -4.6218577772378922e-03 - - -4.0008178353309631e-01 5.6437231600284576e-02 - <_> - - 0 -1 730 -1.5077156014740467e-02 - - 2.3747061192989349e-01 -9.1518931090831757e-02 - <_> - - 0 -1 34 2.1273698657751083e-02 - - 5.3466927260160446e-02 -4.5392176508903503e-01 - <_> - - 0 -1 227 -6.0164434835314751e-03 - - 2.3596890270709991e-01 -1.2803076207637787e-01 - <_> - - 0 -1 148 8.9327711611986160e-03 - - 4.2524505406618118e-02 -5.8664286136627197e-01 - <_> - - 0 -1 118 7.3118656873703003e-03 - - -6.9641888141632080e-02 3.3589112758636475e-01 - <_> - - 0 -1 616 2.6424862444400787e-03 - - 3.4661941230297089e-02 -6.7860239744186401e-01 - <_> - - 0 -1 641 5.9287068434059620e-03 - - 2.7298627421259880e-02 -6.5472942590713501e-01 - <_> - - 0 -1 877 -7.8424429520964622e-03 - - -6.3548064231872559e-01 2.7554484084248543e-02 - <_> - - 0 -1 541 -2.1585542708635330e-03 - - 2.2929325699806213e-01 -9.0029284358024597e-02 - <_> - - 0 -1 484 1.5804420690983534e-03 - - -9.7765833139419556e-02 2.2442239522933960e-01 - <_> - - 0 -1 478 -1.2139983475208282e-02 - - 2.9934337735176086e-01 -7.2730682790279388e-02 - <_> - - 0 -1 149 2.2737295366823673e-03 - - 4.6053361147642136e-02 -4.7994795441627502e-01 - <_> - - 0 -1 229 2.0574156660586596e-03 - - -4.9065478146076202e-02 4.6873793005943298e-01 - <_> - - 0 -1 132 5.9092035517096519e-03 - - 3.3293012529611588e-02 -6.2421238422393799e-01 - <_> - - 0 -1 569 -2.0584808662533760e-02 - - 2.6486057043075562e-01 -7.6441936194896698e-02 - <_> - - 0 -1 92 1.1120462790131569e-02 - - 4.4590156525373459e-02 -5.2196294069290161e-01 - <_> - - 0 -1 797 -3.4440308809280396e-03 - - 1.5679638087749481e-01 -1.3589784502983093e-01 - <_> - - 0 -1 963 -1.0556755587458611e-02 - - 3.0609151721000671e-01 -7.2761178016662598e-02 - <_> - - 0 -1 67 8.1238988786935806e-03 - - 4.4047191739082336e-02 -4.8989585041999817e-01 - <_> - - 0 -1 25 -1.1493992060422897e-02 - - 2.0072945952415466e-01 -1.1034463346004486e-01 - <_> - - 0 -1 586 2.3690698668360710e-02 - - -1.2550449371337891e-01 1.8665367364883423e-01 - <_> - - 0 -1 871 1.5682559460401535e-02 - - -7.4671298265457153e-02 2.8130453824996948e-01 - <_> - - 0 -1 399 -3.3444758504629135e-02 - - 2.6843747496604919e-01 -8.3811916410923004e-02 - <_> - - 0 -1 610 3.0884463340044022e-02 - - -9.9225074052810669e-02 2.2484876215457916e-01 - <_> - - 0 -1 222 -4.0955815464258194e-02 - - 1.8551258742809296e-01 -1.1869347840547562e-01 + 2.2248022258281708e-01 -1.0560184717178345e-01 <_> - 90 - -1.4453492164611816e+00 + 55 + -1.3843152523040771e+00 <_> - 0 -1 735 -4.5189578086137772e-03 + 0 -1 456 6.7532630637288094e-03 - 6.7139738798141479e-01 9.2261902987957001e-02 + -1.5934121608734131e-01 5.1630091667175293e-01 <_> - 0 -1 199 4.2574461549520493e-03 + 0 -1 685 1.6582473181188107e-03 - -1.1547925323247910e-01 4.7692731022834778e-01 + -1.4192129671573639e-01 4.6970281004905701e-01 <_> - 0 -1 395 -3.0073656234890223e-03 + 0 -1 741 8.5381623357534409e-03 - 3.6661648750305176e-01 -1.3400055468082428e-01 + -1.4064009487628937e-01 4.3454051017761230e-01 <_> - 0 -1 185 2.0850619673728943e-01 + 0 -1 711 -5.8347072452306747e-02 - -1.7360156774520874e-01 2.8776788711547852e-01 + 4.8053690791130066e-01 -1.1435888707637787e-01 <_> - 0 -1 263 -3.3409267663955688e-02 + 0 -1 200 7.5503322295844555e-04 - 4.2965263128280640e-01 -1.1280254274606705e-01 + -1.6613751649856567e-01 3.5059270262718201e-01 <_> - 0 -1 444 8.2403160631656647e-03 + 0 -1 463 -1.6263198340311646e-03 - -1.3494767248630524e-01 3.0936670303344727e-01 + 3.3983412384986877e-01 -1.2952369451522827e-01 <_> - 0 -1 201 -5.4142652079463005e-03 + 0 -1 982 -4.9476943910121918e-02 - -5.0563532114028931e-01 6.3294559717178345e-02 + 5.1085108518600464e-01 -7.6757252216339111e-02 <_> - 0 -1 691 -1.3661640696227551e-02 + 0 -1 148 1.5736839268356562e-03 - 2.6760646700859070e-01 -1.3282431662082672e-01 + -9.8503805696964264e-02 4.2097148299217224e-01 <_> - 0 -1 5 -6.6441677510738373e-02 + 0 -1 970 2.8940830379724503e-03 - 4.2027309536933899e-01 -9.1117665171623230e-02 + 8.0476768314838409e-02 -5.9272909164428711e-01 <_> - 0 -1 363 -3.6823814734816551e-03 + 0 -1 470 -8.5198890883475542e-04 - -6.0496860742568970e-01 6.3766337931156158e-02 + 2.7713751792907715e-01 -1.2991340458393097e-01 <_> - 0 -1 363 3.5007880069315434e-03 + 0 -1 513 -3.2718123402446508e-03 - 5.9523750096559525e-02 -5.4523044824600220e-01 + 3.1215441226959229e-01 -1.2980756163597107e-01 <_> - 0 -1 223 1.5307647408917546e-03 + 0 -1 244 6.0219354927539825e-03 - -1.1713726073503494e-01 3.1415259838104248e-01 + 7.2135269641876221e-02 -5.9813290834426880e-01 <_> - 0 -1 769 -1.7609039321541786e-02 + 0 -1 81 2.3065296933054924e-02 - 3.9622062444686890e-01 -8.1705585122108459e-02 + 7.1330830454826355e-02 -5.3722465038299561e-01 <_> - 0 -1 878 2.3612366989254951e-02 + 0 -1 187 2.7176631192560308e-05 - -1.1964736133813858e-01 2.8404179215431213e-01 + -2.6853099465370178e-01 1.4315985143184662e-01 <_> - 0 -1 9 -1.2014270760118961e-02 + 0 -1 401 5.4575498215854168e-03 - 2.7746838331222534e-01 -1.1446747928857803e-01 + 5.5034745484590530e-02 -5.7176333665847778e-01 <_> - 0 -1 450 -4.6456828713417053e-03 + 0 -1 391 2.5911496777553111e-05 - -5.3870040178298950e-01 5.2098110318183899e-02 + -2.3133303225040436e-01 1.4060766994953156e-01 <_> - 0 -1 447 5.3105363622307777e-03 + 0 -1 12 2.1752633154392242e-02 - -1.0284136235713959e-01 3.0061340332031250e-01 + 5.9929180890321732e-02 -5.0224888324737549e-01 <_> - 0 -1 463 -3.2729478552937508e-03 + 0 -1 860 3.5099866800010204e-03 - 1.9203263521194458e-01 -1.6125205159187317e-01 + 4.7387380152940750e-02 -5.8126205205917358e-01 <_> - 0 -1 329 9.8467990756034851e-03 + 0 -1 755 8.6558861657977104e-03 - 4.8938397318124771e-02 -5.1129150390625000e-01 + -1.3651072978973389e-01 2.2407715022563934e-01 <_> - 0 -1 270 3.2083394471555948e-03 + 0 -1 990 3.0432851053774357e-03 - -8.5019417107105255e-02 3.4343490004539490e-01 + 5.7905938476324081e-02 -5.5585581064224243e-01 <_> - 0 -1 228 5.5270073935389519e-03 + 0 -1 240 3.4083288628607988e-03 - 6.3495978713035583e-02 -4.8666983842849731e-01 + 4.6358574181795120e-02 -5.6204903125762939e-01 <_> - 0 -1 866 -2.3475135676562786e-03 + 0 -1 241 -4.1327420622110367e-03 - 2.5843459367752075e-01 -1.1678623408079147e-01 + -4.3748503923416138e-01 6.6312022507190704e-02 <_> - 0 -1 689 -1.5939555596560240e-03 + 0 -1 887 5.4382300004363060e-04 - -3.2783389091491699e-01 8.0364800989627838e-02 + -1.2188895046710968e-01 2.6694831252098083e-01 <_> - 0 -1 422 -4.1191074997186661e-03 + 0 -1 886 2.0359107293188572e-03 - -5.5736887454986572e-01 4.6545837074518204e-02 + -6.9375663995742798e-02 4.1734528541564941e-01 <_> - 0 -1 834 1.7747837118804455e-03 + 0 -1 894 5.6087510893121362e-04 - -7.7934704720973969e-02 3.3011713624000549e-01 + -1.2235503643751144e-01 2.9018589854240417e-01 <_> - 0 -1 789 -1.6894178697839379e-03 + 0 -1 957 5.4084453731775284e-03 - 2.2780518233776093e-01 -1.1316975951194763e-01 + 5.1494579762220383e-02 -6.3784217834472656e-01 <_> - 0 -1 625 -2.0341284107416868e-03 + 0 -1 99 1.9748538732528687e-02 - -3.8829386234283447e-01 6.9249257445335388e-02 + -7.0414997637271881e-02 4.8995351791381836e-01 <_> - 0 -1 655 -3.4458152949810028e-03 + 0 -1 147 -2.0231239497661591e-02 - -4.0543556213378906e-01 5.8193698525428772e-02 + -5.9452813863754272e-01 5.5317912250757217e-02 <_> - 0 -1 813 -9.3588102608919144e-03 + 0 -1 763 -8.5184378549456596e-03 - 3.1281456351280212e-01 -7.8269012272357941e-02 + -4.9081006646156311e-01 5.1023125648498535e-02 <_> - 0 -1 322 -4.9023423343896866e-03 + 0 -1 952 6.4936149865388870e-03 - -4.0507251024246216e-01 6.6911309957504272e-02 + -8.6577519774436951e-02 3.6036944389343262e-01 <_> - 0 -1 68 -4.8415181040763855e-01 + 0 -1 30 -4.0995404124259949e-02 - 6.5363335609436035e-01 -4.0620740503072739e-02 + 4.0132537484169006e-01 -7.1912504732608795e-02 <_> - 0 -1 18 2.6781920343637466e-02 + 0 -1 501 3.1340471468865871e-03 - -1.0990447551012039e-01 2.1767459809780121e-01 + -1.2547470629215240e-01 2.2158138453960419e-01 <_> - 0 -1 800 -9.4280913472175598e-03 + 0 -1 184 -1.9882351160049438e-02 - -7.4746483564376831e-01 2.9869174584746361e-02 + -7.1213179826736450e-01 4.2412471026182175e-02 <_> - 0 -1 492 -7.7869845554232597e-03 + 0 -1 559 2.0461969077587128e-02 - 3.0222293734550476e-01 -8.3480700850486755e-02 + -1.0324169695377350e-01 2.9102885723114014e-01 <_> - 0 -1 426 3.5958206281065941e-03 + 0 -1 686 -1.2761610560119152e-03 - -8.2547821104526520e-02 2.9035624861717224e-01 + 2.3810100555419922e-01 -1.1509060114622116e-01 <_> - 0 -1 487 5.8124819770455360e-03 + 0 -1 549 -3.3783772960305214e-03 - -9.7843483090400696e-02 2.6563084125518799e-01 + -5.6838840246200562e-01 5.6331343948841095e-02 <_> - 0 -1 66 -6.3764736987650394e-03 + 0 -1 302 5.0912564620375633e-03 - -4.6169018745422363e-01 5.5747114121913910e-02 + 4.7987211495637894e-02 -4.7997272014617920e-01 <_> - 0 -1 186 -7.2099521756172180e-02 + 0 -1 508 -4.1752815246582031e-02 - -7.3345041275024414e-01 2.8517069295048714e-02 + -5.9290748834609985e-01 4.2219188064336777e-02 <_> - 0 -1 120 -8.2340046763420105e-02 + 0 -1 263 -1.3672109693288803e-02 - -6.5312498807907104e-01 2.9036073014140129e-02 + 2.7416154742240906e-01 -9.8633147776126862e-02 <_> - 0 -1 927 -1.5001616440713406e-02 + 0 -1 329 4.5463615097105503e-03 - -6.3826096057891846e-01 3.2474573701620102e-02 + -9.5323033630847931e-02 3.3586710691452026e-01 <_> - 0 -1 288 1.1907238513231277e-03 + 0 -1 472 -1.1957241222262383e-02 - -7.9208493232727051e-02 2.9137271642684937e-01 + 1.6140049695968628e-01 -1.6837921738624573e-01 <_> - 0 -1 594 3.1184246763586998e-03 + 0 -1 95 -2.4866103194653988e-03 - 4.7656070441007614e-02 -4.7487255930900574e-01 + -3.8348227739334106e-01 6.6880211234092712e-02 <_> - 0 -1 603 8.2192681729793549e-03 + 0 -1 130 3.3222150523215532e-03 - 2.6732290163636208e-02 -7.3682332038879395e-01 + 4.9669362604618073e-02 -5.2419567108154297e-01 <_> - 0 -1 264 7.1536734700202942e-02 + 0 -1 767 1.2700627557933331e-03 - -6.6174156963825226e-02 3.4596624970436096e-01 + -1.0981336981058121e-01 2.4314954876899719e-01 <_> - 0 -1 707 -1.3247081078588963e-02 + 0 -1 643 -4.0526064112782478e-03 - 2.2122915089130402e-01 -1.1525890231132507e-01 + -5.4617625474929810e-01 4.6236973255872726e-02 <_> - 0 -1 88 6.4605651423335075e-03 + 0 -1 889 -1.7611857037991285e-03 - 5.1374625414609909e-02 -4.2834889888763428e-01 + 2.0527404546737671e-01 -1.1924317479133606e-01 <_> - 0 -1 714 -1.9957395270466805e-03 + 0 -1 832 -2.8845192864537239e-03 - 2.8387853503227234e-01 -8.6039707064628601e-02 + 2.0061042904853821e-01 -1.4499643445014954e-01 <_> - 0 -1 939 2.5912611745297909e-03 + 0 -1 969 -9.4242449849843979e-03 - 6.0468357056379318e-02 -3.9721179008483887e-01 + -7.2513866424560547e-01 3.4894362092018127e-02 <_> - 0 -1 716 1.9276916980743408e-02 + 0 -1 972 3.7029895465821028e-03 - -8.2993559539318085e-02 3.0764940381050110e-01 + 5.5003125220537186e-02 -4.1173446178436279e-01 <_> - 0 -1 887 -4.9096969887614250e-03 + 0 -1 785 -8.4825151134282351e-04 - 2.7268949151039124e-01 -8.6130671203136444e-02 + 2.6719486713409424e-01 -9.9083028733730316e-02 <_> - 0 -1 950 3.6836266517639160e-03 + 0 -1 54 1.5727356076240540e-02 - 5.9468954801559448e-02 -3.9446946978569031e-01 + -1.2551975250244141e-01 2.0588764548301697e-01 <_> - 0 -1 520 3.0758073553442955e-03 + 0 -1 106 5.9068910777568817e-03 - -9.7390249371528625e-02 2.4346484243869781e-01 + 6.0179408639669418e-02 -4.1827461123466492e-01 <_> - 0 -1 522 -4.2319851927459240e-03 + 0 -1 27 -3.9538964629173279e-02 - 3.0930569767951965e-01 -7.9394333064556122e-02 + 3.4726879000663757e-01 -7.4968926608562469e-02 <_> - 0 -1 405 7.2837145999073982e-03 + 0 -1 10 4.7501657158136368e-02 - 4.7933470457792282e-02 -4.8675662279129028e-01 + -7.6978117227554321e-02 3.5068345069885254e-01 <_> - 0 -1 467 -6.2543689273297787e-03 + 0 -1 259 -5.9454172151163220e-04 - -4.8621338605880737e-01 4.2082890868186951e-02 - <_> - - 0 -1 872 -1.1530111078172922e-03 - - 2.6954403519630432e-01 -8.6280718445777893e-02 - <_> - - 0 -1 560 4.0323145687580109e-02 - - -9.4530344009399414e-02 2.3481069505214691e-01 - <_> - - 0 -1 15 -1.2282184325158596e-02 - - -7.2538161277770996e-01 3.0701907351613045e-02 - <_> - - 0 -1 678 3.7427488714456558e-02 - - 2.9119925573468208e-02 -6.4663606882095337e-01 - <_> - - 0 -1 568 2.5721127167344093e-03 - - 4.9338530749082565e-02 -4.0851938724517822e-01 - <_> - - 0 -1 925 -2.0106829702854156e-02 - - -6.2753307819366455e-01 3.1198438256978989e-02 - <_> - - 0 -1 936 2.5536534376442432e-03 - - 2.3092683404684067e-02 -7.4033683538436890e-01 - <_> - - 0 -1 876 -1.3628168962895870e-03 - - 3.4928113222122192e-01 -6.5548241138458252e-02 - <_> - - 0 -1 875 -9.9153746850788593e-04 - - 2.2522389888763428e-01 -9.1688700020313263e-02 - <_> - - 0 -1 965 5.0148647278547287e-03 - - 3.9175543934106827e-02 -5.5856782197952271e-01 - <_> - - 0 -1 853 9.1358053032308817e-04 - - -1.2273798882961273e-01 1.8954706192016602e-01 - <_> - - 0 -1 762 1.6373313963413239e-02 - - 3.9829690009355545e-02 -5.7986593246459961e-01 - <_> - - 0 -1 544 1.4575564302504063e-02 - - -8.6225226521492004e-02 2.4198558926582336e-01 - <_> - - 0 -1 967 5.1754433661699295e-04 - - 8.9498788118362427e-02 -2.1777628362178802e-01 - <_> - - 0 -1 79 -1.1098009534180164e-02 - - 2.2925806045532227e-01 -8.3799630403518677e-02 - <_> - - 0 -1 308 2.4133864790201187e-02 - - -1.0102383792400360e-01 2.0877565443515778e-01 - <_> - - 0 -1 152 -3.7758771330118179e-02 - - 4.3367731571197510e-01 -5.1683723926544189e-02 - <_> - - 0 -1 218 9.0820249170064926e-03 - - 4.0468864142894745e-02 -5.4790335893630981e-01 - <_> - - 0 -1 385 -3.8959060329943895e-03 - - -3.4300115704536438e-01 5.6340463459491730e-02 - <_> - - 0 -1 815 -1.0297749191522598e-02 - - 2.9084947705268860e-01 -8.1125274300575256e-02 - <_> - - 0 -1 815 8.3358399569988251e-03 - - -6.9515161216259003e-02 3.0880457162857056e-01 - <_> - - 0 -1 805 4.1338298469781876e-02 - - 3.2240319997072220e-02 -6.5160977840423584e-01 - <_> - - 0 -1 345 2.6844158768653870e-02 - - -6.5987348556518555e-02 3.1071534752845764e-01 - <_> - - 0 -1 93 -4.4573536142706871e-03 - - -3.4222671389579773e-01 6.0962244868278503e-02 - <_> - - 0 -1 217 -5.6259175762534142e-03 - - 1.9679838418960571e-01 -9.9301390349864960e-02 - <_> - - 0 -1 130 -3.4068014472723007e-02 - - -5.7343089580535889e-01 3.5370521247386932e-02 - <_> - - 0 -1 415 -4.1321285068988800e-02 - - -5.4799556732177734e-01 3.2511439174413681e-02 - <_> - - 0 -1 702 -4.5842211693525314e-03 - - 2.0696444809436798e-01 -9.3100592494010925e-02 - <_> - - 0 -1 705 -8.6525538936257362e-03 - - -5.2304923534393311e-01 4.0334302932024002e-02 - <_> - - 0 -1 656 -8.1807989627122879e-03 - - 3.0393254756927490e-01 -6.9615311920642853e-02 - <_> - - 0 -1 867 -6.2429648824036121e-03 - - -5.0806474685668945e-01 4.2720243334770203e-02 - <_> - - 0 -1 660 -4.3397732079029083e-03 - - -4.7173827886581421e-01 3.7593103945255280e-02 - <_> - - 0 -1 392 -2.4694669991731644e-03 - - 3.4972354769706726e-01 -6.2289424240589142e-02 - <_> - - 0 -1 496 4.6105296351015568e-03 - - 4.8353113234043121e-02 -3.9337757229804993e-01 - <_> - - 0 -1 368 1.5546558424830437e-03 - - -8.5152842104434967e-02 2.4539804458618164e-01 + 1.6073931753635406e-01 -1.5279982984066010e-01 <_> - 100 - -1.6321692466735840e+00 + 58 + -1.2862224578857422e+00 <_> - 0 -1 443 -9.9800406023859978e-03 + 0 -1 882 -1.3625519350171089e-02 - 6.5110075473785400e-01 7.0068746805191040e-02 + 5.0128185749053955e-01 -1.1663150042295456e-01 <_> - 0 -1 656 1.2785504572093487e-02 + 0 -1 375 -2.2920668125152588e-03 - -1.5662825107574463e-01 4.5551964640617371e-01 + 3.9538189768791199e-01 -1.3872602581977844e-01 <_> - 0 -1 197 4.0613190503790975e-04 + 0 -1 792 1.0770710650831461e-03 - -2.3326659202575684e-01 2.4264821410179138e-01 + -1.7133137583732605e-01 3.1510788202285767e-01 <_> - 0 -1 0 -4.4671623036265373e-03 + 0 -1 452 -1.2591466307640076e-02 - 3.0027064681053162e-01 -1.7738959193229675e-01 + 3.9579889178276062e-01 -1.4279782772064209e-01 <_> - 0 -1 733 7.1196053177118301e-03 + 0 -1 460 -4.7927081584930420e-02 - -1.3141728937625885e-01 4.3263924121856689e-01 + -4.9305588006973267e-01 5.6685980409383774e-02 <_> - 0 -1 855 7.1185962297022343e-03 + 0 -1 474 -2.5895023718476295e-03 - -1.5669579803943634e-01 3.3418005704879761e-01 + 1.6586430370807648e-01 -2.2577352821826935e-01 <_> - 0 -1 725 4.5672003179788589e-03 + 0 -1 112 9.8585948348045349e-02 - -1.2860487401485443e-01 3.1136614084243774e-01 + -7.2541341185569763e-02 5.3971153497695923e-01 <_> - 0 -1 859 -1.0435921140015125e-03 + 0 -1 521 7.2299325838685036e-03 - 1.9418887794017792e-01 -1.7872068285942078e-01 + 7.2869211435317993e-02 -6.0541796684265137e-01 <_> - 0 -1 111 -8.6360834538936615e-03 + 0 -1 202 -6.0262705665081739e-04 - -6.0729598999023438e-01 3.6422688513994217e-02 + 2.7961328625679016e-01 -1.3374039530754089e-01 <_> - 0 -1 685 6.4469715580344200e-03 + 0 -1 253 5.3171166218817234e-03 - -1.7270094156265259e-01 1.8412014842033386e-01 + 6.1562143266201019e-02 -5.3435516357421875e-01 <_> - 0 -1 920 -3.2128435559570789e-03 + 0 -1 109 -7.3790093883872032e-03 - -5.6947451829910278e-01 5.5858459323644638e-02 + -5.8770626783370972e-01 5.2599798887968063e-02 <_> - 0 -1 202 2.9547505080699921e-02 + 0 -1 179 2.2994203027337790e-04 - 5.4511282593011856e-02 -4.9024525284767151e-01 + -2.2165967524051666e-01 1.6663813591003418e-01 <_> - 0 -1 161 -5.3524523973464966e-03 + 0 -1 366 -2.7968082576990128e-03 - -4.3886002898216248e-01 5.9159737080335617e-02 + -4.5023602247238159e-01 6.7983791232109070e-02 <_> - 0 -1 159 2.2656358778476715e-03 + 0 -1 949 -4.4262632727622986e-03 - -1.4958912134170532e-01 1.9237321615219116e-01 + -5.4457426071166992e-01 5.3928002715110779e-02 <_> - 0 -1 272 -1.7663020640611649e-02 + 0 -1 431 -6.1236601322889328e-03 - 3.4963962435722351e-01 -9.8792962729930878e-02 + 2.9386061429977417e-01 -1.0868654400110245e-01 <_> - 0 -1 135 -1.4769199490547180e-01 + 0 -1 364 6.1672870069742203e-03 - 3.8789209723472595e-01 -7.4754111468791962e-02 + 6.7409984767436981e-02 -4.2896196246147156e-01 <_> - 0 -1 961 -1.2649353593587875e-02 + 0 -1 335 1.5454929322004318e-02 - 3.6447465419769287e-01 -7.8627258539199829e-02 + -9.3371987342834473e-02 3.2237896323204041e-01 <_> - 0 -1 203 -1.6667589545249939e-01 + 0 -1 285 -5.5358107201755047e-03 - 3.1024694442749023e-01 -9.8567992448806763e-02 + -6.3797932863235474e-01 4.7232467681169510e-02 <_> - 0 -1 823 1.5327525325119495e-03 + 0 -1 210 -5.8793288189917803e-04 - -8.7889634072780609e-02 3.3739477396011353e-01 + 2.6480975747108459e-01 -1.1852940917015076e-01 <_> - 0 -1 37 -4.9399482086300850e-03 + 0 -1 203 1.2575921136885881e-03 - -6.0582613945007324e-01 4.7072298824787140e-02 + -1.2490244954824448e-01 2.8103300929069519e-01 <_> - 0 -1 663 1.6168793663382530e-03 + 0 -1 41 3.3034523949027061e-03 - -1.1102212965488434e-01 2.4625547230243683e-01 + 6.2105692923069000e-02 -4.5968556404113770e-01 <_> - 0 -1 38 -7.9764677211642265e-03 + 0 -1 45 -2.6582641527056694e-02 - -4.5467814803123474e-01 5.6168641895055771e-02 + -5.0849837064743042e-01 5.3966015577316284e-02 <_> - 0 -1 803 2.1164701320230961e-03 + 0 -1 49 2.7427850291132927e-02 - 3.9522409439086914e-02 -5.8244407176971436e-01 + 5.2529457956552505e-02 -5.3614085912704468e-01 <_> - 0 -1 423 1.2181616621091962e-03 + 0 -1 39 -2.1938718855381012e-03 - -1.1960548907518387e-01 1.8955740332603455e-01 + -5.6713318824768066e-01 4.6497207134962082e-02 <_> - 0 -1 414 6.2020774930715561e-02 + 0 -1 926 8.5861550178378820e-04 - -9.2262148857116699e-02 2.4536235630512238e-01 + -1.1162154376506805e-01 2.8105884790420532e-01 <_> - 0 -1 98 1.5368127264082432e-02 + 0 -1 886 -8.4925384726375341e-04 - -7.4950158596038818e-02 3.8813439011573792e-01 + 3.1280112266540527e-01 -1.2138028442859650e-01 <_> - 0 -1 631 -3.6116694100201130e-03 + 0 -1 956 2.9905270785093307e-03 - -5.8402395248413086e-01 4.3880671262741089e-02 + 6.1607286334037781e-02 -5.1581907272338867e-01 <_> - 0 -1 669 -5.4048337042331696e-03 + 0 -1 968 5.8231391012668610e-03 - 2.7466323971748352e-01 -8.3315111696720123e-02 + 4.7376025468111038e-02 -5.1492005586624146e-01 <_> - 0 -1 190 -5.7541755959391594e-03 + 0 -1 480 4.2811138555407524e-03 - -4.8696601390838623e-01 5.0719954073429108e-02 + 3.2761037349700928e-02 -6.7820072174072266e-01 <_> - 0 -1 868 -8.8466441957280040e-04 + 0 -1 915 9.5272483304142952e-04 - 1.4997816085815430e-01 -1.4873522520065308e-01 + -1.5452747046947479e-01 1.7837351560592651e-01 <_> - 0 -1 419 -1.3690529391169548e-02 + 0 -1 270 -2.7698231860995293e-04 - -4.2396122217178345e-01 5.1716264337301254e-02 + 1.8924367427825928e-01 -1.3868112862110138e-01 <_> - 0 -1 231 -9.2098396271467209e-03 + 0 -1 370 3.0586202628910542e-03 - -6.8742758035659790e-01 2.8357446193695068e-02 + 5.3298473358154297e-02 -4.7908756136894226e-01 <_> - 0 -1 433 -1.0102453641593456e-02 + 0 -1 639 2.0293965935707092e-03 - 3.0423650145530701e-01 -7.5886160135269165e-02 + 3.1667634844779968e-02 -6.7199909687042236e-01 <_> - 0 -1 789 -2.1283417008817196e-03 + 0 -1 639 -1.8073513638228178e-03 - 2.2551217675209045e-01 -9.5488928258419037e-02 + -6.4894622564315796e-01 3.3469315618276596e-02 <_> - 0 -1 675 2.2938135080039501e-03 + 0 -1 320 -1.1197938583791256e-03 - 3.2833088189363480e-02 -6.4737302064895630e-01 + 2.2734998166561127e-01 -1.1382233351469040e-01 <_> - 0 -1 795 -2.0679826848208904e-03 + 0 -1 828 1.2703117681667209e-03 - 2.9072764515876770e-01 -8.1707596778869629e-02 + -9.7680233418941498e-02 2.9997348785400391e-01 <_> - 0 -1 495 1.8802012782543898e-03 + 0 -1 835 -1.8036495894193649e-03 - -1.0236340761184692e-01 2.4278828501701355e-01 + 2.3566392064094543e-01 -1.1566326767206192e-01 <_> - 0 -1 566 -1.5465463511645794e-03 + 0 -1 222 2.3318463936448097e-03 - -3.8903787732124329e-01 5.6320030242204666e-02 + 5.5787801742553711e-02 -4.4648987054824829e-01 <_> - 0 -1 630 6.3281953334808350e-03 + 0 -1 111 1.8485619220882654e-03 - -9.9905796349048615e-02 2.2087195515632629e-01 + -1.0420991480350494e-01 2.4521166086196899e-01 <_> - 0 -1 704 3.3235952258110046e-02 + 0 -1 101 8.2633290439844131e-03 - 5.0302099436521530e-02 -4.9443060159683228e-01 + 5.3129263222217560e-02 -4.8460647463798523e-01 <_> - 0 -1 894 -1.9428483210504055e-03 + 0 -1 760 2.7392050469643436e-05 - -6.7564088106155396e-01 2.7948424220085144e-02 + -1.7487643659114838e-01 1.3620604574680328e-01 <_> - 0 -1 849 1.1729343095794320e-03 + 0 -1 352 2.6163433212786913e-03 - -1.1950153112411499e-01 1.8506029248237610e-01 + -9.9586494266986847e-02 2.4075058102607727e-01 <_> - 0 -1 941 5.4220901802182198e-03 + 0 -1 94 3.6149267107248306e-03 - 5.0924405455589294e-02 -4.3448522686958313e-01 + 4.2312353849411011e-02 -5.5195075273513794e-01 <_> - 0 -1 768 3.0700212810188532e-03 + 0 -1 403 1.4812931418418884e-02 - -7.6845921576023102e-02 2.6929470896720886e-01 + -6.7619144916534424e-02 3.7573158740997314e-01 <_> - 0 -1 914 2.6065693236887455e-03 + 0 -1 814 -2.8877586591988802e-03 - 5.5169116705656052e-02 -3.9985677599906921e-01 + -5.3493702411651611e-01 5.1065266132354736e-02 <_> - 0 -1 884 2.6848190464079380e-03 + 0 -1 930 3.5591312916949391e-04 - 2.7681041508913040e-02 -6.6643798351287842e-01 + -1.2231220304965973e-01 1.9974029064178467e-01 <_> - 0 -1 471 4.9525322392582893e-03 + 0 -1 36 -1.0347569361329079e-02 - -7.8715771436691284e-02 2.6918828487396240e-01 + -6.3408315181732178e-01 4.0167611092329025e-02 <_> - 0 -1 466 -1.2217788025736809e-02 + 0 -1 34 -4.4028884731233120e-03 - 2.5042393803596497e-01 -9.2959709465503693e-02 + -5.1359844207763672e-01 4.3052427470684052e-02 <_> - 0 -1 51 -9.7617935389280319e-03 + 0 -1 856 -1.6173283802345395e-03 - -5.8083361387252808e-01 4.1861489415168762e-02 + 1.4859439432621002e-01 -1.4985026419162750e-01 <_> - 0 -1 528 -3.0802208930253983e-03 + 0 -1 996 -3.1839800067245960e-03 - -5.4920911788940430e-01 3.1410869210958481e-02 + -4.1493499279022217e-01 6.0393124818801880e-02 <_> - 0 -1 499 8.8869817554950714e-03 + 0 -1 960 -7.9784039407968521e-03 - -5.7799737900495529e-02 3.5997068881988525e-01 + 2.8296649456024170e-01 -8.6312569677829742e-02 <_> - 0 -1 383 -1.6894126310944557e-03 + 0 -1 797 2.8750954661518335e-03 - 1.5611077845096588e-01 -1.3526220619678497e-01 + -6.7822508513927460e-02 3.2967612147331238e-01 <_> - 0 -1 80 1.1576576158404350e-02 + 0 -1 992 -1.1433581821620464e-03 - 2.6843478903174400e-02 -7.7421426773071289e-01 + -3.4375748038291931e-01 6.8774074316024780e-02 <_> - 0 -1 283 -1.0315187275409698e-02 + 0 -1 668 1.7783213406801224e-03 - -3.7911209464073181e-01 4.7785960137844086e-02 + -8.8273152709007263e-02 2.6904863119125366e-01 <_> - 0 -1 216 9.3458819901570678e-04 + 0 -1 670 -6.3564153388142586e-03 - -1.0482961684465408e-01 1.9531208276748657e-01 + 3.4165042638778687e-01 -7.6342806220054626e-02 <_> - 0 -1 225 -2.1154026035219431e-03 + 0 -1 712 5.8753319084644318e-02 - 3.2437980175018311e-01 -7.0380724966526031e-02 + 3.6884155124425888e-02 -7.0002478361129761e-01 <_> - 0 -1 328 7.0915305987000465e-03 + 0 -1 345 -1.2118986342102289e-03 - 3.1504381448030472e-02 -7.1498668193817139e-01 + 1.8067996203899384e-01 -1.2888990342617035e-01 <_> - 0 -1 968 1.5262098750099540e-03 + 0 -1 268 -3.4786794334650040e-02 - 4.3178513646125793e-02 -4.1175857186317444e-01 - <_> - - 0 -1 194 -2.6456830091774464e-03 - - -6.6830241680145264e-01 2.7078842744231224e-02 - <_> - - 0 -1 722 1.3623384293168783e-03 - - -9.6260324120521545e-02 1.9846718013286591e-01 - <_> - - 0 -1 672 -3.4019351005554199e-03 - - 1.3638894259929657e-01 -1.4331445097923279e-01 - <_> - - 0 -1 667 -4.2538799345493317e-02 - - -6.8543094396591187e-01 2.7219040319323540e-02 - <_> - - 0 -1 572 5.1494771614670753e-03 - - -8.3506844937801361e-02 2.4553795158863068e-01 - <_> - - 0 -1 509 -1.3525998219847679e-03 - - 2.0083853602409363e-01 -1.1441762000322342e-01 - <_> - - 0 -1 889 -4.7460300847887993e-03 - - -5.8234161138534546e-01 3.3193428069353104e-02 - <_> - - 0 -1 559 -1.8419034779071808e-02 - - 2.5098413228988647e-01 -7.8263558447360992e-02 - <_> - - 0 -1 837 -3.6029946058988571e-03 - - 2.5004243850708008e-01 -7.8106440603733063e-02 - <_> - - 0 -1 12 1.0855928063392639e-02 - - 3.8721837103366852e-02 -5.0439488887786865e-01 - <_> - - 0 -1 6 3.1823229044675827e-02 - - 2.8006808832287788e-02 -6.5438795089721680e-01 - <_> - - 0 -1 35 9.0156495571136475e-02 - - 3.6854032427072525e-02 -4.6750095486640930e-01 - <_> - - 0 -1 876 8.1275019329041243e-04 - - -8.1435337662696838e-02 2.3081797361373901e-01 - <_> - - 0 -1 843 -2.2238264791667461e-03 - - -4.6506562829017639e-01 4.2775552719831467e-02 - <_> - - 0 -1 21 8.5265887901186943e-03 - - -9.9068634212017059e-02 1.8661868572235107e-01 - <_> - - 0 -1 601 5.0247795879840851e-03 - - 3.5677276551723480e-02 -5.6390231847763062e-01 - <_> - - 0 -1 353 1.2137264013290405e-02 - - 2.3600205779075623e-02 -6.9947057962417603e-01 - <_> - - 0 -1 687 5.8652815641835332e-04 - - -1.0546504706144333e-01 1.8301849067211151e-01 - <_> - - 0 -1 783 -1.2803040444850922e-02 - - 2.4169570207595825e-01 -9.3701913952827454e-02 - <_> - - 0 -1 362 1.9234570208936930e-03 - - 4.1152808815240860e-02 -5.3527724742889404e-01 - <_> - - 0 -1 413 -5.1119372248649597e-02 - - 2.0418803393840790e-01 -1.0016205906867981e-01 - <_> - - 0 -1 643 2.0427668467164040e-02 - - 3.8303721696138382e-02 -5.6752574443817139e-01 - <_> - - 0 -1 916 1.0702429572120309e-03 - - -1.1941519379615784e-01 1.5449772775173187e-01 - <_> - - 0 -1 45 6.3908234238624573e-02 - - -8.0574154853820801e-02 2.4723786115646362e-01 - <_> - - 0 -1 239 -8.9891534298658371e-03 - - 2.7232396602630615e-01 -7.9600028693675995e-02 - <_> - - 0 -1 181 -7.4440538883209229e-03 - - 1.7151834070682526e-01 -1.1733634769916534e-01 - <_> - - 0 -1 298 9.3747628852725029e-03 - - -5.8857422322034836e-02 3.3993646502494812e-01 - <_> - - 0 -1 890 3.9659179747104645e-03 - - 3.7981141358613968e-02 -5.3772449493408203e-01 - <_> - - 0 -1 698 -2.7701430954039097e-03 - - 2.1686923503875732e-01 -9.1246932744979858e-02 - <_> - - 0 -1 592 -3.0083605088293552e-03 - - -5.1033967733383179e-01 3.8351774215698242e-02 - <_> - - 0 -1 40 5.2285091951489449e-03 - - 6.6746503114700317e-02 -2.5510028004646301e-01 - <_> - - 0 -1 542 2.6635453104972839e-03 - - -8.8651068508625031e-02 2.1260604262351990e-01 - <_> - - 0 -1 545 -3.4417591989040375e-02 - - -6.6850775480270386e-01 3.1463332474231720e-02 - <_> - - 0 -1 550 -9.7544072195887566e-04 - - 2.0566202700138092e-01 -1.0702812671661377e-01 - <_> - - 0 -1 361 1.6097709536552429e-01 - - -4.7826759517192841e-02 3.8993999361991882e-01 - <_> - - 0 -1 489 1.0004348587244749e-03 - - -1.0796900838613510e-01 2.1362201869487762e-01 - <_> - - 0 -1 420 4.0136128664016724e-03 - - -8.1376187503337860e-02 2.2793699800968170e-01 - <_> - - 0 -1 562 3.2076346687972546e-03 - - -1.0031759738922119e-01 2.2700363397598267e-01 - <_> - - 0 -1 53 -4.1395910084247589e-03 - - -4.5727050304412842e-01 4.4953804463148117e-02 - <_> - - 0 -1 595 4.9559203907847404e-03 - - 3.0349666252732277e-02 -5.6468343734741211e-01 - <_> - - 0 -1 835 1.9516122993081808e-03 - - -8.4078930318355560e-02 2.1666139364242554e-01 - <_> - - 0 -1 200 2.8487551957368851e-02 - - -5.8517321944236755e-02 3.7208831310272217e-01 + 2.8380703926086426e-01 -1.0494612902402878e-01 <_> - 100 - -1.5313543081283569e+00 + 61 + -1.3526766300201416e+00 <_> - 0 -1 865 -1.1964191682636738e-02 + 0 -1 875 9.3241240829229355e-03 - 6.5611332654953003e-01 8.7084025144577026e-02 + -1.1945860832929611e-01 4.8265087604522705e-01 <_> - 0 -1 570 -3.6326241679489613e-03 + 0 -1 573 -4.0869116783142090e-03 - 3.0753159523010254e-01 -2.0207116007804871e-01 + 2.7903670072555542e-01 -2.3448269069194794e-01 <_> - 0 -1 739 1.6091932775452733e-03 + 0 -1 676 8.3140000700950623e-02 - -2.1601480245590210e-01 2.4574394524097443e-01 + -8.5437655448913574e-02 5.4905670881271362e-01 <_> - 0 -1 151 -1.0807140171527863e-01 + 0 -1 802 2.6708254590630531e-03 - 5.8551537990570068e-01 -8.0984398722648621e-02 + -1.6097296774387360e-01 3.5868695378303528e-01 <_> - 0 -1 122 6.6386028192937374e-03 + 0 -1 75 2.2817514836788177e-03 - -2.3309321701526642e-01 2.5712442398071289e-01 + -1.6324259340763092e-01 2.3956388235092163e-01 <_> - 0 -1 480 6.6436373163014650e-04 + 0 -1 745 6.7889376077800989e-04 - -1.7002807557582855e-01 2.2093741595745087e-01 + -2.5205141305923462e-01 1.6190616786479950e-01 <_> - 0 -1 109 5.9623841661959887e-04 + 0 -1 811 3.1512721907347441e-03 - -2.1071858704090118e-01 1.5259474515914917e-01 + -1.3325424492359161e-01 2.7017220854759216e-01 <_> - 0 -1 296 -2.1322746761143208e-03 + 0 -1 53 5.7821646332740784e-02 - -3.6114820837974548e-01 7.9649142920970917e-02 + -6.7158013582229614e-02 4.1875806450843811e-01 <_> - 0 -1 102 -6.9360136985778809e-03 + 0 -1 442 2.8442896902561188e-02 - -5.2729552984237671e-01 5.9225857257843018e-02 + 5.5711831897497177e-02 -5.8136337995529175e-01 <_> - 0 -1 1 7.2746481746435165e-03 + 0 -1 644 -1.7370734130963683e-03 - -1.5284915268421173e-01 2.0500071346759796e-01 + -6.7132610082626343e-01 3.2464105635881424e-02 <_> - 0 -1 793 -2.4507325142621994e-03 + 0 -1 324 -1.9680276513099670e-02 - -4.4374018907546997e-01 6.2125567346811295e-02 + 3.9044600725173950e-01 -8.8745564222335815e-02 <_> - 0 -1 677 -1.1941835284233093e-01 + 0 -1 224 1.0001409798860550e-02 - 5.9646230936050415e-01 -5.0393357872962952e-02 + -1.5947268903255463e-01 2.7087828516960144e-01 <_> - 0 -1 830 2.4319710209965706e-03 + 0 -1 644 1.2495646951720119e-03 - -1.4628271758556366e-01 2.2020979225635529e-01 + 8.3702936768531799e-02 -4.6324184536933899e-01 <_> - 0 -1 503 4.0825735777616501e-03 + 0 -1 144 3.0510198324918747e-02 - 4.6519946306943893e-02 -6.0437613725662231e-01 + -1.0709584504365921e-01 3.2648065686225891e-01 <_> - 0 -1 112 3.3597379922866821e-02 + 0 -1 995 -3.7916197907179594e-03 - 5.5770415812730789e-02 -4.4832473993301392e-01 + -6.1073684692382812e-01 4.7788143157958984e-02 <_> - 0 -1 142 -4.1159454733133316e-02 + 0 -1 880 8.5655774455517530e-04 - -4.2802116274833679e-01 5.6050233542919159e-02 + -2.0807541906833649e-01 1.5517778694629669e-01 <_> - 0 -1 357 -3.1343686860054731e-03 + 0 -1 986 -3.2812850549817085e-03 - -4.5189481973648071e-01 4.5713383704423904e-02 + -5.8795136213302612e-01 4.5926980674266815e-02 <_> - 0 -1 449 -3.9362995885312557e-03 + 0 -1 499 3.6125673796050251e-04 - 2.6333171129226685e-01 -8.6672604084014893e-02 + -1.6806155443191528e-01 1.7441834509372711e-01 <_> - 0 -1 274 -3.4228354692459106e-02 + 0 -1 591 -1.2282358948141336e-03 - 2.8555384278297424e-01 -8.0961830914020538e-02 + -4.7641313076019287e-01 5.6790668517351151e-02 <_> - 0 -1 192 2.3194378241896629e-02 + 0 -1 411 9.3263220041990280e-03 - -1.0957508534193039e-01 2.6531192660331726e-01 + -7.4045926332473755e-02 3.7817317247390747e-01 <_> - 0 -1 812 1.1790241114795208e-03 + 0 -1 591 7.4745330493897200e-04 - -1.2578412890434265e-01 2.2350181639194489e-01 + 8.0762349069118500e-02 -3.5692575573921204e-01 <_> - 0 -1 757 2.4525973945856094e-02 + 0 -1 900 7.4315653182566166e-03 - 3.9447281509637833e-02 -6.4369696378707886e-01 + -8.5764542222023010e-02 3.2155406475067139e-01 <_> - 0 -1 234 -5.5821083486080170e-02 + 0 -1 776 2.7057509869337082e-02 - 3.8404938578605652e-01 -6.1516307294368744e-02 + 6.9296583533287048e-02 -4.2836430668830872e-01 <_> - 0 -1 297 8.5053090006113052e-03 + 0 -1 504 3.9283365011215210e-02 - -1.1682828515768051e-01 2.0639540255069733e-01 + -1.0806435346603394e-01 2.9007008671760559e-01 <_> - 0 -1 28 -4.6913616359233856e-02 + 0 -1 23 -3.4139624238014221e-01 - -3.3303919434547424e-01 6.8057745695114136e-02 + 5.0227731466293335e-01 -6.3795588910579681e-02 <_> - 0 -1 531 -6.0622256249189377e-02 + 0 -1 502 -1.8172953277826309e-02 - 3.0634361505508423e-01 -8.0411903560161591e-02 + 2.7207729220390320e-01 -1.0322675853967667e-01 <_> - 0 -1 962 3.3126091584563255e-03 + 0 -1 509 1.5265008434653282e-02 - 6.4039744436740875e-02 -3.6264923214912415e-01 + -1.0788526386022568e-01 2.4405729770660400e-01 <_> - 0 -1 923 -6.2155202031135559e-03 + 0 -1 465 -1.4973650686442852e-03 - 2.6324889063835144e-01 -8.5208639502525330e-02 + 2.8644701838493347e-01 -1.0436929017305374e-01 <_> - 0 -1 840 -3.6174536217004061e-03 + 0 -1 674 2.1207414101809263e-03 - -6.3895624876022339e-01 3.7891831248998642e-02 + 4.5713264495134354e-02 -6.6571021080017090e-01 <_> - 0 -1 321 -3.0694848392158747e-03 + 0 -1 254 1.3393461704254150e-02 - 2.7301403880119324e-01 -8.3168596029281616e-02 + -8.4284797310829163e-02 3.6480179429054260e-01 <_> - 0 -1 106 -1.6663860296830535e-03 + 0 -1 560 9.7873376216739416e-04 - -4.9059715867042542e-01 4.4817935675382614e-02 + -1.2960052490234375e-01 2.2095513343811035e-01 <_> - 0 -1 36 1.6716115176677704e-02 + 0 -1 747 -4.9731796607375145e-03 - 6.0621056705713272e-02 -3.4729966521263123e-01 + 2.7467787265777588e-01 -1.0236363112926483e-01 <_> - 0 -1 401 1.3494723476469517e-02 + 0 -1 294 -7.9883169382810593e-03 - 3.1516350805759430e-02 -6.2451899051666260e-01 + -5.3638678789138794e-01 5.3369920700788498e-02 <_> - 0 -1 321 1.9665439613163471e-03 + 0 -1 413 2.3855306208133698e-03 - -8.6126960813999176e-02 2.5302976369857788e-01 + 5.4967612028121948e-02 -4.2117682099342346e-01 <_> - 0 -1 477 -2.8690965846180916e-02 + 0 -1 899 -3.0849636532366276e-03 - 2.9214075207710266e-01 -6.8187572062015533e-02 + 2.6192533969879150e-01 -9.4207443296909332e-02 <_> - 0 -1 430 5.4161301814019680e-03 + 0 -1 653 4.3416069820523262e-03 - -8.5594080388545990e-02 2.6200750470161438e-01 + -1.5543100237846375e-01 1.6663897037506104e-01 <_> - 0 -1 269 -3.6381594836711884e-02 + 0 -1 451 3.8728015497326851e-03 - -5.9561169147491455e-01 3.6925114691257477e-02 + 4.9280565232038498e-02 -4.9337747693061829e-01 <_> - 0 -1 421 -6.7269792780280113e-03 + 0 -1 563 1.8099667504429817e-03 - -7.9720497131347656e-01 2.4374464526772499e-02 + 4.2697191238403320e-02 -5.2748012542724609e-01 <_> - 0 -1 947 -7.4932668358087540e-03 + 0 -1 157 -3.3727339468896389e-03 - -8.1190264225006104e-01 1.9826157018542290e-02 + 2.0491680502891541e-01 -1.2846539914608002e-01 <_> - 0 -1 165 -5.5202767252922058e-03 + 0 -1 344 3.1393815297633410e-03 - 1.8447315692901611e-01 -1.1608960479497910e-01 + -7.3090612888336182e-02 3.4941059350967407e-01 <_> - 0 -1 869 2.9039490036666393e-03 + 0 -1 851 3.2568261958658695e-03 - 6.3957199454307556e-02 -3.0787152051925659e-01 + 4.5729346573352814e-02 -5.7302659749984741e-01 <_> - 0 -1 41 2.4206712841987610e-01 + 0 -1 853 -2.0513155031949282e-03 - -3.4878797829151154e-02 5.9678316116333008e-01 + -5.4655516147613525e-01 3.8907390087842941e-02 <_> - 0 -1 901 5.8509008958935738e-03 + 0 -1 656 -2.7090720832347870e-03 - -8.4465004503726959e-02 2.3755706846714020e-01 + -5.2781039476394653e-01 3.8093525916337967e-02 <_> - 0 -1 943 1.1404031887650490e-02 + 0 -1 738 -3.6282267421483994e-02 - -6.2884598970413208e-02 3.3538460731506348e-01 + -5.8760797977447510e-01 3.4759882837533951e-02 <_> - 0 -1 946 -6.4798449166119099e-03 + 0 -1 558 3.7925848737359047e-03 - 2.6907229423522949e-01 -8.0378860235214233e-02 + -8.5966393351554871e-02 2.6226586103439331e-01 <_> - 0 -1 175 -1.5257325768470764e-01 + 0 -1 991 -3.7565450184047222e-03 - 3.7274152040481567e-01 -5.3593669086694717e-02 + -5.7828390598297119e-01 3.9440535008907318e-02 <_> - 0 -1 300 -7.8410096466541290e-03 + 0 -1 906 -7.8137982636690140e-03 - 3.5559067130088806e-01 -6.0485389083623886e-02 + 3.5042202472686768e-01 -6.6597603261470795e-02 <_> - 0 -1 895 4.6420615399256349e-04 + 0 -1 904 -3.1100357882678509e-03 - -1.3953977823257446e-01 1.4700867235660553e-01 + 1.8389418721199036e-01 -1.4107073843479156e-01 <_> - 0 -1 365 -2.7928948402404785e-03 + 0 -1 449 9.1797057539224625e-03 - -3.7794330716133118e-01 5.3649291396141052e-02 + -6.2711343169212341e-02 3.4819519519805908e-01 <_> - 0 -1 761 -6.2361196614801884e-03 + 0 -1 255 -2.9698751866817474e-02 - 2.3622865974903107e-01 -8.5419490933418274e-02 + 2.8956320881843567e-01 -8.5679493844509125e-02 <_> - 0 -1 758 -1.0482727549970150e-02 + 0 -1 720 7.9502481967210770e-03 - -4.9808895587921143e-01 4.5149747282266617e-02 + 3.9165180176496506e-02 -6.0753583908081055e-01 <_> - 0 -1 728 5.1559107378125191e-03 + 0 -1 621 2.2064188960939646e-03 - -8.4864191710948944e-02 2.6940858364105225e-01 + 3.5431943833827972e-02 -5.5480444431304932e-01 <_> - 0 -1 854 1.3875829055905342e-02 + 0 -1 175 -3.1044434756040573e-02 - -6.8634092807769775e-02 3.0264788866043091e-01 + -6.2628567218780518e-01 3.1049268320202827e-02 <_> - 0 -1 549 2.0931879989802837e-03 + 0 -1 0 -1.3199620880186558e-03 - -8.1713855266571045e-02 2.2649072110652924e-01 + 1.5564316511154175e-01 -1.3879336416721344e-01 <_> - 0 -1 580 2.2430280223488808e-03 + 0 -1 397 -9.6068280981853604e-04 - 3.2463703304529190e-02 -6.4346092939376831e-01 + 1.9332279264926910e-01 -1.1179215461015701e-01 <_> - 0 -1 686 9.5147592946887016e-03 + 0 -1 43 7.4608568102121353e-03 - 2.9569771140813828e-02 -5.5541282892227173e-01 + 5.7219974696636200e-02 -4.2135125398635864e-01 <_> - 0 -1 358 -1.5026458539068699e-02 + 0 -1 293 -4.3320422992110252e-03 - 2.9199507832527161e-01 -6.7493163049221039e-02 + -6.8079024553298950e-01 2.9504306614398956e-02 <_> - 0 -1 576 -3.0254235025495291e-03 + 0 -1 274 -6.5548438578844070e-03 - -3.6120423674583435e-01 5.3320098668336868e-02 + 2.9043409228324890e-01 -8.7089523673057556e-02 <_> - 0 -1 543 -3.7556474562734365e-03 + 0 -1 204 4.2611984536051750e-03 - 2.4651855230331421e-01 -7.6555579900741577e-02 + -8.5929870605468750e-02 3.1930494308471680e-01 <_> - 0 -1 870 5.2875939756631851e-02 + 0 -1 635 -7.2978977113962173e-03 - -6.2019556760787964e-02 3.0396047234535217e-01 + 1.4620631933212280e-01 -1.7617914080619812e-01 <_> - 0 -1 915 -6.4307113643735647e-04 + 0 -1 225 -2.2543172817677259e-03 - 1.4872814714908600e-01 -1.2868101894855499e-01 - <_> - - 0 -1 802 -2.7651647105813026e-02 - - -4.7678905725479126e-01 4.2087376117706299e-02 - <_> - - 0 -1 673 -2.5210313033312559e-03 - - -6.7401230335235596e-01 2.5271434336900711e-02 - <_> - - 0 -1 107 -1.7504607094451785e-03 - - -6.6526460647583008e-01 2.3153429850935936e-02 - <_> - - 0 -1 137 -1.2022716924548149e-02 - - -6.5252929925918579e-01 2.4157531559467316e-02 - <_> - - 0 -1 23 -1.6721414402127266e-02 - - 2.0145316421985626e-01 -8.8073857128620148e-02 - <_> - - 0 -1 664 -6.1156335286796093e-03 - - 2.3662807047367096e-01 -8.2179009914398193e-02 - <_> - - 0 -1 726 4.1717891581356525e-03 - - 3.0463650822639465e-02 -6.4868044853210449e-01 - <_> - - 0 -1 83 1.0461646597832441e-03 - - -1.0331799834966660e-01 1.7261520028114319e-01 - <_> - - 0 -1 158 -7.5713603291660547e-04 - - 2.2451940178871155e-01 -9.4167023897171021e-02 - <_> - - 0 -1 377 -5.1019098609685898e-03 - - 1.7748890817165375e-01 -1.0525784641504288e-01 - <_> - - 0 -1 951 5.8564399369060993e-03 - - 2.7441246435046196e-02 -6.8668657541275024e-01 - <_> - - 0 -1 331 3.8241008296608925e-03 - - -6.8950459361076355e-02 2.7575340867042542e-01 - <_> - - 0 -1 174 1.1478068307042122e-02 - - 3.9409350603818893e-02 -5.4299759864807129e-01 - <_> - - 0 -1 605 -1.4753835275769234e-03 - - -4.5533245801925659e-01 3.6614906042814255e-02 - <_> - - 0 -1 605 9.4340764917433262e-04 - - 6.0544602572917938e-02 -2.9981470108032227e-01 - <_> - - 0 -1 599 -3.6590839736163616e-03 - - 2.3720666766166687e-01 -8.0204457044601440e-02 - <_> - - 0 -1 100 -3.1423069536685944e-02 - - -7.1167147159576416e-01 2.8132835403084755e-02 - <_> - - 0 -1 403 3.5741357132792473e-03 - - 1.7519874498248100e-02 -8.3257293701171875e-01 - <_> - - 0 -1 585 -6.8605719134211540e-03 - - -6.9204151630401611e-01 2.0872814580798149e-02 - <_> - - 0 -1 902 -8.8996449485421181e-03 - - 1.8208101391792297e-01 -9.8315775394439697e-02 - <_> - - 0 -1 881 6.5573323518037796e-03 - - -7.4690498411655426e-02 2.5062057375907898e-01 - <_> - - 0 -1 912 1.4275535941123962e-02 - - 2.7385318651795387e-02 -6.8721151351928711e-01 - <_> - - 0 -1 241 -2.1887188777327538e-03 - - -4.7836220264434814e-01 3.3499576151371002e-02 - <_> - - 0 -1 6 1.9212976098060608e-02 - - 5.0344366580247879e-02 -3.3104887604713440e-01 - <_> - - 0 -1 521 1.0552004911005497e-02 - - -9.7779601812362671e-02 2.0047651231288910e-01 - <_> - - 0 -1 883 -4.9180793575942516e-04 - - 1.4232192933559418e-01 -1.3171885907649994e-01 - <_> - - 0 -1 964 3.2934427261352539e-02 - - 2.9324809089303017e-02 -5.8789533376693726e-01 - <_> - - 0 -1 305 -1.9249429460614920e-03 - - 1.5106591582298279e-01 -1.2231025844812393e-01 - <_> - - 0 -1 729 -4.4266097247600555e-03 - - 2.6083472371101379e-01 -7.3457822203636169e-02 - <_> - - 0 -1 666 -3.5673312842845917e-02 - - -6.6919100284576416e-01 2.9960991814732552e-02 - <_> - - 0 -1 602 -8.5658043622970581e-02 - - -5.1538497209548950e-01 2.9327427968382835e-02 - <_> - - 0 -1 348 -3.5126551985740662e-02 - - 2.3199184238910675e-01 -7.9689562320709229e-02 - <_> - - 0 -1 123 5.8309547603130341e-03 - - 3.0431609600782394e-02 -6.1856180429458618e-01 - <_> - - 0 -1 22 -4.4557070359587669e-03 - - 2.6333442330360413e-01 -7.0679754018783569e-02 - <_> - - 0 -1 373 1.2730281800031662e-02 - - -6.6051281988620758e-02 3.1401801109313965e-01 - <_> - - 0 -1 498 -4.6875262632966042e-03 - - 1.9294278323650360e-01 -1.0184600949287415e-01 - <_> - - 0 -1 195 -2.9066612478345633e-03 - - 1.9944235682487488e-01 -9.2275582253932953e-02 - <_> - - 0 -1 482 -3.1784668099135160e-03 - - -4.1009154915809631e-01 4.5929219573736191e-02 - <_> - - 0 -1 618 -3.7226981949061155e-03 - - 2.2945560514926910e-01 -7.6773315668106079e-02 + -5.9305733442306519e-01 3.9764832705259323e-02 <_> - 100 - -1.6428810358047485e+00 + 70 + -1.3067549467086792e+00 <_> - 0 -1 777 3.3433635253459215e-03 + 0 -1 742 -5.6160744279623032e-03 - 7.8417956829071045e-02 6.1746358871459961e-01 + 4.7913768887519836e-01 -9.8717339336872101e-02 <_> - 0 -1 171 4.1375826112926006e-03 + 0 -1 536 -5.6263338774442673e-03 - -1.0486003011465073e-01 4.9714615941047668e-01 + 2.8639736771583557e-01 -1.7997759580612183e-01 <_> - 0 -1 512 -5.4358085617423058e-03 + 0 -1 795 -1.6268140170723200e-03 - 2.9817372560501099e-01 -1.8134090304374695e-01 + 3.0874463915824890e-01 -1.3907180726528168e-01 <_> - 0 -1 734 5.7432046160101891e-03 + 0 -1 802 -1.3920383062213659e-03 - -2.1621760725975037e-01 2.8316897153854370e-01 + 3.2034638524055481e-01 -1.3876211643218994e-01 <_> - 0 -1 56 -2.2321434225887060e-03 + 0 -1 826 3.4234612248837948e-03 - 2.0751045644283295e-01 -1.5781952440738678e-01 + -1.0860712081193924e-01 3.2174232602119446e-01 <_> - 0 -1 113 1.4339581131935120e-02 + 0 -1 525 4.3767906725406647e-02 - -9.7252883017063141e-02 4.0868076682090759e-01 + -1.3255064189434052e-01 3.7021124362945557e-01 <_> - 0 -1 205 -1.1081973090767860e-02 + 0 -1 401 -4.4696494005620480e-03 - 3.3920571208000183e-01 -1.0915800184011459e-01 + -4.5687621831893921e-01 8.2243621349334717e-02 <_> - 0 -1 332 1.4586398378014565e-02 + 0 -1 332 -7.1945399977266788e-03 - -8.6110286414623260e-02 3.1800067424774170e-01 + -6.4334297180175781e-01 4.5623987913131714e-02 <_> - 0 -1 369 -1.6978669445961714e-03 + 0 -1 273 6.5287351608276367e-03 - 2.5036969780921936e-01 -1.2437737733125687e-01 + -8.9336074888706207e-02 3.3727860450744629e-01 <_> - 0 -1 708 1.2829914689064026e-02 + 0 -1 771 2.8297028038650751e-03 - 5.1119163632392883e-02 -5.4143118858337402e-01 + -1.0177894681692123e-01 3.5831856727600098e-01 <_> - 0 -1 675 -1.6196181531995535e-03 + 0 -1 925 1.1526069603860378e-02 - -5.3631567955017090e-01 4.6280529350042343e-02 + 7.5238041579723358e-02 -4.8319393396377563e-01 <_> - 0 -1 897 -2.3190132342278957e-03 + 0 -1 207 4.7937319613993168e-03 - -4.3289941549301147e-01 6.0517251491546631e-02 + 5.7682428508996964e-02 -4.7086900472640991e-01 <_> - 0 -1 212 3.5206928849220276e-02 + 0 -1 395 -3.6777029745280743e-03 - -9.1207198798656464e-02 3.1217202544212341e-01 + -4.2743790149688721e-01 7.4363298714160919e-02 <_> - 0 -1 763 3.1395033001899719e-03 + 0 -1 839 -8.0760312266647816e-04 - -7.8746505081653595e-02 3.6259949207305908e-01 + 1.4320656657218933e-01 -1.9929704070091248e-01 <_> - 0 -1 262 1.1297637596726418e-02 + 0 -1 233 3.7253312766551971e-03 - 7.4857383966445923e-02 -3.7226554751396179e-01 + 5.2736207842826843e-02 -5.2105212211608887e-01 <_> - 0 -1 786 4.6712577342987061e-02 + 0 -1 416 -2.3560712113976479e-02 - -9.2495582997798920e-02 2.9710096120834351e-01 + 4.0658730268478394e-01 -7.3024936020374298e-02 <_> - 0 -1 323 -6.8688929080963135e-02 + 0 -1 311 -4.5593185350298882e-03 - -4.8226192593574524e-01 4.9391020089387894e-02 + -6.3590377569198608e-01 3.5127460956573486e-02 <_> - 0 -1 969 -3.5051193553954363e-03 + 0 -1 551 -2.4863984435796738e-03 - -4.8506668210029602e-01 4.1722387075424194e-02 + -4.5599257946014404e-01 5.3035512566566467e-02 <_> - 0 -1 694 1.1046628467738628e-02 + 0 -1 424 -2.6802124921232462e-03 - -5.4003205150365829e-02 4.2598679661750793e-01 + 1.9116453826427460e-01 -1.3404799997806549e-01 <_> - 0 -1 26 -2.0021714270114899e-02 + 0 -1 11 -7.7647715806961060e-02 - -4.3884435296058655e-01 4.9609564244747162e-02 + 4.1297465562820435e-01 -6.3970938324928284e-02 <_> - 0 -1 59 1.1850561946630478e-02 + 0 -1 566 2.3329094983637333e-03 - -7.8088991343975067e-02 2.7602908015251160e-01 + -1.2160944193601608e-01 2.3117628693580627e-01 <_> - 0 -1 180 4.1900265961885452e-02 + 0 -1 5 -6.6609308123588562e-03 - -9.9447727203369141e-02 2.0865923166275024e-01 + 2.2600707411766052e-01 -1.2069495767354965e-01 <_> - 0 -1 590 -2.9064953327178955e-02 + 0 -1 133 -5.0821684300899506e-02 - 2.9170644283294678e-01 -7.3766425251960754e-02 + 3.2217630743980408e-01 -7.6335281133651733e-02 <_> - 0 -1 474 -2.6618237607181072e-03 + 0 -1 537 -7.0379404351115227e-03 - -3.2550674676895142e-01 7.5278282165527344e-02 + 1.8399104475975037e-01 -1.4812190830707550e-01 <_> - 0 -1 342 3.2252955716103315e-03 + 0 -1 134 -3.3276520669460297e-02 - -6.9696784019470215e-02 3.1337058544158936e-01 + -6.0358065366744995e-01 3.5330448299646378e-02 <_> - 0 -1 582 7.8913231845945120e-04 + 0 -1 392 7.5909225270152092e-03 - 6.9301478564739227e-02 -3.2840612530708313e-01 + 3.1779482960700989e-02 -6.4767998456954956e-01 <_> - 0 -1 287 6.6613638773560524e-03 + 0 -1 613 -5.6639023125171661e-02 - 4.5366134494543076e-02 -4.4648596644401550e-01 + -4.6455994248390198e-01 4.6072337776422501e-02 <_> - 0 -1 721 1.9416993018239737e-03 + 0 -1 124 3.7777128163725138e-03 - -1.3086521625518799e-01 1.5360382199287415e-01 + 5.7451672852039337e-02 -3.7793967127799988e-01 <_> - 0 -1 633 6.0106818564236164e-03 + 0 -1 271 8.9145395904779434e-03 - 4.8219148069620132e-02 -4.1355597972869873e-01 + -7.5942978262901306e-02 3.1487807631492615e-01 <_> - 0 -1 267 -6.8208400625735521e-04 + 0 -1 841 -1.4818884432315826e-02 - 1.6169321537017822e-01 -1.2492433935403824e-01 + 2.7122247219085693e-01 -9.8314434289932251e-02 <_> - 0 -1 756 1.0027646087110043e-02 + 0 -1 381 -5.5922558531165123e-03 - 3.0267864465713501e-02 -6.4555937051773071e-01 + -6.4762401580810547e-01 4.1314963251352310e-02 <_> - 0 -1 948 -6.4138583838939667e-03 + 0 -1 595 3.1491921981796622e-04 - -6.9905740022659302e-01 2.3570762947201729e-02 + -1.4864055812358856e-01 1.4411780238151550e-01 <_> - 0 -1 270 4.4392300769686699e-03 + 0 -1 136 -5.7063563726842403e-03 - -5.8655023574829102e-02 3.3790254592895508e-01 + -4.6024248003959656e-01 4.7999884933233261e-02 <_> - 0 -1 556 3.8361353799700737e-03 + 0 -1 210 -1.2257394846528769e-03 - 3.1548105180263519e-02 -6.6295272111892700e-01 + 3.2288366556167603e-01 -7.0425607264041901e-02 <_> - 0 -1 872 -1.0007477831095457e-03 + 0 -1 775 -1.6291948035359383e-02 - 2.2688214480876923e-01 -8.8843353092670441e-02 + 2.7573275566101074e-01 -8.3055868744850159e-02 <_> - 0 -1 928 4.7894790768623352e-03 + 0 -1 156 -8.1639690324664116e-04 - 3.0278960242867470e-02 -6.1569523811340332e-01 + 1.7044979333877563e-01 -1.4129574596881866e-01 <_> - 0 -1 946 5.6278239935636520e-03 + 0 -1 975 5.1114819943904877e-03 - -7.8841529786586761e-02 2.4433708190917969e-01 + 3.3882420510053635e-02 -6.9941717386245728e-01 <_> - 0 -1 942 -7.3229577392339706e-03 + 0 -1 977 -2.8371806256473064e-03 - 3.3265948295593262e-01 -6.7663870751857758e-02 + -3.7707236409187317e-01 5.7759616523981094e-02 <_> - 0 -1 29 -4.5515028759837151e-03 + 0 -1 772 5.3479857742786407e-03 - -4.6472606062889099e-01 4.3983772397041321e-02 + 4.1541736572980881e-02 -4.8687714338302612e-01 <_> - 0 -1 293 1.8201436614617705e-03 + 0 -1 735 1.1360908392816782e-03 - -8.1468850374221802e-02 2.3861412703990936e-01 + -7.8717894852161407e-02 2.9692038893699646e-01 <_> - 0 -1 134 -1.1703525483608246e-01 + 0 -1 947 1.4100213302299380e-03 - -6.7043519020080566e-01 2.9206298291683197e-02 + 4.3843001127243042e-02 -5.1339787244796753e-01 <_> - 0 -1 314 -5.0897812470793724e-03 + 0 -1 387 8.7079760851338506e-04 - 5.1766836643218994e-01 -4.1514929383993149e-02 + -9.8695866763591766e-02 2.2730629146099091e-01 <_> - 0 -1 72 -8.7873879820108414e-03 + 0 -1 211 -5.4065873846411705e-03 - -5.2038532495498657e-01 4.0998894721269608e-02 + -6.3011974096298218e-01 3.7802927196025848e-02 <_> - 0 -1 183 -5.6120483204722404e-03 + 0 -1 816 -1.6894804313778877e-02 - -7.3375105857849121e-01 2.1229419857263565e-02 + -5.0091201066970825e-01 3.5215172916650772e-02 <_> - 0 -1 244 1.0250378400087357e-02 + 0 -1 766 1.4164673630148172e-03 - 2.5667199864983559e-02 -6.1355572938919067e-01 + -8.8441111147403717e-02 2.4102251231670380e-01 <_> - 0 -1 771 -4.8573492094874382e-03 + 0 -1 704 -1.1464871931821108e-03 - 1.6895917057991028e-01 -1.1120435595512390e-01 + 1.9273723661899567e-01 -1.1090471595525742e-01 <_> - 0 -1 312 2.5750461965799332e-02 + 0 -1 861 -3.2706123311072588e-03 - 3.5605397075414658e-02 -5.4535841941833496e-01 + -4.5202803611755371e-01 4.7059688717126846e-02 <_> - 0 -1 932 4.1080308146774769e-03 + 0 -1 70 1.1416582390666008e-02 - 5.0505056977272034e-02 -3.3836016058921814e-01 + 2.6714416220784187e-02 -6.9660711288452148e-01 <_> - 0 -1 317 3.9434060454368591e-03 + 0 -1 310 2.7643535286188126e-03 - -8.8688671588897705e-02 2.0660057663917542e-01 + 4.7252438962459564e-02 -3.9458727836608887e-01 <_> - 0 -1 553 6.5294457599520683e-03 + 0 -1 435 2.4567130021750927e-03 - -1.2931570410728455e-01 1.6514816880226135e-01 + -7.5188823044300079e-02 2.9944056272506714e-01 <_> - 0 -1 931 2.2269077599048615e-02 + 0 -1 441 -7.3516201227903366e-03 - -4.7366518527269363e-02 3.8508006930351257e-01 + 2.8476437926292419e-01 -9.2367134988307953e-02 <_> - 0 -1 455 3.5300105810165405e-03 + 0 -1 662 -4.3670929968357086e-02 - 5.3873997181653976e-02 -3.3755952119827271e-01 + -6.8588620424270630e-01 3.3353023231029510e-02 <_> - 0 -1 286 -2.4763222783803940e-02 + 0 -1 138 -6.4992159605026245e-02 - -3.2349804043769836e-01 5.6731209158897400e-02 + -7.9678738117218018e-01 2.0331909880042076e-02 <_> - 0 -1 790 3.1297234818339348e-03 + 0 -1 286 -1.1700032278895378e-02 - -6.7191042006015778e-02 2.7804708480834961e-01 + -6.1183351278305054e-01 2.7328895404934883e-02 <_> - 0 -1 621 -1.7003760440275073e-03 + 0 -1 589 3.0743866227567196e-03 - -4.2539414763450623e-01 4.3875113129615784e-02 + -7.7295452356338501e-02 2.6685911417007446e-01 <_> - 0 -1 750 8.3633856847882271e-03 + 0 -1 584 -1.5546076931059361e-02 - 3.0976327136158943e-02 -5.2819561958312988e-01 + -5.5246621370315552e-01 4.0912687778472900e-02 <_> - 0 -1 473 -8.7768933735787868e-04 + 0 -1 40 6.5568592399358749e-03 - 1.9984373450279236e-01 -9.0307638049125671e-02 + -1.0432150214910507e-01 1.9379787147045135e-01 <_> - 0 -1 874 -9.2862239107489586e-03 + 0 -1 29 -8.0047458410263062e-02 - -6.9824051856994629e-01 2.5733994320034981e-02 + 3.9228948950767517e-01 -5.2565738558769226e-02 <_> - 0 -1 393 -1.1124708689749241e-03 + 0 -1 227 1.5684183686971664e-02 - 1.9901444017887115e-01 -9.2606224119663239e-02 + -1.1151826381683350e-01 1.8633136153221130e-01 <_> - 0 -1 575 -3.2134181819856167e-03 + 0 -1 546 2.3603178560733795e-03 - 2.3832809925079346e-01 -7.1890726685523987e-02 + -1.0219112038612366e-01 2.0333246886730194e-01 <_> - 0 -1 516 5.9113521128892899e-03 + 0 -1 585 -3.5169085022062063e-03 - -6.7413553595542908e-02 2.7445399761199951e-01 + 2.7427124977111816e-01 -8.6362943053245544e-02 <_> - 0 -1 615 -4.5188870280981064e-03 + 0 -1 476 9.4871241599321365e-03 - -4.0147483348846436e-01 4.4757787138223648e-02 + 3.5626750439405441e-02 -6.2631088495254517e-01 <_> - 0 -1 48 2.8254585340619087e-03 + 0 -1 629 -9.3261618167161942e-03 - 4.3743204325437546e-02 -3.7922030687332153e-01 + -7.1806514263153076e-01 2.4241568520665169e-02 <_> - 0 -1 637 -2.6064300909638405e-03 + 0 -1 666 -6.3302312046289444e-03 - 2.0811253786087036e-01 -8.2700952887535095e-02 + 2.1094995737075806e-01 -9.2475786805152893e-02 <_> - 0 -1 635 1.0516709880903363e-03 + 0 -1 598 -2.8244811110198498e-03 - -8.9635595679283142e-02 2.6205003261566162e-01 + 2.6596403121948242e-01 -8.0099694430828094e-02 <_> - 0 -1 453 -1.2204772792756557e-03 + 0 -1 145 -1.1591307818889618e-02 - 2.0626722276210785e-01 -8.6367763578891754e-02 + 2.3619163036346436e-01 -8.5169024765491486e-02 <_> - 0 -1 765 5.0495425239205360e-03 + 0 -1 117 2.1401243284344673e-03 - 4.5425735414028168e-02 -4.1301593184471130e-01 + -1.0995808988809586e-01 2.1230246126651764e-01 <_> - 0 -1 440 -3.2243374735116959e-03 + 0 -1 562 4.2046746239066124e-03 - 1.4690431952476501e-01 -1.2587989866733551e-01 + 3.6688093096017838e-02 -6.1654287576675415e-01 <_> - 0 -1 340 -2.3263287730515003e-03 + 0 -1 605 1.1085141450166702e-03 - -4.1975629329681396e-01 4.7924898564815521e-02 + -8.0656312406063080e-02 2.7754181623458862e-01 <_> - 0 -1 307 -5.4887672886252403e-03 + 0 -1 829 -8.2805287092924118e-03 - -4.1799965500831604e-01 3.8171879947185516e-02 - <_> - - 0 -1 628 4.6792116016149521e-02 - - -5.7823952287435532e-02 3.2188871502876282e-01 - <_> - - 0 -1 824 2.3481161333620548e-03 - - -5.3754303604364395e-02 3.0415624380111694e-01 - <_> - - 0 -1 179 -3.5063792020082474e-03 - - -3.8483345508575439e-01 4.7024305909872055e-02 - <_> - - 0 -1 247 1.6757374396547675e-03 - - -1.3115778565406799e-01 1.6631519794464111e-01 - <_> - - 0 -1 232 1.1546656489372253e-02 - - -5.0141811370849609e-02 3.1787791848182678e-01 - <_> - - 0 -1 504 1.8043547868728638e-02 - - 2.5008214637637138e-02 -7.1255826950073242e-01 - <_> - - 0 -1 204 -3.1235523521900177e-02 - - 2.1876916289329529e-01 -7.7429860830307007e-02 - <_> - - 0 -1 248 9.7835529595613480e-03 - - -5.6040864437818527e-02 2.7669593691825867e-01 - <_> - - 0 -1 341 2.8905952349305153e-03 - - 5.1800269633531570e-02 -3.1925117969512939e-01 - <_> - - 0 -1 436 7.8792851418256760e-03 - - -6.0856487601995468e-02 2.8146442770957947e-01 - <_> - - 0 -1 717 1.3523480854928493e-02 - - 2.4503752589225769e-02 -7.2409152984619141e-01 - <_> - - 0 -1 966 3.1048720702528954e-03 - - 4.5725930482149124e-02 -3.3751598000526428e-01 - <_> - - 0 -1 808 -1.0647572576999664e-02 - - -5.4894274473190308e-01 2.8428088873624802e-02 - <_> - - 0 -1 49 -4.8104384914040565e-03 - - 2.0432402193546295e-01 -8.2248799502849579e-02 - <_> - - 0 -1 4 2.7336277067661285e-02 - - -6.7068248987197876e-02 2.3702095448970795e-01 - <_> - - 0 -1 940 -1.7123305797576904e-01 - - 5.2998173236846924e-01 -3.1578365713357925e-02 - <_> - - 0 -1 781 -4.3723154813051224e-03 - - 2.8745722770690918e-01 -5.7618625462055206e-02 - <_> - - 0 -1 743 6.7968526855111122e-03 - - -6.3940502703189850e-02 2.5016403198242188e-01 - <_> - - 0 -1 47 -1.6302993753924966e-03 - - -2.6190960407257080e-01 6.1918053776025772e-02 - <_> - - 0 -1 712 1.7953850328922272e-03 - - -5.3176742047071457e-02 3.0019727349281311e-01 - <_> - - 0 -1 311 6.2259500846266747e-03 - - 3.1048897653818130e-02 -5.6447005271911621e-01 - <_> - - 0 -1 712 -1.4370339922606945e-03 - - 1.8240424990653992e-01 -8.9968219399452209e-02 - <_> - - 0 -1 226 -9.0678166598081589e-03 - - -6.3961440324783325e-01 2.3404622450470924e-02 - <_> - - 0 -1 604 -8.2531813532114029e-03 - - -5.9389066696166992e-01 2.3573497310280800e-02 - <_> - - 0 -1 573 -2.2232248447835445e-03 - - 1.9480818510055542e-01 -8.3372615277767181e-02 - <_> - - 0 -1 355 -6.5612345933914185e-03 - - -4.2599579691886902e-01 3.7793021649122238e-02 - <_> - - 0 -1 571 1.2282801326364279e-03 - - -8.5198581218719482e-02 1.9753733277320862e-01 - <_> - - 0 -1 162 -1.0268764197826385e-01 - - -3.9634877443313599e-01 4.0690928697586060e-02 - <_> - - 0 -1 711 -1.5864435583353043e-02 - - 1.9112223386764526e-01 -8.7620854377746582e-02 - <_> - - 0 -1 715 4.8304852680303156e-04 - - -1.2651769816875458e-01 1.5627197921276093e-01 + -6.5883606672286987e-01 3.6048211157321930e-02 <_> - 100 - -1.5192077159881592e+00 + 70 + -1.2368309497833252e+00 <_> - 0 -1 563 -7.2759687900543213e-03 + 0 -1 716 -3.3105849288403988e-03 - 6.4157706499099731e-01 1.0701754689216614e-01 + 5.0566112995147705e-01 -8.2956805825233459e-02 <_> - 0 -1 713 -3.8208619225770235e-03 + 0 -1 190 4.5855166390538216e-03 - 4.9172374606132507e-01 -9.4503603875637054e-02 + -1.3226345181465149e-01 3.9034894108772278e-01 <_> - 0 -1 817 3.4225741401314735e-03 + 0 -1 576 -2.6665716432034969e-03 - -1.3255690038204193e-01 3.2899302244186401e-01 + 2.7508354187011719e-01 -1.3807572424411774e-01 <_> - 0 -1 384 3.3628481905907393e-03 + 0 -1 734 1.8106825649738312e-02 - -1.6529263556003571e-01 3.8905930519104004e-01 + -1.2738862633705139e-01 3.5449108481407166e-01 <_> - 0 -1 400 4.2874794453382492e-03 + 0 -1 830 -5.7813120074570179e-03 - 6.4744032919406891e-02 -4.9827992916107178e-01 + 2.7463605999946594e-01 -1.2951526045799255e-01 <_> - 0 -1 462 -3.3541000448167324e-03 + 0 -1 379 8.9321136474609375e-03 - 1.6614496707916260e-01 -1.8601009249687195e-01 + 4.8491790890693665e-02 -5.8104276657104492e-01 <_> - 0 -1 683 -1.8176173325628042e-03 + 0 -1 17 6.2806839123368263e-03 - 2.6610982418060303e-01 -1.1267235130071640e-01 + -1.3215491175651550e-01 2.1852293610572815e-01 <_> - 0 -1 268 -2.2096108645200729e-02 + 0 -1 9 -4.3670572340488434e-02 - 3.2448813319206238e-01 -8.3371557295322418e-02 + 3.8786840438842773e-01 -7.4191503226757050e-02 <_> - 0 -1 751 5.8036940172314644e-03 + 0 -1 554 -6.2309622764587402e-02 - -1.2335725873708725e-01 2.5443312525749207e-01 + 3.3408007025718689e-01 -8.7087221443653107e-02 <_> - 0 -1 243 4.7676274552941322e-03 + 0 -1 686 -3.2859744969755411e-03 - -1.4914961159229279e-01 1.8570756912231445e-01 + 3.3486780524253845e-01 -8.9008949697017670e-02 <_> - 0 -1 386 2.7053440135205165e-05 + 0 -1 346 -3.9627305231988430e-03 - -2.1181178092956543e-01 1.1339543759822845e-01 + 2.6155433058738708e-01 -9.5614455640316010e-02 <_> - 0 -1 917 -2.5647766888141632e-03 + 0 -1 434 1.0877416934818029e-03 - -4.3090465664863586e-01 5.7283867150545120e-02 + -1.4199735224246979e-01 1.8414285778999329e-01 <_> - 0 -1 5 -9.9645227193832397e-02 + 0 -1 249 5.4819821380078793e-03 - 4.7573822736740112e-01 -5.1954109221696854e-02 + 7.4260123074054718e-02 -5.6989872455596924e-01 <_> - 0 -1 794 2.8423275798559189e-03 + 0 -1 916 4.9011572264134884e-04 - -7.9270146787166595e-02 3.1205773353576660e-01 + -1.9576059281826019e-01 1.3506270945072174e-01 <_> - 0 -1 336 -4.7821709886193275e-03 + 0 -1 911 -7.7052684500813484e-03 - -4.4589859247207642e-01 5.0418782979249954e-02 + -5.0443643331527710e-01 6.1383318156003952e-02 <_> - 0 -1 770 1.6041981056332588e-02 + 0 -1 164 4.8691947013139725e-03 - -7.6039068400859833e-02 3.0843210220336914e-01 + 4.3469026684761047e-02 -5.2802342176437378e-01 <_> - 0 -1 778 -3.6943168379366398e-03 + 0 -1 344 2.4673391599208117e-03 - 2.7407246828079224e-01 -8.8150359690189362e-02 + -8.9178681373596191e-02 3.0606627464294434e-01 <_> - 0 -1 71 8.4026419790461659e-04 + 0 -1 172 -3.6682826466858387e-03 - -1.5873835980892181e-01 1.3953365385532379e-01 + -6.5514552593231201e-01 4.7427203506231308e-02 <_> - 0 -1 70 -8.0992765724658966e-03 + 0 -1 365 2.5194899644702673e-03 - -5.3085809946060181e-01 3.9269823580980301e-02 + 4.9365170300006866e-02 -4.0812951326370239e-01 <_> - 0 -1 826 3.7676268257200718e-03 + 0 -1 531 5.8970693498849869e-03 - 7.0321731269359589e-02 -3.0400907993316650e-01 + 3.5579398274421692e-02 -6.4191317558288574e-01 <_> - 0 -1 719 -8.4449478890746832e-04 + 0 -1 842 1.7767311073839664e-03 - 1.6032356023788452e-01 -1.2606577575206757e-01 + -8.6629316210746765e-02 2.7705979347229004e-01 <_> - 0 -1 424 1.9298447296023369e-03 + 0 -1 885 4.0457276627421379e-03 - -7.4880234897136688e-02 2.8130438923835754e-01 + 5.6002113968133926e-02 -4.7005215287208557e-01 <_> - 0 -1 517 -3.1593129970133305e-03 + 0 -1 522 3.2862280495464802e-03 - -4.1825935244560242e-01 4.7720715403556824e-02 + -1.2930884957313538e-01 2.0613414049148560e-01 <_> - 0 -1 19 7.7791810035705566e-03 + 0 -1 322 1.4660503948107362e-03 - 4.1349764913320541e-02 -4.5770570635795593e-01 + -9.9395424127578735e-02 3.3950179815292358e-01 <_> - 0 -1 427 -3.2682183664292097e-03 + 0 -1 266 1.9015703350305557e-02 - 2.1473638713359833e-01 -9.5344312489032745e-02 + 6.0197159647941589e-02 -5.1893943548202515e-01 <_> - 0 -1 490 -2.2884239442646503e-03 + 0 -1 102 -7.1178808808326721e-02 - 2.4062317609786987e-01 -9.0378150343894958e-02 + -4.3668299913406372e-01 4.7340013086795807e-02 <_> - 0 -1 844 2.5960609782487154e-03 + 0 -1 795 -4.6305771684274077e-04 - 3.4732636064291000e-02 -6.1617314815521240e-01 + 1.4736598730087280e-01 -1.5406486392021179e-01 <_> - 0 -1 32 8.0937854945659637e-03 + 0 -1 298 -4.7644632868468761e-03 - 3.9185214787721634e-02 -4.7461858391761780e-01 + -5.0336647033691406e-01 4.4053792953491211e-02 <_> - 0 -1 289 5.6226095184683800e-03 + 0 -1 761 -8.5318256169557571e-03 - 3.3066269010305405e-02 -5.4723787307739258e-01 + -5.9967356920242310e-01 3.2567754387855530e-02 <_> - 0 -1 249 3.3066368196159601e-03 + 0 -1 713 -2.7496295515447855e-03 - -1.0691711306571960e-01 1.8520861864089966e-01 + 1.3502316176891327e-01 -1.6025592386722565e-01 <_> - 0 -1 277 -6.9545931182801723e-03 + 0 -1 607 4.2666587978601456e-03 - 2.8144246339797974e-01 -6.7726366221904755e-02 + 2.5802688673138618e-02 -7.8170543909072876e-01 <_> - 0 -1 37 2.0960648544132710e-03 + 0 -1 216 -2.9856398701667786e-02 - 6.5764650702476501e-02 -3.1323519349098206e-01 + 2.4982222914695740e-01 -8.8180385529994965e-02 <_> - 0 -1 546 -2.9915343038737774e-03 + 0 -1 226 2.2136634215712547e-03 - 2.4481751024723053e-01 -7.8186720609664917e-02 + -1.4314906299114227e-01 1.6945528984069824e-01 <_> - 0 -1 461 9.8559018224477768e-03 + 0 -1 640 1.6336794942617416e-02 - 2.9282161965966225e-02 -6.9216150045394897e-01 + 4.6008959412574768e-02 -4.9338266253471375e-01 <_> - 0 -1 567 -9.9846869707107544e-03 + 0 -1 459 7.9861842095851898e-03 - 3.1725984811782837e-01 -6.4144395291805267e-02 + -1.1460029333829880e-01 1.9282819330692291e-01 <_> - 0 -1 417 4.0295444428920746e-02 + 0 -1 650 -1.7455726629123092e-03 - -1.0545746237039566e-01 1.9351178407669067e-01 + 1.7520657181739807e-01 -1.2269173562526703e-01 <_> - 0 -1 359 -4.5808870345354080e-03 + 0 -1 124 -6.2451506964862347e-03 - -2.7045866847038269e-01 6.3011758029460907e-02 + -4.5638361573219299e-01 4.8106320202350616e-02 <_> - 0 -1 76 -3.4120261669158936e-02 + 0 -1 406 8.5668899118900299e-03 - -5.0046062469482422e-01 3.3663876354694366e-02 + -8.0403454601764679e-02 3.0411326885223389e-01 <_> - 0 -1 475 5.9857115149497986e-02 + 0 -1 974 8.6863581091165543e-03 - -6.3651382923126221e-02 2.9614394903182983e-01 + 3.4176670014858246e-02 -7.3028022050857544e-01 <_> - 0 -1 434 3.9175078272819519e-03 + 0 -1 36 1.0814646258950233e-02 - 3.2706990838050842e-02 -5.7929420471191406e-01 + 2.5131458416581154e-02 -6.7325627803802490e-01 <_> - 0 -1 60 1.1147339828312397e-02 + 0 -1 709 4.4222913682460785e-02 - -7.9590849578380585e-02 2.3456735908985138e-01 + 3.9326712489128113e-02 -5.1067680120468140e-01 <_> - 0 -1 642 -2.5253929197788239e-03 + 0 -1 903 3.7128489930182695e-03 - -5.9936809539794922e-01 2.9250813648104668e-02 + -1.3248492777347565e-01 1.6692358255386353e-01 <_> - 0 -1 578 -1.6680266708135605e-02 + 0 -1 129 -4.6475054696202278e-03 - 3.0521371960639954e-01 -5.8340109884738922e-02 + 1.7683532834053040e-01 -1.2570241093635559e-01 <_> - 0 -1 800 7.4669495224952698e-03 + 0 -1 291 4.2433524504303932e-03 - 3.1027967110276222e-02 -6.2497019767761230e-01 + 3.6985948681831360e-02 -5.8369445800781250e-01 <_> - 0 -1 913 2.8406577184796333e-03 + 0 -1 315 -5.1774000748991966e-03 - 4.1042126715183258e-02 -4.1006734967231750e-01 + 5.1487326622009277e-01 -4.1473735123872757e-02 <_> - 0 -1 702 -4.7403648495674133e-03 + 0 -1 855 4.2645614594221115e-03 - 2.0529302954673767e-01 -8.8142603635787964e-02 + 3.7253957241773605e-02 -5.7676959037780762e-01 <_> - 0 -1 700 3.7362352013587952e-03 + 0 -1 83 4.8632645048201084e-03 - -6.1495106667280197e-02 3.4078758955001831e-01 + -6.7035257816314697e-02 3.1131938099861145e-01 <_> - 0 -1 679 -4.4546797871589661e-02 + 0 -1 250 2.6089766994118690e-02 - -8.9466398954391479e-01 2.2682141512632370e-02 + -8.2920446991920471e-02 3.0445784330368042e-01 <_> - 0 -1 416 9.0460591018199921e-03 + 0 -1 625 -1.9001008477061987e-03 - 4.8672281205654144e-02 -3.3261755108833313e-01 + -4.3419414758682251e-01 4.6812325716018677e-02 <_> - 0 -1 574 -3.9043920114636421e-03 + 0 -1 891 -6.0952613130211830e-03 - 2.2659721970558167e-01 -7.7551431953907013e-02 + -5.1850622892379761e-01 3.6754775792360306e-02 <_> - 0 -1 380 1.0861126706004143e-02 + 0 -1 564 1.2120242230594158e-02 - -7.7613808214664459e-02 2.2056312859058380e-01 + -7.4773810803890228e-02 2.6738941669464111e-01 <_> - 0 -1 338 -1.2531490065157413e-03 + 0 -1 817 -1.8978580832481384e-02 - 2.2868460416793823e-01 -8.1201769411563873e-02 + 2.5657230615615845e-01 -8.0304212868213654e-02 <_> - 0 -1 339 -5.6936070322990417e-03 + 0 -1 338 4.3438978493213654e-02 - -5.6885385513305664e-01 3.6236546933650970e-02 + -6.2818735837936401e-02 3.2261833548545837e-01 <_> - 0 -1 140 1.4989164192229509e-03 + 0 -1 773 9.4384723342955112e-04 - 3.5795394331216812e-02 -4.7115951776504517e-01 + -9.8582215607166290e-02 2.2370135784149170e-01 <_> - 0 -1 81 4.8389505594968796e-02 + 0 -1 519 -4.1803726926445961e-03 - 2.8578057885169983e-02 -5.6662684679031372e-01 + -4.9802374839782715e-01 4.3809909373521805e-02 <_> - 0 -1 706 -6.7009456455707550e-02 + 0 -1 195 -9.7246468067169189e-03 - 3.6811140179634094e-01 -4.8919521272182465e-02 + 2.2823798656463623e-01 -9.8547600209712982e-02 <_> - 0 -1 129 -6.9928979501128197e-03 + 0 -1 658 2.7193846181035042e-03 - 2.2268642485141754e-01 -8.1494621932506561e-02 + -9.1188244521617889e-02 2.2684387862682343e-01 <_> - 0 -1 506 -5.0552012398838997e-03 + 0 -1 174 6.2224082648754120e-03 - -3.9911568164825439e-01 4.8226438462734222e-02 + 3.2258503139019012e-02 -6.0108250379562378e-01 <_> - 0 -1 577 -1.6228569438681006e-03 + 0 -1 77 -4.8602908849716187e-01 - 2.0442382991313934e-01 -9.1497577726840973e-02 + 6.3337916135787964e-01 -3.3006772398948669e-02 <_> - 0 -1 812 1.4232760295271873e-03 + 0 -1 550 -5.3604291751980782e-03 - -8.9272662997245789e-02 1.9328704476356506e-01 + 2.9434949159622192e-01 -6.1312302947044373e-02 <_> - 0 -1 435 1.4769298955798149e-02 + 0 -1 541 5.5021280422806740e-03 - 4.3185703456401825e-02 -4.1162547469139099e-01 + 4.1839476674795151e-02 -4.5681878924369812e-01 <_> - 0 -1 688 1.0630609467625618e-02 + 0 -1 326 -1.3823953922837973e-03 - 2.0712809637188911e-02 -7.4652433395385742e-01 + 1.6067574918270111e-01 -1.1796293407678604e-01 <_> - 0 -1 366 -4.6220947988331318e-03 + 0 -1 514 2.0954519510269165e-02 - -2.6612642407417297e-01 6.2285874038934708e-02 + -5.7253565639257431e-02 3.3830171823501587e-01 <_> - 0 -1 608 -2.2310419008135796e-03 + 0 -1 409 7.4234008789062500e-03 - -6.4442801475524902e-01 2.2920599207282066e-02 + -7.4798591434955597e-02 2.6430690288543701e-01 <_> - 0 -1 259 -7.5279012322425842e-02 + 0 -1 578 2.1767318248748779e-03 - -5.4105269908905029e-01 2.7185589075088501e-02 + -8.0530151724815369e-02 2.5947657227516174e-01 <_> - 0 -1 319 6.8284743465483189e-03 + 0 -1 623 1.8930230289697647e-03 - -8.5639610886573792e-02 1.9920121133327484e-01 + -8.1788897514343262e-02 2.2988820075988770e-01 <_> - 0 -1 410 -7.6434519141912460e-03 + 0 -1 533 6.9275917485356331e-03 - 2.4088086187839508e-01 -6.8174593150615692e-02 + 2.6962997391819954e-02 -7.6910203695297241e-01 <_> - 0 -1 644 -3.6089830100536346e-03 + 0 -1 334 6.7140227183699608e-03 - 1.8979941308498383e-01 -9.1478735208511353e-02 + 2.3244854062795639e-02 -6.8406605720520020e-01 <_> - 0 -1 105 4.5644217729568481e-01 + 0 -1 632 -3.4494437277317047e-02 - -3.5746987909078598e-02 5.1038581132888794e-01 + -6.5257686376571655e-01 2.4584138765931129e-02 <_> - 0 -1 55 4.3285787105560303e-03 + 0 -1 787 1.9636256620287895e-03 - 5.0642926245927811e-02 -3.4335514903068542e-01 - <_> - - 0 -1 114 -3.0497182160615921e-03 - - 1.5943552553653717e-01 -1.0838232934474945e-01 - <_> - - 0 -1 153 2.9164180159568787e-03 - - -6.2386274337768555e-02 2.6772892475128174e-01 - <_> - - 0 -1 536 -6.7837955430150032e-03 - - -2.8828456997871399e-01 5.4219286888837814e-02 - <_> - - 0 -1 318 4.7922343946993351e-03 - - 4.1374113410711288e-02 -3.9169260859489441e-01 - <_> - - 0 -1 933 1.1295514181256294e-02 - - -5.8489643037319183e-02 2.8171694278717041e-01 - <_> - - 0 -1 847 -1.9917660392820835e-03 - - 1.6076046228408813e-01 -1.1378295719623566e-01 - <_> - - 0 -1 613 -1.5121680917218328e-03 - - -4.2076098918914795e-01 3.7524472922086716e-02 - <_> - - 0 -1 266 -2.0562859252095222e-02 - - 1.6639313101768494e-01 -9.5253549516201019e-02 - <_> - - 0 -1 709 -2.3025400936603546e-02 - - -3.1259611248970032e-01 5.8197792619466782e-02 - <_> - - 0 -1 584 -3.6875833757221699e-03 - - 2.2967162728309631e-01 -7.0608235895633698e-02 - <_> - - 0 -1 632 1.2718647718429565e-02 - - 4.4480670243501663e-02 -4.1392150521278381e-01 - <_> - - 0 -1 392 1.1408344144001603e-03 - - -8.0126009881496429e-02 2.2867898643016815e-01 - <_> - - 0 -1 138 2.8175862506031990e-02 - - -7.3071323335170746e-02 2.3685938119888306e-01 - <_> - - 0 -1 596 6.4620561897754669e-02 - - 4.4116552919149399e-02 -4.2114758491516113e-01 - <_> - - 0 -1 237 -2.5126901455223560e-03 - - 1.7448952794075012e-01 -9.9981509149074554e-02 - <_> - - 0 -1 949 -2.7390490286052227e-03 - - -3.7159797549247742e-01 4.5618161559104919e-02 - <_> - - 0 -1 351 4.5697823166847229e-02 - - 2.5755234062671661e-02 -5.6903475522994995e-01 - <_> - - 0 -1 720 -8.8378116488456726e-03 - - 1.5099802613258362e-01 -9.9460050463676453e-02 - <_> - - 0 -1 488 3.5273849498480558e-03 - - 4.6311099082231522e-02 -3.4411522746086121e-01 - <_> - - 0 -1 876 8.8435463840141892e-04 - - -6.9374859333038330e-02 2.2488924860954285e-01 - <_> - - 0 -1 876 -1.6139955259859562e-03 - - 3.3221766352653503e-01 -5.1287319511175156e-02 - <_> - - 0 -1 970 4.1209710761904716e-03 - - 3.1247327104210854e-02 -5.1796287298202515e-01 - <_> - - 0 -1 593 6.8625092506408691e-02 - - -4.8976749181747437e-02 3.6052888631820679e-01 - <_> - - 0 -1 128 1.9539505243301392e-02 - - -3.5133589059114456e-02 4.0571358799934387e-01 - <_> - - 0 -1 295 1.0195776820182800e-02 - - 2.9883516952395439e-02 -5.4385137557983398e-01 - <_> - - 0 -1 636 -9.7053672652691603e-04 - - 1.7753951251506805e-01 -8.5428759455680847e-02 - <_> - - 0 -1 299 7.0950109511613846e-03 - - 2.6922283694148064e-02 -5.7553297281265259e-01 - <_> - - 0 -1 89 3.3868722617626190e-02 - - 2.4893242865800858e-02 -5.1963424682617188e-01 - <_> - - 0 -1 799 8.9386161416769028e-03 - - -6.5781995654106140e-02 2.1598634123802185e-01 - <_> - - 0 -1 934 -1.1335080489516258e-03 - - 1.3626587390899658e-01 -1.2551343441009521e-01 + -9.1118760406970978e-02 2.0629465579986572e-01 <_> - 100 - -1.5342161655426025e+00 + 80 + -1.3304495811462402e+00 <_> - 0 -1 442 6.4967479556798935e-03 + 0 -1 572 -9.1053368523716927e-03 - 9.2756643891334534e-02 6.3256287574768066e-01 + 4.8031216859817505e-01 -9.3147851526737213e-02 <_> - 0 -1 735 -7.0229507982730865e-03 + 0 -1 715 -2.1384856663644314e-03 - 4.7454160451889038e-01 -9.1181516647338867e-02 + 3.4027156233787537e-01 -1.4834050834178925e-01 <_> - 0 -1 788 -1.1249051894992590e-03 + 0 -1 953 1.2453617528080940e-02 - 2.7701923251152039e-01 -1.5582662820816040e-01 + -8.0359503626823425e-02 4.7585478425025940e-01 <_> - 0 -1 272 2.1593673154711723e-02 + 0 -1 198 5.0965799018740654e-03 - -1.2302023172378540e-01 4.3630394339561462e-01 + -1.6364066302776337e-01 2.9590085148811340e-01 <_> - 0 -1 657 2.7066322509199381e-03 + 0 -1 477 -3.1894792336970568e-03 - -1.9653171300888062e-01 1.8972468376159668e-01 + 1.7039565742015839e-01 -2.1295401453971863e-01 <_> - 0 -1 789 1.9835126586258411e-03 + 0 -1 314 -1.4799979981034994e-03 - -1.0700473189353943e-01 3.2027366757392883e-01 + -4.1050529479980469e-01 5.3783610463142395e-02 <_> - 0 -1 381 -2.2188067436218262e-02 + 0 -1 66 6.0710287652909756e-03 - -3.4057390689849854e-01 9.7314909100532532e-02 + -1.5162153542041779e-01 1.8406888842582703e-01 <_> - 0 -1 900 6.6005333792418242e-04 + 0 -1 401 4.3081510812044144e-03 - -1.9594040513038635e-01 1.6130633652210236e-01 + 5.0293717533349991e-02 -4.6324169635772705e-01 <_> - 0 -1 189 9.8964036442339420e-04 + 0 -1 970 1.8933035898953676e-03 - -1.6125436127185822e-01 1.5948192775249481e-01 + 6.5655551850795746e-02 -3.9198148250579834e-01 <_> - 0 -1 557 5.2934061735868454e-02 + 0 -1 782 -1.6021143645048141e-02 - -7.4111364781856537e-02 3.6531463265419006e-01 + 2.2748421132564545e-01 -1.0609938949346542e-01 <_> - 0 -1 423 9.6504454268142581e-04 + 0 -1 928 -8.9298677630722523e-04 - -1.4388854801654816e-01 1.8791662156581879e-01 + 3.1164079904556274e-01 -1.1380065232515335e-01 <_> - 0 -1 326 -6.5498230978846550e-03 + 0 -1 888 -1.4284942299127579e-03 - -5.1886290311813354e-01 4.9368891865015030e-02 + 2.7966943383216858e-01 -9.6580952405929565e-02 <_> - 0 -1 309 -3.1677065417170525e-03 + 0 -1 822 2.5015190243721008e-02 - -4.5819568634033203e-01 4.6636309474706650e-02 + 4.2534209787845612e-02 -6.2623745203018188e-01 <_> - 0 -1 58 -3.8453172892332077e-03 + 0 -1 583 -2.8645459096878767e-03 - 1.8924130499362946e-01 -1.2508736550807953e-01 + -4.1426309943199158e-01 5.1780503243207932e-02 <_> - 0 -1 279 1.0155377909541130e-02 + 0 -1 902 3.2044243998825550e-03 - -7.4480414390563965e-02 3.1350296735763550e-01 + -1.1883606761693954e-01 1.9546063244342804e-01 <_> - 0 -1 275 9.4711792189627886e-04 + 0 -1 319 -1.0433372110128403e-02 - -1.0617389529943466e-01 2.3810641467571259e-01 + 2.6159819960594177e-01 -9.3164652585983276e-02 <_> - 0 -1 892 -2.4116779677569866e-03 + 0 -1 287 -9.7299478948116302e-03 - -3.9038985967636108e-01 6.1166737228631973e-02 + -4.9464005231857300e-01 5.0998747348785400e-02 <_> - 0 -1 260 -3.9347349666059017e-03 + 0 -1 206 -2.1688457578420639e-02 - -5.7243233919143677e-01 3.4851558506488800e-02 + 5.6923902034759521e-01 -4.9958106130361557e-02 <_> - 0 -1 328 6.6558746621012688e-03 + 0 -1 38 -2.9492072761058807e-02 - 2.8953079134225845e-02 -6.2028181552886963e-01 + -6.1336356401443481e-01 4.7003138810396194e-02 <_> - 0 -1 341 -2.2842539474368095e-03 + 0 -1 35 -2.4866596795618534e-03 - -3.3340734243392944e-01 5.2056297659873962e-02 + -3.9986124634742737e-01 5.7781789451837540e-02 <_> - 0 -1 829 7.6677929610013962e-04 + 0 -1 965 4.0488247759640217e-03 - -9.4001799821853638e-02 2.0127503573894501e-01 + 4.6429801732301712e-02 -4.4500553607940674e-01 <_> - 0 -1 8 -3.9554573595523834e-02 + 0 -1 735 -9.3909690622240305e-04 - 3.9717516303062439e-01 -5.0761125981807709e-02 + 2.4617424607276917e-01 -9.0848781168460846e-02 <_> - 0 -1 166 -2.2336144000291824e-02 + 0 -1 989 -5.2673118188977242e-03 - 2.0378184318542480e-01 -1.0499230772256851e-01 + -6.4129960536956787e-01 3.5207435488700867e-02 <_> - 0 -1 682 4.1007921099662781e-03 + 0 -1 806 -6.1755320057272911e-03 - 3.9605572819709778e-02 -5.6042844057083130e-01 + 1.7039734125137329e-01 -1.3195209205150604e-01 <_> - 0 -1 187 -6.3549563288688660e-02 + 0 -1 201 1.5832348726689816e-03 - 5.9350001811981201e-01 -3.4742560237646103e-02 + -9.2635877430438995e-02 2.5755262374877930e-01 <_> - 0 -1 370 3.7244942504912615e-03 + 0 -1 914 2.8633023612201214e-03 - -5.1448952406644821e-02 3.1930196285247803e-01 + 5.0923369824886322e-02 -4.6171438694000244e-01 <_> - 0 -1 483 1.2377202510833740e-02 + 0 -1 12 -2.3722708225250244e-02 - 3.3052973449230194e-02 -6.5478527545928955e-01 + -4.5609694719314575e-01 4.3677136301994324e-02 <_> - 0 -1 499 -1.0786693543195724e-02 + 0 -1 419 5.8846692554652691e-03 - 2.4589619040489197e-01 -7.2101429104804993e-02 + 5.1512561738491058e-02 -4.4899132847785950e-01 <_> - 0 -1 439 -1.4055164530873299e-02 + 0 -1 201 -8.2513026427477598e-04 - 3.5272973775863647e-01 -5.8014977723360062e-02 + 2.4914309382438660e-01 -8.9795768260955811e-02 <_> - 0 -1 391 -1.4940403401851654e-02 + 0 -1 690 -2.9888928402215242e-03 - -4.5820471644401550e-01 4.5480247586965561e-02 + -4.0133482217788696e-01 5.5449619889259338e-02 <_> - 0 -1 850 1.8285561818629503e-03 + 0 -1 237 1.8384978175163269e-02 - 3.2248783856630325e-02 -4.9957463145256042e-01 + 4.9513496458530426e-02 -4.2024865746498108e-01 <_> - 0 -1 26 1.8330020830035210e-02 + 0 -1 947 -2.4238843470811844e-03 - 4.6777416020631790e-02 -3.7174671888351440e-01 + -6.7325645685195923e-01 2.8972415253520012e-02 <_> - 0 -1 579 -1.1065398575738072e-03 + 0 -1 724 8.1563717685639858e-04 - -3.4255436062812805e-01 4.5848693698644638e-02 + -1.4400914311408997e-01 1.5184181928634644e-01 <_> - 0 -1 481 -2.7136057615280151e-03 + 0 -1 315 2.1788734011352062e-03 - 2.4459818005561829e-01 -6.8955913186073303e-02 + -8.2650899887084961e-02 2.5927037000656128e-01 <_> - 0 -1 163 3.5836829338222742e-03 + 0 -1 376 3.7263201083987951e-03 - 3.9574686437845230e-02 -4.1517943143844604e-01 + -6.3213117420673370e-02 3.8062268495559692e-01 <_> - 0 -1 205 1.3739100657403469e-02 + 0 -1 631 3.0819473322480917e-03 - -6.2165945768356323e-02 2.8256937861442566e-01 + 3.9066124707460403e-02 -6.2055569887161255e-01 <_> - 0 -1 763 -1.1374817695468664e-03 + 0 -1 691 2.7417289093136787e-03 - 1.6939654946327209e-01 -1.0761212557554245e-01 + 3.2166294753551483e-02 -5.6402361392974854e-01 <_> - 0 -1 731 -1.1336053721606731e-03 + 0 -1 581 -3.8205389864742756e-03 - 2.4757325649261475e-01 -7.0519238710403442e-02 + 2.5668358802795410e-01 -7.9121366143226624e-02 <_> - 0 -1 551 2.4884669110178947e-03 + 0 -1 61 -1.2516178190708160e-02 - 4.3731488287448883e-02 -4.3731775879859924e-01 + -7.0402121543884277e-01 3.2493114471435547e-02 <_> - 0 -1 693 9.1567426919937134e-02 + 0 -1 60 4.6941628679633141e-03 - -6.4225792884826660e-02 2.6794373989105225e-01 + 4.7352086752653122e-02 -4.0129581093788147e-01 <_> - 0 -1 863 8.1775393337011337e-03 + 0 -1 483 5.0501096993684769e-03 - -6.9729812443256378e-02 2.7086481451988220e-01 + -1.0563907027244568e-01 2.3647888004779816e-01 <_> - 0 -1 539 -3.1169723719358444e-02 + 0 -1 497 1.5111428685486317e-02 - -5.1539027690887451e-01 4.1658539324998856e-02 + -6.7443214356899261e-02 2.7579694986343384e-01 <_> - 0 -1 589 -1.8694017082452774e-02 + 0 -1 423 7.4835181236267090e-02 - 2.1681772172451019e-01 -8.8622607290744781e-02 + -6.2918186187744141e-02 3.6493194103240967e-01 <_> - 0 -1 472 5.7301642373204231e-03 + 0 -1 498 1.3086002320051193e-02 - -7.2939246892929077e-02 2.3475584387779236e-01 + 2.9699811711907387e-02 -7.4420636892318726e-01 <_> - 0 -1 890 1.6503074439242482e-03 + 0 -1 778 -5.4838880896568298e-03 - 6.9048069417476654e-02 -2.8440928459167480e-01 + 2.2497597336769104e-01 -8.8018722832202911e-02 <_> - 0 -1 191 -7.0378202944993973e-03 + 0 -1 261 3.3699360210448503e-03 - -4.7214046120643616e-01 3.5182151943445206e-02 + -6.9213069975376129e-02 2.9263094067573547e-01 <_> - 0 -1 591 -2.3838514462113380e-03 + 0 -1 118 7.7881952747702599e-03 - 1.9753867387771606e-01 -8.9424118399620056e-02 + 5.8034870773553848e-02 -3.9803403615951538e-01 <_> - 0 -1 349 7.9844584688544273e-03 + 0 -1 421 -1.9298251718282700e-02 - -7.4890352785587311e-02 2.3181028664112091e-01 + 2.1273820102214813e-01 -9.6075013279914856e-02 <_> - 0 -1 124 1.3400901807472110e-03 + 0 -1 440 1.3059679418802261e-02 - -1.0847068578004837e-01 1.9428721070289612e-01 + 4.0989801287651062e-02 -4.9787399172782898e-01 <_> - 0 -1 123 -2.9489169828593731e-03 + 0 -1 510 -2.2303011268377304e-02 - -4.0673759579658508e-01 4.7985706478357315e-02 + -6.5915608406066895e-01 2.7258813381195068e-02 <_> - 0 -1 952 -5.9452969580888748e-03 + 0 -1 260 -5.2872681990265846e-03 - -4.5123618841171265e-01 3.6464843899011612e-02 + 2.9461637139320374e-01 -6.9564543664455414e-02 <_> - 0 -1 659 2.3310778196901083e-03 + 0 -1 464 6.0780980857089162e-04 - -8.0826595425605774e-02 2.1532072126865387e-01 + -9.5468334853649139e-02 2.0951601862907410e-01 <_> - 0 -1 54 -1.9684966653585434e-02 + 0 -1 444 4.8917778767645359e-03 - 2.3020596802234650e-01 -8.1534743309020996e-02 + 3.9317954331636429e-02 -5.3803342580795288e-01 <_> - 0 -1 723 -1.6875991132110357e-03 + 0 -1 238 -1.0402110219001770e-01 - 2.3354543745517731e-01 -7.0870727300643921e-02 + 5.4199391603469849e-01 -3.9763871580362320e-02 <_> - 0 -1 697 -1.5521588502451777e-03 + 0 -1 687 3.8908584974706173e-03 - 1.7072069644927979e-01 -1.0233023017644882e-01 + 3.8185238838195801e-02 -5.3280067443847656e-01 <_> - 0 -1 667 -3.8005404174327850e-02 + 0 -1 353 8.0125425010919571e-03 - -6.0487842559814453e-01 2.8272373601794243e-02 + -7.8310973942279816e-02 2.4926608800888062e-01 <_> - 0 -1 624 -2.1617640741169453e-03 + 0 -1 954 -3.4356187097728252e-03 - -5.5644184350967407e-01 2.5939555838704109e-02 + 2.3415692150592804e-01 -9.2279240489006042e-02 <_> - 0 -1 653 -2.6441088411957026e-03 + 0 -1 896 -5.2030328661203384e-03 - -4.4886007905006409e-01 3.1817246228456497e-02 + -5.0255048274993896e-01 4.4738721102476120e-02 <_> - 0 -1 214 -7.3187379166483879e-04 + 0 -1 555 -5.5568795651197433e-03 - 2.2164805233478546e-01 -7.6915167272090912e-02 + 2.8329169750213623e-01 -7.0860259234905243e-02 <_> - 0 -1 532 -3.4191065933555365e-03 + 0 -1 627 -7.6205702498555183e-03 - -4.4704499840736389e-01 3.5689469426870346e-02 + 2.5350978970527649e-01 -7.2612494230270386e-02 <_> - 0 -1 597 1.4393313322216272e-03 + 0 -1 309 2.7379104495048523e-01 - -8.1237293779850006e-02 2.0022353529930115e-01 + -5.6398060172796249e-02 3.6085364222526550e-01 <_> - 0 -1 352 1.0892877355217934e-02 + 0 -1 622 7.3067229241132736e-03 - -5.9532187879085541e-02 2.6124969124794006e-01 + -6.2759615480899811e-02 3.1996127963066101e-01 <_> - 0 -1 250 2.5800592266023159e-03 + 0 -1 415 3.2574313227087259e-03 - 5.3012363612651825e-02 -3.0210506916046143e-01 + 4.1181974112987518e-02 -4.9355933070182800e-01 <_> - 0 -1 873 -3.7106748204678297e-03 + 0 -1 57 -1.2764024734497070e-01 - -3.7514480948448181e-01 4.0868300944566727e-02 + 2.5147503614425659e-01 -7.5440123677253723e-02 <_> - 0 -1 291 -8.9250775054097176e-03 + 0 -1 530 -3.2227888703346252e-02 - 1.8222920596599579e-01 -8.4776028990745544e-02 + 3.9548832178115845e-01 -4.7284111380577087e-02 <_> - 0 -1 211 -4.4729106128215790e-02 + 0 -1 764 2.3350853472948074e-02 - 2.5505220890045166e-01 -6.6192351281642914e-02 + -7.2977773845195770e-02 2.5172060728073120e-01 <_> - 0 -1 64 -1.0527699440717697e-01 + 0 -1 26 2.7610745746642351e-05 - -4.8529133200645447e-01 3.4933239221572876e-02 + -1.3625738024711609e-01 1.3250400125980377e-01 <_> - 0 -1 411 -6.5371848642826080e-02 + 0 -1 808 6.9611091166734695e-03 - 3.7187507748603821e-01 -5.8592520654201508e-02 + 2.9794082045555115e-02 -5.8855760097503662e-01 <_> - 0 -1 99 5.1612589508295059e-02 + 0 -1 210 -9.9057564511895180e-04 - -7.6325275003910065e-02 2.1536968648433685e-01 + 2.5895762443542480e-01 -7.1211874485015869e-02 <_> - 0 -1 511 4.2564887553453445e-03 + 0 -1 218 -3.7965672090649605e-03 - -7.7395483851432800e-02 2.1907977759838104e-01 + -6.4451014995574951e-01 3.5450231283903122e-02 <_> - 0 -1 671 -3.5104658454656601e-03 + 0 -1 346 3.9518065750598907e-03 - -4.1962492465972900e-01 4.1911821812391281e-02 + -6.3615679740905762e-02 3.0333930253982544e-01 <_> - 0 -1 746 -9.5827406039461493e-04 + 0 -1 282 -5.4976264946162701e-03 - 1.7163562774658203e-01 -1.0379400104284286e-01 + -4.3285435438156128e-01 4.7526597976684570e-02 <_> - 0 -1 886 -3.3416904509067535e-02 + 0 -1 721 7.1266246959567070e-03 - -5.5419611930847168e-01 3.4831445664167404e-02 + -6.6810697317123413e-02 2.8491511940956116e-01 <_> - 0 -1 406 7.4058589525520802e-03 + 0 -1 912 -3.0366722494363785e-03 - -6.6642671823501587e-02 2.6589548587799072e-01 + -4.3046197295188904e-01 4.4313102960586548e-02 <_> - 0 -1 304 -7.3020011186599731e-03 + 0 -1 714 -1.7097850795835257e-03 - 1.7654685676097870e-01 -8.7743707001209259e-02 + 2.5873449444770813e-01 -7.3857538402080536e-02 <_> - 0 -1 505 -4.5689288526773453e-03 + 0 -1 702 -4.4310283847153187e-03 - 1.9193352758884430e-01 -8.0177433788776398e-02 + 2.1451152861118317e-01 -8.7626561522483826e-02 <_> - 0 -1 740 -8.1814359873533249e-03 + 0 -1 47 -3.9760642684996128e-03 - 2.3826718330383301e-01 -6.4945526421070099e-02 + -4.6889033913612366e-01 3.8441929966211319e-02 <_> - 0 -1 404 4.5117912814021111e-03 + 0 -1 683 -2.9741778969764709e-02 - 3.0824853107333183e-02 -5.3869700431823730e-01 + -5.5860131978988647e-01 3.0309556052088737e-02 <_> - 0 -1 502 2.8812256641685963e-03 + 0 -1 13 1.3289751112461090e-01 - -9.6859149634838104e-02 1.6199249029159546e-01 + 2.8634676709771156e-02 -5.6014162302017212e-01 <_> - 0 -1 845 2.4804673157632351e-03 + 0 -1 386 -1.1272695846855640e-03 - 2.1523499861359596e-02 -7.0121616125106812e-01 + 1.7104774713516235e-01 -1.0818520933389664e-01 + + <_> + 83 + -1.2789946794509888e+00 + <_> - 0 -1 640 6.8080224096775055e-02 + 0 -1 649 1.3820428401231766e-02 - 2.1451909095048904e-02 -6.2823659181594849e-01 + -1.0330537706613541e-01 4.5001628994941711e-01 <_> - 0 -1 428 3.8525110576301813e-03 + 0 -1 834 -1.0161036625504494e-02 - -8.2842335104942322e-02 1.9410280883312225e-01 + 3.2188063859939575e-01 -1.5805941820144653e-01 <_> - 0 -1 904 -2.5594229809939861e-03 + 0 -1 398 -3.8372592534869909e-03 - 1.9102296233177185e-01 -8.5406452417373657e-02 + 3.2943242788314819e-01 -1.1501405388116837e-01 <_> - 0 -1 929 5.3212735801935196e-03 + 0 -1 769 3.4624878317117691e-02 - -7.8593194484710693e-02 2.2497585415840149e-01 + -9.8698168992996216e-02 5.4050970077514648e-01 <_> - 0 -1 235 3.1688171438872814e-03 + 0 -1 437 5.7967011816799641e-03 - 3.6922473460435867e-02 -4.5733535289764404e-01 + -1.1608023941516876e-01 2.8170758485794067e-01 <_> - 0 -1 848 1.5939949080348015e-02 + 0 -1 754 4.7825248911976814e-03 - 3.7862829864025116e-02 -3.9459064602851868e-01 + -1.3033217191696167e-01 2.4669390916824341e-01 <_> - 0 -1 634 2.3682378232479095e-03 + 0 -1 74 7.1141775697469711e-04 - 3.5111214965581894e-02 -4.3085646629333496e-01 + -2.0435671508312225e-01 1.1761441081762314e-01 <_> - 0 -1 741 1.2975309044122696e-02 + 0 -1 22 -2.9168082401156425e-02 - -7.1412295103073120e-02 2.1616001427173615e-01 + -6.2692928314208984e-01 5.5113222450017929e-02 <_> - 0 -1 960 -9.9381525069475174e-03 + 0 -1 796 2.1553519181907177e-03 - 2.7434283494949341e-01 -5.9007227420806885e-02 + 5.3858544677495956e-02 -4.2096143960952759e-01 <_> - 0 -1 14 -4.4495373964309692e-02 + 0 -1 894 -2.1254396997392178e-03 - -5.7859867811203003e-01 2.8963629156351089e-02 + 4.2603659629821777e-01 -5.0405498594045639e-02 <_> - 0 -1 457 1.0330894030630589e-02 + 0 -1 894 8.4234733367338777e-04 - -6.5200082957744598e-02 2.6670095324516296e-01 + -9.3583315610885620e-02 2.6316204667091370e-01 <_> - 0 -1 745 -4.2830477468669415e-03 + 0 -1 948 -1.6576268244534731e-03 - -5.2546054124832153e-01 3.3751774579286575e-02 + -3.5802370309829712e-01 6.8603202700614929e-02 <_> - 0 -1 899 1.5691295266151428e-02 + 0 -1 554 6.5620511770248413e-02 - 2.9164802283048630e-02 -4.8206093907356262e-01 + -6.4758449792861938e-02 3.8339248299598694e-01 <_> - 0 -1 903 -1.2077906867489219e-03 + 0 -1 361 -1.8485928885638714e-03 - 2.4997046589851379e-01 -6.1069376766681671e-02 + 1.7337062954902649e-01 -1.3676019012928009e-01 <_> - 0 -1 220 6.6226916387677193e-03 + 0 -1 305 -1.8170465528964996e-01 - 4.8671871423721313e-02 -3.4221932291984558e-01 + 4.0350264310836792e-01 -5.3196940571069717e-02 <_> - 0 -1 236 -5.1539484411478043e-03 + 0 -1 848 -3.4317909739911556e-03 - -3.5398313403129578e-01 4.2696069926023483e-02 + -5.2157330513000488e-01 4.6489212661981583e-02 <_> - 0 -1 74 -2.4832391645759344e-03 + 0 -1 800 -2.7482535224407911e-03 - 2.0646870136260986e-01 -7.5708754360675812e-02 + -5.1078474521636963e-01 4.3557438999414444e-02 <_> - 0 -1 891 3.0503068119287491e-03 + 0 -1 731 -4.7894287854433060e-03 - 2.1991817280650139e-02 -6.9251579046249390e-01 + 3.4981805086135864e-01 -6.5036587417125702e-02 <_> - 0 -1 514 9.2179588973522186e-03 + 0 -1 706 -3.3211666159331799e-03 - 1.7923980951309204e-02 -7.2638368606567383e-01 + 2.1143883466720581e-01 -1.1754662543535233e-01 <_> - 0 -1 776 3.7863249890506268e-03 + 0 -1 677 3.5642951726913452e-02 - -6.6987045109272003e-02 2.2602997720241547e-01 + 3.7131600081920624e-02 -6.2165355682373047e-01 + <_> + + 0 -1 481 -3.1561930663883686e-03 + + -4.2197883129119873e-01 4.7645546495914459e-02 + <_> + + 0 -1 872 5.2224877290427685e-03 + + -1.0117106884717941e-01 2.1957167983055115e-01 + <_> + + 0 -1 140 2.5758458301424980e-02 + + -9.6981137990951538e-02 3.0423089861869812e-01 + <_> + + 0 -1 567 2.8883803170174360e-03 + + 4.4947806745767593e-02 -5.5540132522583008e-01 + <_> + + 0 -1 484 2.6014349423348904e-03 + + 4.5947834849357605e-02 -4.1711980104446411e-01 + <_> + + 0 -1 257 -7.8792509157210588e-04 + + 1.5732656419277191e-01 -1.2769798934459686e-01 + <_> + + 0 -1 252 4.2199464514851570e-03 + + -9.4008974730968475e-02 2.6868444681167603e-01 + <_> + + 0 -1 571 -2.4246796965599060e-03 + + -4.9610009789466858e-01 4.6141009777784348e-02 + <_> + + 0 -1 465 -1.8996626604348421e-03 + + 2.6260954141616821e-01 -8.5721127688884735e-02 + <_> + + 0 -1 945 1.8048105994239450e-03 + + 7.1231566369533539e-02 -3.2751160860061646e-01 + <_> + + 0 -1 249 -5.6593962945044041e-03 + + -5.0264769792556763e-01 4.0275387465953827e-02 + <_> + + 0 -1 940 -3.4701074473559856e-03 + + -4.9033272266387939e-01 3.6995064467191696e-02 + <_> + + 0 -1 766 1.1992279905825853e-03 + + -9.3982182443141937e-02 2.2527951002120972e-01 + <_> + + 0 -1 528 -3.3614276908338070e-03 + + 1.5591301023960114e-01 -1.3875743746757507e-01 + <_> + + 0 -1 758 9.2923380434513092e-03 + + 2.8368480503559113e-02 -6.3946157693862915e-01 + <_> + + 0 -1 98 -1.6806223988533020e-01 + + -6.3519150018692017e-01 2.4432161822915077e-02 + <_> + + 0 -1 614 -1.5483988681808114e-03 + + -4.9389392137527466e-01 3.4452050924301147e-02 + <_> + + 0 -1 961 7.9401559196412563e-04 + + -1.6395612061023712e-01 1.1427336186170578e-01 + <_> + + 0 -1 245 -5.3670424968004227e-03 + + -5.4615026712417603e-01 3.2274313271045685e-02 + <_> + + 0 -1 923 -5.1019818056374788e-04 + + 1.4040225744247437e-01 -1.2673649191856384e-01 + <_> + + 0 -1 846 -9.6546392887830734e-04 + + 2.3117446899414062e-01 -7.7826015651226044e-02 + <_> + + 0 -1 994 -9.7423873376101255e-04 + + -4.0673121809959412e-01 4.6749390661716461e-02 + <_> + + 0 -1 970 -4.7841384075582027e-03 + + -5.0288796424865723e-01 3.4186109900474548e-02 + <_> + + 0 -1 89 6.8537802435457706e-03 + + 5.0501946359872818e-02 -3.5414797067642212e-01 + <_> + + 0 -1 651 4.1695050895214081e-03 + + -6.8471699953079224e-02 2.8334242105484009e-01 + <_> + + 0 -1 391 2.6521178369875997e-05 + + -1.7646598815917969e-01 1.0057727992534637e-01 + <_> + + 0 -1 674 -1.8193974392488599e-03 + + -5.2059328556060791e-01 3.4266594797372818e-02 + <_> + + 0 -1 284 1.1680822353810072e-03 + + -7.5169444084167480e-02 2.3740953207015991e-01 + <_> + + 0 -1 284 -5.8111123507842422e-04 + + 2.4673853814601898e-01 -8.9036554098129272e-02 + <_> + + 0 -1 789 5.5753946304321289e-02 + + -4.8898559063673019e-02 3.7110447883605957e-01 + <_> + + 0 -1 388 -6.0947462916374207e-03 + + -4.8019152879714966e-01 3.6990296095609665e-02 + <_> + + 0 -1 988 3.3249799162149429e-03 + + 3.2017692923545837e-02 -4.8544195294380188e-01 + <_> + + 0 -1 586 -1.1994136497378349e-02 + + 2.7767661213874817e-01 -6.2677264213562012e-02 + <_> + + 0 -1 940 1.9462420605123043e-03 + + 5.7167824357748032e-02 -3.2460683584213257e-01 + <_> + + 0 -1 482 -3.5742400214076042e-03 + + 2.1856486797332764e-01 -7.7333562076091766e-02 + <_> + + 0 -1 543 3.4013153053820133e-03 + + -9.4114005565643311e-02 2.3269242048263550e-01 + <_> + + 0 -1 859 6.4494553953409195e-03 + + 3.4765381366014481e-02 -5.1627504825592041e-01 + <_> + + 0 -1 163 -1.2767435982823372e-02 + + 2.5566741824150085e-01 -6.7411571741104126e-02 + <_> + + 0 -1 230 2.2043818607926369e-03 + + -1.3278621435165405e-01 1.7942063510417938e-01 + <_> + + 0 -1 229 -4.0757502429187298e-03 + + -3.8042715191841125e-01 4.4863421469926834e-02 + <_> + + 0 -1 730 2.2066584788262844e-03 + + -7.0331946015357971e-02 2.5572371482849121e-01 + <_> + + 0 -1 700 2.2714279592037201e-02 + + 4.1653785854578018e-02 -4.4101753830909729e-01 + <_> + + 0 -1 749 -1.1373223736882210e-02 + + 3.2443967461585999e-01 -5.8059785515069962e-02 + <_> + + 0 -1 835 1.8165379296988249e-03 + + -7.2351627051830292e-02 2.2953742742538452e-01 + <_> + + 0 -1 235 -2.8745923191308975e-03 + + -3.9090758562088013e-01 4.6148840337991714e-02 + <_> + + 0 -1 673 -5.7676057331264019e-03 + + 2.4503223598003387e-01 -7.2128646075725555e-02 + <_> + + 0 -1 177 1.2852130457758904e-02 + + -1.1143829673528671e-01 1.6758553683757782e-01 + <_> + + 0 -1 141 -4.2651765048503876e-02 + + 2.3846423625946045e-01 -7.9255387187004089e-02 + <_> + + 0 -1 24 -6.8766735494136810e-03 + + -3.9145267009735107e-01 5.2240811288356781e-02 + <_> + + 0 -1 15 -1.5351611375808716e-01 + + -5.4598790407180786e-01 2.9950620606541634e-02 + <_> + + 0 -1 280 -1.7586871981620789e-02 + + 2.4160921573638916e-01 -7.7404774725437164e-02 + <_> + + 0 -1 557 2.8469474054872990e-03 + + -7.1562752127647400e-02 2.3895153403282166e-01 + <_> + + 0 -1 493 -2.6379337534308434e-02 + + 2.7370086312294006e-01 -6.5483018755912781e-02 + <_> + + 0 -1 759 -6.6346197854727507e-04 + + 1.7174075543880463e-01 -1.0841262340545654e-01 + <_> + + 0 -1 736 1.4637422282248735e-03 + + -1.1365657299757004e-01 1.6123561561107635e-01 + <_> + + 0 -1 569 -1.3798776781186461e-03 + + 2.3192690312862396e-01 -7.5626462697982788e-02 + <_> + + 0 -1 516 -6.8256547674536705e-03 + + 2.4984428286552429e-01 -7.2457753121852875e-02 + <_> + + 0 -1 312 -9.0181883424520493e-03 + + 2.0358866453170776e-01 -9.5499873161315918e-02 + <_> + + 0 -1 218 3.1383798923343420e-03 + + 4.0804021060466766e-02 -4.9618390202522278e-01 + <_> + + 0 -1 171 -1.8526764586567879e-02 + + 2.2743205726146698e-01 -8.6628310382366180e-02 + <_> + + 0 -1 594 -2.2562327794730663e-03 + + -3.2850387692451477e-01 5.9250634163618088e-02 + <_> + + 0 -1 432 -4.1183121502399445e-03 + + -5.0281947851181030e-01 3.2455049455165863e-02 + <_> + + 0 -1 96 4.8136096447706223e-03 + + 3.1708184629678726e-02 -4.9248033761978149e-01 + + <_> + 90 + -1.2794928550720215e+00 + + <_> + + 0 -1 568 -4.7569684684276581e-03 + + 4.4339472055435181e-01 -1.0486443340778351e-01 + <_> + + 0 -1 795 -2.5423073675483465e-03 + + 3.9922216534614563e-01 -1.0431514680385590e-01 + <_> + + 0 -1 649 1.1162508279085159e-02 + + -1.5686489641666412e-01 2.3129878938198090e-01 + <_> + + 0 -1 847 1.7287035007029772e-03 + + -1.5123696625232697e-01 2.9676723480224609e-01 + <_> + + 0 -1 265 2.5025676935911179e-02 + + -5.1661748439073563e-02 4.8509848117828369e-01 + <_> + + 0 -1 78 1.2561861425638199e-02 + + -1.1817755550146103e-01 2.6937758922576904e-01 + <_> + + 0 -1 812 4.6598571352660656e-03 + + -1.3565555214881897e-01 2.1206009387969971e-01 + <_> + + 0 -1 434 7.4310216587036848e-04 + + -1.7020516097545624e-01 1.5990819036960602e-01 + <_> + + 0 -1 231 1.0259399190545082e-02 + + -1.4796857535839081e-01 1.8798792362213135e-01 + <_> + + 0 -1 278 -1.2777388095855713e-02 + + -5.4041445255279541e-01 4.8501875251531601e-02 + <_> + + 0 -1 489 -1.1427352204918861e-02 + + -5.1071381568908691e-01 4.8088576644659042e-02 + <_> + + 0 -1 819 2.8340169592411257e-05 + + -2.0961570739746094e-01 1.0582420229911804e-01 + <_> + + 0 -1 325 -6.4714960753917694e-03 + + -5.0862830877304077e-01 4.8812258988618851e-02 + <_> + + 0 -1 367 1.3540303334593773e-02 + + 2.7134107425808907e-02 -7.1317195892333984e-01 + <_> + + 0 -1 210 1.8916794797405601e-03 + + -6.2187314033508301e-02 3.6233416199684143e-01 + <_> + + 0 -1 51 1.0457850992679596e-02 + + 4.0487006306648254e-02 -5.3173840045928955e-01 + <_> + + 0 -1 893 -9.0822251513600349e-04 + + 2.0090451836585999e-01 -1.0807146877050400e-01 + <_> + + 0 -1 535 -1.9299473613500595e-02 + + -6.4914399385452271e-01 4.0790289640426636e-02 + <_> + + 0 -1 663 -8.2283990923315287e-04 + + 1.5708251297473907e-01 -1.3143004477024078e-01 + <_> + + 0 -1 523 3.7520762998610735e-03 + + 3.8761712610721588e-02 -4.9775493144989014e-01 + <_> + + 0 -1 762 8.2424264401197433e-03 + + 3.6369498819112778e-02 -5.1153117418289185e-01 + <_> + + 0 -1 805 -1.1945937294512987e-03 + + 1.3862735033035278e-01 -1.3917639851570129e-01 + <_> + + 0 -1 985 -1.0589268989861012e-02 + + 3.2981950044631958e-01 -7.6042778789997101e-02 + <_> + + 0 -1 128 2.6780981570482254e-02 + + 4.6954374760389328e-02 -4.5390221476554871e-01 + <_> + + 0 -1 705 5.2458671852946281e-03 + + -4.7804936766624451e-02 4.0361502766609192e-01 + <_> + + 0 -1 729 1.0518019553273916e-03 + + -1.0052871704101562e-01 1.9928459823131561e-01 + <_> + + 0 -1 407 3.9210864342749119e-03 + + 3.6381114274263382e-02 -5.4954099655151367e-01 + <_> + + 0 -1 873 -1.5182888135313988e-02 + + 2.8286656737327576e-01 -7.6106920838356018e-02 + <_> + + 0 -1 279 2.7552489191293716e-03 + + -1.2027227133512497e-01 2.0814672112464905e-01 + <_> + + 0 -1 869 1.3051946647465229e-02 + + 3.6561664193868637e-02 -6.8296074867248535e-01 + <_> + + 0 -1 849 4.4104140251874924e-03 + + 2.9448021203279495e-02 -5.9994471073150635e-01 + <_> + + 0 -1 799 2.3885946720838547e-03 + + 3.9816807955503464e-02 -4.6116915345191956e-01 + <_> + + 0 -1 551 2.3683100007474422e-03 + + 4.9801617860794067e-02 -3.9546611905097961e-01 + <_> + + 0 -1 707 -4.1178334504365921e-03 + + 1.6903834044933319e-01 -1.1102814227342606e-01 + <_> + + 0 -1 466 -2.7111368253827095e-03 + + 2.0166625082492828e-01 -9.3054622411727905e-02 + <_> + + 0 -1 360 -2.4442467838525772e-03 + + 1.3419428467750549e-01 -1.4021472632884979e-01 + <_> + + 0 -1 104 -6.9398069754242897e-03 + + -4.7041961550712585e-01 3.8327444344758987e-02 + <_> + + 0 -1 14 -7.5376339256763458e-02 + + 3.5196593403816223e-01 -5.8293107897043228e-02 + <_> + + 0 -1 270 -7.3061959119513631e-04 + + 2.0563322305679321e-01 -9.7862586379051208e-02 + <_> + + 0 -1 339 -4.4864090159535408e-03 + + -4.3219071626663208e-01 4.6815373003482819e-02 + <_> + + 0 -1 679 -3.3369990997016430e-03 + + -5.7968968152999878e-01 3.2250367105007172e-02 + <_> + + 0 -1 636 -5.7756435126066208e-03 + + -6.3823670148849487e-01 2.6716385036706924e-02 + <_> + + 0 -1 352 3.8174313958734274e-03 + + -7.8204549849033356e-02 2.4104152619838715e-01 + <_> + + 0 -1 414 3.9163082838058472e-03 + + 4.0961768478155136e-02 -4.2656800150871277e-01 + <_> + + 0 -1 670 -3.7615487817674875e-03 + + 2.0846015214920044e-01 -8.6097449064254761e-02 + <_> + + 0 -1 371 -9.5803234726190567e-03 + + -7.0837384462356567e-01 2.8397833928465843e-02 + <_> + + 0 -1 93 1.4632595703005791e-02 + + 1.8669826909899712e-02 -7.4236363172531128e-01 + <_> + + 0 -1 234 5.3799869492650032e-03 + + 3.0915707349777222e-02 -4.7074958682060242e-01 + <_> + + 0 -1 701 -2.4318110663443804e-03 + + 3.0304560065269470e-01 -5.6169599294662476e-02 + <_> + + 0 -1 641 3.8594864308834076e-02 + + 2.5472542271018028e-02 -6.8472218513488770e-01 + <_> + + 0 -1 125 1.6673290729522705e-01 + + -5.9959251433610916e-02 2.9591250419616699e-01 + <_> + + 0 -1 854 -5.0129964947700500e-03 + + 1.9718486070632935e-01 -9.4902090728282928e-02 + <_> + + 0 -1 960 -9.3115903437137604e-03 + + 2.8306549787521362e-01 -6.8168632686138153e-02 + <_> + + 0 -1 804 -2.7176579460501671e-03 + + 2.4883794784545898e-01 -7.3830418288707733e-02 + <_> + + 0 -1 787 6.9358374457806349e-04 + + -1.2474948167800903e-01 1.6316886246204376e-01 + <_> + + 0 -1 783 1.3523821253329515e-03 + + -7.3475763201713562e-02 3.0120497941970825e-01 + <_> + + 0 -1 532 -2.6339504867792130e-02 + + 4.7823980450630188e-01 -3.9222836494445801e-02 + <_> + + 0 -1 866 3.3510509878396988e-02 + + -3.8013227283954620e-02 4.1955846548080444e-01 + <_> + + 0 -1 694 -2.8097369067836553e-05 + + 1.2249568104743958e-01 -1.4184975624084473e-01 + <_> + + 0 -1 988 -4.0141213685274124e-03 + + -4.5551317930221558e-01 3.6903131753206253e-02 + <_> + + 0 -1 934 5.7984986342489719e-03 + + 3.9383981376886368e-02 -4.0305584669113159e-01 + <_> + + 0 -1 753 7.5392555445432663e-03 + + -9.3996182084083557e-02 1.8520636856555939e-01 + <_> + + 0 -1 943 4.5007485896348953e-03 + + 4.2565450072288513e-02 -4.0628531575202942e-01 + <_> + + 0 -1 500 5.0333794206380844e-03 + + -6.7051678895950317e-02 2.5224363803863525e-01 + <_> + + 0 -1 511 8.7359821191057563e-04 + + -9.5469102263450623e-02 1.7292767763137817e-01 + <_> + + 0 -1 771 3.0778967775404453e-03 + + -6.1908006668090820e-02 2.5266119837760925e-01 + <_> + + 0 -1 835 -2.2874618880450726e-03 + + 1.9187310338020325e-01 -8.5145145654678345e-02 + <_> + + 0 -1 634 4.0947222150862217e-03 + + 3.0908439308404922e-02 -5.5290663242340088e-01 + <_> + + 0 -1 488 2.1358881145715714e-02 + + 4.0033571422100067e-02 -3.8174301385879517e-01 + <_> + + 0 -1 159 -4.5840246602892876e-03 + + -5.2027910947799683e-01 3.0034648254513741e-02 + <_> + + 0 -1 232 9.8655056208372116e-03 + + 2.1588459610939026e-02 -6.3089925050735474e-01 + <_> + + 0 -1 223 2.5678081437945366e-03 + + -1.1046713590621948e-01 1.4713281393051147e-01 + <_> + + 0 -1 688 -2.6078277733176947e-03 + + 2.7103677392005920e-01 -5.9257075190544128e-02 + <_> + + 0 -1 355 2.6908484287559986e-03 + + 2.7514556422829628e-02 -6.3733005523681641e-01 + <_> + + 0 -1 715 -1.3983637327328324e-03 + + 1.5699537098407745e-01 -1.0462216287851334e-01 + <_> + + 0 -1 433 1.0498151183128357e-01 + + 3.0471364036202431e-02 -4.9990084767341614e-01 + <_> + + 0 -1 491 -1.4592260122299194e-01 + + 3.2007977366447449e-01 -5.2097231149673462e-02 + <_> + + 0 -1 825 7.8754723072052002e-03 + + -6.7778728902339935e-02 2.8044930100440979e-01 + <_> + + 0 -1 262 -5.3792521357536316e-03 + + 2.1354769170284271e-01 -8.2902953028678894e-02 + <_> + + 0 -1 420 -1.0021779686212540e-02 + + 2.5685080885887146e-01 -7.3165819048881531e-02 + <_> + + 0 -1 1 -4.2762188240885735e-03 + + 1.7162682116031647e-01 -9.7696490585803986e-02 + <_> + + 0 -1 67 1.0965526103973389e-02 + + -7.5053967535495758e-02 2.3615135252475739e-01 + <_> + + 0 -1 328 -4.4276113621890545e-03 + + 2.5747051835060120e-01 -6.3898853957653046e-02 + <_> + + 0 -1 276 -8.6840223520994186e-03 + + -4.7478455305099487e-01 3.6790292710065842e-02 + <_> + + 0 -1 938 2.8339526616036892e-03 + + 4.0944386273622513e-02 -3.6514538526535034e-01 + <_> + + 0 -1 790 7.6391562819480896e-02 + + -4.9489263445138931e-02 3.4142583608627319e-01 + <_> + + 0 -1 148 1.9103729864582419e-03 + + -5.6329321116209030e-02 2.9177185893058777e-01 + <_> + + 0 -1 304 5.2499733865261078e-02 + + 2.8848636895418167e-02 -5.9306102991104126e-01 + <_> + + 0 -1 956 -5.0793914124369621e-03 + + -5.0588577985763550e-01 2.8303196653723717e-02 + <_> + + 0 -1 967 -7.1491668932139874e-03 + + -6.2660187482833862e-01 2.3113224655389786e-02 + + <_> + 88 + -1.2153301239013672e+00 + + <_> + + 0 -1 803 3.5730558447539806e-03 + + -4.2218949645757675e-02 5.5067819356918335e-01 + <_> + + 0 -1 520 1.0531613603234291e-02 + + -1.0848262906074524e-01 4.2079353332519531e-01 + <_> + + 0 -1 570 -2.8240748215466738e-03 + + 1.5155430138111115e-01 -2.2742147743701935e-01 + <_> + + 0 -1 384 -1.6008135862648487e-03 + + 2.9879093170166016e-01 -1.0573560744524002e-01 + <_> + + 0 -1 90 -1.2082614004611969e-02 + + 2.5803449749946594e-01 -1.1197961121797562e-01 + <_> + + 0 -1 746 9.8490377422422171e-04 + + -1.8312133848667145e-01 1.3942104578018188e-01 + <_> + + 0 -1 347 1.3184763491153717e-02 + + -1.0306112468242645e-01 2.5403776764869690e-01 + <_> + + 0 -1 143 2.5388993322849274e-02 + + 6.4101323485374451e-02 -4.2444714903831482e-01 + <_> + + 0 -1 196 7.8083951957523823e-03 + + -7.8133262693881989e-02 3.2170715928077698e-01 + <_> + + 0 -1 921 1.2125947978347540e-03 + + -1.4831624925136566e-01 1.6055701673030853e-01 + <_> + + 0 -1 920 -5.7722916826605797e-03 + + -6.2254351377487183e-01 4.7926213592290878e-02 + <_> + + 0 -1 987 -6.7740413360297680e-03 + + -6.4991837739944458e-01 1.9058052450418472e-02 + <_> + + 0 -1 291 -2.8847754001617432e-03 + + -5.1574712991714478e-01 4.2939033359289169e-02 + <_> + + 0 -1 922 -5.1092512905597687e-02 + + -7.1794927120208740e-01 3.0500946566462517e-02 + <_> + + 0 -1 303 -3.0863287393003702e-03 + + -5.1027435064315796e-01 3.7360988557338715e-02 + <_> + + 0 -1 593 -3.1833123648539186e-04 + + 1.1626140773296356e-01 -1.7245446145534515e-01 + <_> + + 0 -1 210 1.2636608444154263e-03 + + -7.4942886829376221e-02 2.7081242203712463e-01 + <_> + + 0 -1 693 -2.7436314150691032e-02 + + -5.7718968391418457e-01 3.3168055117130280e-02 + <_> + + 0 -1 342 -1.8837231909856200e-03 + + -3.0960574746131897e-01 6.1044581234455109e-02 + <_> + + 0 -1 797 3.2289433293044567e-03 + + -6.8203814327716827e-02 2.9658797383308411e-01 + <_> + + 0 -1 503 -3.6236688029021025e-03 + + -4.9605649709701538e-01 4.2492914944887161e-02 + <_> + + 0 -1 135 -1.3776571722701192e-03 + + 1.3447758555412292e-01 -1.3678476214408875e-01 + <_> + + 0 -1 579 2.9051192104816437e-03 + + -1.2944447994232178e-01 1.4306847751140594e-01 + <_> + + 0 -1 722 4.4553354382514954e-03 + + 3.8421813398599625e-02 -4.5035859942436218e-01 + <_> + + 0 -1 622 1.0964765213429928e-02 + + -4.8769049346446991e-02 3.9813303947448730e-01 + <_> + + 0 -1 682 2.8863823972642422e-03 + + 5.1313977688550949e-02 -3.6272794008255005e-01 + <_> + + 0 -1 283 8.8652484118938446e-03 + + -9.4886533915996552e-02 2.1068450808525085e-01 + <_> + + 0 -1 333 -1.9646657630801201e-02 + + 2.2927023470401764e-01 -1.0384474694728851e-01 + <_> + + 0 -1 684 -2.3328745737671852e-03 + + -3.0931735038757324e-01 6.4516365528106689e-02 + <_> + + 0 -1 8 -4.0204055607318878e-02 + + 2.7381995320320129e-01 -7.6448827981948853e-02 + <_> + + 0 -1 100 1.9051276147365570e-02 + + 4.9466736614704132e-02 -3.6089882254600525e-01 + <_> + + 0 -1 936 1.1553505435585976e-02 + + -7.4454858899116516e-02 2.5223839282989502e-01 + <_> + + 0 -1 76 6.0810474678874016e-03 + + 4.9583721905946732e-02 -3.6660569906234741e-01 + <_> + + 0 -1 212 5.4147411137819290e-03 + + 3.2274514436721802e-02 -4.9895319342613220e-01 + <_> + + 0 -1 544 4.6544210053980350e-03 + + 2.5989409536123276e-02 -6.1053085327148438e-01 + <_> + + 0 -1 166 2.4446439929306507e-03 + + -1.2073440849781036e-01 1.4529803395271301e-01 + <_> + + 0 -1 698 4.6318914974108338e-04 + + -1.0553400218486786e-01 1.7337696254253387e-01 + <_> + + 0 -1 642 -3.7485856562852859e-02 + + -4.0581890940666199e-01 4.1759915649890900e-02 + <_> + + 0 -1 529 -2.0438145846128464e-02 + + 2.9171264171600342e-01 -6.6287793219089508e-02 + <_> + + 0 -1 524 -3.8345486391335726e-03 + + 1.5750087797641754e-01 -1.2569475173950195e-01 + <_> + + 0 -1 884 8.8059913832694292e-04 + + -1.0610871762037277e-01 1.7642241716384888e-01 + <_> + + 0 -1 33 2.0514219067990780e-03 + + 3.4303460270166397e-02 -5.5235451459884644e-01 + <_> + + 0 -1 851 -3.5282317548990250e-03 + + -5.3414058685302734e-01 3.0512372031807899e-02 + <_> + + 0 -1 506 6.1051873490214348e-03 + + -8.4812760353088379e-02 1.9969700276851654e-01 + <_> + + 0 -1 137 -6.4141638576984406e-03 + + -4.0772309899330139e-01 4.3864764273166656e-02 + <_> + + 0 -1 823 1.7272554337978363e-02 + + 2.1965105086565018e-02 -6.9809681177139282e-01 + <_> + + 0 -1 512 -1.9691141787916422e-03 + + 1.8511210381984711e-01 -9.0554594993591309e-02 + <_> + + 0 -1 59 -5.5513512343168259e-03 + + -4.2040807008743286e-01 4.0062893182039261e-02 + <_> + + 0 -1 626 -1.1905157566070557e-01 + + -6.4312189817428589e-01 2.3472266271710396e-02 + <_> + + 0 -1 290 4.0823101997375488e-02 + + -7.3068141937255859e-02 2.4851579964160919e-01 + <_> + + 0 -1 119 -8.1011475995182991e-03 + + 2.2747313976287842e-01 -7.5412914156913757e-02 + <_> + + 0 -1 87 4.7750310041010380e-03 + + -7.8901365399360657e-02 2.3182301223278046e-01 + <_> + + 0 -1 404 -2.7586806565523148e-02 + + -6.4926701784133911e-01 2.5375340133905411e-02 + <_> + + 0 -1 907 4.3069543316960335e-03 + + 2.4360222741961479e-02 -5.7372909784317017e-01 + <_> + + 0 -1 385 -6.1931653181090951e-04 + + 2.2557340562343597e-01 -7.5787223875522614e-02 + <_> + + 0 -1 50 -1.1459679901599884e-01 + + 3.0668416619300842e-01 -5.2840072661638260e-02 + <_> + + 0 -1 239 3.1560026109218597e-02 + + -9.5666781067848206e-02 1.7659574747085571e-01 + <_> + + 0 -1 871 1.5142546035349369e-03 + + -9.2694908380508423e-02 2.0833927392959595e-01 + <_> + + 0 -1 731 4.7312509268522263e-03 + + -4.9851816147565842e-02 3.4422698616981506e-01 + <_> + + 0 -1 253 -5.9051956050097942e-03 + + -4.6798244118690491e-01 3.6009732633829117e-02 + <_> + + 0 -1 703 3.3569703809916973e-03 + + -5.1445800811052322e-02 3.3950069546699524e-01 + <_> + + 0 -1 966 -1.1821147799491882e-01 + + 4.6877983212471008e-01 -3.2708466053009033e-02 + <_> + + 0 -1 363 -8.8651233818382025e-04 + + 1.5177871286869049e-01 -1.0880727320909500e-01 + <_> + + 0 -1 680 -2.5330238044261932e-02 + + 1.7184022068977356e-01 -9.8979160189628601e-02 + <_> + + 0 -1 770 5.5901473388075829e-03 + + -7.1004293859004974e-02 2.7359166741371155e-01 + <_> + + 0 -1 189 1.2344302609562874e-02 + + 3.2738436013460159e-02 -5.2876019477844238e-01 + <_> + + 0 -1 348 -7.4871592223644257e-03 + + -5.1955360174179077e-01 2.7597136795520782e-02 + <_> + + 0 -1 646 -2.6753707788884640e-03 + + -4.7180628776550293e-01 3.1411368399858475e-02 + <_> + + 0 -1 168 -3.2419776543974876e-03 + + 1.5980260074138641e-01 -9.5776490867137909e-02 + <_> + + 0 -1 169 8.8083129376173019e-03 + + -8.2104682922363281e-02 2.0850872993469238e-01 + <_> + + 0 -1 58 2.7282098308205605e-03 + + 6.1908718198537827e-02 -2.6338595151901245e-01 + <_> + + 0 -1 671 5.0587565638124943e-03 + + -8.2083821296691895e-02 1.9557759165763855e-01 + <_> + + 0 -1 708 -2.1199107170104980e-02 + + -5.0425887107849121e-01 3.0914928764104843e-02 + <_> + + 0 -1 723 3.4958114847540855e-03 + + -8.2294017076492310e-02 1.9164223968982697e-01 + <_> + + 0 -1 842 1.5914414543658495e-03 + + -6.9352962076663971e-02 2.1474194526672363e-01 + <_> + + 0 -1 193 -5.0045788288116455e-02 + + 2.4582423269748688e-01 -6.2959901988506317e-02 + <_> + + 0 -1 19 -4.1983526200056076e-02 + + -6.3210010528564453e-01 2.5985429063439369e-02 + <_> + + 0 -1 402 -6.9432961754500866e-04 + + 2.2444137930870056e-01 -7.0591680705547333e-02 + <_> + + 0 -1 540 6.0177911072969437e-03 + + 3.7622205913066864e-02 -4.1375440359115601e-01 + <_> + + 0 -1 492 4.7936867922544479e-03 + + -9.0203136205673218e-02 1.7498855292797089e-01 + <_> + + 0 -1 390 -4.7484524548053741e-03 + + -3.9998278021812439e-01 3.8966752588748932e-02 + <_> + + 0 -1 620 -7.7324017882347107e-02 + + -4.8634868860244751e-01 2.9687402769923210e-02 + <_> + + 0 -1 417 1.1184449307620525e-02 + + -4.9598570913076401e-02 3.2780852913856506e-01 + <_> + + 0 -1 132 -1.0921864770352840e-02 + + 1.7756749689579010e-01 -8.5219532251358032e-02 + <_> + + 0 -1 357 4.5135535299777985e-02 + + 2.8995228931307793e-02 -5.3758519887924194e-01 + <_> + + 0 -1 341 -1.1866749264299870e-03 + + 1.8304300308227539e-01 -8.5605643689632416e-02 + <_> + + 0 -1 609 2.0626676268875599e-03 + + 2.5438303127884865e-02 -5.9883767366409302e-01 + <_> + + 0 -1 251 2.7453177608549595e-05 + + -1.3831512629985809e-01 1.0590004175901413e-01 + + <_> + 98 + -1.2823635339736938e+00 + + <_> + + 0 -1 840 -8.7535101920366287e-03 + + 3.7845414876937866e-01 -1.2724789977073669e-01 + <_> + + 0 -1 376 -5.7867290452122688e-03 + + 4.6451708674430847e-01 -1.0028645396232605e-01 + <_> + + 0 -1 467 -1.5636831521987915e-02 + + 2.7137696743011475e-01 -1.3237486779689789e-01 + <_> + + 0 -1 743 7.9419813118875027e-04 + + -2.2457434237003326e-01 1.8765783309936523e-01 + <_> + + 0 -1 511 9.8101666662842035e-04 + + -1.1674020439386368e-01 2.3788549005985260e-01 + <_> + + 0 -1 148 -1.1779682245105505e-03 + + 2.5913080573081970e-01 -8.3949849009513855e-02 + <_> + + 0 -1 330 9.6748135983943939e-03 + + -8.3296068012714386e-02 3.4700453281402588e-01 + <_> + + 0 -1 307 2.9431451112031937e-03 + + 4.6826824545860291e-02 -5.1865130662918091e-01 + <_> + + 0 -1 918 -1.0496248723939061e-03 + + -2.9976195096969604e-01 6.9594070315361023e-02 + <_> + + 0 -1 697 -1.6385620459914207e-02 + + 2.1480703353881836e-01 -9.7807772457599640e-02 + <_> + + 0 -1 910 4.9830954521894455e-03 + + 2.2837642580270767e-02 -7.7743059396743774e-01 + <_> + + 0 -1 796 -3.1421617604792118e-03 + + -5.6898134946823120e-01 3.6988433450460434e-02 + <_> + + 0 -1 901 1.6069117933511734e-02 + + -1.0548119246959686e-01 1.9650301337242126e-01 + <_> + + 0 -1 751 1.5043821185827255e-02 + + -1.0749972611665726e-01 2.0178599655628204e-01 + <_> + + 0 -1 295 6.8444460630416870e-03 + + 5.0306834280490875e-02 -4.3162798881530762e-01 + <_> + + 0 -1 827 1.1850953102111816e-02 + + 3.2905589789152145e-02 -5.1617246866226196e-01 + <_> + + 0 -1 831 2.1246306598186493e-02 + + -6.3726536929607391e-02 3.0544599890708923e-01 + <_> + + 0 -1 256 1.1852337047457695e-02 + + -8.9553833007812500e-02 2.9359081387519836e-01 + <_> + + 0 -1 323 -2.5085010565817356e-03 + + 2.2805334627628326e-01 -9.5263637602329254e-02 + <_> + + 0 -1 752 7.5797801837325096e-03 + + 3.8756053894758224e-02 -5.7552194595336914e-01 + <_> + + 0 -1 86 5.4980744607746601e-03 + + 4.6144284307956696e-02 -3.6506399512290955e-01 + <_> + + 0 -1 208 -3.0190458055585623e-03 + + -2.9709556698799133e-01 7.5851216912269592e-02 + <_> + + 0 -1 552 -7.0441095158457756e-03 + + 1.6086654365062714e-01 -1.1914677917957306e-01 + <_> + + 0 -1 364 -6.9178184494376183e-03 + + -4.1069602966308594e-01 4.4916272163391113e-02 + <_> + + 0 -1 351 5.0740875303745270e-03 + + -7.4677795171737671e-02 2.4945564568042755e-01 + <_> + + 0 -1 121 -1.0403880849480629e-02 + + -5.3336864709854126e-01 3.9480298757553101e-02 + <_> + + 0 -1 323 2.3738082963973284e-03 + + -7.8084513545036316e-02 2.3774850368499756e-01 + <_> + + 0 -1 391 2.7033074729843065e-05 + + -1.8558554351329803e-01 9.6640095114707947e-02 + <_> + + 0 -1 167 2.9049259610474110e-03 + + 4.6409133821725845e-02 -3.9720407128334045e-01 + <_> + + 0 -1 181 -5.6298477575182915e-03 + + -4.5908093452453613e-01 3.7730857729911804e-02 + <_> + + 0 -1 638 5.0751655362546444e-03 + + 2.3507807403802872e-02 -6.4602053165435791e-01 + <_> + + 0 -1 909 -7.5826002284884453e-04 + + 1.2444372475147247e-01 -1.3639765977859497e-01 + <_> + + 0 -1 11 -9.7201213240623474e-02 + + 3.9986947178840637e-01 -4.4366274029016495e-02 + <_> + + 0 -1 496 -2.3840454220771790e-01 + + -5.3094118833541870e-01 3.8410611450672150e-02 + <_> + + 0 -1 114 -1.3428549282252789e-02 + + 2.2794343531131744e-01 -7.7827021479606628e-02 + <_> + + 0 -1 64 -5.0623202696442604e-04 + + 1.5778008103370667e-01 -1.2732668220996857e-01 + <_> + + 0 -1 931 -8.6578715126961470e-04 + + 1.4809772372245789e-01 -1.1785575747489929e-01 + <_> + + 0 -1 544 -2.7892580255866051e-03 + + -4.2324438691139221e-01 4.1194166988134384e-02 + <_> + + 0 -1 654 2.9110969044268131e-03 + + -1.2145258486270905e-01 1.4758351445198059e-01 + <_> + + 0 -1 122 -1.7908504605293274e-01 + + 4.0684828162193298e-01 -4.6298943459987640e-02 + <_> + + 0 -1 894 4.2685694643296301e-04 + + -9.4548642635345459e-02 1.8615303933620453e-01 + <_> + + 0 -1 72 1.9871112704277039e-01 + + -5.6818448007106781e-02 3.2197028398513794e-01 + <_> + + 0 -1 892 1.2496551498770714e-03 + + -7.0664338767528534e-02 2.5729593634605408e-01 + <_> + + 0 -1 447 1.6119793057441711e-02 + + -5.0713617354631424e-02 3.9684635400772095e-01 + <_> + + 0 -1 964 -2.5047704111784697e-03 + + -3.5733562707901001e-01 4.9460943788290024e-02 + <_> + + 0 -1 672 5.2866833284497261e-03 + + 3.2510578632354736e-02 -4.4326359033584595e-01 + <_> + + 0 -1 633 -3.4677600488066673e-03 + + 2.3254001140594482e-01 -7.3516972362995148e-02 + <_> + + 0 -1 600 -3.3557973802089691e-03 + + 2.3221854865550995e-01 -6.9719336926937103e-02 + <_> + + 0 -1 801 -6.3276281580328941e-03 + + -4.0112924575805664e-01 4.3525256216526031e-02 + <_> + + 0 -1 218 -4.3456726707518101e-03 + + -6.8020933866500854e-01 1.9806224852800369e-02 + <_> + + 0 -1 604 6.2400596216320992e-03 + + 1.8352568149566650e-02 -7.0223194360733032e-01 + <_> + + 0 -1 979 3.3795731142163277e-03 + + 4.3487045913934708e-02 -3.0831974744796753e-01 + <_> + + 0 -1 937 1.3499217107892036e-02 + + -4.4923197478055954e-02 3.2624542713165283e-01 + <_> + + 0 -1 408 -1.0585743002593517e-03 + + 1.6033367812633514e-01 -9.8465800285339355e-02 + <_> + + 0 -1 405 -5.3765797056257725e-03 + + 2.6544988155364990e-01 -6.7050188779830933e-02 + <_> + + 0 -1 980 -2.4880110286176205e-03 + + -2.9397118091583252e-01 5.4097402840852737e-02 + <_> + + 0 -1 505 -2.1792344748973846e-02 + + -7.2506862878799438e-01 1.9187789410352707e-02 + <_> + + 0 -1 714 4.7056311741471291e-03 + + -5.2215453237295151e-02 3.1615570187568665e-01 + <_> + + 0 -1 669 -4.2645912617444992e-03 + + 2.3567616939544678e-01 -6.8938009440898895e-02 + <_> + + 0 -1 774 5.8556320145726204e-03 + + 4.2000979185104370e-02 -4.6045160293579102e-01 + <_> + + 0 -1 926 1.3632343616336584e-03 + + -6.5663956105709076e-02 2.3397234082221985e-01 + <_> + + 0 -1 895 -6.0495175421237946e-03 + + -4.3943586945533752e-01 3.6742802709341049e-02 + <_> + + 0 -1 308 6.7223357036709785e-03 + + 1.9922675564885139e-02 -6.8767511844635010e-01 + <_> + + 0 -1 917 -5.1960002630949020e-02 + + -7.5993520021438599e-01 1.5627101063728333e-02 + <_> + + 0 -1 542 3.3762669190764427e-03 + + -7.7943108975887299e-02 1.9545321166515350e-01 + <_> + + 0 -1 582 -1.8302195239812136e-03 + + 1.9154363870620728e-01 -9.4946600496768951e-02 + <_> + + 0 -1 71 -4.3824277818202972e-03 + + -5.3172159194946289e-01 2.8438575565814972e-02 + <_> + + 0 -1 107 4.8605538904666901e-03 + + 1.8084224313497543e-02 -7.0419138669967651e-01 + <_> + + 0 -1 289 -5.0755832344293594e-03 + + 1.3961549103260040e-01 -1.0557857155799866e-01 + <_> + + 0 -1 349 9.0303886681795120e-03 + + -5.6681722402572632e-02 3.0537691712379456e-01 + <_> + + 0 -1 52 1.7635107040405273e-01 + + -3.5581633448600769e-02 3.9358299970626831e-01 + <_> + + 0 -1 728 1.1068049352616072e-03 + + -9.6729792654514313e-02 1.6677951812744141e-01 + <_> + + 0 -1 162 1.1059102602303028e-02 + + 2.9283966869115829e-02 -5.1121145486831665e-01 + <_> + + 0 -1 236 -5.0462923943996429e-02 + + -4.2722624540328979e-01 3.1082244589924812e-02 + <_> + + 0 -1 316 -3.8071773014962673e-03 + + 2.9747742414474487e-01 -5.1289469003677368e-02 + <_> + + 0 -1 373 -1.5183673240244389e-03 + + 1.8215130269527435e-01 -1.0301912575960159e-01 + <_> + + 0 -1 258 2.1069757640361786e-02 + + 2.4503789842128754e-02 -5.8991265296936035e-01 + <_> + + 0 -1 68 6.6435593180358410e-03 + + 4.3313629925251007e-02 -3.1504327058792114e-01 + <_> + + 0 -1 574 -8.2504414021968842e-03 + + -4.7998124361038208e-01 3.0433293431997299e-02 + <_> + + 0 -1 617 -1.0892231017351151e-02 + + 3.1449675559997559e-01 -5.2475348114967346e-02 + <_> + + 0 -1 213 8.1554818898439407e-03 + + 3.9224579930305481e-02 -3.8470247387886047e-01 + <_> + + 0 -1 838 -5.4475883953273296e-03 + + -6.5578418970108032e-01 2.0117431879043579e-02 + <_> + + 0 -1 487 -2.6005427935160697e-04 + + 1.4328984916210175e-01 -9.8999619483947754e-02 + <_> + + 0 -1 461 1.3821206521242857e-03 + + -5.2590593695640564e-02 2.7557003498077393e-01 + <_> + + 0 -1 445 -1.1740636080503464e-02 + + 2.7564841508865356e-01 -5.9799015522003174e-02 + <_> + + 0 -1 941 2.7866149321198463e-03 + + 5.0002526491880417e-02 -3.5232934355735779e-01 + <_> + + 0 -1 962 6.6179647110402584e-03 + + -6.3348092138767242e-02 2.3150660097599030e-01 + <_> + + 0 -1 297 -1.3244405854493380e-03 + + -2.6642721891403198e-01 5.5936500430107117e-02 + <_> + + 0 -1 485 1.1830568313598633e-02 + + -6.9061063230037689e-02 2.1172530949115753e-01 + <_> + + 0 -1 644 2.5925931986421347e-03 + + 1.9716180860996246e-02 -7.7208590507507324e-01 + <_> + + 0 -1 748 -2.8010653331875801e-03 + + 1.3846111297607422e-01 -9.7015053033828735e-02 + <_> + + 0 -1 144 -4.7637272626161575e-02 + + 2.1245625615119934e-01 -7.0445045828819275e-02 + <_> + + 0 -1 197 1.3677144888788462e-03 + + -8.5676178336143494e-02 1.9613882899284363e-01 + <_> + + 0 -1 556 -1.3261453807353973e-01 + + 4.3639957904815674e-01 -3.4653130918741226e-02 + <_> + + 0 -1 69 7.1225965023040771e-01 + + 1.9474601373076439e-02 -8.7232232093811035e-01 + <_> + + 0 -1 149 -5.9057516045868397e-03 + + -3.7135502696037292e-01 3.5206548869609833e-02 + <_> + + 0 -1 971 3.5532126203179359e-03 + + -6.6334858536720276e-02 2.3531165719032288e-01 + <_> + + 0 -1 31 -1.9724387675523758e-02 + + 2.5173032283782959e-01 -5.7575348764657974e-02 + + <_> + 100 + -1.3067311048507690e+00 + + <_> + + 0 -1 458 8.1832958385348320e-03 + + -1.1180391162633896e-01 3.9526882767677307e-01 + <_> + + 0 -1 717 -5.5650249123573303e-03 + + 3.3437621593475342e-01 -1.2654128670692444e-01 + <_> + + 0 -1 577 8.1406952813267708e-04 + + -1.7086146771907806e-01 1.8384252488613129e-01 + <_> + + 0 -1 113 -2.0645279437303543e-03 + + 1.7057111859321594e-01 -1.7103828489780426e-01 + <_> + + 0 -1 864 1.9037863239645958e-03 + + -1.6791534423828125e-01 1.5749432146549225e-01 + <_> + + 0 -1 242 1.1136581189930439e-02 + + 4.0173061192035675e-02 -3.7364640831947327e-01 + <_> + + 0 -1 228 5.6379067245870829e-04 + + -1.6792711615562439e-01 1.4207355678081512e-01 + <_> + + 0 -1 797 -3.3720356877893209e-03 + + 2.5698736310005188e-01 -7.5178287923336029e-02 + <_> + + 0 -1 710 -1.7311582341790199e-02 + + -5.2065086364746094e-01 4.7350786626338959e-02 + <_> + + 0 -1 845 -3.3407085575163364e-03 + + -4.5184752345085144e-01 3.2597322016954422e-02 + <_> + + 0 -1 661 -3.4317255020141602e-02 + + 2.5700893998146057e-01 -8.3455510437488556e-02 + <_> + + 0 -1 423 -6.8267658352851868e-02 + + 2.8288829326629639e-01 -7.8631594777107239e-02 + <_> + + 0 -1 951 2.8722581191686913e-05 + + -1.8466357886791229e-01 1.1576397716999054e-01 + <_> + + 0 -1 267 9.9579263478517532e-03 + + -6.3400641083717346e-02 3.6796927452087402e-01 + <_> + + 0 -1 733 -1.8424488604068756e-02 + + 2.4584248661994934e-01 -9.4283707439899445e-02 + <_> + + 0 -1 837 6.8876314908266068e-03 + + -9.9725127220153809e-02 2.8111982345581055e-01 + <_> + + 0 -1 657 -2.2637452930212021e-03 + + -4.1033151745796204e-01 6.1188895255327225e-02 + <_> + + 0 -1 191 -8.5531552031170577e-05 + + 1.1543370783329010e-01 -1.6276736557483673e-01 + <_> + + 0 -1 32 3.3203132450580597e-02 + + 4.8811107873916626e-02 -3.7535405158996582e-01 + <_> + + 0 -1 929 5.1993243396282196e-03 + + 3.9811953902244568e-02 -4.8758861422538757e-01 + <_> + + 0 -1 365 4.8818998038768768e-03 + + 2.4118293076753616e-02 -6.7809182405471802e-01 + <_> + + 0 -1 82 -7.2956003248691559e-02 + + 1.8825025856494904e-01 -9.5193333923816681e-02 + <_> + + 0 -1 836 9.4123989343643188e-02 + + -7.2761356830596924e-02 2.7999758720397949e-01 + <_> + + 0 -1 718 1.0472428984940052e-03 + + -7.4624419212341309e-02 2.4220877885818481e-01 + <_> + + 0 -1 446 8.0979522317647934e-03 + + -5.4950036108493805e-02 3.0833497643470764e-01 + <_> + + 0 -1 463 -2.8517602477222681e-03 + + 3.2442548871040344e-01 -7.1306072175502777e-02 + <_> + + 0 -1 63 3.7457090802490711e-03 + + 5.7812750339508057e-02 -3.3119776844978333e-01 + <_> + + 0 -1 217 -3.9520347490906715e-03 + + -4.3750977516174316e-01 3.9293695241212845e-02 + <_> + + 0 -1 865 -5.8175362646579742e-03 + + 2.0937338471412659e-01 -8.1724949181079865e-02 + <_> + + 0 -1 878 7.8594256192445755e-03 + + 4.8747915774583817e-02 -4.1596582531929016e-01 + <_> + + 0 -1 913 -6.7130924435332417e-04 + + 1.4715777337551117e-01 -1.2916122376918793e-01 + <_> + + 0 -1 62 -4.2964564636349678e-03 + + -3.5870963335037231e-01 4.8831127583980560e-02 + <_> + + 0 -1 868 -3.8814521394670010e-03 + + -4.7464737296104431e-01 3.4466378390789032e-02 + <_> + + 0 -1 950 -1.8017216352745891e-03 + + -3.5517925024032593e-01 4.9101348966360092e-02 + <_> + + 0 -1 813 7.7566690742969513e-03 + + 2.7035165578126907e-02 -5.5951416492462158e-01 + <_> + + 0 -1 886 1.9125882536172867e-03 + + -6.3309118151664734e-02 2.5223699212074280e-01 + <_> + + 0 -1 886 -9.9804997444152832e-04 + + 2.4349449574947357e-01 -8.9007876813411713e-02 + <_> + + 0 -1 97 -7.5093598570674658e-04 + + 1.3702079653739929e-01 -1.2293258309364319e-01 + <_> + + 0 -1 7 1.0788314975798130e-02 + + -7.3592424392700195e-02 2.3694764077663422e-01 + <_> + + 0 -1 428 -1.2814668007194996e-03 + + 1.7014959454536438e-01 -9.3263216316699982e-02 + <_> + + 0 -1 851 3.5997035447508097e-03 + + 2.4880735203623772e-02 -5.7666695117950439e-01 + <_> + + 0 -1 410 5.9913634322583675e-03 + + -6.6571407020092010e-02 2.3750782012939453e-01 + <_> + + 0 -1 299 3.7381309084594250e-03 + + 3.7266705185174942e-02 -4.3619966506958008e-01 + <_> + + 0 -1 372 8.8815446943044662e-03 + + 3.0544634908437729e-02 -4.6924960613250732e-01 + <_> + + 0 -1 243 -3.1860180199146271e-02 + + -4.8059463500976562e-01 3.1165035441517830e-02 + <_> + + 0 -1 881 -5.4914336651563644e-03 + + 1.7584608495235443e-01 -9.0091012418270111e-02 + <_> + + 0 -1 821 -1.2325609102845192e-02 + + 3.4678825736045837e-01 -5.6969922035932541e-02 + <_> + + 0 -1 281 5.8694169856607914e-03 + + 3.9381653070449829e-02 -4.6237498521804810e-01 + <_> + + 0 -1 207 -5.0925426185131073e-03 + + -4.0191245079040527e-01 4.1170045733451843e-02 + <_> + + 0 -1 636 4.5132841914892197e-03 + + 2.7933681383728981e-02 -4.8419687151908875e-01 + <_> + + 0 -1 665 2.2130757570266724e-02 + + 2.1358741447329521e-02 -6.0434627532958984e-01 + <_> + + 0 -1 597 -1.8624030053615570e-03 + + 1.9556084275245667e-01 -7.8905813395977020e-02 + <_> + + 0 -1 599 3.2466566190123558e-03 + + -8.3141714334487915e-02 2.5859814882278442e-01 + <_> + + 0 -1 575 1.9641252234578133e-02 + + 2.1901637315750122e-02 -7.2247391939163208e-01 + <_> + + 0 -1 271 1.2722628191113472e-02 + + -4.9173772335052490e-02 3.1656193733215332e-01 + <_> + + 0 -1 210 -3.9457585080526769e-04 + + 1.7969387769699097e-01 -1.0087045282125473e-01 + <_> + + 0 -1 88 -3.0111533123999834e-04 + + 1.2916654348373413e-01 -1.5019074082374573e-01 + <_> + + 0 -1 84 -4.1901473887264729e-03 + + 1.6727919876575470e-01 -9.4101771712303162e-02 + <_> + + 0 -1 186 -2.9096096754074097e-02 + + 2.4397623538970947e-01 -6.5033406019210815e-02 + <_> + + 0 -1 815 -3.0687432736158371e-02 + + -5.3695982694625854e-01 3.6870311945676804e-02 + <_> + + 0 -1 596 8.9634142816066742e-02 + + -4.5044522732496262e-02 3.7668040394783020e-01 + <_> + + 0 -1 765 -1.8486939370632172e-02 + + -4.5869186520576477e-01 3.6696173250675201e-02 + <_> + + 0 -1 561 -2.0481455139815807e-03 + + 1.9705456495285034e-01 -8.1085532903671265e-02 + <_> + + 0 -1 160 7.9915560781955719e-03 + + 2.6794398203492165e-02 -6.0658437013626099e-01 + <_> + + 0 -1 368 -4.5167207717895508e-03 + + -3.5664665699005127e-01 4.1606105864048004e-02 + <_> + + 0 -1 429 -8.8896900415420532e-03 + + -5.6794744729995728e-01 2.4264462292194366e-02 + <_> + + 0 -1 601 -2.7863893657922745e-02 + + -6.6293621063232422e-01 1.7915287986397743e-02 + <_> + + 0 -1 153 1.9837494473904371e-03 + + -5.5686347186565399e-02 2.7396288514137268e-01 + <_> + + 0 -1 624 -2.9144049622118473e-03 + + -4.3623712658882141e-01 3.1940482556819916e-02 + <_> + + 0 -1 924 -1.1720246402546763e-03 + + 1.5299941599369049e-01 -8.8886320590972900e-02 + <_> + + 0 -1 927 2.1249109413474798e-03 + + -7.1360021829605103e-02 2.0698173344135284e-01 + <_> + + 0 -1 602 4.6013649553060532e-03 + + 2.5328675284981728e-02 -5.1310408115386963e-01 + <_> + + 0 -1 644 -9.4112986698746681e-04 + + -2.9404127597808838e-01 4.4868268072605133e-02 + <_> + + 0 -1 719 5.2681900560855865e-03 + + -6.4163528382778168e-02 2.2999708354473114e-01 + <_> + + 0 -1 652 1.4232876710593700e-03 + + -7.8037962317466736e-02 1.9061613082885742e-01 + <_> + + 0 -1 858 -1.0191567242145538e-02 + + -5.7409489154815674e-01 2.2581731900572777e-02 + <_> + + 0 -1 547 -4.9564028158783913e-03 + + 2.4646909534931183e-01 -5.9094201773405075e-02 + <_> + + 0 -1 545 2.2057720925658941e-03 + + -9.8776444792747498e-02 1.9191808998584747e-01 + <_> + + 0 -1 809 -4.7279503196477890e-03 + + -2.9638877511024475e-01 4.7132529318332672e-02 + <_> + + 0 -1 905 1.8900397699326277e-03 + + -1.2390431761741638e-01 1.2199163436889648e-01 + <_> + + 0 -1 692 -3.9616838330402970e-04 + + -2.0177872478961945e-01 6.7829817533493042e-02 + <_> + + 0 -1 378 1.5198520850390196e-03 + + -5.0418090075254440e-02 2.8014704585075378e-01 + <_> + + 0 -1 377 -3.0729006975889206e-03 + + 1.6384753584861755e-01 -9.6394442021846771e-02 + <_> + + 0 -1 637 3.3707641065120697e-02 + + 3.3062599599361420e-02 -4.3530252575874329e-01 + <_> + + 0 -1 993 -2.7547087520360947e-03 + + -6.2498420476913452e-01 2.0407166332006454e-02 + <_> + + 0 -1 993 1.0800797026604414e-03 + + 4.3235320597887039e-02 -3.1784874200820923e-01 + <_> + + 0 -1 981 -2.4060246068984270e-03 + + 1.3923163712024689e-01 -9.8239123821258545e-02 + <_> + + 0 -1 727 4.6191983856260777e-03 + + 2.3523205891251564e-02 -6.0865134000778198e-01 + <_> + + 0 -1 284 2.1874131634831429e-03 + + -4.4655255973339081e-02 3.2406413555145264e-01 + <_> + + 0 -1 137 7.9257078468799591e-03 + + 2.8643675148487091e-02 -5.0231784582138062e-01 + <_> + + 0 -1 340 9.6561573445796967e-03 + + -6.7481219768524170e-02 2.0780794322490692e-01 + <_> + + 0 -1 180 -4.3771188706159592e-02 + + 2.0091144740581512e-01 -8.7350860238075256e-02 + <_> + + 0 -1 28 -3.9570517838001251e-02 + + -6.9823634624481201e-01 2.2996466606855392e-02 + <_> + + 0 -1 517 -7.4827047064900398e-03 + + -3.2485857605934143e-01 4.2747449129819870e-02 + <_> + + 0 -1 863 -9.5894857076928020e-04 + + 1.3692225515842438e-01 -1.0624063760042191e-01 + <_> + + 0 -1 495 -5.6482471525669098e-02 + + 2.7130955457687378e-01 -5.5133864283561707e-02 + <_> + + 0 -1 526 -5.5641448125243187e-03 + + -6.5910613536834717e-01 2.6108600199222565e-02 + <_> + + 0 -1 833 4.5432001352310181e-03 + + -1.0277131199836731e-01 1.4715240895748138e-01 + <_> + + 0 -1 804 -1.9441416952759027e-03 + + 1.7929133772850037e-01 -7.8247167170047760e-02 + <_> + + 0 -1 615 1.5584268840029836e-03 + + 5.2101351320743561e-02 -2.7727204561233521e-01 + <_> + + <_> + 0 0 6 1 -1. + <_> + 3 0 3 1 2. + 0 <_> <_> @@ -5651,6 +6128,13 @@ <_> 4 0 4 1 2. 0 + <_> + + <_> + 0 0 8 2 -1. + <_> + 4 0 4 2 2. + 0 <_> <_> @@ -5660,6 +6144,22 @@ <_> 4 3 4 3 2. 0 + <_> + + <_> + 0 0 8 12 -1. + <_> + 0 0 4 6 2. + <_> + 4 6 4 6 2. + 0 + <_> + + <_> + 0 0 10 1 -1. + <_> + 5 0 5 1 2. + 0 <_> <_> @@ -5672,18 +6172,34 @@ <_> <_> - 0 0 24 5 -1. + 0 0 24 1 -1. <_> - 6 0 12 5 2. + 6 0 12 1 2. 0 <_> <_> - 0 0 16 6 -1. + 0 0 24 2 -1. <_> - 0 0 8 3 2. + 6 0 12 2 2. + 0 + <_> + <_> - 8 3 8 3 2. + 0 0 14 8 -1. + <_> + 0 0 7 4 2. + <_> + 7 4 7 4 2. + 0 + <_> + + <_> + 0 0 16 8 -1. + <_> + 0 0 8 4 2. + <_> + 8 4 8 4 2. 0 <_> @@ -5704,98 +6220,59 @@ <_> <_> - 0 0 24 12 -1. + 0 0 13 10 -1. <_> - 0 0 12 6 2. - <_> - 12 6 12 6 2. + 0 5 13 5 2. 0 <_> <_> - 0 1 8 10 -1. + 0 1 16 10 -1. <_> - 0 1 4 5 2. + 0 1 8 5 2. <_> - 4 6 4 5 2. + 8 6 8 5 2. 0 <_> <_> - 0 1 10 2 -1. + 0 1 13 15 -1. <_> - 5 1 5 2 2. + 0 6 13 5 3. 0 <_> <_> - 0 1 10 6 -1. + 0 2 8 12 -1. <_> - 0 1 5 3 2. + 0 2 4 6 2. <_> - 5 4 5 3 2. + 4 8 4 6 2. 0 <_> <_> - 0 1 10 10 -1. + 0 2 10 4 -1. <_> - 0 1 5 5 2. + 0 2 5 2 2. <_> - 5 6 5 5 2. + 5 4 5 2 2. 0 <_> <_> - 0 1 24 2 -1. + 0 4 24 2 -1. <_> - 0 1 12 1 2. + 0 4 12 1 2. <_> - 12 2 12 1 2. + 12 5 12 1 2. 0 <_> <_> - 0 2 18 9 -1. + 0 5 4 9 -1. <_> - 0 5 18 3 3. - 0 - <_> - - <_> - 0 3 6 9 -1. - <_> - 0 6 6 3 3. - 0 - <_> - - <_> - 0 3 24 2 -1. - <_> - 0 3 12 1 2. - <_> - 12 4 12 1 2. - 0 - <_> - - <_> - 0 4 16 15 -1. - <_> - 0 9 16 5 3. - 0 - <_> - - <_> - 0 4 22 6 -1. - <_> - 0 6 22 2 3. - 0 - <_> - - <_> - 0 4 24 6 -1. - <_> - 0 6 24 2 3. + 0 8 4 3 3. 0 <_> @@ -5806,6 +6283,29 @@ <_> 12 6 12 1 2. 0 + <_> + + <_> + 0 5 24 4 -1. + <_> + 0 5 12 2 2. + <_> + 12 7 12 2 2. + 0 + <_> + + <_> + 0 6 5 8 -1. + <_> + 0 8 5 4 2. + 0 + <_> + + <_> + 0 6 22 17 -1. + <_> + 11 6 11 17 2. + 0 <_> <_> @@ -5818,50 +6318,51 @@ <_> <_> - 0 6 24 3 -1. + 0 6 14 8 -1. <_> - 0 7 24 1 3. + 0 10 14 4 2. 0 <_> <_> - 0 7 8 2 -1. + 0 7 2 3 -1. <_> - 0 7 4 1 2. - <_> - 4 8 4 1 2. + 0 8 2 1 3. 0 <_> <_> - 0 7 24 1 -1. + 0 7 6 16 -1. <_> - 8 7 8 1 3. + 3 7 3 16 2. 0 <_> <_> - 0 7 24 4 -1. + 0 7 4 9 -1. <_> - 0 7 12 2 2. - <_> - 12 9 12 2 2. + 0 10 4 3 3. 0 <_> <_> - 0 7 22 4 -1. + 0 7 8 17 -1. <_> - 0 8 22 2 2. + 4 7 4 17 2. 0 <_> <_> - 0 8 24 4 -1. + 0 7 24 2 -1. <_> - 0 8 12 2 2. + 6 7 12 2 2. + 0 + <_> + <_> - 12 10 12 2 2. + 0 8 4 16 -1. + <_> + 2 8 2 16 2. 0 <_> @@ -5875,25 +6376,9 @@ <_> <_> - 0 8 24 8 -1. + 0 9 1 3 -1. <_> - 0 8 12 4 2. - <_> - 12 12 12 4 2. - 0 - <_> - - <_> - 0 9 4 3 -1. - <_> - 0 10 4 1 3. - 0 - <_> - - <_> - 0 9 4 8 -1. - <_> - 0 11 4 4 2. + 0 10 1 1 3. 0 <_> @@ -5905,11 +6390,9 @@ <_> <_> - 0 9 20 2 -1. + 0 9 8 2 -1. <_> - 0 9 10 1 2. - <_> - 10 10 10 1 2. + 0 10 8 1 2. 0 <_> @@ -5923,20 +6406,11 @@ <_> <_> - 0 9 22 4 -1. + 0 9 24 2 -1. <_> - 0 9 11 2 2. + 0 9 12 1 2. <_> - 11 11 11 2 2. - 0 - <_> - - <_> - 0 9 22 10 -1. - <_> - 0 9 11 5 2. - <_> - 11 14 11 5 2. + 12 10 12 1 2. 0 <_> @@ -5950,9 +6424,39 @@ <_> <_> - 0 10 3 3 -1. + 0 10 2 2 -1. <_> - 0 11 3 1 3. + 0 11 2 1 2. + 0 + <_> + + <_> + 0 10 4 10 -1. + <_> + 2 10 2 10 2. + 0 + <_> + + <_> + 0 10 4 3 -1. + <_> + 0 11 4 1 3. + 0 + <_> + + <_> + 0 10 5 3 -1. + <_> + 0 11 5 1 3. + 0 + <_> + + <_> + 0 10 22 2 -1. + <_> + 0 10 11 1 2. + <_> + 11 11 11 1 2. 0 <_> @@ -5963,6 +6467,29 @@ <_> 12 11 12 1 2. 0 + <_> + + <_> + 0 10 24 4 -1. + <_> + 0 10 12 2 2. + <_> + 12 12 12 2 2. + 0 + <_> + + <_> + 0 10 24 14 -1. + <_> + 12 10 12 14 2. + 0 + <_> + + <_> + 0 11 3 3 -1. + <_> + 0 12 3 1 3. + 0 <_> <_> @@ -5975,111 +6502,99 @@ <_> <_> - 0 11 24 2 -1. + 0 11 24 4 -1. <_> - 0 11 12 1 2. + 0 11 12 2 2. <_> - 12 12 12 1 2. + 12 13 12 2 2. 0 <_> <_> - 0 11 24 7 -1. + 0 12 18 7 -1. <_> - 12 11 12 7 2. + 9 12 9 7 2. 0 <_> <_> - 0 12 6 10 -1. + 0 12 22 2 -1. <_> - 3 12 3 10 2. + 0 12 11 1 2. + <_> + 11 13 11 1 2. 0 <_> <_> - 0 13 22 10 -1. + 0 12 24 6 -1. <_> - 11 13 11 10 2. + 12 12 12 6 2. 0 <_> <_> - 0 14 8 6 -1. + 0 13 24 3 -1. <_> - 4 14 4 6 2. + 6 13 12 3 2. 0 <_> <_> - 0 15 18 7 -1. + 0 14 8 7 -1. <_> - 9 15 9 7 2. + 4 14 4 7 2. 0 <_> <_> - 0 16 10 3 -1. + 0 14 12 10 -1. <_> - 5 16 5 3 2. + 0 14 6 5 2. + <_> + 6 19 6 5 2. 0 <_> <_> - 0 17 3 3 -1. + 0 14 18 8 -1. <_> - 1 17 1 3 3. + 6 14 6 8 3. 0 <_> <_> - 0 17 3 4 -1. + 0 14 20 10 -1. <_> - 1 17 1 4 3. + 10 14 10 10 2. 0 <_> <_> - 0 18 6 4 -1. + 0 15 3 8 -1. <_> - 3 18 3 4 2. + 1 15 1 8 3. 0 <_> <_> - 0 18 10 4 -1. + 0 16 3 7 -1. <_> - 5 18 5 4 2. + 1 16 1 7 3. 0 <_> <_> - 0 18 9 3 -1. + 0 19 6 3 -1. <_> - 0 19 9 1 3. + 0 20 6 1 3. 0 <_> <_> - 0 18 18 6 -1. + 0 19 9 3 -1. <_> - 0 18 9 3 2. - <_> - 9 21 9 3 2. - 0 - <_> - - <_> - 0 19 3 5 -1. - <_> - 1 19 1 5 3. - 0 - <_> - - <_> - 0 20 24 2 -1. - <_> - 6 20 12 2 2. + 0 20 9 1 3. 0 <_> @@ -6091,9 +6606,16 @@ <_> <_> - 1 0 6 1 -1. + 0 21 7 3 -1. <_> - 4 0 3 1 2. + 0 22 7 1 3. + 0 + <_> + + <_> + 1 0 1 4 -1. + <_> + 1 2 1 2 2. 0 <_> @@ -6105,87 +6627,48 @@ <_> <_> - 1 0 8 1 -1. + 1 0 8 6 -1. <_> - 5 0 4 1 2. + 1 0 4 3 2. + <_> + 5 3 4 3 2. 0 <_> <_> - 1 0 20 1 -1. + 1 0 8 4 -1. <_> - 6 0 10 1 2. + 5 0 4 4 2. 0 <_> <_> - 1 0 14 4 -1. + 1 0 22 2 -1. <_> - 1 0 7 2 2. + 1 0 11 1 2. <_> - 8 2 7 2 2. + 12 1 11 1 2. 0 <_> <_> - 1 0 14 8 -1. + 1 3 21 15 -1. <_> - 1 0 7 4 2. - <_> - 8 4 7 4 2. + 8 8 7 5 9. 0 <_> <_> - 1 0 14 10 -1. + 1 3 11 3 -1. <_> - 1 0 7 5 2. - <_> - 8 5 7 5 2. + 1 4 11 1 3. 0 <_> <_> - 1 3 22 21 -1. + 1 5 3 3 -1. <_> - 12 3 11 21 2. - 0 - <_> - - <_> - 1 3 14 12 -1. - <_> - 1 6 14 6 2. - 0 - <_> - - <_> - 1 4 5 3 -1. - <_> - 1 5 5 1 3. - 0 - <_> - - <_> - 1 4 9 3 -1. - <_> - 1 5 9 1 3. - 0 - <_> - - <_> - 1 4 22 2 -1. - <_> - 1 4 11 1 2. - <_> - 12 5 11 1 2. - 0 - <_> - - <_> - 1 4 22 18 -1. - <_> - 12 4 11 18 2. + 1 6 3 1 3. 0 <_> @@ -6210,6 +6693,13 @@ <_> 1 7 4 1 3. 0 + <_> + + <_> + 1 6 5 3 -1. + <_> + 1 7 5 1 3. + 0 <_> <_> @@ -6222,18 +6712,16 @@ <_> <_> - 1 6 13 8 -1. + 1 6 22 17 -1. <_> - 1 10 13 4 2. + 12 6 11 17 2. 0 <_> <_> - 1 7 6 2 -1. + 1 6 20 3 -1. <_> - 1 7 3 1 2. - <_> - 4 8 3 1 2. + 1 7 20 1 3. 0 <_> @@ -6245,32 +6733,50 @@ <_> <_> - 1 7 4 9 -1. + 1 7 8 6 -1. <_> - 1 10 4 3 3. + 1 9 8 2 3. 0 <_> <_> - 1 7 21 2 -1. + 1 7 20 4 -1. <_> - 1 8 21 1 2. + 1 7 10 2 2. + <_> + 11 9 10 2 2. 0 <_> <_> - 1 8 20 4 -1. + 1 7 22 12 -1. <_> - 1 8 10 2 2. - <_> - 11 10 10 2 2. + 1 11 22 4 3. 0 <_> <_> - 1 8 23 3 -1. + 1 8 8 2 -1. <_> - 1 9 23 1 3. + 1 8 4 1 2. + <_> + 5 9 4 1 2. + 0 + <_> + + <_> + 1 8 9 3 -1. + <_> + 1 9 9 1 3. + 0 + <_> + + <_> + 1 8 22 4 -1. + <_> + 1 8 11 2 2. + <_> + 12 10 11 2 2. 0 <_> @@ -6284,27 +6790,16 @@ <_> <_> - 1 9 20 6 -1. + 1 10 4 3 -1. <_> - 1 9 10 3 2. - <_> - 11 12 10 3 2. + 3 10 2 3 2. 0 <_> <_> - 1 9 22 2 -1. + 1 10 4 4 -1. <_> - 1 9 11 1 2. - <_> - 12 10 11 1 2. - 0 - <_> - - <_> - 1 10 4 1 -1. - <_> - 3 10 2 1 2. + 1 11 4 2 2. 0 <_> @@ -6318,59 +6813,23 @@ <_> <_> - 1 12 8 1 -1. + 1 10 21 4 -1. <_> - 3 12 4 1 2. + 1 11 21 2 2. 0 <_> <_> - 1 12 8 12 -1. + 1 11 3 13 -1. <_> - 1 12 4 6 2. - <_> - 5 18 4 6 2. + 2 11 1 13 3. 0 <_> <_> - 1 12 20 2 -1. + 1 13 3 10 -1. <_> - 1 12 10 1 2. - <_> - 11 13 10 1 2. - 0 - <_> - - <_> - 1 13 3 11 -1. - <_> - 2 13 1 11 3. - 0 - <_> - - <_> - 1 13 22 4 -1. - <_> - 1 13 11 2 2. - <_> - 12 15 11 2 2. - 0 - <_> - - <_> - 1 13 19 4 -1. - <_> - 1 15 19 2 2. - 0 - <_> - - <_> - 1 14 10 10 -1. - <_> - 1 14 5 5 2. - <_> - 6 19 5 5 2. + 2 13 1 10 3. 0 <_> @@ -6381,13 +6840,6 @@ <_> 12 15 11 1 2. 0 - <_> - - <_> - 1 15 3 8 -1. - <_> - 2 15 1 8 3. - 0 <_> <_> @@ -6398,23 +6850,30 @@ <_> <_> - 1 16 3 3 -1. + 1 17 4 1 -1. <_> - 2 16 1 3 3. - 0 - <_> - - <_> - 1 17 3 1 -1. - <_> - 2 18 1 1 3. + 2 18 2 1 2. 1 <_> <_> - 1 17 3 7 -1. + 1 19 4 1 -1. <_> - 2 17 1 7 3. + 2 20 2 1 2. + 1 + <_> + + <_> + 2 0 4 1 -1. + <_> + 4 0 2 1 2. + 0 + <_> + + <_> + 2 0 12 14 -1. + <_> + 6 0 4 14 3. 0 <_> @@ -6423,15 +6882,6 @@ <_> 7 0 10 1 2. 0 - <_> - - <_> - 2 0 14 12 -1. - <_> - 2 0 7 6 2. - <_> - 9 6 7 6 2. - 0 <_> <_> @@ -6442,9 +6892,27 @@ <_> <_> - 2 3 10 3 -1. + 2 2 22 2 -1. <_> - 2 4 10 1 3. + 2 2 11 1 2. + <_> + 13 3 11 1 2. + 0 + <_> + + <_> + 2 2 22 10 -1. + <_> + 2 2 11 5 2. + <_> + 13 7 11 5 2. + 0 + <_> + + <_> + 2 3 20 1 -1. + <_> + 7 3 10 1 2. 0 <_> @@ -6474,25 +6942,9 @@ <_> <_> - 2 4 22 18 -1. + 2 5 2 3 -1. <_> - 13 4 11 18 2. - 0 - <_> - - <_> - 2 5 1 3 -1. - <_> - 2 6 1 1 3. - 0 - <_> - - <_> - 2 5 2 2 -1. - <_> - 2 5 1 1 2. - <_> - 3 6 1 1 2. + 2 6 2 1 3. 0 <_> @@ -6503,13 +6955,6 @@ <_> 12 6 10 1 2. 0 - <_> - - <_> - 2 6 3 3 -1. - <_> - 2 7 3 1 3. - 0 <_> <_> @@ -6522,27 +6967,25 @@ <_> <_> - 2 6 22 2 -1. + 2 6 21 18 -1. <_> - 2 6 11 1 2. - <_> - 13 7 11 1 2. + 2 15 21 9 2. 0 <_> <_> - 2 6 22 6 -1. + 2 7 6 2 -1. <_> - 2 6 11 3 2. + 2 7 3 1 2. <_> - 13 9 11 3 2. + 5 8 3 1 2. 0 <_> <_> - 2 6 19 3 -1. + 2 7 9 6 -1. <_> - 2 7 19 1 3. + 5 9 3 2 9. 0 <_> @@ -6554,9 +6997,16 @@ <_> <_> - 2 7 7 4 -1. + 2 7 18 2 -1. <_> - 2 8 7 2 2. + 2 8 18 1 2. + 0 + <_> + + <_> + 2 7 18 3 -1. + <_> + 2 8 18 1 3. 0 <_> @@ -6568,79 +7018,33 @@ <_> <_> - 2 7 21 6 -1. + 2 8 4 2 -1. <_> - 2 9 21 2 3. + 4 8 2 2 2. 0 <_> <_> - 2 8 5 2 -1. + 2 8 22 2 -1. <_> - 2 8 5 1 2. + 2 8 11 1 2. + <_> + 13 9 11 1 2. + 0 + <_> + + <_> + 2 9 7 2 -1. + <_> + 2 9 7 1 2. 1 <_> <_> - 2 8 20 3 -1. + 2 9 20 3 -1. <_> - 2 9 20 1 3. + 2 10 20 1 3. 0 - <_> - - <_> - 2 9 20 8 -1. - <_> - 2 9 10 4 2. - <_> - 12 13 10 4 2. - 0 - <_> - - <_> - 2 9 22 2 -1. - <_> - 2 9 11 1 2. - <_> - 13 10 11 1 2. - 0 - <_> - - <_> - 2 9 19 3 -1. - <_> - 2 10 19 1 3. - 0 - <_> - - <_> - 2 10 3 1 -1. - <_> - 3 11 1 1 3. - 1 - <_> - - <_> - 2 10 4 1 -1. - <_> - 4 10 2 1 2. - 0 - <_> - - <_> - 2 10 22 2 -1. - <_> - 2 10 11 1 2. - <_> - 13 11 11 1 2. - 0 - <_> - - <_> - 2 11 3 1 -1. - <_> - 3 12 1 1 3. - 1 <_> <_> @@ -6653,122 +7057,115 @@ <_> <_> - 2 11 11 2 -1. + 2 12 22 7 -1. <_> - 2 11 11 1 2. + 13 12 11 7 2. + 0 + <_> + + <_> + 2 12 19 10 -1. + <_> + 2 17 19 5 2. + 0 + <_> + + <_> + 2 13 3 8 -1. + <_> + 3 13 1 8 3. + 0 + <_> + + <_> + 2 13 20 10 -1. + <_> + 12 13 10 10 2. + 0 + <_> + + <_> + 2 15 6 2 -1. + <_> + 5 15 3 2 2. + 0 + <_> + + <_> + 2 15 6 3 -1. + <_> + 5 15 3 3 2. + 0 + <_> + + <_> + 2 15 20 4 -1. + <_> + 2 15 10 2 2. + <_> + 12 17 10 2 2. + 0 + <_> + + <_> + 2 16 6 6 -1. + <_> + 2 16 3 3 2. + <_> + 5 19 3 3 2. + 0 + <_> + + <_> + 2 17 3 1 -1. + <_> + 3 18 1 1 3. 1 <_> <_> - 2 11 18 3 -1. + 2 18 3 5 -1. <_> - 2 12 18 1 3. + 3 18 1 5 3. 0 <_> <_> - 2 13 20 4 -1. + 2 21 12 3 -1. <_> - 2 13 10 2 2. - <_> - 12 15 10 2 2. + 8 21 6 3 2. 0 <_> <_> - 2 15 3 7 -1. + 3 2 20 1 -1. <_> - 3 15 1 7 3. - 0 - <_> - - <_> - 2 16 4 1 -1. - <_> - 3 17 2 1 2. + 3 2 10 1 2. 1 <_> <_> - 2 17 3 5 -1. + 3 3 8 6 -1. <_> - 3 17 1 5 3. + 5 3 4 6 2. 0 <_> <_> - 3 0 9 16 -1. + 3 4 6 4 -1. <_> - 6 0 3 16 3. + 3 4 3 2 2. + <_> + 6 6 3 2 2. 0 <_> <_> - 3 0 18 3 -1. + 3 4 18 2 -1. <_> - 3 0 9 3 2. - 1 - <_> - + 3 4 9 1 2. <_> - 3 2 18 2 -1. - <_> - 3 2 9 1 2. - <_> - 12 3 9 1 2. - 0 - <_> - - <_> - 3 3 12 1 -1. - <_> - 6 3 6 1 2. - 0 - <_> - - <_> - 3 3 20 3 -1. - <_> - 8 3 10 3 2. - 0 - <_> - - <_> - 3 3 18 2 -1. - <_> - 3 3 9 1 2. - <_> - 12 4 9 1 2. - 0 - <_> - - <_> - 3 4 1 3 -1. - <_> - 3 5 1 1 3. - 0 - <_> - - <_> - 3 4 5 16 -1. - <_> - 3 8 5 8 2. - 0 - <_> - - <_> - 3 4 18 8 -1. - <_> - 3 4 9 4 2. - <_> - 12 8 9 4 2. - 0 - <_> - - <_> - 3 4 20 19 -1. - <_> - 13 4 10 19 2. + 12 5 9 1 2. 0 <_> @@ -6782,90 +7179,71 @@ <_> <_> - 3 5 16 9 -1. + 3 5 20 6 -1. <_> - 3 8 16 3 3. + 3 5 10 3 2. + <_> + 13 8 10 3 2. 0 <_> <_> - 3 5 20 9 -1. + 3 6 3 3 -1. <_> - 3 8 20 3 3. + 3 7 3 1 3. 0 <_> <_> - 3 6 2 3 -1. + 3 6 16 8 -1. <_> - 3 7 2 1 3. + 3 8 16 4 2. 0 <_> <_> - 3 6 18 2 -1. + 3 6 19 6 -1. <_> - 3 6 9 1 2. - <_> - 12 7 9 1 2. + 3 8 19 2 3. 0 <_> <_> - 3 7 3 1 -1. + 3 7 5 4 -1. <_> - 4 7 1 1 3. + 3 8 5 2 2. 0 <_> <_> - 3 7 3 2 -1. + 3 7 18 6 -1. <_> - 3 8 3 1 2. + 3 7 9 3 2. + <_> + 12 10 9 3 2. 0 <_> <_> - 3 7 9 6 -1. + 3 7 17 6 -1. <_> - 6 9 3 2 9. + 3 9 17 2 3. 0 <_> <_> - 3 7 20 2 -1. + 3 7 19 2 -1. <_> - 8 7 10 2 2. + 3 8 19 1 2. 0 <_> <_> - 3 7 6 2 -1. + 3 8 18 4 -1. <_> - 3 8 6 1 2. - 0 - <_> - + 3 8 9 2 2. <_> - 3 7 7 3 -1. - <_> - 3 8 7 1 3. - 0 - <_> - - <_> - 3 7 18 4 -1. - <_> - 3 7 9 2 2. - <_> - 12 9 9 2 2. - 0 - <_> - - <_> - 3 7 19 12 -1. - <_> - 3 11 19 4 3. + 12 10 9 2 2. 0 <_> @@ -6886,18 +7264,16 @@ <_> <_> - 3 9 6 3 -1. + 3 9 3 3 -1. <_> - 3 10 6 1 3. - 0 + 4 10 1 3 3. + 1 <_> <_> - 3 9 16 2 -1. + 3 9 8 9 -1. <_> - 3 9 8 1 2. - <_> - 11 10 8 1 2. + 3 12 8 3 3. 0 <_> @@ -6911,11 +7287,16 @@ <_> <_> - 3 9 20 12 -1. + 3 9 19 9 -1. <_> - 3 9 10 6 2. + 3 12 19 3 3. + 0 + <_> + <_> - 13 15 10 6 2. + 3 10 3 1 -1. + <_> + 4 10 1 1 3. 0 <_> @@ -6934,16 +7315,25 @@ <_> <_> - 3 10 15 3 -1. + 3 10 2 4 -1. <_> - 3 11 15 1 3. + 3 11 2 2 2. 0 <_> <_> - 3 10 20 8 -1. + 3 10 8 3 -1. <_> - 3 12 20 4 2. + 3 11 8 1 3. + 0 + <_> + + <_> + 3 10 18 4 -1. + <_> + 3 10 9 2 2. + <_> + 12 12 9 2 2. 0 <_> @@ -6952,152 +7342,142 @@ <_> 4 12 1 1 3. 1 - <_> - - <_> - 3 11 3 3 -1. - <_> - 4 11 1 3 3. - 0 - <_> - - <_> - 3 11 3 4 -1. - <_> - 4 11 1 4 3. - 0 - <_> - - <_> - 3 11 3 7 -1. - <_> - 4 11 1 7 3. - 0 - <_> - - <_> - 3 11 6 2 -1. - <_> - 3 11 3 1 2. - <_> - 6 12 3 1 2. - 0 <_> <_> 3 11 3 8 -1. <_> - 3 15 3 4 2. + 4 11 1 8 3. 0 <_> <_> - 3 11 7 8 -1. + 3 11 4 8 -1. <_> - 3 15 7 4 2. + 3 15 4 4 2. 0 <_> <_> - 3 11 20 2 -1. + 3 11 18 2 -1. <_> - 3 11 10 1 2. + 3 11 9 1 2. <_> - 13 12 10 1 2. + 12 12 9 1 2. 0 <_> <_> - 3 11 20 8 -1. + 3 11 10 2 -1. <_> - 13 11 10 8 2. - 0 - <_> - - <_> - 3 12 4 8 -1. - <_> - 5 12 2 8 2. - 0 - <_> - - <_> - 3 12 3 8 -1. - <_> - 3 16 3 4 2. - 0 - <_> - - <_> - 3 12 18 8 -1. - <_> - 3 16 18 4 2. - 0 - <_> - - <_> - 3 13 3 3 -1. - <_> - 4 13 1 3 3. - 0 - <_> - - <_> - 3 13 19 6 -1. - <_> - 3 16 19 3 2. - 0 - <_> - - <_> - 3 14 6 10 -1. - <_> - 3 14 3 5 2. - <_> - 6 19 3 5 2. - 0 - <_> - - <_> - 3 15 6 2 -1. - <_> - 6 15 3 2 2. - 0 - <_> - - <_> - 3 16 4 1 -1. - <_> - 4 17 2 1 2. + 3 11 10 1 2. 1 <_> <_> - 3 20 3 3 -1. + 3 12 3 2 -1. <_> - 4 20 1 3 3. - 0 - <_> - - <_> - 4 0 16 20 -1. - <_> - 4 10 16 10 2. - 0 - <_> - - <_> - 4 2 8 13 -1. - <_> - 6 2 4 13 2. - 0 - <_> - - <_> - 4 2 16 1 -1. - <_> - 4 2 8 1 2. + 4 13 1 2 3. 1 + <_> + + <_> + 3 12 8 12 -1. + <_> + 3 16 8 4 3. + 0 + <_> + + <_> + 3 15 4 3 -1. + <_> + 5 15 2 3 2. + 0 + <_> + + <_> + 3 16 3 1 -1. + <_> + 4 17 1 1 3. + 1 + <_> + + <_> + 3 16 6 4 -1. + <_> + 3 16 3 2 2. + <_> + 6 18 3 2 2. + 0 + <_> + + <_> + 3 16 8 6 -1. + <_> + 3 16 4 3 2. + <_> + 7 19 4 3 2. + 0 + <_> + + <_> + 3 20 3 4 -1. + <_> + 4 20 1 4 3. + 0 + <_> + + <_> + 4 0 6 4 -1. + <_> + 6 2 2 4 3. + 1 + <_> + + <_> + 4 2 3 2 -1. + <_> + 5 2 1 2 3. + 0 + <_> + + <_> + 4 2 16 2 -1. + <_> + 4 2 8 1 2. + <_> + 12 3 8 1 2. + 0 + <_> + + <_> + 4 3 6 1 -1. + <_> + 6 3 2 1 3. + 0 + <_> + + <_> + 4 3 9 3 -1. + <_> + 7 3 3 3 3. + 0 + <_> + + <_> + 4 3 16 2 -1. + <_> + 4 3 8 1 2. + <_> + 12 4 8 1 2. + 0 + <_> + + <_> + 4 3 9 6 -1. + <_> + 4 6 9 3 2. + 0 <_> <_> @@ -7108,10 +7488,17 @@ <_> <_> - 4 4 2 4 -1. + 4 4 1 4 -1. <_> - 4 6 2 2 2. + 4 6 1 2 2. 0 + <_> + + <_> + 4 4 9 4 -1. + <_> + 7 7 3 4 3. + 1 <_> <_> @@ -7124,46 +7511,39 @@ <_> <_> - 4 4 18 2 -1. + 4 4 18 6 -1. <_> - 4 4 9 1 2. - <_> - 13 5 9 1 2. + 4 6 18 2 3. 0 <_> <_> - 4 4 10 6 -1. + 4 4 20 6 -1. <_> - 4 7 10 3 2. + 4 6 20 2 3. 0 <_> <_> - 4 4 17 6 -1. + 4 5 4 5 -1. <_> - 4 7 17 3 2. + 6 5 2 5 2. 0 <_> <_> - 4 5 1 3 -1. + 4 5 16 6 -1. <_> - 4 6 1 1 3. + 4 5 8 3 2. + <_> + 12 8 8 3 2. 0 <_> <_> - 4 5 3 3 -1. + 4 5 15 6 -1. <_> - 5 6 1 3 3. - 1 - <_> - - <_> - 4 5 17 6 -1. - <_> - 4 8 17 3 2. + 4 7 15 2 3. 0 <_> @@ -7179,6 +7559,13 @@ <_> 4 7 2 1 3. 0 + <_> + + <_> + 4 6 6 2 -1. + <_> + 6 6 2 2 3. + 0 <_> <_> @@ -7189,85 +7576,25 @@ <_> <_> - 4 6 4 9 -1. + 4 6 6 2 -1. <_> - 4 9 4 3 3. + 4 6 3 1 2. + <_> + 7 7 3 1 2. 0 <_> <_> - 4 6 16 2 -1. + 4 7 4 3 -1. <_> - 4 6 8 1 2. - <_> - 12 7 8 1 2. + 4 8 4 1 3. 0 <_> <_> - 4 6 16 6 -1. + 4 7 15 6 -1. <_> - 4 6 8 3 2. - <_> - 12 9 8 3 2. - 0 - <_> - - <_> - 4 6 20 18 -1. - <_> - 14 6 10 18 2. - 0 - <_> - - <_> - 4 6 15 6 -1. - <_> - 4 8 15 2 3. - 0 - <_> - - <_> - 4 6 16 4 -1. - <_> - 4 7 16 2 2. - 0 - <_> - - <_> - 4 6 16 4 -1. - <_> - 4 8 16 2 2. - 0 - <_> - - <_> - 4 7 6 6 -1. - <_> - 6 9 2 2 9. - 0 - <_> - - <_> - 4 7 5 4 -1. - <_> - 3 8 5 2 2. - 1 - <_> - - <_> - 4 7 5 6 -1. - <_> - 4 9 5 2 3. - 0 - <_> - - <_> - 4 7 16 6 -1. - <_> - 4 7 8 3 2. - <_> - 12 10 8 3 2. + 4 9 15 2 3. 0 <_> @@ -7279,25 +7606,9 @@ <_> <_> - 4 7 17 6 -1. + 4 7 17 3 -1. <_> - 4 9 17 2 3. - 0 - <_> - - <_> - 4 7 18 2 -1. - <_> - 4 8 18 1 2. - 0 - <_> - - <_> - 4 8 2 2 -1. - <_> - 4 8 1 1 2. - <_> - 5 9 1 1 2. + 4 8 17 1 3. 0 <_> @@ -7316,48 +7627,25 @@ <_> <_> - 4 8 4 4 -1. + 4 8 5 4 -1. <_> - 3 9 4 2 2. - 1 - <_> - - <_> - 4 8 14 2 -1. - <_> - 4 8 7 1 2. - <_> - 11 9 7 1 2. + 4 9 5 2 2. 0 <_> <_> - 4 8 7 4 -1. + 4 8 18 4 -1. <_> - 3 9 7 2 2. - 1 - <_> - + 4 8 9 2 2. <_> - 4 8 16 2 -1. - <_> - 4 8 8 1 2. - <_> - 12 9 8 1 2. + 13 10 9 2 2. 0 <_> <_> - 4 8 9 4 -1. + 4 9 2 1 -1. <_> - 4 8 9 2 2. - 1 - <_> - - <_> - 4 8 19 12 -1. - <_> - 4 12 19 4 3. + 5 9 1 1 2. 0 <_> @@ -7378,23 +7666,34 @@ <_> <_> - 4 9 2 2 -1. + 4 9 2 4 -1. <_> - 5 9 1 2 2. + 4 9 1 2 2. + <_> + 5 11 1 2 2. 0 <_> <_> 4 9 3 2 -1. <_> - 5 10 1 2 3. + 4 9 3 1 2. 1 <_> <_> - 4 9 4 6 -1. + 4 9 6 6 -1. <_> - 4 11 4 2 3. + 4 9 3 3 2. + <_> + 7 12 3 3 2. + 0 + <_> + + <_> + 4 9 16 1 -1. + <_> + 8 9 8 1 2. 0 <_> @@ -7405,6 +7704,22 @@ <_> 12 10 8 1 2. 0 + <_> + + <_> + 4 9 18 2 -1. + <_> + 4 9 9 1 2. + <_> + 13 10 9 1 2. + 0 + <_> + + <_> + 4 9 11 4 -1. + <_> + 4 9 11 2 2. + 1 <_> <_> @@ -7431,10 +7746,10 @@ <_> <_> - 4 10 4 4 -1. + 4 10 3 14 -1. <_> - 3 11 4 2 2. - 1 + 5 10 1 14 3. + 0 <_> <_> @@ -7449,6 +7764,20 @@ <_> 4 10 10 2 2. 1 + <_> + + <_> + 4 10 16 6 -1. + <_> + 4 12 16 2 3. + 0 + <_> + + <_> + 4 11 3 1 -1. + <_> + 5 12 1 1 3. + 1 <_> <_> @@ -7459,17 +7788,10 @@ <_> <_> - 4 11 3 6 -1. + 4 11 3 4 -1. <_> - 5 11 1 6 3. + 5 11 1 4 3. 0 - <_> - - <_> - 4 11 3 2 -1. - <_> - 4 11 3 1 2. - 1 <_> <_> @@ -7477,79 +7799,68 @@ <_> 4 16 3 5 2. 0 - <_> - - <_> - 4 11 7 2 -1. - <_> - 4 11 7 1 2. - 1 - <_> - - <_> - 4 11 9 4 -1. - <_> - 4 11 9 2 2. - 1 <_> <_> 4 12 3 1 -1. <_> - 5 12 1 1 3. + 5 13 1 1 3. + 1 + <_> + + <_> + 4 12 3 2 -1. + <_> + 5 12 1 2 3. 0 <_> <_> - 4 12 3 3 -1. + 4 12 1 6 -1. <_> - 5 12 1 3 3. + 4 15 1 3 2. 0 <_> <_> - 4 12 2 6 -1. + 4 12 2 8 -1. <_> - 4 15 2 3 2. + 4 16 2 4 2. 0 <_> <_> - 4 12 16 2 -1. + 4 13 3 1 -1. <_> - 4 12 8 1 2. - <_> - 12 13 8 1 2. + 5 13 1 1 3. 0 <_> <_> - 4 13 4 4 -1. + 4 13 4 3 -1. <_> - 6 13 2 4 2. + 6 13 2 3 2. 0 <_> <_> - 4 13 10 10 -1. + 4 13 9 5 -1. <_> - 4 13 5 5 2. - <_> - 9 18 5 5 2. + 7 13 3 5 3. 0 <_> <_> - 4 14 4 2 -1. + 4 14 4 1 -1. <_> - 6 14 2 2 2. + 6 14 2 1 2. 0 <_> <_> - 4 14 5 4 -1. + 4 15 3 2 -1. <_> - 3 15 5 2 2. + 5 16 1 2 3. 1 <_> @@ -7561,30 +7872,93 @@ <_> <_> - 4 19 3 4 -1. + 4 15 9 4 -1. <_> - 5 19 1 4 3. + 7 15 3 4 3. 0 <_> <_> - 5 0 14 1 -1. + 4 15 4 4 -1. <_> - 12 0 7 1 2. + 4 16 4 2 2. 0 <_> <_> - 5 1 10 8 -1. + 4 17 3 1 -1. <_> - 5 5 10 4 2. + 5 18 1 1 3. + 1 + <_> + + <_> + 4 18 3 6 -1. + <_> + 5 18 1 6 3. 0 <_> <_> - 5 1 12 10 -1. + 4 20 3 4 -1. <_> - 5 6 12 5 2. + 5 20 1 4 3. + 0 + <_> + + <_> + 5 0 6 18 -1. + <_> + 7 0 2 18 3. + 0 + <_> + + <_> + 5 2 4 12 -1. + <_> + 7 2 2 12 2. + 0 + <_> + + <_> + 5 2 14 2 -1. + <_> + 5 2 7 2 2. + 1 + <_> + + <_> + 5 2 15 6 -1. + <_> + 5 5 15 3 2. + 0 + <_> + + <_> + 5 3 1 3 -1. + <_> + 4 4 1 1 3. + 1 + <_> + + <_> + 5 3 2 3 -1. + <_> + 4 4 2 1 3. + 1 + <_> + + <_> + 5 3 4 9 -1. + <_> + 7 3 2 9 2. + 0 + <_> + + <_> + 5 3 9 3 -1. + <_> + 8 4 3 1 9. 0 <_> @@ -7598,41 +7972,18 @@ <_> <_> - 5 3 7 4 -1. + 5 4 2 3 -1. <_> - 4 4 7 2 2. + 4 5 2 1 3. 1 <_> <_> - 5 4 2 2 -1. + 5 4 16 2 -1. <_> - 5 4 2 1 2. - 1 - <_> - + 5 4 8 1 2. <_> - 5 4 14 6 -1. - <_> - 5 4 7 3 2. - <_> - 12 7 7 3 2. - 0 - <_> - - <_> - 5 4 9 4 -1. - <_> - 4 5 9 2 2. - 1 - <_> - - <_> - 5 4 18 8 -1. - <_> - 5 4 9 4 2. - <_> - 14 8 9 4 2. + 13 5 8 1 2. 0 <_> @@ -7641,6 +7992,13 @@ <_> 4 6 1 1 3. 1 + <_> + + <_> + 5 5 4 9 -1. + <_> + 5 8 4 3 3. + 0 <_> <_> @@ -7653,39 +8011,53 @@ <_> <_> - 5 5 14 4 -1. + 5 5 15 6 -1. <_> - 5 5 7 2 2. - <_> - 12 7 7 2 2. + 5 7 15 2 3. 0 <_> <_> - 5 5 14 6 -1. + 5 6 1 2 -1. <_> - 5 7 14 2 3. + 5 7 1 1 2. 0 <_> <_> - 5 5 14 9 -1. + 5 6 4 4 -1. <_> - 5 8 14 3 3. + 5 7 4 2 2. 0 <_> <_> - 5 6 15 8 -1. + 5 6 14 2 -1. <_> - 5 8 15 4 2. + 5 6 7 1 2. + <_> + 12 7 7 1 2. 0 <_> <_> - 5 6 16 6 -1. + 5 6 14 4 -1. <_> - 5 8 16 2 3. + 5 7 14 2 2. + 0 + <_> + + <_> + 5 6 14 6 -1. + <_> + 5 8 14 2 3. + 0 + <_> + + <_> + 5 6 15 4 -1. + <_> + 5 7 15 2 2. 0 <_> @@ -7697,16 +8069,23 @@ <_> <_> - 5 7 3 6 -1. + 5 7 4 15 -1. <_> - 6 9 1 2 9. + 6 7 2 15 2. 0 <_> <_> - 5 7 6 7 -1. + 5 7 4 1 -1. <_> - 7 7 2 7 3. + 7 7 2 1 2. + 0 + <_> + + <_> + 5 7 3 2 -1. + <_> + 5 8 3 1 2. 0 <_> @@ -7715,6 +8094,13 @@ <_> 5 8 3 1 3. 0 + <_> + + <_> + 5 7 3 4 -1. + <_> + 5 8 3 2 2. + 0 <_> <_> @@ -7722,6 +8108,13 @@ <_> 5 9 3 2 3. 0 + <_> + + <_> + 5 7 4 4 -1. + <_> + 5 9 4 2 2. + 0 <_> <_> @@ -7732,16 +8125,25 @@ <_> <_> - 5 7 5 4 -1. + 5 7 16 4 -1. <_> - 4 8 5 2 2. - 1 + 5 7 8 2 2. + <_> + 13 9 8 2 2. + 0 <_> <_> - 5 7 15 6 -1. + 5 7 14 2 -1. <_> - 5 9 15 2 3. + 5 8 14 1 2. + 0 + <_> + + <_> + 5 7 16 6 -1. + <_> + 5 9 16 2 3. 0 <_> @@ -7766,6 +8168,13 @@ <_> 4 9 3 1 3. 1 + <_> + + <_> + 5 8 3 4 -1. + <_> + 4 9 3 2 2. + 1 <_> <_> @@ -7792,16 +8201,18 @@ <_> <_> - 5 8 13 2 -1. + 5 8 16 2 -1. <_> - 5 9 13 1 2. + 5 8 8 1 2. + <_> + 13 9 8 1 2. 0 <_> <_> - 5 8 15 4 -1. + 5 8 13 16 -1. <_> - 5 9 15 2 2. + 5 12 13 8 2. 0 <_> @@ -7813,10 +8224,17 @@ <_> <_> - 5 9 15 2 -1. + 5 9 4 3 -1. <_> - 10 9 5 2 3. + 5 10 4 1 3. 0 + <_> + + <_> + 5 9 4 4 -1. + <_> + 5 9 4 2 2. + 1 <_> <_> @@ -7826,15 +8244,6 @@ <_> 12 10 7 1 2. 0 - <_> - - <_> - 5 9 14 6 -1. - <_> - 5 9 7 3 2. - <_> - 12 12 7 3 2. - 0 <_> <_> @@ -7844,6 +8253,13 @@ <_> 13 10 8 1 2. 0 + <_> + + <_> + 5 9 15 3 -1. + <_> + 5 10 15 1 3. + 0 <_> <_> @@ -7856,9 +8272,23 @@ <_> <_> - 5 10 2 4 -1. + 5 10 3 1 -1. <_> - 6 10 1 4 2. + 6 11 1 1 3. + 1 + <_> + + <_> + 5 10 3 14 -1. + <_> + 6 10 1 14 3. + 0 + <_> + + <_> + 5 10 4 3 -1. + <_> + 7 10 2 3 2. 0 <_> @@ -7870,23 +8300,23 @@ <_> <_> - 5 10 17 4 -1. + 5 10 14 3 -1. <_> - 5 11 17 2 2. + 5 11 14 1 3. 0 <_> <_> - 5 11 3 3 -1. + 5 10 16 8 -1. <_> - 6 11 1 3 3. + 5 12 16 4 2. 0 <_> <_> - 5 11 2 2 -1. + 5 11 3 2 -1. <_> - 5 12 2 1 2. + 6 11 1 2 3. 0 <_> @@ -7898,79 +8328,62 @@ <_> <_> - 5 14 3 3 -1. + 5 12 3 2 -1. <_> - 6 15 1 1 9. + 6 12 1 2 3. 0 <_> <_> - 5 15 4 2 -1. + 5 12 14 2 -1. <_> - 6 16 2 2 2. - 1 - <_> - + 5 12 7 1 2. <_> - 5 15 8 5 -1. - <_> - 7 15 4 5 2. + 12 13 7 1 2. 0 <_> <_> - 5 15 5 3 -1. + 5 13 14 2 -1. <_> - 4 16 5 1 3. - 1 - <_> - + 5 13 7 1 2. <_> - 5 16 4 3 -1. - <_> - 5 17 4 1 3. + 12 14 7 1 2. 0 <_> <_> - 5 16 6 2 -1. + 5 13 14 10 -1. <_> - 5 16 6 1 2. - 1 - <_> - - <_> - 5 17 3 1 -1. - <_> - 6 18 1 1 3. - 1 - <_> - - <_> - 5 20 3 1 -1. - <_> - 6 21 1 1 3. - 1 - <_> - - <_> - 5 20 3 3 -1. - <_> - 6 20 1 3 3. + 5 18 14 5 2. 0 <_> <_> - 5 20 8 3 -1. + 5 15 4 1 -1. <_> - 9 20 4 3 2. + 6 16 2 1 2. + 1 + <_> + + <_> + 5 15 3 2 -1. + <_> + 6 16 1 2 3. + 1 + <_> + + <_> + 5 19 3 4 -1. + <_> + 6 19 1 4 3. 0 <_> <_> - 6 0 10 4 -1. + 5 20 3 4 -1. <_> - 6 1 10 2 2. + 6 20 1 4 3. 0 <_> @@ -7991,10 +8404,31 @@ <_> <_> - 6 2 7 8 -1. + 6 2 1 3 -1. <_> - 6 6 7 4 2. - 0 + 5 3 1 1 3. + 1 + <_> + + <_> + 6 2 4 6 -1. + <_> + 6 2 4 3 2. + 1 + <_> + + <_> + 6 2 12 6 -1. + <_> + 6 2 6 6 2. + 1 + <_> + + <_> + 6 3 1 2 -1. + <_> + 6 3 1 1 2. + 1 <_> <_> @@ -8002,13 +8436,6 @@ <_> 5 4 1 1 3. 1 - <_> - - <_> - 6 3 4 1 -1. - <_> - 7 4 2 1 2. - 1 <_> <_> @@ -8019,10 +8446,38 @@ <_> <_> - 6 4 3 4 -1. + 6 3 18 21 -1. <_> - 6 4 3 2 2. + 15 3 9 21 2. + 0 + <_> + + <_> + 6 4 1 3 -1. + <_> + 5 5 1 1 3. 1 + <_> + + <_> + 6 4 4 3 -1. + <_> + 6 5 4 1 3. + 0 + <_> + + <_> + 6 4 5 4 -1. + <_> + 5 5 5 2 2. + 1 + <_> + + <_> + 6 4 6 3 -1. + <_> + 6 5 6 1 3. + 0 <_> <_> @@ -8040,9 +8495,9 @@ <_> <_> - 6 5 2 9 -1. + 6 5 3 3 -1. <_> - 6 8 2 3 3. + 7 5 1 3 3. 0 <_> @@ -8056,25 +8511,32 @@ <_> <_> - 6 6 3 3 -1. + 6 6 10 2 -1. <_> - 5 7 3 1 3. - 1 - <_> - + 6 6 5 1 2. <_> - 6 6 12 2 -1. - <_> - 6 6 6 1 2. - <_> - 12 7 6 1 2. + 11 7 5 1 2. 0 <_> <_> - 6 6 15 4 -1. + 6 6 5 3 -1. <_> - 6 7 15 2 2. + 5 7 5 1 3. + 1 + <_> + + <_> + 6 7 1 3 -1. + <_> + 6 8 1 1 3. + 0 + <_> + + <_> + 6 7 1 6 -1. + <_> + 6 9 1 2 3. 0 <_> @@ -8090,6 +8552,13 @@ <_> 6 8 2 1 3. 0 + <_> + + <_> + 6 7 3 6 -1. + <_> + 6 9 3 2 3. + 0 <_> <_> @@ -8102,17 +8571,10 @@ <_> <_> - 6 7 9 12 -1. + 6 8 3 1 -1. <_> - 6 13 9 6 2. - 0 - <_> - - <_> - 6 7 13 15 -1. - <_> - 6 12 13 5 3. - 0 + 7 9 1 1 3. + 1 <_> <_> @@ -8120,6 +8582,34 @@ <_> 6 9 2 1 3. 0 + <_> + + <_> + 6 8 2 3 -1. + <_> + 5 9 2 1 3. + 1 + <_> + + <_> + 6 8 3 4 -1. + <_> + 6 9 3 2 2. + 0 + <_> + + <_> + 6 8 3 3 -1. + <_> + 5 9 3 1 3. + 1 + <_> + + <_> + 6 8 12 3 -1. + <_> + 9 8 6 3 2. + 0 <_> <_> @@ -8132,9 +8622,9 @@ <_> <_> - 6 8 12 12 -1. + 6 8 13 6 -1. <_> - 6 11 12 6 2. + 6 10 13 2 3. 0 <_> @@ -8143,27 +8633,6 @@ <_> 6 9 1 2 2. 1 - <_> - - <_> - 6 9 3 6 -1. - <_> - 7 10 1 6 3. - 1 - <_> - - <_> - 6 9 2 3 -1. - <_> - 6 10 2 1 3. - 0 - <_> - - <_> - 6 9 2 4 -1. - <_> - 6 10 2 2 2. - 0 <_> <_> @@ -8204,9 +8673,9 @@ <_> <_> - 6 10 1 2 -1. + 6 9 12 3 -1. <_> - 6 11 1 1 2. + 6 10 12 1 3. 0 <_> @@ -8218,23 +8687,16 @@ <_> <_> - 6 10 3 1 -1. + 6 10 2 3 -1. <_> - 7 11 1 1 3. - 1 - <_> - - <_> - 6 10 2 2 -1. - <_> - 7 10 1 2 2. + 7 10 1 3 2. 0 <_> <_> - 6 10 2 3 -1. + 6 10 2 4 -1. <_> - 7 10 1 3 2. + 7 10 1 4 2. 0 <_> @@ -8243,6 +8705,20 @@ <_> 6 11 2 1 3. 0 + <_> + + <_> + 6 10 2 4 -1. + <_> + 6 11 2 2 2. + 0 + <_> + + <_> + 6 10 3 3 -1. + <_> + 6 11 3 1 3. + 0 <_> <_> @@ -8250,20 +8726,6 @@ <_> 9 10 6 1 2. 0 - <_> - - <_> - 6 10 9 4 -1. - <_> - 9 10 3 4 3. - 0 - <_> - - <_> - 6 10 4 6 -1. - <_> - 4 12 4 2 3. - 1 <_> <_> @@ -8273,6 +8735,27 @@ <_> 12 11 6 1 2. 0 + <_> + + <_> + 6 10 13 3 -1. + <_> + 6 11 13 1 3. + 0 + <_> + + <_> + 6 11 2 3 -1. + <_> + 6 12 2 1 3. + 0 + <_> + + <_> + 6 11 3 2 -1. + <_> + 6 12 3 1 2. + 0 <_> <_> @@ -8283,23 +8766,30 @@ <_> <_> - 6 11 12 6 -1. + 6 11 13 3 -1. <_> - 9 11 6 6 2. + 6 12 13 1 3. 0 <_> <_> - 6 11 13 2 -1. + 6 13 7 4 -1. <_> - 6 12 13 1 2. + 6 13 7 2 2. + 1 + <_> + + <_> + 6 14 1 3 -1. + <_> + 6 15 1 1 3. 0 <_> <_> - 6 14 6 4 -1. + 6 15 3 4 -1. <_> - 5 15 6 2 2. + 7 16 1 4 3. 1 <_> @@ -8311,52 +8801,31 @@ <_> <_> - 6 15 5 4 -1. + 6 18 3 1 -1. <_> - 5 16 5 2 2. + 7 19 1 1 3. 1 <_> <_> - 6 16 3 3 -1. + 6 19 3 5 -1. <_> - 7 17 1 1 9. + 7 19 1 5 3. 0 <_> <_> - 6 16 11 8 -1. + 7 0 3 4 -1. <_> - 6 18 11 4 2. - 0 - <_> - - <_> - 6 17 4 2 -1. - <_> - 7 18 2 2 2. + 7 0 3 2 2. 1 <_> <_> - 6 19 3 3 -1. + 7 0 4 2 -1. <_> - 7 19 1 3 3. - 0 - <_> - - <_> - 6 20 3 1 -1. - <_> - 7 21 1 1 3. + 7 0 4 1 2. 1 - <_> - - <_> - 6 20 7 4 -1. - <_> - 6 22 7 2 2. - 0 <_> <_> @@ -8367,23 +8836,18 @@ <_> <_> - 7 0 9 10 -1. + 7 1 2 6 -1. <_> - 7 5 9 5 2. + 7 1 1 3 2. + <_> + 8 4 1 3 2. 0 <_> <_> - 7 1 9 12 -1. + 7 1 10 1 -1. <_> - 10 5 3 4 9. - 0 - <_> - - <_> - 7 2 1 3 -1. - <_> - 7 3 1 1 3. + 12 1 5 1 2. 0 <_> @@ -8395,9 +8859,30 @@ <_> <_> - 7 2 11 10 -1. + 7 2 1 4 -1. <_> - 7 7 11 5 2. + 6 3 1 2 2. + 1 + <_> + + <_> + 7 2 3 4 -1. + <_> + 6 3 3 2 2. + 1 + <_> + + <_> + 7 2 6 3 -1. + <_> + 7 3 6 1 3. + 0 + <_> + + <_> + 7 2 13 10 -1. + <_> + 7 7 13 5 2. 0 <_> @@ -8409,10 +8894,24 @@ <_> <_> - 7 3 1 6 -1. + 7 3 2 4 -1. <_> - 5 5 1 2 3. + 6 4 2 2 2. 1 + <_> + + <_> + 7 3 4 2 -1. + <_> + 7 3 4 1 2. + 1 + <_> + + <_> + 7 4 3 3 -1. + <_> + 8 4 1 3 3. + 0 <_> <_> @@ -8429,13 +8928,6 @@ <_> 8 5 1 2 3. 0 - <_> - - <_> - 7 5 2 3 -1. - <_> - 8 5 1 3 2. - 0 <_> <_> @@ -8446,30 +8938,30 @@ <_> <_> - 7 5 3 6 -1. + 7 5 3 5 -1. <_> - 8 5 1 6 3. + 8 5 1 5 3. 0 <_> <_> - 7 5 9 17 -1. + 7 6 3 1 -1. <_> - 10 5 3 17 3. + 8 6 1 1 3. 0 <_> <_> - 7 5 4 4 -1. + 7 6 1 4 -1. <_> - 6 6 4 2 2. + 7 6 1 2 2. 1 <_> <_> - 7 5 5 3 -1. + 7 6 6 10 -1. <_> - 7 6 5 1 3. + 9 6 2 10 3. 0 <_> @@ -8480,6 +8972,13 @@ <_> 12 7 5 1 2. 0 + <_> + + <_> + 7 6 5 3 -1. + <_> + 6 7 5 1 3. + 1 <_> <_> @@ -8490,37 +8989,25 @@ <_> <_> - 7 7 4 4 -1. + 7 7 1 3 -1. <_> - 8 8 2 4 2. - 1 - <_> - - <_> - 7 7 2 4 -1. - <_> - 7 9 2 2 2. + 7 8 1 1 3. 0 <_> <_> - 7 7 5 6 -1. + 7 7 2 2 -1. <_> - 5 9 5 2 3. - 1 + 7 7 1 1 2. + <_> + 8 8 1 1 2. + 0 <_> <_> - 7 7 6 4 -1. + 7 8 1 3 -1. <_> - 6 8 6 2 2. - 1 - <_> - - <_> - 7 7 6 12 -1. - <_> - 7 13 6 6 2. + 7 9 1 1 3. 0 <_> @@ -8534,16 +9021,16 @@ <_> <_> - 7 8 4 4 -1. + 7 8 2 2 -1. <_> - 8 8 2 4 2. - 0 + 7 8 1 2 2. + 1 <_> <_> - 7 8 2 4 -1. + 7 8 12 7 -1. <_> - 7 9 2 2 2. + 11 8 4 7 3. 0 <_> @@ -8564,9 +9051,16 @@ <_> <_> - 7 9 6 3 -1. + 7 9 2 3 -1. <_> - 9 9 2 3 3. + 7 9 1 3 2. + 1 + <_> + + <_> + 7 9 2 3 -1. + <_> + 7 10 2 1 3. 0 <_> @@ -8577,13 +9071,6 @@ <_> 10 14 3 5 2. 0 - <_> - - <_> - 7 9 12 2 -1. - <_> - 11 9 4 2 3. - 0 <_> <_> @@ -8593,15 +9080,6 @@ <_> 12 10 5 1 2. 0 - <_> - - <_> - 7 9 10 4 -1. - <_> - 7 9 5 2 2. - <_> - 12 11 5 2 2. - 0 <_> <_> @@ -8616,13 +9094,6 @@ <_> 7 11 1 1 3. 0 - <_> - - <_> - 7 10 4 3 -1. - <_> - 8 10 2 3 2. - 0 <_> <_> @@ -8633,32 +9104,16 @@ <_> <_> - 7 10 4 4 -1. + 7 10 6 5 -1. <_> - 9 10 2 4 2. + 9 10 2 5 3. 0 <_> <_> - 7 10 6 4 -1. + 7 10 9 4 -1. <_> - 9 10 2 4 3. - 0 - <_> - - <_> - 7 10 6 8 -1. - <_> - 7 10 3 4 2. - <_> - 10 14 3 4 2. - 0 - <_> - - <_> - 7 10 12 5 -1. - <_> - 11 10 4 5 3. + 10 10 3 4 3. 0 <_> @@ -8672,24 +9127,38 @@ <_> <_> - 7 11 3 12 -1. + 7 11 1 2 -1. <_> - 8 11 1 12 3. + 7 12 1 1 2. 0 <_> <_> - 7 13 9 3 -1. + 7 15 5 4 -1. <_> - 10 13 3 3 3. - 0 + 6 16 5 2 2. + 1 <_> <_> - 7 14 1 3 -1. + 7 16 6 2 -1. <_> - 7 15 1 1 3. - 0 + 9 18 2 2 3. + 1 + <_> + + <_> + 7 16 4 2 -1. + <_> + 7 16 4 1 2. + 1 + <_> + + <_> + 7 16 4 4 -1. + <_> + 6 17 4 2 2. + 1 <_> <_> @@ -8700,9 +9169,23 @@ <_> <_> - 7 17 4 2 -1. + 7 17 1 4 -1. <_> - 8 18 2 2 2. + 7 19 1 2 2. + 0 + <_> + + <_> + 7 17 3 6 -1. + <_> + 7 20 3 3 2. + 0 + <_> + + <_> + 7 17 4 3 -1. + <_> + 6 18 4 1 3. 1 <_> @@ -8714,9 +9197,23 @@ <_> <_> - 7 18 3 6 -1. + 7 18 3 1 -1. <_> - 8 18 1 6 3. + 8 19 1 1 3. + 1 + <_> + + <_> + 7 19 3 1 -1. + <_> + 8 20 1 1 3. + 1 + <_> + + <_> + 7 19 3 5 -1. + <_> + 8 19 1 5 3. 0 <_> @@ -8728,23 +9225,53 @@ <_> <_> - 7 20 7 4 -1. + 7 20 9 4 -1. <_> - 7 22 7 2 2. + 7 22 9 2 2. 0 <_> <_> - 8 0 5 4 -1. + 7 20 10 4 -1. <_> - 8 2 5 2 2. + 7 21 10 2 2. 0 <_> <_> - 8 0 7 10 -1. + 7 20 10 4 -1. <_> - 8 5 7 5 2. + 7 22 10 2 2. + 0 + <_> + + <_> + 8 0 8 1 -1. + <_> + 12 0 4 1 2. + 0 + <_> + + <_> + 8 0 7 4 -1. + <_> + 8 2 7 2 2. + 0 + <_> + + <_> + 8 0 16 6 -1. + <_> + 8 0 8 3 2. + <_> + 16 3 8 3 2. + 0 + <_> + + <_> + 8 0 8 10 -1. + <_> + 8 5 8 5 2. 0 <_> @@ -8758,11 +9285,9 @@ <_> <_> - 8 0 16 12 -1. + 8 0 9 4 -1. <_> - 8 0 8 6 2. - <_> - 16 6 8 6 2. + 8 1 9 2 2. 0 <_> @@ -8774,53 +9299,44 @@ <_> <_> - 8 1 3 6 -1. + 8 1 8 8 -1. <_> - 8 1 3 3 2. - 1 - <_> - - <_> - 8 1 8 2 -1. - <_> - 12 1 4 2 2. + 8 5 8 4 2. 0 <_> <_> - 8 1 16 6 -1. + 8 1 12 10 -1. <_> - 6 3 16 2 3. - 1 - <_> - - <_> - 8 2 8 2 -1. - <_> - 8 2 4 1 2. - <_> - 12 3 4 1 2. + 8 6 12 5 2. 0 <_> <_> - 8 3 2 6 -1. + 8 2 3 3 -1. <_> - 6 5 2 2 3. - 1 - <_> - - <_> - 8 4 3 9 -1. - <_> - 9 4 1 9 3. + 9 2 1 3 3. 0 <_> <_> - 8 4 4 3 -1. + 8 2 2 4 -1. <_> - 8 5 4 1 3. + 7 3 2 2 2. + 1 + <_> + + <_> + 8 2 2 6 -1. + <_> + 6 4 2 2 3. + 1 + <_> + + <_> + 8 3 3 8 -1. + <_> + 9 3 1 8 3. 0 <_> @@ -8831,6 +9347,13 @@ <_> 12 5 4 1 2. 0 + <_> + + <_> + 8 4 7 15 -1. + <_> + 8 9 7 5 3. + 0 <_> <_> @@ -8841,30 +9364,16 @@ <_> <_> - 8 5 2 2 -1. + 8 5 3 2 -1. <_> - 9 5 1 2 2. + 9 5 1 2 3. 0 <_> <_> - 8 5 4 3 -1. + 8 5 2 5 -1. <_> - 9 5 2 3 2. - 0 - <_> - - <_> - 8 5 3 4 -1. - <_> - 9 5 1 4 3. - 0 - <_> - - <_> - 8 5 3 5 -1. - <_> - 9 5 1 5 3. + 9 5 1 5 2. 0 <_> @@ -8892,8 +9401,22 @@ <_> 8 5 3 7 -1. <_> - 9 5 1 7 3. + 9 6 1 7 3. + 1 + <_> + + <_> + 8 5 3 8 -1. + <_> + 9 5 1 8 3. 0 + <_> + + <_> + 8 5 3 6 -1. + <_> + 8 5 3 3 2. + 1 <_> <_> @@ -8901,6 +9424,15 @@ <_> 6 7 4 2 3. 1 + <_> + + <_> + 8 5 10 2 -1. + <_> + 8 5 5 1 2. + <_> + 13 6 5 1 2. + 0 <_> <_> @@ -8911,18 +9443,23 @@ <_> <_> - 8 6 4 2 -1. + 8 6 3 6 -1. <_> - 8 6 2 1 2. - <_> - 10 7 2 1 2. + 9 6 1 6 3. 0 + <_> + + <_> + 8 6 3 4 -1. + <_> + 7 7 3 2 2. + 1 <_> <_> 8 6 4 2 -1. <_> - 8 6 2 2 2. + 8 6 4 1 2. 1 <_> @@ -8938,20 +9475,15 @@ <_> 7 7 4 2 2. 1 - <_> - - <_> - 8 6 5 4 -1. - <_> - 7 7 5 2 2. - 1 <_> <_> 8 6 10 2 -1. <_> - 8 6 10 1 2. - 1 + 8 6 5 1 2. + <_> + 13 7 5 1 2. + 0 <_> <_> @@ -8966,6 +9498,20 @@ <_> 7 8 3 2 2. 1 + <_> + + <_> + 8 7 9 5 -1. + <_> + 11 10 3 5 3. + 1 + <_> + + <_> + 8 7 9 8 -1. + <_> + 11 10 3 8 3. + 1 <_> <_> @@ -8990,46 +9536,25 @@ <_> <_> - 8 7 8 4 -1. + 8 7 8 2 -1. <_> - 7 8 8 2 2. + 8 7 8 1 2. 1 + <_> + + <_> + 8 7 10 12 -1. + <_> + 8 13 10 6 2. + 0 <_> <_> 8 8 2 2 -1. <_> - 8 8 1 2 2. - 1 - <_> - + 8 8 1 1 2. <_> - 8 8 2 3 -1. - <_> - 7 9 2 1 3. - 1 - <_> - - <_> - 8 8 8 5 -1. - <_> - 10 10 4 5 2. - 1 - <_> - - <_> - 8 9 3 3 -1. - <_> - 9 9 1 3 3. - 0 - <_> - - <_> - 8 9 10 2 -1. - <_> - 8 9 5 1 2. - <_> - 13 10 5 1 2. + 9 9 1 1 2. 0 <_> @@ -9045,6 +9570,15 @@ <_> 9 10 1 1 3. 0 + <_> + + <_> + 8 10 2 2 -1. + <_> + 8 10 1 1 2. + <_> + 9 11 1 1 2. + 0 <_> <_> @@ -9052,6 +9586,13 @@ <_> 9 10 1 2 2. 0 + <_> + + <_> + 8 10 3 2 -1. + <_> + 9 10 1 2 3. + 0 <_> <_> @@ -9073,26 +9614,47 @@ <_> <_> - 8 11 6 5 -1. + 8 10 15 12 -1. <_> - 10 11 2 5 3. + 13 14 5 4 9. 0 <_> <_> - 8 11 4 10 -1. + 8 11 2 2 -1. <_> - 8 11 2 5 2. + 8 11 1 1 2. <_> - 10 16 2 5 2. + 9 12 1 1 2. 0 <_> <_> - 8 13 7 4 -1. + 8 13 9 3 -1. <_> - 8 13 7 2 2. - 1 + 11 13 3 3 3. + 0 + <_> + + <_> + 8 15 9 6 -1. + <_> + 11 15 3 6 3. + 0 + <_> + + <_> + 8 15 8 6 -1. + <_> + 8 17 8 2 3. + 0 + <_> + + <_> + 8 16 8 2 -1. + <_> + 10 16 4 2 2. + 0 <_> <_> @@ -9103,44 +9665,16 @@ <_> <_> - 8 16 9 3 -1. + 8 17 3 3 -1. <_> - 11 16 3 3 3. - 0 + 9 18 1 3 3. + 1 <_> <_> - 8 17 3 7 -1. + 8 17 8 3 -1. <_> - 9 17 1 7 3. - 0 - <_> - - <_> - 8 17 8 2 -1. - <_> - 10 17 4 2 2. - 0 - <_> - - <_> - 8 17 9 1 -1. - <_> - 11 17 3 1 3. - 0 - <_> - - <_> - 8 17 9 7 -1. - <_> - 11 17 3 7 3. - 0 - <_> - - <_> - 8 17 8 6 -1. - <_> - 8 20 8 3 2. + 10 17 4 3 2. 0 <_> @@ -9149,13 +9683,6 @@ <_> 8 19 9 2 3. 0 - <_> - - <_> - 8 18 3 2 -1. - <_> - 9 19 1 2 3. - 1 <_> <_> @@ -9163,13 +9690,6 @@ <_> 9 18 1 6 3. 0 - <_> - - <_> - 8 18 8 6 -1. - <_> - 8 20 8 2 3. - 0 <_> <_> @@ -9180,30 +9700,67 @@ <_> <_> - 8 19 8 3 -1. + 8 19 3 4 -1. <_> - 8 20 8 1 3. + 9 19 1 4 3. 0 <_> <_> - 8 20 8 4 -1. + 8 19 7 3 -1. <_> - 8 21 8 2 2. + 8 20 7 1 3. 0 <_> <_> - 9 0 2 2 -1. + 8 19 9 4 -1. <_> - 9 1 2 1 2. + 8 20 9 2 2. 0 <_> <_> - 9 0 6 1 -1. + 8 20 3 3 -1. <_> - 12 0 3 1 2. + 9 20 1 3 3. + 0 + <_> + + <_> + 8 20 16 4 -1. + <_> + 8 20 8 2 2. + <_> + 16 22 8 2 2. + 0 + <_> + + <_> + 8 21 3 3 -1. + <_> + 9 21 1 3 3. + 0 + <_> + + <_> + 9 0 1 2 -1. + <_> + 9 1 1 1 2. + 0 + <_> + + <_> + 9 0 3 6 -1. + <_> + 7 2 3 2 3. + 1 + <_> + + <_> + 9 0 6 3 -1. + <_> + 12 0 3 3 2. 0 <_> @@ -9215,55 +9772,53 @@ <_> <_> - 9 0 6 2 -1. + 9 0 8 9 -1. <_> - 9 1 6 1 2. + 9 0 4 9 2. + 1 + <_> + + <_> + 9 0 5 4 -1. + <_> + 9 2 5 2 2. 0 <_> <_> - 9 0 6 8 -1. + 9 0 5 8 -1. <_> - 9 4 6 4 2. + 9 4 5 4 2. 0 <_> <_> - 9 0 7 4 -1. + 9 0 14 12 -1. <_> - 9 2 7 2 2. + 9 0 7 6 2. + <_> + 16 6 7 6 2. 0 <_> <_> - 9 0 11 4 -1. + 9 0 8 10 -1. <_> - 9 1 11 2 2. + 9 5 8 5 2. 0 <_> <_> - 9 1 2 3 -1. + 9 0 15 18 -1. <_> - 10 1 1 3 2. + 9 6 15 6 3. 0 <_> <_> - 9 1 2 6 -1. + 9 1 2 8 -1. <_> - 9 1 1 3 2. - <_> - 10 4 1 3 2. - 0 - <_> - - <_> - 9 1 6 2 -1. - <_> - 9 1 3 1 2. - <_> - 12 2 3 1 2. + 9 5 2 4 2. 0 <_> @@ -9275,40 +9830,89 @@ <_> <_> - 9 2 2 4 -1. + 9 2 2 2 -1. <_> - 10 2 1 4 2. + 10 2 1 2 2. 0 <_> <_> - 9 2 6 8 -1. + 9 2 1 6 -1. <_> - 11 2 2 8 3. + 9 5 1 3 2. 0 <_> <_> - 9 3 1 6 -1. + 9 2 3 10 -1. <_> - 7 5 1 2 3. + 10 2 1 10 3. + 0 + <_> + + <_> + 9 2 8 4 -1. + <_> + 11 4 4 4 2. 1 <_> <_> - 9 4 2 9 -1. + 9 2 6 2 -1. <_> - 10 4 1 9 2. + 9 2 3 1 2. + <_> + 12 3 3 1 2. 0 <_> <_> - 9 4 8 2 -1. + 9 2 7 8 -1. <_> - 9 4 4 1 2. - <_> - 13 5 4 1 2. + 9 6 7 4 2. 0 + <_> + + <_> + 9 3 3 7 -1. + <_> + 10 4 1 7 3. + 1 + <_> + + <_> + 9 3 3 12 -1. + <_> + 10 3 1 12 3. + 0 + <_> + + <_> + 9 3 6 7 -1. + <_> + 11 3 2 7 3. + 0 + <_> + + <_> + 9 3 12 3 -1. + <_> + 13 4 4 1 9. + 0 + <_> + + <_> + 9 3 11 4 -1. + <_> + 8 4 11 2 2. + 1 + <_> + + <_> + 9 4 3 8 -1. + <_> + 10 5 1 8 3. + 1 <_> <_> @@ -9326,10 +9930,24 @@ <_> <_> - 9 5 3 9 -1. + 9 5 3 6 -1. <_> - 10 6 1 9 3. - 1 + 10 5 1 6 3. + 0 + <_> + + <_> + 9 5 6 4 -1. + <_> + 11 5 2 4 3. + 0 + <_> + + <_> + 9 5 3 3 -1. + <_> + 9 6 3 1 3. + 0 <_> <_> @@ -9337,6 +9955,13 @@ <_> 8 6 4 1 3. 1 + <_> + + <_> + 9 6 3 2 -1. + <_> + 10 7 1 2 3. + 1 <_> <_> @@ -9347,23 +9972,23 @@ <_> <_> - 9 6 3 3 -1. + 9 6 4 3 -1. <_> - 9 7 3 1 3. + 9 7 4 1 3. 0 <_> <_> - 9 7 1 2 -1. + 9 6 4 3 -1. <_> - 9 7 1 1 2. + 8 7 4 1 3. 1 <_> <_> - 9 7 2 2 -1. + 9 7 2 3 -1. <_> - 9 7 1 2 2. + 9 7 1 3 2. 1 <_> @@ -9375,16 +10000,18 @@ <_> <_> - 9 7 2 4 -1. + 9 7 6 2 -1. <_> - 8 8 2 2 2. - 1 + 9 7 3 1 2. + <_> + 12 8 3 1 2. + 0 <_> <_> - 9 7 3 3 -1. + 9 8 2 3 -1. <_> - 8 8 3 1 3. + 8 9 2 1 3. 1 <_> @@ -9403,74 +10030,90 @@ <_> <_> - 9 9 2 7 -1. + 9 8 9 9 -1. <_> - 10 9 1 7 2. + 12 8 3 9 3. 0 <_> <_> - 9 9 2 3 -1. + 9 9 2 12 -1. <_> - 9 10 2 1 3. + 9 9 1 6 2. + <_> + 10 15 1 6 2. 0 <_> <_> - 9 9 15 2 -1. + 9 9 6 3 -1. <_> - 9 10 15 1 2. + 11 11 2 3 3. + 1 + <_> + + <_> + 9 9 6 4 -1. + <_> + 11 11 2 4 3. + 1 + <_> + + <_> + 9 9 3 3 -1. + <_> + 9 10 3 1 3. 0 <_> <_> - 9 10 4 8 -1. + 9 9 6 4 -1. <_> - 10 10 2 8 2. + 12 9 3 4 2. 0 <_> <_> - 9 11 4 3 -1. + 9 10 3 3 -1. <_> - 9 12 4 1 3. + 9 11 3 1 3. 0 <_> <_> - 9 12 4 8 -1. + 9 10 5 3 -1. <_> - 9 12 2 4 2. - <_> - 11 16 2 4 2. + 9 11 5 1 3. 0 <_> <_> - 9 12 9 4 -1. + 9 10 14 3 -1. <_> - 12 12 3 4 3. + 9 11 14 1 3. 0 <_> <_> - 9 16 4 1 -1. + 9 13 4 6 -1. <_> - 11 16 2 1 2. + 9 13 2 3 2. + <_> + 11 16 2 3 2. 0 <_> <_> - 9 16 6 4 -1. + 9 13 9 4 -1. <_> - 11 16 2 4 3. + 12 13 3 4 3. 0 <_> <_> - 9 16 6 4 -1. + 9 16 6 5 -1. <_> - 9 17 6 2 2. + 11 16 2 5 3. 0 <_> @@ -9496,37 +10139,30 @@ <_> <_> - 9 19 3 5 -1. + 9 19 6 3 -1. <_> - 10 19 1 5 3. + 9 20 6 1 3. 0 <_> <_> - 9 19 6 4 -1. + 9 19 7 3 -1. <_> - 9 20 6 2 2. + 9 20 7 1 3. 0 <_> <_> - 9 20 3 1 -1. + 9 20 3 3 -1. <_> - 10 21 1 1 3. - 1 - <_> - - <_> - 9 20 5 4 -1. - <_> - 9 21 5 2 2. + 10 20 1 3 3. 0 <_> <_> - 9 20 5 4 -1. + 9 20 5 3 -1. <_> - 9 22 5 2 2. + 9 21 5 1 3. 0 <_> @@ -9535,13 +10171,6 @@ <_> 9 21 6 1 3. 0 - <_> - - <_> - 9 20 12 2 -1. - <_> - 15 20 6 2 2. - 0 <_> <_> @@ -9554,7 +10183,7 @@ <_> 9 20 7 4 -1. <_> - 9 21 7 2 2. + 9 22 7 2 2. 0 <_> @@ -9566,47 +10195,31 @@ <_> <_> - 9 21 4 3 -1. + 9 21 8 2 -1. <_> - 10 21 2 3 2. + 9 22 8 1 2. 0 <_> <_> - 9 22 3 2 -1. + 10 0 4 1 -1. <_> - 10 22 1 2 3. + 12 0 2 1 2. 0 <_> <_> - 10 0 1 2 -1. + 10 0 3 12 -1. <_> - 10 0 1 1 2. - 1 - <_> - - <_> - 10 0 4 2 -1. - <_> - 10 0 2 1 2. - <_> - 12 1 2 1 2. + 10 4 3 4 3. 0 <_> <_> - 10 0 6 8 -1. + 10 0 4 8 -1. <_> - 12 2 2 8 3. - 1 - <_> - - <_> - 10 0 6 10 -1. - <_> - 10 0 3 10 2. - 1 + 10 4 4 4 2. + 0 <_> <_> @@ -9619,74 +10232,23 @@ <_> <_> - 10 1 4 1 -1. + 10 2 4 6 -1. <_> - 12 1 2 1 2. + 11 2 2 6 2. 0 <_> <_> - 10 1 9 9 -1. + 10 2 6 10 -1. <_> - 13 4 3 9 3. + 10 2 3 10 2. 1 <_> <_> - 10 1 12 2 -1. + 10 3 2 5 -1. <_> - 14 1 4 2 3. - 0 - <_> - - <_> - 10 1 14 8 -1. - <_> - 10 1 7 4 2. - <_> - 17 5 7 4 2. - 0 - <_> - - <_> - 10 2 1 6 -1. - <_> - 8 4 1 2 3. - 1 - <_> - - <_> - 10 2 10 10 -1. - <_> - 10 7 10 5 2. - 0 - <_> - - <_> - 10 3 2 12 -1. - <_> - 11 3 1 12 2. - 0 - <_> - - <_> - 10 3 9 3 -1. - <_> - 13 4 3 1 9. - 0 - <_> - - <_> - 10 3 14 2 -1. - <_> - 17 3 7 2 2. - 0 - <_> - - <_> - 10 4 3 4 -1. - <_> - 11 4 1 4 3. + 11 3 1 5 2. 0 <_> @@ -9698,129 +10260,66 @@ <_> <_> - 10 4 3 6 -1. + 10 4 4 19 -1. <_> - 11 4 1 6 3. + 12 4 2 19 2. 0 <_> <_> - 10 4 4 10 -1. + 10 5 1 2 -1. <_> - 12 4 2 10 2. - 0 - <_> - - <_> - 10 4 9 3 -1. - <_> - 13 4 3 3 3. - 0 - <_> - - <_> - 10 5 2 6 -1. - <_> - 11 5 1 6 2. - 0 - <_> - - <_> - 10 5 6 3 -1. - <_> - 10 6 6 1 3. - 0 - <_> - - <_> - 10 5 14 9 -1. - <_> - 10 8 14 3 3. - 0 - <_> - - <_> - 10 6 3 3 -1. - <_> - 11 6 1 3 3. - 0 - <_> - - <_> - 10 6 2 4 -1. - <_> - 11 6 1 4 2. - 0 - <_> - - <_> - 10 6 2 3 -1. - <_> - 10 7 2 1 3. - 0 - <_> - - <_> - 10 6 3 3 -1. - <_> - 10 7 3 1 3. - 0 - <_> - - <_> - 10 6 3 4 -1. - <_> - 10 6 3 2 2. + 10 5 1 1 2. 1 <_> <_> - 10 6 6 7 -1. + 10 5 4 3 -1. <_> - 13 6 3 7 2. + 11 5 2 3 2. 0 <_> <_> - 10 6 4 3 -1. + 10 5 3 3 -1. <_> - 10 7 4 1 3. + 10 6 3 1 3. 0 <_> <_> - 10 7 2 3 -1. + 10 6 1 3 -1. <_> - 10 8 2 1 3. + 10 7 1 1 3. 0 <_> <_> - 10 7 6 6 -1. + 10 6 4 6 -1. <_> - 12 9 2 6 3. + 12 6 2 6 2. + 0 + <_> + + <_> + 10 7 4 3 -1. + <_> + 10 8 4 1 3. + 0 + <_> + + <_> + 10 8 1 2 -1. + <_> + 10 8 1 1 2. 1 <_> <_> - 10 7 3 3 -1. + 10 8 2 2 -1. <_> - 10 8 3 1 3. + 10 9 2 1 2. 0 - <_> - - <_> - 10 8 6 4 -1. - <_> - 12 10 2 4 3. - 1 - <_> - - <_> - 10 8 6 10 -1. - <_> - 12 10 2 10 3. - 1 <_> <_> @@ -9831,9 +10330,25 @@ <_> <_> - 10 9 2 7 -1. + 10 9 2 3 -1. <_> - 11 9 1 7 2. + 11 9 1 3 2. + 0 + <_> + + <_> + 10 9 2 12 -1. + <_> + 10 9 1 6 2. + <_> + 11 15 1 6 2. + 0 + <_> + + <_> + 10 9 2 3 -1. + <_> + 10 10 2 1 3. 0 <_> @@ -9842,48 +10357,6 @@ <_> 9 10 2 1 3. 1 - <_> - - <_> - 10 9 8 6 -1. - <_> - 12 9 4 6 2. - 0 - <_> - - <_> - 10 9 4 3 -1. - <_> - 10 10 4 1 3. - 0 - <_> - - <_> - 10 10 1 3 -1. - <_> - 10 11 1 1 3. - 0 - <_> - - <_> - 10 10 4 5 -1. - <_> - 11 11 2 5 2. - 1 - <_> - - <_> - 10 10 2 3 -1. - <_> - 10 11 2 1 3. - 0 - <_> - - <_> - 10 10 6 7 -1. - <_> - 12 12 2 7 3. - 1 <_> <_> @@ -9894,23 +10367,46 @@ <_> <_> - 10 15 4 2 -1. + 10 11 5 3 -1. <_> - 11 15 2 2 2. + 10 12 5 1 3. 0 <_> <_> - 10 15 6 3 -1. + 10 12 14 3 -1. <_> - 12 15 2 3 3. + 10 13 14 1 3. 0 <_> <_> - 10 15 5 3 -1. + 10 17 4 2 -1. <_> - 10 16 5 1 3. + 11 17 2 2 2. + 0 + <_> + + <_> + 10 17 2 6 -1. + <_> + 10 17 1 3 2. + <_> + 11 20 1 3 2. + 0 + <_> + + <_> + 10 17 3 3 -1. + <_> + 10 18 3 1 3. + 0 + <_> + + <_> + 10 17 6 2 -1. + <_> + 13 17 3 2 2. 0 <_> @@ -9922,9 +10418,16 @@ <_> <_> - 10 19 4 4 -1. + 10 19 5 4 -1. <_> - 10 20 4 2 2. + 10 20 5 2 2. + 0 + <_> + + <_> + 10 19 6 3 -1. + <_> + 10 20 6 1 3. 0 <_> @@ -9936,30 +10439,46 @@ <_> <_> - 10 20 3 4 -1. + 10 20 6 4 -1. <_> - 10 21 3 2 2. + 12 20 2 4 3. 0 <_> <_> - 10 20 7 4 -1. + 10 20 5 4 -1. <_> - 10 22 7 2 2. + 10 21 5 2 2. 0 <_> <_> - 10 21 3 1 -1. + 10 20 5 4 -1. <_> - 11 21 1 1 3. + 10 22 5 2 2. 0 <_> <_> - 10 22 3 1 -1. + 10 20 14 4 -1. <_> - 11 22 1 1 3. + 10 20 7 2 2. + <_> + 17 22 7 2 2. + 0 + <_> + + <_> + 10 21 3 3 -1. + <_> + 11 21 1 3 3. + 0 + <_> + + <_> + 10 21 5 2 -1. + <_> + 10 22 5 1 2. 0 <_> @@ -9978,88 +10497,86 @@ <_> <_> - 11 0 12 10 -1. + 11 0 1 2 -1. <_> - 11 0 6 5 2. + 11 0 1 1 2. + 1 + <_> + <_> - 17 5 6 5 2. + 11 0 1 4 -1. + <_> + 10 1 1 2 2. + 1 + <_> + + <_> + 11 0 4 1 -1. + <_> + 13 0 2 1 2. 0 <_> <_> - 11 1 3 6 -1. + 11 1 1 2 -1. <_> - 12 1 1 6 3. + 11 1 1 1 2. + 1 + <_> + + <_> + 11 2 8 9 -1. + <_> + 13 4 4 9 2. + 1 + <_> + + <_> + 11 3 3 3 -1. + <_> + 12 3 1 3 3. 0 <_> <_> - 11 1 6 1 -1. + 11 3 3 4 -1. <_> - 13 1 2 1 3. + 12 3 1 4 3. 0 <_> <_> - 11 1 7 10 -1. + 11 4 3 4 -1. <_> - 11 6 7 5 2. + 12 4 1 4 3. 0 <_> <_> - 11 2 3 4 -1. + 11 4 3 5 -1. <_> - 12 2 1 4 3. + 12 4 1 5 3. 0 <_> <_> - 11 2 2 11 -1. + 11 4 3 7 -1. <_> - 12 2 1 11 2. + 12 5 1 7 3. + 1 + <_> + + <_> + 11 4 4 1 -1. + <_> + 13 4 2 1 2. 0 <_> <_> - 11 2 4 14 -1. + 11 4 2 3 -1. <_> - 13 2 2 14 2. - 0 - <_> - - <_> - 11 2 4 22 -1. - <_> - 13 2 2 22 2. - 0 - <_> - - <_> - 11 3 3 5 -1. - <_> - 12 3 1 5 3. - 0 - <_> - - <_> - 11 3 2 3 -1. - <_> - 11 4 2 1 3. - 0 - <_> - - <_> - 11 3 6 9 -1. - <_> - 13 6 2 3 9. - 0 - <_> - - <_> - 11 4 3 3 -1. - <_> - 11 5 3 1 3. + 11 5 2 1 3. 0 <_> @@ -10071,30 +10588,16 @@ <_> <_> - 11 4 4 8 -1. + 11 5 3 1 -1. <_> - 11 4 4 4 2. - 1 - <_> - - <_> - 11 5 3 2 -1. - <_> - 12 5 1 2 3. + 12 5 1 1 3. 0 <_> <_> - 11 5 4 6 -1. + 11 5 4 11 -1. <_> - 12 5 2 6 2. - 0 - <_> - - <_> - 11 6 4 5 -1. - <_> - 12 6 2 5 2. + 13 5 2 11 2. 0 <_> @@ -10110,27 +10613,6 @@ <_> 11 7 4 1 3. 0 - <_> - - <_> - 11 6 4 8 -1. - <_> - 11 6 4 4 2. - 1 - <_> - - <_> - 11 6 5 3 -1. - <_> - 11 7 5 1 3. - 0 - <_> - - <_> - 11 6 6 3 -1. - <_> - 11 7 6 1 3. - 0 <_> <_> @@ -10148,10 +10630,24 @@ <_> <_> - 11 7 6 9 -1. + 11 7 2 6 -1. <_> - 13 7 2 9 3. + 11 7 2 3 2. + 1 + <_> + + <_> + 11 7 3 3 -1. + <_> + 11 8 3 1 3. 0 + <_> + + <_> + 11 7 3 8 -1. + <_> + 11 7 3 4 2. + 1 <_> <_> @@ -10169,45 +10665,40 @@ <_> <_> - 11 8 6 9 -1. + 11 9 3 3 -1. <_> - 13 10 2 9 3. + 11 10 3 1 3. + 0 + <_> + + <_> + 11 10 4 5 -1. + <_> + 12 11 2 5 2. 1 <_> <_> - 11 8 3 2 -1. + 11 10 6 3 -1. <_> - 11 9 3 1 2. + 13 10 2 3 3. 0 <_> <_> - 11 8 3 3 -1. + 11 10 6 8 -1. <_> - 11 9 3 1 3. + 11 10 3 4 2. + <_> + 14 14 3 4 2. 0 <_> <_> - 11 9 1 3 -1. + 11 10 8 6 -1. <_> - 11 10 1 1 3. - 0 - <_> - - <_> - 11 10 6 4 -1. - <_> - 13 10 2 4 3. - 0 - <_> - - <_> - 11 10 4 3 -1. - <_> - 11 11 4 1 3. - 0 + 9 12 8 2 3. + 1 <_> <_> @@ -10218,60 +10709,16 @@ <_> <_> - 11 12 9 9 -1. + 11 14 3 3 -1. <_> - 14 15 3 3 9. - 0 + 10 15 3 1 3. + 1 <_> <_> - 11 14 4 2 -1. + 11 16 3 3 -1. <_> - 13 14 2 2 2. - 0 - <_> - - <_> - 11 16 4 8 -1. - <_> - 11 18 4 4 2. - 0 - <_> - - <_> - 11 18 12 6 -1. - <_> - 11 18 6 3 2. - <_> - 17 21 6 3 2. - 0 - <_> - - <_> - 11 20 3 1 -1. - <_> - 12 20 1 1 3. - 0 - <_> - - <_> - 11 20 3 4 -1. - <_> - 12 20 1 4 3. - 0 - <_> - - <_> - 11 20 4 4 -1. - <_> - 11 22 4 2 2. - 0 - <_> - - <_> - 11 21 3 1 -1. - <_> - 12 21 1 1 3. + 11 17 3 1 3. 0 <_> @@ -10283,61 +10730,45 @@ <_> <_> - 11 22 4 2 -1. + 11 22 3 2 -1. <_> - 12 22 2 2 2. + 12 22 1 2 3. 0 <_> <_> - 12 0 12 2 -1. + 12 0 9 17 -1. <_> - 15 0 6 2 2. + 15 0 3 17 3. 0 <_> <_> - 12 0 6 6 -1. + 12 2 2 14 -1. <_> - 12 0 3 6 2. - 1 - <_> - - <_> - 12 0 12 10 -1. - <_> - 12 0 6 5 2. - <_> - 18 5 6 5 2. + 13 2 1 14 2. 0 <_> <_> - 12 1 4 10 -1. + 12 3 6 1 -1. <_> - 13 1 2 10 2. - 0 - <_> - - <_> - 12 2 2 3 -1. - <_> - 12 3 2 1 3. + 14 3 2 1 3. 0 <_> <_> 12 3 8 3 -1. <_> - 14 3 4 3 2. + 12 4 8 1 3. 0 <_> <_> - 12 3 9 3 -1. + 12 3 12 6 -1. <_> - 12 4 9 1 3. - 0 + 10 5 12 2 3. + 1 <_> <_> @@ -10348,45 +10779,31 @@ <_> <_> - 12 5 2 2 -1. + 12 4 9 3 -1. <_> - 13 5 1 2 2. + 15 5 3 1 9. 0 <_> <_> - 12 5 3 2 -1. + 12 5 3 5 -1. <_> - 13 5 1 2 3. + 13 5 1 5 3. 0 <_> <_> - 12 5 2 5 -1. + 12 5 3 3 -1. <_> - 13 5 1 5 2. + 12 6 3 1 3. 0 <_> <_> - 12 5 4 6 -1. + 12 5 9 8 -1. <_> - 13 5 2 6 2. + 15 5 3 8 3. 0 - <_> - - <_> - 12 5 6 7 -1. - <_> - 14 5 2 7 3. - 0 - <_> - - <_> - 12 5 3 8 -1. - <_> - 12 5 3 4 2. - 1 <_> <_> @@ -10397,31 +10814,17 @@ <_> <_> - 12 6 1 4 -1. + 12 6 2 8 -1. <_> - 12 7 1 2 2. - 0 - <_> - - <_> - 12 6 1 8 -1. - <_> - 12 6 1 4 2. + 12 6 2 4 2. 1 <_> <_> - 12 6 2 10 -1. + 12 6 3 3 -1. <_> - 13 6 1 10 2. + 12 7 3 1 3. 0 - <_> - - <_> - 12 6 8 1 -1. - <_> - 12 6 4 1 2. - 1 <_> <_> @@ -10432,16 +10835,30 @@ <_> <_> - 12 7 2 3 -1. + 12 7 1 8 -1. <_> - 12 8 2 1 3. - 0 + 12 7 1 4 2. + 1 <_> <_> - 12 7 4 3 -1. + 12 7 2 6 -1. <_> - 12 8 4 1 3. + 12 7 2 3 2. + 1 + <_> + + <_> + 12 7 2 8 -1. + <_> + 12 7 2 4 2. + 1 + <_> + + <_> + 12 7 3 3 -1. + <_> + 12 8 3 1 3. 0 <_> @@ -10457,22 +10874,6 @@ <_> 12 9 2 1 3. 0 - <_> - - <_> - 12 8 6 8 -1. - <_> - 12 8 3 4 2. - <_> - 15 12 3 4 2. - 0 - <_> - - <_> - 12 9 1 3 -1. - <_> - 12 10 1 1 3. - 0 <_> <_> @@ -10480,6 +10881,13 @@ <_> 12 10 2 1 3. 0 + <_> + + <_> + 12 10 6 4 -1. + <_> + 14 10 2 4 3. + 0 <_> <_> @@ -10489,13 +10897,6 @@ <_> 14 15 2 5 2. 0 - <_> - - <_> - 12 10 3 3 -1. - <_> - 12 11 3 1 3. - 0 <_> <_> @@ -10508,30 +10909,53 @@ <_> <_> - 12 16 4 4 -1. + 12 13 4 3 -1. <_> - 14 16 2 4 2. + 13 13 2 3 2. 0 <_> <_> - 12 17 6 6 -1. + 12 14 3 2 -1. <_> - 12 20 6 3 2. + 13 15 1 2 3. + 1 + <_> + + <_> + 12 15 2 4 -1. + <_> + 12 15 1 2 2. + <_> + 13 17 1 2 2. 0 <_> <_> - 12 18 3 4 -1. + 12 15 4 5 -1. <_> - 12 19 3 2 2. + 14 15 2 5 2. 0 <_> <_> - 12 19 3 4 -1. + 12 16 6 2 -1. <_> - 13 19 1 4 3. + 14 16 2 2 3. + 0 + <_> + + <_> + 12 19 3 5 -1. + <_> + 13 19 1 5 3. + 0 + <_> + + <_> + 12 21 3 2 -1. + <_> + 13 21 1 2 3. 0 <_> @@ -10540,6 +10964,43 @@ <_> 13 21 1 3 3. 0 + <_> + + <_> + 13 0 2 10 -1. + <_> + 13 0 1 5 2. + <_> + 14 5 1 5 2. + 0 + <_> + + <_> + 13 0 4 12 -1. + <_> + 14 0 2 12 2. + 0 + <_> + + <_> + 13 0 6 10 -1. + <_> + 15 0 2 10 3. + 0 + <_> + + <_> + 13 0 11 8 -1. + <_> + 11 2 11 4 2. + 1 + <_> + + <_> + 13 1 6 8 -1. + <_> + 15 1 2 8 3. + 0 <_> <_> @@ -10550,88 +11011,74 @@ <_> <_> - 13 2 2 6 -1. + 13 3 2 4 -1. <_> - 13 2 1 3 2. + 13 3 1 2 2. <_> - 14 5 1 3 2. + 14 5 1 2 2. 0 <_> <_> - 13 2 2 10 -1. + 13 3 6 3 -1. <_> - 14 2 1 10 2. + 15 4 2 1 9. 0 <_> <_> - 13 2 2 14 -1. + 13 4 4 7 -1. <_> - 14 2 1 14 2. + 14 4 2 7 2. 0 <_> <_> - 13 2 8 6 -1. + 13 4 3 8 -1. <_> - 15 2 4 6 2. + 14 4 1 8 3. 0 <_> <_> - 13 2 6 7 -1. + 13 5 3 2 -1. <_> - 15 2 2 7 3. + 14 5 1 2 3. 0 <_> <_> - 13 3 4 8 -1. + 13 5 3 5 -1. <_> - 14 3 2 8 2. + 14 5 1 5 3. 0 <_> <_> - 13 4 3 7 -1. + 13 5 3 6 -1. <_> - 14 4 1 7 3. + 14 5 1 6 3. 0 <_> <_> - 13 4 8 2 -1. + 13 5 3 8 -1. <_> - 15 4 4 2 2. + 14 5 1 8 3. 0 <_> <_> - 13 4 4 3 -1. + 13 5 6 1 -1. <_> - 13 5 4 1 3. + 15 5 2 1 3. 0 <_> <_> - 13 5 6 6 -1. + 13 6 7 4 -1. <_> - 15 5 2 6 3. - 0 - <_> - - <_> - 13 6 1 3 -1. - <_> - 13 7 1 1 3. - 0 - <_> - - <_> - 13 6 6 6 -1. - <_> - 15 6 2 6 3. + 13 7 7 2 2. 0 <_> @@ -10643,10 +11090,12 @@ <_> <_> - 13 7 1 8 -1. + 13 7 4 8 -1. <_> - 13 7 1 4 2. - 1 + 13 7 2 4 2. + <_> + 15 11 2 4 2. + 0 <_> <_> @@ -10664,9 +11113,23 @@ <_> <_> - 13 8 6 5 -1. + 13 7 8 1 -1. <_> - 15 8 2 5 3. + 13 7 4 1 2. + 1 + <_> + + <_> + 13 8 2 3 -1. + <_> + 13 9 2 1 3. + 0 + <_> + + <_> + 13 8 9 3 -1. + <_> + 16 9 3 1 9. 0 <_> @@ -10680,16 +11143,30 @@ <_> <_> - 13 9 3 3 -1. + 13 9 2 3 -1. <_> - 14 9 1 3 3. + 13 10 2 1 3. 0 <_> <_> - 13 9 2 3 -1. + 13 9 6 4 -1. <_> - 13 10 2 1 3. + 15 9 2 4 3. + 0 + <_> + + <_> + 13 9 10 2 -1. + <_> + 13 10 10 1 2. + 0 + <_> + + <_> + 13 10 3 1 -1. + <_> + 14 10 1 1 3. 0 <_> @@ -10701,46 +11178,32 @@ <_> <_> - 13 11 4 8 -1. + 13 11 2 3 -1. <_> - 13 11 2 4 2. - <_> - 15 15 2 4 2. + 13 12 2 1 3. 0 <_> <_> - 13 12 8 5 -1. + 13 13 2 6 -1. <_> - 15 12 4 5 2. + 13 13 1 3 2. + <_> + 14 16 1 3 2. 0 <_> <_> - 13 13 7 3 -1. + 13 13 4 6 -1. <_> - 13 14 7 1 3. - 0 + 14 14 2 6 2. + 1 <_> <_> - 13 14 4 1 -1. + 13 20 3 4 -1. <_> - 14 14 2 1 2. - 0 - <_> - - <_> - 13 17 3 7 -1. - <_> - 14 17 1 7 3. - 0 - <_> - - <_> - 13 21 3 3 -1. - <_> - 14 21 1 3 3. + 14 20 1 4 3. 0 <_> @@ -10749,6 +11212,27 @@ <_> 14 22 1 2 3. 0 + <_> + + <_> + 13 23 3 1 -1. + <_> + 14 23 1 1 3. + 0 + <_> + + <_> + 14 0 3 11 -1. + <_> + 15 1 1 11 3. + 1 + <_> + + <_> + 14 0 2 3 -1. + <_> + 14 1 2 1 3. + 0 <_> <_> @@ -10770,51 +11254,62 @@ <_> <_> - 14 0 10 9 -1. + 14 1 10 6 -1. <_> - 11 3 10 3 3. + 14 1 5 3 2. + <_> + 19 4 5 3 2. + 0 + <_> + + <_> + 14 2 1 2 -1. + <_> + 14 2 1 1 2. 1 <_> <_> - 14 1 1 8 -1. + 14 2 3 8 -1. <_> - 14 5 1 4 2. + 15 2 1 8 3. 0 <_> <_> - 14 2 10 2 -1. + 14 2 6 7 -1. <_> - 19 2 5 2 2. + 16 2 2 7 3. 0 <_> <_> - 14 3 2 8 -1. + 14 3 2 4 -1. <_> - 15 3 1 8 2. + 14 3 1 2 2. + <_> + 15 5 1 2 2. 0 <_> <_> - 14 4 3 3 -1. + 14 3 2 7 -1. <_> - 15 4 1 3 3. + 15 3 1 7 2. 0 <_> <_> - 14 4 3 4 -1. + 14 5 3 2 -1. <_> - 15 4 1 4 3. + 15 5 1 2 3. 0 <_> <_> - 14 4 8 3 -1. + 14 5 2 3 -1. <_> - 14 5 8 1 3. + 15 5 1 3 2. 0 <_> @@ -10833,30 +11328,30 @@ <_> <_> - 14 6 3 5 -1. + 14 5 2 7 -1. <_> - 15 6 1 5 3. + 15 5 1 7 2. 0 <_> <_> - 14 6 6 17 -1. + 14 5 6 4 -1. <_> - 16 6 2 17 3. + 16 5 2 4 3. 0 <_> <_> - 14 6 8 2 -1. + 14 6 6 3 -1. <_> - 14 6 4 2 2. + 14 6 3 3 2. 1 <_> <_> - 14 7 4 3 -1. + 14 7 4 16 -1. <_> - 15 7 2 3 2. + 15 7 2 16 2. 0 <_> @@ -10868,38 +11363,26 @@ <_> <_> - 14 8 6 3 -1. + 14 7 6 16 -1. <_> - 16 9 2 1 9. + 16 7 2 16 3. 0 <_> <_> - 14 8 6 1 -1. + 14 7 9 4 -1. <_> - 14 8 3 1 2. - 1 - <_> - - <_> - 14 8 6 2 -1. - <_> - 14 8 3 2 2. - 1 - <_> - - <_> - 14 9 4 1 -1. - <_> - 16 9 2 1 2. + 14 8 9 2 2. 0 <_> <_> - 14 9 6 6 -1. + 14 9 2 4 -1. <_> - 12 11 6 2 3. - 1 + 14 9 1 2 2. + <_> + 15 11 1 2 2. + 0 <_> <_> @@ -10917,70 +11400,94 @@ <_> <_> - 14 10 2 6 -1. + 14 10 3 3 -1. <_> - 14 10 1 3 2. - <_> - 15 13 1 3 2. + 15 10 1 3 3. 0 <_> <_> - 14 15 1 2 -1. + 14 12 2 1 -1. <_> - 14 15 1 1 2. + 15 12 1 1 2. + 0 + <_> + + <_> + 14 14 3 4 -1. + <_> + 15 15 1 4 3. 1 <_> <_> - 14 16 8 8 -1. + 14 14 5 3 -1. <_> - 14 16 4 4 2. - <_> - 18 20 4 4 2. + 14 15 5 1 3. 0 <_> <_> - 14 17 9 3 -1. + 14 15 3 3 -1. <_> - 14 18 9 1 3. - 0 - <_> - - <_> - 14 20 3 4 -1. - <_> - 15 20 1 4 3. - 0 - <_> - - <_> - 15 0 3 1 -1. - <_> - 16 1 1 1 3. + 15 16 1 3 3. 1 <_> <_> - 15 0 4 13 -1. + 14 19 3 5 -1. <_> - 16 1 2 13 2. - 1 - <_> - - <_> - 15 1 3 4 -1. - <_> - 15 3 3 2 2. + 15 19 1 5 3. 0 <_> <_> - 15 3 2 2 -1. + 14 21 10 1 -1. <_> - 15 3 2 1 2. + 19 21 5 1 2. + 0 + <_> + + <_> + 15 0 2 2 -1. + <_> + 15 0 1 2 2. 1 + <_> + + <_> + 15 0 4 2 -1. + <_> + 16 1 2 2 2. + 1 + <_> + + <_> + 15 3 6 3 -1. + <_> + 15 4 6 1 3. + 0 + <_> + + <_> + 15 4 2 3 -1. + <_> + 15 5 2 1 3. + 0 + <_> + + <_> + 15 5 2 1 -1. + <_> + 15 5 1 1 2. + 1 + <_> + + <_> + 15 5 2 2 -1. + <_> + 16 5 1 2 2. + 0 <_> <_> @@ -10998,39 +11505,16 @@ <_> <_> - 15 5 2 7 -1. + 15 7 4 4 -1. <_> - 16 5 1 7 2. + 15 9 4 2 2. 0 <_> <_> - 15 5 4 2 -1. + 15 7 4 6 -1. <_> - 15 5 2 1 2. - <_> - 17 6 2 1 2. - 0 - <_> - - <_> - 15 5 5 6 -1. - <_> - 15 7 5 2 3. - 0 - <_> - - <_> - 15 6 3 2 -1. - <_> - 16 7 1 2 3. - 1 - <_> - - <_> - 15 6 3 5 -1. - <_> - 16 6 1 5 3. + 15 9 4 2 3. 0 <_> @@ -11048,6 +11532,27 @@ <_> 16 9 1 1 2. 0 + <_> + + <_> + 15 8 2 1 -1. + <_> + 15 8 1 1 2. + 1 + <_> + + <_> + 15 8 1 12 -1. + <_> + 15 14 1 6 2. + 0 + <_> + + <_> + 15 8 6 2 -1. + <_> + 15 8 3 2 2. + 1 <_> <_> @@ -11058,9 +11563,9 @@ <_> <_> - 15 8 4 4 -1. + 15 8 5 4 -1. <_> - 15 9 4 2 2. + 15 9 5 2 2. 0 <_> @@ -11076,20 +11581,6 @@ <_> 16 10 1 1 3. 1 - <_> - - <_> - 15 9 1 10 -1. - <_> - 15 14 1 5 2. - 0 - <_> - - <_> - 15 10 2 1 -1. - <_> - 16 10 1 1 2. - 0 <_> <_> @@ -11097,6 +11588,22 @@ <_> 16 10 1 1 3. 0 + <_> + + <_> + 15 10 2 2 -1. + <_> + 15 10 1 1 2. + <_> + 16 11 1 1 2. + 0 + <_> + + <_> + 15 10 2 2 -1. + <_> + 16 10 1 2 2. + 0 <_> <_> @@ -11107,81 +11614,55 @@ <_> <_> - 15 10 4 4 -1. + 15 10 3 4 -1. <_> - 14 11 4 2 2. + 14 11 3 2 2. 1 <_> <_> - 15 11 7 4 -1. + 15 10 5 4 -1. <_> - 14 12 7 2 2. + 15 11 5 2 2. + 0 + <_> + + <_> + 15 10 5 4 -1. + <_> + 14 11 5 2 2. 1 <_> <_> - 15 12 6 6 -1. + 15 15 8 3 -1. <_> - 17 14 2 6 3. - 1 - <_> - - <_> - 15 13 3 4 -1. - <_> - 16 14 1 4 3. - 1 - <_> - - <_> - 15 13 3 11 -1. - <_> - 16 13 1 11 3. + 19 15 4 3 2. 0 <_> <_> - 15 13 2 3 -1. + 15 15 8 8 -1. <_> - 15 14 2 1 3. + 15 15 4 4 2. + <_> + 19 19 4 4 2. 0 <_> <_> - 15 14 1 8 -1. + 15 16 5 3 -1. <_> - 15 16 1 4 2. + 15 17 5 1 3. 0 <_> <_> - 15 14 8 10 -1. + 15 18 8 6 -1. <_> - 15 14 4 5 2. + 15 18 4 3 2. <_> - 19 19 4 5 2. - 0 - <_> - - <_> - 15 15 4 3 -1. - <_> - 15 16 4 1 3. - 0 - <_> - - <_> - 15 16 8 2 -1. - <_> - 19 16 4 2 2. - 0 - <_> - - <_> - 15 16 6 3 -1. - <_> - 15 17 6 1 3. + 19 21 4 3 2. 0 <_> @@ -11215,15 +11696,6 @@ <_> 20 4 4 4 2. 0 - <_> - - <_> - 16 0 8 16 -1. - <_> - 16 0 4 8 2. - <_> - 20 8 4 8 2. - 0 <_> <_> @@ -11234,9 +11706,30 @@ <_> <_> - 16 1 6 2 -1. + 16 1 2 1 -1. <_> - 18 3 2 2 3. + 16 1 1 1 2. + 1 + <_> + + <_> + 16 2 1 2 -1. + <_> + 16 3 1 1 2. + 0 + <_> + + <_> + 16 2 3 3 -1. + <_> + 17 3 1 1 9. + 0 + <_> + + <_> + 16 2 4 2 -1. + <_> + 17 3 2 2 2. 1 <_> @@ -11248,30 +11741,51 @@ <_> <_> - 16 2 4 3 -1. + 16 3 4 12 -1. <_> - 16 3 4 1 3. + 17 4 2 12 2. + 1 + <_> + + <_> + 16 4 6 3 -1. + <_> + 15 5 6 1 3. + 1 + <_> + + <_> + 16 5 1 2 -1. + <_> + 16 5 1 1 2. + 1 + <_> + + <_> + 16 5 3 2 -1. + <_> + 17 5 1 2 3. 0 <_> <_> - 16 2 4 8 -1. + 16 5 3 9 -1. <_> - 14 4 4 4 2. + 16 8 3 3 3. + 0 + <_> + + <_> + 16 6 6 2 -1. + <_> + 18 8 2 2 3. 1 <_> <_> - 16 6 3 3 -1. + 16 7 1 6 -1. <_> - 17 7 1 3 3. - 1 - <_> - - <_> - 16 6 4 4 -1. - <_> - 18 6 2 4 2. + 16 9 1 2 3. 0 <_> @@ -11280,13 +11794,6 @@ <_> 16 8 2 1 3. 0 - <_> - - <_> - 16 7 2 4 -1. - <_> - 16 8 2 2 2. - 0 <_> <_> @@ -11294,15 +11801,6 @@ <_> 16 7 2 1 2. 1 - <_> - - <_> - 16 7 4 10 -1. - <_> - 16 7 2 5 2. - <_> - 18 12 2 5 2. - 0 <_> <_> @@ -11313,10 +11811,10 @@ <_> <_> - 16 7 3 3 -1. + 16 7 3 2 -1. <_> - 16 8 3 1 3. - 0 + 16 7 3 1 2. + 1 <_> <_> @@ -11327,9 +11825,30 @@ <_> <_> - 16 7 4 6 -1. + 16 7 6 4 -1. <_> - 16 9 4 2 3. + 16 7 3 4 2. + 1 + <_> + + <_> + 16 7 4 3 -1. + <_> + 16 8 4 1 3. + 0 + <_> + + <_> + 16 7 5 3 -1. + <_> + 16 8 5 1 3. + 0 + <_> + + <_> + 16 7 5 6 -1. + <_> + 16 9 5 2 3. 0 <_> @@ -11341,9 +11860,16 @@ <_> <_> - 16 7 7 4 -1. + 16 7 7 8 -1. <_> - 16 8 7 2 2. + 14 9 7 4 2. + 1 + <_> + + <_> + 16 7 8 6 -1. + <_> + 16 9 8 2 3. 0 <_> @@ -11359,6 +11885,15 @@ <_> 16 9 1 2 2. 0 + <_> + + <_> + 16 8 2 2 -1. + <_> + 16 8 1 1 2. + <_> + 17 9 1 1 2. + 0 <_> <_> @@ -11369,9 +11904,9 @@ <_> <_> - 16 8 3 1 -1. + 16 8 2 1 -1. <_> - 17 9 1 1 3. + 16 8 1 1 2. 1 <_> @@ -11383,32 +11918,23 @@ <_> <_> - 16 8 2 4 -1. + 16 8 5 6 -1. <_> - 16 9 2 2 2. - 0 + 14 10 5 2 3. + 1 <_> <_> - 16 8 3 4 -1. + 16 8 7 8 -1. <_> - 16 9 3 2 2. - 0 + 14 10 7 4 2. + 1 <_> <_> - 16 8 3 16 -1. + 16 9 3 1 -1. <_> - 16 12 3 8 2. - 0 - <_> - - <_> - 16 8 8 2 -1. - <_> - 16 8 4 1 2. - <_> - 20 9 4 1 2. + 17 9 1 1 3. 0 <_> @@ -11420,37 +11946,16 @@ <_> <_> - 16 9 3 6 -1. + 16 9 5 3 -1. <_> - 14 11 3 2 3. - 1 + 16 10 5 1 3. + 0 <_> <_> - 16 9 5 6 -1. + 16 9 8 2 -1. <_> - 14 11 5 2 3. - 1 - <_> - - <_> - 16 9 6 6 -1. - <_> - 14 11 6 2 3. - 1 - <_> - - <_> - 16 9 8 6 -1. - <_> - 14 11 8 2 3. - 1 - <_> - - <_> - 16 10 1 2 -1. - <_> - 16 11 1 1 2. + 16 10 8 1 2. 0 <_> @@ -11459,6 +11964,13 @@ <_> 16 11 1 1 3. 0 + <_> + + <_> + 16 10 2 2 -1. + <_> + 17 10 1 2 2. + 0 <_> <_> @@ -11469,23 +11981,16 @@ <_> <_> - 16 10 3 3 -1. + 16 10 6 6 -1. <_> - 16 11 3 1 3. - 0 + 14 12 6 2 3. + 1 <_> <_> - 16 10 5 2 -1. + 16 11 3 1 -1. <_> - 16 11 5 1 2. - 0 - <_> - - <_> - 16 10 6 8 -1. - <_> - 16 12 6 4 2. + 17 11 1 1 3. 0 <_> @@ -11494,6 +11999,13 @@ <_> 17 11 1 2 3. 0 + <_> + + <_> + 16 11 3 13 -1. + <_> + 17 11 1 13 3. + 0 <_> <_> @@ -11504,39 +12016,37 @@ <_> <_> - 16 11 3 2 -1. + 16 11 2 3 -1. <_> - 16 12 3 1 2. + 16 12 2 1 3. 0 <_> <_> - 16 14 8 10 -1. + 16 11 3 3 -1. <_> - 16 14 4 5 2. - <_> - 20 19 4 5 2. + 16 12 3 1 3. 0 <_> <_> - 16 16 8 2 -1. + 16 14 4 2 -1. <_> - 20 16 4 2 2. + 18 14 2 2 2. 0 <_> <_> - 16 18 3 6 -1. + 16 14 6 3 -1. <_> - 17 18 1 6 3. + 19 14 3 3 2. 0 <_> <_> - 16 18 8 3 -1. + 16 19 3 5 -1. <_> - 20 18 4 3 2. + 17 19 1 5 3. 0 <_> @@ -11548,59 +12058,73 @@ <_> <_> - 16 20 1 3 -1. + 16 19 8 3 -1. <_> - 15 21 1 1 3. - 1 - <_> - - <_> - 17 1 6 2 -1. - <_> - 17 1 3 2 2. - 1 - <_> - - <_> - 17 3 3 1 -1. - <_> - 18 3 1 1 3. + 16 20 8 1 3. 0 <_> <_> - 17 3 2 3 -1. + 17 0 6 15 -1. <_> - 17 4 2 1 3. - 0 - <_> - - <_> - 17 3 6 3 -1. - <_> - 19 5 2 3 3. + 19 2 2 15 3. 1 <_> <_> - 17 3 3 3 -1. + 17 0 6 1 -1. <_> - 17 4 3 1 3. + 20 0 3 1 2. 0 <_> <_> - 17 3 7 3 -1. + 17 0 6 2 -1. <_> - 17 4 7 1 3. + 20 0 3 2 2. 0 <_> <_> - 17 4 4 2 -1. + 17 2 3 3 -1. <_> - 18 5 2 2 2. + 18 3 1 1 9. + 0 + <_> + + <_> + 17 3 3 2 -1. + <_> + 18 3 1 2 3. + 0 + <_> + + <_> + 17 3 3 9 -1. + <_> + 18 6 1 3 9. + 0 + <_> + + <_> + 17 3 6 2 -1. + <_> + 19 5 2 2 3. 1 + <_> + + <_> + 17 3 3 8 -1. + <_> + 15 5 3 4 2. + 1 + <_> + + <_> + 17 3 5 3 -1. + <_> + 17 4 5 1 3. + 0 <_> <_> @@ -11610,20 +12134,6 @@ <_> 18 7 1 3 2. 0 - <_> - - <_> - 17 4 6 5 -1. - <_> - 19 6 2 5 3. - 1 - <_> - - <_> - 17 4 7 16 -1. - <_> - 17 8 7 8 2. - 0 <_> <_> @@ -11641,10 +12151,24 @@ <_> <_> - 17 6 1 9 -1. + 17 5 6 2 -1. <_> - 17 9 1 3 3. - 0 + 17 5 3 2 2. + 1 + <_> + + <_> + 17 5 7 3 -1. + <_> + 16 6 7 1 3. + 1 + <_> + + <_> + 17 6 2 3 -1. + <_> + 17 6 1 3 2. + 1 <_> <_> @@ -11652,13 +12176,6 @@ <_> 18 7 1 4 3. 1 - <_> - - <_> - 17 6 6 3 -1. - <_> - 19 8 2 3 3. - 1 <_> <_> @@ -11666,6 +12183,13 @@ <_> 17 7 3 1 3. 0 + <_> + + <_> + 17 6 6 1 -1. + <_> + 17 6 3 1 2. + 1 <_> <_> @@ -11673,6 +12197,13 @@ <_> 17 8 1 1 3. 0 + <_> + + <_> + 17 7 1 3 -1. + <_> + 16 8 1 1 3. + 1 <_> <_> @@ -11680,6 +12211,27 @@ <_> 17 9 1 2 3. 0 + <_> + + <_> + 17 7 3 6 -1. + <_> + 18 9 1 2 9. + 0 + <_> + + <_> + 17 7 3 2 -1. + <_> + 18 8 1 2 3. + 1 + <_> + + <_> + 17 7 2 3 -1. + <_> + 17 7 1 3 2. + 1 <_> <_> @@ -11690,68 +12242,17 @@ <_> <_> - 17 7 4 5 -1. + 17 7 2 3 -1. <_> - 18 8 2 5 2. + 17 8 2 1 3. + 0 + <_> + + <_> + 17 7 6 9 -1. + <_> + 14 10 6 3 3. 1 - <_> - - <_> - 17 7 4 9 -1. - <_> - 18 8 2 9 2. - 1 - <_> - - <_> - 17 7 2 2 -1. - <_> - 17 8 2 1 2. - 0 - <_> - - <_> - 17 7 3 2 -1. - <_> - 17 8 3 1 2. - 0 - <_> - - <_> - 17 7 3 3 -1. - <_> - 17 8 3 1 3. - 0 - <_> - - <_> - 17 7 3 2 -1. - <_> - 17 7 3 1 2. - 1 - <_> - - <_> - 17 7 5 2 -1. - <_> - 17 8 5 1 2. - 0 - <_> - - <_> - 17 7 5 4 -1. - <_> - 17 8 5 2 2. - 0 - <_> - - <_> - 17 8 2 2 -1. - <_> - 17 8 1 1 2. - <_> - 18 9 1 1 2. - 0 <_> <_> @@ -11762,23 +12263,73 @@ <_> <_> - 17 8 6 9 -1. + 17 8 2 4 -1. <_> - 20 8 3 9 2. + 17 8 1 2 2. + <_> + 18 10 1 2 2. 0 <_> <_> - 17 8 7 8 -1. + 17 8 2 8 -1. <_> - 15 10 7 4 2. + 17 8 1 4 2. + <_> + 18 12 1 4 2. + 0 + <_> + + <_> + 17 8 3 4 -1. + <_> + 18 9 1 4 3. 1 <_> <_> - 17 9 3 3 -1. + 17 8 4 6 -1. <_> - 18 10 1 1 9. + 15 10 4 2 3. + 1 + <_> + + <_> + 17 9 3 1 -1. + <_> + 18 9 1 1 3. + 0 + <_> + + <_> + 17 9 2 6 -1. + <_> + 17 9 1 3 2. + <_> + 18 12 1 3 2. + 0 + <_> + + <_> + 17 9 6 10 -1. + <_> + 17 9 3 5 2. + <_> + 20 14 3 5 2. + 0 + <_> + + <_> + 17 9 7 2 -1. + <_> + 17 10 7 1 2. + 0 + <_> + + <_> + 17 10 3 1 -1. + <_> + 18 10 1 1 3. 0 <_> @@ -11790,44 +12341,25 @@ <_> <_> - 17 10 4 1 -1. + 17 10 2 3 -1. <_> - 19 10 2 1 2. + 18 10 1 3 2. 0 <_> <_> 17 10 2 4 -1. <_> - 17 11 2 2 2. + 18 10 1 4 2. 0 <_> <_> - 17 10 2 2 -1. + 17 10 4 2 -1. <_> - 17 10 2 1 2. - 1 - <_> - + 17 10 2 1 2. <_> - 17 10 4 4 -1. - <_> - 17 11 4 2 2. - 0 - <_> - - <_> - 17 10 4 8 -1. - <_> - 17 12 4 4 2. - 0 - <_> - - <_> - 17 11 2 2 -1. - <_> - 18 11 1 2 2. + 19 11 2 1 2. 0 <_> @@ -11853,67 +12385,123 @@ <_> <_> - 17 14 1 3 -1. + 17 12 6 2 -1. <_> - 17 15 1 1 3. + 20 12 3 2 2. 0 <_> <_> - 17 14 2 2 -1. + 17 15 2 3 -1. <_> - 17 14 1 1 2. - <_> - 18 15 1 1 2. + 17 16 2 1 3. 0 <_> <_> - 17 14 4 4 -1. + 17 15 4 3 -1. <_> - 19 14 2 4 2. + 19 15 2 3 2. 0 <_> <_> - 17 15 4 2 -1. + 17 15 4 4 -1. <_> - 19 15 2 2 2. - 0 - <_> - - <_> - 17 17 2 4 -1. - <_> - 17 17 2 2 2. + 17 15 2 4 2. 1 <_> <_> - 18 0 4 1 -1. + 17 18 2 4 -1. <_> - 20 0 2 1 2. + 16 19 2 2 2. + 1 + <_> + + <_> + 17 18 5 3 -1. + <_> + 17 19 5 1 3. 0 <_> <_> - 18 3 3 1 -1. + 17 19 1 3 -1. + <_> + 16 20 1 1 3. + 1 + <_> + + <_> + 17 20 1 3 -1. + <_> + 16 21 1 1 3. + 1 + <_> + + <_> + 17 20 3 4 -1. + <_> + 18 20 1 4 3. + 0 + <_> + + <_> + 18 0 2 2 -1. + <_> + 18 0 1 2 2. + 1 + <_> + + <_> + 18 0 6 1 -1. + <_> + 21 0 3 1 2. + 0 + <_> + + <_> + 18 0 6 5 -1. + <_> + 21 0 3 5 2. + 0 + <_> + + <_> + 18 0 6 12 -1. + <_> + 18 0 3 6 2. + <_> + 21 6 3 6 2. + 0 + <_> + + <_> + 18 2 3 1 -1. <_> 19 3 1 1 3. - 0 - <_> - - <_> - 18 4 6 5 -1. - <_> - 20 6 2 5 3. 1 <_> <_> - 18 4 6 19 -1. + 18 2 4 1 -1. <_> - 21 4 3 19 2. + 19 3 2 1 2. + 1 + <_> + + <_> + 18 2 4 3 -1. + <_> + 19 3 2 3 2. + 1 + <_> + + <_> + 18 4 4 3 -1. + <_> + 18 5 4 1 3. 0 <_> @@ -11925,23 +12513,16 @@ <_> <_> - 18 5 4 9 -1. + 18 6 2 3 -1. <_> - 19 6 2 9 2. + 18 6 1 3 2. 1 <_> <_> - 18 6 2 4 -1. + 18 6 4 3 -1. <_> - 18 6 1 4 2. - 1 - <_> - - <_> - 18 6 3 4 -1. - <_> - 19 7 1 4 3. + 19 7 2 3 2. 1 <_> @@ -11953,44 +12534,51 @@ <_> <_> - 18 6 4 5 -1. + 18 6 2 5 -1. <_> - 19 7 2 5 2. + 18 6 1 5 2. + 1 + <_> + + <_> + 18 6 4 6 -1. + <_> + 19 7 2 6 2. 1 <_> <_> 18 6 2 3 -1. <_> - 17 7 2 1 3. + 18 7 2 1 3. + 0 + <_> + + <_> + 18 6 4 1 -1. + <_> + 18 6 2 1 2. 1 <_> <_> - 18 6 3 3 -1. + 18 6 5 3 -1. <_> - 18 7 3 1 3. + 18 7 5 1 3. 0 <_> <_> - 18 6 4 3 -1. + 18 6 6 3 -1. <_> - 18 7 4 1 3. + 18 7 6 1 3. 0 <_> <_> - 18 7 1 3 -1. + 18 7 3 2 -1. <_> - 18 8 1 1 3. - 0 - <_> - - <_> - 18 7 3 4 -1. - <_> - 19 8 1 4 3. + 19 8 1 2 3. 1 <_> @@ -12002,30 +12590,16 @@ <_> <_> - 18 7 3 6 -1. + 18 8 1 3 -1. <_> - 19 8 1 6 3. - 1 - <_> - - <_> - 18 7 2 3 -1. - <_> - 18 8 2 1 3. + 18 9 1 1 3. 0 <_> <_> - 18 7 2 2 -1. + 18 8 2 3 -1. <_> - 18 7 2 1 2. - 1 - <_> - - <_> - 18 7 3 3 -1. - <_> - 18 8 3 1 3. + 18 9 2 1 3. 0 <_> @@ -12034,20 +12608,6 @@ <_> 18 8 2 1 2. 1 - <_> - - <_> - 18 8 3 9 -1. - <_> - 15 11 3 3 3. - 1 - <_> - - <_> - 18 8 6 5 -1. - <_> - 21 8 3 5 2. - 0 <_> <_> @@ -12058,9 +12618,32 @@ <_> <_> - 18 9 6 2 -1. + 18 9 2 2 -1. <_> - 18 10 6 1 2. + 18 9 1 1 2. + <_> + 19 10 1 1 2. + 0 + <_> + + <_> + 18 9 3 2 -1. + <_> + 19 9 1 2 3. + 0 + <_> + + <_> + 18 9 2 4 -1. + <_> + 18 11 2 2 2. + 0 + <_> + + <_> + 18 9 6 9 -1. + <_> + 21 9 3 9 2. 0 <_> @@ -12069,6 +12652,13 @@ <_> 18 10 6 1 3. 0 + <_> + + <_> + 18 10 2 1 -1. + <_> + 19 10 1 1 2. + 0 <_> <_> @@ -12088,30 +12678,37 @@ <_> <_> - 18 10 3 5 -1. + 18 10 6 2 -1. <_> - 19 10 1 5 3. + 18 11 6 1 2. 0 <_> <_> - 18 11 4 8 -1. + 18 11 3 4 -1. <_> - 18 15 4 4 2. + 19 11 1 4 3. 0 <_> <_> - 18 12 2 6 -1. + 18 11 3 13 -1. <_> - 18 15 2 3 2. + 19 11 1 13 3. 0 <_> <_> - 18 12 2 8 -1. + 18 11 2 8 -1. <_> - 18 16 2 4 2. + 18 15 2 4 2. + 0 + <_> + + <_> + 18 11 6 1 -1. + <_> + 21 11 3 1 2. 0 <_> @@ -12123,46 +12720,37 @@ <_> <_> - 18 12 6 8 -1. + 18 12 3 8 -1. <_> - 18 12 3 4 2. - <_> - 21 16 3 4 2. + 18 16 3 4 2. 0 <_> <_> - 18 14 2 4 -1. + 18 13 2 4 -1. <_> - 19 14 1 4 2. + 18 15 2 2 2. 0 <_> <_> - 18 15 1 3 -1. + 18 14 4 4 -1. <_> - 18 16 1 1 3. + 18 16 4 2 2. 0 <_> <_> 18 15 4 5 -1. <_> - 18 15 2 5 2. - 1 + 20 15 2 5 2. + 0 <_> <_> - 18 15 3 6 -1. + 18 16 2 4 -1. <_> - 16 17 3 2 3. - 1 - <_> - - <_> - 18 17 2 4 -1. - <_> - 18 17 1 4 2. + 18 16 2 2 2. 1 <_> @@ -12188,10 +12776,10 @@ <_> <_> - 19 0 3 1 -1. + 19 0 2 3 -1. <_> - 20 0 1 1 3. - 0 + 19 0 1 3 2. + 1 <_> <_> @@ -12199,6 +12787,13 @@ <_> 20 3 1 1 3. 1 + <_> + + <_> + 19 2 4 3 -1. + <_> + 20 3 2 3 2. + 1 <_> <_> @@ -12209,12 +12804,24 @@ <_> <_> - 19 4 2 2 -1. + 19 4 1 2 -1. <_> - 19 4 1 1 2. + 19 4 1 1 2. + 1 + <_> + <_> - 20 5 1 1 2. - 0 + 19 4 3 1 -1. + <_> + 20 5 1 1 3. + 1 + <_> + + <_> + 19 4 1 3 -1. + <_> + 18 5 1 1 3. + 1 <_> <_> @@ -12225,9 +12832,9 @@ <_> <_> - 19 4 2 3 -1. + 19 4 5 9 -1. <_> - 19 5 2 1 3. + 19 7 5 3 3. 0 <_> @@ -12246,30 +12853,58 @@ <_> <_> - 19 6 1 6 -1. + 19 6 1 3 -1. <_> - 19 6 1 3 2. + 18 7 1 1 3. 1 <_> <_> - 19 6 3 3 -1. + 19 6 2 3 -1. <_> - 19 7 3 1 3. + 19 7 2 1 3. + 0 + <_> + + <_> + 19 6 5 9 -1. + <_> + 19 9 5 3 3. + 0 + <_> + + <_> + 19 7 1 3 -1. + <_> + 19 8 1 1 3. + 0 + <_> + + <_> + 19 7 3 4 -1. + <_> + 20 7 1 4 3. + 0 + <_> + + <_> + 19 7 2 4 -1. + <_> + 19 7 2 2 2. + 1 + <_> + + <_> + 19 8 1 3 -1. + <_> + 19 9 1 1 3. 0 <_> <_> 19 8 3 3 -1. <_> - 20 9 1 3 3. - 1 - <_> - - <_> - 19 8 4 11 -1. - <_> - 21 8 2 11 2. + 20 8 1 3 3. 0 <_> @@ -12281,65 +12916,74 @@ <_> <_> - 19 10 2 4 -1. + 19 9 2 2 -1. <_> - 19 12 2 2 2. + 19 9 2 1 2. + 1 + <_> + + <_> + 19 10 2 2 -1. + <_> + 19 10 1 1 2. + <_> + 20 11 1 1 2. 0 <_> <_> - 19 11 3 13 -1. + 19 10 3 4 -1. <_> - 20 11 1 13 3. + 19 11 3 2 2. 0 <_> <_> 19 12 4 8 -1. <_> - 19 12 2 8 2. + 20 13 2 8 2. 1 <_> <_> - 19 13 3 8 -1. + 19 12 3 10 -1. <_> - 20 13 1 8 3. + 20 12 1 10 3. 0 <_> <_> - 19 13 4 7 -1. + 19 12 3 12 -1. <_> - 19 13 2 7 2. + 20 12 1 12 3. + 0 + <_> + + <_> + 19 13 3 9 -1. + <_> + 20 13 1 9 3. + 0 + <_> + + <_> + 19 14 4 6 -1. + <_> + 20 15 2 6 2. 1 <_> <_> - 19 15 4 5 -1. + 19 15 3 6 -1. <_> - 20 16 2 5 2. + 20 16 1 6 3. 1 <_> <_> - 19 17 3 6 -1. + 19 17 1 3 -1. <_> - 20 17 1 6 3. - 0 - <_> - - <_> - 19 17 3 7 -1. - <_> - 20 17 1 7 3. - 0 - <_> - - <_> - 19 17 3 4 -1. - <_> - 18 18 3 2 2. + 18 18 1 1 3. 1 <_> @@ -12358,17 +13002,52 @@ <_> <_> - 20 0 2 2 -1. + 19 19 1 4 -1. <_> - 20 0 1 2 2. + 18 20 1 2 2. 1 <_> <_> - 20 3 1 4 -1. + 19 20 1 3 -1. <_> - 19 4 1 2 2. + 18 21 1 1 3. 1 + <_> + + <_> + 19 21 5 3 -1. + <_> + 19 22 5 1 3. + 0 + <_> + + <_> + 20 0 4 4 -1. + <_> + 19 1 4 2 2. + 1 + <_> + + <_> + 20 3 3 1 -1. + <_> + 21 4 1 1 3. + 1 + <_> + + <_> + 20 3 3 2 -1. + <_> + 21 4 1 2 3. + 1 + <_> + + <_> + 20 4 1 3 -1. + <_> + 20 5 1 1 3. + 0 <_> <_> @@ -12383,13 +13062,6 @@ <_> 21 5 1 2 3. 1 - <_> - - <_> - 20 4 2 3 -1. - <_> - 20 5 2 1 3. - 0 <_> <_> @@ -12400,38 +13072,31 @@ <_> <_> - 20 8 1 4 -1. + 20 6 4 3 -1. <_> - 20 8 1 2 2. - 1 - <_> - - <_> - 20 8 4 3 -1. - <_> - 21 9 2 3 2. - 1 - <_> - - <_> - 20 8 3 4 -1. - <_> - 21 9 1 4 3. - 1 - <_> - - <_> - 20 8 4 4 -1. - <_> - 21 9 2 4 2. - 1 - <_> - - <_> - 20 8 4 6 -1. - <_> - 20 10 4 2 3. + 20 7 4 1 3. 0 + <_> + + <_> + 20 8 3 2 -1. + <_> + 21 9 1 2 3. + 1 + <_> + + <_> + 20 8 3 3 -1. + <_> + 21 9 1 3 3. + 1 + <_> + + <_> + 20 9 3 2 -1. + <_> + 21 10 1 2 3. + 1 <_> <_> @@ -12439,13 +13104,6 @@ <_> 20 9 2 10 2. 1 - <_> - - <_> - 20 9 4 3 -1. - <_> - 19 10 4 1 3. - 1 <_> <_> @@ -12456,45 +13114,45 @@ <_> <_> - 20 10 4 3 -1. + 20 10 2 2 -1. <_> - 21 11 2 3 2. + 20 10 2 1 2. 1 <_> <_> - 20 10 3 10 -1. + 20 11 4 9 -1. <_> - 21 10 1 10 3. - 0 - <_> - - <_> - 20 12 4 8 -1. - <_> - 21 13 2 8 2. + 20 11 2 9 2. 1 <_> <_> - 20 13 3 8 -1. + 20 14 4 6 -1. <_> - 21 13 1 8 3. - 0 - <_> - - <_> - 20 15 4 5 -1. - <_> - 21 16 2 5 2. + 21 15 2 6 2. 1 <_> <_> - 20 15 4 4 -1. + 20 14 2 7 -1. <_> - 22 15 2 4 2. - 0 + 20 14 1 7 2. + 1 + <_> + + <_> + 20 15 3 4 -1. + <_> + 19 16 3 2 2. + 1 + <_> + + <_> + 20 16 4 4 -1. + <_> + 21 17 2 4 2. + 1 <_> <_> @@ -12502,27 +13160,6 @@ <_> 21 17 1 5 3. 0 - <_> - - <_> - 20 18 3 1 -1. - <_> - 21 18 1 1 3. - 0 - <_> - - <_> - 20 18 1 3 -1. - <_> - 19 19 1 1 3. - 1 - <_> - - <_> - 20 19 3 4 -1. - <_> - 21 19 1 4 3. - 0 <_> <_> @@ -12533,10 +13170,24 @@ <_> <_> - 21 2 3 16 -1. + 20 20 4 3 -1. <_> - 21 2 3 8 2. + 20 21 4 1 3. + 0 + <_> + + <_> + 21 1 2 16 -1. + <_> + 21 1 2 8 2. 1 + <_> + + <_> + 21 1 3 4 -1. + <_> + 21 2 3 2 2. + 0 <_> <_> @@ -12547,23 +13198,9 @@ <_> <_> - 21 8 3 3 -1. + 21 4 3 3 -1. <_> - 22 9 1 3 3. - 1 - <_> - - <_> - 21 8 3 5 -1. - <_> - 22 9 1 5 3. - 1 - <_> - - <_> - 21 9 3 3 -1. - <_> - 20 10 3 1 3. + 22 5 1 3 3. 1 <_> @@ -12575,38 +13212,31 @@ <_> <_> - 21 10 2 5 -1. + 21 10 2 2 -1. <_> - 21 10 1 5 2. + 21 10 1 2 2. 1 <_> <_> - 21 10 3 3 -1. + 21 10 3 4 -1. <_> - 21 11 3 1 3. + 21 11 3 2 2. 0 <_> <_> - 21 11 1 3 -1. + 21 11 1 2 -1. <_> - 20 12 1 1 3. + 21 11 1 1 2. 1 <_> <_> - 21 15 1 3 -1. + 21 15 2 3 -1. <_> - 20 16 1 1 3. + 20 16 2 1 3. 1 - <_> - - <_> - 21 15 3 6 -1. - <_> - 22 15 1 6 3. - 0 <_> <_> @@ -12617,16 +13247,30 @@ <_> <_> - 21 16 3 7 -1. + 21 16 3 8 -1. <_> - 22 16 1 7 3. + 22 16 1 8 3. 0 <_> <_> - 21 16 3 8 -1. + 21 16 2 3 -1. <_> - 22 16 1 8 3. + 20 17 2 1 3. + 1 + <_> + + <_> + 21 17 1 3 -1. + <_> + 20 18 1 1 3. + 1 + <_> + + <_> + 21 17 3 7 -1. + <_> + 22 17 1 7 3. 0 <_> @@ -12638,16 +13282,23 @@ <_> <_> - 21 22 3 2 -1. + 22 1 2 4 -1. <_> - 22 22 1 2 3. - 0 + 21 2 2 2 2. + 1 <_> <_> - 22 2 1 18 -1. + 22 2 1 16 -1. <_> - 22 2 1 9 2. + 22 2 1 8 2. + 1 + <_> + + <_> + 22 9 2 4 -1. + <_> + 22 9 1 4 2. 1 <_> @@ -12656,6 +13307,20 @@ <_> 21 11 1 1 3. 1 + <_> + + <_> + 22 10 2 7 -1. + <_> + 22 10 1 7 2. + 1 + <_> + + <_> + 22 10 2 3 -1. + <_> + 22 11 2 1 3. + 0 <_> <_> @@ -12673,58 +13338,30 @@ <_> <_> - 22 11 2 6 -1. + 22 12 1 3 -1. <_> - 22 11 1 6 2. + 21 13 1 1 3. 1 <_> <_> - 22 11 2 9 -1. + 22 13 1 3 -1. <_> - 22 11 1 9 2. + 21 14 1 1 3. 1 <_> <_> - 22 12 2 3 -1. + 22 16 1 3 -1. <_> - 21 13 2 1 3. + 21 17 1 1 3. 1 <_> <_> - 22 13 2 9 -1. + 23 7 1 3 -1. <_> - 22 13 1 9 2. - 1 - <_> - - <_> - 22 13 2 8 -1. - <_> - 20 15 2 4 2. - 1 - <_> - - <_> - 22 17 1 4 -1. - <_> - 21 18 1 2 2. - 1 - <_> - - <_> - 22 18 1 4 -1. - <_> - 21 19 1 2 2. - 1 - <_> - - <_> - 23 9 1 3 -1. - <_> - 23 10 1 1 3. + 23 8 1 1 3. 0 <_> @@ -12733,6 +13370,13 @@ <_> 23 11 1 1 3. 0 + <_> + + <_> + 23 11 1 2 -1. + <_> + 23 12 1 1 2. + 0 <_> <_> @@ -12743,8 +13387,8 @@ <_> <_> - 23 12 1 3 -1. + 23 15 1 4 -1. <_> - 22 13 1 1 3. + 22 16 1 2 2. 1 diff --git a/data/lbpcascades/lbpcascade_frontalcatface.xml b/data/lbpcascades/lbpcascade_frontalcatface.xml index 4d8d829931..c950754004 100644 --- a/data/lbpcascades/lbpcascade_frontalcatface.xml +++ b/data/lbpcascades/lbpcascade_frontalcatface.xml @@ -21,14 +21,19 @@ KNOWN LIMITATIONS: - Sometimes, the detector mistakenly thinks that a human face is a cat face. In - situations where either a human or a cat might be encountered, use both a - human face detector and a cat face detector. Then, if a detected human face - and a detected cat face intersect, reject the cat face. - An upright subject is assumed. In situations where the cat's face might be sideways or upside down (e.g. the cat is rolling over), try various rotations of the input image. + + CHANGELOG: + + 2016-08-06: Re-trained with more negative samples and more stages. False + positives are much rarer now. If you tailored your code for the cascade's + previous version, now you should re-adjust the arguments of + CascadeClassifier::detectMultiScale. For example, decrease the value of the + minNeighbors argument. You do not need to use a human face detector to + cross-check the positives anymore. + 2014-04-25: First release (at https://bitbucket.org/Joe_Howse/angora-blue) ////////////////////////////////////////////////////////////////////////// | Contributors License Agreement @@ -38,7 +43,7 @@ | If you do not agree to this license, do not download, install, | copy or use the software. | - | Copyright (c) 2014, Joseph Howse (Nummist Media Corporation Limited, + | Copyright (c) 2014-2016, Joseph Howse (Nummist Media Corporation Limited, | Halifax, Nova Scotia, Canada). All rights reserved. | | Redistribution and use in source and binary forms, with or without @@ -76,7 +81,7 @@ 24 GAB - 9.9900001287460327e-01 + 9.9500000476837158e-01 5.0000000000000000e-01 9.4999999999999996e-01 1 @@ -84,2325 +89,2674 @@ 256 1 - 15 + 20 <_> - 12 - -1.7687875032424927e+00 + 9 + -1.5429834127426147e+00 <_> - 0 -1 102 391095182 -138018897 -1311235414 -134348801 - -10637363 1363472332 -168428565 -170000676 + 0 -1 104 1599056782 -3801105 836281000 -134348801 -10616883 + 1430585292 -33555461 -170000676 - -3.8902848958969116e-01 7.1630239486694336e-01 + -5.4490309953689575e-01 5.6734609603881836e-01 <_> - 0 -1 266 135269620 1065172957 761273949 1068766640 - -285409281 -1075109889 -1073808385 -1073741825 + 0 -1 294 204479732 1065172189 790634493 1060117940 + -289603585 -1075077121 -1092617217 -1073741825 - -5.0905084609985352e-01 4.4736129045486450e-01 + -5.6601214408874512e-01 3.9540845155715942e-01 <_> - 0 -1 248 -882714626 -11077637 -2105857 -5255203 1594642431 - -536896039 -540028929 266295295 + 0 -1 71 -547356836 1566019389 -77856769 -551952545 + -539172900 -10560035 -52600869 994540299 - -4.0175846219062805e-01 4.7943404316902161e-01 + -4.4183051586151123e-01 4.4477555155754089e-01 <_> - 0 -1 5 -617089137 -547883529 1911919584 -2239534 1530067199 - 1140914475 -1092824836 1892022980 + 0 -1 148 -620691696 486545936 825237297 521165584 436288155 + 536422827 1026760619 523727735 - -4.2830348014831543e-01 4.3316614627838135e-01 + -4.9225500226020813e-01 3.4415841102600098e-01 <_> - 0 -1 103 251265151 2145342812 1501453661 1046368729 - -1975908196 -1105592134 -1897996802 -88470342 + 0 -1 8 2065692655 -539494441 1911927792 -2108480 455801071 + 67664201 -1084369169 1926622918 - -3.9837184548377991e-01 4.3966090679168701e-01 + -4.0782809257507324e-01 3.7964683771133423e-01 <_> - 0 -1 249 653255651 -1427184958 -736368649 -1052429 - 1722766161 -455896464 1155912595 -167811855 + 0 -1 343 791362869 -1075233419 -573079553 -33596427 + -1610973955 -262147 1026375359 -1107337903 - -3.9872139692306519e-01 3.9076396822929382e-01 + -4.4104734063148499e-01 3.3767992258071899e-01 <_> - 0 -1 98 -147601648 452990736 522407185 1599686417 1169689768 - 407507112 -1762308210 1599803223 + 0 -1 247 -770966446 -10095278 -717226475 1462226875 + 1326402382 -70331239 1175244766 1326179231 - -4.5285862684249878e-01 3.3382070064544678e-01 + -3.6573803424835205e-01 4.1576108336448669e-01 <_> - 0 -1 300 805836816 1351616140 -1629160611 -1696006160 - 2133143824 -1418430667 -1093085224 -91160647 + 0 -1 137 -1898553987 -42050596 -1074372609 -38388009 + -50700804 -268436101 -352819484 -1163887504 - -5.1765918731689453e-01 2.8637027740478516e-01 + -4.2117568850517273e-01 3.3924096822738647e-01 <_> - 0 -1 206 771753813 1072999924 -637907073 1072594908 - 1022435188 -1073874507 -1076936836 -1141628556 + 0 -1 188 -321131994 712703979 -1157694222 586350586 + 1085998084 1281738876 -403229068 -925369374 - -4.5144259929656982e-01 3.3236411213874817e-01 - <_> - - 0 -1 188 -1493176369 712675187 -55120016 -1570308126 - 1845183255 -34048033 -1090533504 -386469418 - - -3.6836385726928711e-01 4.1354060173034668e-01 - <_> - - 0 -1 84 1876927247 -103435857 821334050 -202379046 - -607136374 354198146 1878387370 -455740474 - - -3.8681995868682861e-01 3.9221677184104919e-01 - <_> - - 0 -1 85 70388767 580795691 -83467 1051082410 -287417474 - -1076176594 -57439237 -1430597793 - - -4.1789534687995911e-01 3.5533955693244934e-01 + -5.1358664035797119e-01 2.6718941330909729e-01 <_> - 13 - -1.3504111766815186e+00 + 12 + -1.2918862104415894e+00 <_> - 0 -1 52 -582353192 453631753 -1189740547 490856223 - -1064974120 -1927684129 1413925631 151519071 + 0 -1 54 1397073902 2013244398 -177098006 -201331986 + 2002780074 1006612398 -1110 -67132758 - -2.2373910248279572e-01 6.7752838134765625e-01 + -4.0280899405479431e-01 5.0070983171463013e-01 <_> - 0 -1 213 -576729857 454575443 -1996943617 536547583 - 206047452 -1088734277 210521343 264241151 + 0 -1 80 -16823041 -41857 205806847 509368831 -1431699272 + -130942 167828670 -635806469 - -3.7819463014602661e-01 5.2549731731414795e-01 + -3.7250527739524841e-01 4.8033073544502258e-01 <_> - 0 -1 275 -249562832 -1181502479 -174589519 -1112427119 - -1189167448 -1081345300 -1534158677 -1431310669 + 0 -1 228 -866136833 419433907 182275839 536546047 201854172 + 28121467 214781439 268402175 - -3.6486798524856567e-01 4.7923672199249268e-01 + -4.5891678333282471e-01 3.6297130584716797e-01 <_> - 0 -1 125 -1405482952 -15924365 -1147527681 -10535319 - -1345282310 -1103133 698354938 -1073790989 + 0 -1 270 -1561337117 -1426066718 -1010829325 -38805262 + 1202713555 -324545872 1441789815 -134233869 - -4.9668836593627930e-01 3.3489266037940979e-01 + -3.5680472850799561e-01 4.3237748742103577e-01 <_> - 0 -1 82 2135911182 -553255561 -1835761112 -744206088 - 1443360719 1427151980 -208273409 -136971281 + 0 -1 259 -597278700 268435458 -550058223 855800610 149425288 + 775302951 -118555396 -272630117 - -4.9673599004745483e-01 2.9186215996742249e-01 + -4.8106637597084045e-01 2.9466137290000916e-01 <_> - 0 -1 64 750650461 -1141224741 228524031 1066678329 - -392530945 -1119829 -389633282 -1909948481 + 0 -1 327 -1111901448 1023973552 253008120 500562168 -5242881 + -1156710915 1340989437 -536879105 - -4.4474920630455017e-01 3.3087861537933350e-01 + -3.2977777719497681e-01 4.3013024330139160e-01 <_> - 0 -1 80 -8364 961050640 -337450 -170150085 -4518372 - 1480613384 -270925857 -203948193 + 0 -1 77 -537179120 521143296 -21635309 2134891643 1350441722 + -632386648 -1129300294 -263173 - -3.6774283647537231e-01 3.8125535845756531e-01 + -3.6992338299751282e-01 3.5658127069473267e-01 <_> - 0 -1 304 -1279559723 488853328 894958865 523048208 - -1111801861 -1113625095 -1410843652 -1615113099 + 0 -1 164 -1362153945 741281595 -1496274305 720813755 + 2088729719 2146431455 -251775916 -185278474 - -3.8107365369796753e-01 3.7617510557174683e-01 + -4.7965702414512634e-01 2.5329035520553589e-01 <_> - 0 -1 27 -1038891372 866262272 -1124866827 -7307515 2556056 - -1947784189 145625549 -537934001 + 0 -1 129 2009068661 286465811 -1714126495 320044919 + -321273376 1216088341 -187041632 276299767 - -3.3774635195732117e-01 4.1467228531837463e-01 + -4.0860968828201294e-01 3.0382931232452393e-01 <_> - 0 -1 214 1313841735 674152170 -1368464720 -1597048870 - 759309825 -295860621 1709856085 -587729545 + 0 -1 222 70785877 1041800816 -75508353 1071923196 2113290236 + -1074941012 -1075086339 -1351740304 - -4.4100293517112732e-01 3.1954705715179443e-01 + -3.9227196574211121e-01 3.2063353061676025e-01 <_> - 0 -1 310 -1432731787 -1219055176 -42533035 -1126253868 - -2038280772 -55715078 -2000923144 -1936931520 + 0 -1 52 -733166882 -44852481 -145568001 -15114497 -924915460 + -33678721 -88592641 1063732851 - -4.3541839718818665e-01 3.1401738524436951e-01 + -3.7047380208969116e-01 3.1812894344329834e-01 <_> - 0 -1 180 232552309 -537305729 -3104297 -67617446 -1211085572 - -20391173 -1968567044 -1392871087 + 0 -1 32 -2097737981 1148364791 -1210636301 -1330585805 + 123014973 2113833983 -32925 -236603423 - -3.7881413102149963e-01 3.5767501592636108e-01 - <_> - - 0 -1 46 -36984309 904630143 823414970 -188744006 1900770270 - 1399711367 -473188378 1969748707 - - -4.0620720386505127e-01 3.2759186625480652e-01 + -4.2788907885551453e-01 2.8403493762016296e-01 <_> - 19 - -1.3998974561691284e+00 + 13 + -1.3729060888290405e+00 <_> - 0 -1 128 -236980233 16777207 -520752904 15793139 -168428203 - 1979187191 -33554947 -251920389 + 0 -1 316 1058750395 -1080312336 -1078198785 -3 -1145389058 + -1078318408 -1079328769 -1077958496 - -1.7629407346248627e-01 6.5313565731048584e-01 + -2.5900188088417053e-01 6.1616760492324829e-01 <_> - 0 -1 230 -871825409 -580752385 -713042433 -540061189 - 1549092351 -587761733 1607687679 1577014783 + 0 -1 151 -201887221 1915747883 -218104097 3145727 -92571030 + -117772190 -88408321 -1566377217 - -3.1553706526756287e-01 4.9262753129005432e-01 + -3.7379077076911926e-01 4.5426961779594421e-01 <_> - 0 -1 79 -545306406 -547422721 474111600 -570360321 -507816 - 1599364180 -11379845 -12845089 + 0 -1 96 386868111 1607319551 2145227774 -81921 2136981469 + 1564794828 -3277827 -171573810 - -3.5872745513916016e-01 4.0607807040214539e-01 + -3.5450288653373718e-01 4.5893719792366028e-01 <_> - 0 -1 123 -252337502 -658267397 7348400 821935103 1377280435 - 47000107 -169347101 939467707 + 0 -1 2 -551362576 -73215120 -364212554 -11998256 71434372 + -1616176195 209715400 -840182021 - -5.1070415973663330e-01 2.8583043813705444e-01 + -4.2596518993377686e-01 3.3351564407348633e-01 <_> - 0 -1 45 645859107 708031411 -168346241 -1330581136 81734679 - 783767351 -45193 -34341517 + 0 -1 82 247336735 586821439 -134217729 1056866239 + -1090551809 -9217 -33628162 -1430597650 - -4.4308465719223022e-01 2.9009637236595154e-01 + -3.8904032111167908e-01 3.6951214075088501e-01 <_> - 0 -1 241 -154214396 268437506 -680474855 864167714 684199820 - 204876327 -52122180 -262209 + 0 -1 249 -672137222 -74448921 -21891587 -136323721 + 1322253791 -822281795 1565482863 1465906911 - -4.1140288114547729e-01 2.9478433728218079e-01 + -3.2322180271148682e-01 4.2339357733726501e-01 <_> - 0 -1 265 -1365070662 -380938 -1139629826 -35735556 49021040 - 1020949984 219416278 -293 + 0 -1 319 -1347239947 1069203248 -2097163 -1610678308 + -1879052295 -268437506 -1934079492 -1935110672 - -3.9993125200271606e-01 2.9704034328460693e-01 + -4.0132158994674683e-01 3.3234956860542297e-01 <_> - 0 -1 295 217001265 -1346379851 1862205053 -1342447907 - 30277700 -1360008036 -1988349004 -287317952 + 0 -1 37 -1068709308 -1102522849 1644484342 -268379409 + 1443710532 -11090094 -213845121 -12059649 - -3.9956006407737732e-01 2.8518736362457275e-01 + -4.2390203475952148e-01 2.9791557788848877e-01 <_> - 0 -1 72 290390927 534606847 534719466 -100668033 1607942091 - 1499327373 -101712435 -187324532 + 0 -1 202 -285495441 -1427182081 -290198603 -527241618 + -419467196 -855709209 -268509632 -922957372 - -3.0478826165199280e-01 3.7477290630340576e-01 + -3.6988914012908936e-01 3.4229919314384460e-01 <_> - 0 -1 136 -285336459 2110655990 -2013274145 2143051605 - -1124443700 -9506961 -604210584 -1161806512 + 0 -1 43 -18449 1073711035 -1319386462 -203620626 2070804431 + 854521820 -134545716 1442310948 - -4.0837058424949646e-01 2.7444043755531311e-01 + -4.0420171618461609e-01 3.0070811510086060e-01 <_> - 0 -1 55 -62093618 -581362746 -141373441 -10940834 -840543755 - -638181765 1859448799 996361303 + 0 -1 205 225460085 1069170549 -1213441 -268681410 536639980 + -272859906 -1344397956 -1090621548 - -3.7610772252082825e-01 3.0961802601814270e-01 + -4.0233635902404785e-01 3.1345960497856140e-01 <_> - 0 -1 110 -404233212 134685696 -2016460609 -1379932177 - -540018825 -2163729 806790835 607646519 + 0 -1 65 1347781250 -252185797 18161683 335127199 -918162925 + -68564231 1079360443 1080539939 - -4.3601146340370178e-01 2.5886246562004089e-01 + -4.4784346222877502e-01 2.6452672481536865e-01 <_> - 0 -1 288 -907025790 1474249959 -806494209 -10763 -283444824 - -364917254 -828244229 -1968201565 + 0 -1 40 138021973 914534260 -1628242049 179970033 2088664692 + -279028579 -285573707 -1431115148 - -2.6032009720802307e-01 4.3652611970901489e-01 - <_> - - 0 -1 229 -18370769 -757680277 788372142 -2072580242 - -273678553 745365463 -134222107 -229310606 - - -3.0938607454299927e-01 3.5719990730285645e-01 - <_> - - 0 -1 14 -1603048865 578088863 -390533121 140676846 - -495489499 -42082971 -4194586 -26017865 - - -3.1977957487106323e-01 3.4310647845268250e-01 - <_> - - 0 -1 249 1643111394 -1211240000 1172894578 -641010466 - 1181712375 -2068614428 1433624934 -671119917 - - -3.3919364213943481e-01 3.4504517912864685e-01 - <_> - - 0 -1 164 1606136599 587595301 -21521312 1079307891 62912316 - 2136471350 -285346140 -201854089 - - -3.1577944755554199e-01 3.4307131171226501e-01 - <_> - - 0 -1 152 785525471 1052180799 1060533999 2120755670 - 1316621908 -270833354 -73736274 -361439920 - - -3.4840318560600281e-01 3.2924604415893555e-01 - <_> - - 0 -1 47 1824524292 1056221828 -268623876 -1615033532 - -2092452655 144493033 502744181 -571159100 - - -4.5537719130516052e-01 2.4885603785514832e-01 + -4.6739324927330017e-01 2.6337191462516785e-01 <_> - 17 - -1.6478537321090698e+00 + 15 + -1.3434195518493652e+00 <_> - 0 -1 99 1126020910 939511791 -137494546 -134218002 928378510 - 667815688 -131090 -21878 + 0 -1 312 1594941436 -539099137 1597374397 2136866813 + 2133434303 -2359299 -180801 532360959 - -1.9173553586006165e-01 6.1490827798843384e-01 + -3.9849624037742615e-01 4.3070858716964722e-01 <_> - 0 -1 277 1066647483 -1078215472 -1078199809 -515 -1078280194 - -1079276888 -1112801281 -1077956952 + 0 -1 107 -1687737718 -136351793 819208354 -201466130 + -304104530 1430290438 -74187782 -254479670 - -2.5890102982521057e-01 6.0596489906311035e-01 + -5.2847045660018921e-01 2.9759022593498230e-01 <_> - 0 -1 280 -1347239939 -1078263848 -6291491 -1073954860 - -1883246595 -1075838997 -1346850307 -1393015372 + 0 -1 106 1593187583 -57860 494558719 1568543997 -1430627078 + -17168194 -22085633 -17167126 - -3.5419720411300659e-01 3.9201220870018005e-01 + -3.2349127531051636e-01 4.4297724962234497e-01 <_> - 0 -1 148 -16582767 990936848 -15337711 1024534289 522275741 - 530061615 1786740027 2132761183 + 0 -1 233 -289936401 719515647 1894970098 -67961857 + 1429694295 1079178739 1417049205 -235416077 - -4.0790781378746033e-01 3.3604335784912109e-01 + -4.0733993053436279e-01 3.3705353736877441e-01 <_> - 0 -1 33 -1024790785 -33673381 -715534345 -5787889 -721957121 - -17850629 -654587205 -27048190 + 0 -1 338 -804225008 -1130847023 -1644863659 -626985985 + -1151011816 -67830287 -1090585640 -72811781 - -3.0084383487701416e-01 4.4991242885589600e-01 + -4.0251138806343079e-01 3.1045806407928467e-01 <_> - 0 -1 173 779038223 578498431 -26263553 -1430717601 - 1426011767 1870118397 -726064396 -184550929 + 0 -1 30 1325133735 -235668011 -4196493 -1297076240 37159747 + -1078198341 -5247041 -17338573 - -4.3469619750976562e-01 2.9388919472694397e-01 + -3.5516351461410522e-01 3.3867400884628296e-01 <_> - 0 -1 207 11804501 -1074249744 2143289343 -1359077380 - 2074886065 -262692 -1075003396 -1431820272 + 0 -1 61 1563885570 990015234 1715350066 -1612515566 + 2121997646 -562425 -1460130098 -2 - -4.1263562440872192e-01 2.8357046842575073e-01 + -3.6495906114578247e-01 3.1801441311836243e-01 <_> - 0 -1 263 -620104768 -83232282 -548406795 -1074143767 - -828717122 -21770245 251698105 68943602 + 0 -1 35 -486805761 -30385 -164631585 -67393017 -662962177 + -269484302 -302258246 -298365693 - -3.8648277521133423e-01 3.0467325448989868e-01 + -2.5626540184020996e-01 4.6705508232116699e-01 <_> - 0 -1 161 1391411790 41936415 -228930992 1892677067 - 1987802112 1480885434 -1362 -219942962 + 0 -1 242 582106997 -1375949832 -2097155 -1611859716 + -1078984707 -71372812 -1174471336 -1364685600 - -3.7596645951271057e-01 3.1412878632545471e-01 + -3.4055373072624207e-01 3.2303497195243835e-01 <_> - 0 -1 308 248452913 1071429554 -251663105 -538972499 - -1928628395 -1346437645 -1745150348 -33596064 + 0 -1 213 1857005319 651918339 -1159732176 -294652937 + 2146914899 1349774535 -2097404 -50856010 - -3.9380916953086853e-01 2.8952071070671082e-01 + -3.3969157934188843e-01 3.1695431470870972e-01 <_> - 0 -1 182 626985985 930297719 -286325569 -147866829 - -692197027 2138802865 -117701012 -118164992 + 0 -1 292 -1364537606 -1925122 -36259590 -102826180 + -2098986320 243153064 -1515278601 -137380105 - -3.5818240046501160e-01 3.2363671064376831e-01 + -3.3688172698020935e-01 3.2412472367286682e-01 <_> - 0 -1 60 -1361623937 -1149491078 5825754 508056955 -88210408 - -655077264 -1174209542 -33408130 + 0 -1 211 -824758745 174632251 -469831961 -1428162053 + 1157038145 213857255 -186772236 -185273869 - -3.4054177999496460e-01 3.2592311501502991e-01 + -4.0657189488410950e-01 2.5756362080574036e-01 <_> - 0 -1 184 1311738415 -1375274001 1726672390 -829228034 - 2070837764 1208920803 -67308591 -419954764 + 0 -1 110 -16884641 -36276290 -160105525 -659501198 -652220 + -295070 -2176776 -15009184 - -3.7184986472129822e-01 2.8876912593841553e-01 + -2.8538039326667786e-01 3.6766386032104492e-01 <_> - 0 -1 1 -566173704 -81765536 -328487245 -545227007 8650948 - -1342492099 8915104 -307505157 + 0 -1 90 -792331710 -1069030682 13697279 -2057320217 + -175702061 -60841468 -222841601 1783605027 - -3.2362362742424011e-01 3.4028744697570801e-01 + -3.4717887639999390e-01 2.9574045538902283e-01 <_> - 0 -1 223 787644405 1052643324 -671622145 1060113936 - -1543669260 -621052931 497506684 -1094759403 + 0 -1 234 749378744 935105716 -1397302147 1001388025 + 255328920 -1799926224 -1397966593 -1074790917 - -3.8580575585365295e-01 2.8625565767288208e-01 - <_> - - 0 -1 90 -754941560 -598092101 -1244290303 281751211 - 1463866633 1153550863 -806946917 38740739 - - -4.4092047214508057e-01 2.5595286488533020e-01 - <_> - - 0 -1 167 184294525 -9037826 -21186597 -1497857980 - -1372058532 -1233225231 -341673474 -1099675796 - - -3.7506091594696045e-01 2.9585087299346924e-01 + -3.7167704105377197e-01 2.8397652506828308e-01 <_> - 21 - -1.4008288383483887e+00 + 15 + -1.2288014888763428e+00 <_> - 0 -1 233 -814746846 -2111111254 -553913104 -2097922 - 2004869959 1141046786 1970763104 -134744334 + 0 -1 271 -290784257 -542572545 -167807627 -2061 209652223 + -1093158913 1157580031 1173837303 - -2.1097929775714874e-01 5.7671958208084106e-01 + -3.3414435386657715e-01 4.7178736329078674e-01 <_> - 0 -1 75 -8396836 -538976473 -16384001 -10879489 -8397857 - -10498599 -45416465 1595899679 + 0 -1 317 -2098253 -1146358896 1476391185 -704777743 + -1140850693 -1415582030 -7696 -640683845 - -3.1942996382713318e-01 4.6969848871231079e-01 + -2.5055918097496033e-01 5.2570897340774536e-01 <_> - 0 -1 4 -824512541 -524299 -344077 -72323247 206048519 - -1409589837 -84975873 -805875917 + 0 -1 132 -100663299 272629759 -789195536 544341979 + -167781039 1966601201 -515 -234881025 - -3.0280569195747375e-01 4.2180880904197693e-01 + -3.5798946022987366e-01 3.6239877343177795e-01 <_> - 0 -1 290 -1086615304 956872912 223108216 496889077 - -1097860099 956429808 1601034749 -538976769 + 0 -1 48 -2105507696 -1366759952 -1126500363 -570630416 + -317934356 -33619969 -36643332 -2304812 - -3.5371550917625427e-01 3.6481952667236328e-01 + -3.9822307229042053e-01 2.8633421659469604e-01 <_> - 0 -1 146 -85985781 1914665473 1351604943 269482959 - -118967717 -264571342 -71633409 -1574764609 + 0 -1 74 -792677742 -101713185 7352369 298695163 -1761297729 + 6029312 -25184257 1608465947 - -3.5075160861015320e-01 3.4602758288383484e-01 + -4.2175698280334473e-01 2.4120111763477325e-01 <_> - 0 -1 81 -579450864 489695248 -568994533 -671905287 - 1484394168 -21040594 -1132978498 -4358 + 0 -1 223 169615221 -1174487300 -281051137 -1090642276 + -4703305 -33558539 1073692156 -1359214592 - -3.6514815688133240e-01 3.3418157696723938e-01 + -3.8317176699638367e-01 2.8932854533195496e-01 <_> - 0 -1 300 -1071640576 -1794071852 -589571267 -622299971 - -128680624 -107152175 -1128604712 -93782371 + 0 -1 75 -102806438 -9703431 1045568568 503377755 -547864488 + 1534349686 1867669466 -82706561 - -4.3749809265136719e-01 2.3641848564147949e-01 + -3.8330292701721191e-01 2.9036629199981689e-01 <_> - 0 -1 43 1347789474 278788859 1078009887 1450704633 755482275 - -890279806 1601682923 1145430595 + 0 -1 332 784272181 -1073742539 -554188937 -67127948 + 938153105 -1091568641 -1917947412 -2140908 - -4.5889991521835327e-01 2.1458856761455536e-01 + -3.4002754092216492e-01 3.1559377908706665e-01 <_> - 0 -1 58 -67811136 507778012 2090770170 940627838 -547680164 - -564395008 -1507362 -15533189 + 0 -1 214 256847367 707514298 -1090536922 -286331166 + 1877943126 258930467 -52826284 -50858080 - -3.4613710641860962e-01 2.9729354381561279e-01 + -4.0559005737304688e-01 2.5587162375450134e-01 <_> - 0 -1 40 708451453 915939127 2086399799 -1364049961 - -111247856 -278977 -562528515 -1432293672 + 0 -1 210 -176953385 839001603 -118293121 -46662093 + -928341523 783159107 1824812218 -294654113 - -4.1620507836341858e-01 2.4089127779006958e-01 + -2.2742739319801331e-01 4.4131305813789368e-01 <_> - 0 -1 279 -1423966541 177905074 -199210 -1914114123 - 1966529760 -2068908586 -574294864 -841165576 + 0 -1 291 -292556917 -268603344 -882511881 -142650156 + -1955672434 -84524073 -941787305 -807451567 - -3.1373840570449829e-01 3.2040333747863770e-01 + -2.8523033857345581e-01 3.5285699367523193e-01 <_> - 0 -1 198 1848585743 -1940984369 1618804030 -285289836 - 1994084869 67912305 -4262128 -303498266 + 0 -1 86 -1006633234 -8464643 -1800132448 -126160132 + 1597972294 2137374137 2130142532 -67635593 - -3.6098247766494751e-01 2.7308923006057739e-01 + -3.6786875128746033e-01 2.6055160164833069e-01 <_> - 0 -1 83 -34593 -42134437 83156217 534796439 -206958426 - -542489456 -301270341 -1910021 + 0 -1 347 809435409 188951103 -1134973121 -1196245185 + 926905404 -2113948 -1122058375 -93651077 - -2.1900075674057007e-01 4.6534782648086548e-01 + -3.1239312887191772e-01 3.1785130500793457e-01 <_> - 0 -1 255 -732498730 808132612 -1694705650 637674514 - -856846932 790002977 -1523128100 -5768257 + 0 -1 47 -242549308 -1693329125 2124733233 857453163 + -233386788 -69871665 -1055992678 173495071 - -3.0635869503021240e-01 3.2308223843574524e-01 + -3.7436348199844360e-01 2.9003840684890747e-01 <_> - 0 -1 142 -272658653 -2039881873 -1093759223 -295772198 - 316478038 1219928242 1542411604 -523960875 + 0 -1 88 1543496623 -1277707265 1375580878 -1141900354 + -202408001 1073719014 -20973842 -454167574 - -4.1005435585975647e-01 2.4376337230205536e-01 - <_> - - 0 -1 314 -1886651248 233035768 -579887888 -644481803 - -1924527808 72215888 -813972012 -838860849 - - -3.2710522413253784e-01 3.0177840590476990e-01 - <_> - - 0 -1 109 -626385315 -541893255 -289637249 -2982538 - -285318128 -335644678 -934750724 -1937614 - - -3.0264344811439514e-01 3.4333297610282898e-01 - <_> - - 0 -1 127 -675308008 858262544 -546392130 -86565344 889738476 - 1024209296 -539034113 -17892421 - - -3.0164864659309387e-01 3.2610884308815002e-01 - <_> - - 0 -1 76 289874895 1574889454 356325874 -1257339986 - 2013148111 1523362314 -209587256 -51584276 - - -3.0728715658187866e-01 3.2666257023811340e-01 - <_> - - 0 -1 191 207364212 -1629723097 -69798913 180098791 445713016 - -1342538933 -112443395 -1436022512 - - -4.8653569817543030e-01 2.1469378471374512e-01 - <_> - - 0 -1 316 -1891992271 534502897 -709725931 -1133905467 - -1625325679 -1098169635 -1377993223 -1175556795 - - -3.6775574088096619e-01 2.6944977045059204e-01 + -2.5309252738952637e-01 3.8837322592735291e-01 <_> - 20 - -1.6370692253112793e+00 + 17 + -1.3014856576919556e+00 <_> - 0 -1 246 -544546902 -40378434 1166794751 -553126475 - 1124863438 -6684681 252464271 252663279 + 0 -1 56 -16777228 1343290737 -73730 1979579903 -167772964 + 1145364445 -1 1969225695 - -1.7677198350429535e-01 5.9283459186553955e-01 + -3.7386018037796021e-01 4.0434870123863220e-01 <_> - 0 -1 105 -1688231254 -136322578 542408738 -167781650 - -284181590 88186882 -74646534 -254480182 + 0 -1 329 -1078722575 -1078454128 991133557 -4369067 + -1079247105 -1145394016 522813437 -1080337223 - -4.8250266909599304e-01 3.2293373346328735e-01 + -3.0502972006797791e-01 4.3909499049186707e-01 <_> - 0 -1 291 -1087113223 -1153788752 923893117 -40019499 - -1444151361 -1145394000 520297981 -7610887 + 0 -1 252 -806361310 -492110674 -268445968 -1049642 + 2002778951 1024456291 2012705892 -135792649 - -2.7269113063812256e-01 4.6762999892234802e-01 + -4.1819226741790771e-01 2.9456692934036255e-01 <_> - 0 -1 163 1431698391 477399807 5291197 215258107 2097218267 - 1070271552 1347764095 1497759739 + 0 -1 279 -52962084 805379072 -99820514 1040191240 -857961316 + -1164230721 -318841633 -1185 - -3.6439743638038635e-01 3.3937779068946838e-01 + -3.2393226027488708e-01 3.5176092386245728e-01 <_> - 0 -1 49 -494878000 -1408572168 -1216184843 -570753839 - -1385631492 -1572929 -37698091 -140075 + 0 -1 131 -148956144 992812800 463421370 920482344 + -1626551044 512506296 -8586248 -4198469 - -3.4019106626510620e-01 3.2104432582855225e-01 + -4.0920355916023254e-01 2.6287314295768738e-01 <_> - 0 -1 101 -15196934 2140689563 1546672602 1591347871 - 1544035576 488135152 2142261182 -4259841 + 0 -1 67 -1947229405 577929191 -1142967369 819199477 + 1610560307 1002176493 -268443355 -185204747 - -3.7342280149459839e-01 2.8317087888717651e-01 + -3.9257824420928955e-01 2.6880934834480286e-01 <_> - 0 -1 195 -357586129 70201151 -292424585 -1468006937 - 1163158101 45494091 -492310284 -184618257 + 0 -1 173 2136997887 492685274 610548733 501067503 1428159743 + 139549608 1843232763 1146223423 - -4.2928436398506165e-01 2.4182404577732086e-01 + -2.6709714531898499e-01 3.5500597953796387e-01 <_> - 0 -1 219 -346034385 -1509510400 -590396300 -56691898 - -2013314811 -11148442 -790137804 -17301901 + 0 -1 323 -173546237 2012723003 -208685715 1965110275 + -1648389341 -1207969861 -1532023285 -2068848597 - -3.2902050018310547e-01 3.1380781531333923e-01 + -2.9938983917236328e-01 3.2542988657951355e-01 <_> - 0 -1 276 51573280 869252567 856020959 2136817673 -1825854798 - 1786292453 1863958011 51070032 + 0 -1 72 -1025850814 -226835760 -10485921 -537564929 + 1390123691 -201328836 -1152983169 -229685189 - -4.4989612698554993e-01 2.3105476796627045e-01 + -2.8262135386466980e-01 3.3869415521621704e-01 <_> - 0 -1 239 221945781 -1351824656 -369627303 -1616906768 - 180205816 -1398111810 986511580 -2002860624 + 0 -1 300 186646459 772435664 -277088299 -811293964 510621556 + -2003902767 768513520 -858982156 - -3.3374428749084473e-01 3.0387389659881592e-01 + -3.5066390037536621e-01 2.6261052489280701e-01 <_> - 0 -1 88 -12577 1384049145 -1464090918 -265274512 1423314444 - -330608884 -134684970 -95228557 + 0 -1 277 -1901527179 -1079583240 1608384509 -1214321156 + -1475544131 -1618224659 -1350140680 -1343693700 - -2.9424193501472473e-01 3.4667330980300903e-01 + -3.1748643517494202e-01 2.9679971933364868e-01 <_> - 0 -1 215 -349179217 304152230 -725813534 -44849422 206658671 - 1343674791 1143817582 1414000887 + 0 -1 57 -1370792705 -151110594 137920254 505970139 -16908198 + -119123852 2113992958 -27118721 - -3.5459104180335999e-01 2.8464645147323608e-01 + -2.9851835966110229e-01 3.1736648082733154e-01 <_> - 0 -1 44 2135942447 398828943 961557154 -85264382 -9441329 - 191609019 -135559186 1155988198 + 0 -1 34 -421870864 -121460494 -69399301 -37695628 1854146044 + -572886810 -1662657067 -2754955 - -3.9276805520057678e-01 2.5532895326614380e-01 + -3.1197559833526611e-01 2.9238173365592957e-01 <_> - 0 -1 322 792354069 -1442292348 -725922817 -1075650752 - -1345299339 -270808291 1585978709 -1363456899 + 0 -1 20 -395053825 -1172089085 -20972641 -36479168 16188668 + 170858277 1862209791 -43004073 - -4.0223011374473572e-01 2.3934543132781982e-01 + -2.6653704047203064e-01 3.6648163199424744e-01 <_> - 0 -1 51 -963985190 526195161 -632047017 -13433768 -170216210 - -584509261 -1147462405 2122007633 + 0 -1 162 -876099570 -1028677841 346016622 -791218210 + -798236064 1141175622 -19929374 -733615388 - -3.5836115479469299e-01 2.7841308712959290e-01 + -3.3825182914733887e-01 2.6917472481727600e-01 <_> - 0 -1 69 1282640527 -221028405 -1115770991 -1312815327 - 518459295 -5010698 -8421409 -52340448 + 0 -1 314 268538656 1006620135 2070388735 2065690825 + -1156937026 -1545866585 -350495013 193696921 - -3.0360385775566101e-01 3.3305782079696655e-01 + -3.5214114189147949e-01 2.6037210226058960e-01 <_> - 0 -1 63 240090463 1543015448 1657994909 1376934782 - 2121953054 -3393448 774963198 -364875945 + 0 -1 344 649287281 -1970393800 -524355 1006436977 + -1880457436 -1364230690 -575458832 -1711323724 - -3.1514179706573486e-01 3.1063860654830933e-01 - <_> - - 0 -1 149 -117441008 272437552 -2011728848 808844177 - -115035003 901066096 -392587048 829815772 - - -4.1897901892662048e-01 2.3548045754432678e-01 - <_> - - 0 -1 41 -285250029 -1342531469 -1337688454 76061301 - 2140621344 -26490526 -230505742 -498673325 - - -3.7328067421913147e-01 2.7277800440788269e-01 - <_> - - 0 -1 186 197109511 113539807 -1663738276 652405614 - 2079664708 -1381909716 -83887277 -340414799 - - -3.5890376567840576e-01 2.7977034449577332e-01 + -3.5447227954864502e-01 2.6205524802207947e-01 <_> - 24 - -1.3530069589614868e+00 + 19 + -1.5306358337402344e+00 <_> - 0 -1 231 -607125512 -203956738 -146407939 -549587593 - 2106032085 -7015967 1296916047 1465901007 + 0 -1 325 -14630984 -4473090 -1074397189 -33964034 -72302598 + -1074020356 -1073741825 798731006 - -1.2551400065422058e-01 6.0037857294082642e-01 + -3.5602328181266785e-01 4.2827311158180237e-01 <_> - 0 -1 126 -12041 289127191 -1961178373 858913587 -452995643 - -573056619 -184946437 811859443 + 0 -1 130 -551551009 486645509 1899748147 355677975 222889183 + -1073921969 -8405249 863993727 - -3.1659016013145447e-01 4.0386086702346802e-01 + -3.4908288717269897e-01 3.5527125000953674e-01 <_> - 0 -1 305 -4456453 -1079345488 1601271281 1566430416 - -1145044997 -1363497544 -807547663 -846209539 + 0 -1 98 1599900924 -103183170 2077315071 -8544581 2147076347 + -348676 -6751554 1039993019 - -2.4047850072383881e-01 4.9467754364013672e-01 + -4.1958260536193848e-01 2.6830750703811646e-01 <_> - 0 -1 205 -422843738 730826189 -93007646 -1561338070 - 1156254860 82792447 -359691576 -318767125 + 0 -1 341 -551306566 -1928790024 409301104 -570567172 + 155380464 201374866 1307966709 -840957953 - -4.0942522883415222e-01 2.8118029236793518e-01 + -2.9362049698829651e-01 3.5112550854682922e-01 <_> - 0 -1 130 286242991 1430640951 -1315388758 -5384739 - 1897658847 1435892732 -241122312 -190447622 + 0 -1 159 -25168073 792404277 -1048577 -1077938185 -50397955 + -1125161865 -118697795 -17040197 - -3.6675310134887695e-01 2.7747273445129395e-01 + -2.4668307602405548e-01 4.3156060576438904e-01 <_> - 0 -1 155 -360711817 1044065557 -202645505 -1078462473 - -554253058 -123796300 -991681292 -117447077 + 0 -1 102 -254483728 -134352193 1078993009 -438445569 + -145493001 236195840 2010188607 803207983 - -2.2938863933086395e-01 4.3152013421058655e-01 + -4.0355175733566284e-01 2.2437272965908051e-01 <_> - 0 -1 33 -486546689 -38568697 -114385161 -1078244605 - -1398768130 -16859405 -387455605 -95221245 + 0 -1 270 543941090 32109282 -158607600 -539249547 1450174403 + -2037673760 1430348867 -706789133 - -2.5292310118675232e-01 4.0669292211532593e-01 + -3.8295698165893555e-01 2.4519409239292145e-01 <_> - 0 -1 197 -347108861 707787566 -271712714 -286066182 - 1660625669 23327763 -118368650 -16781581 + 0 -1 194 1820081525 1073508181 -237185025 -1627884305 + -1208341124 -1549315 786959612 -1360889776 - -3.2693040370941162e-01 2.9912397265434265e-01 + -3.9130604267120361e-01 2.4020861089229584e-01 <_> - 0 -1 48 44773155 -1400496480 -2013315201 -2130179 1928269391 - 2146108387 1871512017 -2109991 + 0 -1 123 -126746406 -16910241 1317990340 2140139227 + -152170248 -665943862 -494767108 -1308598001 - -3.1153312325477600e-01 3.0730357766151428e-01 + -3.3991897106170654e-01 2.5616830587387085e-01 <_> - 0 -1 277 817397681 -4651712 -1074593921 -4489223 -1464975366 - -1080350544 1068207931 -1414856608 + 0 -1 169 -25173426 1157590007 -1462405486 9141882 1563902020 + 1986233998 -121111822 1375206347 - -2.7505692839622498e-01 3.4677764773368835e-01 + -3.9309167861938477e-01 2.3203048110008240e-01 <_> - 0 -1 158 -805311870 -1362548369 -186736224 -220270666 - 1742698308 1147947264 -251792176 -789512618 + 0 -1 119 -2109765118 -1549312122 1974331919 -15794219 + -68435067 -10513465 -203437628 -207886460 - -3.9942753314971924e-01 2.4047489464282990e-01 + -3.2824972271919250e-01 2.5953757762908936e-01 <_> - 0 -1 65 -700036014 -675626240 648044818 -69944464 -389395237 - -215288017 -1719763715 -12588054 + 0 -1 293 532419764 -2413864 1004477621 931662384 -1970602497 + -1095996537 -839968773 -1411438117 - -3.1749448180198669e-01 3.0149078369140625e-01 + -4.1732871532440186e-01 2.0762878656387329e-01 <_> - 0 -1 319 765664309 -1401170476 -22282241 -1880818860 - -1688316571 -52824373 -1730200112 -889291499 + 0 -1 139 1857947903 1492633971 -1101013025 975886606 + 1350846468 -121757915 -130875788 -869224848 - -3.5558241605758667e-01 2.6557549834251404e-01 + -3.4800508618354797e-01 2.4446432292461395e-01 <_> - 0 -1 272 -1164201800 -1716289100 -378039852 -1409579788 - -1121338919 -1880520559 932112367 -1869871980 + 0 -1 103 -2466598 -4662086 -978313286 -784675555 454565560 + 487593980 1603337147 -7147781 - -3.6485251784324646e-01 2.5734969973564148e-01 + -2.7047672867774963e-01 3.1779998540878296e-01 <_> - 0 -1 22 -21049601 -25866473 325725 1043995470 1592678894 - -269259937 -971837858 -8913089 + 0 -1 109 -1561869790 120520547 1657708544 -1898513430 + -1614825521 2092432685 1538717248 -289931533 - -2.2092992067337036e-01 4.2716163396835327e-01 + -4.0362039208412170e-01 2.1034663915634155e-01 <_> - 0 -1 138 763233167 2004741991 -277961986 -35997914 897543679 - 1741158903 -50331667 -1578882304 + 0 -1 180 1084531215 -707808258 -1210116245 -439570458 + 897553343 1907884029 -135266566 -188437888 - -3.0084916949272156e-01 3.0936580896377563e-01 + -2.8848439455032349e-01 2.9848706722259521e-01 <_> - 0 -1 92 66036611 -2133412515 2136683646 -184645734 - 1604280073 202711897 -1379383 -186590399 + 0 -1 70 -526324565 -2473047 -1752530953 -720765307 + -829754181 -88588561 725799882 -1423966207 - -3.7059250473976135e-01 2.4178710579872131e-01 + -2.9072195291519165e-01 2.8631457686424255e-01 <_> - 0 -1 196 -326382376 361846096 -2045590179 1068964371 - 705563792 -1156488704 1208497115 994048507 + 0 -1 186 -1035688188 -2075351177 1742138910 -1361646049 + 2038259221 1281666845 -10016229 -927864043 - -3.2299432158470154e-01 2.8366291522979736e-01 + -4.0738871693611145e-01 2.1433149278163910e-01 <_> - 0 -1 70 -412097022 -1568018524 -1342448718 -1253932 - -1260185663 1258275150 -2067820288 -138937659 + 0 -1 111 -193049515 -579904651 -1078067337 -1125110406 + 657196408 -308999 -269432520 -1626310360 - -3.5679051280021667e-01 2.6213440299034119e-01 - <_> - - 0 -1 193 -714615533 270672129 -306258157 -1758339253 - 47808742 -1902768889 -1941903362 -893526249 - - -2.5351437926292419e-01 3.6361116170883179e-01 - <_> - - 0 -1 165 -318796273 1227399022 -1369769360 -675875878 - -344383672 1582766693 -86017024 -344793116 - - -3.1456202268600464e-01 3.0873265862464905e-01 - <_> - - 0 -1 93 -1045815078 -235892117 -571835429 -3460789 - -108525848 -1332172392 -1503517894 -1300229375 - - -3.5038644075393677e-01 2.6677846908569336e-01 - <_> - - 0 -1 15 -1976677263 3726998 -392242219 214976380 -1048834204 - -44384235 -81855380 -1434428367 - - -4.1762107610702515e-01 2.1475161612033844e-01 - <_> - - 0 -1 166 209059956 2146573530 1933758719 -1670893344 - -1206231472 -538281424 -605128624 -88975308 - - -4.3403875827789307e-01 2.1460674703121185e-01 + -3.4779027104377747e-01 2.4815729260444641e-01 <_> - 26 - -1.3850060701370239e+00 + 19 + -1.5291346311569214e+00 <_> - 0 -1 250 1118499839 -796332098 -134253196 -6424581 259721215 - -1671186434 100533499 1170700287 + 0 -1 251 -13959169 -28639242 -402655813 -34537805 256249855 + -568918017 1146377727 1413838847 - -1.3170924782752991e-01 5.9910702705383301e-01 + -3.0813953280448914e-01 4.0832179784774780e-01 <_> - 0 -1 94 1570566140 2106702270 -577478657 -9625925 -36328709 - -75449636 -394325 1071454459 + 0 -1 58 -2117889 -6785 -88080641 -1078673830 1592918250 + -130866 -28588321 -67420082 - -3.8424813747406006e-01 3.6834198236465454e-01 + -2.4101538956165314e-01 4.6791258454322815e-01 <_> - 0 -1 278 -136315975 -1187792752 1568109937 -571788877 - -86048838 -1433673030 -1190563400 -1984968261 + 0 -1 104 63906446 1607320575 -243471634 -35783681 + -1106396194 1430561736 -201721409 -168502531 - -2.4970491230487823e-01 4.7245621681213379e-01 + -4.4818142056465149e-01 2.3805019259452820e-01 <_> - 0 -1 155 -25692619 573911103 -1090519553 -1074266633 - -1124204292 -1199619017 -387151619 -1363171157 + 0 -1 313 -201338603 -10642115 1604312349 -1120184061 + -570443331 -16641 -588542516 -1936978931 - -2.7256563305854797e-01 4.0413850545883179e-01 + -2.7106782793998718e-01 3.9553779363632202e-01 <_> - 0 -1 299 270536720 -82027755 -542052353 -744834006 - -172433515 -36839897 -2048335877 -1356137589 + 0 -1 42 -1358982349 -1862229200 -537145985 -1122992815 + 178914341 -1439598077 1593789951 -272634817 - -3.7769773602485657e-01 2.3510186374187469e-01 + -3.2034155726432800e-01 3.0296289920806885e-01 <_> - 0 -1 102 133774 1573843455 290464424 -173151905 771865036 - 1430562872 -109382744 -246039832 + 0 -1 318 -1440743437 235588504 -10494472 -1887027976 + -1288767504 -1398099527 -843000652 -863175440 - -4.7037139534950256e-01 2.0533446967601776e-01 + -3.0287060141563416e-01 3.1029415130615234e-01 <_> - 0 -1 127 -618460144 -1256386552 -1618575940 1972721552 - 469800920 504635776 -846791686 -69254485 + 0 -1 292 -555045126 -361514 762749686 -139778 235667694 + -1093395212 -11471106 -6309889 - -3.5127875208854675e-01 2.5741419196128845e-01 + -3.0765682458877563e-01 3.1880700588226318e-01 <_> - 0 -1 85 150343455 40910711 -1248068641 -1430372421 - -1895949361 -21272033 -331755522 -1431642114 + 0 -1 196 250872917 -68273685 -1078051329 -1082508571 + -1091283460 -1168712 -1417288 -1363666432 - -3.7984871864318848e-01 2.3182238638401031e-01 + -3.3388796448707581e-01 2.7029579877853394e-01 <_> - 0 -1 286 -13916067 -237157163 1069283741 -7496371 - -1771992641 -17192227 -1383805025 -2004252467 + 0 -1 219 -290476795 -465649810 -35918852 -289735302 + -34138796 -84935682 -318770912 -857082906 - -2.1929037570953369e-01 3.8296228647232056e-01 + -3.2501670718193054e-01 2.7079197764396667e-01 <_> - 0 -1 206 9705301 508957948 -71469059 431911901 2041834229 - -1141023756 -38047748 -1432742364 + 0 -1 351 255542577 -1383080455 -134234123 -35669132 + 225794545 -1073809475 501579485 -43919 - -3.4404903650283813e-01 2.3727993667125702e-01 + -3.1916373968124390e-01 2.6903003454208374e-01 <_> - 0 -1 162 -28187574 1457201967 -1799949806 542855772 - -22592508 347566595 -86051214 -254279713 + 0 -1 133 215553112 -1107551056 251485533 -1117840291 + -23183686 -1157685096 148380684 -1359280118 - -3.3773353695869446e-01 2.3899486660957336e-01 + -3.4327763319015503e-01 2.6013481616973877e-01 <_> - 0 -1 78 1353317010 -353449217 14955059 233737419 1113314227 - 1272002592 2140215167 200230499 + 0 -1 229 1781507627 11182978 -1532302414 -453707565 + 2112190021 1230535507 1940017765 -723454538 - -3.5864931344985962e-01 2.1981315314769745e-01 + -4.0361833572387695e-01 2.0124079287052155e-01 <_> - 0 -1 50 -592281584 1487966200 -1782854276 -34165307 - -911392552 -588393496 -86945955 -302569115 + 0 -1 35 1659037435 -1074583282 -585441281 -1142706330 + -487432961 -50689038 -752619781 2119369219 - -2.9026558995246887e-01 2.8104048967361450e-01 + -2.8866782784461975e-01 2.8524476289749146e-01 <_> - 0 -1 301 -14053072 -2064062200 -928567823 -983051523 - 201916593 150423153 -1859132687 -1929383993 + 0 -1 5 -277098501 -426275 -537657353 -80707839 148375995 + -1443515977 -1360028481 -290306189 - -3.2115238904953003e-01 2.5486564636230469e-01 + -2.2325216233730316e-01 4.0045592188835144e-01 <_> - 0 -1 79 -607531822 2133030428 1045592120 922799991 - -1958080364 -631876516 -551887109 -116138161 + 0 -1 342 -12845061 -1146450256 1643999573 -578956079 + -1430327361 -1364660568 1068039673 -826557192 - -2.5716596841812134e-01 3.1999784708023071e-01 + -1.7625236511230469e-01 4.5335152745246887e-01 <_> - 0 -1 7 -1897370238 2088280021 -27542220 955523029 143789824 - -1732421377 -270311431 -319465097 + 0 -1 246 -5334 16170343 -1563618650 -559235090 -213913050 + 543944397 -82347060 -186319018 - -3.7310892343521118e-01 2.2297158837318420e-01 + -3.3681878447532654e-01 2.5925871729850769e-01 <_> - 0 -1 151 2117994623 -596493511 -42869249 2123389533 - -102873516 -1194255940 -1077870956 -1369933454 + 0 -1 200 706711043 240052095 -1057817422 -288572133 + 2104128000 107326306 -142977008 -184549550 - -3.2065725326538086e-01 2.5838941335678101e-01 + -4.0993413329124451e-01 1.9274616241455078e-01 <_> - 0 -1 141 -402659162 81777018 894353956 -1095917410 - 1470100164 1429538625 -675679616 22405077 + 0 -1 207 678842645 -554033765 -299117059 -2195490 787765744 + -85783809 801398270 -1342553048 - -3.9470222592353821e-01 2.1365866065025330e-01 + -3.0899345874786377e-01 2.7749294042587280e-01 <_> - 0 -1 306 371408657 -1390197839 -610304075 -1084394735 - 740911518 -1442850385 1025329500 -1085287308 + 0 -1 239 -352653541 -1464975560 -1711377924 1006431154 + -1914849861 -1997605505 -723791652 -2005992518 - -3.5310438275337219e-01 2.2878694534301758e-01 - <_> - - 0 -1 96 1411399848 1607023650 2118667161 2115963630 - 825267416 -1300086616 866705067 1593838595 - - -3.7212049961090088e-01 2.1682462096214294e-01 - <_> - - 0 -1 236 -1023751505 1654647882 654289424 -221611870 - 1142643327 2865238 1353434162 -218116589 - - -3.0895259976387024e-01 2.7360698580741882e-01 - <_> - - 0 -1 25 263714691 -1500250442 -572970029 1029922655 - 461194497 -1384691616 902512981 -831890189 - - -2.8019675612449646e-01 2.8230005502700806e-01 - <_> - - 0 -1 157 -1009275158 703439343 1881063906 1407643120 - 1357622212 1698779727 -175905592 -799737222 - - -3.0597987771034241e-01 2.6828068494796753e-01 - <_> - - 0 -1 24 -655102849 1007864659 -1544094705 -1540313220 - -574699 -47065227 -1091975362 -278732953 - - -2.5672450661659241e-01 3.1667667627334595e-01 - <_> - - 0 -1 103 347621596 1037305260 358617181 753140063 -61713220 - -610393186 -1106322953 -1350956022 - - -3.4445220232009888e-01 2.3471401631832123e-01 - <_> - - 0 -1 36 -923349290 256096042 219291806 -1155987134 - 2086406828 1508909094 -2007541485 1887403703 - - -3.4530115127563477e-01 2.3805907368659973e-01 + -2.7373707294464111e-01 3.1265005469322205e-01 <_> - 25 - -1.2224140167236328e+00 + 20 + -1.2624083757400513e+00 <_> - 0 -1 252 -22088450 -5325374 -33282 -258 12993776 67429556 - 1976988926 2005923583 + 0 -1 152 -536896171 528166667 -89134213 863190787 -10787 + -42746009 -135004165 861372191 - -1.9573126733303070e-01 5.5536717176437378e-01 + -3.0395314097404480e-01 4.0150311589241028e-01 <_> - 0 -1 216 -941896961 288549683 -965260547 1902502507 - 1287981311 723742655 1157582079 1173354239 + 0 -1 316 1058061817 1069530432 1072045437 -779 -1079460102 + -1078220624 -1086607877 -1347745096 - -3.0669313669204712e-01 3.6197665333747864e-01 + -3.1513056159019470e-01 3.4505581855773926e-01 <_> - 0 -1 62 -571494657 -2099490 -25243649 -1082480054 2115633354 - -130996 -329130274 -67419570 + 0 -1 231 -681586977 321007414 1157254391 -135793561 + 1280068831 961635295 1153779199 1107294463 - -2.4500623345375061e-01 4.3682980537414551e-01 + -3.4076648950576782e-01 2.9044425487518311e-01 <_> - 0 -1 19 -704647185 2113917365 -428522838 -141168226 - 2123362255 2006664827 -254348594 1459088068 + 0 -1 281 13565963 -1605663761 -1068499969 -1551382549 + -957611569 -88150085 -486669105 -489698353 - -3.4159252047538757e-01 2.9353541135787964e-01 + -2.9677531123161316e-01 3.0763381719589233e-01 <_> - 0 -1 285 -138414285 -168045645 -550635909 -240708569 - -36728913 -33554641 -890270582 -2069142366 + 0 -1 326 -1053826398 -721436430 -280231937 -975176521 + -409225541 -71593733 -6291717 -1413486341 - -2.8817924857139587e-01 3.4106674790382385e-01 + -2.8983283042907715e-01 3.1503608822822571e-01 <_> - 0 -1 77 -220544510 -184926009 2147213135 -209757985 - -1177821558 -139002180 845151099 -8701317 + 0 -1 183 1163896751 1977614331 671051643 -138674226 + 2144851967 1470987751 -58725393 -188420220 - -2.2831186652183533e-01 3.8085940480232239e-01 + -2.0130541920661926e-01 3.9263197779655457e-01 <_> - 0 -1 256 12976195 569051735 -1044464777 -2131832853 - -1863693873 -889525281 -1060633090 -1024468017 + 0 -1 38 -16788225 -25265109 -1172116865 974286447 -18980838 + -2269836 -349111681 -30245109 - -3.4035223722457886e-01 2.4870637059211731e-01 + -2.6475778222084045e-01 3.2654273509979248e-01 <_> - 0 -1 225 243431285 -1342397538 -1074439183 -198404 - -1147339787 -1950366979 -1176535299 -1346857836 + 0 -1 84 1433881682 1597703946 1291197240 -9438094 1526162906 + -394281474 -50917514 -414 - -2.9916274547576904e-01 2.7878564596176147e-01 + -2.9093095660209656e-01 2.9709726572036743e-01 <_> - 0 -1 188 -389107962 -1496674445 -1433293856 1650520822 - -808004780 -340166498 -270808076 -327882656 + 0 -1 49 -603945842 -1315963413 -414862337 -9040081 + -925350721 -117485633 -68928293 841171459 - -3.6523097753524780e-01 2.3002453148365021e-01 + -3.6999693512916565e-01 2.1880353987216949e-01 <_> - 0 -1 249 -1561660693 -1964116758 -433068176 -674252332 - 76465114 -86789644 1441781719 -167788045 + 0 -1 335 -235151561 906503990 -6316714 948108800 -319324675 + -16843053 -603980191 -117506534 - -2.6452550292015076e-01 3.1857562065124512e-01 + -2.7334323525428772e-01 3.0180162191390991e-01 <_> - 0 -1 30 83758542 1352905533 -25477260 888412977 1174342621 - -581240613 -1877419 954559493 + 0 -1 66 -1413764333 724760368 601747389 -6095968 37694209 + -1342441059 92217889 -273154057 - -3.9430552721023560e-01 2.1380217373371124e-01 + -2.6323935389518738e-01 2.9735177755355835e-01 <_> - 0 -1 291 1060338993 -1618339632 1411411797 -1111518927 - 1038801631 -1171216200 431569585 -1627714192 + 0 -1 163 -335559766 -453021782 -323533214 1893203877 + -270539322 17588935 -186715916 -252379394 - -3.1174781918525696e-01 2.5848281383514404e-01 + -3.0761030316352844e-01 2.5141632556915283e-01 <_> - 0 -1 174 1272433155 241160959 -187054076 -1428167714 - 1656705620 178680903 -188744156 -92279086 + 0 -1 328 -13631567 -1212417327 403124577 89128053 905935803 + 805306111 455804405 -1913655045 - -3.5104271769523621e-01 2.4124261736869812e-01 + -2.4577388167381287e-01 3.1640377640724182e-01 <_> - 0 -1 100 276007552 1448970891 1624277552 1433388541 - -144262781 203467264 -747113541 1187367471 + 0 -1 338 -1805103104 -204178216 -1109225537 -645859592 + -1179295532 -17539075 -1342640193 -1085605221 - -4.3640381097793579e-01 2.0373314619064331e-01 + -2.7292105555534363e-01 2.8334984183311462e-01 <_> - 0 -1 265 514492090 -1084506382 802327294 -574652997 - -1951495942 -1115800400 -1734105369 -745080833 + 0 -1 113 184427503 2077949879 2130628607 -1972228222 + 267784191 -122913 -19677458 -87003834 - -2.6869311928749084e-01 3.1262946128845215e-01 + -2.6322066783905029e-01 2.9420077800750732e-01 <_> - 0 -1 238 975568369 -1078429260 -1073778819 -1246039248 - -566763547 -574710393 -1879731715 -1363518280 + 0 -1 81 105097999 1542832493 298852512 -33591146 -7371798 + 1171296972 -159057160 -792331574 - -2.5506082177162170e-01 3.2470330595970154e-01 + -3.1270226836204529e-01 2.4914608895778656e-01 <_> - 0 -1 116 -197130578 -69435407 25570034 -1282381057 - -736477475 1078203406 1072176808 -224107914 + 0 -1 287 -1423199312 -1691103151 -1814751664 -1613770752 + 990048439 1006682272 1472720818 -805482223 - -3.3984503149986267e-01 2.3857665061950684e-01 + -3.1640163064002991e-01 2.3388214409351349e-01 <_> - 0 -1 170 2006936207 2046780255 -906124674 -571018634 - 465548283 1995414095 -469838166 -53152636 + 0 -1 18 706367007 709894941 -1978089477 -1976242714 + 1047418708 -9413867 -8999074 -94175241 - -2.3337669670581818e-01 3.4638467431068420e-01 + -3.4782758355140686e-01 2.1951326727867126e-01 <_> - 0 -1 261 -1993607757 -1984171376 -1964620068 -1377319864 - -878651982 2100351409 -540935193 -846344047 + 0 -1 320 -1074273477 -1349648528 -26397387 -305765168 + -1750336135 -1414551302 -820448067 -1996649316 - -2.5745591521263123e-01 3.1530505418777466e-01 + -2.4355542659759521e-01 3.1015169620513916e-01 <_> - 0 -1 129 -585119904 520350737 -1602237728 387020659 - -316697172 -809628610 -341521253 1937239575 + 0 -1 151 -25443838 1937727008 -398471218 40370095 -231164274 + -1339821902 -97325926 -88867841 - -3.0576938390731812e-01 2.6786401867866516e-01 - <_> - - 0 -1 303 -48760835 -1382112048 1192391029 185356020 - 783760374 -1402171184 959454513 -1431708544 - - -2.8466665744781494e-01 3.0237734317779541e-01 - <_> - - 0 -1 321 700150833 -1366030659 -590225483 -1393138060 - -1364311531 -1142207587 2140558729 -1370849424 - - -3.7198981642723083e-01 2.3002536594867706e-01 - <_> - - 0 -1 228 -1054166 -201341212 1923367016 1916986952 - 1992519431 1213361995 1174402160 -1068174746 - - -3.4979847073554993e-01 2.4561876058578491e-01 - <_> - - 0 -1 106 -1907696549 -268565315 -1342514689 336742770 - -1439790339 -1301623122 -1342275841 -1440064298 - - -2.6577013731002808e-01 3.1544610857963562e-01 - <_> - - 0 -1 210 -257776636 1915752044 -1649103180 -1095126373 - 1422147805 210473965 2022068463 1660109363 - - -3.7758591771125793e-01 2.2004681825637817e-01 + -2.6998028159141541e-01 2.8467071056365967e-01 <_> - 28 - -1.3550500869750977e+00 + 19 + -1.3592376708984375e+00 <_> - 0 -1 273 1595195384 1608363967 1595766713 -572674083 - 1226391547 -44180227 2111155631 531574527 + 0 -1 348 -995118944 -930416974 345887952 -570558340 88531328 + -1945218639 -587737611 -570425861 - -1.6430117189884186e-01 5.4418802261352539e-01 + -2.9777532815933228e-01 4.2831858992576599e-01 <_> - 0 -1 39 -5377 -57601 538639103 -347397 -17301286 -4259105 - -79502593 -77380901 + 0 -1 253 -67110358 1893122090 1893397120 -86249774 + 1180660851 7567942 1349997680 -134220065 - -1.8002209067344666e-01 5.2194720506668091e-01 + -3.9622232317924500e-01 2.9791569709777832e-01 <_> - 0 -1 177 1566441471 2103287797 492075325 500554077 - 1998422011 -155652 192249721 1565917179 + 0 -1 75 -539240230 -648023297 469764112 1593868287 -11661110 + 1532777684 -552444965 -14942209 - -2.7448469400405884e-01 3.6767318844795227e-01 + -2.9889813065528870e-01 3.6522966623306274e-01 <_> - 0 -1 3 -524550921 -1669383407 -574620225 -33590459 143458441 - 256708119 -805314577 -6324385 + 0 -1 289 -67125368 -79955026 -2020348961 -35793731 + -1077342273 -616575495 -1089623397 497024223 - -2.3465685546398163e-01 4.0192386507987976e-01 + -3.4431287646293640e-01 2.9128664731979370e-01 <_> - 0 -1 71 -846691120 1439476212 -690689 -2237091 -67570179 - -36374787 -2105923 -143907 + 0 -1 166 1384071754 1113049038 -758590950 1895815884 + -763411890 1209352476 -89797814 -220206337 - -2.7146762609481812e-01 3.2002952694892883e-01 + -4.1682410240173340e-01 2.1082815527915955e-01 <_> - 0 -1 294 263139089 -581452515 2010774399 -2106799 477955253 - -72357417 267875276 -1097712 + 0 -1 105 -254496094 -18879841 14000245 771751931 -11010061 + 134742528 -8912901 929018859 - -3.5161617398262024e-01 2.3248630762100220e-01 + -3.7486401200294495e-01 2.4162678420543671e-01 <_> - 0 -1 302 -15214854 -1884686344 167600312 -581052707 37857013 - 202028220 1305828853 -840957953 + 0 -1 179 -654313675 742329655 -262625 1060896639 -390366980 + 74072179 -253568780 -289418469 - -2.6214873790740967e-01 3.0466583371162415e-01 + -2.5083890557289124e-01 3.3719986677169800e-01 <_> - 0 -1 169 613396271 2003697295 1738141229 -35000540 - 2147446463 2131993840 -10096690 1690603136 + 0 -1 315 -73668360 1565910264 2081358045 2146916605 + -1621517064 357571729 -1480983299 -24065 - -3.2117179036140442e-01 2.4732810258865356e-01 + -2.4764552712440491e-01 3.5451245307922363e-01 <_> - 0 -1 281 -1355025965 -1961980240 -671219723 -283264688 - -1936837383 -1952736320 -908474131 -875701004 + 0 -1 301 -811597901 -1364218069 -1648402160 -325060800 + -1976643936 -1364209682 -975732736 -856689421 - -2.4713008105754852e-01 3.1776627898216248e-01 + -2.7585402131080627e-01 3.0668458342552185e-01 <_> - 0 -1 232 -894441054 -1880167002 -853281294 -338827028 - 1348301603 877440640 1936192066 -135400158 + 0 -1 285 -16801110 1942398638 2139043338 1884201710 + 1565129044 1073771567 1927598335 1089267455 - -3.2655048370361328e-01 2.4388861656188965e-01 + -3.5849529504776001e-01 2.3467011749744415e-01 <_> - 0 -1 288 -553260894 -155221559 -13927175 -570440513 - -23332102 -93644167 -1079190789 -1431330575 + 0 -1 124 -552751172 -106362566 379098395 -619987142 + 2056910831 -256982033 -448484726 991891214 - -2.4785453081130981e-01 3.1448525190353394e-01 + -3.6114555597305298e-01 2.2252097725868225e-01 <_> - 0 -1 190 672423253 -570534469 -174826505 -1074210146 - -1158800264 -67208458 802954712 -1079507880 + 0 -1 28 -922792361 135407106 915543278 -1441729929 + -209763771 -33465743 -85987393 -79495181 - -3.1213754415512085e-01 2.4356111884117126e-01 + -2.9683136940002441e-01 2.8010207414627075e-01 <_> - 0 -1 120 -656932646 -651487779 -956164148 2064599515 - -136440708 -588512112 -1232981444 -1979159765 + 0 -1 174 -65566202 5422903 -1572145044 -617562398 -77657088 + 1967600929 854335524 -8915084 - -3.0449146032333374e-01 2.5301957130432129e-01 + -3.7435227632522583e-01 2.1536998450756073e-01 <_> - 0 -1 243 1649084931 672964650 -1105808049 713205535 - 2036285460 -666148121 -55162040 -18875393 + 0 -1 22 -487912721 -800642866 2009588683 -1392279546 + 1656090575 1071632022 -2052634693 -2044509181 - -3.4271252155303955e-01 2.1502359211444855e-01 + -3.0010569095611572e-01 2.6017066836357117e-01 <_> - 0 -1 11 -152656190 868356183 -501591426 -201146046 - -546953661 1982915527 -759837225 -751304729 + 0 -1 226 -741397974 -774903581 1081934016 -260181765 + 2068804966 -935049268 1908400875 -168901016 - -3.6129125952720642e-01 2.0629832148551941e-01 + -2.7382543683052063e-01 2.9915502667427063e-01 <_> - 0 -1 107 -537765384 1060665394 2014012895 -1179616664 - -22202433 -1074072677 -147975202 -1147076845 + 0 -1 44 1817520043 -1431149805 -35670017 848351552 + 1036462355 -1879155406 -302153961 -67637897 - -2.9889339208602905e-01 2.5862032175064087e-01 + -3.3639410138130188e-01 2.2802397608757019e-01 <_> - 0 -1 199 -328257785 -858932225 -530764942 -826874930 - -82742922 -1671853892 -218380796 -169018736 + 0 -1 311 -1330405232 -1146452984 -920726316 -1147304716 + -1089883143 -1260027579 -1255145527 -1869873152 - -3.1055119633674622e-01 2.3958165943622589e-01 + -3.6143729090690613e-01 2.2017471492290497e-01 <_> - 0 -1 154 494120195 870143859 -1647046746 -36192340 - 2139319279 803383587 -332148852 -175859072 + 0 -1 255 -488642849 338857182 1447921202 -691318883 + 1085163095 23216146 1883555028 -209735809 - -2.8900969028472900e-01 2.5575104355812073e-01 + -2.8023749589920044e-01 2.8233993053436279e-01 <_> - 0 -1 282 -811560420 827561735 -12914945 -80101505 - -1361111928 -1185616587 -1407676420 -16973965 + 0 -1 6 -857296913 -38559749 -1123606723 -1326175183 + 214765461 1826707963 1609522143 250940451 - -2.4221476912498474e-01 3.2213848829269409e-01 - <_> - - 0 -1 28 -1807515438 -1923894982 -1525713421 -149168351 - 240714426 -1418935881 419048443 426584671 - - -3.4787160158157349e-01 2.1293328702449799e-01 - <_> - - 0 -1 147 -67165120 453708801 -1303483468 895300097 - 1246742261 -70442158 -982536969 1920335427 - - -3.4275433421134949e-01 2.1697193384170532e-01 - <_> - - 0 -1 84 1234906919 2103279727 -1846517728 -34739694 - 2067706763 1171293376 -104744214 -776609560 - - -3.1936296820640564e-01 2.2989478707313538e-01 - <_> - - 0 -1 203 -148968905 1008481713 788164595 781877169 240125438 - -1348980802 1087673598 -1963666822 - - -2.6340115070343018e-01 2.8225165605545044e-01 - <_> - - 0 -1 292 1837891345 -1365117008 931935797 254075285 - 1304075707 781882527 284906609 -1998401051 - - -3.0138608813285828e-01 2.5070127844810486e-01 - <_> - - 0 -1 31 -2141011328 549559667 -576755279 -1989065165 - -1471060704 -1108160073 -825160949 47662087 - - -4.3011611700057983e-01 1.7580580711364746e-01 - <_> - - 0 -1 244 -747375089 -747702293 -219779522 1890186598 - -335684346 1718484847 1643894306 -206110753 - - -2.3109740018844604e-01 3.2786485552787781e-01 - <_> - - 0 -1 26 -1784488175 -36553927 -1031147589 -369559501 - 125374437 -1648822347 8863969 -1498451769 - - -2.3490820825099945e-01 3.1162357330322266e-01 - <_> - - 0 -1 259 -1071476830 -1095595629 -1920078129 -1444498449 - 810365109 -21630982 -290653569 -392299569 - - -2.5611433386802673e-01 2.9074308276176453e-01 + -2.9626613855361938e-01 2.7211683988571167e-01 <_> - 30 - -1.3058989048004150e+00 + 20 + -1.2654424905776978e+00 <_> - 0 -1 262 -270610434 -134359075 -811399758 -681603633 - -286489698 -45513244 -1344862513 227476639 + 0 -1 274 -152045826 -542116132 -671384098 -536871169 + 71611552 4511120 1691862270 2144334079 - -1.0025274008512497e-01 5.5719470977783203e-01 + -3.2745066285133362e-01 3.7415373325347900e-01 <_> - 0 -1 104 -2097187 353744664 -1074283233 962461525 -17042946 - 2132074456 -185611768 173014862 + 0 -1 55 -562049324 1347689172 838916858 323023775 -10528232 + 1547698176 -79496197 -16257057 - -2.9774430394172668e-01 3.4969726204872131e-01 + -3.2601267099380493e-01 3.1999495625495911e-01 <_> - 0 -1 192 -201591309 322053939 -66051 -1150042305 -1967374172 - 720309079 -1929450275 -9437249 + 0 -1 155 -150864973 823197205 855899696 1897004151 + 1359478447 239799783 -1119879173 2071721983 - -2.2600507736206055e-01 3.8218078017234802e-01 + -3.1169268488883972e-01 3.2441514730453491e-01 <_> - 0 -1 290 -1690568520 1023449340 21823732 -1646306859 - -661660161 529059241 -845261571 -536871425 + 0 -1 131 -8122216 -1694493696 1544425874 1971917534 + 1494268856 974434736 -47924226 -1081103685 - -2.8739321231842041e-01 2.8658962249755859e-01 + -3.4951829910278320e-01 2.8645709156990051e-01 <_> - 0 -1 253 -894497022 101363498 -1468636304 174491490 - 1306476909 100485583 -17240860 -50397265 + 0 -1 2 -148702222 -39652368 -926160348 -4129301 71565440 + 1002386359 4456576 -269484065 - -4.0346711874008179e-01 1.7318421602249146e-01 + -3.2985246181488037e-01 2.8976812958717346e-01 <_> - 0 -1 83 -318927617 2139044223 -1908122241 779509119 - -1159705360 -13892400 239132095 -1357193897 + 0 -1 269 -537196528 367210120 -810330341 -1611069392 + 452626939 -275337221 -1889288261 -4456709 - -2.4370998144149780e-01 3.1787887215614319e-01 + -3.6027029156684875e-01 2.2897857427597046e-01 <_> - 0 -1 240 -1372487695 -1464797736 -608961161 -539484303 - -1347732485 -1107560232 -1770177028 -1397928683 + 0 -1 46 581575179 144736896 -1511062769 771591377 13044399 + 613156333 461832575 -33602083 - -2.9030051827430725e-01 2.7010890841484070e-01 + -3.1637319922447205e-01 2.6715582609176636e-01 <_> - 0 -1 162 -77617562 1723582851 -388105926 10740970 2075870464 - 2001443802 -264144166 1912602619 + 0 -1 72 -631190908 -791476526 2102263115 -707719041 + -1824344143 -221118035 1935670155 -681895917 - -3.6183983087539673e-01 2.2234350442886353e-01 + -3.1301385164260864e-01 2.6414388418197632e-01 <_> - 0 -1 209 1737993987 575323583 570599958 -1593901402 - -537396969 800103342 -218367233 -210440396 + 0 -1 143 -395337586 1290599162 -1480586611 -1107445125 + -780276278 1222177164 1909323816 1431695206 - -3.0187138915061951e-01 2.5218242406845093e-01 + -3.1736305356025696e-01 2.5901272892951965e-01 <_> - 0 -1 115 -3692022 -33948459 -1481085416 -169476374 - -243802706 1464294676 -138677344 -135135404 + 0 -1 327 -1618216774 487712984 335544528 478095577 -16078406 + 185086393 210310393 1339020735 - -2.6393750309944153e-01 2.8237256407737732e-01 + -3.2663252949714661e-01 2.4670498073101044e-01 <_> - 0 -1 38 652099711 -1564843973 104523854 704662580 2126923816 - -548581264 -351211922 -63803885 + 0 -1 266 102918451 -821892609 49152511 -286461629 2080379763 + 2137245875 2051079551 -858486798 - -3.4199714660644531e-01 2.2430206835269928e-01 + -3.4607407450675964e-01 2.0814558863639832e-01 <_> - 0 -1 42 -1969279581 -1481414863 -1376914049 -1163909120 - 207957301 -1456248013 -347640417 -358126493 + 0 -1 115 1965030149 69155845 -270820041 -1078461449 + -136584193 762821931 -588278748 674225702 - -3.2226172089576721e-01 2.3534862697124481e-01 + -3.3318042755126953e-01 2.3290997743606567e-01 <_> - 0 -1 97 -721363152 486579872 1882454289 1434257045 - 1611566751 1289487287 996045691 1005540351 + 0 -1 181 -489698686 -2131832314 -1039863296 818323586 + -523765334 440824136 -780927062 -528941364 - -3.4691241383552551e-01 2.1465319395065308e-01 + -3.0289414525032043e-01 2.5606787204742432e-01 <_> - 0 -1 146 -613203450 1931612930 -221388928 2357067 -95798262 - -1633004965 -1206355046 -1305281858 + 0 -1 7 -1968533749 -1158234249 -1903504601 1289568835 + -2110509277 1055784827 -16777649 -1061695641 - -3.5142555832862854e-01 2.2679552435874939e-01 + -3.1121507287025452e-01 2.4493122100830078e-01 <_> - 0 -1 53 726466699 -783429313 -1320406822 -3624870 1498638047 - 293610405 -545215571 -171145013 + 0 -1 59 -1258926881 -549822406 408301535 2050653013 + -1703261576 -76779424 973269887 -98400385 - -2.8053104877471924e-01 2.5749957561492920e-01 + -2.7002063393592834e-01 2.7681529521942139e-01 <_> - 0 -1 258 -96033630 1940556686 -497037664 -252647058 - 703265613 1079474790 -142103350 1089273046 + 0 -1 272 -758193574 1389009342 -1059925886 -5881636 12990686 + 2163886 1106474407 1364714403 - -3.5805869102478027e-01 1.9770637154579163e-01 + -3.4319832921028137e-01 2.2524215281009674e-01 <_> - 0 -1 29 801058311 -1581801242 219502516 -808469412 264711475 - -2031926289 805127380 -840973936 + 0 -1 89 2010493580 1490924031 558703340 1878899615 + 2136242133 256903807 1130158729 818193091 - -3.1421071290969849e-01 2.3023897409439087e-01 + -4.1370552778244019e-01 1.7945855855941772e-01 <_> - 0 -1 172 -431184122 -2146638145 -899408814 -320144615 - -413827291 -936008940 -1376277757 -856306909 + 0 -1 306 -202440190 -738220126 82060896 -477207729 + -153700670 -570891389 -199329793 -203755569 - -3.3034646511077881e-01 2.2980070114135742e-01 + -2.5417929887771606e-01 2.9859820008277893e-01 <_> - 0 -1 296 -1934886608 -1103642657 -1616127841 2141970916 - 12401112 -606080117 -28750412 -975218195 + 0 -1 264 -221254326 1925904495 1704207914 1894699598 + -451424859 4246980 -49167940 1886450374 - -3.0468633770942688e-01 2.4846823513507843e-01 + -3.4114065766334534e-01 2.2073985636234283e-01 <_> - 0 -1 137 1828669055 -890173322 1056472031 1383623540 - -356497848 -275776488 -319784148 -45023438 + 0 -1 53 -98573686 -233458620 -1145323521 -580784361 + 1931469735 -260055489 -1291736289 -1421354481 - -2.7311590313911438e-01 2.6826277375221252e-01 - <_> - - 0 -1 9 1255206898 -1667881507 -10989766 54528930 1868912080 - 1497103356 -1096470729 195839511 - - -3.6629125475883484e-01 2.0582148432731628e-01 - <_> - - 0 -1 221 -374953039 110804926 -627248196 1059075576 - -271092824 -1449292838 -306539616 -1950680360 - - -2.7446079254150391e-01 2.6614543795585632e-01 - <_> - - 0 -1 77 1079656456 1450316376 -44560086 -86675865 821811859 - -203750610 1644870683 862142514 - - -4.1938367486000061e-01 1.8087086081504822e-01 - <_> - - 0 -1 0 -290783281 -303164749 -1470447878 -1487432078 - 916915428 -88877852 1774133328 -992512778 - - -2.6362594962120056e-01 2.8109744191169739e-01 - <_> - - 0 -1 234 -756036050 839304974 -287378334 -278205702 - 1541888379 252445922 1089229910 1534066638 - - -3.4634828567504883e-01 2.1581955254077911e-01 - <_> - - 0 -1 276 855880616 863230344 1428139679 995299387 - -1190999286 -2031656420 -1089224709 393285777 - - -3.6159241199493408e-01 2.0310276746749878e-01 - <_> - - 0 -1 311 -1512047005 -894771811 -1683823949 -598542090 - 1995129382 -1899059137 1498537061 -838863787 - - -2.8326958417892456e-01 2.6241222023963928e-01 - <_> - - 0 -1 315 -1885077515 -1147345968 765009497 190991824 - -1880224543 -1444116296 170661041 -1880099595 - - -2.7807191014289856e-01 2.6050725579261780e-01 - <_> - - 0 -1 135 -678450904 253998378 1239066322 -181932174 - 1262701314 1057893524 -413531308 -638649353 - - -3.3198201656341553e-01 2.2709015011787415e-01 - <_> - - 0 -1 34 -581179905 -1848462196 1945061311 -5371768 - -323621137 -1263209313 1589634526 -1983639545 - - -2.1172577142715454e-01 3.3727011084556580e-01 + -2.1690982580184937e-01 3.4113904833793640e-01 <_> - 28 - -1.5291974544525146e+00 + 21 + -1.2858563661575317e+00 <_> - 0 -1 118 1460139419 453084545 822327865 822292283 352929169 - 417272919 135004047 924844031 + 0 -1 288 -268513282 -170008577 -1615475234 -37777945 + -54096706 -3303955 -268497714 233768959 - -8.1135094165802002e-02 5.6568491458892822e-01 + -2.9269060492515564e-01 3.6005640029907227e-01 <_> - 0 -1 80 -715128994 1934810962 -672407682 -201597282 - -35692578 809635668 -268435489 2147483551 + 0 -1 171 2139094807 590479159 -422320014 544275186 + 1609553655 1064828726 -268463004 1979187191 - -3.0913391709327698e-01 3.3743736147880554e-01 + -3.9009553194046021e-01 2.6665380597114563e-01 <_> - 0 -1 247 1122941951 1555757531 -694977567 -540019318 - 137302463 470541003 1136607934 1306525407 + 0 -1 337 240061441 237972797 -1342754881 782424635 956105749 + -1115687441 -557891589 -1360330817 - -3.1006491184234619e-01 3.1824222207069397e-01 + -3.6515378952026367e-01 2.4825972318649292e-01 <_> - 0 -1 260 -720124792 -536901237 1570357663 -1650861895 - -552270619 -68301133 1302024703 79667599 + 0 -1 39 -20737 -21921 1387329791 -1145902337 -19250950 + -8502569 -126817537 -77082373 - -3.3839857578277588e-01 2.5523734092712402e-01 + -1.8133202195167542e-01 4.5872864127159119e-01 <_> - 0 -1 17 -8193062 -6097966 -1548746898 -379066394 143198346 - -645407521 12583050 -472923985 + 0 -1 136 -562084225 -588480681 -1099243521 506624528 + 1316756572 -84124547 -33784228 -365920720 - -2.4971115589141846e-01 3.2822373509407043e-01 + -3.9777505397796631e-01 1.8508131802082062e-01 <_> - 0 -1 237 -825768185 724487963 -390073602 -330379374 - 1107247415 83879931 -993921692 -452988933 + 0 -1 217 785362727 216853359 -402800844 -287899666 + 1395881781 1156951983 -134349248 -185271564 - -3.0709245800971985e-01 2.5717419385910034e-01 + -3.4530290961265564e-01 2.4639949202537537e-01 <_> - 0 -1 58 -824653104 303085300 -1502438950 676395390 - 1255626832 486565974 -815202689 -79167553 + 0 -1 68 -1062206256 1283745013 -34114723 -655764 1070420469 + 365214205 -805365315 -7516835 - -3.6309060454368591e-01 2.1628698706626892e-01 + -3.2642650604248047e-01 2.5048437714576721e-01 <_> - 0 -1 67 1465723394 105884335 67529631 1199566589 -1622165645 - 1811892772 1549268950 1652352758 + 0 -1 190 1474272223 1432203262 499659167 532543359 307625983 + 340797832 1059537791 1944010239 - -4.2343840003013611e-01 1.6860494017601013e-01 + -2.8207024931907654e-01 2.8570288419723511e-01 <_> - 0 -1 185 148088327 717657079 -1158484046 -2098532510 - 1870465024 1417516115 -834205 -218760204 + 0 -1 310 -48295664 -646879950 -749237799 -1153479021 + -1097202291 -33608429 -1514198007 146252931 - -3.6911985278129578e-01 2.0653814077377319e-01 + -3.7337026000022888e-01 2.1691022813320160e-01 <_> - 0 -1 300 -461242368 1477725653 -1215242820 -90145126 - 1009057732 -704735 -1141055496 -1162708353 + 0 -1 145 -54539121 1325248383 -1444411622 -1078132833 + 2097041119 1281153237 -135827344 1899100997 - -3.3464974164962769e-01 2.3336097598075867e-01 + -3.1012156605720520e-01 2.4879796802997589e-01 <_> - 0 -1 293 -1423237359 -1789315824 -574109707 -1107438219 - -1363603597 -872691976 -1657075536 -1933638287 + 0 -1 208 215618933 536625151 -537774081 -1073979708 + 1022653716 -1077149825 -1073987588 -1426440928 - -3.1273457407951355e-01 2.2250117361545563e-01 + -3.5794767737388611e-01 2.0182034373283386e-01 <_> - 0 -1 194 -144708057 1699343849 -1838157252 -177211402 - -159396385 625472608 -135793676 -521076854 + 0 -1 275 -460354046 75902886 -1114232776 144879392 + 1700742225 200101343 -20972316 -268435457 - -2.3151670396327972e-01 3.2311838865280151e-01 + -3.3210799098014832e-01 2.3649631440639496e-01 <_> - 0 -1 168 -1931608011 913325143 -171254849 266627963 - -2035524252 -69309961 -81258276 -98535933 + 0 -1 331 -1120698607 -1816316560 -1115727883 -771893903 + -1498071255 -1342570824 698559600 -1935190671 - -2.9178491234779358e-01 2.4896363914012909e-01 + -3.1769388914108276e-01 2.3492129147052765e-01 <_> - 0 -1 91 1087671428 82841500 -823391220 -1623396996 - -102804027 1314177621 -1141613796 -1074263479 + 0 -1 26 171629823 667944063 135529717 34762367 1819038997 + 1002177831 1348229755 2135252863 - -3.8546600937843323e-01 1.7542295157909393e-01 + -3.5822075605392456e-01 2.1465454995632172e-01 <_> - 0 -1 159 -933240178 -1878596882 1715175556 -1194366298 - 411894039 268454833 -470873276 719547915 + 0 -1 154 -637551088 286731008 -121898852 540119849 + -716208703 -1779023243 -386809896 1901461404 - -3.2228979468345642e-01 2.1430800855159760e-01 + -4.3143102526664734e-01 1.6342623531818390e-01 <_> - 0 -1 220 -939528673 -1404420134 -369182724 1002367802 - 15711733 -1410089155 1960793528 -2001995142 + 0 -1 184 1860151087 1929903535 1385154026 1995326315 + -186651217 1908896727 -1578172729 1690632140 - -2.3454265296459198e-01 3.0028054118156433e-01 + -3.0808129906654358e-01 2.3992852866649628e-01 <_> - 0 -1 113 536155908 470828324 -1369532674 -1364256937 - 965751798 -35376543 78916068 750088039 + 0 -1 261 -750652672 825569187 363565347 226880649 1425642663 + 1027652669 -1527280645 234220511 - -4.0617641806602478e-01 1.7761451005935669e-01 + -2.8312164545059204e-01 2.6677671074867249e-01 <_> - 0 -1 35 -2071666137 -5603018 -1985288769 -1434200 1335921899 - -1427144213 -1685518963 -1157538765 + 0 -1 283 -319861241 1113296810 -274206881 -358425573 + 2079722844 -400747690 -318934163 -10490913 - -2.4697369337081909e-01 2.9498186707496643e-01 + -2.8361973166465759e-01 2.6147827506065369e-01 <_> - 0 -1 229 -288895194 586300718 -1428684760 -123278042 - -121959099 946274053 -1125681616 1348531058 + 0 -1 100 1152141516 -134536513 1728012219 -613438294 + 289388027 -172525705 2052631547 523382314 - -4.4196075201034546e-01 1.6939437389373779e-01 + -3.5195887088775635e-01 1.9971875846385956e-01 <_> - 0 -1 21 -1431908781 2021291639 -1130434561 980837616 - 575372375 -335353565 -1127443082 -8913481 + 0 -1 250 1915726114 799985062 -863564618 -1796286242 + 1412398914 902102177 1130850167 -206571550 - -2.6150795817375183e-01 2.7675113081932068e-01 + -3.5833287239074707e-01 2.0236967504024506e-01 <_> - 0 -1 68 -1163937995 319737271 1308060341 -1120611591 - 215961812 -849912353 -825672464 -121636649 + 0 -1 95 -455700956 82848733 132951356 -67846796 -33744443 + 248862805 -1162704376 -1075833039 - -2.0028464496135712e-01 3.5346552729606628e-01 - <_> - - 0 -1 112 -1550874873 68414247 420172119 -1144260794 - -508579405 -134226281 -772565676 -204480722 - - -2.3316873610019684e-01 3.1222426891326904e-01 - <_> - - 0 -1 218 -541341454 531709016 -1735251873 1326185481 - -1933801064 801776562 1154066423 1474264822 - - -2.6953682303428650e-01 2.8109839558601379e-01 - <_> - - 0 -1 181 1280835701 -19635873 -1961789445 -282569314 - 2036092788 -1093054601 -151512323 -1347805666 - - -2.9192847013473511e-01 2.4838224053382874e-01 - <_> - - 0 -1 95 -311496552 764872328 -498934241 504728371 - -1669213988 -1084285404 -22094113 977657810 - - -3.2798394560813904e-01 2.1226845681667328e-01 - <_> - - 0 -1 309 -830243037 -455709770 -1109557600 -394303915 - 1283690960 229296318 285572161 -1936864027 - - -2.9578369855880737e-01 2.4679656326770782e-01 - <_> - - 0 -1 202 -353374409 -1910657629 -153750156 -291312600 - -824232155 -1323582188 -1830135484 -1029119357 - - -3.0753603577613831e-01 2.2499974071979523e-01 - <_> - - 0 -1 150 1861152279 336385887 -1598237261 1532541780 - 717032533 845016530 -1129812228 -567126192 - - -2.7896767854690552e-01 2.5912684202194214e-01 + -3.7909838557243347e-01 1.7440141737461090e-01 <_> - 32 - -1.3275781869888306e+00 + 24 + -1.2824541330337524e+00 <_> - 0 -1 235 -9764865 -604078086 -173773889 -2987398 1279545343 - -557388648 1149200335 1195863143 + 0 -1 80 -45825 -536920833 1280073215 495738239 -88473416 + -130820 -570238469 -71639553 - -2.8027681633830070e-02 5.9074550867080688e-01 + -1.6788482666015625e-01 4.4611564278602600e-01 <_> - 0 -1 55 -715992866 -553046580 -170277985 -572962233 - -202911505 -562080269 -271361 2136426523 + 0 -1 228 -572535553 397093339 -1062400257 1610558363 + 214714620 1068935571 68145083 532673471 - -2.9094350337982178e-01 3.2474684715270996e-01 + -3.1849989295005798e-01 2.7583411335945129e-01 <_> - 0 -1 2 -285213773 -97321424 -537973381 -1342251019 249102355 - 186786323 -1879110913 -269489669 + 0 -1 317 -1231 -1819561582 1911910833 1570722209 -1093 + -1685331270 -1076924144 -2002009685 - -2.4952219426631927e-01 3.3645749092102051e-01 + -2.7908280491828918e-01 2.8472077846527100e-01 <_> - 0 -1 274 -5251811 -46589657 -577170147 -1649982203 -147523 - -67650657 -307360312 -1945170545 + 0 -1 258 -1942309903 -1342795280 -4194443 -1073899024 + -1354893895 -1079265281 529358301 -1447062096 - -2.2803187370300293e-01 3.6403229832649231e-01 + -2.6034539937973022e-01 2.9407960176467896e-01 <_> - 0 -1 132 1587350780 -6418628 -1073864867 -604037841 - -21053701 -1195406672 784076557 -1342501334 + 0 -1 282 -486603761 538575875 2129538959 34218767 -573161380 + -70690275 -285287348 -2363473 - -2.9213908314704895e-01 2.7659067511558533e-01 + -3.4062975645065308e-01 2.0401223003864288e-01 <_> - 0 -1 176 -826544217 -1431112397 -488065488 540212786 - -722778748 1157429871 -270294508 -520884270 + 0 -1 291 -1349524722 -69233725 -1720626217 -536900587 + -2143975798 -12746304 118214239 1599029333 - -3.5402128100395203e-01 2.1517892181873322e-01 + -3.2409128546714783e-01 2.2399894893169403e-01 <_> - 0 -1 87 712975879 79833691 -1361412946 686460060 -691335585 - -125978095 -285512546 -1430258133 + 0 -1 120 -269775230 1408819148 -390615384 -8392706 -1057528 + 1464277268 -1276123648 2004090628 - -3.1391125917434692e-01 2.2734560072422028e-01 + -3.6182680726051331e-01 1.8862281739711761e-01 <_> - 0 -1 200 -976172866 286760680 6735455 198928110 1074026973 - 990905122 10809743 255401983 + 0 -1 78 521087406 894214626 828121640 -236406052 935394252 + 1426326282 -507511876 -138091528 - -3.5261881351470947e-01 2.0989060401916504e-01 + -4.3280023336410522e-01 1.7912270128726959e-01 <_> - 0 -1 224 774125429 -1154154632 -439675595 -1111523364 - 1012643517 -1454645 798207228 -1128575640 + 0 -1 349 196050803 -1364574018 2042330965 -841132080 + -1466964805 -1882464834 1636143569 -860888828 - -2.6199585199356079e-01 2.7558091282844543e-01 + -2.9185295104980469e-01 2.3511406779289246e-01 <_> - 0 -1 251 -487657822 48661756 -659241758 -135899942 - 1153834238 10993310 1170301815 1424455655 + 0 -1 19 -21018037 1783262287 -1597196625 -1442780128 + -414100906 -277852304 -355078554 -46081177 - -4.2886912822723389e-01 1.5836857259273529e-01 + -2.9949510097503662e-01 2.4424977600574493e-01 <_> - 0 -1 61 721311231 -1653716997 -1990311447 531501487 - -1965404323 -67478251 171464059 184576600 + 0 -1 12 49418002 -2003701765 -313130209 -2000720353 + 1219644673 -285278209 -872858825 1123765061 - -3.8873490691184998e-01 1.7470200359821320e-01 + -4.4975990056991577e-01 1.4456595480442047e-01 <_> - 0 -1 57 327418278 390873324 -1341550100 -1277569843 - 890828715 1352696428 762946218 871965384 + 0 -1 52 -364085048 491458118 -675123209 -541193660 + -839658244 -262730335 -604312834 2115044436 - -4.1405329108238220e-01 1.7622730135917664e-01 + -3.9896175265312195e-01 1.7343275249004364e-01 <_> - 0 -1 313 1356549140 -1631210850 -1129431843 -1204505275 - -93539215 -1074227267 -386080853 -84902083 + 0 -1 160 -470817137 156157702 -1967203869 -772802881 + -246418489 1363658693 -218633237 -245891170 - -2.7681437134742737e-01 2.4316167831420898e-01 + -2.1532715857028961e-01 3.3184850215911865e-01 <_> - 0 -1 157 -488643058 180875078 -329274718 -236520514 - -1068514035 1145270019 1940253924 1625680036 + 0 -1 175 -352409586 -1190861826 -1642823092 -71631894 + -923852796 1998658431 -399708968 -11345840 - -3.7754905223846436e-01 1.7737720906734467e-01 + -2.8774553537368774e-01 2.3346234858036041e-01 <_> - 0 -1 318 1568653099 -1486684233 -270730127 -320215680 - -1480112719 -1448552587 444420880 -859837569 + 0 -1 178 1146397583 1440677111 1789980602 -168959196 + 1607858623 1003980783 -95098146 -520838912 - -2.4140998721122742e-01 2.7932175993919373e-01 + -2.7916902303695679e-01 2.3335020244121552e-01 <_> - 0 -1 189 -17905025 1950769147 -402672769 2131932059 - 251095909 -1377736845 -268624424 1935896624 + 0 -1 352 -50332877 -1350565899 -589480591 -849224360 + -2014845531 -1930707058 -1980770927 -857737763 - -2.4894605576992035e-01 2.6565098762512207e-01 + -1.8601153790950775e-01 3.3500474691390991e-01 <_> - 0 -1 56 -229980658 1379962893 -378530289 -1286386082 - 541532620 -136587009 1094085135 657713951 + 0 -1 116 -679517179 235021312 -2015978753 -308288545 -3083 + -1148969 572941047 -1531453593 - -2.9520252346992493e-01 2.2449728846549988e-01 + -2.8746202588081360e-01 2.3165051639080048e-01 <_> - 0 -1 271 -383212128 -6160449 -283244184 -1365334076 - 762609077 1768025015 -304497187 -1344499269 + 0 -1 246 -283094 -78995521 989667876 -388040262 1269563143 + 376496915 -180422212 1906376566 - -2.8447866439819336e-01 2.4520753324031830e-01 + -3.3096152544021606e-01 1.9776308536529541e-01 <_> - 0 -1 212 -823677149 33812366 63268002 -1196492664 759909893 - 73716507 -306223978 -151718043 + 0 -1 97 -182451973 -202104337 -1497597953 -141604069 + -417856360 -236145225 -14023781 -1308484861 - -3.2939437031745911e-01 2.0377136766910553e-01 + -2.5251045823097229e-01 2.6549828052520752e-01 <_> - 0 -1 312 -1374019853 713820810 -669067463 -2043769806 - -847767619 -1963069954 1575449037 -450464140 + 0 -1 298 1873775874 -1934907533 -1096029424 -930612685 + -2068250556 -1915946543 1105810433 -977930811 - -3.0366918444633484e-01 2.2024095058441162e-01 + -4.1322487592697144e-01 1.5656088292598724e-01 <_> - 0 -1 114 -470316922 717621094 -923928028 -172110089 - -175398463 2009855399 -194461440 -243275802 + 0 -1 327 -559975688 -1098343184 56689852 -541071107 + -1096812098 -1650825224 -821928707 -570434053 - -2.6190644502639771e-01 2.6647549867630005e-01 + -2.2519363462924957e-01 2.9129114747047424e-01 <_> - 0 -1 140 1951769299 1434447053 -1336849665 -721425681 - -78677193 -2902011 2045245095 -24300714 + 0 -1 322 1760817168 2014969105 -1342718095 -115803287 + -1804093744 -249891400 -828918088 -1133191201 - -2.2465880215167999e-01 3.1657159328460693e-01 + -2.5303143262863159e-01 2.6384234428405762e-01 <_> - 0 -1 267 -861210968 688568240 -1004941864 -35890713 - -662335344 8503434 1128813796 1162868189 + 0 -1 201 -337401329 79624186 -157749454 -2107704234 + 2136683024 1450477407 -277792234 -789447723 - -4.0748140215873718e-01 1.7012281715869904e-01 + -3.5275053977966309e-01 1.8988111615180969e-01 <_> - 0 -1 8 1909956778 -958730002 73759065 117326543 -170462666 - -1638796928 -144999309 1180628626 + 0 -1 85 1483955794 880441222 1177964078 -1207814558 + 1556696189 -13904937 -805344549 -21761033 - -3.5050147771835327e-01 1.8371912837028503e-01 - <_> - - 0 -1 156 -1007695481 -1609761269 -218186094 -1297941718 - 1501545350 1348355905 -785383567 -535441850 - - -2.8428241610527039e-01 2.3429898917675018e-01 - <_> - - 0 -1 277 -1088815371 1060734832 -4223497 1069000375 - -1138325508 -23580996 -1751106129 -1447097814 - - -2.0420564711093903e-01 3.2137596607208252e-01 - <_> - - 0 -1 10 1861672606 -668397946 1208024407 1141008467 - 793079834 440603748 -705639574 -48042237 - - -2.7496239542961121e-01 2.4548499286174774e-01 - <_> - - 0 -1 283 -992769979 767790999 -48337487 2140880143 215229748 - 418870965 -320966916 1188940671 - - -2.7034837007522583e-01 2.4777430295944214e-01 - <_> - - 0 -1 254 -1532809423 -1493812843 -1351098395 -172312296 - -515160205 -1498547284 268291320 -1426238432 - - -2.8834709525108337e-01 2.2686660289764404e-01 - <_> - - 0 -1 298 -3221657 908227842 -305164460 942829106 -357061387 - -1565722789 -9463718 -360710886 - - -2.2364138066768646e-01 3.1509658694267273e-01 - <_> - - 0 -1 93 -735960950 -170126554 1909113855 -23709394 - -1542321238 -737632549 -361625941 867181313 - - -3.6416807770729065e-01 1.8943277001380920e-01 - <_> - - 0 -1 297 -1427114189 -1498618581 -224896028 -1392720912 - -1096677881 -972078302 -136092556 -1000345005 - - -3.1630918383598328e-01 2.1302369236946106e-01 + -2.9593563079833984e-01 2.2950462996959686e-01 <_> - 36 - -1.3241410255432129e+00 + 25 + -1.1346004009246826e+00 <_> - 0 -1 264 -1886982258 -671648799 -570864297 -606221228 - -1899852152 -3292975 236208719 1600077909 + 0 -1 135 248384512 -2230281 -67167425 -278721 -1430323288 + -4097 -1364709878 -1427136853 - -7.9810082912445068e-02 5.2391374111175537e-01 + -2.7531594038009644e-01 3.4290844202041626e-01 <_> - 0 -1 226 -85990657 570624531 -67109121 992976191 -386251554 - -1965159927 -83923475 -1048581 + 0 -1 192 1473642495 274004474 933182335 500809723 1997913085 + 487862028 2077977039 1608383199 - -1.8287384510040283e-01 4.4005623459815979e-01 + -2.5518363714218140e-01 3.2124108076095581e-01 <_> - 0 -1 278 -37758029 -1146357328 -206212751 -572669447 - -3147333 -1147409733 -67110471 -1714697285 + 0 -1 150 -671627180 1440067463 -55773956 -252462474 + -212729877 -1744769111 -298451490 805420943 - -2.0388080179691315e-01 4.2895537614822388e-01 + -3.4691503643989563e-01 2.3676414787769318e-01 <_> - 0 -1 145 -183247173 1023475216 1027163441 1527839249 - 1017224859 1738217629 1060840379 1065315199 + 0 -1 3 -186646854 -72960256 -822609825 -856193 5046414 + 733941519 1287603359 -129 - -3.3740916848182678e-01 2.1529236435890198e-01 + -2.4629610776901245e-01 3.0966648459434509e-01 <_> - 0 -1 103 481318143 -134278060 -1749526563 -1078064995 - -1372435270 -1162474278 -358945793 -1431173974 + 0 -1 324 -1334507507 -1115837163 -1198804579 1034753295 + -237926227 -69613103 -269694261 -2138504179 - -2.8765675425529480e-01 2.5110965967178345e-01 + -3.6555841565132141e-01 1.9017384946346283e-01 <_> - 0 -1 268 -805831759 -302189077 -591401807 -305135631 - 144606625 -1936723969 -992408563 -855769927 + 0 -1 45 0 -824089359 -278966017 -749744779 8831144 + -347413507 -1475415988 -855648819 - -2.2018201649188995e-01 3.1721305847167969e-01 + -3.4803688526153564e-01 2.1789649128913879e-01 <_> - 0 -1 20 -534756686 1380106992 -2462279 -33757488 28591869 - -456875269 -1610624779 -1051657 + 0 -1 340 1112532642 1173963979 -811315745 99566887 + -777275981 -439360269 -376451157 133893287 - -2.6303508877754211e-01 2.5412750244140625e-01 + -3.0945461988449097e-01 2.2969539463520050e-01 <_> - 0 -1 175 1342137858 36560521 -895533800 683603905 1263879488 - 1146407324 -1450126 -537788681 + 0 -1 297 185535267 790098739 711963921 -268439240 218058052 + -294925 -1396768448 -2100139 - -3.6383235454559326e-01 1.9057570397853851e-01 + -3.6581969261169434e-01 1.7462332546710968e-01 <_> - 0 -1 66 1340125183 -134742145 -692979981 -1214109056 - 1289101223 -4839633 -21061633 -369409502 + 0 -1 292 -21844242 -6605322 -1616468484 -536912933 + -1499165960 -1126293580 925141758 -20448289 - -2.0452670753002167e-01 3.3919993042945862e-01 + -2.5863876938819885e-01 2.6582530140876770e-01 <_> - 0 -1 269 193720319 100840569 -303833102 763156184 978053077 - 531299573 -839056136 -1929622308 + 0 -1 304 522433969 772063152 -1143210539 -1383027464 + -1405567063 -1431049791 221093305 -1933786908 - -2.7057421207427979e-01 2.3806059360504150e-01 + -2.9382315278053284e-01 2.4171116948127747e-01 <_> - 0 -1 73 1437966890 -129122561 1958795834 1556596447 - 1598142386 1074702522 -272384141 1205144459 + 0 -1 119 -202381694 -798150994 -5573602 -41028290 + -1178601783 -77728283 -135801400 -145231988 - -3.8338547945022583e-01 1.6122914850711823e-01 + -2.2170369327068329e-01 3.1273341178894043e-01 <_> - 0 -1 171 1115680527 115249619 895027446 -92284851 1599078213 - 1735769988 -537445018 1689910980 + 0 -1 128 -203439442 280484343 -191502652 1082521539 + 1518288386 574050238 -360088850 -84153089 - -3.6433032155036926e-01 1.7980493605136871e-01 + -3.2988098263740540e-01 2.0559535920619965e-01 <_> - 0 -1 144 1900011604 2069139451 1149891166 -1061030506 - 1967646922 -937402003 -1292100642 838974267 + 0 -1 36 -1473073466 1917855318 -364848516 1483753731 + 522944080 -1504285156 -282021901 -79439061 - -3.2297107577323914e-01 1.9990013539791107e-01 + -2.9433536529541016e-01 2.1896927058696747e-01 <_> - 0 -1 86 1216302162 1437731410 -1922152432 -586510344 - -937599750 1065827099 -621007040 -86024589 + 0 -1 185 -270062289 741719453 2088717183 -159405089 + -1063525273 -201780627 -990061324 -189792529 - -2.9406809806823730e-01 2.1769714355468750e-01 + -2.8305205702781677e-01 2.3085375130176544e-01 <_> - 0 -1 288 34597026 -688274366 1187213567 -671108889 - -1508901182 -1308638469 -559091031 247438496 + 0 -1 64 781209199 -604801249 -137056771 -1644152576 + 1425768019 -4985945 -33825329 -352630170 - -3.2822206616401672e-01 1.8776336312294006e-01 + -2.5803419947624207e-01 2.3583941161632538e-01 <_> - 0 -1 207 103046517 133606652 1733190463 -1346628911 - -1148684048 -22091807 901613945 -1460139888 + 0 -1 218 -684139841 891109289 -2146903425 497252031 + 1814861009 1063463728 69532089 1061139391 - -3.3780130743980408e-01 1.9073766469955444e-01 + -2.3609955608844757e-01 2.6694893836975098e-01 <_> - 0 -1 111 -746085629 -676994367 1095924655 -1122388257 - -212397823 -202506293 -205057719 -208672818 + 0 -1 195 1560171645 -1625665705 -1891663905 -1109320513 + -127236 -67273237 -268804357 -5614422 - -1.8210665881633759e-01 3.4192490577697754e-01 + -2.2031366825103760e-01 2.8743496537208557e-01 <_> - 0 -1 74 -425549783 -371579759 -351371857 -575060349 - -1214609473 -88295489 419684031 -1624088569 + 0 -1 289 -368723304 -1087131273 -2028144723 465693884 + 1523430298 -71370269 -1182790141 144305137 - -2.2647747397422791e-01 2.7878209948539734e-01 + -3.6453738808631897e-01 1.7253066599369049e-01 <_> - 0 -1 208 -894491986 -219288836 1075036258 -1764754717 - -573582558 -1807733298 1383817634 -196806592 + 0 -1 199 787998475 677575591 -739252480 -285290066 508918644 + 1719481202 -179306992 -51386418 - -2.9377350211143494e-01 2.1309736371040344e-01 + -3.0859819054603577e-01 2.0732647180557251e-01 <_> - 0 -1 201 -2106874097 -931096794 1687396770 -828052004 - 2015982962 -126682795 -294764796 -323961156 + 0 -1 14 -221256090 -30629334 -1778521617 -141047802 70346658 + -453359515 1744520459 -268644849 - -3.2405611872673035e-01 1.9604462385177612e-01 + -2.7200087904930115e-01 2.2423355281352997e-01 <_> - 0 -1 222 -2042653379 1051606960 500611353 1069291288 - -1453967943 -1919900749 -547038872 -1414655812 + 0 -1 142 1622928902 583970724 1109312096 1904539840 + 1969219012 1980786278 1948496000 1911025111 - -2.6115354895591736e-01 2.3542492091655731e-01 + -3.3403554558753967e-01 1.9454947113990784e-01 <_> - 0 -1 314 -588537600 -844176924 1464154596 -637687780 - 487338116 68063409 -1978163723 -840968737 + 0 -1 112 -295762925 915309558 -1095828421 1019540600 + -1141749996 -1192305118 -17631630 -903815374 - -2.7114504575729370e-01 2.3290830850601196e-01 + -3.0503559112548828e-01 2.0471774041652679e-01 <_> - 0 -1 317 120290097 -1288032431 1651243885 -76200631 - -2068365766 -1346655489 246316733 -1108265899 + 0 -1 330 1865153393 185138952 -955431147 431881140 698022290 + 142707862 1294169361 217054693 - -3.0526432394981384e-01 2.0446150004863739e-01 + -3.3315172791481018e-01 1.9509385526180267e-01 <_> - 0 -1 16 -822121865 -768454985 -352395443 -367512593 - -1091080379 -202815919 -279024202 -28119438 + 0 -1 50 1057818511 484285945 -170124612 1005093883 + -1156844547 1371617765 -69795876 -1257986355 - -2.4680423736572266e-01 2.5303974747657776e-01 + -2.9253959655761719e-01 2.2863319516181946e-01 <_> - 0 -1 39 -624497410 423430210 168884479 707847256 -901496725 - 2133000198 -1135412149 1936933458 + 0 -1 216 567255330 -707734926 -925572514 -624041174 + 1433628799 21294608 156263627 -721438458 - -3.1653416156768799e-01 2.0023956894874573e-01 - <_> - - 0 -1 242 1650942474 1345050478 886355088 1168828219 - 1112207884 1231876612 1550108076 1951460330 - - -3.2898175716400146e-01 1.8093948066234589e-01 - <_> - - 0 -1 124 369300756 891056133 -1916674564 -1374783349 - 996154237 -1145226207 -5607004 744775764 - - -3.2225444912910461e-01 1.9573701918125153e-01 - <_> - - 0 -1 211 205577554 1071184148 -1263948549 1998946051 - 1260935961 -304903199 -606843718 1677159567 - - -3.0931469798088074e-01 2.0338173210620880e-01 - <_> - - 0 -1 143 -591418226 177508317 -1342069760 -4867939 - 1927953629 272683209 -1222155904 1886512754 - - -3.4405741095542908e-01 1.8495233356952667e-01 - <_> - - 0 -1 265 -21049686 -28131359 1073478397 -34340880 - -2075882246 -1093124168 -64807690 -1243108611 - - -2.2883313894271851e-01 2.9109308123588562e-01 - <_> - - 0 -1 307 781346419 639805680 -546181353 -1174989674 - -1555551183 -893031525 -2006836811 -1392561707 - - -3.0891278386116028e-01 2.1537151932716370e-01 - <_> - - 0 -1 134 -26563529 576995058 1442217478 -1427177744 - -68769859 -1241776649 -424779152 -285805586 - - -2.3855516314506531e-01 2.6137462258338928e-01 - <_> - - 0 -1 178 -491860352 1783772447 -1761018371 989361018 - 2037451840 -988741302 2128769468 1865931536 - - -3.3605426549911499e-01 1.9781108200550079e-01 - <_> - - 0 -1 59 -1359078146 -21349537 1081098827 794979703 147593312 - -343136234 308281456 -1121813221 - - -3.4179690480232239e-01 1.8693566322326660e-01 - <_> - - 0 -1 131 -467418588 607934740 -510185553 -839002645 - 2000942967 1793376114 710533396 209909344 - - -3.9927759766578674e-01 1.5319514274597168e-01 - <_> - - 0 -1 6 -251463749 -1087866735 954640701 -1345720208 - 257393053 -1721918337 71237772 -522239782 - - -2.0329028367996216e-01 3.1257370114326477e-01 + -2.8726491332054138e-01 2.1820212900638580e-01 <_> - 36 - -1.3515049219131470e+00 + 25 + -1.2997064590454102e+00 <_> - 0 -1 121 -583157832 -41345124 -1667477754 -47472728 - -1631649861 -192782657 -1106464817 1060048799 + 0 -1 296 -1372705244 -53892 -276885633 -1880289792 + -620822785 -393217 -142745633 -268474549 - -6.6292375326156616e-02 5.3096652030944824e-01 + -2.2954036295413971e-01 3.6702767014503479e-01 <_> - 0 -1 250 -961874181 -589629441 -202714187 -33687726 - 246352127 -1125919869 1090470655 1441756927 + 0 -1 69 -10514724 -1625446526 -12058789 1028355882 + -106955041 -6565701 -146018337 1599032783 - -2.9468271136283875e-01 2.9257065057754517e-01 + -3.4712401032447815e-01 2.4896951019763947e-01 <_> - 0 -1 284 -219161456 1561959797 -1157910723 -644253203 - -37769852 -1175163461 -358812998 -1146105857 + 0 -1 76 -1430331393 -1752738851 226721247 1059010911 + 145900799 -1429468513 615153631 988436415 - -2.2191908955574036e-01 3.5355353355407715e-01 + -3.3930867910385132e-01 2.3344205319881439e-01 <_> - 0 -1 133 -1395773932 -19337 -872592385 -1082417169 - -268501000 -203988001 -1360523750 -1430265925 + 0 -1 270 -506747998 -1362439710 -745936942 -39853582 + 1334757315 -124603168 2009421779 -672148493 - -2.6642906665802002e-01 2.7330449223518372e-01 + -2.8237146139144897e-01 2.7164348959922791e-01 <_> - 0 -1 89 937245647 533051903 22876957 837784063 -113164289 - 1593942211 1207413693 1942338443 + 0 -1 321 -4203299 1360986883 -3412641 956312066 -171979299 + -315445 -1843240 -80744689 - -3.1208184361457825e-01 2.1690289676189423e-01 + -2.1301591396331787e-01 3.5703513026237488e-01 <_> - 0 -1 245 -135270614 1911454511 -694266878 1894711038 - 1380414469 1078062543 -200939772 1616172018 + 0 -1 149 -689977121 -662996513 -1725966451 2068778907 + -251700994 419184760 -93683841 -99614885 - -3.7340530753135681e-01 2.0424529910087585e-01 + -2.3296064138412476e-01 3.1665518879890442e-01 <_> - 0 -1 79 -673199910 2132653981 -1105191310 -1622098985 - -279161640 1874615084 2066898922 -82575381 + 0 -1 309 -285179488 -9441281 1043235368 -1342265362 + 874839541 2133912549 -1032021509 -1392732225 - -2.7581161260604858e-01 2.3679631948471069e-01 + -2.8806942701339722e-01 2.2282725572586060e-01 <_> - 0 -1 108 -88609193 -764250339 -21964208 1785903000 - -705804525 -281542881 -17301633 -29425689 + 0 -1 114 1475815183 2107337983 -224023574 -2176766 + 2147067887 1876795342 1818099336 1707645312 - -2.1142585575580597e-01 3.1125506758689880e-01 + -3.1313076615333557e-01 2.1244764328002930e-01 <_> - 0 -1 287 2117156824 2142892795 -1715733421 -1118208017 - 1981329130 -1132205343 -531030662 218086646 + 0 -1 329 -1657544715 -1145500528 997257077 503141457 + 763625151 -1430741832 153165617 266033296 - -3.1311789155006409e-01 2.2028388082981110e-01 + -3.0358061194419861e-01 2.2090645134449005e-01 <_> - 0 -1 217 657173799 1208409516 -304231172 -319884740 - 829234695 822389124 -1816709292 -725510 + 0 -1 177 1147035391 -50398729 -8725505 1072834859 2090734480 + -115489 -570483718 -270631374 - -3.4273931384086609e-01 1.9222305715084076e-01 + -1.8830235302448273e-01 3.3752456307411194e-01 <_> - 0 -1 270 -102301694 -135807070 -1880672401 -253298777 - -354657254 -100668629 2011055773 -155453461 + 0 -1 299 -1356597325 -1388052592 -847288592 -314052611 + -1927458391 -896273511 -1943219992 -855777356 - -2.4226696789264679e-01 2.7088710665702820e-01 + -2.6349818706512451e-01 2.4316447973251343e-01 <_> - 0 -1 191 215240020 -1148310119 -707214049 -1112003969 - 1860719544 -6638593 -4317491 -1414921888 + 0 -1 91 1683333818 -928527617 73759575 1290403503 1430371123 + -103067615 1875204903 1786229266 - -3.1184914708137512e-01 2.1366736292839050e-01 + -3.6631527543067932e-01 1.7680935561656952e-01 <_> - 0 -1 18 -873476105 -30229647 -168296643 -1682912767 - 161284371 -1972125919 -12305 -268965957 + 0 -1 75 -723572486 1398781951 2102550384 -15679489 + 1677216988 -883140642 -552403973 -619446289 - -2.1284404397010803e-01 3.0867013335227966e-01 + -2.4558630585670471e-01 2.6674869656562805e-01 <_> - 0 -1 289 -449986302 74968807 2145360303 20911369 1088274818 - 1642837031 -1026366551 53429507 + 0 -1 31 -909118669 -1568492624 -15803021 -1602693664 + 1276055058 203659013 2128997939 -285229957 - -3.2960832118988037e-01 1.9843052327632904e-01 + -3.1990760564804077e-01 1.9987310469150543e-01 <_> - 0 -1 187 -294473945 1289282231 -69736418 -366809570 - 585961254 -894112782 -352349116 -857431116 + 0 -1 153 -641211774 456884155 -371067230 828505907 + 1660797068 1414657751 -654513950 -260707437 - -3.4131202101707458e-01 1.7822383344173431e-01 + -2.5050690770149231e-01 2.5742626190185547e-01 <_> - 0 -1 117 -260075316 810653599 -307212416 -1090154618 - 1085218542 2014454434 -889360754 840974879 + 0 -1 24 -229906089 -739840258 535355359 -1513324470 + -706239233 -106463539 396649887 -2030041851 - -2.8617727756500244e-01 2.1801990270614624e-01 + -2.5204655528068542e-01 2.6508477330207825e-01 <_> - 0 -1 32 683352887 144804986 883838777 -470815534 749351701 - -1376201987 -1007927147 -269498899 + 0 -1 16 -956904237 -900393 744684798 440408308 1474759700 + 2144675413 -1203478660 -15336458 - -2.7213591337203979e-01 2.3029308021068573e-01 + -2.3463597893714905e-01 2.7154859900474548e-01 <_> - 0 -1 160 -221779237 2055449126 1356126973 1739434813 - -69756111 -78052576 -724205593 927834891 + 0 -1 245 -53498110 -768948404 114700466 -262216722 + 1751010824 1074124611 1456993248 1358295782 - -2.1148133277893066e-01 2.9901567101478577e-01 + -3.6311113834381104e-01 1.7788498103618622e-01 <_> - 0 -1 139 -327161337 -541288917 -1074706625 2069214763 - 1422886542 -570618263 1425911455 1965665867 + 0 -1 103 -2450246 -1080320589 1308138658 825785752 482925554 + 487604154 -283631617 -72380437 - -1.9790525734424591e-01 3.1719624996185303e-01 + -2.4650368094444275e-01 2.5755673646926880e-01 <_> - 0 -1 12 -286652406 -1499051796 -2055991469 557910223 - 226286607 -307013288 537285247 1340571263 + 0 -1 126 1058870580 903144469 -83886593 -1392513810 + -1611137039 -33792596 2145253024 -1402167248 - -3.5588899254798889e-01 1.8802331387996674e-01 + -2.3422972857952118e-01 2.8370600938796997e-01 <_> - 0 -1 204 -440754172 -1969605175 -11230786 -1369112738 - -164163787 -439228643 -440438364 -855854880 + 0 -1 222 70522484 -1663270860 2006973951 737044894 734095092 + 2113182189 -1113780932 -1398140368 - -3.3756810426712036e-01 1.8606249988079071e-01 + -4.2064115405082703e-01 1.4178343117237091e-01 <_> - 0 -1 54 -2103276886 1587028506 -1920974049 -382890163 - -50953603 -625169247 -75998374 847320848 + 0 -1 326 1107681440 1184465408 1697245882 -575681545 + -1209274896 -441716737 -274206977 -1497652999 - -3.3854812383651733e-01 1.8501213192939758e-01 + -2.6777487993240356e-01 2.3421689867973328e-01 <_> - 0 -1 149 -912264192 1437763456 -117442116 1477965101 - -109596288 -782313675 -520249859 -174065925 + 0 -1 238 -876378345 -2002059937 -402854058 2047008718 + -977546123 96466271 -724044704 -855902004 - -2.3874689638614655e-01 2.6692461967468262e-01 + -2.6567915081977844e-01 2.4086490273475647e-01 <_> - 0 -1 179 -74761 -1193108610 -1627717634 -1141359812 - -1350594860 -1212204947 -1900803076 -68466436 + 0 -1 215 -939802373 1936008783 249448665 -1680407978 + 1336956126 721695808 1217691803 968323227 - -1.8434369564056396e-01 3.4898519515991211e-01 + -2.6731696724891663e-01 2.3347604274749756e-01 <_> - 0 -1 320 -806388957 -1603323478 -319904391 -1889144109 - -1427144299 -1074553867 -1577597820 -822218338 + 0 -1 235 1312794114 5408 -1306041678 -1593904412 2071675925 + 373612661 1106728032 -51052590 - -1.9554206728935242e-01 3.1441712379455566e-01 + -4.5101743936538696e-01 1.3724696636199951e-01 + + <_> + 26 + -1.3585999011993408e+00 + <_> - 0 -1 13 -495530405 -1200567737 -562818530 1426283955 - -646798267 -42047966 -283939201 -15210669 + 0 -1 99 -16253125 -1862205680 924703251 353705495 18354879 + -1646443061 1061106495 521109375 - -2.0684894919395447e-01 3.0842429399490356e-01 + -2.6204770803451538e-01 3.2944434881210327e-01 <_> - 0 -1 227 -204473205 -111677525 1659697788 -168822810 - 164468462 95878471 1418323918 -705698930 + 0 -1 106 1589402879 2111243421 -1921360385 498991519 + -1430778630 -1095235424 -299958273 -1415968598 - -1.5447042882442474e-01 4.0702703595161438e-01 + -2.9923591017723083e-01 2.6061478257179260e-01 <_> - 0 -1 122 332207055 1368372207 1371537916 1541155303 - 1377022927 1195687084 -845629564 -191055413 + 0 -1 256 -269500670 -1934972022 -212386444 -340983920 + -840985607 216660013 -838930280 -855967046 - -2.6908680796623230e-01 2.3349469900131226e-01 + -3.1109735369682312e-01 2.4578146636486053e-01 <_> - 0 -1 183 2095555624 -1858958714 880848550 -1086881165 - 1278302507 2017585116 -2100032289 83174071 + 0 -1 290 -785411968 -793272784 -1244701525 -1863077704 + -252760056 -138438225 -325343096 -1934628726 - -3.3865603804588318e-01 1.8762224912643433e-01 + -3.1990429759025574e-01 2.4755740165710449e-01 <_> - 0 -1 257 -1599264894 1347540775 548331985 566406079 - -490018643 2125284619 -542620802 -507647254 + 0 -1 210 -69535757 858989363 -101122561 -1154744385 + -1426397852 787417871 -1394279747 -1049665 - -2.4964332580566406e-01 2.5305619835853577e-01 + -2.4644587934017181e-01 3.1389617919921875e-01 <_> - 0 -1 153 -928904029 -73474081 -431055591 -1365072480 - 1082731439 -1163105435 -401696790 -331068832 + 0 -1 33 44994211 548056274 1050609429 -269234960 235348991 + -1461066343 133104023 -536881691 - -2.4641251564025879e-01 2.5806349515914917e-01 + -3.0615699291229248e-01 2.1291562914848328e-01 <_> - 0 -1 261 -1551324256 227211248 -139191220 -1912739520 - 1712117749 1864425601 1605297047 232734801 + 0 -1 169 -19927354 -998541361 -1031864744 548925694 + 2058738946 1086813587 -117441590 -236978209 - -3.6956688761711121e-01 1.7259617149829865e-01 + -2.8440350294113159e-01 2.4974717199802399e-01 <_> - 0 -1 37 2062683840 -1171226870 -634334626 -42988729 - -177907627 1819501884 -1554858149 -81568901 + 0 -1 225 -403723614 -137498998 12815458 -201331990 + -143659953 -292815449 -1025137984 -146418144 - -2.8280401229858398e-01 2.3210345208644867e-01 + -2.7793189883232117e-01 2.1837951242923737e-01 <_> - 0 -1 101 -52896752 2073648803 -104703392 -1877326687 - 1482183868 486564792 -1181155586 -1078764545 + 0 -1 8 -245367841 -2134021 1724214226 -33737026 -546361345 + 2104391438 -235029522 1894053750 - -2.6182973384857178e-01 2.4921841919422150e-01 + -2.3921246826648712e-01 2.5940048694610596e-01 <_> - 0 -1 119 931876834 -1689820513 -175925869 295803187 - 1288847768 -1394638455 -527053926 -1609099725 + 0 -1 110 -50344201 2021002463 -295113026 503381792 + 1802897488 -1216649 -649569682 -29165030 - -2.8890526294708252e-01 2.2244787216186523e-01 + -2.3499047756195068e-01 2.6225870847702026e-01 <_> - 0 -1 23 674383927 640705886 -1980567045 775069703 941246324 - -1074502869 821615185 -1439559299 + 0 -1 122 -789934932 1559100927 -1917276468 -484037 + -573975107 1557186265 -1157693928 -13043150 - -3.7707689404487610e-01 1.7476500570774078e-01 + -2.7699887752532959e-01 2.1751758456230164e-01 + <_> + + 0 -1 243 -1356859599 -2071938592 -1711301131 -1108552207 + 1067300539 -1648756997 -1988182799 -2007106383 + + -2.2797892987728119e-01 2.6686671376228333e-01 + <_> + + 0 -1 100 1414807752 -136118094 1570099167 1610550975 + 1428132782 -1565038658 1393646523 59441770 + + -3.6224871873855591e-01 1.7005157470703125e-01 + <_> + + 0 -1 198 -1372390622 -1105023217 43974655 -1372390929 + 1012170358 -1352684673 229665733 1794436783 + + -3.7763473391532898e-01 1.4173112809658051e-01 + <_> + + 0 -1 316 638615286 -1109868352 524464629 -1113590375 + 964831210 -1371914704 153292152 -1346434008 + + -3.1874561309814453e-01 1.9032885134220123e-01 + <_> + + 0 -1 305 -269486329 -1908425238 -1208756943 -323096206 + -1547964669 -1433756185 -1767970460 -924320141 + + -2.5788185000419617e-01 2.3276108503341675e-01 + <_> + + 0 -1 193 918434045 498645434 798903545 -1142289332 784082164 + 1851118315 682499324 -340128680 + + -2.8957661986351013e-01 2.0316053926944733e-01 + <_> + + 0 -1 55 -905778490 67121822 -1743743400 -2012053637 + -1636832684 -917214628 -17762321 2135162719 + + -3.3608233928680420e-01 1.7717513442039490e-01 + <_> + + 0 -1 29 -1758265669 915073431 -283673347 -948315937 86215958 + -1624023241 90637669 -823733761 + + -2.1280290186405182e-01 2.7446863055229187e-01 + <_> + + 0 -1 285 -8461782 -86087006 -687954246 -521941938 -614269955 + 1611715303 -151198213 1958209278 + + -2.6345619559288025e-01 2.2300323843955994e-01 + <_> + + 0 -1 212 -1832397616 -766332258 -412702245 -1292380803 + 1220365911 -822484818 -282100849 1398793395 + + -2.9608255624771118e-01 2.0772157609462738e-01 + <_> + + 0 -1 62 -872994057 1071450172 -1104786213 -317692670 + -67746216 -50513552 -88453541 -128910506 + + -2.5465941429138184e-01 2.4114270508289337e-01 + <_> + + 0 -1 10 81939939 183556950 -539144585 -353355856 165875573 + -1782603781 -338732685 -491295903 + + -3.2701194286346436e-01 1.8006059527397156e-01 + <_> + + 0 -1 134 1886692082 -1729102165 542420273 631107582 + -546201661 1476403972 -169532509 1997277933 + + -3.5394954681396484e-01 1.6798554360866547e-01 + <_> + + 0 -1 311 -1700548176 -1715829716 -1343244964 -1155942204 + -53954163 -27257407 -1547772419 -2131951339 + + -3.2425084710121155e-01 1.8224255740642548e-01 + <_> + + 0 -1 203 -490033404 -1438717153 1991554832 -1507676246 + 801593156 -1468572866 -17199788 -391776096 + + -3.5948479175567627e-01 1.6648940742015839e-01 + + <_> + 29 + -1.1730608940124512e+00 + + <_> + + 0 -1 338 -793735168 -175047596 -35594563 -1145503875 + -99305999 -8398955 -71640065 -71630853 + + -2.0565655827522278e-01 3.6647084355354309e-01 + <_> + + 0 -1 58 -1388802 -135286154 -1154293889 689875534 + -1412562742 -2424758 -81338657 -13958585 + + -2.5342568755149841e-01 2.9973617196083069e-01 + <_> + + 0 -1 273 -424689729 1793992298 -69797944 -47701166 147718827 + 217783198 1417368059 1174403067 + + -3.0622813105583191e-01 2.2849719226360321e-01 + <_> + + 0 -1 162 -421534290 -481301273 -343938830 -202899458 + -756039285 1195863875 -218106116 -169345076 + + -2.2961020469665527e-01 2.8787249326705933e-01 + <_> + + 0 -1 334 -8389857 -2043769330 -69534958 -2010610142 + -19399681 -860957441 -40118413 -59769989 + + -2.6856726408004761e-01 2.2150200605392456e-01 + <_> + + 0 -1 342 -4194317 -1097160528 1129927121 -572583600 + -1480608773 -1388663112 1299799505 -840960547 + + -1.8076962232589722e-01 3.2131236791610718e-01 + <_> + + 0 -1 127 1407140879 -538213336 -41173601 -854589681 + -689245505 -92547849 1284158459 168487359 + + -3.0466887354850769e-01 1.9067247211933136e-01 + <_> + + 0 -1 204 -337910785 -18153601 -805309444 1917893626 + -11014155 -1074659969 -67119620 -76515328 + + -1.9108071923255920e-01 2.9606026411056519e-01 + <_> + + 0 -1 4 -1374747297 -1672142509 -690225283 -61276329 + 113970219 -1175502287 1247706719 -545947789 + + -2.3365408182144165e-01 2.5229984521865845e-01 + <_> + + 0 -1 27 -587211009 616612637 -996282177 1350760431 743900160 + -183233459 -1076131105 -546181281 + + -2.4930721521377563e-01 2.2612276673316956e-01 + <_> + + 0 -1 286 -8147552 -1625113614 1286228632 -353481008 + 822466289 1966144435 -285295617 1291708404 + + -2.7701693773269653e-01 2.1534711122512817e-01 + <_> + + 0 -1 308 490673157 1427765332 -1746674373 -1860839277 + 290395277 -1685050565 -1197556801 -1465123113 + + -2.6409074664115906e-01 2.2850526869297028e-01 + <_> + + 0 -1 125 298128335 -187922961 861671868 -33787650 + -1141802097 516205188 -270663748 -255530164 + + -2.7780425548553467e-01 2.1246871352195740e-01 + <_> + + 0 -1 141 1375730695 627907893 -51644163 -268568093 + -503710475 -23415107 2095341716 -1406671321 + + -2.1832446753978729e-01 2.5456944108009338e-01 + <_> + + 0 -1 83 1479937050 1527130690 779251298 -1753555086 + 738741914 1273777055 1391749242 -269504542 + + -3.3689221739768982e-01 1.6092190146446228e-01 + <_> + + 0 -1 227 -940593661 706414255 -1899740490 -1493243222 + -129536651 1683451935 -731306 -185673886 + + -2.9129263758659363e-01 1.9923964142799377e-01 + <_> + + 0 -1 268 1214682914 -1107497954 -50963712 -36048662 + 2122380642 -1060772926 494353798 1572299255 + + -3.1202444434165955e-01 1.9046534597873688e-01 + <_> + + 0 -1 51 -526218504 -655159201 -1651243249 -1083324983 + -1061447364 -1165127435 -1313734326 587291393 + + -3.1355553865432739e-01 1.8095606565475464e-01 + <_> + + 0 -1 138 -16841511 1409112829 -1225064449 -144016265 + -285320164 -3236505 -109781282 -16712598 + + -2.2392266988754272e-01 2.6122003793716431e-01 + <_> + + 0 -1 187 1811899910 1188020131 -427336262 681310146 + 1283408900 1086641242 -201490620 -67766399 + + -3.1929084658622742e-01 1.8652729690074921e-01 + <_> + + 0 -1 92 -1566333438 -1239270996 -1135107763 -1114249923 + -536288113 -707011874 -1302858034 -1326459420 + + -2.6035124063491821e-01 2.1769930422306061e-01 + <_> + + 0 -1 346 139396887 44502064 537054341 437190617 719719428 + -793069360 -663781634 -1368724662 + + -2.9000744223594666e-01 1.9265611469745636e-01 + <_> + + 0 -1 265 -250095070 2097181951 1243884576 263172296 + 1408750261 289431972 2143664050 754312418 + + -2.8242233395576477e-01 2.0532251894474030e-01 + <_> + + 0 -1 206 620238429 1536959391 -6758403 535174905 1047149052 + 921712776 -1362093858 -5615942 + + -2.5363510847091675e-01 2.1782724559307098e-01 + <_> + + 0 -1 340 -943787582 1390929134 2007850965 1575994853 + -1768757774 -404895814 -1244790789 -949809617 + + -2.1436288952827454e-01 2.7378448843955994e-01 + <_> + + 0 -1 21 -69011461 -6135840 -472170147 1668209188 225380825 + -1694527907 15597764 -958430977 + + -1.7761918902397156e-01 2.9578888416290283e-01 + <_> + + 0 -1 63 2145317171 -1615352016 -337285123 796003570 + 525665077 -1366597353 -286321259 -903181106 + + -2.3187226057052612e-01 2.3607331514358521e-01 + <_> + + 0 -1 191 -495277538 434272486 -501947458 526441212 + -1496864652 -1100739471 -792975140 -619624103 + + -2.5271594524383545e-01 2.1627274155616760e-01 + <_> + + 0 -1 303 -805569741 680173544 -709755055 -1378886831 + -1378621171 -1963028225 -1398473520 -2003306283 + + -2.5094878673553467e-01 2.2561351954936981e-01 + + <_> + 29 + -1.3573215007781982e+00 + + <_> + + 0 -1 348 -34622032 -173542149 -656574992 -572523139 + -1051863563 -863055138 -570565121 -572522497 + + -1.2100619077682495e-01 4.5341226458549500e-01 + <_> + + 0 -1 170 -77594885 1060339475 -2139947270 807665435 + 399475712 1041203007 -251923474 1920204539 + + -2.7747187018394470e-01 2.7045109868049622e-01 + <_> + + 0 -1 316 899790847 -4383371 -1087668481 -16941 -2034717186 + -1078292832 -1346650113 -1079270742 + + -2.1022592484951019e-01 3.3468201756477356e-01 + <_> + + 0 -1 0 -279969793 -1 -292628226 -268437778 267325424 + -880878352 216613332 -268443403 + + -2.3492383956909180e-01 2.7808070182800293e-01 + <_> + + 0 -1 68 -656374532 -590854788 -1141031683 -539111939 + -286464771 -705056771 -1611816999 -14883 + + -1.9249799847602844e-01 3.0399987101554871e-01 + <_> + + 0 -1 276 258465713 462159759 15965472 2103961046 1280627108 + -268435525 2026765496 -1025 + + -2.4311806261539459e-01 2.4972844123840332e-01 + <_> + + 0 -1 144 -419434834 1657591678 -455923284 -5386498 + -1216358521 1371620740 2013263792 1442179056 + + -2.8065973520278931e-01 2.2235853970050812e-01 + <_> + + 0 -1 73 -255016286 -723652609 1892807313 -35652917 + -568542589 1275961346 -142606437 1154327186 + + -3.2926952838897705e-01 1.6259366273880005e-01 + <_> + + 0 -1 167 3384620 904725092 -504505106 -10623284 1932031989 + -2330160 -1248468832 -1126046076 + + -2.8664493560791016e-01 2.2413903474807739e-01 + <_> + + 0 -1 284 -1026571858 -1026883601 -488570970 -492639282 + 1508886477 -1060260628 -1479752754 1962733263 + + -2.9589930176734924e-01 1.9247196614742279e-01 + <_> + + 0 -1 341 -78686238 -2027290630 -378837808 -570440104 + 1632253693 101381112 1498878421 -841095201 + + -2.3898813128471375e-01 2.4848675727844238e-01 + <_> + + 0 -1 108 -1971972962 -8706569 2096520703 594690133 + -1434911233 -341858 -1163260049 -1440077729 + + -2.8525370359420776e-01 2.0041574537754059e-01 + <_> + + 0 -1 113 1339985527 -934921 -1409937733 -895471966 + 1451110391 -1073836291 -268755217 -760410 + + -2.0745021104812622e-01 2.7934357523918152e-01 + <_> + + 0 -1 87 -1360393537 1727751901 -889274753 2081439599 + 1607743092 -67350714 -1091371394 -27240650 + + -2.3077887296676636e-01 2.4403619766235352e-01 + <_> + + 0 -1 72 -17272190 -730449666 983947743 -134882993 1883483442 + -72060809 1044905951 -211072966 + + -2.6235556602478027e-01 2.0745755732059479e-01 + <_> + + 0 -1 189 -210252097 1884165717 -50659376 860389370 -33585068 + 2132105077 -553789572 -9176254 + + -1.9577032327651978e-01 2.8605857491493225e-01 + <_> + + 0 -1 244 -12107230 1405347498 9728696 -774898706 1468220672 + 1174850371 1180713096 1409800424 + + -3.3929014205932617e-01 1.6556024551391602e-01 + <_> + + 0 -1 307 -994181088 1291627471 1262103330 -354443110 + 1962482852 1291513853 1151615436 1157370878 + + -4.2177367210388184e-01 1.3324783742427826e-01 + <_> + + 0 -1 267 -307502430 988475890 1831374754 -1645284694 + 2130962323 221299939 -582233169 -875695884 + + -2.4994827806949615e-01 2.2937348484992981e-01 + <_> + + 0 -1 278 -1916848333 -1945176701 -1778585227 -2064614508 + -122685775 -1462060545 176022580 -862585616 + + -2.7523562312126160e-01 2.1038419008255005e-01 + <_> + + 0 -1 15 1794562783 -1707697032 8965707 201493599 -1078044347 + 2071358036 -228402354 -16253105 + + -2.4676196277141571e-01 2.2217004001140594e-01 + <_> + + 0 -1 329 -570688129 -559096592 461864797 -1648504323 + -1381270595 -1162301576 748698989 -1140857537 + + -1.3901424407958984e-01 3.8346973061561584e-01 + <_> + + 0 -1 336 1356057541 815348525 -54210793 825603867 -185511716 + 2030008165 -1397949527 -105647169 + + -1.8459501862525940e-01 2.9480937123298645e-01 + <_> + + 0 -1 241 -1373456459 -1213441040 -1090789891 -1087429059 + -1397245955 -1074004547 -1883766851 -1079288824 + + -2.1159930527210236e-01 2.6970177888870239e-01 + <_> + + 0 -1 168 2001407789 335849869 -147476753 -1053743 895956974 + 2104879189 76816574 -186254656 + + -2.4863779544830322e-01 2.2415082156658173e-01 + <_> + + 0 -1 161 -1071127926 -104798275 1634638992 -201508730 + 1308444431 1370014335 -43939345 735390534 + + -2.4622464179992676e-01 2.2192895412445068e-01 + <_> + + 0 -1 260 746016303 709037870 45760155 141491407 1256916534 + 185498431 812100448 -602305968 + + -3.7083637714385986e-01 1.5087808668613434e-01 + <_> + + 0 -1 118 2084023842 2097190758 -39176271 -570569955 + -688182614 -1748393229 1173046543 1430650494 + + -2.4530048668384552e-01 2.2491128742694855e-01 + <_> + + 0 -1 23 1900052178 -1459537106 -167381666 1029895584 + -675654745 -1737122 844265207 1512783454 + + -3.1983017921447754e-01 1.8673284351825714e-01 + + <_> + 30 + -1.1131941080093384e+00 + + <_> + + 0 -1 254 -26289153 -67174410 -335742017 -272455006 + 1212186622 -20513038 172322783 1162040387 + + -2.4323463439941406e-01 3.2466232776641846e-01 + <_> + + 0 -1 48 -528449376 -101669640 -553748993 -536903943 + 1018034165 -17510413 -570626819 -10529 + + -2.5142908096313477e-01 2.8689405322074890e-01 + <_> + + 0 -1 240 -1539 -1130741968 -34078723 1032337712 -1251478531 + -1665269762 -1075314726 -1145380949 + + -1.8148881196975708e-01 3.5420870780944824e-01 + <_> + + 0 -1 280 -83887105 817571843 -1039149548 1548950080 + -1465058162 -1157678437 -1463092262 -201326609 + + -1.6771338880062103e-01 3.5687464475631714e-01 + <_> + + 0 -1 57 -532737 -35715969 135855871 -1145344385 -16888678 + -83947472 -1440547846 -15532193 + + -1.8111394345760345e-01 3.3908957242965698e-01 + <_> + + 0 -1 11 720900064 2130477023 -1412285101 955268081 + -2069885116 -55066689 -1073778857 2096463733 + + -3.9165833592414856e-01 1.3025353848934174e-01 + <_> + + 0 -1 101 -1346721094 453313040 838687891 1466900303 + -1399343880 -1362120449 -1204875206 2078743195 + + -3.0911612510681152e-01 1.8588562309741974e-01 + <_> + + 0 -1 264 -202906070 1938124526 -409308124 1894181886 + 1886745604 73722021 -169346204 1624557028 + + -3.7369936704635620e-01 1.6779878735542297e-01 + <_> + + 0 -1 315 253329560 487885008 764610172 1031107061 353634728 + 340804628 54078428 1065330931 + + -4.6387240290641785e-01 9.7853913903236389e-02 + <_> + + 0 -1 221 1018691377 213157736 -1922048203 -1935119200 + 1002285621 -1923389008 220951933 -2001869391 + + -2.8209856152534485e-01 1.9869700074195862e-01 + <_> + + 0 -1 131 -145809672 -585615056 -1115156804 1607413650 + 1024261612 944513264 -1966100738 -6315329 + + -2.5250333547592163e-01 2.1315294504165649e-01 + <_> + + 0 -1 236 -273750513 1726356523 -25760220 -1359572570 + -708967119 2113503015 1155493984 -1057490414 + + -2.9303619265556335e-01 2.0555299520492554e-01 + <_> + + 0 -1 94 323820494 491589631 963097087 -1677743793 1968422864 + 122533774 -13255752 2009905796 + + -3.3369639515876770e-01 1.6422146558761597e-01 + <_> + + 0 -1 147 -227028310 322043889 -97472590 993106459 -935679349 + 1170424128 -355628373 -1186994445 + + -2.3621979355812073e-01 2.4498730897903442e-01 + <_> + + 0 -1 302 522927795 -1425531232 -1757151367 -349047764 + 505005821 -1367184427 1026187772 -2002064200 + + -2.7412149310112000e-01 1.9911617040634155e-01 + <_> + + 0 -1 339 895166720 2111801021 1608646093 1966952754 + -270845440 -14704805 797543682 146244640 + + -3.7740421295166016e-01 1.6069526970386505e-01 + <_> + + 0 -1 157 1323192543 -699121475 -560546497 4377727 -795736016 + -617006470 -94369186 -25800110 + + -2.7069774270057678e-01 1.9588492810726166e-01 + <_> + + 0 -1 327 -818173702 520657616 646455540 -2083557932 + -75238914 420007072 1594772940 231600639 + + -3.1584987044334412e-01 1.7538470029830933e-01 + <_> + + 0 -1 1 -148176937 -22288910 -828264777 -858011334 549667459 + -104350212 83820556 -521682689 + + -1.8492446839809418e-01 2.9220038652420044e-01 + <_> + + 0 -1 123 -253231012 -573137851 -1892901128 1566408309 + -1769517004 -666343243 -1438498978 -1574952149 + + -3.1360149383544922e-01 1.7211912572383881e-01 + <_> + + 0 -1 60 170284113 586555385 1058684927 947969752 -1950608368 + -385672127 -1672070998 -1168986245 + + -3.3217278122901917e-01 1.5771922469139099e-01 + <_> + + 0 -1 248 1432934647 967738510 1321343231 -1294596018 + 1010881693 478544329 145528063 1050558707 + + -2.6398298144340515e-01 2.1170960366725922e-01 + <_> + + 0 -1 209 1165995551 424529746 -728651937 -169112117 + 1305345535 2025713070 -338894882 1081454374 + + -2.2665287554264069e-01 2.3902100324630737e-01 + <_> + + 0 -1 257 -167798992 1502279678 -537643148 2040558008 + -319819863 -1915752500 1705108696 -858081046 + + -2.0653969049453735e-01 2.7062198519706726e-01 + <_> + + 0 -1 333 800009831 1001521851 -124862633 533722757 935548439 + -1187270792 2020438516 -349479616 + + -2.8587275743484497e-01 1.8258976936340332e-01 + <_> + + 0 -1 263 -1004379104 -317547503 -1375022085 -1350509633 + -1535534960 -559793401 -1261510978 -1412440193 + + -2.5795167684555054e-01 2.0566099882125854e-01 + <_> + + 0 -1 146 465286027 242062640 1583158025 -1699742834 + 824414919 851244643 -1124620860 -795411494 + + -2.4531027674674988e-01 2.1592345833778381e-01 + <_> + + 0 -1 25 -2043693556 -725407700 793901503 -36185267 5371426 + 653472838 1473727247 129745679 + + -3.0099743604660034e-01 1.7710824310779572e-01 + <_> + + 0 -1 292 -1275032352 -23523116 1030926068 -570510472 + 33719442 719784182 96905635 -1916299537 + + -2.9368206858634949e-01 1.8733473122119904e-01 + <_> + + 0 -1 9 1373348482 -2133926229 953967473 1290797039 + -354421821 777789632 1265367830 1148839750 + + -3.7210872769355774e-01 1.5113249421119690e-01 + + <_> + 32 + -1.1860446929931641e+00 + + <_> + + 0 -1 165 1356843726 1624768255 -826079028 -286274834 + 1507794655 -722342276 -3191601 -352325921 + + -1.7216572165489197e-01 3.7796711921691895e-01 + <_> + + 0 -1 313 -780169199 2100304165 -586083043 -1123467235 + -638110531 -4406601 -274183091 201852044 + + -3.2011264562606812e-01 2.1122068166732788e-01 + <_> + + 0 -1 133 -571204388 -100720840 -1619059363 -539550628 + -19218498 -193040 -88209091 -1086649846 + + -2.5261041522026062e-01 2.6258233189582825e-01 + <_> + + 0 -1 117 -1828478207 -1843284467 -485637257 -1828588787 + -988301809 -3170571 1124595215 -206576893 + + -2.2752490639686584e-01 2.6724869012832642e-01 + <_> + + 0 -1 156 -25473825 877659895 -67700993 2077895802 -18998020 + -69575009 -640262 -21489648 + + -2.6945993304252625e-01 2.0498518645763397e-01 + <_> + + 0 -1 252 1800381322 61586570 -598811408 -805833218 + 1363795719 21154001 -790399642 -19401985 + + -2.7357041835784912e-01 2.2086700797080994e-01 + <_> + + 0 -1 13 -1601560401 -1678195249 -800754625 -819308539 + 1645503999 -1361531665 -491535701 -552874238 + + -2.4950334429740906e-01 2.1326830983161926e-01 + <_> + + 0 -1 197 -1130634113 775889725 -1098908817 -1382023297 + -252264234 -1460797259 -391364236 -1203775120 + + -2.2527810931205750e-01 2.4279835820198059e-01 + <_> + + 0 -1 350 792411409 1058027552 -110125307 2134056272 + 605163321 -1347378309 1504534524 226299985 + + -4.0245848894119263e-01 1.2799273431301117e-01 + <_> + + 0 -1 347 1050083335 406261055 -1363608721 597939991 + -146861538 -1075839447 -122225990 -73208017 + + -2.2469925880432129e-01 2.3744599521160126e-01 + <_> + + 0 -1 85 1582192403 1062343974 1627149746 -704505584 + 1569152382 -607155889 -671101020 -67379489 + + -2.4716284871101379e-01 2.0234791934490204e-01 + <_> + + 0 -1 232 -911388934 285282595 -1026079813 96171241 + -1995666022 998839072 9210339 769654523 + + -2.7387142181396484e-01 1.9601228833198547e-01 + <_> + + 0 -1 345 -1232081117 -1601765464 1841782352 -1359108881 + 206394688 214450860 -570607531 -866268431 + + -3.0001869797706604e-01 1.6920509934425354e-01 + <_> + + 0 -1 295 -4458576 -1314131792 1398469949 -1792059607 + -1345405187 -1079051090 1452237728 -1919952197 + + -1.9607956707477570e-01 2.6292434334754944e-01 + <_> + + 0 -1 79 1506257807 1575786835 -1278408030 -1253124710 + -82575398 1430293160 1930209224 -796269912 + + -2.9750382900238037e-01 1.7626072466373444e-01 + <_> + + 0 -1 237 -426011871 401504059 -655056592 -96541869 + 1174138997 83593771 1356719392 -1057033481 + + -2.6239070296287537e-01 2.0239675045013428e-01 + <_> + + 0 -1 224 528217457 -1887267120 -21899275 230954172 182253557 + -1078346768 673994781 -1465425804 + + -2.4917839467525482e-01 2.0696680247783661e-01 + <_> + + 0 -1 140 1077257734 1897370406 -259859707 1059435291 + 1506651014 -1718550481 1420667359 1969609218 + + -2.4424369633197784e-01 2.1042110025882721e-01 + <_> + + 0 -1 230 -134218838 2137809570 -218175868 -139728728 + 2147479551 1513965270 -436767017 -19926812 + + -2.1578867733478546e-01 2.3687294125556946e-01 + <_> + + 0 -1 41 1061133429 -1680215183 951637661 -1082528295 + -1722602208 -281648288 -576384764 -1426137478 + + -2.3583492636680603e-01 2.2509087622165680e-01 + <_> + + 0 -1 326 -1035541888 1145865728 -431122728 1154338362 + -692060765 -187976868 -205526277 111929518 + + -3.4106892347335815e-01 1.7086119949817657e-01 + <_> + + 0 -1 158 763361143 740787839 -1648101507 -1076559121 + -256380937 758360290 -1207635964 68200468 + + -3.1536939740180969e-01 1.5365907549858093e-01 + <_> + + 0 -1 176 -1898557315 -1344526497 1827929727 1610372479 + -2220468 -110762 -560275617 -1168483765 + + -2.1805766224861145e-01 2.4546204507350922e-01 + <_> + + 0 -1 262 -167774321 -749754393 -772349322 1946088623 -529788 + -570036402 -404621404 -202506274 + + -1.4736793935298920e-01 3.7225186824798584e-01 + <_> + + 0 -1 121 337917444 140836324 -1369830227 -1342456915 + -1175112267 2101116535 -1384838109 741831797 + + -3.9851671457290649e-01 1.3316881656646729e-01 + <_> + + 0 -1 172 -10244980 1412480785 2134521425 1932578931 + 1778322640 1063337502 1048517040 -142620803 + + -2.2908750176429749e-01 2.3318812251091003e-01 + <_> + + 0 -1 220 739784564 884511140 894928089 1065491218 122138060 + 524623529 391056888 532291626 + + -3.5874554514884949e-01 1.4738923311233521e-01 + <_> + + 0 -1 182 -1557157214 -1407349557 276451840 542158770 + -767297572 1620822855 -1963265624 -1002119198 + + -3.2322171330451965e-01 1.5725640952587128e-01 + <_> + + 0 -1 98 1561639164 -577384833 -972029477 -26394741 + 1433517817 -1145825634 2090400506 1064572985 + + -3.8865497708320618e-01 1.4794999361038208e-01 + <_> + + 0 -1 17 1785851519 234900079 -867150209 -1033437237 + -338602732 -9149625 -888193454 -33498413 + + -2.5603562593460083e-01 2.1439185738563538e-01 + <_> + + 0 -1 93 1062021007 670948845 -237027440 889116157 2002805591 + 1966188591 -1350453384 1885696686 + + -3.7720784544944763e-01 1.3390180468559265e-01 + <_> + + 0 -1 129 -239339312 255035166 -873625424 958256640 -59805472 + 1222090819 -746264190 269999815 + + -3.5460588335990906e-01 1.4317318797111511e-01 <_> 0 0 2 2 + <_> + + 0 0 2 4 <_> 0 0 3 4 <_> - 0 0 5 3 + 0 0 4 4 <_> - 0 0 5 4 + 0 0 5 7 <_> 0 0 6 3 + <_> + + 0 0 6 4 + <_> + + 0 0 6 6 <_> 0 0 8 1 <_> - 0 1 2 3 + 0 1 8 5 <_> - 0 1 6 4 + 0 3 6 2 <_> - 0 2 8 5 + 0 3 6 3 <_> - 0 7 6 2 + 0 4 6 4 + <_> + + 0 6 3 2 + <_> + + 0 8 3 1 <_> 0 9 2 2 <_> - 0 9 3 1 - <_> - - 0 9 5 3 + 0 10 2 2 <_> 0 14 3 3 @@ -2411,73 +2765,61 @@ 0 15 2 2 <_> - 0 16 1 2 + 0 17 3 2 <_> - 0 17 2 2 + 1 0 4 4 <_> - 1 0 2 4 + 1 1 2 3 <_> - 1 0 5 3 + 1 6 2 2 <_> - 1 0 7 1 + 1 6 4 3 <_> - 1 6 2 1 + 1 7 2 1 <_> - 1 9 1 1 + 1 8 2 1 <_> - 1 9 2 2 + 1 8 2 3 <_> - 1 15 1 2 + 1 12 2 1 <_> 1 16 2 2 - <_> - - 2 0 2 2 <_> 2 0 2 3 <_> - 2 0 3 4 + 2 0 5 3 <_> - 2 1 3 7 + 2 1 4 2 <_> - 2 4 1 1 - <_> - - 2 4 5 2 - <_> - - 2 4 5 4 + 2 3 5 2 <_> 2 5 1 1 + <_> + + 2 6 2 1 <_> 2 6 2 2 - <_> - - 2 7 1 1 - <_> - - 2 7 2 1 - <_> - - 2 8 3 3 <_> 2 9 1 1 + <_> + + 2 9 2 1 <_> 2 10 1 1 @@ -2489,40 +2831,31 @@ 2 15 1 2 <_> - 2 19 2 1 + 3 0 1 1 <_> - 3 0 4 3 + 3 0 3 3 <_> - 3 0 6 6 - <_> - - 3 0 7 1 + 3 0 6 1 <_> 3 2 4 2 <_> - 3 2 6 1 - <_> - - 3 4 2 2 + 3 4 1 2 <_> 3 5 1 1 + <_> + + 3 5 3 3 <_> 3 6 1 1 <_> - 3 6 2 1 - <_> - - 3 6 2 3 - <_> - - 3 6 3 3 + 3 6 2 2 <_> 3 6 6 1 @@ -2543,13 +2876,10 @@ 3 9 1 1 <_> - 3 9 1 2 + 3 9 3 1 <_> 3 10 1 1 - <_> - - 3 10 1 2 <_> 3 10 2 1 @@ -2558,34 +2888,34 @@ 3 11 1 1 <_> - 3 11 1 3 + 3 12 1 1 <_> - 3 13 3 3 + 3 13 3 2 + <_> + + 3 18 2 2 + <_> + + 4 0 2 2 <_> 4 0 4 2 <_> - 4 0 6 7 + 4 0 5 6 <_> - 4 1 1 1 + 4 2 2 2 <_> - 4 1 4 3 - <_> - - 4 4 2 1 + 4 5 3 1 <_> 4 6 1 1 <_> - 4 6 5 1 - <_> - - 4 6 5 4 + 4 6 2 3 <_> 4 7 1 1 @@ -2594,10 +2924,10 @@ 4 7 2 2 <_> - 4 7 5 1 + 4 8 1 1 <_> - 4 8 1 1 + 4 8 5 3 <_> 4 8 5 4 @@ -2606,13 +2936,16 @@ 4 9 1 1 <_> - 4 9 2 1 + 4 9 1 3 <_> 4 9 3 5 <_> 4 9 5 1 + <_> + + 4 9 6 1 <_> 4 10 1 1 @@ -2624,25 +2957,46 @@ 4 12 1 2 <_> - 4 14 3 3 + 4 12 3 3 <_> - 4 15 1 1 + 4 13 3 3 <_> - 4 18 2 1 + 4 14 2 2 <_> - 5 2 5 3 + 4 17 3 1 <_> - 5 3 4 4 + 4 21 2 1 + <_> + + 5 0 5 1 + <_> + + 5 0 5 4 + <_> + + 5 1 5 5 + <_> + + 5 1 5 6 + <_> + + 5 4 1 1 + <_> + + 5 5 5 1 + <_> + + 5 5 5 2 <_> 5 6 1 1 <_> - 5 6 4 1 + 5 6 5 1 <_> 5 7 1 1 @@ -2651,22 +3005,16 @@ 5 7 1 2 <_> - 5 7 2 2 + 5 7 3 4 <_> 5 8 1 1 <_> - 5 8 3 4 + 5 8 2 4 <_> - 5 8 3 5 - <_> - - 5 8 5 1 - <_> - - 5 8 5 3 + 5 8 5 4 <_> 5 9 1 1 @@ -2675,10 +3023,10 @@ 5 9 5 1 <_> - 5 10 1 1 + 5 9 5 3 <_> - 5 10 2 1 + 5 10 1 1 <_> 5 10 5 1 @@ -2687,13 +3035,25 @@ 5 11 1 1 <_> - 5 13 1 3 + 5 13 2 1 <_> - 5 16 1 1 + 5 17 1 1 <_> - 5 18 1 2 + 5 17 1 2 + <_> + + 5 20 1 1 + <_> + + 6 0 3 1 + <_> + + 6 0 4 1 + <_> + + 6 0 6 2 <_> 6 0 6 5 @@ -2702,10 +3062,7 @@ 6 1 1 2 <_> - 6 3 1 1 - <_> - - 6 3 6 3 + 6 3 1 2 <_> 6 4 1 1 @@ -2714,16 +3071,10 @@ 6 5 1 1 <_> - 6 5 1 2 + 6 5 6 3 <_> - 6 6 2 2 - <_> - - 6 6 2 4 - <_> - - 6 6 3 3 + 6 6 1 1 <_> 6 7 1 1 @@ -2733,75 +3084,81 @@ <_> 6 7 4 1 - <_> - - 6 7 4 4 <_> 6 7 6 1 <_> - 6 8 1 4 + 6 8 1 1 + <_> + + 6 8 2 1 <_> 6 8 2 2 + <_> + + 6 8 2 3 <_> 6 9 1 1 <_> 6 9 2 1 - <_> - - 6 9 2 2 - <_> - - 6 9 5 1 - <_> - - 6 9 6 2 <_> 6 10 1 1 + <_> + + 6 10 4 3 <_> 6 11 1 1 <_> - 6 13 1 1 - <_> - - 6 13 2 1 + 6 18 1 1 <_> 6 18 1 2 <_> - 6 20 1 1 + 6 19 1 1 <_> - 7 0 3 1 + 6 21 2 1 <_> - 7 2 1 3 + 7 0 1 4 <_> - 7 3 4 5 + 7 0 5 3 + <_> + + 7 4 1 1 + <_> + + 7 4 1 2 <_> 7 5 1 1 - <_> - - 7 5 2 1 <_> 7 6 1 1 <_> - 7 7 1 2 + 7 6 2 1 <_> - 7 7 2 4 + 7 6 2 3 + <_> + + 7 6 2 5 + <_> + + 7 7 1 1 + <_> + + 7 7 1 2 <_> 7 8 1 1 @@ -2810,31 +3167,31 @@ 7 8 1 2 <_> - 7 8 2 4 + 7 8 2 2 <_> 7 9 1 1 <_> - 7 16 1 1 + 7 9 2 3 <_> - 7 21 1 1 + 7 18 1 1 <_> - 7 21 2 1 + 7 20 2 1 <_> - 8 0 2 1 - <_> - - 8 0 3 1 + 8 0 5 1 <_> 8 0 5 3 <_> 8 3 1 1 + <_> + + 8 3 1 3 <_> 8 4 1 1 @@ -2843,67 +3200,94 @@ 8 5 1 1 <_> - 8 5 1 2 + 8 5 5 1 <_> - 8 7 3 4 + 8 6 1 2 <_> 8 8 1 1 + <_> + + 8 8 4 1 + <_> + + 8 8 4 2 <_> 8 9 1 1 <_> - 8 9 3 5 + 8 9 1 2 <_> 8 11 1 1 + <_> + + 8 12 1 2 + <_> + + 8 13 3 3 <_> 8 14 1 1 <_> - 8 19 1 1 - <_> - - 8 20 1 1 + 8 15 1 1 <_> 8 21 1 1 <_> - 9 0 2 3 + 8 21 2 1 <_> - 9 1 2 1 + 9 0 2 2 <_> - 9 5 2 1 + 9 0 5 3 + <_> + + 9 1 2 2 + <_> + + 9 2 1 1 + <_> + + 9 3 1 1 + <_> + + 9 3 2 2 + <_> + + 9 4 2 1 + <_> + + 9 4 4 1 <_> 9 5 2 3 - <_> - - 9 5 4 1 - <_> - - 9 7 1 1 <_> 9 9 1 1 <_> - 9 11 1 1 - <_> - - 9 12 2 4 + 9 10 1 1 <_> 9 15 1 1 <_> - 9 17 1 1 + 9 15 2 2 + <_> + + 9 16 1 1 + <_> + + 9 16 2 2 + <_> + + 9 18 1 1 <_> 9 18 1 2 @@ -2912,19 +3296,22 @@ 9 20 1 1 <_> - 10 0 2 2 + 9 21 1 1 <_> - 10 6 3 3 + 10 0 4 3 + <_> + + 10 4 4 2 + <_> + + 10 6 1 1 <_> 10 7 1 1 <_> 10 8 1 1 - <_> - - 10 9 1 1 <_> 10 11 1 1 @@ -2933,73 +3320,73 @@ 10 12 1 1 <_> - 10 15 1 1 + 10 14 1 1 + <_> + + 10 18 1 2 + <_> + + 10 19 1 1 <_> 10 20 1 1 <_> 10 21 1 1 + <_> + + 11 0 1 3 <_> 11 0 4 4 <_> - 11 1 4 4 + 11 2 3 2 <_> - 11 3 1 1 + 11 5 4 3 <_> - 11 4 3 1 - <_> - - 11 6 3 6 + 11 6 1 1 <_> 11 7 1 1 <_> - 11 8 1 1 + 11 7 2 4 + <_> + + 11 8 2 2 <_> 11 9 1 1 <_> - 11 9 2 3 + 11 9 2 4 <_> - 11 10 1 1 + 11 12 1 1 <_> - 11 11 1 1 + 11 18 1 1 <_> - 11 12 2 3 - <_> - - 11 13 1 1 - <_> - - 11 15 3 1 + 11 18 3 2 <_> 11 20 1 1 <_> 11 21 1 1 + <_> + + 11 21 2 1 + <_> + + 12 2 1 1 <_> 12 3 1 1 - <_> - - 12 5 1 1 - <_> - - 12 5 2 3 - <_> - - 12 5 3 3 <_> 12 6 1 1 @@ -3011,31 +3398,37 @@ 12 8 1 1 <_> - 12 8 2 2 + 12 8 2 1 <_> 12 8 2 3 <_> - 12 9 1 1 + 12 8 2 4 <_> - 12 10 2 3 + 12 9 2 1 <_> - 12 11 1 1 + 12 9 2 5 + <_> + + 12 10 1 1 + <_> + + 12 12 1 1 + <_> + + 12 13 1 1 + <_> + + 12 14 1 1 <_> 12 16 1 1 - <_> - - 12 17 1 1 <_> 12 18 1 1 - <_> - - 12 18 1 2 <_> 12 20 1 1 @@ -3044,7 +3437,7 @@ 12 21 1 1 <_> - 13 0 3 3 + 12 21 2 1 <_> 13 3 1 1 @@ -3056,13 +3449,19 @@ 13 5 1 1 <_> - 13 6 2 3 + 13 6 3 3 + <_> + + 13 7 1 4 <_> 13 7 3 2 <_> 13 8 1 1 + <_> + + 13 8 2 2 <_> 13 9 1 1 @@ -3077,40 +3476,46 @@ 13 11 1 1 <_> - 13 13 1 1 + 13 15 1 1 <_> - 13 19 1 1 + 13 16 1 1 <_> 13 20 1 1 - <_> - - 13 21 1 1 <_> 14 0 3 4 <_> - 14 3 1 2 + 14 1 2 1 <_> - 14 3 2 1 + 14 3 1 3 <_> 14 4 1 1 + <_> + + 14 4 3 2 <_> 14 5 1 1 <_> - 14 6 2 3 + 14 5 1 2 <_> - 14 7 1 3 + 14 6 2 1 <_> - 14 7 2 2 + 14 7 1 1 + <_> + + 14 7 1 2 + <_> + + 14 7 2 5 <_> 14 8 1 1 @@ -3120,6 +3525,9 @@ <_> 14 9 1 1 + <_> + + 14 9 1 2 <_> 14 9 2 1 @@ -3128,25 +3536,37 @@ 14 13 1 1 <_> - 14 21 1 1 + 14 14 2 2 + <_> + + 14 18 1 2 + <_> + + 14 21 2 1 <_> 15 0 3 4 + <_> + + 15 0 3 5 <_> 15 1 1 2 <_> - 15 2 1 2 + 15 2 2 2 + <_> + + 15 3 2 1 + <_> + + 15 4 1 1 <_> 15 5 1 1 <_> - 15 6 2 1 - <_> - - 15 6 2 2 + 15 6 1 1 <_> 15 7 1 1 @@ -3156,30 +3576,69 @@ <_> 15 7 2 2 + <_> + + 15 7 3 2 <_> 15 8 1 1 <_> 15 9 1 1 + <_> + + 15 9 1 4 <_> 15 9 1 5 <_> - 15 9 2 1 + 15 10 2 1 <_> - 15 15 3 3 + 15 11 1 1 + <_> + + 15 13 2 2 + <_> + + 15 15 3 2 + <_> + + 15 16 2 2 <_> 15 17 1 1 + <_> + + 15 17 3 2 + <_> + + 15 18 1 1 + <_> + + 15 18 3 2 + <_> + + 15 19 1 1 + <_> + + 15 21 3 1 <_> 16 4 1 1 + <_> + + 16 5 1 1 + <_> + + 16 5 2 2 <_> 16 6 1 1 + <_> + + 16 6 2 2 <_> 16 7 1 1 @@ -3191,10 +3650,10 @@ 16 7 2 1 <_> - 16 7 2 2 + 16 8 1 1 <_> - 16 8 1 1 + 16 9 1 1 <_> 16 10 1 1 @@ -3209,13 +3668,10 @@ 16 17 1 2 <_> - 16 18 1 1 + 16 19 1 1 <_> - 17 4 2 2 - <_> - - 17 5 1 1 + 17 1 2 3 <_> 17 6 2 1 @@ -3233,10 +3689,10 @@ 17 8 1 1 <_> - 17 8 2 1 + 17 9 1 1 <_> - 17 9 1 1 + 17 9 2 2 <_> 17 10 1 1 @@ -3251,86 +3707,62 @@ 17 12 1 2 <_> - 17 13 1 2 + 17 13 1 1 <_> - 17 13 1 3 - <_> - - 17 21 2 1 + 18 0 2 1 <_> 18 0 2 2 <_> - 18 4 1 2 + 18 4 2 2 + <_> + + 18 5 1 1 <_> 18 6 1 1 <_> - 18 8 2 2 + 18 6 1 2 + <_> + + 18 8 1 1 <_> 18 9 1 1 - <_> - - 18 9 1 2 - <_> - - 18 9 1 3 <_> 18 10 1 1 <_> - 18 11 1 2 + 18 11 1 3 <_> 18 12 1 1 - <_> - - 18 13 1 2 <_> 18 17 2 2 <_> - 18 18 1 2 + 19 4 1 1 <_> - 18 19 2 1 - <_> - - 19 0 1 1 - <_> - - 19 6 1 1 + 19 5 1 1 <_> 19 9 1 1 <_> - 19 9 1 2 - <_> - - 19 10 1 4 + 19 11 1 1 <_> 19 12 1 2 <_> - 20 10 1 1 + 19 15 1 2 <_> - 20 15 1 2 - <_> - - 21 10 1 1 - <_> - - 21 14 1 2 - <_> - - 21 15 1 3 + 20 10 1 1 From 00045bbf27236ac44d48a076941157b2f6645d76 Mon Sep 17 00:00:00 2001 From: Joe Howse Date: Fri, 12 Aug 2016 00:31:50 -0300 Subject: [PATCH 055/178] Removing whitespace to appease doc builder --- data/haarcascades/haarcascade_frontalcatface.xml | 4 ++-- data/haarcascades/haarcascade_frontalcatface_extended.xml | 4 ++-- data/lbpcascades/lbpcascade_frontalcatface.xml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/data/haarcascades/haarcascade_frontalcatface.xml b/data/haarcascades/haarcascade_frontalcatface.xml index cc3fb33d81..67893dcc07 100755 --- a/data/haarcascades/haarcascade_frontalcatface.xml +++ b/data/haarcascades/haarcascade_frontalcatface.xml @@ -25,9 +25,9 @@ An upright subject is assumed. In situations where the cat's face might be sideways or upside down (e.g. the cat is rolling over), try various rotations of the input image. - + CHANGELOG: - + 2016-08-06: Re-trained with more negative samples and more stages. False positives are much rarer now. If you tailored your code for the cascade's previous version, now you should re-adjust the arguments of diff --git a/data/haarcascades/haarcascade_frontalcatface_extended.xml b/data/haarcascades/haarcascade_frontalcatface_extended.xml index 5c4a0a62f6..ccee995f73 100755 --- a/data/haarcascades/haarcascade_frontalcatface_extended.xml +++ b/data/haarcascades/haarcascade_frontalcatface_extended.xml @@ -25,9 +25,9 @@ An upright subject is assumed. In situations where the cat's face might be sideways or upside down (e.g. the cat is rolling over), try various rotations of the input image. - + CHANGELOG: - + 2016-08-06: Re-trained with more negative samples and more stages. False positives are much rarer now. If you tailored your code for the cascade's previous version, now you should re-adjust the arguments of diff --git a/data/lbpcascades/lbpcascade_frontalcatface.xml b/data/lbpcascades/lbpcascade_frontalcatface.xml index c950754004..3b4b1bf426 100644 --- a/data/lbpcascades/lbpcascade_frontalcatface.xml +++ b/data/lbpcascades/lbpcascade_frontalcatface.xml @@ -24,9 +24,9 @@ An upright subject is assumed. In situations where the cat's face might be sideways or upside down (e.g. the cat is rolling over), try various rotations of the input image. - + CHANGELOG: - + 2016-08-06: Re-trained with more negative samples and more stages. False positives are much rarer now. If you tailored your code for the cascade's previous version, now you should re-adjust the arguments of From 8bcec7d77f0bd83e791144792f669309e263e9c0 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Fri, 12 Aug 2016 09:50:42 +0300 Subject: [PATCH 056/178] IPP enabling fix and typo fix; --- modules/core/src/system.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index a3858c1d19..edf9e0ebd7 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -1303,10 +1303,10 @@ void setUseCollection(bool flag) namespace ipp { -struct IPPInitSingelton +struct IPPInitSingleton { public: - IPPInitSingelton() + IPPInitSingleton() { useIPP = true; ippStatus = 0; @@ -1360,15 +1360,15 @@ public: int ippFeatures; }; -static IPPInitSingelton& getIPPSingelton() +static IPPInitSingleton& getIPPSingleton() { - CV_SINGLETON_LAZY_INIT_REF(IPPInitSingelton, new IPPInitSingelton()) + CV_SINGLETON_LAZY_INIT_REF(IPPInitSingleton, new IPPInitSingleton()) } int getIppFeatures() { #ifdef HAVE_IPP - return getIPPSingelton().ippFeatures; + return getIPPSingleton().ippFeatures; #else return 0; #endif @@ -1376,20 +1376,20 @@ int getIppFeatures() void setIppStatus(int status, const char * const _funcname, const char * const _filename, int _line) { - getIPPSingelton().ippStatus = status; - getIPPSingelton().funcname = _funcname; - getIPPSingelton().filename = _filename; - getIPPSingelton().linen = _line; + getIPPSingleton().ippStatus = status; + getIPPSingleton().funcname = _funcname; + getIPPSingleton().filename = _filename; + getIPPSingleton().linen = _line; } int getIppStatus() { - return getIPPSingelton().ippStatus; + return getIPPSingleton().ippStatus; } String getIppErrorLocation() { - return format("%s:%d %s", getIPPSingelton().filename ? getIPPSingelton().filename : "", getIPPSingelton().linen, getIPPSingelton().funcname ? getIPPSingelton().funcname : ""); + return format("%s:%d %s", getIPPSingleton().filename ? getIPPSingleton().filename : "", getIPPSingleton().linen, getIPPSingleton().funcname ? getIPPSingleton().funcname : ""); } bool useIPP() @@ -1398,7 +1398,7 @@ bool useIPP() CoreTLSData* data = getCoreTlsData().get(); if(data->useIPP < 0) { - data->useIPP = getIPPSingelton().useIPP; + data->useIPP = getIPPSingleton().useIPP; } return (data->useIPP > 0); #else @@ -1410,7 +1410,7 @@ void setUseIPP(bool flag) { CoreTLSData* data = getCoreTlsData().get(); #ifdef HAVE_IPP - data->useIPP = flag; + data->useIPP = (getIPPSingleton().useIPP)?flag:false; #else (void)flag; data->useIPP = false; From d8dc6caf09bb98424d9b20d32738e54eb35d64bf Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Wed, 10 Aug 2016 19:56:46 +0300 Subject: [PATCH 057/178] Fix for incorrect calcOpticalFlowPyrLK result evaluation with ARM NEON --- modules/video/src/lkpyramid.cpp | 46 ++++++++++++++++----------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 25614d9ced..e17b0d75c1 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -294,7 +294,7 @@ void cv::detail::LKTrackerInvoker::operator()(const Range& range) const #if CV_NEON - int CV_DECL_ALIGNED(16) nA11[] = {0, 0, 0, 0}, nA12[] = {0, 0, 0, 0}, nA22[] = {0, 0, 0, 0}; + float CV_DECL_ALIGNED(16) nA11[] = { 0, 0, 0, 0 }, nA12[] = { 0, 0, 0, 0 }, nA22[] = { 0, 0, 0, 0 }; const int shifter1 = -(W_BITS - 5); //negative so it shifts right const int shifter2 = -(W_BITS); @@ -406,19 +406,19 @@ void cv::detail::LKTrackerInvoker::operator()(const Range& range) const q6 = vaddq_s32(q6, q8); q7 = vmull_s16(d4d5.val[0], d28); - int32x4_t nq0 = vmull_s16(d4d5.val[1], d28); + int32x4_t q14 = vmull_s16(d4d5.val[1], d28); q8 = vmull_s16(d6d7.val[0], d29); int32x4_t q15 = vmull_s16(d6d7.val[1], d29); q7 = vaddq_s32(q7, q8); - nq0 = vaddq_s32(nq0, q15); + q14 = vaddq_s32(q14, q15); q4 = vaddq_s32(q4, q7); - q6 = vaddq_s32(q6, nq0); + q6 = vaddq_s32(q6, q14); - int32x4_t nq1 = vld1q_s32(nA12); - int32x4_t nq2 = vld1q_s32(nA22); - nq0 = vld1q_s32(nA11); + float32x4_t nq0 = vld1q_f32(nA11); + float32x4_t nq1 = vld1q_f32(nA12); + float32x4_t nq2 = vld1q_f32(nA22); q4 = vqrshlq_s32(q4, q12); q6 = vqrshlq_s32(q6, q12); @@ -427,13 +427,13 @@ void cv::detail::LKTrackerInvoker::operator()(const Range& range) const q8 = vmulq_s32(q4, q6); q15 = vmulq_s32(q6, q6); - nq0 = vaddq_s32(nq0, q7); - nq1 = vaddq_s32(nq1, q8); - nq2 = vaddq_s32(nq2, q15); + nq0 = vaddq_f32(nq0, vreinterpretq_f32_s32(q7)); + nq1 = vaddq_f32(nq1, vreinterpretq_f32_s32(q8)); + nq2 = vaddq_f32(nq2, vreinterpretq_f32_s32(q15)); - vst1q_s32(nA11, nq0); - vst1q_s32(nA12, nq1); - vst1q_s32(nA22, nq2); + vst1q_f32(nA11, nq0); + vst1q_f32(nA12, nq1); + vst1q_f32(nA22, nq2); int16x4_t d8 = vmovn_s32(q4); int16x4_t d12 = vmovn_s32(q6); @@ -474,9 +474,9 @@ void cv::detail::LKTrackerInvoker::operator()(const Range& range) const #endif #if CV_NEON - iA11 += (float)(nA11[0] + nA11[1] + nA11[2] + nA11[3]); - iA12 += (float)(nA12[0] + nA12[1] + nA12[2] + nA12[3]); - iA22 += (float)(nA22[0] + nA22[1] + nA22[2] + nA22[3]); + iA11 += nA11[0] + nA11[1] + nA11[2] + nA11[3]; + iA12 += nA12[0] + nA12[1] + nA12[2] + nA12[3]; + iA22 += nA22[0] + nA22[1] + nA22[2] + nA22[3]; #endif A11 = iA11*FLT_SCALE; @@ -530,7 +530,7 @@ void cv::detail::LKTrackerInvoker::operator()(const Range& range) const #endif #if CV_NEON - int CV_DECL_ALIGNED(16) nB1[] = {0,0,0,0}, nB2[] = {0,0,0,0}; + float CV_DECL_ALIGNED(16) nB1[] = { 0,0,0,0 }, nB2[] = { 0,0,0,0 }; const int16x4_t d26_2 = vdup_n_s16((int16_t)iw00); const int16x4_t d27_2 = vdup_n_s16((int16_t)iw01); @@ -625,8 +625,8 @@ void cv::detail::LKTrackerInvoker::operator()(const Range& range) const nq5 = vqrshlq_s32(nq5, q11); int16x8x2_t q0q1 = vld2q_s16(dIptr); - nq11 = vld1q_s32(nB1); - int32x4_t nq15 = vld1q_s32(nB2); + float32x4_t nB1v = vld1q_f32(nB1); + float32x4_t nB2v = vld1q_f32(nB2); nq4 = vsubq_s32(nq4, nq6); nq5 = vsubq_s32(nq5, nq8); @@ -646,11 +646,11 @@ void cv::detail::LKTrackerInvoker::operator()(const Range& range) const nq9 = vaddq_s32(nq9, nq10); nq4 = vaddq_s32(nq4, nq5); - nq11 = vaddq_s32(nq11, nq9); - nq15 = vaddq_s32(nq15, nq4); + nB1v = vaddq_f32(nB1v, vreinterpretq_f32_s32(nq9)); + nB2v = vaddq_f32(nB2v, vreinterpretq_f32_s32(nq4)); - vst1q_s32(nB1, nq11); - vst1q_s32(nB2, nq15); + vst1q_f32(nB1, nB1v); + vst1q_f32(nB2, nB2v); } #endif From 9db93d773dec95e2b6cf34fe8eb67983a1f8f24a Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Thu, 11 Aug 2016 20:20:36 +0300 Subject: [PATCH 058/178] Fix for MSER::detectRegions crash on images with either dimension less than 3 --- modules/features2d/include/opencv2/features2d.hpp | 2 +- modules/features2d/src/mser.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/features2d/include/opencv2/features2d.hpp b/modules/features2d/include/opencv2/features2d.hpp index 32fdabd8a4..4d362923ce 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -355,7 +355,7 @@ public: /** @brief Detect %MSER regions - @param image input image (8UC1, 8UC3 or 8UC4) + @param image input image (8UC1, 8UC3 or 8UC4, must be greater or equal than 3x3) @param msers resulting list of point sets @param bboxes resulting bounding boxes */ diff --git a/modules/features2d/src/mser.cpp b/modules/features2d/src/mser.cpp index 1143addc12..72b2314d9c 100644 --- a/modules/features2d/src/mser.cpp +++ b/modules/features2d/src/mser.cpp @@ -1020,12 +1020,11 @@ extractMSER_8uC3( const Mat& src, void MSER_Impl::detectRegions( InputArray _src, vector >& msers, vector& bboxes ) { Mat src = _src.getMat(); - size_t npix = src.total(); msers.clear(); bboxes.clear(); - if( npix == 0 ) + if( src.rows < 3 || src.cols < 3 ) return; Size size = src.size(); From 1b3f634843d8a8cf7398cd68f66b7d3eb6432a5e Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 12 Feb 2016 00:33:18 +0300 Subject: [PATCH 059/178] fixed compilation warning --- modules/core/include/opencv2/core/fast_math.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/core/include/opencv2/core/fast_math.hpp b/modules/core/include/opencv2/core/fast_math.hpp index b8b241b026..0a0e02831e 100644 --- a/modules/core/include/opencv2/core/fast_math.hpp +++ b/modules/core/include/opencv2/core/fast_math.hpp @@ -71,6 +71,7 @@ #define ARM_ROUND(_value, _asm_string) \ int res; \ float temp; \ + (void)temp; \ asm(_asm_string : [res] "=r" (res), [temp] "=w" (temp) : [value] "w" (_value)); \ return res // 2. version for double From 020b47c41abedcdb38e3990f11fd510f775099ff Mon Sep 17 00:00:00 2001 From: k-shinotsuka Date: Wed, 3 Aug 2016 23:42:24 +0900 Subject: [PATCH 060/178] improve RGB2Gray() --- modules/imgproc/src/color.cpp | 120 ++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 57 deletions(-) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index b08c608220..cc88c7c203 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -1492,36 +1492,47 @@ struct RGB2Gray if( blueIdx == 0 ) std::swap(coeffs[0], coeffs[2]); - v_cb = _mm_set1_epi16((short)coeffs[0]); - v_cg = _mm_set1_epi16((short)coeffs[1]); - v_cr = _mm_set1_epi16((short)coeffs[2]); v_delta = _mm_set1_epi32(1 << (yuv_shift - 1)); + v_zero = _mm_setzero_si128(); haveSIMD = checkHardwareSupport(CV_CPU_SSE4_1); } // 16s x 8 - void process(__m128i v_b, __m128i v_g, __m128i v_r, + void process(__m128i* v_rgb, __m128i* v_coeffs, __m128i & v_gray) const { - __m128i v_mullo_r = _mm_mullo_epi16(v_r, v_cr); - __m128i v_mullo_g = _mm_mullo_epi16(v_g, v_cg); - __m128i v_mullo_b = _mm_mullo_epi16(v_b, v_cb); - __m128i v_mulhi_r = _mm_mulhi_epu16(v_r, v_cr); - __m128i v_mulhi_g = _mm_mulhi_epu16(v_g, v_cg); - __m128i v_mulhi_b = _mm_mulhi_epu16(v_b, v_cb); + __m128i v_rgb_hi[4]; + v_rgb_hi[0] = _mm_cmplt_epi16(v_rgb[0], v_zero); + v_rgb_hi[1] = _mm_cmplt_epi16(v_rgb[1], v_zero); + v_rgb_hi[2] = _mm_cmplt_epi16(v_rgb[2], v_zero); + v_rgb_hi[3] = _mm_cmplt_epi16(v_rgb[3], v_zero); - __m128i v_gray0 = _mm_add_epi32(_mm_unpacklo_epi16(v_mullo_r, v_mulhi_r), - _mm_unpacklo_epi16(v_mullo_g, v_mulhi_g)); - v_gray0 = _mm_add_epi32(_mm_unpacklo_epi16(v_mullo_b, v_mulhi_b), v_gray0); - v_gray0 = _mm_srli_epi32(_mm_add_epi32(v_gray0, v_delta), yuv_shift); + v_rgb_hi[0] = _mm_and_si128(v_rgb_hi[0], v_coeffs[1]); + v_rgb_hi[1] = _mm_and_si128(v_rgb_hi[1], v_coeffs[1]); + v_rgb_hi[2] = _mm_and_si128(v_rgb_hi[2], v_coeffs[1]); + v_rgb_hi[3] = _mm_and_si128(v_rgb_hi[3], v_coeffs[1]); - __m128i v_gray1 = _mm_add_epi32(_mm_unpackhi_epi16(v_mullo_r, v_mulhi_r), - _mm_unpackhi_epi16(v_mullo_g, v_mulhi_g)); - v_gray1 = _mm_add_epi32(_mm_unpackhi_epi16(v_mullo_b, v_mulhi_b), v_gray1); - v_gray1 = _mm_srli_epi32(_mm_add_epi32(v_gray1, v_delta), yuv_shift); + v_rgb_hi[0] = _mm_hadd_epi16(v_rgb_hi[0], v_rgb_hi[1]); + v_rgb_hi[2] = _mm_hadd_epi16(v_rgb_hi[2], v_rgb_hi[3]); + v_rgb_hi[0] = _mm_hadd_epi16(v_rgb_hi[0], v_rgb_hi[2]); - v_gray = _mm_packus_epi32(v_gray0, v_gray1); + v_rgb[0] = _mm_madd_epi16(v_rgb[0], v_coeffs[0]); + v_rgb[1] = _mm_madd_epi16(v_rgb[1], v_coeffs[0]); + v_rgb[2] = _mm_madd_epi16(v_rgb[2], v_coeffs[0]); + v_rgb[3] = _mm_madd_epi16(v_rgb[3], v_coeffs[0]); + + v_rgb[0] = _mm_hadd_epi32(v_rgb[0], v_rgb[1]); + v_rgb[2] = _mm_hadd_epi32(v_rgb[2], v_rgb[3]); + + v_rgb[0] = _mm_add_epi32(v_rgb[0], v_delta); + v_rgb[2] = _mm_add_epi32(v_rgb[2], v_delta); + + v_rgb[0] = _mm_srai_epi32(v_rgb[0], yuv_shift); + v_rgb[2] = _mm_srai_epi32(v_rgb[2], yuv_shift); + + v_gray = _mm_packs_epi32(v_rgb[0], v_rgb[2]); + v_gray = _mm_add_epi16(v_gray, v_rgb_hi[0]); } void operator()(const ushort* src, ushort* dst, int n) const @@ -1530,54 +1541,49 @@ struct RGB2Gray if (scn == 3 && haveSIMD) { - for ( ; i <= n - 16; i += 16, src += scn * 16) + __m128i v_coeffs[2]; + v_coeffs[0] = _mm_set_epi16(0, (short)coeffs[2], (short)coeffs[1], (short)coeffs[0], (short)coeffs[2], (short)coeffs[1], (short)coeffs[0], 0); + v_coeffs[1] = _mm_slli_epi16(v_coeffs[0], 2); + + for ( ; i <= n - 8; i += 8, src += scn * 8) { - __m128i v_r0 = _mm_loadu_si128((__m128i const *)(src)); - __m128i v_r1 = _mm_loadu_si128((__m128i const *)(src + 8)); - __m128i v_g0 = _mm_loadu_si128((__m128i const *)(src + 16)); - __m128i v_g1 = _mm_loadu_si128((__m128i const *)(src + 24)); - __m128i v_b0 = _mm_loadu_si128((__m128i const *)(src + 32)); - __m128i v_b1 = _mm_loadu_si128((__m128i const *)(src + 40)); + __m128i v_src[2]; + v_src[0] = _mm_loadu_si128((__m128i const *)(src)); + v_src[1] = _mm_loadu_si128((__m128i const *)(src + 8)); + v_src[2] = _mm_loadu_si128((__m128i const *)(src + 16)); - _mm_deinterleave_epi16(v_r0, v_r1, v_g0, v_g1, v_b0, v_b1); + __m128i v_rgb[4]; + v_rgb[0] = _mm_slli_si128(v_src[0], 2); + v_rgb[1] = _mm_alignr_epi8(v_src[1], v_src[0], 10); + v_rgb[2] = _mm_alignr_epi8(v_src[2], v_src[1], 6); + v_rgb[3] = _mm_srli_si128(v_src[2], 2); - __m128i v_gray0; - process(v_r0, v_g0, v_b0, - v_gray0); + __m128i v_gray; + process(v_rgb, v_coeffs, + v_gray); - __m128i v_gray1; - process(v_r1, v_g1, v_b1, - v_gray1); - - _mm_storeu_si128((__m128i *)(dst + i), v_gray0); - _mm_storeu_si128((__m128i *)(dst + i + 8), v_gray1); + _mm_storeu_si128((__m128i *)(dst + i), v_gray); } } else if (scn == 4 && haveSIMD) { - for ( ; i <= n - 16; i += 16, src += scn * 16) + __m128i v_coeffs[2]; + v_coeffs[0] = _mm_set_epi16(0, (short)coeffs[2], (short)coeffs[1], (short)coeffs[0], 0, (short)coeffs[2], (short)coeffs[1], (short)coeffs[0]); + v_coeffs[1] = _mm_slli_epi16(v_coeffs[0], 2); + + for ( ; i <= n - 8; i += 8, src += scn * 8) { - __m128i v_r0 = _mm_loadu_si128((__m128i const *)(src)); - __m128i v_r1 = _mm_loadu_si128((__m128i const *)(src + 8)); - __m128i v_g0 = _mm_loadu_si128((__m128i const *)(src + 16)); - __m128i v_g1 = _mm_loadu_si128((__m128i const *)(src + 24)); - __m128i v_b0 = _mm_loadu_si128((__m128i const *)(src + 32)); - __m128i v_b1 = _mm_loadu_si128((__m128i const *)(src + 40)); - __m128i v_a0 = _mm_loadu_si128((__m128i const *)(src + 48)); - __m128i v_a1 = _mm_loadu_si128((__m128i const *)(src + 56)); + __m128i v_rgb[4]; + v_rgb[0] = _mm_loadu_si128((__m128i const *)(src)); + v_rgb[1] = _mm_loadu_si128((__m128i const *)(src + 8)); + v_rgb[2] = _mm_loadu_si128((__m128i const *)(src + 16)); + v_rgb[3] = _mm_loadu_si128((__m128i const *)(src + 24)); - _mm_deinterleave_epi16(v_r0, v_r1, v_g0, v_g1, v_b0, v_b1, v_a0, v_a1); + __m128i v_gray; + process(v_rgb, v_coeffs, + v_gray); - __m128i v_gray0; - process(v_r0, v_g0, v_b0, - v_gray0); - - __m128i v_gray1; - process(v_r1, v_g1, v_b1, - v_gray1); - - _mm_storeu_si128((__m128i *)(dst + i), v_gray0); - _mm_storeu_si128((__m128i *)(dst + i + 8), v_gray1); + _mm_storeu_si128((__m128i *)(dst + i), v_gray); } } @@ -1586,8 +1592,8 @@ struct RGB2Gray } int srccn, coeffs[3]; - __m128i v_cb, v_cg, v_cr; __m128i v_delta; + __m128i v_zero; bool haveSIMD; }; From 3860b8db02e93c71e1a5e9bbc5dafbbebbd81fec Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Fri, 12 Aug 2016 18:16:04 +0300 Subject: [PATCH 061/178] IPP was enabled in mathfuncs_core; Exp and Log IPP implementations are changed to hal interface; --- modules/core/include/opencv2/core/private.hpp | 8 +- modules/core/src/mathfuncs.cpp | 89 ++----------------- modules/core/src/mathfuncs_core.cpp | 74 ++++----------- 3 files changed, 30 insertions(+), 141 deletions(-) diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index 656394bd38..c884815d2e 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -382,9 +382,15 @@ static struct __IppInitializer__ __ipp_initializer__; return __VA_ARGS__; \ } #endif - +#define CV_IPP_RUN_FAST(func, ...) \ + if (cv::ipp::useIPP() && (func)) \ + { \ + CV_IMPL_ADD(CV_IMPL_IPP); \ + return __VA_ARGS__; \ + } #else #define CV_IPP_RUN_(condition, func, ...) +#define CV_IPP_RUN_FAST(func, ...) #endif #define CV_IPP_RUN(condition, func, ...) CV_IPP_RUN_(condition, func, __VA_ARGS__) diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index e974776c85..f69381061b 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -618,43 +618,6 @@ void polarToCart( InputArray src1, InputArray src2, * E X P * \****************************************************************************************/ -#ifdef HAVE_IPP -static void Exp_32f_ipp(const float *x, float *y, int n) -{ - CV_IPP_CHECK() - { - if (0 <= ippsExp_32f_A21(x, y, n)) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } - hal::exp32f(x, y, n); -} - -static void Exp_64f_ipp(const double *x, double *y, int n) -{ - CV_IPP_CHECK() - { - if (0 <= ippsExp_64f_A50(x, y, n)) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } - hal::exp64f(x, y, n); -} - -#define Exp_32f Exp_32f_ipp -#define Exp_64f Exp_64f_ipp -#else -#define Exp_32f hal::exp32f -#define Exp_64f hal::exp64f -#endif - - void exp( InputArray _src, OutputArray _dst ) { int type = _src.type(), depth = _src.depth(), cn = _src.channels(); @@ -675,9 +638,9 @@ void exp( InputArray _src, OutputArray _dst ) for( size_t i = 0; i < it.nplanes; i++, ++it ) { if( depth == CV_32F ) - Exp_32f((const float*)ptrs[0], (float*)ptrs[1], len); + hal::exp32f((const float*)ptrs[0], (float*)ptrs[1], len); else - Exp_64f((const double*)ptrs[0], (double*)ptrs[1], len); + hal::exp64f((const double*)ptrs[0], (double*)ptrs[1], len); } } @@ -686,42 +649,6 @@ void exp( InputArray _src, OutputArray _dst ) * L O G * \****************************************************************************************/ -#ifdef HAVE_IPP -static void Log_32f_ipp(const float *x, float *y, int n) -{ - CV_IPP_CHECK() - { - if (0 <= ippsLn_32f_A21(x, y, n)) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } - hal::log32f(x, y, n); -} - -static void Log_64f_ipp(const double *x, double *y, int n) -{ - CV_IPP_CHECK() - { - if (0 <= ippsLn_64f_A50(x, y, n)) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } - hal::log64f(x, y, n); -} - -#define Log_32f Log_32f_ipp -#define Log_64f Log_64f_ipp -#else -#define Log_32f hal::log32f -#define Log_64f hal::log64f -#endif - void log( InputArray _src, OutputArray _dst ) { int type = _src.type(), depth = _src.depth(), cn = _src.channels(); @@ -742,9 +669,9 @@ void log( InputArray _src, OutputArray _dst ) for( size_t i = 0; i < it.nplanes; i++, ++it ) { if( depth == CV_32F ) - Log_32f( (const float*)ptrs[0], (float*)ptrs[1], len ); + hal::log32f( (const float*)ptrs[0], (float*)ptrs[1], len ); else - Log_64f( (const double*)ptrs[0], (double*)ptrs[1], len ); + hal::log64f( (const double*)ptrs[0], (double*)ptrs[1], len ); } } @@ -1345,10 +1272,10 @@ void pow( InputArray _src, double power, OutputArray _dst ) if( x != x0 ) memcpy(x, x0, bsz*esz1); - Log_32f(x, y, bsz); + hal::log32f(x, y, bsz); for( k = 0; k < bsz; k++ ) y[k] = (float)(y[k]*power); - Exp_32f(y, y, bsz); + hal::exp32f(y, y, bsz); for( k = 0; k < bsz; k++ ) { if( x0[k] <= 0 ) @@ -1372,10 +1299,10 @@ void pow( InputArray _src, double power, OutputArray _dst ) if( x != x0 ) memcpy(x, x0, bsz*esz1); - Log_64f(x, y, bsz); + hal::log64f(x, y, bsz); for( k = 0; k < bsz; k++ ) y[k] *= power; - Exp_64f(y, y, bsz); + hal::exp64f(y, y, bsz); for( k = 0; k < bsz; k++ ) { diff --git a/modules/core/src/mathfuncs_core.cpp b/modules/core/src/mathfuncs_core.cpp index de292fae94..25fb951775 100644 --- a/modules/core/src/mathfuncs_core.cpp +++ b/modules/core/src/mathfuncs_core.cpp @@ -44,8 +44,6 @@ using namespace std; -#undef HAVE_IPP - namespace { static const float atan2_p1 = 0.9997878412794807f*(float)(180/CV_PI); @@ -224,18 +222,7 @@ void fastAtan2(const float *Y, const float *X, float *angle, int len, bool angle void magnitude32f(const float* x, const float* y, float* mag, int len) { CALL_HAL(magnitude32f, cv_hal_magnitude32f, x, y, mag, len); -#if defined HAVE_IPP - CV_IPP_CHECK() - { - IppStatus status = ippsMagnitude_32f(x, y, mag, len); - if (status >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } -#endif + CV_IPP_RUN_FAST(ippsMagnitude_32f(x, y, mag, len) >= 0); int i = 0; @@ -261,18 +248,7 @@ void magnitude32f(const float* x, const float* y, float* mag, int len) void magnitude64f(const double* x, const double* y, double* mag, int len) { CALL_HAL(magnitude64f, cv_hal_magnitude64f, x, y, mag, len); -#if defined(HAVE_IPP) - CV_IPP_CHECK() - { - IppStatus status = ippsMagnitude_64f(x, y, mag, len); - if (status >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } -#endif + CV_IPP_RUN_FAST(ippsMagnitude_64f(x, y, mag, len) >= 0); int i = 0; @@ -299,17 +275,7 @@ void magnitude64f(const double* x, const double* y, double* mag, int len) void invSqrt32f(const float* src, float* dst, int len) { CALL_HAL(invSqrt32f, cv_hal_invSqrt32f, src, dst, len); -#if defined(HAVE_IPP) - CV_IPP_CHECK() - { - if (ippsInvSqrt_32f_A21(src, dst, len) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } -#endif + CV_IPP_RUN_FAST(ippsInvSqrt_32f_A21(src, dst, len) >= 0); int i = 0; @@ -331,6 +297,8 @@ void invSqrt32f(const float* src, float* dst, int len) void invSqrt64f(const double* src, double* dst, int len) { CALL_HAL(invSqrt64f, cv_hal_invSqrt64f, src, dst, len); + CV_IPP_RUN_FAST(ippsInvSqrt_64f_A50(src, dst, len) >= 0); + int i = 0; #if CV_SSE2 @@ -347,17 +315,7 @@ void invSqrt64f(const double* src, double* dst, int len) void sqrt32f(const float* src, float* dst, int len) { CALL_HAL(sqrt32f, cv_hal_sqrt32f, src, dst, len); -#if defined(HAVE_IPP) - CV_IPP_CHECK() - { - if (ippsSqrt_32f_A21(src, dst, len) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } -#endif + CV_IPP_RUN_FAST(ippsSqrt_32f_A21(src, dst, len) >= 0); int i = 0; @@ -379,17 +337,7 @@ void sqrt32f(const float* src, float* dst, int len) void sqrt64f(const double* src, double* dst, int len) { CALL_HAL(sqrt64f, cv_hal_sqrt64f, src, dst, len); -#if defined(HAVE_IPP) - CV_IPP_CHECK() - { - if (ippsSqrt_64f_A50(src, dst, len) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } -#endif + CV_IPP_RUN_FAST(ippsSqrt_64f_A50(src, dst, len) >= 0); int i = 0; @@ -511,6 +459,8 @@ static const double exp_max_val = 3000.*(1 << EXPTAB_SCALE); // log10(DBL_MAX) < void exp32f( const float *_x, float *y, int n ) { CALL_HAL(exp32f, cv_hal_exp32f, _x, y, n); + CV_IPP_RUN_FAST(ippsExp_32f_A21(_x, y, n) >= 0); + static const float A4 = (float)(1.000000000000002438532970795181890933776 / EXPPOLY_32F_A0), A3 = (float)(.6931471805521448196800669615864773144641 / EXPPOLY_32F_A0), @@ -711,6 +661,8 @@ void exp32f( const float *_x, float *y, int n ) void exp64f( const double *_x, double *y, int n ) { CALL_HAL(exp64f, cv_hal_exp64f, _x, y, n); + CV_IPP_RUN_FAST(ippsExp_64f_A50(_x, y, n) >= 0); + static const double A5 = .99999999999999999998285227504999 / EXPPOLY_32F_A0, A4 = .69314718055994546743029643825322 / EXPPOLY_32F_A0, @@ -1156,6 +1108,8 @@ static const double ln_2 = 0.69314718055994530941723212145818; void log32f( const float *_x, float *y, int n ) { CALL_HAL(log32f, cv_hal_log32f, _x, y, n); + CV_IPP_RUN_FAST(ippsLn_32f_A21(_x, y, n) >= 0); + static const float shift[] = { 0, -1.f/512 }; static const float A0 = 0.3333333333333333333333333f, @@ -1301,6 +1255,8 @@ void log32f( const float *_x, float *y, int n ) void log64f( const double *x, double *y, int n ) { CALL_HAL(log64f, cv_hal_log64f, x, y, n); + CV_IPP_RUN_FAST(ippsLn_64f_A50(x, y, n) >= 0); + static const double shift[] = { 0, -1./512 }; static const double A7 = 1.0, From ac2d79fd670035429053a9cd305b99fd88f7fa8c Mon Sep 17 00:00:00 2001 From: will hunt Date: Sun, 7 Aug 2016 08:38:38 +0800 Subject: [PATCH 062/178] MSER: all test passed. 1. if a component's variation is a global minimum than it should be a local minimum 2. for the small image with invert and blur, the MSERs number should be 20 --- modules/features2d/src/mser.cpp | 2 +- modules/features2d/test/test_mser.cpp | 2 +- modules/python/test/test_mser.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/features2d/src/mser.cpp b/modules/features2d/src/mser.cpp index 669e3877d8..8f43eeaa38 100644 --- a/modules/features2d/src/mser.cpp +++ b/modules/features2d/src/mser.cpp @@ -211,7 +211,7 @@ public: return; } } - if( parent_ && parent_->var >= 0.f && var >= parent_->var ) + if( var > 0.f && parent_ && parent_->var >= 0.f && var >= parent_->var ) return; int xmin = INT_MAX, ymin = INT_MAX, xmax = INT_MIN, ymax = INT_MIN, j = 0; wp.msers->push_back(vector()); diff --git a/modules/features2d/test/test_mser.cpp b/modules/features2d/test/test_mser.cpp index 89b8ddbade..a52c3c3b81 100644 --- a/modules/features2d/test/test_mser.cpp +++ b/modules/features2d/test/test_mser.cpp @@ -132,7 +132,7 @@ TEST(Features2d_MSER, cases) GaussianBlur(src, src, Size(5, 5), 1.5, 1.5); int minRegs = use_big_image ? 7 : 2; - int maxRegs = use_big_image ? 1000 : 15; + int maxRegs = use_big_image ? 1000 : 20; if( binarize && (thresh == 0 || thresh == 255) ) minRegs = maxRegs = 0; diff --git a/modules/python/test/test_mser.py b/modules/python/test/test_mser.py index 619300b865..f66582ee4b 100644 --- a/modules/python/test/test_mser.py +++ b/modules/python/test/test_mser.py @@ -59,11 +59,11 @@ class mser_test(NewOpenCVTests): if blur: src = cv2.GaussianBlur(src, (5, 5), 1.5, 1.5) minRegs = 7 if use_big_image else 2 - maxRegs = 1000 if use_big_image else 15 + maxRegs = 1000 if use_big_image else 20 if binarize and (thresh == 0 or thresh == 255): minRegs = maxRegs = 0 msers, boxes = mserExtractor.detectRegions(src) nmsers = len(msers) self.assertEqual(nmsers, len(boxes)) self.assertLessEqual(minRegs, nmsers) - self.assertGreaterEqual(maxRegs, nmsers) \ No newline at end of file + self.assertGreaterEqual(maxRegs, nmsers) From 4f7679cf5131faa44be160d3f9eaaf279aa34d74 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Mon, 15 Aug 2016 08:40:13 +0900 Subject: [PATCH 063/178] use universal intrinsic in accumulate series * accumulate, accumulateSquare, accumulateProduct and accumulateWeighted --- modules/imgproc/src/accum.cpp | 729 +++++++++------------------------- 1 file changed, 192 insertions(+), 537 deletions(-) diff --git a/modules/imgproc/src/accum.cpp b/modules/imgproc/src/accum.cpp index 083192bdbd..dc1807f960 100644 --- a/modules/imgproc/src/accum.cpp +++ b/modules/imgproc/src/accum.cpp @@ -43,6 +43,7 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" +#include "opencv2/core/hal/intrin.hpp" namespace cv { @@ -728,44 +729,54 @@ struct AccW_SIMD }; #endif -#if CV_SSE2 +#if CV_SIMD128 template <> struct Acc_SIMD { int operator() (const uchar * src, float * dst, const uchar * mask, int len, int cn) const { int x = 0; - __m128i v_0 = _mm_setzero_si128(); if (!mask) { len *= cn; for ( ; x <= len - 16; x += 16) { - __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); - __m128i v_src0 = _mm_unpacklo_epi8(v_src, v_0); - __m128i v_src1 = _mm_unpackhi_epi8(v_src, v_0); + v_uint8x16 v_src = v_load((const uchar*)(src + x)); + v_uint16x8 v_src0, v_src1; + v_expand(v_src, v_src0, v_src1); - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src0, v_0)))); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src0, v_0)))); - _mm_storeu_ps(dst + x + 8, _mm_add_ps(_mm_loadu_ps(dst + x + 8), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src1, v_0)))); - _mm_storeu_ps(dst + x + 12, _mm_add_ps(_mm_loadu_ps(dst + x + 12), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src1, v_0)))); + v_uint32x4 v_src00, v_src01, v_src10, v_src11; + v_expand(v_src0, v_src00, v_src01); + v_expand(v_src1, v_src10, v_src11); + + v_store(dst + x, v_load(dst + x) + v_cvt_f32(v_reinterpret_as_s32(v_src00))); + v_store(dst + x + 4, v_load(dst + x + 4) + v_cvt_f32(v_reinterpret_as_s32(v_src01))); + v_store(dst + x + 8, v_load(dst + x + 8) + v_cvt_f32(v_reinterpret_as_s32(v_src10))); + v_store(dst + x + 12, v_load(dst + x + 12) + v_cvt_f32(v_reinterpret_as_s32(v_src11))); } } else if (cn == 1) { - __m128i v_255 = _mm_set1_epi8(-1); + v_uint8x16 v_0 = v_setall_u8(0); for ( ; x <= len - 16; x += 16) { - __m128i v_src = _mm_and_si128(_mm_loadu_si128((const __m128i*)(src + x)), _mm_xor_si128(v_255, _mm_cmpeq_epi8(_mm_loadu_si128((const __m128i*)(mask + x)), v_0))); - __m128i v_src0 = _mm_unpacklo_epi8(v_src, v_0); - __m128i v_src1 = _mm_unpackhi_epi8(v_src, v_0); + v_uint8x16 v_mask = v_load((const uchar*)(mask + x)); + v_mask = ~(v_0 == v_mask); + v_uint8x16 v_src = v_load((const uchar*)(src + x)); + v_src = v_src & v_mask; + v_uint16x8 v_src0, v_src1; + v_expand(v_src, v_src0, v_src1); - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src0, v_0)))); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src0, v_0)))); - _mm_storeu_ps(dst + x + 8, _mm_add_ps(_mm_loadu_ps(dst + x + 8), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src1, v_0)))); - _mm_storeu_ps(dst + x + 12, _mm_add_ps(_mm_loadu_ps(dst + x + 12), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src1, v_0)))); + v_uint32x4 v_src00, v_src01, v_src10, v_src11; + v_expand(v_src0, v_src00, v_src01); + v_expand(v_src1, v_src10, v_src11); + + v_store(dst + x, v_load(dst + x) + v_cvt_f32(v_reinterpret_as_s32(v_src00))); + v_store(dst + x + 4, v_load(dst + x + 4) + v_cvt_f32(v_reinterpret_as_s32(v_src01))); + v_store(dst + x + 8, v_load(dst + x + 8) + v_cvt_f32(v_reinterpret_as_s32(v_src10))); + v_store(dst + x + 12, v_load(dst + x + 12) + v_cvt_f32(v_reinterpret_as_s32(v_src11))); } } @@ -779,19 +790,17 @@ struct Acc_SIMD int operator() (const ushort * src, float * dst, const uchar * mask, int len, int cn) const { int x = 0; - __m128i v_0 = _mm_setzero_si128(); - if (!mask) { len *= cn; for ( ; x <= len - 8; x += 8) { - __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); - __m128i v_src0 = _mm_unpacklo_epi16(v_src, v_0); - __m128i v_src1 = _mm_unpackhi_epi16(v_src, v_0); + v_uint16x8 v_src = v_load((const ushort*)(src + x)); + v_uint32x4 v_src0, v_src1; + v_expand(v_src, v_src0, v_src1); - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_cvtepi32_ps(v_src0))); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_cvtepi32_ps(v_src1))); + v_store(dst + x, v_load(dst + x) + v_cvt_f32(v_reinterpret_as_s32(v_src0))); + v_store(dst + x + 4, v_load(dst + x + 4) + v_cvt_f32(v_reinterpret_as_s32(v_src1))); } } @@ -799,6 +808,7 @@ struct Acc_SIMD } }; +#if CV_SSE2 template <> struct Acc_SIMD { @@ -900,6 +910,7 @@ struct Acc_SIMD return x; } }; +#endif template <> struct AccSqr_SIMD @@ -907,42 +918,50 @@ struct AccSqr_SIMD int operator() (const uchar * src, float * dst, const uchar * mask, int len, int cn) const { int x = 0; - __m128i v_0 = _mm_setzero_si128(); if (!mask) { len *= cn; for ( ; x <= len - 16; x += 16) { - __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); - __m128i v_src0 = _mm_unpacklo_epi8(v_src, v_0); - __m128i v_src1 = _mm_unpackhi_epi8(v_src, v_0); - v_src0 = _mm_mullo_epi16(v_src0, v_src0); - v_src1 = _mm_mullo_epi16(v_src1, v_src1); + v_uint8x16 v_src = v_load((const uchar*)(src + x)); + v_uint16x8 v_src0, v_src1; + v_expand(v_src, v_src0, v_src1); + v_src0 = v_src0 * v_src0; + v_src1 = v_src1 * v_src1; - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src0, v_0)))); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src0, v_0)))); - _mm_storeu_ps(dst + x + 8, _mm_add_ps(_mm_loadu_ps(dst + x + 8), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src1, v_0)))); - _mm_storeu_ps(dst + x + 12, _mm_add_ps(_mm_loadu_ps(dst + x + 12), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src1, v_0)))); + v_uint32x4 v_src00, v_src01, v_src10, v_src11; + v_expand(v_src0, v_src00, v_src01); + v_expand(v_src1, v_src10, v_src11); + + v_store(dst + x, v_load(dst + x) + v_cvt_f32(v_reinterpret_as_s32(v_src00))); + v_store(dst + x + 4, v_load(dst + x + 4) + v_cvt_f32(v_reinterpret_as_s32(v_src01))); + v_store(dst + x + 8, v_load(dst + x + 8) + v_cvt_f32(v_reinterpret_as_s32(v_src10))); + v_store(dst + x + 12, v_load(dst + x + 12) + v_cvt_f32(v_reinterpret_as_s32(v_src11))); } } else if (cn == 1) { - - __m128i v_255 = _mm_set1_epi8(-1); + v_uint8x16 v_0 = v_setall_u8(0); for ( ; x <= len - 16; x += 16) { + v_uint8x16 v_mask = v_load((const uchar*)(mask + x)); + v_mask = ~(v_0 == v_mask); + v_uint8x16 v_src = v_load((const uchar*)(src + x)); + v_src = v_src & v_mask; + v_uint16x8 v_src0, v_src1; + v_expand(v_src, v_src0, v_src1); + v_src0 = v_src0 * v_src0; + v_src1 = v_src1 * v_src1; - __m128i v_src = _mm_and_si128(_mm_loadu_si128((const __m128i*)(src + x)), _mm_xor_si128(v_255, _mm_cmpeq_epi8(_mm_loadu_si128((const __m128i*)(mask + x)), v_0))); - __m128i v_src0 = _mm_unpacklo_epi8(v_src, v_0); - __m128i v_src1 = _mm_unpackhi_epi8(v_src, v_0); - v_src0 = _mm_mullo_epi16(v_src0, v_src0); - v_src1 = _mm_mullo_epi16(v_src1, v_src1); + v_uint32x4 v_src00, v_src01, v_src10, v_src11; + v_expand(v_src0, v_src00, v_src01); + v_expand(v_src1, v_src10, v_src11); - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src0, v_0)))); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src0, v_0)))); - _mm_storeu_ps(dst + x + 8, _mm_add_ps(_mm_loadu_ps(dst + x + 8), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src1, v_0)))); - _mm_storeu_ps(dst + x + 12, _mm_add_ps(_mm_loadu_ps(dst + x + 12), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src1, v_0)))); + v_store(dst + x, v_load(dst + x) + v_cvt_f32(v_reinterpret_as_s32(v_src00))); + v_store(dst + x + 4, v_load(dst + x + 4) + v_cvt_f32(v_reinterpret_as_s32(v_src01))); + v_store(dst + x + 8, v_load(dst + x + 8) + v_cvt_f32(v_reinterpret_as_s32(v_src10))); + v_store(dst + x + 12, v_load(dst + x + 12) + v_cvt_f32(v_reinterpret_as_s32(v_src11))); } } @@ -956,23 +975,24 @@ struct AccSqr_SIMD int operator() (const ushort * src, float * dst, const uchar * mask, int len, int cn) const { int x = 0; - __m128i v_0 = _mm_setzero_si128(); if (!mask) { len *= cn; for ( ; x <= len - 8; x += 8) { - __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); - __m128i v_int0 = _mm_unpacklo_epi16(v_src, v_0); - __m128i v_int1 = _mm_unpackhi_epi16(v_src, v_0); - __m128 v_src0 = _mm_cvtepi32_ps(v_int0); - __m128 v_src1 = _mm_cvtepi32_ps(v_int1); - v_src0 = _mm_mul_ps(v_src0, v_src0); - v_src1 = _mm_mul_ps(v_src1, v_src1); + v_uint16x8 v_src = v_load((const ushort*)(src + x)); + v_uint32x4 v_src0, v_src1; + v_expand(v_src, v_src0, v_src1); - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), v_src0)); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), v_src1)); + v_float32x4 v_float0, v_float1; + v_float0 = v_cvt_f32(v_reinterpret_as_s32(v_src0)); + v_float1 = v_cvt_f32(v_reinterpret_as_s32(v_src1)); + v_float0 = v_float0 * v_float0; + v_float1 = v_float1 * v_float1; + + v_store(dst + x, v_load(dst + x) + v_float0); + v_store(dst + x + 4, v_load(dst + x + 4) + v_float1); } } @@ -980,6 +1000,7 @@ struct AccSqr_SIMD } }; +#if CV_SSE2 template <> struct AccSqr_SIMD { @@ -1070,6 +1091,7 @@ struct AccSqr_SIMD return x; } }; +#endif template <> struct AccProd_SIMD @@ -1078,58 +1100,60 @@ struct AccProd_SIMD { int x = 0; - __m128i v_0 = _mm_setzero_si128(); len *= cn; if (!mask) { for ( ; x <= len - 16; x += 16) { - __m128i v_1src = _mm_loadu_si128((const __m128i*)(src1 + x)); - __m128i v_2src = _mm_loadu_si128((const __m128i*)(src2 + x)); + v_uint8x16 v_1src = v_load(src1 + x); + v_uint8x16 v_2src = v_load(src2 + x); - __m128i v_1src0 = _mm_unpacklo_epi8(v_1src, v_0); - __m128i v_1src1 = _mm_unpackhi_epi8(v_1src, v_0); - __m128i v_2src0 = _mm_unpacklo_epi8(v_2src, v_0); - __m128i v_2src1 = _mm_unpackhi_epi8(v_2src, v_0); - __m128i v_src0 = _mm_mullo_epi16(v_1src0, v_2src0); - __m128i v_src1 = _mm_mullo_epi16(v_1src1, v_2src1); - __m128 v_src00 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src0, v_0)); - __m128 v_src01 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src0, v_0)); - __m128 v_src10 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src1, v_0)); - __m128 v_src11 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src1, v_0)); + v_uint16x8 v_1src0, v_1src1, v_2src0, v_2src1; + v_expand(v_1src, v_1src0, v_1src1); + v_expand(v_2src, v_2src0, v_2src1); - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), v_src00)); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), v_src01)); - _mm_storeu_ps(dst + x + 8, _mm_add_ps(_mm_loadu_ps(dst + x + 8), v_src10)); - _mm_storeu_ps(dst + x + 12, _mm_add_ps(_mm_loadu_ps(dst + x + 12), v_src11)); + v_uint16x8 v_src0, v_src1; + v_src0 = v_1src0 * v_2src0; + v_src1 = v_1src1 * v_2src1; + + v_uint32x4 v_src00, v_src01, v_src10, v_src11; + v_expand(v_src0, v_src00, v_src01); + v_expand(v_src1, v_src10, v_src11); + + v_store(dst + x, v_load(dst + x) + v_cvt_f32(v_reinterpret_as_s32(v_src00))); + v_store(dst + x + 4, v_load(dst + x + 4) + v_cvt_f32(v_reinterpret_as_s32(v_src01))); + v_store(dst + x + 8, v_load(dst + x + 8) + v_cvt_f32(v_reinterpret_as_s32(v_src10))); + v_store(dst + x + 12, v_load(dst + x + 12) + v_cvt_f32(v_reinterpret_as_s32(v_src11))); } } else if (cn == 1) { - __m128i v_255 = _mm_set1_epi8(-1); + v_uint8x16 v_0 = v_setzero_u8(); for ( ; x <= len - 16; x += 16) { - __m128i v_mask = _mm_loadu_si128((const __m128i*)(mask + x)); - v_mask = _mm_xor_si128(v_255, _mm_cmpeq_epi8(v_mask, v_0)); - __m128i v_1src = _mm_and_si128(_mm_loadu_si128((const __m128i*)(src1 + x)), v_mask); - __m128i v_2src = _mm_and_si128(_mm_loadu_si128((const __m128i*)(src2 + x)), v_mask); + v_uint8x16 v_mask = v_load(mask + x); + v_mask = ~(v_0 == v_mask); - __m128i v_1src0 = _mm_unpacklo_epi8(v_1src, v_0); - __m128i v_1src1 = _mm_unpackhi_epi8(v_1src, v_0); - __m128i v_2src0 = _mm_unpacklo_epi8(v_2src, v_0); - __m128i v_2src1 = _mm_unpackhi_epi8(v_2src, v_0); - __m128i v_src0 = _mm_mullo_epi16(v_1src0, v_2src0); - __m128i v_src1 = _mm_mullo_epi16(v_1src1, v_2src1); - __m128 v_src00 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src0, v_0)); - __m128 v_src01 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src0, v_0)); - __m128 v_src10 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src1, v_0)); - __m128 v_src11 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src1, v_0)); + v_uint8x16 v_1src = v_load(src1 + x) & v_mask; + v_uint8x16 v_2src = v_load(src2 + x) & v_mask; - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), v_src00)); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), v_src01)); - _mm_storeu_ps(dst + x + 8, _mm_add_ps(_mm_loadu_ps(dst + x + 8), v_src10)); - _mm_storeu_ps(dst + x + 12, _mm_add_ps(_mm_loadu_ps(dst + x + 12), v_src11)); + v_uint16x8 v_1src0, v_1src1, v_2src0, v_2src1; + v_expand(v_1src, v_1src0, v_1src1); + v_expand(v_2src, v_2src0, v_2src1); + + v_uint16x8 v_src0, v_src1; + v_src0 = v_1src0 * v_2src0; + v_src1 = v_1src1 * v_2src1; + + v_uint32x4 v_src00, v_src01, v_src10, v_src11; + v_expand(v_src0, v_src00, v_src01); + v_expand(v_src1, v_src10, v_src11); + + v_store(dst + x, v_load(dst + x) + v_cvt_f32(v_reinterpret_as_s32(v_src00))); + v_store(dst + x + 4, v_load(dst + x + 4) + v_cvt_f32(v_reinterpret_as_s32(v_src01))); + v_store(dst + x + 8, v_load(dst + x + 8) + v_cvt_f32(v_reinterpret_as_s32(v_src10))); + v_store(dst + x + 12, v_load(dst + x + 12) + v_cvt_f32(v_reinterpret_as_s32(v_src11))); } } @@ -1143,47 +1167,59 @@ struct AccProd_SIMD int operator() (const ushort * src1, const ushort * src2, float * dst, const uchar * mask, int len, int cn) const { int x = 0; - __m128i v_0 = _mm_setzero_si128(); if (!mask) { len *= cn; for ( ; x <= len - 8; x += 8) { - __m128i v_1src = _mm_loadu_si128((const __m128i*)(src1 + x)); - __m128i v_2src = _mm_loadu_si128((const __m128i*)(src2 + x)); - __m128 v_1src0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_1src, v_0)); - __m128 v_1src1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_1src, v_0)); - __m128 v_2src0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_2src, v_0)); - __m128 v_2src1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_2src, v_0)); - __m128 v_src0 = _mm_mul_ps(v_1src0, v_2src0); - __m128 v_src1 = _mm_mul_ps(v_1src1, v_2src1); + v_uint16x8 v_1src = v_load(src1 + x); + v_uint16x8 v_2src = v_load(src2 + x); - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), v_src0)); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), v_src1)); + v_uint32x4 v_1src0, v_1src1, v_2src0, v_2src1; + v_expand(v_1src, v_1src0, v_1src1); + v_expand(v_2src, v_2src0, v_2src1); + + v_float32x4 v_1float0 = v_cvt_f32(v_reinterpret_as_s32(v_1src0)); + v_float32x4 v_1float1 = v_cvt_f32(v_reinterpret_as_s32(v_1src1)); + v_float32x4 v_2float0 = v_cvt_f32(v_reinterpret_as_s32(v_2src0)); + v_float32x4 v_2float1 = v_cvt_f32(v_reinterpret_as_s32(v_2src1)); + + v_float32x4 v_src0 = v_1float0 * v_2float0; + v_float32x4 v_src1 = v_1float1 * v_2float1; + + v_store(dst + x, v_load(dst + x) + v_src0); + v_store(dst + x + 4, v_load(dst + x + 4) + v_src1); } } else if (cn == 1) { - __m128i v_65535 = _mm_set1_epi16(-1); + v_uint16x8 v_0 = v_setzero_u16(); for ( ; x <= len - 8; x += 8) { - __m128i v_mask = _mm_loadl_epi64((const __m128i*)(mask + x)); - __m128i v_mask0 = _mm_unpacklo_epi8(v_mask, v_0); - v_mask0 = _mm_xor_si128(v_65535, _mm_cmpeq_epi16(v_mask0, v_0)); + v_uint8x16 v_mask = v_load_halves(mask + x, mask + x); + v_uint16x8 v_mask0, v_mask1; + v_expand(v_mask, v_mask0, v_mask1); + v_mask0 = ~(v_0 == v_mask0); - __m128i v_1src = _mm_and_si128(_mm_loadu_si128((const __m128i*)(src1 + x)), v_mask0); - __m128i v_2src = _mm_and_si128(_mm_loadu_si128((const __m128i*)(src2 + x)), v_mask0); - __m128 v_1src0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_1src, v_0)); - __m128 v_1src1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_1src, v_0)); - __m128 v_2src0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_2src, v_0)); - __m128 v_2src1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_2src, v_0)); - __m128 v_src0 = _mm_mul_ps(v_1src0, v_2src0); - __m128 v_src1 = _mm_mul_ps(v_1src1, v_2src1); + v_uint16x8 v_1src = v_load(src1 + x) & v_mask0; + v_uint16x8 v_2src = v_load(src2 + x) & v_mask0; - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), v_src0)); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), v_src1)); + v_uint32x4 v_1src0, v_1src1, v_2src0, v_2src1; + v_expand(v_1src, v_1src0, v_1src1); + v_expand(v_2src, v_2src0, v_2src1); + + v_float32x4 v_1float0 = v_cvt_f32(v_reinterpret_as_s32(v_1src0)); + v_float32x4 v_1float1 = v_cvt_f32(v_reinterpret_as_s32(v_1src1)); + v_float32x4 v_2float0 = v_cvt_f32(v_reinterpret_as_s32(v_2src0)); + v_float32x4 v_2float1 = v_cvt_f32(v_reinterpret_as_s32(v_2src1)); + + v_float32x4 v_src0 = v_1float0 * v_2float0; + v_float32x4 v_src1 = v_1float1 * v_2float1; + + v_store(dst + x, v_load(dst + x) + v_src0); + v_store(dst + x + 4, v_load(dst + x + 4) + v_src1); } } @@ -1191,6 +1227,7 @@ struct AccProd_SIMD } }; +#if CV_SSE2 template <> struct AccProd_SIMD { @@ -1281,6 +1318,7 @@ struct AccProd_SIMD return x; } }; +#endif template <> struct AccW_SIMD @@ -1288,37 +1326,37 @@ struct AccW_SIMD int operator() (const uchar * src, float * dst, const uchar * mask, int len, int cn, float alpha) const { int x = 0; - __m128 v_alpha = _mm_set1_ps(alpha); - __m128 v_beta = _mm_set1_ps(1.0f - alpha); - __m128i v_0 = _mm_setzero_si128(); + v_float32x4 v_alpha = v_setall_f32(alpha); + v_float32x4 v_beta = v_setall_f32(1.0f - alpha); if (!mask) { len *= cn; for ( ; x <= len - 16; x += 16) { - __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); - __m128i v_src0 = _mm_unpacklo_epi8(v_src, v_0); - __m128i v_src1 = _mm_unpackhi_epi8(v_src, v_0); - __m128 v_src00 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src0, v_0)); - __m128 v_src01 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src0, v_0)); - __m128 v_src10 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src1, v_0)); - __m128 v_src11 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src1, v_0)); + v_uint8x16 v_src = v_load(src + x); - __m128 v_dst00 = _mm_loadu_ps(dst + x); - __m128 v_dst01 = _mm_loadu_ps(dst + x + 4); - __m128 v_dst10 = _mm_loadu_ps(dst + x + 8); - __m128 v_dst11 = _mm_loadu_ps(dst + x + 12); + v_uint16x8 v_src0, v_src1; + v_expand(v_src, v_src0, v_src1); - v_dst00 = _mm_add_ps(_mm_mul_ps(v_dst00, v_beta), _mm_mul_ps(v_src00, v_alpha)); - v_dst01 = _mm_add_ps(_mm_mul_ps(v_dst01, v_beta), _mm_mul_ps(v_src01, v_alpha)); - v_dst10 = _mm_add_ps(_mm_mul_ps(v_dst10, v_beta), _mm_mul_ps(v_src10, v_alpha)); - v_dst11 = _mm_add_ps(_mm_mul_ps(v_dst11, v_beta), _mm_mul_ps(v_src11, v_alpha)); + v_uint32x4 v_src00, v_src01, v_src10, v_src11; + v_expand(v_src0, v_src00, v_src01); + v_expand(v_src1, v_src10, v_src11); - _mm_storeu_ps(dst + x, v_dst00); - _mm_storeu_ps(dst + x + 4, v_dst01); - _mm_storeu_ps(dst + x + 8, v_dst10); - _mm_storeu_ps(dst + x + 12, v_dst11); + v_float32x4 v_dst00 = v_load(dst + x); + v_float32x4 v_dst01 = v_load(dst + x + 4); + v_float32x4 v_dst10 = v_load(dst + x + 8); + v_float32x4 v_dst11 = v_load(dst + x + 12); + + v_dst00 = (v_dst00 * v_beta) + (v_cvt_f32(v_reinterpret_as_s32(v_src00)) * v_alpha); + v_dst01 = (v_dst01 * v_beta) + (v_cvt_f32(v_reinterpret_as_s32(v_src01)) * v_alpha); + v_dst10 = (v_dst10 * v_beta) + (v_cvt_f32(v_reinterpret_as_s32(v_src10)) * v_alpha); + v_dst11 = (v_dst11 * v_beta) + (v_cvt_f32(v_reinterpret_as_s32(v_src11)) * v_alpha); + + v_store(dst + x, v_dst00); + v_store(dst + x + 4, v_dst01); + v_store(dst + x + 8, v_dst10); + v_store(dst + x + 12, v_dst11); } } @@ -1332,26 +1370,28 @@ struct AccW_SIMD int operator() (const ushort * src, float * dst, const uchar * mask, int len, int cn, float alpha) const { int x = 0; - __m128 v_alpha = _mm_set1_ps(alpha); - __m128 v_beta = _mm_set1_ps(1.0f - alpha); - __m128i v_0 = _mm_setzero_si128(); + v_float32x4 v_alpha = v_setall_f32(alpha); + v_float32x4 v_beta = v_setall_f32(1.0f - alpha); if (!mask) { len *= cn; for ( ; x <= len - 8; x += 8) { - __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); - __m128 v_src0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src, v_0)); - __m128 v_src1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src, v_0)); - v_src0 = _mm_mul_ps(v_src0, v_alpha); - v_src1 = _mm_mul_ps(v_src1, v_alpha); + v_uint16x8 v_src = v_load(src + x); + v_uint32x4 v_int0, v_int1; + v_expand(v_src, v_int0, v_int1); - __m128 v_dst0 = _mm_mul_ps(_mm_loadu_ps(dst + x), v_beta); - __m128 v_dst1 = _mm_mul_ps(_mm_loadu_ps(dst + x + 4), v_beta); + v_float32x4 v_src0 = v_cvt_f32(v_reinterpret_as_s32(v_int0)); + v_float32x4 v_src1 = v_cvt_f32(v_reinterpret_as_s32(v_int1)); + v_src0 = v_src0 * v_alpha; + v_src1 = v_src1 * v_alpha; - _mm_storeu_ps(dst + x, _mm_add_ps(v_dst0, v_src0)); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(v_dst1, v_src1)); + v_float32x4 v_dst0 = v_load(dst + x) * v_beta; + v_float32x4 v_dst1 = v_load(dst + x + 4) * v_beta; + + v_store(dst + x, v_dst0 + v_src0); + v_store(dst + x + 4, v_dst1 + v_src1); } } @@ -1359,6 +1399,7 @@ struct AccW_SIMD } }; +#if CV_SSE2 template <> struct AccW_SIMD { @@ -1448,393 +1489,7 @@ struct AccW_SIMD } }; #endif //CV_SSE2 - -#if CV_NEON - -template <> -struct Acc_SIMD -{ - int operator() (const uchar * src, float * dst, const uchar * mask, int len, int cn) const - { - int x = 0; - - if (!mask) - { - len *= cn; - for ( ; x <= len - 16; x += 16) - { - uint8x16_t v_src = vld1q_u8(src + x); - uint16x8_t v_src0 = vmovl_u8(vget_low_u8(v_src)), v_src1 = vmovl_u8(vget_high_u8(v_src)); - - vst1q_f32(dst + x, vaddq_f32(vld1q_f32(dst + x), vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_src0))))); - vst1q_f32(dst + x + 4, vaddq_f32(vld1q_f32(dst + x + 4), vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_src0))))); - vst1q_f32(dst + x + 8, vaddq_f32(vld1q_f32(dst + x + 8), vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_src1))))); - vst1q_f32(dst + x + 12, vaddq_f32(vld1q_f32(dst + x + 12), vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_src1))))); - } - } - else if (cn == 1) - { - uint8x16_t v_255 = vdupq_n_u8(255), v_0 = vdupq_n_u8(0); - - for ( ; x <= len - 16; x += 16) - { - uint8x16_t v_src = vandq_u8(vld1q_u8(src + x), veorq_u8(v_255, vceqq_u8(vld1q_u8(mask + x), v_0))); - uint16x8_t v_src0 = vmovl_u8(vget_low_u8(v_src)), v_src1 = vmovl_u8(vget_high_u8(v_src)); - - vst1q_f32(dst + x, vaddq_f32(vld1q_f32(dst + x), vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_src0))))); - vst1q_f32(dst + x + 4, vaddq_f32(vld1q_f32(dst + x + 4), vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_src0))))); - vst1q_f32(dst + x + 8, vaddq_f32(vld1q_f32(dst + x + 8), vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_src1))))); - vst1q_f32(dst + x + 12, vaddq_f32(vld1q_f32(dst + x + 12), vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_src1))))); - } - } - - return x; - } -}; - -template <> -struct Acc_SIMD -{ - int operator() (const ushort * src, float * dst, const uchar * mask, int len, int cn) const - { - int x = 0; - - if (!mask) - { - len *= cn; - for ( ; x <= len - 8; x += 8) - { - uint16x8_t v_src = vld1q_u16(src + x); - uint32x4_t v_src0 = vmovl_u16(vget_low_u16(v_src)), v_src1 = vmovl_u16(vget_high_u16(v_src)); - - vst1q_f32(dst + x, vaddq_f32(vld1q_f32(dst + x), vcvtq_f32_u32(v_src0))); - vst1q_f32(dst + x + 4, vaddq_f32(vld1q_f32(dst + x + 4), vcvtq_f32_u32(v_src1))); - } - } - - return x; - } -}; - -template <> -struct Acc_SIMD -{ - int operator() (const float * src, float * dst, const uchar * mask, int len, int cn) const - { - int x = 0; - - if (!mask) - { - len *= cn; - for ( ; x <= len - 8; x += 8) - { - vst1q_f32(dst + x, vaddq_f32(vld1q_f32(dst + x), vld1q_f32(src + x))); - vst1q_f32(dst + x + 4, vaddq_f32(vld1q_f32(dst + x + 4), vld1q_f32(src + x + 4))); - } - } - - return x; - } -}; - -template <> -struct AccSqr_SIMD -{ - int operator() (const uchar * src, float * dst, const uchar * mask, int len, int cn) const - { - int x = 0; - - if (!mask) - { - len *= cn; - for ( ; x <= len - 16; x += 16) - { - uint8x16_t v_src = vld1q_u8(src + x); - uint8x8_t v_src_0 = vget_low_u8(v_src), v_src_1 = vget_high_u8(v_src); - uint16x8_t v_src0 = vmull_u8(v_src_0, v_src_0), v_src1 = vmull_u8(v_src_1, v_src_1); - - vst1q_f32(dst + x, vaddq_f32(vld1q_f32(dst + x), vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_src0))))); - vst1q_f32(dst + x + 4, vaddq_f32(vld1q_f32(dst + x + 4), vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_src0))))); - vst1q_f32(dst + x + 8, vaddq_f32(vld1q_f32(dst + x + 8), vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_src1))))); - vst1q_f32(dst + x + 12, vaddq_f32(vld1q_f32(dst + x + 12), vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_src1))))); - } - } - else if (cn == 1) - { - uint8x16_t v_255 = vdupq_n_u8(255), v_0 = vdupq_n_u8(0); - - for ( ; x <= len - 16; x += 16) - { - uint8x16_t v_src = vandq_u8(vld1q_u8(src + x), veorq_u8(v_255, vceqq_u8(vld1q_u8(mask + x), v_0))); - uint8x8_t v_src_0 = vget_low_u8(v_src), v_src_1 = vget_high_u8(v_src); - uint16x8_t v_src0 = vmull_u8(v_src_0, v_src_0), v_src1 = vmull_u8(v_src_1, v_src_1); - - vst1q_f32(dst + x, vaddq_f32(vld1q_f32(dst + x), vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_src0))))); - vst1q_f32(dst + x + 4, vaddq_f32(vld1q_f32(dst + x + 4), vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_src0))))); - vst1q_f32(dst + x + 8, vaddq_f32(vld1q_f32(dst + x + 8), vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_src1))))); - vst1q_f32(dst + x + 12, vaddq_f32(vld1q_f32(dst + x + 12), vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_src1))))); - } - } - - return x; - } -}; - -template <> -struct AccSqr_SIMD -{ - int operator() (const ushort * src, float * dst, const uchar * mask, int len, int cn) const - { - int x = 0; - - if (!mask) - { - len *= cn; - for ( ; x <= len - 8; x += 8) - { - uint16x8_t v_src = vld1q_u16(src + x); - uint16x4_t v_src_0 = vget_low_u16(v_src), v_src_1 = vget_high_u16(v_src); - uint32x4_t v_src0 = vmull_u16(v_src_0, v_src_0), v_src1 = vmull_u16(v_src_1, v_src_1); - - vst1q_f32(dst + x, vaddq_f32(vld1q_f32(dst + x), vcvtq_f32_u32(v_src0))); - vst1q_f32(dst + x + 4, vaddq_f32(vld1q_f32(dst + x + 4), vcvtq_f32_u32(v_src1))); - } - } - else if (cn == 1) - { - uint8x8_t v_255 = vdup_n_u8(255), v_0 = vdup_n_u8(0); - - for ( ; x <= len - 8; x += 8) - { - uint8x8_t v_mask_src = veor_u8(v_255, vceq_u8(vld1_u8(mask + x), v_0)); - uint8x8x2_t v_mask_zp = vzip_u8(v_mask_src, v_mask_src); - uint16x8_t v_mask = vreinterpretq_u16_u8(vcombine_u8(v_mask_zp.val[0], v_mask_zp.val[1])), - v_src = vandq_u16(vld1q_u16(src + x), v_mask); - - uint16x4_t v_src_0 = vget_low_u16(v_src), v_src_1 = vget_high_u16(v_src); - uint32x4_t v_src0 = vmull_u16(v_src_0, v_src_0), v_src1 = vmull_u16(v_src_1, v_src_1); - - vst1q_f32(dst + x, vaddq_f32(vld1q_f32(dst + x), vcvtq_f32_u32(v_src0))); - vst1q_f32(dst + x + 4, vaddq_f32(vld1q_f32(dst + x + 4), vcvtq_f32_u32(v_src1))); - } - } - - return x; - } -}; - -template <> -struct AccSqr_SIMD -{ - int operator() (const float * src, float * dst, const uchar * mask, int len, int cn) const - { - int x = 0; - - if (!mask) - { - len *= cn; - for ( ; x <= len - 8; x += 8) - { - float32x4_t v_src = vld1q_f32(src + x); - vst1q_f32(dst + x, vmlaq_f32(vld1q_f32(dst + x), v_src, v_src)); - - v_src = vld1q_f32(src + x + 4); - vst1q_f32(dst + x + 4, vmlaq_f32(vld1q_f32(dst + x + 4), v_src, v_src)); - } - } - - return x; - } -}; - -template <> -struct AccProd_SIMD -{ - int operator() (const uchar * src1, const uchar * src2, float * dst, const uchar * mask, int len, int cn) const - { - int x = 0; - - if (!mask) - { - len *= cn; - for ( ; x <= len - 16; x += 16) - { - uint8x16_t v_1src = vld1q_u8(src1 + x), v_2src = vld1q_u8(src2 + x); - uint16x8_t v_src0 = vmull_u8(vget_low_u8(v_1src), vget_low_u8(v_2src)), - v_src1 = vmull_u8(vget_high_u8(v_1src), vget_high_u8(v_2src)); - - vst1q_f32(dst + x, vaddq_f32(vld1q_f32(dst + x), vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_src0))))); - vst1q_f32(dst + x + 4, vaddq_f32(vld1q_f32(dst + x + 4), vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_src0))))); - vst1q_f32(dst + x + 8, vaddq_f32(vld1q_f32(dst + x + 8), vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_src1))))); - vst1q_f32(dst + x + 12, vaddq_f32(vld1q_f32(dst + x + 12), vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_src1))))); - } - } - else if (cn == 1) - { - uint8x16_t v_255 = vdupq_n_u8(255), v_0 = vdupq_n_u8(0); - - for ( ; x <= len - 16; x += 16) - { - uint8x16_t v_mask = veorq_u8(v_255, vceqq_u8(vld1q_u8(mask + x), v_0)); - uint8x16_t v_1src = vandq_u8(vld1q_u8(src1 + x), v_mask), v_2src = vandq_u8(vld1q_u8(src2 + x), v_mask); - uint16x8_t v_src0 = vmull_u8(vget_low_u8(v_1src), vget_low_u8(v_2src)), - v_src1 = vmull_u8(vget_high_u8(v_1src), vget_high_u8(v_2src)); - - vst1q_f32(dst + x, vaddq_f32(vld1q_f32(dst + x), vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_src0))))); - vst1q_f32(dst + x + 4, vaddq_f32(vld1q_f32(dst + x + 4), vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_src0))))); - vst1q_f32(dst + x + 8, vaddq_f32(vld1q_f32(dst + x + 8), vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_src1))))); - vst1q_f32(dst + x + 12, vaddq_f32(vld1q_f32(dst + x + 12), vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_src1))))); - } - } - - return x; - } -}; - -template <> -struct AccProd_SIMD -{ - int operator() (const ushort * src1, const ushort * src2, float * dst, const uchar * mask, int len, int cn) const - { - int x = 0; - - if (!mask) - { - len *= cn; - for ( ; x <= len - 8; x += 8) - { - uint16x8_t v_1src = vld1q_u16(src1 + x), v_2src = vld1q_u16(src2 + x); - uint32x4_t v_src0 = vmull_u16(vget_low_u16(v_1src), vget_low_u16(v_2src)), - v_src1 = vmull_u16(vget_high_u16(v_1src), vget_high_u16(v_2src)); - - vst1q_f32(dst + x, vaddq_f32(vld1q_f32(dst + x), vcvtq_f32_u32(v_src0))); - vst1q_f32(dst + x + 4, vaddq_f32(vld1q_f32(dst + x + 4), vcvtq_f32_u32(v_src1))); - } - } - else if (cn == 1) - { - uint8x8_t v_255 = vdup_n_u8(255), v_0 = vdup_n_u8(0); - - for ( ; x <= len - 8; x += 8) - { - uint8x8_t v_mask_src = veor_u8(v_255, vceq_u8(vld1_u8(mask + x), v_0)); - uint8x8x2_t v_mask_zp = vzip_u8(v_mask_src, v_mask_src); - uint16x8_t v_mask = vreinterpretq_u16_u8(vcombine_u8(v_mask_zp.val[0], v_mask_zp.val[1])), - v_1src = vandq_u16(vld1q_u16(src1 + x), v_mask), - v_2src = vandq_u16(vld1q_u16(src2 + x), v_mask); - - uint32x4_t v_src0 = vmull_u16(vget_low_u16(v_1src), vget_low_u16(v_2src)), - v_src1 = vmull_u16(vget_high_u16(v_1src), vget_high_u16(v_2src)); - - vst1q_f32(dst + x, vaddq_f32(vld1q_f32(dst + x), vcvtq_f32_u32(v_src0))); - vst1q_f32(dst + x + 4, vaddq_f32(vld1q_f32(dst + x + 4), vcvtq_f32_u32(v_src1))); - } - } - - return x; - } -}; - -template <> -struct AccProd_SIMD -{ - int operator() (const float * src1, const float * src2, float * dst, const uchar * mask, int len, int cn) const - { - int x = 0; - - if (!mask) - { - len *= cn; - for ( ; x <= len - 8; x += 8) - { - vst1q_f32(dst + x, vmlaq_f32(vld1q_f32(dst + x), vld1q_f32(src1 + x), vld1q_f32(src2 + x))); - vst1q_f32(dst + x + 4, vmlaq_f32(vld1q_f32(dst + x + 4), vld1q_f32(src1 + x + 4), vld1q_f32(src2 + x + 4))); - } - } - - return x; - } -}; - -template <> -struct AccW_SIMD -{ - int operator() (const uchar * src, float * dst, const uchar * mask, int len, int cn, float alpha) const - { - int x = 0; - float32x4_t v_alpha = vdupq_n_f32(alpha), v_beta = vdupq_n_f32(1.0f - alpha); - - if (!mask) - { - len *= cn; - for ( ; x <= len - 16; x += 16) - { - uint8x16_t v_src = vld1q_u8(src + x); - uint16x8_t v_src0 = vmovl_u8(vget_low_u8(v_src)), v_src1 = vmovl_u8(vget_high_u8(v_src)); - - vst1q_f32(dst + x, vmlaq_f32(vmulq_f32(vld1q_f32(dst + x), v_beta), - vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_src0))), v_alpha)); - vst1q_f32(dst + x + 4, vmlaq_f32(vmulq_f32(vld1q_f32(dst + x + 4), v_beta), - vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_src0))), v_alpha)); - vst1q_f32(dst + x + 8, vmlaq_f32(vmulq_f32(vld1q_f32(dst + x + 8), v_beta), - vcvtq_f32_u32(vmovl_u16(vget_low_u16(v_src1))), v_alpha)); - vst1q_f32(dst + x + 12, vmlaq_f32(vmulq_f32(vld1q_f32(dst + x + 12), v_beta), - vcvtq_f32_u32(vmovl_u16(vget_high_u16(v_src1))), v_alpha)); - } - } - - return x; - } -}; - -template <> -struct AccW_SIMD -{ - int operator() (const ushort * src, float * dst, const uchar * mask, int len, int cn, float alpha) const - { - int x = 0; - float32x4_t v_alpha = vdupq_n_f32(alpha), v_beta = vdupq_n_f32(1.0f - alpha); - - if (!mask) - { - len *= cn; - for ( ; x <= len - 8; x += 8) - { - uint16x8_t v_src = vld1q_u16(src + x); - uint32x4_t v_src0 = vmovl_u16(vget_low_u16(v_src)), v_src1 = vmovl_u16(vget_high_u16(v_src)); - - vst1q_f32(dst + x, vmlaq_f32(vmulq_f32(vld1q_f32(dst + x), v_beta), vcvtq_f32_u32(v_src0), v_alpha)); - vst1q_f32(dst + x + 4, vmlaq_f32(vmulq_f32(vld1q_f32(dst + x + 4), v_beta), vcvtq_f32_u32(v_src1), v_alpha)); - } - } - - return x; - } -}; - -template <> -struct AccW_SIMD -{ - int operator() (const float * src, float * dst, const uchar * mask, int len, int cn, float alpha) const - { - int x = 0; - float32x4_t v_alpha = vdupq_n_f32(alpha), v_beta = vdupq_n_f32(1.0f - alpha); - - if (!mask) - { - len *= cn; - for ( ; x <= len - 8; x += 8) - { - vst1q_f32(dst + x, vmlaq_f32(vmulq_f32(vld1q_f32(dst + x), v_beta), vld1q_f32(src + x), v_alpha)); - vst1q_f32(dst + x + 4, vmlaq_f32(vmulq_f32(vld1q_f32(dst + x + 4), v_beta), vld1q_f32(src + x + 4), v_alpha)); - } - } - - return x; - } -}; - -#endif +#endif //CV_SIMD128 template void acc_( const T* src, AT* dst, const uchar* mask, int len, int cn ) From 3faaabd6f41d66e3fc983b927637ccb29eecea02 Mon Sep 17 00:00:00 2001 From: k-shinotsuka Date: Sun, 14 Aug 2016 23:24:33 +0900 Subject: [PATCH 064/178] improve YCrCb2RGB_i() --- modules/imgproc/src/color.cpp | 151 ++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index af75445e61..6331eab79b 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -2987,6 +2987,72 @@ struct YCrCb2RGB_i haveSIMD = checkHardwareSupport(CV_CPU_SSE2); } +#if CV_SSE4_1 + // 16s x 8 + void process(__m128i* v_src, __m128i* v_shuffle, + __m128i* v_coeffs) const + { + __m128i v_ycrcb[3]; + v_ycrcb[0] = _mm_shuffle_epi8(v_src[0], v_shuffle[0]); + v_ycrcb[1] = _mm_shuffle_epi8(_mm_alignr_epi8(v_src[1], v_src[0], 8), v_shuffle[0]); + v_ycrcb[2] = _mm_shuffle_epi8(v_src[1], v_shuffle[0]); + + __m128i v_y[3]; + v_y[1] = _mm_shuffle_epi8(v_src[0], v_shuffle[1]); + v_y[2] = _mm_srli_si128(_mm_shuffle_epi8(_mm_alignr_epi8(v_src[1], v_src[0], 15), v_shuffle[1]), 1); + v_y[0] = _mm_unpacklo_epi8(v_y[1], v_zero); + v_y[1] = _mm_unpackhi_epi8(v_y[1], v_zero); + v_y[2] = _mm_unpacklo_epi8(v_y[2], v_zero); + + __m128i v_rgb[6]; + v_rgb[0] = _mm_unpacklo_epi8(v_ycrcb[0], v_zero); + v_rgb[1] = _mm_unpackhi_epi8(v_ycrcb[0], v_zero); + v_rgb[2] = _mm_unpacklo_epi8(v_ycrcb[1], v_zero); + v_rgb[3] = _mm_unpackhi_epi8(v_ycrcb[1], v_zero); + v_rgb[4] = _mm_unpacklo_epi8(v_ycrcb[2], v_zero); + v_rgb[5] = _mm_unpackhi_epi8(v_ycrcb[2], v_zero); + + v_rgb[0] = _mm_sub_epi16(v_rgb[0], v_delta); + v_rgb[1] = _mm_sub_epi16(v_rgb[1], v_delta); + v_rgb[2] = _mm_sub_epi16(v_rgb[2], v_delta); + v_rgb[3] = _mm_sub_epi16(v_rgb[3], v_delta); + v_rgb[4] = _mm_sub_epi16(v_rgb[4], v_delta); + v_rgb[5] = _mm_sub_epi16(v_rgb[5], v_delta); + + v_rgb[0] = _mm_madd_epi16(v_rgb[0], v_coeffs[0]); + v_rgb[1] = _mm_madd_epi16(v_rgb[1], v_coeffs[1]); + v_rgb[2] = _mm_madd_epi16(v_rgb[2], v_coeffs[2]); + v_rgb[3] = _mm_madd_epi16(v_rgb[3], v_coeffs[0]); + v_rgb[4] = _mm_madd_epi16(v_rgb[4], v_coeffs[1]); + v_rgb[5] = _mm_madd_epi16(v_rgb[5], v_coeffs[2]); + + v_rgb[0] = _mm_add_epi32(v_rgb[0], v_delta2); + v_rgb[1] = _mm_add_epi32(v_rgb[1], v_delta2); + v_rgb[2] = _mm_add_epi32(v_rgb[2], v_delta2); + v_rgb[3] = _mm_add_epi32(v_rgb[3], v_delta2); + v_rgb[4] = _mm_add_epi32(v_rgb[4], v_delta2); + v_rgb[5] = _mm_add_epi32(v_rgb[5], v_delta2); + + v_rgb[0] = _mm_srai_epi32(v_rgb[0], yuv_shift); + v_rgb[1] = _mm_srai_epi32(v_rgb[1], yuv_shift); + v_rgb[2] = _mm_srai_epi32(v_rgb[2], yuv_shift); + v_rgb[3] = _mm_srai_epi32(v_rgb[3], yuv_shift); + v_rgb[4] = _mm_srai_epi32(v_rgb[4], yuv_shift); + v_rgb[5] = _mm_srai_epi32(v_rgb[5], yuv_shift); + + v_rgb[0] = _mm_packs_epi32(v_rgb[0], v_rgb[1]); + v_rgb[2] = _mm_packs_epi32(v_rgb[2], v_rgb[3]); + v_rgb[4] = _mm_packs_epi32(v_rgb[4], v_rgb[5]); + + v_rgb[0] = _mm_add_epi16(v_rgb[0], v_y[0]); + v_rgb[2] = _mm_add_epi16(v_rgb[2], v_y[1]); + v_rgb[4] = _mm_add_epi16(v_rgb[4], v_y[2]); + + v_src[0] = _mm_packus_epi16(v_rgb[0], v_rgb[2]); + v_src[1] = _mm_packus_epi16(v_rgb[4], v_rgb[4]); + } +#endif // CV_SSE4_1 + // 16s x 8 void process(__m128i v_y, __m128i v_cr, __m128i v_cb, __m128i & v_r, __m128i & v_g, __m128i & v_b) const @@ -3040,6 +3106,91 @@ struct YCrCb2RGB_i int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3]; n *= 3; +#if CV_SSE4_1 + if (checkHardwareSupport(CV_CPU_SSE4_1) && useSSE) + { + __m128i v_shuffle[2]; + v_shuffle[0] = _mm_set_epi8(0x8, 0x7, 0x7, 0x6, 0x6, 0x5, 0x5, 0x4, 0x4, 0x3, 0x3, 0x2, 0x2, 0x1, 0x1, 0x0); + v_shuffle[1] = _mm_set_epi8(0xf, 0xc, 0xc, 0xc, 0x9, 0x9, 0x9, 0x6, 0x6, 0x6, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0); + __m128i v_coeffs[3]; + v_coeffs[0] = _mm_set_epi16((short)C0, 0, 0, (short)C3, (short)C2, (short)C1, (short)C0, 0); + v_coeffs[1] = _mm_set_epi16((short)C2, (short)C1, (short)C0, 0, 0, (short)C3, (short)C2, (short)C1); + v_coeffs[2] = _mm_set_epi16(0, (short)C3, (short)C2, (short)C1, (short)C0, 0, 0, (short)C3); + + if (dcn == 3) + { + if (bidx == 0) + { + __m128i v_shuffle_dst = _mm_set_epi8(0xf, 0xc, 0xd, 0xe, 0x9, 0xa, 0xb, 0x6, 0x7, 0x8, 0x3, 0x4, 0x5, 0x0, 0x1, 0x2); + for ( ; i <= n - 24; i += 24, dst += dcn * 8) + { + __m128i v_src[2]; + v_src[0] = _mm_loadu_si128((__m128i const *)(src + i)); + v_src[1] = _mm_loadl_epi64((__m128i const *)(src + i + 16)); + + process(v_src, v_shuffle, v_coeffs); + + __m128i v_dst[2]; + v_dst[0] = _mm_shuffle_epi8(v_src[0], v_shuffle_dst); + v_dst[1] = _mm_shuffle_epi8(_mm_alignr_epi8(v_src[1], v_src[0], 15), v_shuffle_dst); + + _mm_storeu_si128((__m128i *)(dst), _mm_alignr_epi8(v_dst[1], _mm_slli_si128(v_dst[0], 1), 1)); + _mm_storel_epi64((__m128i *)(dst + 16), _mm_srli_si128(v_dst[1], 1)); + } + } + else + { + for ( ; i <= n - 24; i += 24, dst += dcn * 8) + { + __m128i v_src[2]; + v_src[0] = _mm_loadu_si128((__m128i const *)(src + i)); + v_src[1] = _mm_loadl_epi64((__m128i const *)(src + i + 16)); + + process(v_src, v_shuffle, v_coeffs); + + _mm_storeu_si128((__m128i *)(dst), v_src[0]); + _mm_storel_epi64((__m128i *)(dst + 16), v_src[1]); + } + } + } + else + { + if (bidx == 0) + { + __m128i v_shuffle_dst = _mm_set_epi8(0x0, 0xa, 0xb, 0xc, 0x0, 0x7, 0x8, 0x9, 0x0, 0x4, 0x5, 0x6, 0x0, 0x1, 0x2, 0x3); + + for ( ; i <= n - 24; i += 24, dst += dcn * 8) + { + __m128i v_src[2]; + v_src[0] = _mm_loadu_si128((__m128i const *)(src + i)); + v_src[1] = _mm_loadl_epi64((__m128i const *)(src + i + 16)); + + process(v_src, v_shuffle, v_coeffs); + + _mm_storeu_si128((__m128i *)(dst), _mm_shuffle_epi8(_mm_alignr_epi8(v_src[0], v_alpha, 15), v_shuffle_dst)); + _mm_storeu_si128((__m128i *)(dst + 16), _mm_shuffle_epi8(_mm_alignr_epi8(_mm_alignr_epi8(v_src[1], v_src[0], 12), v_alpha, 15), v_shuffle_dst)); + } + } + else + { + __m128i v_shuffle_dst = _mm_set_epi8(0x0, 0xc, 0xb, 0xa, 0x0, 0x9, 0x8, 0x7, 0x0, 0x6, 0x5, 0x4, 0x0, 0x3, 0x2, 0x1); + + for ( ; i <= n - 24; i += 24, dst += dcn * 8) + { + __m128i v_src[2]; + v_src[0] = _mm_loadu_si128((__m128i const *)(src + i)); + v_src[1] = _mm_loadl_epi64((__m128i const *)(src + i + 16)); + + process(v_src, v_shuffle, v_coeffs); + + _mm_storeu_si128((__m128i *)(dst), _mm_shuffle_epi8(_mm_alignr_epi8(v_src[0], v_alpha, 15), v_shuffle_dst)); + _mm_storeu_si128((__m128i *)(dst + 16), _mm_shuffle_epi8(_mm_alignr_epi8(_mm_alignr_epi8(v_src[1], v_src[0], 12), v_alpha, 15), v_shuffle_dst)); + } + } + } + } + else +#endif // CV_SSE4_1 if (haveSIMD && useSSE) { for ( ; i <= n - 96; i += 96, dst += dcn * 32) From 62c1a5a15232ddc9cc97b46d0d3c07a4c5b35d9e Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Mon, 15 Aug 2016 11:28:52 +0300 Subject: [PATCH 065/178] Replaced quiet return from MSER:detectRegion function with exeption throwing to notify user in case small image is processed --- modules/features2d/src/mser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/features2d/src/mser.cpp b/modules/features2d/src/mser.cpp index 72b2314d9c..4f2cab1dc0 100644 --- a/modules/features2d/src/mser.cpp +++ b/modules/features2d/src/mser.cpp @@ -1025,7 +1025,7 @@ void MSER_Impl::detectRegions( InputArray _src, vector >& msers, v bboxes.clear(); if( src.rows < 3 || src.cols < 3 ) - return; + CV_Error(Error::StsBadArg, "Input image is too small. Expected at least 3x3"); Size size = src.size(); From bb6f65c199115ae1026a5e9bd6d19f51ea530b3d Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Mon, 18 Jul 2016 16:32:05 +0300 Subject: [PATCH 066/178] Update documentation ( tutorials ) --- .../core/adding_images/adding_images.markdown | 62 ++------ .../basic_geometric_drawing.markdown | 148 +++--------------- .../corner_subpixeles.markdown | 99 +----------- .../good_features_to_track.markdown | 89 +---------- .../harris_detector/harris_detector.markdown | 73 +-------- .../highgui/trackbar/trackbar.markdown | 96 ++---------- .../raster-gdal/raster_io_gdal.markdown | 8 +- .../erosion_dilatation.markdown | 44 +----- ...sian_median_blur_bilateral_filter.markdown | 122 ++------------- .../canny_detector/canny_detector.markdown | 55 ++----- .../copyMakeBorder/copyMakeBorder.markdown | 54 ++----- .../imgtrans/filter_2d/filter_2d.markdown | 85 +--------- .../hough_circle/hough_circle.markdown | 50 ++---- .../laplace_operator.markdown | 36 +---- .../sobel_derivatives.markdown | 47 +----- .../opening_closing_hats.markdown | 121 ++------------ .../imgproc/pyramids/pyramids.markdown | 54 ++----- .../imgproc/threshold/threshold.markdown | 38 +---- .../cascade_classifier.markdown | 86 +--------- samples/cpp/houghcircles.cpp | 37 +++-- .../HighGUI/AddingImagesTrackbar.cpp | 15 +- .../tutorial_code/ImgProc/Morphology_1.cpp | 8 + .../tutorial_code/ImgProc/Morphology_2.cpp | 20 ++- .../cpp/tutorial_code/ImgProc/Pyramids.cpp | 27 +++- .../cpp/tutorial_code/ImgProc/Smoothing.cpp | 11 +- .../cpp/tutorial_code/ImgProc/Threshold.cpp | 26 +-- .../ImgTrans/CannyDetector_Demo.cpp | 30 +++- .../tutorial_code/ImgTrans/Laplace_Demo.cpp | 30 ++-- .../cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp | 34 ++-- .../ImgTrans/copyMakeBorder_demo.cpp | 26 ++- .../tutorial_code/ImgTrans/filter2D_demo.cpp | 15 +- .../AddingImages}/AddingImages.cpp | 17 +- .../tutorial_code/core/Matrix/Drawing_1.cpp | 35 +++-- .../imgcodecs/GDAL_IO/gdal-image.cpp | 4 + 34 files changed, 369 insertions(+), 1333 deletions(-) rename samples/cpp/tutorial_code/{ImgProc => core/AddingImages}/AddingImages.cpp (81%) diff --git a/doc/tutorials/core/adding_images/adding_images.markdown b/doc/tutorials/core/adding_images/adding_images.markdown index 1565e7ed8b..012a2480fa 100644 --- a/doc/tutorials/core/adding_images/adding_images.markdown +++ b/doc/tutorials/core/adding_images/adding_images.markdown @@ -25,51 +25,13 @@ By varying \f$\alpha\f$ from \f$0 \rightarrow 1\f$ this operator can be used to *cross-dissolve* between two images or videos, as seen in slide shows and film productions (cool, eh?) -Code ----- +Source Code +----------- -As usual, after the not-so-lengthy explanation, let's go to the code: -@code{.cpp} -#include -#include +Download the source code from +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/core/AddingImages/AddingImages.cpp). +@include cpp/tutorial_code/core/AddingImages/AddingImages.cpp -using namespace cv; - -int main( int argc, char** argv ) -{ - double alpha = 0.5; double beta; double input; - - Mat src1, src2, dst; - - /// Ask the user enter alpha - std::cout<<" Simple Linear Blender "<>input; - - /// We use the alpha provided by the user if it is between 0 and 1 - if( input >= 0.0 && input <= 1.0 ) - { alpha = input; } - - /// Read image ( same size, same type ) - src1 = imread("../../images/LinuxLogo.jpg"); - src2 = imread("../../images/WindowsLogo.jpg"); - - if( !src1.data ) { printf("Error loading src1 \n"); return -1; } - if( !src2.data ) { printf("Error loading src2 \n"); return -1; } - - /// Create Windows - namedWindow("Linear Blend", 1); - - beta = ( 1.0 - alpha ); - addWeighted( src1, alpha, src2, beta, 0.0, dst); - - imshow( "Linear Blend", dst ); - - waitKey(0); - return 0; -} -@endcode Explanation ----------- @@ -78,25 +40,21 @@ Explanation \f[g(x) = (1 - \alpha)f_{0}(x) + \alpha f_{1}(x)\f] We need two source images (\f$f_{0}(x)\f$ and \f$f_{1}(x)\f$). So, we load them in the usual way: - @code{.cpp} - src1 = imread("../../images/LinuxLogo.jpg"); - src2 = imread("../../images/WindowsLogo.jpg"); - @endcode + @snippet cpp/tutorial_code/core/AddingImages/AddingImages.cpp load + **warning** Since we are *adding* *src1* and *src2*, they both have to be of the same size (width and height) and type. --# Now we need to generate the `g(x)` image. For this, the function add_weighted:addWeighted comes quite handy: - @code{.cpp} - beta = ( 1.0 - alpha ); - addWeighted( src1, alpha, src2, beta, 0.0, dst); - @endcode +-# Now we need to generate the `g(x)` image. For this, the function @ref cv::addWeighted comes quite handy: + @snippet cpp/tutorial_code/core/AddingImages/AddingImages.cpp blend_images since @ref cv::addWeighted produces: \f[dst = \alpha \cdot src1 + \beta \cdot src2 + \gamma\f] In this case, `gamma` is the argument \f$0.0\f$ in the code above. -# Create windows, show the images and wait for the user to end the program. + @snippet cpp/tutorial_code/core/AddingImages/AddingImages.cpp display Result ------ diff --git a/doc/tutorials/core/basic_geometric_drawing/basic_geometric_drawing.markdown b/doc/tutorials/core/basic_geometric_drawing/basic_geometric_drawing.markdown index 4c68517bbc..c27e3293a4 100644 --- a/doc/tutorials/core/basic_geometric_drawing/basic_geometric_drawing.markdown +++ b/doc/tutorials/core/basic_geometric_drawing/basic_geometric_drawing.markdown @@ -48,69 +48,26 @@ Code - This code is in your OpenCV sample folder. Otherwise you can grab it from [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/core/Matrix/Drawing_1.cpp) + @include samples/cpp/tutorial_code/core/Matrix/Drawing_1.cpp Explanation ----------- --# Since we plan to draw two examples (an atom and a rook), we have to create 02 images and two +-# Since we plan to draw two examples (an atom and a rook), we have to create two images and two windows to display them. - @code{.cpp} - /// Windows names - char atom_window[] = "Drawing 1: Atom"; - char rook_window[] = "Drawing 2: Rook"; + @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp create_images - /// Create black empty images - Mat atom_image = Mat::zeros( w, w, CV_8UC3 ); - Mat rook_image = Mat::zeros( w, w, CV_8UC3 ); - @endcode -# We created functions to draw different geometric shapes. For instance, to draw the atom we used *MyEllipse* and *MyFilledCircle*: - @code{.cpp} - /// 1. Draw a simple atom: + @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp draw_atom - /// 1.a. Creating ellipses - MyEllipse( atom_image, 90 ); - MyEllipse( atom_image, 0 ); - MyEllipse( atom_image, 45 ); - MyEllipse( atom_image, -45 ); - - /// 1.b. Creating circles - MyFilledCircle( atom_image, Point( w/2.0, w/2.0) ); - @endcode -# And to draw the rook we employed *MyLine*, *rectangle* and a *MyPolygon*: - @code{.cpp} - /// 2. Draw a rook + @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp draw_rook - /// 2.a. Create a convex polygon - MyPolygon( rook_image ); - - /// 2.b. Creating rectangles - rectangle( rook_image, - Point( 0, 7*w/8.0 ), - Point( w, w), - Scalar( 0, 255, 255 ), - -1, - 8 ); - - /// 2.c. Create a few lines - MyLine( rook_image, Point( 0, 15*w/16 ), Point( w, 15*w/16 ) ); - MyLine( rook_image, Point( w/4, 7*w/8 ), Point( w/4, w ) ); - MyLine( rook_image, Point( w/2, 7*w/8 ), Point( w/2, w ) ); - MyLine( rook_image, Point( 3*w/4, 7*w/8 ), Point( 3*w/4, w ) ); - @endcode -# Let's check what is inside each of these functions: - *MyLine* - @code{.cpp} - void MyLine( Mat img, Point start, Point end ) - { - int thickness = 2; - int lineType = 8; - line( img, start, end, - Scalar( 0, 0, 0 ), - thickness, - lineType ); - } - @endcode + @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp myline + As we can see, *MyLine* just call the function @ref cv::line , which does the following: - Draw a line from Point **start** to Point **end** @@ -120,95 +77,31 @@ Explanation - The line thickness is set to **thickness** (in this case 2) - The line is a 8-connected one (**lineType** = 8) - *MyEllipse* - @code{.cpp} - void MyEllipse( Mat img, double angle ) - { - int thickness = 2; - int lineType = 8; + @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp myellipse - ellipse( img, - Point( w/2.0, w/2.0 ), - Size( w/4.0, w/16.0 ), - angle, - 0, - 360, - Scalar( 255, 0, 0 ), - thickness, - lineType ); - } - @endcode From the code above, we can observe that the function @ref cv::ellipse draws an ellipse such that: - The ellipse is displayed in the image **img** - - The ellipse center is located in the point **(w/2.0, w/2.0)** and is enclosed in a box - of size **(w/4.0, w/16.0)** + - The ellipse center is located in the point **(w/2, w/2)** and is enclosed in a box + of size **(w/4, w/16)** - The ellipse is rotated **angle** degrees - The ellipse extends an arc between **0** and **360** degrees - - The color of the figure will be **Scalar( 255, 0, 0)** which means blue in RGB value. + - The color of the figure will be **Scalar( 255, 0, 0)** which means blue in BGR value. - The ellipse's **thickness** is 2. - *MyFilledCircle* - @code{.cpp} - void MyFilledCircle( Mat img, Point center ) - { - int thickness = -1; - int lineType = 8; + @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp myfilledcircle - circle( img, - center, - w/32.0, - Scalar( 0, 0, 255 ), - thickness, - lineType ); - } - @endcode Similar to the ellipse function, we can observe that *circle* receives as arguments: - The image where the circle will be displayed (**img**) - The center of the circle denoted as the Point **center** - - The radius of the circle: **w/32.0** + - The radius of the circle: **w/32** - The color of the circle: **Scalar(0, 0, 255)** which means *Red* in BGR - Since **thickness** = -1, the circle will be drawn filled. - *MyPolygon* - @code{.cpp} - void MyPolygon( Mat img ) - { - int lineType = 8; + @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp mypolygon - /* Create some points */ - Point rook_points[1][20]; - rook_points[0][0] = Point( w/4.0, 7*w/8.0 ); - rook_points[0][1] = Point( 3*w/4.0, 7*w/8.0 ); - rook_points[0][2] = Point( 3*w/4.0, 13*w/16.0 ); - rook_points[0][3] = Point( 11*w/16.0, 13*w/16.0 ); - rook_points[0][4] = Point( 19*w/32.0, 3*w/8.0 ); - rook_points[0][5] = Point( 3*w/4.0, 3*w/8.0 ); - rook_points[0][6] = Point( 3*w/4.0, w/8.0 ); - rook_points[0][7] = Point( 26*w/40.0, w/8.0 ); - rook_points[0][8] = Point( 26*w/40.0, w/4.0 ); - rook_points[0][9] = Point( 22*w/40.0, w/4.0 ); - rook_points[0][10] = Point( 22*w/40.0, w/8.0 ); - rook_points[0][11] = Point( 18*w/40.0, w/8.0 ); - rook_points[0][12] = Point( 18*w/40.0, w/4.0 ); - rook_points[0][13] = Point( 14*w/40.0, w/4.0 ); - rook_points[0][14] = Point( 14*w/40.0, w/8.0 ); - rook_points[0][15] = Point( w/4.0, w/8.0 ); - rook_points[0][16] = Point( w/4.0, 3*w/8.0 ); - rook_points[0][17] = Point( 13*w/32.0, 3*w/8.0 ); - rook_points[0][18] = Point( 5*w/16.0, 13*w/16.0 ); - rook_points[0][19] = Point( w/4.0, 13*w/16.0) ; - - const Point* ppt[1] = { rook_points[0] }; - int npt[] = { 20 }; - - fillPoly( img, - ppt, - npt, - 1, - Scalar( 255, 255, 255 ), - lineType ); - } - @endcode To draw a filled polygon we use the function @ref cv::fillPoly . We note that: - The polygon will be drawn on **img** @@ -218,22 +111,17 @@ Explanation - The color of the polygon is defined by **Scalar( 255, 255, 255)**, which is the BGR value for *white* - *rectangle* - @code{.cpp} - rectangle( rook_image, - Point( 0, 7*w/8.0 ), - Point( w, w), - Scalar( 0, 255, 255 ), - -1, 8 ); - @endcode + @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp rectangle + Finally we have the @ref cv::rectangle function (we did not create a special function for this guy). We note that: - The rectangle will be drawn on **rook_image** - - Two opposite vertices of the rectangle are defined by *\* Point( 0, 7*w/8.0 )*\* + - Two opposite vertices of the rectangle are defined by *\* Point( 0, 7*w/8 )*\* andPoint( w, w)*\* - The color of the rectangle is given by **Scalar(0, 255, 255)** which is the BGR value for *yellow* - - Since the thickness value is given by **-1**, the rectangle will be filled. + - Since the thickness value is given by **FILLED (-1)**, the rectangle will be filled. Result ------ diff --git a/doc/tutorials/features2d/trackingmotion/corner_subpixeles/corner_subpixeles.markdown b/doc/tutorials/features2d/trackingmotion/corner_subpixeles/corner_subpixeles.markdown index 92f3459d35..946fd77b29 100644 --- a/doc/tutorials/features2d/trackingmotion/corner_subpixeles/corner_subpixeles.markdown +++ b/doc/tutorials/features2d/trackingmotion/corner_subpixeles/corner_subpixeles.markdown @@ -17,105 +17,8 @@ Code This tutorial code's is shown lines below. You can also download it from [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/TrackingMotion/cornerSubPix_Demo.cpp) -@code{.cpp} -#include "opencv2/highgui.hpp" -#include "opencv2/imgproc.hpp" -#include -#include -#include +@include samples/cpp/tutorial_code/TrackingMotion/cornerSubPix_Demo.cpp -using namespace cv; -using namespace std; - -/// Global variables -Mat src, src_gray; - -int maxCorners = 10; -int maxTrackbar = 25; - -RNG rng(12345); -char* source_window = "Image"; - -/// Function header -void goodFeaturesToTrack_Demo( int, void* ); - -/* @function main */ -int main( int argc, char** argv ) -{ - /// Load source image and convert it to gray - src = imread( argv[1], 1 ); - cvtColor( src, src_gray, COLOR_BGR2GRAY ); - - /// Create Window - namedWindow( source_window, WINDOW_AUTOSIZE ); - - /// Create Trackbar to set the number of corners - createTrackbar( "Max corners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_Demo); - - imshow( source_window, src ); - - goodFeaturesToTrack_Demo( 0, 0 ); - - waitKey(0); - return(0); -} - -/* - * @function goodFeaturesToTrack_Demo.cpp - * @brief Apply Shi-Tomasi corner detector - */ -void goodFeaturesToTrack_Demo( int, void* ) -{ - if( maxCorners < 1 ) { maxCorners = 1; } - - /// Parameters for Shi-Tomasi algorithm - vector corners; - double qualityLevel = 0.01; - double minDistance = 10; - int blockSize = 3; - bool useHarrisDetector = false; - double k = 0.04; - - /// Copy the source image - Mat copy; - copy = src.clone(); - - /// Apply corner detection - goodFeaturesToTrack( src_gray, - corners, - maxCorners, - qualityLevel, - minDistance, - Mat(), - blockSize, - useHarrisDetector, - k ); - - - /// Draw corners detected - cout<<"** Number of corners detected: "< -#include -#include +@include samples/cpp/tutorial_code/TrackingMotion/goodFeaturesToTrack_Demo.cpp -using namespace cv; -using namespace std; - -/// Global variables -Mat src, src_gray; - -int maxCorners = 23; -int maxTrackbar = 100; - -RNG rng(12345); -char* source_window = "Image"; - -/// Function header -void goodFeaturesToTrack_Demo( int, void* ); - -/* - * @function main - */ -int main( int argc, char** argv ) -{ - /// Load source image and convert it to gray - src = imread( argv[1], 1 ); - cvtColor( src, src_gray, COLOR_BGR2GRAY ); - - /// Create Window - namedWindow( source_window, WINDOW_AUTOSIZE ); - - /// Create Trackbar to set the number of corners - createTrackbar( "Max corners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_Demo ); - - imshow( source_window, src ); - - goodFeaturesToTrack_Demo( 0, 0 ); - - waitKey(0); - return(0); -} - -/* - * @function goodFeaturesToTrack_Demo.cpp - * @brief Apply Shi-Tomasi corner detector - */ -void goodFeaturesToTrack_Demo( int, void* ) -{ - if( maxCorners < 1 ) { maxCorners = 1; } - - /// Parameters for Shi-Tomasi algorithm - vector corners; - double qualityLevel = 0.01; - double minDistance = 10; - int blockSize = 3; - bool useHarrisDetector = false; - double k = 0.04; - - /// Copy the source image - Mat copy; - copy = src.clone(); - - /// Apply corner detection - goodFeaturesToTrack( src_gray, - corners, - maxCorners, - qualityLevel, - minDistance, - Mat(), - blockSize, - useHarrisDetector, - k ); - - - /// Draw corners detected - cout<<"** Number of corners detected: "< -#include -#include +@include samples/cpp/tutorial_code/TrackingMotion/cornerHarris_Demo.cpp -using namespace cv; -using namespace std; - -/// Global variables -Mat src, src_gray; -int thresh = 200; -int max_thresh = 255; - -char* source_window = "Source image"; -char* corners_window = "Corners detected"; - -/// Function header -void cornerHarris_demo( int, void* ); - -/* @function main */ -int main( int argc, char** argv ) -{ - /// Load source image and convert it to gray - src = imread( argv[1], 1 ); - cvtColor( src, src_gray, COLOR_BGR2GRAY ); - - /// Create a window and a trackbar - namedWindow( source_window, WINDOW_AUTOSIZE ); - createTrackbar( "Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo ); - imshow( source_window, src ); - - cornerHarris_demo( 0, 0 ); - - waitKey(0); - return(0); -} - -/* @function cornerHarris_demo */ -void cornerHarris_demo( int, void* ) -{ - - Mat dst, dst_norm, dst_norm_scaled; - dst = Mat::zeros( src.size(), CV_32FC1 ); - - /// Detector parameters - int blockSize = 2; - int apertureSize = 3; - double k = 0.04; - - /// Detecting corners - cornerHarris( src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT ); - - /// Normalizing - normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() ); - convertScaleAbs( dst_norm, dst_norm_scaled ); - - /// Drawing a circle around corners - for( int j = 0; j < dst_norm.rows ; j++ ) - { for( int i = 0; i < dst_norm.cols; i++ ) - { - if( (int) dst_norm.at(j,i) > thresh ) - { - circle( dst_norm_scaled, Point( i, j ), 5, Scalar(0), 2, 8, 0 ); - } - } - } - /// Showing the result - namedWindow( corners_window, WINDOW_AUTOSIZE ); - imshow( corners_window, dst_norm_scaled ); -} -@endcode Explanation ----------- diff --git a/doc/tutorials/highgui/trackbar/trackbar.markdown b/doc/tutorials/highgui/trackbar/trackbar.markdown index 50c13fa4af..b39572c1a8 100644 --- a/doc/tutorials/highgui/trackbar/trackbar.markdown +++ b/doc/tutorials/highgui/trackbar/trackbar.markdown @@ -4,7 +4,7 @@ Adding a Trackbar to our applications! {#tutorial_trackbar} - In the previous tutorials (about *linear blending* and the *brightness and contrast adjustments*) you might have noted that we needed to give some **input** to our programs, such as \f$\alpha\f$ and \f$beta\f$. We accomplished that by entering this data using the Terminal -- Well, it is time to use some fancy GUI tools. OpenCV provides some GUI utilities (*highgui.h*) +- Well, it is time to use some fancy GUI tools. OpenCV provides some GUI utilities (*highgui.hpp*) for you. An example of this is a **Trackbar** ![](images/Adding_Trackbars_Tutorial_Trackbar.png) @@ -24,104 +24,36 @@ Code Let's modify the program made in the tutorial @ref tutorial_adding_images. We will let the user enter the \f$\alpha\f$ value by using the Trackbar. -@code{.cpp} -#include -using namespace cv; - -/// Global Variables -const int alpha_slider_max = 100; -int alpha_slider; -double alpha; -double beta; - -/// Matrices to store images -Mat src1; -Mat src2; -Mat dst; - -/* - * @function on_trackbar - * @brief Callback for trackbar - */ -void on_trackbar( int, void* ) -{ - alpha = (double) alpha_slider/alpha_slider_max ; - beta = ( 1.0 - alpha ); - - addWeighted( src1, alpha, src2, beta, 0.0, dst); - - imshow( "Linear Blend", dst ); -} - -int main( int argc, char** argv ) -{ - /// Read image ( same size, same type ) - src1 = imread("../../images/LinuxLogo.jpg"); - src2 = imread("../../images/WindowsLogo.jpg"); - - if( !src1.data ) { printf("Error loading src1 \n"); return -1; } - if( !src2.data ) { printf("Error loading src2 \n"); return -1; } - - /// Initialize values - alpha_slider = 0; - - /// Create Windows - namedWindow("Linear Blend", 1); - - /// Create Trackbars - char TrackbarName[50]; - sprintf( TrackbarName, "Alpha x %d", alpha_slider_max ); - - createTrackbar( TrackbarName, "Linear Blend", &alpha_slider, alpha_slider_max, on_trackbar ); - - /// Show some stuff - on_trackbar( alpha_slider, 0 ); - - /// Wait until user press some key - waitKey(0); - return 0; -} -@endcode +This tutorial code's is shown lines below. You can also download it from +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp) +@include cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp Explanation ----------- We only analyze the code that is related to Trackbar: --# First, we load 02 images, which are going to be blended. - @code{.cpp} - src1 = imread("../../images/LinuxLogo.jpg"); - src2 = imread("../../images/WindowsLogo.jpg"); - @endcode +-# First, we load two images, which are going to be blended. + @snippet cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp load + -# To create a trackbar, first we have to create the window in which it is going to be located. So: - @code{.cpp} - namedWindow("Linear Blend", 1); - @endcode + @snippet cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp window + -# Now we can create the Trackbar: - @code{.cpp} - createTrackbar( TrackbarName, "Linear Blend", &alpha_slider, alpha_slider_max, on_trackbar ); - @endcode + @snippet cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp create_trackbar + Note the following: - Our Trackbar has a label **TrackbarName** - - The Trackbar is located in the window named **"Linear Blend"** + - The Trackbar is located in the window named **Linear Blend** - The Trackbar values will be in the range from \f$0\f$ to **alpha_slider_max** (the minimum limit is always **zero**). - The numerical value of Trackbar is stored in **alpha_slider** - Whenever the user moves the Trackbar, the callback function **on_trackbar** is called -# Finally, we have to define the callback function **on_trackbar** - @code{.cpp} - void on_trackbar( int, void* ) - { - alpha = (double) alpha_slider/alpha_slider_max ; - beta = ( 1.0 - alpha ); + @snippet cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp on_trackbar - addWeighted( src1, alpha, src2, beta, 0.0, dst); - - imshow( "Linear Blend", dst ); - } - @endcode Note that: - We use the value of **alpha_slider** (integer) to get a double value for **alpha**. - **alpha_slider** is updated each time the trackbar is displaced by the user. @@ -135,7 +67,7 @@ Result ![](images/Adding_Trackbars_Tutorial_Result_0.jpg) -- As a manner of practice, you can also add 02 trackbars for the program made in +- As a manner of practice, you can also add two trackbars for the program made in @ref tutorial_basic_linear_transform. One trackbar to set \f$\alpha\f$ and another for \f$\beta\f$. The output might look like: diff --git a/doc/tutorials/imgcodecs/raster-gdal/raster_io_gdal.markdown b/doc/tutorials/imgcodecs/raster-gdal/raster_io_gdal.markdown index a511d80887..2193d26870 100644 --- a/doc/tutorials/imgcodecs/raster-gdal/raster_io_gdal.markdown +++ b/doc/tutorials/imgcodecs/raster-gdal/raster_io_gdal.markdown @@ -35,17 +35,13 @@ How to Read Raster Data using GDAL This demonstration uses the default OpenCV imread function. The primary difference is that in order to force GDAL to load the image, you must use the appropriate flag. -@code{.cpp} -cv::Mat image = cv::imread( argv[1], cv::IMREAD_LOAD_GDAL ); -@endcode +@snippet cpp/tutorial_code/imgcodecs/GDAL_IO/gdal-image.cpp load1 When loading digital elevation models, the actual numeric value of each pixel is essential and cannot be scaled or truncated. For example, with image data a pixel represented as a double with a value of 1 has an equal appearance to a pixel which is represented as an unsigned character with a value of 255. With terrain data, the pixel value represents the elevation in meters. In order to ensure that OpenCV preserves the native value, use the GDAL flag in imread with the ANYDEPTH flag. -@code{.cpp} -cv::Mat dem = cv::imread( argv[2], cv::IMREAD_LOAD_GDAL | cv::IMREAD_ANYDEPTH ); -@endcode +@snippet cpp/tutorial_code/imgcodecs/GDAL_IO/gdal-image.cpp load2 If you know beforehand the type of DEM model you are loading, then it may be a safe bet to test the Mat::type() or Mat::depth() using an assert or other mechanism. NASA or DOD specification documents can provide the input types for various elevation models. The major types, SRTM and DTED, are both diff --git a/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.markdown b/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.markdown index e3786e607b..444e0c4f87 100644 --- a/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.markdown +++ b/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.markdown @@ -71,7 +71,7 @@ Explanation - Load an image (can be BGR or grayscale) - Create two windows (one for dilation output, the other for erosion) - - Create a set of 02 Trackbars for each operation: + - Create a set of two Trackbars for each operation: - The first trackbar "Element" returns either **erosion_elem** or **dilation_elem** - The second trackbar "Kernel size" return **erosion_size** or **dilation_size** for the corresponding operation. @@ -81,23 +81,8 @@ Explanation Let's analyze these two functions: -# **erosion:** - @code{.cpp} - /* @function Erosion */ - void Erosion( int, void* ) - { - int erosion_type; - if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; } - else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; } - else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; } + @snippet cpp/tutorial_code/ImgProc/Morphology_1.cpp erosion - Mat element = getStructuringElement( erosion_type, - Size( 2*erosion_size + 1, 2*erosion_size+1 ), - Point( erosion_size, erosion_size ) ); - /// Apply the erosion operation - erode( src, erosion_dst, element ); - imshow( "Erosion Demo", erosion_dst ); - } - @endcode - The function that performs the *erosion* operation is @ref cv::erode . As we can see, it receives three arguments: - *src*: The source image @@ -105,11 +90,8 @@ Explanation - *element*: This is the kernel we will use to perform the operation. If we do not specify, the default is a simple `3x3` matrix. Otherwise, we can specify its shape. For this, we need to use the function cv::getStructuringElement : - @code{.cpp} - Mat element = getStructuringElement( erosion_type, - Size( 2*erosion_size + 1, 2*erosion_size+1 ), - Point( erosion_size, erosion_size ) ); - @endcode + @snippet cpp/tutorial_code/ImgProc/Morphology_1.cpp kernel + We can choose any of three shapes for our kernel: - Rectangular box: MORPH_RECT @@ -129,23 +111,7 @@ Reference for more details. The code is below. As you can see, it is completely similar to the snippet of code for **erosion**. Here we also have the option of defining our kernel, its anchor point and the size of the operator to be used. - @code{.cpp} - /* @function Dilation */ - void Dilation( int, void* ) - { - int dilation_type; - if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; } - else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; } - else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; } - - Mat element = getStructuringElement( dilation_type, - Size( 2*dilation_size + 1, 2*dilation_size+1 ), - Point( dilation_size, dilation_size ) ); - /// Apply the dilation operation - dilate( src, dilation_dst, element ); - imshow( "Dilation Demo", dilation_dst ); - } - @endcode + @snippet cpp/tutorial_code/ImgProc/Morphology_1.cpp dilation Results ------- diff --git a/doc/tutorials/imgproc/gausian_median_blur_bilateral_filter/gausian_median_blur_bilateral_filter.markdown b/doc/tutorials/imgproc/gausian_median_blur_bilateral_filter/gausian_median_blur_bilateral_filter.markdown index 2d17c3aade..753b368c0d 100644 --- a/doc/tutorials/imgproc/gausian_median_blur_bilateral_filter/gausian_median_blur_bilateral_filter.markdown +++ b/doc/tutorials/imgproc/gausian_median_blur_bilateral_filter/gausian_median_blur_bilateral_filter.markdown @@ -16,8 +16,7 @@ Theory ------ @note The explanation below belongs to the book [Computer Vision: Algorithms and -Applications](http://szeliski.org/Book/) by Richard Szeliski and to *LearningOpenCV* .. container:: -enumeratevisibleitemswithsquare +Applications](http://szeliski.org/Book/) by Richard Szeliski and to *LearningOpenCV* - *Smoothing*, also called *blurring*, is a simple and frequently used image processing operation. @@ -96,96 +95,7 @@ Code - **Downloadable code**: Click [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp) - **Code at glance:** -@code{.cpp} -#include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" - -using namespace std; -using namespace cv; - -/// Global Variables -int DELAY_CAPTION = 1500; -int DELAY_BLUR = 100; -int MAX_KERNEL_LENGTH = 31; - -Mat src; Mat dst; -char window_name[] = "Filter Demo 1"; - -/// Function headers -int display_caption( char* caption ); -int display_dst( int delay ); - -/* - * function main - */ - int main( int argc, char** argv ) - { - namedWindow( window_name, WINDOW_AUTOSIZE ); - - /// Load the source image - src = imread( "../images/lena.jpg", 1 ); - - if( display_caption( "Original Image" ) != 0 ) { return 0; } - - dst = src.clone(); - if( display_dst( DELAY_CAPTION ) != 0 ) { return 0; } - - /// Applying Homogeneous blur - if( display_caption( "Homogeneous Blur" ) != 0 ) { return 0; } - - for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) - { blur( src, dst, Size( i, i ), Point(-1,-1) ); - if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } - - /// Applying Gaussian blur - if( display_caption( "Gaussian Blur" ) != 0 ) { return 0; } - - for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) - { GaussianBlur( src, dst, Size( i, i ), 0, 0 ); - if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } - - /// Applying Median blur - if( display_caption( "Median Blur" ) != 0 ) { return 0; } - - for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) - { medianBlur ( src, dst, i ); - if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } - - /// Applying Bilateral Filter - if( display_caption( "Bilateral Blur" ) != 0 ) { return 0; } - - for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) - { bilateralFilter ( src, dst, i, i*2, i/2 ); - if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } - - /// Wait until user press a key - display_caption( "End: Press a key!" ); - - waitKey(0); - return 0; - } - - int display_caption( char* caption ) - { - dst = Mat::zeros( src.size(), src.type() ); - putText( dst, caption, - Point( src.cols/4, src.rows/2), - FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) ); - - imshow( window_name, dst ); - int c = waitKey( DELAY_CAPTION ); - if( c >= 0 ) { return -1; } - return 0; - } - - int display_dst( int delay ) - { - imshow( window_name, dst ); - int c = waitKey ( delay ); - if( c >= 0 ) { return -1; } - return 0; - } -@endcode + @include samples/cpp/tutorial_code/ImgProc/Smoothing.cpp Explanation ----------- @@ -195,11 +105,8 @@ Explanation -# **Normalized Block Filter:** OpenCV offers the function @ref cv::blur to perform smoothing with this filter. - @code{.cpp} - for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) - { blur( src, dst, Size( i, i ), Point(-1,-1) ); - if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } - @endcode + @snippet cpp/tutorial_code/ImgProc/Smoothing.cpp blur + We specify 4 arguments (more details, check the Reference): - *src*: Source image @@ -213,11 +120,8 @@ Explanation -# **Gaussian Filter:** It is performed by the function @ref cv::GaussianBlur : - @code{.cpp} - for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) - { GaussianBlur( src, dst, Size( i, i ), 0, 0 ); - if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } - @endcode + @snippet cpp/tutorial_code/ImgProc/Smoothing.cpp gaussianblur + Here we use 4 arguments (more details, check the OpenCV reference): - *src*: Source image @@ -233,11 +137,8 @@ Explanation -# **Median Filter:** This filter is provided by the @ref cv::medianBlur function: - @code{.cpp} - for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) - { medianBlur ( src, dst, i ); - if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } - @endcode + @snippet cpp/tutorial_code/ImgProc/Smoothing.cpp medianblur + We use three arguments: - *src*: Source image @@ -247,11 +148,8 @@ Explanation -# **Bilateral Filter** Provided by OpenCV function @ref cv::bilateralFilter - @code{.cpp} - for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) - { bilateralFilter ( src, dst, i, i*2, i/2 ); - if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } - @endcode + @snippet cpp/tutorial_code/ImgProc/Smoothing.cpp bilateralfilter + We use 5 arguments: - *src*: Source image diff --git a/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.markdown b/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.markdown index c7bd63ed4f..e86b16daf6 100644 --- a/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.markdown +++ b/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.markdown @@ -81,17 +81,8 @@ Explanation ----------- -# Create some needed variables: - @code{.cpp} - Mat src, src_gray; - Mat dst, detected_edges; + @snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp variables - int edgeThresh = 1; - int lowThreshold; - int const max_lowThreshold = 100; - int ratio = 3; - int kernel_size = 3; - char* window_name = "Edge Map"; - @endcode Note the following: -# We establish a ratio of lower:upper threshold of 3:1 (with the variable *ratio*) @@ -100,29 +91,16 @@ Explanation -# We set a maximum value for the lower Threshold of \f$100\f$. -# Loads the source image: - @code{.cpp} - /// Load an image - src = imread( argv[1] ); + @snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp load - if( !src.data ) - { return -1; } - @endcode -# Create a matrix of the same type and size of *src* (to be *dst*) - @code{.cpp} - dst.create( src.size(), src.type() ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp create_mat -# Convert the image to grayscale (using the function @ref cv::cvtColor : - @code{.cpp} - cvtColor( src, src_gray, COLOR_BGR2GRAY ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp convert_to_gray -# Create a window to display the results - @code{.cpp} - namedWindow( window_name, WINDOW_AUTOSIZE ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp create_window -# Create a Trackbar for the user to enter the lower threshold for our Canny detector: - @code{.cpp} - createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold, CannyThreshold ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp create_trackbar Observe the following: -# The variable to be controlled by the Trackbar is *lowThreshold* with a limit of @@ -132,13 +110,9 @@ Explanation -# Let's check the *CannyThreshold* function, step by step: -# First, we blur the image with a filter of kernel size 3: - @code{.cpp} - blur( src_gray, detected_edges, Size(3,3) ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp reduce_noise -# Second, we apply the OpenCV function @ref cv::Canny : - @code{.cpp} - Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp canny where the arguments are: - *detected_edges*: Source image, grayscale @@ -150,23 +124,16 @@ Explanation internally) -# We fill a *dst* image with zeros (meaning the image is completely black). - @code{.cpp} - dst = Scalar::all(0); - @endcode + @snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp fill -# Finally, we will use the function @ref cv::Mat::copyTo to map only the areas of the image that are identified as edges (on a black background). - @code{.cpp} - src.copyTo( dst, detected_edges); - @endcode @ref cv::Mat::copyTo copy the *src* image onto *dst*. However, it will only copy the pixels in the locations where they have non-zero values. Since the output of the Canny detector is the edge contours on a black background, the resulting *dst* will be black in all the area but the detected edges. - + @snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp copyto -# We display our result: - @code{.cpp} - imshow( window_name, dst ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp display Result ------ diff --git a/doc/tutorials/imgproc/imgtrans/copyMakeBorder/copyMakeBorder.markdown b/doc/tutorials/imgproc/imgtrans/copyMakeBorder/copyMakeBorder.markdown index dd4d785515..6b6efdf125 100644 --- a/doc/tutorials/imgproc/imgtrans/copyMakeBorder/copyMakeBorder.markdown +++ b/doc/tutorials/imgproc/imgtrans/copyMakeBorder/copyMakeBorder.markdown @@ -53,61 +53,29 @@ Explanation ----------- -# First we declare the variables we are going to use: - @code{.cpp} - Mat src, dst; - int top, bottom, left, right; - int borderType; - Scalar value; - char* window_name = "copyMakeBorder Demo"; - RNG rng(12345); - @endcode + @snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp variables + Especial attention deserves the variable *rng* which is a random number generator. We use it to generate the random border color, as we will see soon. -# As usual we load our source image *src*: - @code{.cpp} - src = imread( argv[1] ); + @snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp load - if( !src.data ) - { return -1; - printf(" No data entered, please enter the path to an image file \n"); - } - @endcode -# After giving a short intro of how to use the program, we create a window: - @code{.cpp} - namedWindow( window_name, WINDOW_AUTOSIZE ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp create_window -# Now we initialize the argument that defines the size of the borders (*top*, *bottom*, *left* and *right*). We give them a value of 5% the size of *src*. - @code{.cpp} - top = (int) (0.05*src.rows); bottom = (int) (0.05*src.rows); - left = (int) (0.05*src.cols); right = (int) (0.05*src.cols); - @endcode --# The program begins a *while* loop. If the user presses 'c' or 'r', the *borderType* variable + @snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp init_arguments +-# The program runs in a **for** loop. If the user presses 'c' or 'r', the *borderType* variable takes the value of *BORDER_CONSTANT* or *BORDER_REPLICATE* respectively: - @code{.cpp} - while( true ) - { - c = waitKey(500); - - if( (char)c == 27 ) - { break; } - else if( (char)c == 'c' ) - { borderType = BORDER_CONSTANT; } - else if( (char)c == 'r' ) - { borderType = BORDER_REPLICATE; } - @endcode + @snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp check_keypress -# In each iteration (after 0.5 seconds), the variable *value* is updated... - @code{.cpp} - value = Scalar( rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255) ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp update_value with a random value generated by the **RNG** variable *rng*. This value is a number picked randomly in the range \f$[0,255]\f$ -# Finally, we call the function @ref cv::copyMakeBorder to apply the respective padding: - @code{.cpp} - copyMakeBorder( src, dst, top, bottom, left, right, borderType, value ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp copymakeborder The arguments are: -# *src*: Source image @@ -120,9 +88,7 @@ Explanation pixels. -# We display our output image in the image created previously - @code{.cpp} - imshow( window_name, dst ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp display Results ------- diff --git a/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.markdown b/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.markdown index ef25b979f3..a09146419d 100644 --- a/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.markdown +++ b/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.markdown @@ -63,100 +63,25 @@ Code -# The tutorial code's is shown lines below. You can also download it from [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp) -@code{.cpp} -#include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" -#include -#include + @include cpp/tutorial_code/ImgTrans/filter2D_demo.cpp -using namespace cv; - -/* @function main */ -int main ( int argc, char** argv ) -{ - /// Declare variables - Mat src, dst; - - Mat kernel; - Point anchor; - double delta; - int ddepth; - int kernel_size; - char* window_name = "filter2D Demo"; - - int c; - - /// Load an image - src = imread( argv[1] ); - - if( !src.data ) - { return -1; } - - /// Create window - namedWindow( window_name, WINDOW_AUTOSIZE ); - - /// Initialize arguments for the filter - anchor = Point( -1, -1 ); - delta = 0; - ddepth = -1; - - /// Loop - Will filter the image with different kernel sizes each 0.5 seconds - int ind = 0; - while( true ) - { - c = waitKey(500); - /// Press 'ESC' to exit the program - if( (char)c == 27 ) - { break; } - - /// Update kernel size for a normalized box filter - kernel_size = 3 + 2*( ind%5 ); - kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size); - - /// Apply filter - filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT ); - imshow( window_name, dst ); - ind++; - } - - return 0; -} -@endcode Explanation ----------- -# Load an image - @code{.cpp} - src = imread( argv[1] ); - - if( !src.data ) - { return -1; } - @endcode --# Create a window to display the result - @code{.cpp} - namedWindow( window_name, WINDOW_AUTOSIZE ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp load -# Initialize the arguments for the linear filter - @code{.cpp} - anchor = Point( -1, -1 ); - delta = 0; - ddepth = -1; - @endcode + @snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp init_arguments -# Perform an infinite loop updating the kernel size and applying our linear filter to the input image. Let's analyze that more in detail: -# First we define the kernel our filter is going to use. Here it is: - @code{.cpp} - kernel_size = 3 + 2*( ind%5 ); - kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size); - @endcode + @snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp update_kernel The first line is to update the *kernel_size* to odd values in the range: \f$[3,11]\f$. The second line actually builds the kernel by setting its value to a matrix filled with \f$1's\f$ and normalizing it by dividing it between the number of elements. -# After setting the kernel, we can generate the filter by using the function @ref cv::filter2D : - @code{.cpp} - filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp apply_filter The arguments denote: -# *src*: Source image diff --git a/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.markdown b/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.markdown index 61f83aabce..9f3951927c 100644 --- a/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.markdown +++ b/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.markdown @@ -48,63 +48,33 @@ Explanation ----------- -# Load an image - @code{.cpp} - src = imread( argv[1], 1 ); - - if( !src.data ) - { return -1; } - @endcode + @snippet samples/cpp/houghcircles.cpp load -# Convert it to grayscale: - @code{.cpp} - cvtColor( src, src_gray, COLOR_BGR2GRAY ); - @endcode --# Apply a Gaussian blur to reduce noise and avoid false circle detection: - @code{.cpp} - GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 ); - @endcode + @snippet samples/cpp/houghcircles.cpp convert_to_gray +-# Apply a Median blur to reduce noise and avoid false circle detection: + @snippet samples/cpp/houghcircles.cpp reduce_noise -# Proceed to apply Hough Circle Transform: - @code{.cpp} - vector circles; - - HoughCircles( src_gray, circles, HOUGH_GRADIENT, 1, src_gray.rows/8, 200, 100, 0, 0 ); - @endcode + @snippet samples/cpp/houghcircles.cpp houghcircles with the arguments: - - *src_gray*: Input image (grayscale). + - *gray*: Input image (grayscale). - *circles*: A vector that stores sets of 3 values: \f$x_{c}, y_{c}, r\f$ for each detected circle. - *HOUGH_GRADIENT*: Define the detection method. Currently this is the only one available in OpenCV. - *dp = 1*: The inverse ratio of resolution. - - *min_dist = src_gray.rows/8*: Minimum distance between detected centers. + - *min_dist = gray.rows/16*: Minimum distance between detected centers. - *param_1 = 200*: Upper threshold for the internal Canny edge detector. - *param_2* = 100\*: Threshold for center detection. - *min_radius = 0*: Minimum radio to be detected. If unknown, put zero as default. - *max_radius = 0*: Maximum radius to be detected. If unknown, put zero as default. -# Draw the detected circles: - @code{.cpp} - for( size_t i = 0; i < circles.size(); i++ ) - { - Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); - int radius = cvRound(circles[i][2]); - // circle center - circle( src, center, 3, Scalar(0,255,0), -1, 8, 0 ); - // circle outline - circle( src, center, radius, Scalar(0,0,255), 3, 8, 0 ); - } - @endcode + @snippet samples/cpp/houghcircles.cpp draw You can see that we will draw the circle(s) on red and the center(s) with a small green dot --# Display the detected circle(s): - @code{.cpp} - namedWindow( "Hough Circle Transform Demo", WINDOW_AUTOSIZE ); - imshow( "Hough Circle Transform Demo", src ); - @endcode --# Wait for the user to exit the program - @code{.cpp} - waitKey(0); - @endcode +-# Display the detected circle(s) and wait for the user to exit the program: + @snippet samples/cpp/houghcircles.cpp display Result ------ diff --git a/doc/tutorials/imgproc/imgtrans/laplace_operator/laplace_operator.markdown b/doc/tutorials/imgproc/imgtrans/laplace_operator/laplace_operator.markdown index 8976803c51..f1781706cb 100644 --- a/doc/tutorials/imgproc/imgtrans/laplace_operator/laplace_operator.markdown +++ b/doc/tutorials/imgproc/imgtrans/laplace_operator/laplace_operator.markdown @@ -58,33 +58,15 @@ Explanation ----------- -# Create some needed variables: - @code{.cpp} - Mat src, src_gray, dst; - int kernel_size = 3; - int scale = 1; - int delta = 0; - int ddepth = CV_16S; - char* window_name = "Laplace Demo"; - @endcode + @snippet cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp variables -# Loads the source image: - @code{.cpp} - src = imread( argv[1] ); - - if( !src.data ) - { return -1; } - @endcode + @snippet cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp load -# Apply a Gaussian blur to reduce noise: - @code{.cpp} - GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp reduce_noise -# Convert the image to grayscale using @ref cv::cvtColor - @code{.cpp} - cvtColor( src, src_gray, COLOR_RGB2GRAY ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp convert_to_gray -# Apply the Laplacian operator to the grayscale image: - @code{.cpp} - Laplacian( src_gray, dst, ddepth, kernel_size, scale, delta, BORDER_DEFAULT ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp laplacian where the arguments are: - *src_gray*: The input image. @@ -96,13 +78,9 @@ Explanation - *scale*, *delta* and *BORDER_DEFAULT*: We leave them as default values. -# Convert the output from the Laplacian operator to a *CV_8U* image: - @code{.cpp} - convertScaleAbs( dst, abs_dst ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp convert -# Display the result in a window: - @code{.cpp} - imshow( window_name, abs_dst ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp display Results ------- diff --git a/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.markdown b/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.markdown index 2d92fa0226..3112b08cd0 100644 --- a/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.markdown +++ b/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.markdown @@ -115,40 +115,16 @@ Explanation ----------- -# First we declare the variables we are going to use: - @code{.cpp} - Mat src, src_gray; - Mat grad; - char* window_name = "Sobel Demo - Simple Edge Detector"; - int scale = 1; - int delta = 0; - int ddepth = CV_16S; - @endcode + @snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp variables -# As usual we load our source image *src*: - @code{.cpp} - src = imread( argv[1] ); - - if( !src.data ) - { return -1; } - @endcode + @snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp load -# First, we apply a @ref cv::GaussianBlur to our image to reduce the noise ( kernel size = 3 ) - @code{.cpp} - GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp reduce_noise -# Now we convert our filtered image to grayscale: - @code{.cpp} - cvtColor( src, src_gray, COLOR_RGB2GRAY ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp convert_to_gray -# Second, we calculate the "*derivatives*" in *x* and *y* directions. For this, we use the function @ref cv::Sobel as shown below: - @code{.cpp} - Mat grad_x, grad_y; - Mat abs_grad_x, abs_grad_y; - - /// Gradient X - Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT ); - /// Gradient Y - Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp sobel The function takes the following arguments: - *src_gray*: In our example, the input image. Here it is *CV_8U* @@ -162,19 +138,12 @@ Explanation \f$y_{order} = 0\f$. We do analogously for the *y* direction. -# We convert our partial results back to *CV_8U*: - @code{.cpp} - convertScaleAbs( grad_x, abs_grad_x ); - convertScaleAbs( grad_y, abs_grad_y ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp convert -# Finally, we try to approximate the *gradient* by adding both directional gradients (note that this is not an exact calculation at all! but it is good for our purposes). - @code{.cpp} - addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp blend -# Finally, we show our result: - @code{.cpp} - imshow( window_name, grad ); - @endcode + @snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp display Results ------- diff --git a/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.markdown b/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.markdown index 09331109d8..be32508afa 100644 --- a/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.markdown +++ b/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.markdown @@ -81,76 +81,7 @@ Code This tutorial code's is shown lines below. You can also download it from [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Morphology_2.cpp) -@code{.cpp} -#include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" -#include -#include - -using namespace cv; - -/// Global variables -Mat src, dst; - -int morph_elem = 0; -int morph_size = 0; -int morph_operator = 0; -int const max_operator = 4; -int const max_elem = 2; -int const max_kernel_size = 21; - -char* window_name = "Morphology Transformations Demo"; - -/* Function Headers */ -void Morphology_Operations( int, void* ); - -/* @function main */ -int main( int argc, char** argv ) -{ - /// Load an image - src = imread( argv[1] ); - - if( !src.data ) - { return -1; } - - /// Create window - namedWindow( window_name, WINDOW_AUTOSIZE ); - - /// Create Trackbar to select Morphology operation - createTrackbar("Operator:\n 0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat", window_name, &morph_operator, max_operator, Morphology_Operations ); - - /// Create Trackbar to select kernel type - createTrackbar( "Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name, - &morph_elem, max_elem, - Morphology_Operations ); - - /// Create Trackbar to choose kernel size - createTrackbar( "Kernel size:\n 2n +1", window_name, - &morph_size, max_kernel_size, - Morphology_Operations ); - - /// Default start - Morphology_Operations( 0, 0 ); - - waitKey(0); - return 0; - } - - /* - * @function Morphology_Operations - */ -void Morphology_Operations( int, void* ) -{ - // Since MORPH_X : 2,3,4,5 and 6 - int operation = morph_operator + 2; - - Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) ); - - /// Apply the specified morphology operation - morphologyEx( src, dst, operation, element ); - imshow( window_name, dst ); - } -@endcode +@include cpp/tutorial_code/ImgProc/Morphology_2.cpp Explanation ----------- @@ -158,47 +89,23 @@ Explanation -# Let's check the general structure of the program: - Load an image - Create a window to display results of the Morphological operations - - Create 03 Trackbars for the user to enter parameters: - - The first trackbar **"Operator"** returns the kind of morphology operation to use + - Create three Trackbars for the user to enter parameters: + - The first trackbar **Operator** returns the kind of morphology operation to use (**morph_operator**). - @code{.cpp} - createTrackbar("Operator:\n 0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat", - window_name, &morph_operator, max_operator, - Morphology_Operations ); - @endcode - - The second trackbar **"Element"** returns **morph_elem**, which indicates what kind of + @snippet cpp/tutorial_code/ImgProc/Morphology_2.cpp create_trackbar1 + + - The second trackbar **Element** returns **morph_elem**, which indicates what kind of structure our kernel is: - @code{.cpp} - createTrackbar( "Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name, - &morph_elem, max_elem, - Morphology_Operations ); - @endcode - - The final trackbar **"Kernel Size"** returns the size of the kernel to be used + @snippet cpp/tutorial_code/ImgProc/Morphology_2.cpp create_trackbar2 + + - The final trackbar **Kernel Size** returns the size of the kernel to be used (**morph_size**) - @code{.cpp} - createTrackbar( "Kernel size:\n 2n +1", window_name, - &morph_size, max_kernel_size, - Morphology_Operations ); - @endcode + @snippet cpp/tutorial_code/ImgProc/Morphology_2.cpp create_trackbar3 + - Every time we move any slider, the user's function **Morphology_Operations** will be called to effectuate a new morphology operation and it will update the output image based on the current trackbar values. - @code{.cpp} - /* - * @function Morphology_Operations - */ - void Morphology_Operations( int, void* ) - { - // Since MORPH_X : 2,3,4,5 and 6 - int operation = morph_operator + 2; - - Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) ); - - /// Apply the specified morphology operation - morphologyEx( src, dst, operation, element ); - imshow( window_name, dst ); - } - @endcode + @snippet cpp/tutorial_code/ImgProc/Morphology_2.cpp morphology_operations We can observe that the key function to perform the morphology transformations is @ref cv::morphologyEx . In this example we use four arguments (leaving the rest as defaults): @@ -216,9 +123,7 @@ Explanation As you can see the values range from \<2-6\>, that is why we add (+2) to the values entered by the Trackbar: - @code{.cpp} - int operation = morph_operator + 2; - @endcode + @snippet cpp/tutorial_code/ImgProc/Morphology_2.cpp operation - **element**: The kernel to be used. We use the function @ref cv::getStructuringElement to define our own structure. diff --git a/doc/tutorials/imgproc/pyramids/pyramids.markdown b/doc/tutorials/imgproc/pyramids/pyramids.markdown index 0bb5160fbb..69df1cda63 100644 --- a/doc/tutorials/imgproc/pyramids/pyramids.markdown +++ b/doc/tutorials/imgproc/pyramids/pyramids.markdown @@ -77,13 +77,7 @@ Let's check the general structure of the program: - Load an image (in this case it is defined in the program, the user does not have to enter it as an argument) - @code{.cpp} - /// Test image - Make sure it s divisible by 2^{n} - src = imread( "../images/chicky_512.jpg" ); - if( !src.data ) - { printf(" No data! -- Exiting the program \n"); - return -1; } - @endcode + @snippet cpp/tutorial_code/ImgProc/Pyramids.cpp load - Create a Mat object to store the result of the operations (*dst*) and one to save temporal results (*tmp*). @@ -95,40 +89,15 @@ Let's check the general structure of the program: @endcode - Create a window to display the result - @code{.cpp} - namedWindow( window_name, WINDOW_AUTOSIZE ); - imshow( window_name, dst ); - @endcode + @snippet cpp/tutorial_code/ImgProc/Pyramids.cpp create_window - Perform an infinite loop waiting for user input. - @code{.cpp} - while( true ) - { - int c; - c = waitKey(10); - - if( (char)c == 27 ) - { break; } - if( (char)c == 'u' ) - { pyrUp( tmp, dst, Size( tmp.cols*2, tmp.rows*2 ) ); - printf( "** Zoom In: Image x 2 \n" ); - } - else if( (char)c == 'd' ) - { pyrDown( tmp, dst, Size( tmp.cols/2, tmp.rows/2 ) ); - printf( "** Zoom Out: Image / 2 \n" ); - } - - imshow( window_name, dst ); - tmp = dst; - } - @endcode + @snippet cpp/tutorial_code/ImgProc/Pyramids.cpp infinite_loop Our program exits if the user presses *ESC*. Besides, it has two options: - **Perform upsampling (after pressing 'u')** - @code{.cpp} - pyrUp( tmp, dst, Size( tmp.cols*2, tmp.rows*2 ) - @endcode - We use the function @ref cv::pyrUp with 03 arguments: + @snippet cpp/tutorial_code/ImgProc/Pyramids.cpp pyrup + We use the function @ref cv::pyrUp with three arguments: - *tmp*: The current image, it is initialized with the *src* original image. - *dst*: The destination image (to be shown on screen, supposedly the double of the @@ -136,11 +105,8 @@ Let's check the general structure of the program: - *Size( tmp.cols*2, tmp.rows\*2 )\* : The destination size. Since we are upsampling, @ref cv::pyrUp expects a size double than the input image (in this case *tmp*). - **Perform downsampling (after pressing 'd')** - @code{.cpp} - pyrDown( tmp, dst, Size( tmp.cols/2, tmp.rows/2 ) - @endcode - Similarly as with @ref cv::pyrUp , we use the function @ref cv::pyrDown with 03 - arguments: + @snippet cpp/tutorial_code/ImgProc/Pyramids.cpp pyrdown + Similarly as with @ref cv::pyrUp , we use the function @ref cv::pyrDown with three arguments: - *tmp*: The current image, it is initialized with the *src* original image. - *dst*: The destination image (to be shown on screen, supposedly half the input @@ -151,15 +117,13 @@ Let's check the general structure of the program: both dimensions). Otherwise, an error will be shown. - Finally, we update the input image **tmp** with the current image displayed, so the subsequent operations are performed on it. - @code{.cpp} - tmp = dst; - @endcode + @snippet cpp/tutorial_code/ImgProc/Pyramids.cpp update_tmp Results ------- - After compiling the code above we can test it. The program calls an image **chicky_512.jpg** - that comes in the *tutorial_code/image* folder. Notice that this image is \f$512 \times 512\f$, + that comes in the *samples/data* folder. Notice that this image is \f$512 \times 512\f$, hence a downsample won't generate any error (\f$512 = 2^{9}\f$). The original image is shown below: ![](images/Pyramids_Tutorial_Original_Image.jpg) diff --git a/doc/tutorials/imgproc/threshold/threshold.markdown b/doc/tutorials/imgproc/threshold/threshold.markdown index f0bc735ab6..c93650aacd 100644 --- a/doc/tutorials/imgproc/threshold/threshold.markdown +++ b/doc/tutorials/imgproc/threshold/threshold.markdown @@ -106,51 +106,23 @@ Explanation -# Let's check the general structure of the program: - Load an image. If it is BGR we convert it to Grayscale. For this, remember that we can use the function @ref cv::cvtColor : - @code{.cpp} - src = imread( argv[1], 1 ); + @snippet cpp/tutorial_code/ImgProc/Threshold.cpp load - /// Convert the image to Gray - cvtColor( src, src_gray, COLOR_BGR2GRAY ); - @endcode - Create a window to display the result - @code{.cpp} - namedWindow( window_name, WINDOW_AUTOSIZE ); - @endcode + @snippet cpp/tutorial_code/ImgProc/Threshold.cpp window + - Create \f$2\f$ trackbars for the user to enter user input: - **Type of thresholding**: Binary, To Zero, etc... - **Threshold value** - @code{.cpp} - createTrackbar( trackbar_type, - window_name, &threshold_type, - max_type, Threshold_Demo ); + @snippet cpp/tutorial_code/ImgProc/Threshold.cpp trackbar - createTrackbar( trackbar_value, - window_name, &threshold_value, - max_value, Threshold_Demo ); - @endcode - Wait until the user enters the threshold value, the type of thresholding (or until the program exits) - Whenever the user changes the value of any of the Trackbars, the function *Threshold_Demo* is called: - @code{.cpp} - /* - * @function Threshold_Demo - */ - void Threshold_Demo( int, void* ) - { - /* 0: Binary - 1: Binary Inverted - 2: Threshold Truncated - 3: Threshold to Zero - 4: Threshold to Zero Inverted - */ + @snippet cpp/tutorial_code/ImgProc/Threshold.cpp Threshold_Demo - threshold( src_gray, dst, threshold_value, max_BINARY_value,threshold_type ); - - imshow( window_name, dst ); - } - @endcode As you can see, the function @ref cv::threshold is invoked. We give \f$5\f$ parameters: - *src_gray*: Our input image diff --git a/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.markdown b/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.markdown index ec27dc2731..3953635193 100644 --- a/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.markdown +++ b/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.markdown @@ -21,92 +21,8 @@ This tutorial code's is shown lines below. You can also download it from [here](https://github.com/opencv/tree/master/samples/cpp/tutorial_code/objectDetection/objectDetection.cpp) . The second version (using LBP for face detection) can be [found here](https://github.com/opencv/tree/master/samples/cpp/tutorial_code/objectDetection/objectDetection2.cpp) -@code{.cpp} -#include "opencv2/objdetect.hpp" -#include "opencv2/highgui.hpp" -#include "opencv2/imgproc.hpp" +@include samples/cpp/tutorial_code/objectDetection/objectDetection.cpp -#include -#include - -using namespace std; -using namespace cv; - -/* Function Headers */ -void detectAndDisplay( Mat frame ); - -/* Global variables */ -String face_cascade_name = "haarcascade_frontalface_alt.xml"; -String eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml"; -CascadeClassifier face_cascade; -CascadeClassifier eyes_cascade; -String window_name = "Capture - Face detection"; - -/* @function main */ -int main( void ) -{ - VideoCapture capture; - Mat frame; - - //-- 1. Load the cascades - if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading face cascade\n"); return -1; }; - if( !eyes_cascade.load( eyes_cascade_name ) ){ printf("--(!)Error loading eyes cascade\n"); return -1; }; - - //-- 2. Read the video stream - capture.open( -1 ); - if ( ! capture.isOpened() ) { printf("--(!)Error opening video capture\n"); return -1; } - - while ( capture.read(frame) ) - { - if( frame.empty() ) - { - printf(" --(!) No captured frame -- Break!"); - break; - } - - //-- 3. Apply the classifier to the frame - detectAndDisplay( frame ); - - int c = waitKey(10); - if( (char)c == 27 ) { break; } // escape - } - return 0; -} - -/* @function detectAndDisplay */ -void detectAndDisplay( Mat frame ) -{ - std::vector faces; - Mat frame_gray; - - cvtColor( frame, frame_gray, COLOR_BGR2GRAY ); - equalizeHist( frame_gray, frame_gray ); - - //-- Detect faces - face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CASCADE_SCALE_IMAGE, Size(30, 30) ); - - for( size_t i = 0; i < faces.size(); i++ ) - { - Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 ); - ellipse( frame, center, Size( faces[i].width/2, faces[i].height/2), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 ); - - Mat faceROI = frame_gray( faces[i] ); - std::vector eyes; - - //-- In each face, detect eyes - eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CASCADE_SCALE_IMAGE, Size(30, 30) ); - - for( size_t j = 0; j < eyes.size(); j++ ) - { - Point eye_center( faces[i].x + eyes[j].x + eyes[j].width/2, faces[i].y + eyes[j].y + eyes[j].height/2 ); - int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 ); - circle( frame, eye_center, radius, Scalar( 255, 0, 0 ), 4, 8, 0 ); - } - } - //-- Show what you got - imshow( window_name, frame ); -} -@endcode Explanation ----------- diff --git a/samples/cpp/houghcircles.cpp b/samples/cpp/houghcircles.cpp index 26c4dbae08..f749b0e247 100644 --- a/samples/cpp/houghcircles.cpp +++ b/samples/cpp/houghcircles.cpp @@ -24,39 +24,48 @@ int main(int argc, char** argv) help(); return 0; } + //![load] string filename = parser.get("@image"); - if (filename.empty()) - { - help(); - cout << "no image_name provided" << endl; - return -1; - } - Mat img = imread(filename, 0); + Mat img = imread(filename, IMREAD_COLOR); if(img.empty()) { help(); cout << "can not open " << filename << endl; return -1; } + //![load] - Mat cimg; - medianBlur(img, img, 5); - cvtColor(img, cimg, COLOR_GRAY2BGR); + //![convert_to_gray] + Mat gray; + cvtColor(img, gray, COLOR_BGR2GRAY); + //![convert_to_gray] + //![reduce_noise] + medianBlur(gray, gray, 5); + //![reduce_noise] + + //![houghcircles] vector circles; - HoughCircles(img, circles, HOUGH_GRADIENT, 1, 10, + HoughCircles(gray, circles, HOUGH_GRADIENT, 1, + gray.rows/16, // change this value to detect circles with different distances to each other 100, 30, 1, 30 // change the last two parameters // (min_radius & max_radius) to detect larger circles ); + //![houghcircles] + + //![draw] for( size_t i = 0; i < circles.size(); i++ ) { Vec3i c = circles[i]; - circle( cimg, Point(c[0], c[1]), c[2], Scalar(0,0,255), 3, LINE_AA); - circle( cimg, Point(c[0], c[1]), 2, Scalar(0,255,0), 3, LINE_AA); + circle( img, Point(c[0], c[1]), c[2], Scalar(0,0,255), 3, LINE_AA); + circle( img, Point(c[0], c[1]), 2, Scalar(0,255,0), 3, LINE_AA); } + //![draw] - imshow("detected circles", cimg); + //![display] + imshow("detected circles", img); waitKey(); + //![display] return 0; } diff --git a/samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp b/samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp index 93a7b48b19..51522fa5ca 100644 --- a/samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp +++ b/samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp @@ -21,6 +21,7 @@ Mat src1; Mat src2; Mat dst; +//![on_trackbar] /** * @function on_trackbar * @brief Callback for trackbar @@ -35,7 +36,7 @@ static void on_trackbar( int, void* ) imshow( "Linear Blend", dst ); } - +//![on_trackbar] /** * @function main @@ -43,9 +44,11 @@ static void on_trackbar( int, void* ) */ int main( void ) { - /// Read image ( same size, same type ) + //![load] + /// Read images ( both have to be of the same size and type ) src1 = imread("../data/LinuxLogo.jpg"); src2 = imread("../data/WindowsLogo.jpg"); + //![load] if( src1.empty() ) { printf("Error loading src1 \n"); return -1; } if( src2.empty() ) { printf("Error loading src2 \n"); return -1; } @@ -53,13 +56,15 @@ int main( void ) /// Initialize values alpha_slider = 0; - /// Create Windows - namedWindow("Linear Blend", 1); + //![window] + namedWindow("Linear Blend", WINDOW_AUTOSIZE); // Create Window + //![window] - /// Create Trackbars + //![create_trackbar] char TrackbarName[50]; sprintf( TrackbarName, "Alpha x %d", alpha_slider_max ); createTrackbar( TrackbarName, "Linear Blend", &alpha_slider, alpha_slider_max, on_trackbar ); + //![create_trackbar] /// Show some stuff on_trackbar( alpha_slider, 0 ); diff --git a/samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp b/samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp index 626bd8b960..cfcd75553f 100644 --- a/samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp +++ b/samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp @@ -66,6 +66,7 @@ int main( int, char** argv ) return 0; } +//![erosion] /** * @function Erosion */ @@ -76,14 +77,19 @@ void Erosion( int, void* ) else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; } else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; } + //![kernel] Mat element = getStructuringElement( erosion_type, Size( 2*erosion_size + 1, 2*erosion_size+1 ), Point( erosion_size, erosion_size ) ); + //![kernel] + /// Apply the erosion operation erode( src, erosion_dst, element ); imshow( "Erosion Demo", erosion_dst ); } +//![erosion] +//![dilation] /** * @function Dilation */ @@ -97,7 +103,9 @@ void Dilation( int, void* ) Mat element = getStructuringElement( dilation_type, Size( 2*dilation_size + 1, 2*dilation_size+1 ), Point( dilation_size, dilation_size ) ); + /// Apply the dilation operation dilate( src, dilation_dst, element ); imshow( "Dilation Demo", dilation_dst ); } +//![dilation] diff --git a/samples/cpp/tutorial_code/ImgProc/Morphology_2.cpp b/samples/cpp/tutorial_code/ImgProc/Morphology_2.cpp index 97304a4612..7a8fb57284 100644 --- a/samples/cpp/tutorial_code/ImgProc/Morphology_2.cpp +++ b/samples/cpp/tutorial_code/ImgProc/Morphology_2.cpp @@ -31,27 +31,35 @@ void Morphology_Operations( int, void* ); */ int main( int, char** argv ) { - /// Load an image - src = imread( argv[1], IMREAD_COLOR ); + //![load] + src = imread( argv[1], IMREAD_COLOR ); // Load an image if( src.empty() ) { return -1; } + //![load] - /// Create window - namedWindow( window_name, WINDOW_AUTOSIZE ); + //![window] + namedWindow( window_name, WINDOW_AUTOSIZE ); // Create window + //![window] + //![create_trackbar1] /// Create Trackbar to select Morphology operation createTrackbar("Operator:\n 0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat", window_name, &morph_operator, max_operator, Morphology_Operations ); + //![create_trackbar1] + //![create_trackbar2] /// Create Trackbar to select kernel type createTrackbar( "Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name, &morph_elem, max_elem, Morphology_Operations ); + //![create_trackbar2] + //![create_trackbar3] /// Create Trackbar to choose kernel size createTrackbar( "Kernel size:\n 2n +1", window_name, &morph_size, max_kernel_size, Morphology_Operations ); + //![create_trackbar3] /// Default start Morphology_Operations( 0, 0 ); @@ -60,13 +68,16 @@ int main( int, char** argv ) return 0; } +//![morphology_operations] /** * @function Morphology_Operations */ void Morphology_Operations( int, void* ) { // Since MORPH_X : 2,3,4,5 and 6 + //![operation] int operation = morph_operator + 2; + //![operation] Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) ); @@ -74,3 +85,4 @@ void Morphology_Operations( int, void* ) morphologyEx( src, dst, operation, element ); imshow( window_name, dst ); } +//![morphology_operations] diff --git a/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp b/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp index e4b7096e6d..d8067f9869 100644 --- a/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp +++ b/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp @@ -28,39 +28,50 @@ int main( void ) printf( " * [d] -> Zoom out \n" ); printf( " * [ESC] -> Close program \n \n" ); - /// Test image - Make sure it s divisible by 2^{n} - src = imread( "../data/chicky_512.png" ); + //![load] + src = imread( "../data/chicky_512.png" ); // Loads the test image if( src.empty() ) { printf(" No data! -- Exiting the program \n"); return -1; } + //![load] tmp = src; dst = tmp; - /// Create window - namedWindow( window_name, WINDOW_AUTOSIZE ); + //![create_window] imshow( window_name, dst ); + //![create_window] - /// Loop + //![infinite_loop] for(;;) { int c; - c = waitKey(10); + c = waitKey(0); if( (char)c == 27 ) { break; } if( (char)c == 'u' ) - { pyrUp( tmp, dst, Size( tmp.cols*2, tmp.rows*2 ) ); + { + //![pyrup] + pyrUp( tmp, dst, Size( tmp.cols*2, tmp.rows*2 ) ); + //![pyrup] printf( "** Zoom In: Image x 2 \n" ); } else if( (char)c == 'd' ) - { pyrDown( tmp, dst, Size( tmp.cols/2, tmp.rows/2 ) ); + { + //![pyrdown] + pyrDown( tmp, dst, Size( tmp.cols/2, tmp.rows/2 ) ); + //![pyrdown] printf( "** Zoom Out: Image / 2 \n" ); } imshow( window_name, dst ); + + //![update_tmp] tmp = dst; + //![update_tmp] } + //![infinite_loop] return 0; } diff --git a/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp b/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp index 6a84da073b..58aa474c38 100644 --- a/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp +++ b/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp @@ -43,33 +43,38 @@ int main( void ) /// Applying Homogeneous blur if( display_caption( "Homogeneous Blur" ) != 0 ) { return 0; } + //![blur] for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) { blur( src, dst, Size( i, i ), Point(-1,-1) ); if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } - + //![blur] /// Applying Gaussian blur if( display_caption( "Gaussian Blur" ) != 0 ) { return 0; } + //![gaussianblur] for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) { GaussianBlur( src, dst, Size( i, i ), 0, 0 ); if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } - + //![gaussianblur] /// Applying Median blur if( display_caption( "Median Blur" ) != 0 ) { return 0; } + //![medianblur] for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) { medianBlur ( src, dst, i ); if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } - + //![medianblur] /// Applying Bilateral Filter if( display_caption( "Bilateral Blur" ) != 0 ) { return 0; } + //![bilateralfilter] for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) { bilateralFilter ( src, dst, i, i*2, i/2 ); if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } + //![bilateralfilter] /// Wait until user press a key display_caption( "End: Press a key!" ); diff --git a/samples/cpp/tutorial_code/ImgProc/Threshold.cpp b/samples/cpp/tutorial_code/ImgProc/Threshold.cpp index 36943028d9..cee1a51c9c 100644 --- a/samples/cpp/tutorial_code/ImgProc/Threshold.cpp +++ b/samples/cpp/tutorial_code/ImgProc/Threshold.cpp @@ -32,29 +32,30 @@ void Threshold_Demo( int, void* ); */ int main( int, char** argv ) { - /// Load an image - src = imread( argv[1], IMREAD_COLOR ); + //! [load] + src = imread( argv[1], IMREAD_COLOR ); // Load an image if( src.empty() ) { return -1; } - /// Convert the image to Gray - cvtColor( src, src_gray, COLOR_BGR2GRAY ); + cvtColor( src, src_gray, COLOR_BGR2GRAY ); // Convert the image to Gray + //! [load] - /// Create a window to display results - namedWindow( window_name, WINDOW_AUTOSIZE ); + //! [window] + namedWindow( window_name, WINDOW_AUTOSIZE ); // Create a window to display results + //! [window] - /// Create Trackbar to choose type of Threshold + //! [trackbar] createTrackbar( trackbar_type, window_name, &threshold_type, - max_type, Threshold_Demo ); + max_type, Threshold_Demo ); // Create Trackbar to choose type of Threshold createTrackbar( trackbar_value, window_name, &threshold_value, - max_value, Threshold_Demo ); + max_value, Threshold_Demo ); // Create Trackbar to choose Threshold value + //! [trackbar] - /// Call the function to initialize - Threshold_Demo( 0, 0 ); + Threshold_Demo( 0, 0 ); // Call the function to initialize /// Wait until user finishes program for(;;) @@ -67,7 +68,7 @@ int main( int, char** argv ) } - +//![Threshold_Demo] /** * @function Threshold_Demo */ @@ -84,3 +85,4 @@ void Threshold_Demo( int, void* ) imshow( window_name, dst ); } +//![Threshold_Demo] diff --git a/samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp b/samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp index 8b94bb3207..efdeca1425 100644 --- a/samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp @@ -10,8 +10,7 @@ using namespace cv; -/// Global variables - +//![variables] Mat src, src_gray; Mat dst, detected_edges; @@ -21,6 +20,7 @@ int const max_lowThreshold = 100; int ratio = 3; int kernel_size = 3; const char* window_name = "Edge Map"; +//![variables] /** * @function CannyThreshold @@ -28,17 +28,28 @@ const char* window_name = "Edge Map"; */ static void CannyThreshold(int, void*) { + //![reduce_noise] /// Reduce noise with a kernel 3x3 blur( src_gray, detected_edges, Size(3,3) ); + //![reduce_noise] + //![canny] /// Canny detector Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size ); + //![canny] /// Using Canny's output as a mask, we display our result + //![fill] dst = Scalar::all(0); + //![fill] + //![copyto] src.copyTo( dst, detected_edges); + //![copyto] + + //![display] imshow( window_name, dst ); + //![display] } @@ -47,23 +58,30 @@ static void CannyThreshold(int, void*) */ int main( int, char** argv ) { - /// Load an image - src = imread( argv[1], IMREAD_COLOR ); + //![load] + src = imread( argv[1], IMREAD_COLOR ); // Load an image if( src.empty() ) { return -1; } + //![load] + //![create_mat] /// Create a matrix of the same type and size as src (for dst) dst.create( src.size(), src.type() ); + //![create_mat] - /// Convert the image to grayscale + //![convert_to_gray] cvtColor( src, src_gray, COLOR_BGR2GRAY ); + //![convert_to_gray] - /// Create a window + //![create_window] namedWindow( window_name, WINDOW_AUTOSIZE ); + //![create_window] + //![create_trackbar] /// Create a Trackbar for user to enter threshold createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold, CannyThreshold ); + //![create_trackbar] /// Show the image CannyThreshold(0, 0); diff --git a/samples/cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp b/samples/cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp index 386b26da74..6a41c3a1c3 100644 --- a/samples/cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp @@ -15,39 +15,45 @@ using namespace cv; */ int main( int, char** argv ) { - + //![variables] Mat src, src_gray, dst; int kernel_size = 3; int scale = 1; int delta = 0; int ddepth = CV_16S; const char* window_name = "Laplace Demo"; + //![variables] - /// Load an image - src = imread( argv[1], IMREAD_COLOR ); + //![load] + src = imread( argv[1], IMREAD_COLOR ); // Load an image if( src.empty() ) { return -1; } + //![load] - /// Remove noise by blurring with a Gaussian filter + //![reduce_noise] + /// Reduce noise by blurring with a Gaussian filter GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT ); + //![reduce_noise] - /// Convert the image to grayscale - cvtColor( src, src_gray, COLOR_RGB2GRAY ); - - /// Create window - namedWindow( window_name, WINDOW_AUTOSIZE ); + //![convert_to_gray] + cvtColor( src, src_gray, COLOR_BGR2GRAY ); // Convert the image to grayscale + //![convert_to_gray] /// Apply Laplace function Mat abs_dst; - + //![laplacian] Laplacian( src_gray, dst, ddepth, kernel_size, scale, delta, BORDER_DEFAULT ); + //![laplacian] + + //![convert] convertScaleAbs( dst, abs_dst ); + //![convert] - /// Show what you got + //![display] imshow( window_name, abs_dst ); - waitKey(0); + //![display] return 0; } diff --git a/samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp b/samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp index efe4c71691..ad45452021 100644 --- a/samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp @@ -1,6 +1,6 @@ /** * @file Sobel_Demo.cpp - * @brief Sample code using Sobel and/orScharr OpenCV functions to make a simple Edge Detector + * @brief Sample code using Sobel and/or Scharr OpenCV functions to make a simple Edge Detector * @author OpenCV team */ @@ -15,28 +15,31 @@ using namespace cv; */ int main( int, char** argv ) { - + //![variables] Mat src, src_gray; Mat grad; const char* window_name = "Sobel Demo - Simple Edge Detector"; int scale = 1; int delta = 0; int ddepth = CV_16S; + //![variables] - /// Load an image - src = imread( argv[1], IMREAD_COLOR ); + //![load] + src = imread( argv[1], IMREAD_COLOR ); // Load an image if( src.empty() ) { return -1; } + //![load] + //![reduce_noise] GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT ); + //![reduce_noise] - /// Convert it to gray - cvtColor( src, src_gray, COLOR_RGB2GRAY ); - - /// Create window - namedWindow( window_name, WINDOW_AUTOSIZE ); + //![convert_to_gray] + cvtColor( src, src_gray, COLOR_BGR2GRAY ); + //![convert_to_gray] + //![sobel] /// Generate grad_x and grad_y Mat grad_x, grad_y; Mat abs_grad_x, abs_grad_y; @@ -44,19 +47,26 @@ int main( int, char** argv ) /// Gradient X //Scharr( src_gray, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT ); Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT ); - convertScaleAbs( grad_x, abs_grad_x ); /// Gradient Y //Scharr( src_gray, grad_y, ddepth, 0, 1, scale, delta, BORDER_DEFAULT ); Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT ); - convertScaleAbs( grad_y, abs_grad_y ); + //![sobel] + //![convert] + convertScaleAbs( grad_x, abs_grad_x ); + convertScaleAbs( grad_y, abs_grad_y ); + //![convert] + + //![blend] /// Total Gradient (approximate) addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad ); + //![blend] + //![display] imshow( window_name, grad ); - waitKey(0); + //![display] return 0; } diff --git a/samples/cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp b/samples/cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp index 6da2b296b2..60a6d9fcb5 100644 --- a/samples/cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp @@ -10,12 +10,13 @@ using namespace cv; -/// Global Variables +//![variables] Mat src, dst; int top, bottom, left, right; int borderType; const char* window_name = "copyMakeBorder Demo"; RNG rng(12345); +//![variables] /** * @function main @@ -25,14 +26,15 @@ int main( int, char** argv ) int c; - /// Load an image - src = imread( argv[1], IMREAD_COLOR ); + //![load] + src = imread( argv[1], IMREAD_COLOR ); // Load an image if( src.empty() ) { printf(" No data entered, please enter the path to an image file \n"); return -1; } + //![load] /// Brief how-to for this program printf( "\n \t copyMakeBorder Demo: \n" ); @@ -41,18 +43,22 @@ int main( int, char** argv ) printf( " ** Press 'r' to set the border to be replicated \n"); printf( " ** Press 'ESC' to exit the program \n"); - /// Create window + //![create_window] namedWindow( window_name, WINDOW_AUTOSIZE ); + //![create_window] + //![init_arguments] /// Initialize arguments for the filter top = (int) (0.05*src.rows); bottom = (int) (0.05*src.rows); left = (int) (0.05*src.cols); right = (int) (0.05*src.cols); - dst = src; + //![init_arguments] + dst = src; imshow( window_name, dst ); for(;;) { + //![check_keypress] c = waitKey(500); if( (char)c == 27 ) @@ -61,11 +67,19 @@ int main( int, char** argv ) { borderType = BORDER_CONSTANT; } else if( (char)c == 'r' ) { borderType = BORDER_REPLICATE; } + //![check_keypress] + //![update_value] Scalar value( rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255) ); - copyMakeBorder( src, dst, top, bottom, left, right, borderType, value ); + //![update_value] + //![copymakeborder] + copyMakeBorder( src, dst, top, bottom, left, right, borderType, value ); + //![copymakeborder] + + //![display] imshow( window_name, dst ); + //![display] } return 0; diff --git a/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp b/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp index 6fc04d8f41..e1ceb0bf6d 100644 --- a/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp @@ -27,19 +27,19 @@ int main ( int, char** argv ) int c; - /// Load an image - src = imread( argv[1], IMREAD_COLOR ); + //![load] + src = imread( argv[1], IMREAD_COLOR ); // Load an image if( src.empty() ) { return -1; } + //![load] - /// Create window - namedWindow( window_name, WINDOW_AUTOSIZE ); - + //![init_arguments] /// Initialize arguments for the filter anchor = Point( -1, -1 ); delta = 0; ddepth = -1; + //![init_arguments] /// Loop - Will filter the image with different kernel sizes each 0.5 seconds int ind = 0; @@ -50,12 +50,15 @@ int main ( int, char** argv ) if( (char)c == 27 ) { break; } + //![update_kernel] /// Update kernel size for a normalized box filter kernel_size = 3 + 2*( ind%5 ); kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size); + //![update_kernel] - /// Apply filter + //![apply_filter] filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT ); + //![apply_filter] imshow( window_name, dst ); ind++; } diff --git a/samples/cpp/tutorial_code/ImgProc/AddingImages.cpp b/samples/cpp/tutorial_code/core/AddingImages/AddingImages.cpp similarity index 81% rename from samples/cpp/tutorial_code/ImgProc/AddingImages.cpp rename to samples/cpp/tutorial_code/core/AddingImages/AddingImages.cpp index 20b09ec32b..491ae7ad9e 100644 --- a/samples/cpp/tutorial_code/ImgProc/AddingImages.cpp +++ b/samples/cpp/tutorial_code/core/AddingImages/AddingImages.cpp @@ -16,7 +16,6 @@ using namespace cv; */ int main( void ) { - double alpha = 0.5; double beta; double input; Mat src1, src2, dst; @@ -27,26 +26,28 @@ int main( void ) std::cout<<"* Enter alpha [0-1]: "; std::cin>>input; - // We use the alpha provided by the user iff it is between 0 and 1 + // We use the alpha provided by the user if it is between 0 and 1 if( alpha >= 0 && alpha <= 1 ) { alpha = input; } - /// Read image ( same size, same type ) + //![load] + /// Read images ( both have to be of the same size and type ) src1 = imread("../data/LinuxLogo.jpg"); src2 = imread("../data/WindowsLogo.jpg"); + //![load] if( src1.empty() ) { std::cout<< "Error loading src1"< Date: Tue, 16 Aug 2016 09:51:09 +0200 Subject: [PATCH 067/178] Canny with own gradient (#6664) * example using the Canny algorithm with custom image gradient. * Modified example to integrate new function canny with custom gradient --- samples/cpp/edge.cpp | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/samples/cpp/edge.cpp b/samples/cpp/edge.cpp index 88abd8b257..4fbef937a1 100644 --- a/samples/cpp/edge.cpp +++ b/samples/cpp/edge.cpp @@ -9,19 +9,34 @@ using namespace cv; using namespace std; int edgeThresh = 1; -Mat image, gray, edge, cedge; +int edgeThreshScharr=1; + +Mat image, gray, blurImage, edge1, edge2, cedge; + +const char* window_name1 = "Edge map : Canny default (Sobel gradient)"; +const char* window_name2 = "Edge map : Canny with custom gradient (Scharr)"; // define a trackbar callback static void onTrackbar(int, void*) { - blur(gray, edge, Size(3,3)); + blur(gray, blurImage, Size(3,3)); // Run the edge detector on grayscale - Canny(edge, edge, edgeThresh, edgeThresh*3, 3); + Canny(blurImage, edge1, edgeThresh, edgeThresh*3, 3); cedge = Scalar::all(0); - image.copyTo(cedge, edge); - imshow("Edge map", cedge); + image.copyTo(cedge, edge1); + imshow(window_name1, cedge); + + /// Canny detector with scharr + Mat dx,dy; + Scharr(blurImage,dx,CV_16S,1,0); + Scharr(blurImage,dy,CV_16S,0,1); + Canny( dx,dy, edge2, edgeThreshScharr, edgeThreshScharr*3 ); + /// Using Canny's output as a mask, we display our result + cedge = Scalar::all(0); + image.copyTo(cedge, edge2); + imshow(window_name2, cedge); } static void help() @@ -57,10 +72,12 @@ int main( int argc, const char** argv ) cvtColor(image, gray, COLOR_BGR2GRAY); // Create a window - namedWindow("Edge map", 1); + namedWindow(window_name1, 1); + namedWindow(window_name2, 1); // create a toolbar - createTrackbar("Canny threshold", "Edge map", &edgeThresh, 100, onTrackbar); + createTrackbar("Canny threshold default", window_name1, &edgeThresh, 100, onTrackbar); + createTrackbar("Canny threshold Scharr", window_name2, &edgeThreshScharr, 400, onTrackbar); // Show the image onTrackbar(0, 0); From 84e17126593c40e38305fad6a16e81545a8f687c Mon Sep 17 00:00:00 2001 From: Patrick Spettel Date: Tue, 16 Aug 2016 10:49:11 +0200 Subject: [PATCH 068/178] Fix temporary file removal in imdecode for tiff The TiffDecoder keeps an open file handle. As a consequence the file cannot be removed before the TiffDecoder closes the file. --- modules/imgcodecs/src/loadsave.cpp | 20 ++++++++++++++++---- modules/imgcodecs/test/test_grfmt.cpp | 13 +++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index 1c0b794b8e..244d05dd83 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -514,8 +514,14 @@ imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 ) if( !decoder->readHeader() ) { - if( !filename.empty() ) - remove(filename.c_str()); + decoder.release(); + if ( !filename.empty() ) + { + if ( remove(filename.c_str()) != 0 ) + { + CV_Error( CV_StsError, "unable to remove temporary file" ); + } + } return 0; } @@ -556,8 +562,14 @@ imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 ) } bool code = decoder->readData( *data ); - if( !filename.empty() ) - remove(filename.c_str()); + decoder.release(); + if ( !filename.empty() ) + { + if ( remove(filename.c_str()) != 0 ) + { + CV_Error( CV_StsError, "unable to remove temporary file" ); + } + } if( !code ) { diff --git a/modules/imgcodecs/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp index f305ca137a..14860f9a8b 100644 --- a/modules/imgcodecs/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -890,6 +890,19 @@ TEST(Imgcodecs_Tiff, decode_multipage) CV_GrfmtReadTifMultiPage test; test.safe_run(); } +TEST(Imgcodecs_Tiff, imdecode_no_exception_temporary_file_removed) +{ + cvtest::TS& ts = *cvtest::TS::ptr(); + string input = string(ts.get_data_path()) + "../cv/shared/lena.png"; + cv::Mat img = cv::imread(input); + ASSERT_FALSE(img.empty()); + + std::vector buf; + EXPECT_NO_THROW(cv::imencode(".tiff", img, buf)); + + EXPECT_NO_THROW(cv::imdecode(buf, IMREAD_UNCHANGED)); +} + #endif #ifdef HAVE_WEBP From ab8de8f506dcc799e8426c5d04da7f9157f805bd Mon Sep 17 00:00:00 2001 From: Vitaliy Lyudvichenko Date: Sat, 6 Aug 2016 19:46:17 +0300 Subject: [PATCH 069/178] Adding of user-defined type conversions for python bindings inside module directories Adding of destructor and placement new constructors for classes wrapped with CV_EXPORTS_W_SIMPLE macro --- .../py_bindings_basics.markdown | 5 +- .../misc/python/pyopencv_features2d.hpp | 3 + modules/flann/misc/python/pyopencv_flann.hpp | 79 +++++++++++ modules/ml/misc/python/pyopencv_ml.hpp | 22 +++ modules/python/common.cmake | 11 +- modules/python/src2/cv2.cpp | 131 +----------------- modules/python/src2/gen2.py | 8 +- .../misc/python/pyopencv_stitching.hpp | 9 ++ 8 files changed, 132 insertions(+), 136 deletions(-) create mode 100644 modules/features2d/misc/python/pyopencv_features2d.hpp create mode 100644 modules/flann/misc/python/pyopencv_flann.hpp create mode 100644 modules/ml/misc/python/pyopencv_ml.hpp create mode 100644 modules/stitching/misc/python/pyopencv_stitching.hpp diff --git a/doc/py_tutorials/py_bindings/py_bindings_basics/py_bindings_basics.markdown b/doc/py_tutorials/py_bindings/py_bindings_basics/py_bindings_basics.markdown index e256bcea03..4f48ae7799 100644 --- a/doc/py_tutorials/py_bindings/py_bindings_basics/py_bindings_basics.markdown +++ b/doc/py_tutorials/py_bindings/py_bindings_basics/py_bindings_basics.markdown @@ -142,5 +142,6 @@ public: So these are the major extension macros available in OpenCV. Typically, a developer has to put proper macros in their appropriate positions. Rest is done by generator scripts. Sometimes, there may be an exceptional cases where generator scripts cannot create the wrappers. Such functions need -to be handled manually. But most of the time, a code written according to OpenCV coding guidelines -will be automatically wrapped by generator scripts. +to be handled manually, to do this write your own pyopencv_*.hpp extending headers and put them into +misc/python subdirectory of your module. But most of the time, a code written according to OpenCV +coding guidelines will be automatically wrapped by generator scripts. \ No newline at end of file diff --git a/modules/features2d/misc/python/pyopencv_features2d.hpp b/modules/features2d/misc/python/pyopencv_features2d.hpp new file mode 100644 index 0000000000..b865e361b6 --- /dev/null +++ b/modules/features2d/misc/python/pyopencv_features2d.hpp @@ -0,0 +1,3 @@ +#ifdef HAVE_OPENCV_FEATURES2D +typedef SimpleBlobDetector::Params SimpleBlobDetector_Params; +#endif \ No newline at end of file diff --git a/modules/flann/misc/python/pyopencv_flann.hpp b/modules/flann/misc/python/pyopencv_flann.hpp new file mode 100644 index 0000000000..a9da8d0f00 --- /dev/null +++ b/modules/flann/misc/python/pyopencv_flann.hpp @@ -0,0 +1,79 @@ +#ifdef HAVE_OPENCV_FLANN +typedef cvflann::flann_distance_t cvflann_flann_distance_t; +typedef cvflann::flann_algorithm_t cvflann_flann_algorithm_t; + +template<> +PyObject* pyopencv_from(const cvflann_flann_algorithm_t& value) +{ + return PyInt_FromLong(int(value)); +} + +template<> +PyObject* pyopencv_from(const cvflann_flann_distance_t& value) +{ + return PyInt_FromLong(int(value)); +} + +template<> +bool pyopencv_to(PyObject *o, cv::flann::IndexParams& p, const char *name) +{ + (void)name; + bool ok = true; + PyObject* key = NULL; + PyObject* item = NULL; + Py_ssize_t pos = 0; + + if(PyDict_Check(o)) { + while(PyDict_Next(o, &pos, &key, &item)) { + if( !PyString_Check(key) ) { + ok = false; + break; + } + + String k = PyString_AsString(key); + if( PyString_Check(item) ) + { + const char* value = PyString_AsString(item); + p.setString(k, value); + } + else if( !!PyBool_Check(item) ) + p.setBool(k, item == Py_True); + else if( PyInt_Check(item) ) + { + int value = (int)PyInt_AsLong(item); + if( strcmp(k.c_str(), "algorithm") == 0 ) + p.setAlgorithm(value); + else + p.setInt(k, value); + } + else if( PyFloat_Check(item) ) + { + double value = PyFloat_AsDouble(item); + p.setDouble(k, value); + } + else + { + ok = false; + break; + } + } + } + + return ok && !PyErr_Occurred(); +} + +template<> +bool pyopencv_to(PyObject* obj, cv::flann::SearchParams & value, const char * name) +{ + return pyopencv_to(obj, value, name); +} + +template<> +bool pyopencv_to(PyObject *o, cvflann::flann_distance_t& dist, const char *name) +{ + int d = (int)dist; + bool ok = pyopencv_to(o, d, name); + dist = (cvflann::flann_distance_t)d; + return ok; +} +#endif \ No newline at end of file diff --git a/modules/ml/misc/python/pyopencv_ml.hpp b/modules/ml/misc/python/pyopencv_ml.hpp new file mode 100644 index 0000000000..6a86c46c2e --- /dev/null +++ b/modules/ml/misc/python/pyopencv_ml.hpp @@ -0,0 +1,22 @@ +template<> +bool pyopencv_to(PyObject *obj, CvTermCriteria& dst, const char *name) +{ + (void)name; + if(!obj) + return true; + return PyArg_ParseTuple(obj, "iid", &dst.type, &dst.max_iter, &dst.epsilon) > 0; +} + +template<> +bool pyopencv_to(PyObject* obj, CvSlice& r, const char* name) +{ + (void)name; + if(!obj || obj == Py_None) + return true; + if(PyObject_Size(obj) == 0) + { + r = CV_WHOLE_SEQ; + return true; + } + return PyArg_ParseTuple(obj, "ii", &r.start_index, &r.end_index) > 0; +} \ No newline at end of file diff --git a/modules/python/common.cmake b/modules/python/common.cmake index ba65100fb7..ffe709f3dc 100644 --- a/modules/python/common.cmake +++ b/modules/python/common.cmake @@ -24,8 +24,11 @@ foreach(m ${OPENCV_MODULES_BUILD}) endforeach() set(opencv_hdrs "") +set(opencv_userdef_hdrs "") foreach(m ${OPENCV_PYTHON_MODULES}) list(APPEND opencv_hdrs ${OPENCV_MODULE_${m}_HEADERS}) + file(GLOB userdef_hdrs ${OPENCV_MODULE_${m}_LOCATION}/misc/python/pyopencv*.hpp) + list(APPEND opencv_userdef_hdrs ${userdef_hdrs}) endforeach(m) # header blacklist @@ -52,7 +55,13 @@ add_custom_command( DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/headers.txt DEPENDS ${opencv_hdrs}) -ocv_add_library(${the_module} MODULE ${PYTHON_SOURCE_DIR}/src2/cv2.cpp ${cv2_generated_hdrs}) +set(cv2_custom_hdr "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_custom_headers.h") +file(WRITE ${cv2_custom_hdr} "//user-defined headers\n") +foreach(uh ${opencv_userdef_hdrs}) + file(APPEND ${cv2_custom_hdr} "#include \"${uh}\"\n") +endforeach(uh) + +ocv_add_library(${the_module} MODULE ${PYTHON_SOURCE_DIR}/src2/cv2.cpp ${cv2_generated_hdrs} ${opencv_userdef_hdrs} ${cv2_custom_hdr}) if(APPLE) set_target_properties(${the_module} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") diff --git a/modules/python/src2/cv2.cpp b/modules/python/src2/cv2.cpp index 4b07e60fa4..1c189e7b67 100644 --- a/modules/python/src2/cv2.cpp +++ b/modules/python/src2/cv2.cpp @@ -111,19 +111,6 @@ typedef std::vector > vector_vector_Point2f; typedef std::vector > vector_vector_Point3f; typedef std::vector > vector_vector_DMatch; -#ifdef HAVE_OPENCV_FEATURES2D -typedef SimpleBlobDetector::Params SimpleBlobDetector_Params; -#endif - -#ifdef HAVE_OPENCV_FLANN -typedef cvflann::flann_distance_t cvflann_flann_distance_t; -typedef cvflann::flann_algorithm_t cvflann_flann_algorithm_t; -#endif - -#ifdef HAVE_OPENCV_STITCHING -typedef Stitcher::Status Status; -#endif - static PyObject* failmsgp(const char *fmt, ...) { char str[1000]; @@ -469,14 +456,6 @@ PyObject* pyopencv_from(const bool& value) return PyBool_FromLong(value); } -#ifdef HAVE_OPENCV_STITCHING -template<> -PyObject* pyopencv_from(const Status& value) -{ - return PyInt_FromLong(value); -} -#endif - template<> bool pyopencv_to(PyObject* obj, bool& value, const char* name) { @@ -512,20 +491,6 @@ PyObject* pyopencv_from(const int& value) return PyInt_FromLong(value); } -#ifdef HAVE_OPENCV_FLANN -template<> -PyObject* pyopencv_from(const cvflann_flann_algorithm_t& value) -{ - return PyInt_FromLong(int(value)); -} - -template<> -PyObject* pyopencv_from(const cvflann_flann_distance_t& value) -{ - return PyInt_FromLong(int(value)); -} -#endif - template<> bool pyopencv_to(PyObject* obj, int& value, const char* name) { @@ -1094,62 +1059,6 @@ PyObject* pyopencv_from(const Moments& m) "nu30", m.nu30, "nu21", m.nu21, "nu12", m.nu12, "nu03", m.nu03); } -#ifdef HAVE_OPENCV_FLANN -template<> -bool pyopencv_to(PyObject *o, cv::flann::IndexParams& p, const char *name) -{ - (void)name; - bool ok = true; - PyObject* key = NULL; - PyObject* item = NULL; - Py_ssize_t pos = 0; - - if(PyDict_Check(o)) { - while(PyDict_Next(o, &pos, &key, &item)) { - if( !PyString_Check(key) ) { - ok = false; - break; - } - - String k = PyString_AsString(key); - if( PyString_Check(item) ) - { - const char* value = PyString_AsString(item); - p.setString(k, value); - } - else if( !!PyBool_Check(item) ) - p.setBool(k, item == Py_True); - else if( PyInt_Check(item) ) - { - int value = (int)PyInt_AsLong(item); - if( strcmp(k.c_str(), "algorithm") == 0 ) - p.setAlgorithm(value); - else - p.setInt(k, value); - } - else if( PyFloat_Check(item) ) - { - double value = PyFloat_AsDouble(item); - p.setDouble(k, value); - } - else - { - ok = false; - break; - } - } - } - - return ok && !PyErr_Occurred(); -} - -template<> -bool pyopencv_to(PyObject* obj, cv::flann::SearchParams & value, const char * name) -{ - return pyopencv_to(obj, value, name); -} -#endif - template bool pyopencv_to(PyObject *o, Ptr& p, const char *name) { @@ -1157,45 +1066,7 @@ bool pyopencv_to(PyObject *o, Ptr& p, const char *name) return pyopencv_to(o, *p, name); } -#ifdef HAVE_OPENCV_FLANN -template<> -bool pyopencv_to(PyObject *o, cvflann::flann_distance_t& dist, const char *name) -{ - int d = (int)dist; - bool ok = pyopencv_to(o, d, name); - dist = (cvflann::flann_distance_t)d; - return ok; -} -#endif - - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// TODO: REMOVE used only by ml wrapper - -template<> -bool pyopencv_to(PyObject *obj, CvTermCriteria& dst, const char *name) -{ - (void)name; - if(!obj) - return true; - return PyArg_ParseTuple(obj, "iid", &dst.type, &dst.max_iter, &dst.epsilon) > 0; -} - -template<> -bool pyopencv_to(PyObject* obj, CvSlice& r, const char* name) -{ - (void)name; - if(!obj || obj == Py_None) - return true; - if(PyObject_Size(obj) == 0) - { - r = CV_WHOLE_SEQ; - return true; - } - return PyArg_ParseTuple(obj, "ii", &r.start_index, &r.end_index) > 0; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// +#include "pyopencv_custom_headers.h" static void OnMouse(int event, int x, int y, int flags, void* param) { diff --git a/modules/python/src2/gen2.py b/modules/python/src2/gen2.py index 0175f1e6db..86cde882b7 100755 --- a/modules/python/src2/gen2.py +++ b/modules/python/src2/gen2.py @@ -30,7 +30,7 @@ gen_template_call_constructor = Template("""self->v.reset(new ${cname}${args})"" gen_template_simple_call_constructor_prelude = Template("""self = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type); if(self) """) -gen_template_simple_call_constructor = Template("""self->v = ${cname}${args}""") +gen_template_simple_call_constructor = Template("""new (&(self->v)) ${cname}${args}""") gen_template_parse_args = Template("""const char* keywords[] = { $kw_list, NULL }; if( PyArg_ParseTupleAndKeywords(args, kw, "$fmtspec", (char**)keywords, $parse_arglist)$code_cvt )""") @@ -74,13 +74,14 @@ static PyTypeObject pyopencv_${name}_Type = static void pyopencv_${name}_dealloc(PyObject* self) { + ((pyopencv_${name}_t*)self)->v.${cname}::~${sname}(); PyObject_Del(self); } template<> PyObject* pyopencv_from(const ${cname}& r) { pyopencv_${name}_t *m = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type); - m->v = r; + new (&m->v) ${cname}(r); //Copy constructor return (PyObject*)m; } @@ -258,6 +259,7 @@ class ClassInfo(object): def __init__(self, name, decl=None): self.cname = name.replace(".", "::") self.name = self.wname = normalize_class_name(name) + self.sname = name[name.rfind('.') + 1:] self.ismap = False self.issimple = False self.isalgorithm = False @@ -904,7 +906,7 @@ class PythonWrapperGenerator(object): templ = gen_template_simple_type_decl else: templ = gen_template_type_decl - self.code_types.write(templ.substitute(name=name, wname=classinfo.wname, cname=classinfo.cname, + self.code_types.write(templ.substitute(name=name, wname=classinfo.wname, cname=classinfo.cname, sname=classinfo.sname, cname1=("cv::Algorithm" if classinfo.isalgorithm else classinfo.cname))) # register classes in the same order as they have been declared. diff --git a/modules/stitching/misc/python/pyopencv_stitching.hpp b/modules/stitching/misc/python/pyopencv_stitching.hpp new file mode 100644 index 0000000000..e5d0cd2481 --- /dev/null +++ b/modules/stitching/misc/python/pyopencv_stitching.hpp @@ -0,0 +1,9 @@ +#ifdef HAVE_OPENCV_STITCHING +typedef Stitcher::Status Status; + +template<> +PyObject* pyopencv_from(const Status& value) +{ + return PyInt_FromLong(value); +} +#endif \ No newline at end of file From 4b099e8ade9805c8c8bc6bddf3f824eb905cb22f Mon Sep 17 00:00:00 2001 From: "PkLab.net" Date: Thu, 11 Aug 2016 19:32:29 +0200 Subject: [PATCH 070/178] Fix rho,phi exchange and amend linearPolar & logPolar docs with details and pics. --- modules/imgproc/doc/pics/polar_remap_doc.png | Bin 0 -> 303653 bytes modules/imgproc/doc/pics/polar_remap_doc.svg | 3776 ++++++++++++++++++ modules/imgproc/include/opencv2/imgproc.hpp | 79 +- samples/cpp/polar_transforms.cpp | 15 +- 4 files changed, 3842 insertions(+), 28 deletions(-) create mode 100644 modules/imgproc/doc/pics/polar_remap_doc.png create mode 100644 modules/imgproc/doc/pics/polar_remap_doc.svg diff --git a/modules/imgproc/doc/pics/polar_remap_doc.png b/modules/imgproc/doc/pics/polar_remap_doc.png new file mode 100644 index 0000000000000000000000000000000000000000..e3e4105bb89d600376c7336f84bebe885799e9b1 GIT binary patch literal 303653 zcmZsDbzD|avo&2(igbx|cc-MZDBTUx-SB|4l(fV{cXxMpcXxL;-@*6Z_x|(w6Hz>z zv(N0ASu<4XmtxCs62qA!jPrq*^4-^^w7^ck#-9OCjJ-)?~O_J1OFMtTlEt*t&O{ag%!supXXU)jWz{J?I*?bQH@d-jw^oycP z^3k%hhoaKU>-p@JB%=_OBmy}iV!Bl93N|_n3``ak5*5QkWl4jV<0ew$O*f{PmcmEj za_`^XpC+=fvk_oE@F0@;e2kJ|Nw|633>ce8F#Iks+G{{0X?*fLl+d>1y1V2)qM)EY zJ|6zvn${0p7=c6zi?Girg#w&lD=i8xZ%%g_Je1V>#UTiLb&UVjVYo0heIi1o^0rE2qb>!9rb2E;C1!X zSQt?C^`%xg>5wVp=>DxiNwZZ5!fYs)Cky%GC{b`bt;-vjpSofj{Kc z*~|YP4j7`KFmKDShlqb5#uxr)Vw|$g>$uzX9Ry&WKsfcFC) zVU~v#&&Yayrbj^_AY*D~*8WWS{H!)pfGMp}z42AZ`<(_=LFErGucp;%+EeFaDI0M( z3^Zcni+0~C8A-jKm*=6m*3{1H!^%8aeEo$glJUX8X<01cDg6mZs(%mg%VWMmg(nRs zc)R#Y(6K;wB$M{!!~+}m--?I`=sMl~e}He#*TabTT{0!mGNPgrJoeDh2)Tp~v&dE+ zwy{^{%6!1>?Hv!y~W7ws_(a5RU@Z#C6($Ssn#vKGxeeHGA>vaQy6$5GpFfr}fKY z&-%~i3nM7d|MYhEmhfr!#%nX)w0VB;SSlwCS*(hjcK07tWdk3un%>KWdU%%sQ-%NH1##;)7~Q4`am2X z3X1>^-!tU-=(2UYx}O}~>5R>2XK|vrVmcp1E}NuJUqD*+yBU<7G8OH{P^98Fkt!Y( z?iBN=_Rs0Mjx#dNC&>wGP5R52{&JOX@o#Q?qR81g&e9Ic+l3tx#XZmvd~Jz-c^Nuh zh-F-;Ce){amwLd-v&fhOnUTQRP6AKVN14dg^0b zITDG=|3;AJ2(b&43(Kp!ce9UA(|j{8Eh(uHLROxVodb`+(Ncmuufv*8XP~R?BFAS2 zogLCO%r*WsgHMCi!ykneN&oA`Hn^`%d?{l4PmLUT&gNec?A@;QJui0{EE3R5OvX*` zDztd9sx1dSd&AEstXpkoyF;2#nh-qxfTSHQS^WXS{Wqj(z_s&3lf2FsS2xFZTdTMB zrc|#7^Uamc|To7t9&d#*Qh<875~y!rV}@$nLI$dTB> zAHV$9FJgO086zlfj@Ii5dGicdAj?`@?X~x3BlvxM7_7kPN~;THOfv!gUn(fBK&kabM-c z%X)K4dE$$9cN>5*#hfs=QpfyE_b-kdn5VmIg3j!dUmn|kjhpw4)WCrIX z;|f(uH-I4B=nlExNwPk>xS(;BAQAQdzxejwb6ba66nIUJ9gKT#d(UF)c)+yt^0gfPEZf^9%HeU1DafcT^B96nn~h>znQ(XKB6HvQ zC=o$49E?G^H&J7m&DV;aVfx?qu_<_H!k4Kq|Kygw>wL~!3g)Fxo^cF2ru?dq*Oos?Ir(uYN{x1+hbHyKTlb#P!iIXU?& zL$R^3VG7_DZye+9b_zf3RlPrYH|;Z}wS&X9{HK3Ar4TJ9F`J_Or>tzTGOLu)FEGBz z+KnffOX0%l`{?#{6)HSvxNi;E{Il}K{%JGUS`E&XqZP0WfW`~L2)P%d{p;DQUIsHM z{5ZwRC1%y4kN4+35oj|TJR5^9eBbgFJvwIq2t3LiX(zGi+7zaq{HE{jC;{Y_KIrbw_xXN3D+!$H277udnm5yD$M@CtX7Am-kI}V)A};RFIX01IrtL zGgkAxZ#4maA6rCl!{HMpqgA==$TB~Zo{#M_snN+io=e2N+?%u;v*L5^6qg%7{uS`# z8H}T+tRVm~fW!*$xqGv1DGqwguK=jYJv`dK&XpsB)*$zv zFfx8~Z5|Hhop0hY86lNB9!~I32h;0#v=@*|BQ&^GFF87@)6@2b(e6Fja}n&Z-=S#S`oHpYXj7W``GWy0lpHI^GM z#UqHe%(h37NeVJ_lGrnchZ6W&oEa-QtqkXaF|NRz5wq^s8_QP9Wd+ipus=yj_=T-^ zzZixS*GncN!STHtB7uKb(xFdZwi#tCS5sb3R%8pkA#!T1Ba*Zu`VI9@SDG>Jko?ib zB5D5@RE#E0uYRHqr;aYAf_fG$jKvJeB0@olEpIDpG&lUvf5J!)|mQ8 zXcJjm%(b=13ugD$+jpNVri;Lb6L5F@ArYBtaHQ2*tm&35B%id%SyjnThF6^c33}h{|H(9!Jv$L}c3JEbdS*nk{lJZCAjFLAYDfs;E4~pUP8T&h??Nn6l)7-u7|G`Xn2-UX@mzjNW`PQcai z3P$46u4Rx%#qD_58P-~6vnB11%J?Yvc+afg0TTe`YJW7Jow%7Gukm`}PIWr!yBto8 zRO=Iv7kp-;*QhZZPGsNO*~yqalpGz-zU}ZQkduScbryyq6u9@Rqf8Mh{vN5v5gi%Z z?X2U~FZgnfMu#Q6-SUkD<`bc}aGf~AAEc~pP_xq@6pK$2l9w0$pXgUlIa_=zVHB4% z7_L(MmIr9Z3u~TTwjck%ycc4P^%EH>bfxm3p!@9(*lM|N(o}P~YC)nR%O)eWqjP?& z2$#`nu_t7)=6tWk^J#mInFx|&rQ$eCGJ3AXlh=NCq+6HCTdMnc)k|aS-g!8?h)zbC zRsarqaWr*z1@uzs5JG@JLK6xAk3!^xx3mxoXJF;gfa`-mayps`#GDKU$K=*X$b!Nz zBfVUhFKQY~@Z?R?!>wA6D~}_o+Hb3j9VB$YbRo(<-O=@h<72ZUgU4gDvFtR1?vIKh zr@o}ONm$mAoTQmj9o zF2V(osVqI@d7D0%DnCX=iRhR2;jJ7oDT9vpiFwla{6{F;zcS-$9r;z)zFl4p(URO2 zV*kE2x|Yuv;s6@ONBmyrkXuOUAa?MrDpCk`gGz-?_ZBPOIksAM$+p&^yMS-DmyBzY ztH_cjELMrIis0+0};4V7m&7^nhoFu2?Vtdb~*O0+0M?}^QNQzCP*47nYC#oFiZ%aWlg=2$D{M^a!hn_(Z6w>(Ia^-;Vj@DI2XSL%t-VO76 zsfiqFDkb@Qv+_PA(8y=CijA*vMNASA>4;K8b!P^!Pfw2C`Bn3 zb11(w%{TzSGTf*wE^hx*5PEKINO8J0O*Lk^1&n=LDbk3ibUqe_Jwik_Jm`xgC{`)m z+C}G#rrTGKA_wm*OnaMmcBtMx-&VD{MCyFNNLZ|vt^tlC^f;OR_cp~iABh2PzD zwuBH75mC<5Qg{jru(TQDy8)(9jQiRo<FD%C;C7azeNy2pJODhHUowu4Geo@8-1DJ~hcDS^)k`|p4+fQt@{;PK z=eEv!0NyIBCdisl;4Dz#6O36SO0|bKFlpCj4+q06R$IV8fmg2A3Fmfm)E^IIN^eN$ zFO3NvgBn~z)pECeDH8YM3kKEC&y&{E#!kbaO>3>NWk@!XB;!|6kL3DSO# z+fPa={>O@~p-f3B*|0xRqQWrY*nBFek;pSf9>^sCUR8X=LE;Ozz@iT0ghOuAD(&5| z`4bZ>Hpq*_I+wDN$ug zC^%yrLni2N{iy(@i628kWLJd&GR*fUF~~aN?O7E9OePK*B(S=yvNjPvP|!~9*UHAYVpPtDcCNQs zaA06!cHc)+g0H0f^7yxyD9k8$Z9Z^?ewZs*J2-!N;lX2PnJ7zN&q-=+MI|OC#N^)& zZ%^yd{kD0mRnsYCRRSK2zr65G_6I(Fl^NRZ@YnqCVaU)}Ir7K4at!EEHAb4?Gw>D| zhKk{D7;K4j_I{wR7pMVnIi2VN4`!W#cfje7B9Ee@hG;QcjC)4GuXswb4w918!)C%z z)f^JI=Hr6^lHSltLv`1Ppm%PH8&a`y$g~+bC+94+C3Z$lB&v`?C0Uwg3kYW0&I|iT ze%cpk=;5Ts$*O$(FJHv*I23;+j;r!hPIKT*!@%MqBGGubd=n3d_46|)k-K+$@nFDa zOr)*P=In!g>1%a`F8&6k2|dd$2{?bAg?5|A+5(TSPL=g2hDgAl;@L*P%|Z?Pkto$F zcDO&Fw=GZRFoUkmD2RBvKBo~gg>(eMm?RFHD$&Sr;JZter}fs^ZvN$Qq!G`2-?%*T z^8A?Y^K{`)MY|92aXJ-~JnI;Wp`ip9FYLE?7_whL!(?4Kei(k^`}gY#JCzyJ;D`t; zVq$sqnyaRLuju}s1Xk{@-lU+2Q3`>TF8_D+TvFA#^%z>PPFt%7kc8fi5ci7`2qdB? zGX!^#K~NP}ZpNtiJsTXBno9*V!WD+GKuUKTV8i(fl;%a&E6EXF55f8OBEKXcOswWP zdd;>Yq~rId^4{NyiC63o6>Cr_(qPK-Uw^DL8SPnKCXDXy>Lmur7#rujfgNh~;iTvk z9d(;POl1{A9nw;#h{#}EN|o8Rm|_g&aAJMtWWS4dMqMLqYbk!Grg%X0r#3>~xb8?& zwXK~6+ENATwoxkDwrW@&NJrY!eIOqO4UD}`khj1+`3OQo;qY4#P##R#I#z1RR~S~m zt-Owd?5=Tp@TdJYQlk%Zn{}-Pr};3RlWbB?(FmA3I%UM2*V)cM$I8WpOFE7&T`U9( zU{Ioyk_Lh1%Vj@1p60Y0L80?2d|ICNkq|){KG${{3+0-P^DH{i$(O|%?JA3XNtZf_ zc9{MQ4-bzjhrKnCKvV&UxnrAym|$r561yu?EQtu?NU#qY-=l1qpHegPjQNj*EQsHd}lREWY^h= zd$(j?6%i_$JDILf*w2!1_uTjXBtZb&^anj#2!%^P8t7SK+_L8xQ-R!dK!QI9eFR@o zvaD9_BUz|4UJ#27=D8m$0duyu!zt1r{=}3l22j&kSY#QpOr0>9D{?qpB!NI6xqm!U zO|=-4Z-n%{Dx!rD?!-8vQJe!%=s6p2bS<8Sg!umb8+D8Fj`ocTGUTT}BRYdwgIGBl z_iepBjcBeh#_f-){$IaO@{?eAu z6chnF!%3I5dYwo&wY&s|+uM58i}$UvNp~)*0tA`jTA*K_!$Bx`Y`Q(6xJ~Ch_*>iC zO8x)PR<0PEQ0u@q5qQ@EdT1lBu+{n(Nd=##=IW}SnK0E1S{~-;>v20!MO!X@pKs*!Eh<9d%S;MpNjAVA@RMwYz@;Y#$_u@m5Rh+D^L<93a>Q?h`xv_;T zH%9^~5+JPmZK!pH12lxY(p&y8E+f~3mpieC8Bg)7q9!@;E(k6smI{-^2 z&Esz(D0~RkEg9BU6rHyjx+DxXCwlgi9$75S~7VEEX~=$Q`#reX7|U*##%uXd_0Fl42FvS7)%L&7_TySCbbYn6Z-6=DW;7Q`tAz>ardZMg?4)hj5MNs*ImR5e5 zD*je?l)8J9dvli2QUyKsgl%TT$A@Sr^#d!91y)|Lt#$#>OZz;YJhbujnfAg^ygt-a znc3hk+27B%qUBjkMhGl8@ByMKT_mugV>s-w253e~ySnxK@-l!nLJ=ibAufPN$yR>- zv@}zN5%h3%p6hCV``i8V`UescD?h(FW<6mMz+%ROaf&rovgD+l^Se)qHc;C$ID05; z&KLiBGovfMGm3#CC!HGe-ptMby_uPeJVv$eOC@bu~~OqS|Q<>hJ?3o!$6^eTP*wigMl z_HCa(;ov~{an&}x)k+^Q&rr{hbyf0Ryw-$Pj%S9uiwi`f$i-m)(5cx1$^s^wD=!Fh?lUPrE=v}}a^qwAY#~@%M-k189Tr1S@Zu{vuX9eN zlOOhj$-FYZp1M8P>#nh^`Z>9iQ~1&oPB@qfqN#k>)7y*j zI?M@ckK|-A6(q=@-L;dq7Mte(pUp3^(4{TIHX=f%gyYCmkWCeE!~xbjoY-H6Y|9FK zVYTJu>iBRJfY&0m=nlqKO$yH0U=uq7pG_g@G{LpgrU{@L>k8uo%5Aqx;{YgNQegm? z!!bR*#7en4nvPmiv?A-0-fA*HIwhq@wI-C>)%6Z?lMq#g{AhM;GTKvKK$2fx-hqdZ zB09Ks)hmhHen+<&OTh5)y2bOpRlE5P7;^Q19_gL-VLny^*8M#Y8NxzxX(a_x&y5il zUc%w2BJzB=+dL_;wX#(pg@wgUU?%-58I4!|^9POj44M6jW{Lf8UT;z=$P&`AcV{+o zKLPtfwFy!NDoMwU(KAQVT3I0{aYbr<`SP}8p!h04?~fX(Ojl!l5WM?TXrPZ{#ZrFW z0UMAYqv^!hfFWRfWqRQ1?z=p)Js4lVo8mrKX(C@fTDf(mmvTH4R!*;>-*_rOQKCu$ z_Rg50ex|P6Gj(+is;Eqdsb2La*o{>xOm}w{JgKMj&ZCmw#l)(f0s6!WV_76#r!0d? z?sFRxhzAHT=KbL54 zhn6ye68I7@91mhND;wTk0;+6L@XqABZ4qn@@5`?-4 z-`Q!y(XCF>9igG z{OYPpzx-@Q!}=}xWhfW!&sS2yqY`}MDAMnBf19*^lb5BQ9g8Gs>$qp}L1}A0jAoG# zpV_`J!l0%mAKv@Mm8me?=HrOV-vH@&u$MeDRnT|%jijF|vwqcli>20i*#WCgr}k^%`_mQ| zYIWi}Xm~8#1w{^g!rh_tkyKE|aJ|4v&+DFoaO-^lp><1e{uf`CmX3q&UWq|yG&cRI zJh-QeK_lg&x~^DSqa+8@k>nQ{@Iv^g;Hz)E&Pw0*AO#m>viQAp3B27$EFjlsoV2O8 zy}Kj%{0lKtB096s2do-Jei{T+V*B{VYX7SR5UVhx26I8KdcqsC4*mVoFy5EeAFWnp zM{W>7pa(4l+MU67ay=^Vjt?ZEN0HSgnt776CNyKGX(UvnVKZiZAA+T4Huon> z4*a{==$y`j0bf=Q)hsED&)RyZ8yWYvX5F8LK-6^Rq;gzjRX)BkBa_UEMdqyB$?I5^ zxvTSDE;e?T&ru#$R%R#7oZjuehZl#XDt8Zu(wZ&FDjQzM3+!v_fs2{rd4HKRp=p%~ z43-vHh;8us&&sa2Ro(W&`` zBHx`$aJgd@DH|aeW{N}ntyZT9B??n2HttyOEE2{=ZDIw@c6Et9$fgYKl(y#Nmof$d zlOrPwI*JhgNP6|P)01!{E}Qeux2>0`=cmoP8Q9dK)1L{wH%1IIWyJ089?-+^i#431 zQoVTE%k z$T$;|^@qi^XCYx?(Mi&G8{J|7HB)_GYg(_B(<7=MwlF**hP^1c|-O5=37^?o}tjjL7yV~J&{MYHU zc`oGcsifv#UDsbAU12EDNa%DLAe$5uF4#y|rH;dQmosc(#vUyZ)={9$dcXF?>kD8` z^4D|U^75+JEsVGbT#;V!u)lK+>=3Adz8|B5u{kYt*L|S5qM~T7w-FU$fpHR5D=C$U zS!H_NwPA|efe9R{1;ApYyWavG#m|1uRf6W9_`Y9;&(m0I=$5a!t_zQ|^YQf|G7zq90dthn#4DaMM{N<^Y@f$6Zt?@ zgjUTXox=Za6@)fF|0f=VnI#1q8TqZxY=@&dF`rZ%f(bB~vb{a!TEdk>gU1an7#eyX zGvle{hLWP<`bf<}3`|bt6DTL)gebD+pI2hmdwteXZ|5D`#<>MwvjOHy=xK6w2Zj{4 z%dKlCB|{oOoZ#@)5v6)9{Dvn+E~*Bw3ggdB>~I^bztct1UT zYo=IZtL7S&KqxvXWO_KvPrKR5jV{|#W9puGMu1ZO`_}%gdYh>ttFa99%WbQ2DDEUg zv-bUSL;X+J%V9{^#pm1BMsC{;seaf>pHd%ks_0apP|T}t$j&-ro#lO{Sa#MK#=D_a zs}KfwYHc&6xS@U@Oj_M@{jbuEEBEjN)1c=E%=*J>xi&G&#SI@jC5Kaun)&EIZM*=} zKN3!8!DFAJ2?h=0a~iLP;vRvSp>GqpdJE9|FugO1!qW*HD+g*8%}XtTrgw(TbWPHx zjB}LVnG>Ir$ao@490qP?NvSP4dww96Ys&0f{#P{GM>1kr&{O%RAWY74R`1>WOK%pF z(0sklB%(^(u(@luDP>yJYCI8jJY&!+OKmR2`OVD5ny(Ks?)Qkle?{GHEX1NI1}ZH2 z`{##JnydYgYPleXBodD6VkA4{ZT@{X)lf1X=(hQ% z>gW>wA`pAR6e?5GKCLX=!>5f4Q3v`gPMHxAG5;zp(L((D_iHMvN%G8+0GM|(f7YOS zaeuao8W>7)71y9E`D;Q_NnybkL6xkiC2S9(onH((V|@6IU92o3DhdO7IuB%3S2b`2 zbBpB8SH7cA5a6`=^fNNjsNj8tF^X9TY@oP^@M_Ckb$9FW^sGSgv6BT{r)9+A)x+VU zdPquL9mnrbfQk9x)ryFiU!-b#H-gjywd)-zbO)}HLm<&CDk}{4@FZa<+47v6e7D*P zH{JMnVKig46cpdx0g!Sordxf9lW(DH1cWjp`)BE$osMwAv&Yi`Oz)JG0VbVhqVL~h z9xXVsFBw_Bb2G$ERLcofceZDV1l}=I1blgZC@=g=vQJK!%3EdDEipdsU@?spE9FlE zdKn0Ca$oN~q`A8%xi)ico;Zq^=YbF#r=u#YIBuyq zH#usZ1}wDq0&jIBdPYMM*ZIxk#y?e$XJ-e}YHPrhxjzfd48EE2KTiPgwR!3<-A^_e z`-f$&($rx%>G)rP@S1gLPesZit1W;S^GBhp>DE^W3PPSP`NNrU3?nBWVN6>OtAoQq z5FDDZsw$3IHD1W{Zw8Q;jJ+HxvEXg;M6lX`TWx+$s>JtFyqS=2hHKMnygziJ{&i4v zYvIrumBv<0*UB)J#{O&D*(CJzVO?Eazj`w>GLS|pf)1A$wX+s4M>E+I$_}ry#6-(Z zv*TmxH3rh!OSE7M%eJSArHx+>RJ;2d*Xfc4E^l!CO8q&iyMNUqn;e<3#7c=Nz92b6 z1OuABoScpQ{Ppr)JXU8b>5L4%(=A+G$}`*ncYt6J4I9TXs@4(I6*Dv(-hTpSSlO!GDGs|jYiqyhOCrK0 zV2*VQ4CSF!0oUTYpH?w6qTbAoj*7Z#E*lXfDX7Q$!{9eb2qyr`5Zme(A0L;%8jDsK zgbZgSK_%89kqA%oaN zfDvTpkmeyMb7TK2!(@z%gFIXMLTkLeI#HHCErY|K2*{)m#P?z7EVvV5i9Nek_9tCW zP8wbFCD29$p4mXhOSskQ!-;iVp9P=(>=!DZ3)Nb=xVq}GB>d&HUa@p!+g9b*2r9^d zBST(i!-~0AYk?kMo;_k;Zn$R#d3_WKoXIT1sNm-2PUds1SlbN>La5qCAY+fzkV0Bc zbw|}Qrf>puMzTp2kJq#1@dngxwJ{%?uIco?O+TX?J|YyjT5 zMO>pcqhirEPch5kNOgy!e&9{y$Q`Bhl8(_m254+VML#}yTx?0o%m&mf31xpDZv_zw zJTd)d&^lSOsKr%<^g!E+Z4Ct&pIJL-FNn|oNOX29g8FHGG=R9|21qH93PbMa2U^Vr z7z_$36^H`|-Etwtk9T)Vw)X_!@O2Cd8(?;#o}npwY&*#D`g}lpgbHtshS!zs^=va~ zcE7nH)^&9u4(SSpF~s2e;^khP8C=rlf-F)?1)n)P4jQh;cO-p0S#t9A+P>* z-SuXf4fXM&!Q|n1q72UDgej*pgGnH2_u~|GVyUVR4o#M69ectpgIYoJzBT~sC&IiXZv#$Ba-Sq7^FP0xJqNwcCev$tzu$_sH#Eko z_^keu0D=L+z~^C`7Vyswb_c3=4o>iLj}I)S7lsoBkFnpP$hG7u47&k-P0szMt=!=3 ztaAYBQ<}%L=>Yq!jsi=l_(=j+ZeFHkEmbriQlhWQo?0dSw9GX+3zfetE+H`^Rs@X906BvY50EO;1 zW0_~jK6+3vDq)lBMli)x{*MN<4)ge$TI*FJpt9vnm=xBl?VQLCF49c!Q!X6P(H;2m zH3)x{Z!&8jkh3<6tg5~~@5o89=t>>>NVIomd698d+yx@9y-n%CO*dJFnrK*W(H(N0xPu-Ue zX?fgU5e{f)oxmk?Nd+Gb&<+Urf&@sR8|4D0m%+50GBlcafJYN$TN;F-6?CRXE>3Uq0wpA@27Y&}WSp(VwK$Ku|yig4T3mch`5G<9gfB$$onbU&Y z`hGfE6H--UJ0p}om=P2lPU!iUoi=Mo?^qllv8X`MR%M>X-@lKC~&4UO23E@p#qMT4z;%O%s__h5L) zzaC5lUx#3CV&jJ_ZVv)%!Pk(Wwhcelqu74kZ<8fpY`_JXUF|*zKF4%ybYu4oS63QI z(*P5*rFlLYAt@;&YHI53l~#KbV)ZK1{>Rf)z0;LYJH>D99G_t8(3oNxsev|)W^A&& zoDU6Pu|x3$QvkX9n<=NG=x{NjgZjzTzE@-!_J8LF5h)k{f+zCskh8);9w`2G1Sl4m zZ&ybFt)NT06(!=G{ELBdBUsIRW~pX$6U?)oGZ|@8U7_0!1qBW53J3*p+08xzRZZpm z(4uwgaFTUPzjHOI{uDI9P~pscH;g)-DYIPI&yCtT8%+$^ z>tm*0={Ip#3uFqFnC%Q9+?s#;zhnFpZD6uJkj0B?IkL8yxgD#Lc)1xtO{eJsSy)Yw zs~Z8G3c0Be7xxheVxuMJBb?Kd)d;O@eL$L1R7%lF{7xyP!fX(}OJe9eBjWMAH=V`zjX^ z(amB}0cN-yOl$6kCPnV;ccUu^Mbo@g554s!~p?CGL+M4;NMvq2# zI6T*Ne`7XF^=gWO76(Z+vk{9LjE@e_MMb5hakJX*HurNQfWWP{>+Tqcl?0m8HYHii zSc~O`K{m?+ahJR6dx?$?zHf!GYbnW^j&T!8`HG=9?}ZALQ<|=4s6Su~miy@=ol!F( z1ySi~0DY^Bt!?dUdd-rTRh+4wN%p55?itWSj2SiS`VeYU7W}z?Y(q7MO2cx$^AtL(5V7*tFXdE zTAKcBX=8!sD?p|E8;H_%dVYyfpX-c%uU5d@zP(5hd^)tY(e#?eu$Rm4To zN%pI;uwr1*|5|BIN76dJH;y2xl9MyuNEazmZ%!Op@*2N*b-z(-3Y7|M?Ob02NKw9< zN%OF`N44qt z7hz!rn+_SniyLgerf=-z>?D{Z0+V*^%iUB`&e~9r<-E_e5F8WEw!s&m zw9lS^T!k3+c@D!n-z(E&uu|ZbjEkXDla`Fjx}!@-Ds&Kc*h^a~`1=zO|CyT6XfbH6 z@y5Iina`RROq(6d6ids=q2}l3^WC3&RRw;C23CtrG&~$H-n~l1=%OHikc`o$#Jy_ zeIIh^Ph>D|S9P7r%AuOYaSEF~w(W~aDVjRyFfo`QcoaNf(kvi7nIo%K?$unFNG+Nj ziQ1Mp1mhuAuVQkzyqH>VuQ8D&xvewfwf);4TZeB%!y2rAxkG!jsPbf{e7xwMIZczB zedKhvpSviccDnKcYwu`is46L4$b)-W!0)g(6zJY;GoS)_hbJ@nz*t+WaONM8Nw0`j7!Cu%A%t3E$t0AP7xjb)i!)uy z>I!|$s|)=uKg7Qd4Zk)o*vreyhf)QJL$aSvx8IYB+nlX^fkVcz>9xen$dH8Bm5oL8 zK-8pqETO@a`8)P!H^uxQYH%77m9Rm|qbYbvlNZ=epa8&XjEWV{)W6sg2euFJVmb|{ z$Pnz|TFc3XYHSD|@Iy_n*maG81RgVUFu-2y*YpCY5Wzo#19*h1tCJjffZBE?rHGE! z7Y;Z@(S-t*3me|~#JkvIk_z4pMkvgmydnkeA{coj`ReX-E@%2uhLltA* zkknLS%Y`bv`-^RWMBpy3Kp&wb^k!F}IfMP9c%v02&d%6MFaV8KXSMI-4S;_*zFe!3 z$>QC4?}pA8Fv2>&oJ{}j)4j0X{op(fX<2g&T_Wy_Ej#h+#pu2 z%}n1miKA(``BB!sawR`6j|$jM?`gB{-rhjQmb(r_CI39G>0LrvDa!Y%-XE3*@&EKJ#9SVa5daZjjOVVoii4up&PU*=*(mhg z`#ks}RJ7ggmuIb|47)#Xdy54yHR?$urysMzeY*~7Q}(2vA1f*7LV4PxVho(r@)c&lSaU7gIpH5Z9gaF|3G6l8IjD9 zeT+V`zz10N#?u?xRW(KhqcA+BRCpp&zxFi0Cou1id(i7C)n+fTE^s1~jBHE4(nq;a zf37Tw@^kIt`b2ip=t&I#2daNRU^?(%+S=wIxzcC9C$QKOd=1W$j<*}yj)JCxlH+bv z0&uL+6Q&9>95}fEohe~Z3MaB@We4{rdpD==k0PIcM*u}3Qle2k6a`T7@Zu3Ws>=;k z;@rmAV$OrpVJAF7o#`d&pcU-((0kz^YWkAe}kC>{O0V80(y0~4?rze zxdGF+eJ{|m!4M8AI3UqQ`cpi~{P6NvZ${Otv`_*J%DfHx7l8SWLU=kItN`wr;z>b{ z8cV0C;g%nw;lZ`c7jCQ7gZ&b%`ls4f<_xiSznYp|oyR^!rMQRJ!l9D&trEZKWhyGT z07i<{cqr`)aL(Xn&VWv%1{pY+EpWHyJK&`z93!qX5D8DvWE+dpsY19?;u;gwHfhWt(OUgLVW#$N6NhA20+%aESKX;7!>sP2u%2E(2 zp%hVE3{VpvOo_mn+$+%lfC3J|wr5T_0vh0^rYetXrKDe&&|1fbrHmCWwi}kTv$0>{ zL!pIf(-ee*qQoRr!hF9PA-rpRM%X@lx4uq(nv{Y{DHqcO4mt2ACo2OTDmNWD5#e!1 zF#^i=F1V@_vAB!gO!=HgRrF; zS2dQ>o0}1%kccL0gdj7iJ2Si9%wx0&h@g-%SI z5)!=rOzp3w;}SyibWd?zAlb|UOl0iAEmVyz1DJCFoW4cJLM>xAZZNOIjtna3B|%a- zF04(66lf}S+2RONWGJ>jRwX5|)Jh3?r?ft06CKWE|4B0MwHOh}{{EiWdgJMS=>ubD zd>h5@=oBllOojDrM^A=SBL1hnx$(f;72aWDkfvDn_w>p9z1dRKH(FA!b0g3RECB8d zK#Ave=ZJT^cDOn@mTz>zd`vk6t^rit4})I7PdoU}&jomSKK%iEn*O~UQU}_=C+ZdM z10cciz4dW2W_>&LXmDqv!kKIFhHD??6j&>_#A29RNU3Ws(F!c%l3hpn9i+adDcP|A zjos)bC*RFpX2e9Pjvy2i)LfY!bTozRXIfh6eQ)YtNN3DAV+GSyR+=5BG6>jzP}>e@ zh*ZTBppyW`8Q9|(Ec$`U9ff_ZCet0TvmBsdLUn3{4(aw8&lAu6@t%-Snd#nAp~RoV z`Sx{m1>8HYd5T5=0y~Zzg(T>O8XZbI%ad;(TkXU^vAjvV8!n{RqM7?&di3u7^PC>0_Tq>*=K$;bZmF zZ7Vi#I#hbj0u(Nu9~3&p>S(r94ECexas;vsL47?3g*-!@Q@ifB%Z-q7WPGQfDmGT9 zMuS!C=9eB{I*z0c_fxRJ;mn|FF~EF%%h&A3P6DiheK^S2(aV!vr73)=7YVDnaJ2BGv4eUp$Pr6KVI`ERe}hQcp2!JZt23gC4mxz)q}Zs33yVTnAG2HVW5eFr0pbCz{BM!G;8DtUhqxxX;AOyP$ui{9O~{v7*rUa6^MSENMde5c3}Jq4{| zW$FO)zG!AqeIwub$@i(&<`b2RXShY;eysZ|X?w2Q`axkdUwUu zlQlLk8{6Acb=m>t>2BMb!+*q`YyHFh8^bJEo8$5F-rkruQXw_U5hN{<yxHnTrpwb3%YikXCc&-{+75 zm$x0$Jt#UE8Iy=ORvy-V9=0}H=}s9cF-QwSLBHjp#c}2uLz9k$`ALXtHgr}A~0n(KWVC-U_jilly#^ZPvfmP5T0R>gQU{6raSBO1TTIW?}T^U|zPf~_8p zwAaB^-Km;kdR3PSTK%^#(dF2pz5pxX@*hSdayJEb%;8QS@e@poj+%(2xH!ddHT4-6 zc@VwSdmUhaP0P~nSk#$1b>~i{;2_zHla8YPU8-oGtE_JGN5I)LX%0lD67i$R(2J5O zmO<6$OXJon-c*sFj|C0!>YoowI;PJbdol^#{w!J(Zo;u2RUN^i2Hzk9!_WCu?Q={@ z!Q(v7m6U&%7qb>*kC^iQUW|`x0Z&t_Q0n>Lo||=` zA}V~ zjOZOdfw2L5k{hQ%`N#e*&kH_k6)ymgf=z30qrkVj0D1* zp!RcKDkj!|TD3ir@O0EoPqA*il3^zF{L&}e_#t7Wney-{B|&#^dS>;-sA+Afl=tdG z4WrYhPV@nB>0Ax^6(P&~KU@gW{0D(#FO4*aTqY`=TzC=BD+hOB;5m&;r&(8`)A6P* zn`OhfNsf45=4pvjJMb)3C#FLY!cmHPD_#0AVH-Nm>Y1>ROx8g%Z zN?Sqqsl%PtEs%qW$n`cdemk%EHNI93| zBUMq*_}A<{c<*y!*fVSN+g#mpW=ibI$Lni~yk`+6e-ap?X&ydaNDQZU@=1SPcOMiy z@(hf`{tq7!E-ZwXQWB`SUh&wLn%Hx+^<{N@?&tcfLd#BZvZTv+zxFepy{e&eCuqVG zjQr0+bt}wYIU0)ui_j%iejUEMJ{V?1%4wc3{O8A-CI6X0_2n6VmMrTB1UX~c-b3Ce zRL*B$<{2oF^3?+S0^=DASGGg8%#Sx~7|8@$aVP!!${yiZQ{vm*(TYVZ!ajZRu$ zJYkDP>+2X@FDfFOks3|SHn+IgxTSq{#ix`(0Yec+{nkD7Xu@e4Y4;dnsi{&SllE zTARUYN7=T|3B~Dk*v;B>OCvH)QjvmEq)EXWW+q#A5e7yfnRilBl_4RQM=vL99|a4{ z2yW&54yh4KNdej<2qyuD7xdC=5Ke(IYL0A}T9E5&(G&Kcvqn#(q^L9t6CD@NO`7x6 zFhQ3mIzc(>`@~iTtw~0jdneOpiaOebA&Dqk-%*yM76x94oJPHe>w_>9;B>lzBT1kB z{?I2o=Ur#F>4?W{?dP7hBo6%foxaM8ZF*KoH14P4pkh&}L>bd8XYKDtGw=Rlu=(cq zw)4Iz2aH%gV5RcADd|f13CFBvNwlUpWSXz`-t|B4Jn9&~qdIZxR;8d;P(jJnNfHWr z`RU~WQKXCrS}>w*3IF@NPtb~sMXqb8zzIw?9I1bCymTlCfq5HE!C+^+Xq5*iQ*k1l z-$i0fZWH1p>=WELya4W-@mi&3Qpr?ubv=Aoy|`7ol%*IHrS~xBc=Hp8*{Y|sK771q zXgm0(5AE)~KI6yvS_k$qG#rsy7^{doC4^(kq5EO(<->U9QC41qsdy^E_n|#`a~p-9 z-0cEp{4aPp>)*?%so^lio7@BwGAnR}>SN%lHu)pDi$I$?Qu1tmsZ*2)^}BsT_u+a6 zcM1^%(&4XX1NkcRVg^$W?o0LAln!&8HJH#le$|kIh9QQ)w7SA|T3Dkw0f$DJ{J5}g2PHfu8ul^(m-hD%G`(!n5e?6BN>H*I; zXI54kb-XM;w3D&JK&=cbHSVVuN$o9f`{5}3U)vBuDUB90-=!+}w?q8%BI$?()Qv`suXsOvCr- z=pF>P92qYovjx49#H2?#H=EOxY0S|J`YO)ybbpEmdKo#58oR+* z0tg))HTgtnkLrc~i+EepX<~|rT-JRwBOxKXS5+q<8pFrO|M}}zx!oi`q`tdSh_Ir3 zQ8oU%LPsz*wk2E4=M<6F#5i%Q6hhn0O*YmC?Jx8fdY5Wv<#reXG6&o{&sbTBMK5gK zwtujFsmyi;66>8mRjYw|*bo34{n&s3!+7XD+{1Q96$dEMnSS4e#k`-ETMaVyrgN)( zdL8YvgPr4b@X{k}H9;ooRtgtgqHcxqOAq%IIg02MrW?tX_&ap<;Uqe5O$16(wkBf9 z@aI?FhSMP~uAbFOoUX2}QY!B|8ZmFjo2!#LmW5V$TG8ia_e-lB`i6>M=$;<*@uISi z&iGuPtwQTTySKL&n4``mAds|KFFGUPn{0M*;&PupN7Bb#dj9O$sPdDt@ju(aZ$&a8 zYrlRdsQi>QsDm~pPdy(imms=OTIQeCjA%0W3LyT4PyaR1w?c>RPY?y4FFAL1YF%56 zS@Dao-M#>=`8M1e$HoDtIgyWwR??tZG;`qnizkRr@++O+Zi-rY55i$9+Z1~ejNiW~ z3KEW+@^Jf|yXsY0OV2j?8Q?EG^K#)3Dztln2JUQET}fUfo(B^f>+9?FyRCQF^=t5e z8@0dOrCV-_S;t}Y=5g>8c{yIFr=!FL^@7J7I&;3f(O`uI!_~Rh$g5lJ&R6YtBj~$$5jk$Ab+1Y>_zi4WaH$WYL zr`Vj(Y&97RWud3Z?DwoCdP#kGRdbSNHNyTjKl7`e9{z{aUB?Cn8>s|B6$yi=JEW19 z*FN75J~Sd_2kvvHJjIyDadHYZx`P??`SZetxjBhJ6VXIkR-BZh7RgQVizMtS8`9ZC z5qbDcM}2@j|3#yKpaBe6=30VX{|yz435RFz{-SjFIBZS+$owv=<~YZPlM#Jq^`6wC zQuQ!H*%%%+uJ;{mLTGB6&F{hg2(#^t(><~2J>R|N)wIgh+$|yX9g5YR+nAV)lzK!0 z7HElcV<*k>kbhSCVmfAxl(7h;5=x5LDf=X{0Zeb6Z?Uf1%)(wpAtK@@7Zk93w|r_9{PXMdJ%PEeGN{8}5YB`p<#cis<=T z4&&Do=zv|$53TZ)QeGSGWJbF<^e`40)JiS9Mm^PIpE~(T=u1ne?)n(lr%~R=aLN$V zSzhmcSo=qcWFCj^1FC~mL{Yt{I`D_6(0>e|R zvZnDB|AE)Kf#}v-Lv$1>XAf!SURp^*rp;Zgg&*#^cfX^pH94S9Y#V2F1-_1j=(*L^ zj&iduokm|FgvOmV;F22&Q2|{XZ-xGGn5v1T1(}i6VBS0!G>*)ZEELx+ZSva*5>qGy z4{69;?|0c%Cs~y3N~Q5f+RmhxR9V;FlcEb}q7F2BNPYU%RFlT1i07f+)Xd%v0BUTh ze0Pj@=hosh&tDVtDBw$BcoZgN^fZ9KbU}^W)6PY(U>cl}!qmRngJWnNc5Odzo;gD zjqB3*n*8)`hnNZmgq<@evcC2IwmAA%)}PYzV_F(=Kz(YzrD=CE_vTbBVIZsK*KfAt zJX$6Cor5Y8&rD4jkbu-TF-omg8F1sD$YJmYgqizYo&*lvjHB%x72F)rf9plf{Z0%% zom~0(dhWKMV_r?V6L>dd!e_k?`ZXuGl*)F~e-<*u-r;(rr&AFUv|g2!neCJR%#ei! zd7xUd{Gi>$*q2;{Kd)QGjzH>dlh5(^KaG;jMc+_UQGZ-gx)3Bw_xW2WxHJqZ`6icD z&j4+eMtu<>z|Ed|8l zwO;x94cDIDb3}X5~;JI?0j=yRyvB&v$2t zkbUR0N)(KiXf3B-hj?#XP7 zd?604O~X3YYHaiubFa$)YXs+iLk~zE>OJj#8Lk zcG112o7l{x)jSo3`V7{XHonb&;x8OR$OyX_}Orst=Um*S*69|CjfR}|&JP0{Fv*IqlRkl#5kn^qB$ zWZ^K6_n{@c!FISj7{KdcWDI?vp2y{T>X^!Bvr@9F_>&NcD?xm# zuTb7^`0goZu>Sq@1oK!9OelB;ieEhK+*Z*JDph<)MHfKa4{v!n z_vZr}0|NulL2-fYDdORq@M6WT)-*8&x76SwfNOQqp?_lQZ0Bmj=%&@Y;#Kve*V?Br z&(#bMLH|q7>x&BWo@^;O3?STy7JhhT`EVQ-z^?k)-i}X9j4FAuJ*`{k{_tS6 zkC}%j4h{*Aib~1eo&(^FJopSmVJNqKDOlY->D&oeq(%4k^w0dc+Ge8`_ zV!TuK$vrNtUACStAuM481lykn$+2d+78YLq{kUMm#Mn}m>nN~n>T{kWD^zby%op^j z!KVW5-@>FjI-oVXtQ|45vZ_SjtoWRW@g|TaqP;Z)lMsv!5uai42)ByGI&jh%8M$F( zl%1W;mDZz_!V~&$xbTtllAMQs!XzB?5`7rXUO<-rAJls|zZ*Iaet#TxJ{-3wpdbnv zH(xB|Z2Igl+jzE9sKJUuB`66V5}r%3vN{#!QInbQxV4rl&s2r9@J%rtt)fgs$() z@PHk?{*!CQ4~b7Cvk%(S1aR{#`rfMD0iPQEVxJTEsM%WHrJx73{r8&-GB(?;7=_^= z?>grzkBJ^de1Kq);Da#D$N|PIj5N+l?WTWx00)h|v(>Csk9{PK5`74NzrLAukuWJG zH=ph;T224p1F%I}Rp;AFWRi$bC^uI6sMvP^0@u)B1=ScW66dX;(JfTZ2Ce@7yAC6F zB{HI^B0`yy*y*5lx1at|=DBAa7auR=yo3>qjw_=|gb4J_K`33j@fZ#(pU72&lAgSi zVFo}Wl9F_hPr#Y(=YQT4n-#;r7#B3MLSanpxgUa8atwqA4PJ_I&0H*_k&>-#$8aV@ zcaaHM6d>X$uzUojPgZ2)-Dd7Pj@K~k^O*HRc$|FB&tDz2n*9EdkXf05i|aj%yPamM zaB^eB&)InivV`95WB7LPt@tg0W z0BUc7p(qq&^d{~*On*%m3Tp)2H4gs9I|H=eYGcVu;p^v@BItC#>E>D_%m3W!+6PJ+ zNRn~M$-klIQY8xA+}yl%1ZF5UAb5R|r<|c6DJiKNW@HYxYl?)hZDmYH%I^Cma=ye- zWJDWcs9yH6a{P3ANnVECKmn{iK=$)$s>TU;q{I>J``Q_qVqW{5%<>JswM7!)yHWsp zDrn8wtVW=tT9FG4Jc(DK3mH`-67(LbvSF5qDN%m;v7$mnBYK&VKj{sa;Rz61@^E{f z*drM_jP~~QPX!{fYX*pop>&jmk_?jSJ?_2I9x)RW6T}bFt#xK}S?PW?`Q7ep2k6)l znuS`i@83)6=p<9#Z{qG`blC1|KF?dNbw^rJ?P;5}Q*67UG^2lOfIbOvxU}NMK zI`}B1en$EG!T&Z-I;Xg`2H)#ov)VU!*_%|t3GKgQ!#wxe>3y%c|nWO7LzG_fq)k3|8&MP>()5ZU0s}5Ec|>2YAY^}?WtRj zuDlP|9)s`!69eNTnA{>!2|5O%-XY;K`$GiU#A#yxScW9_85PaKeFIze78&|J;F?}< z%%%&r9HjA=Z5>*%3kWhieLKKF9$cu8>@I9nuUUvU@!f6O8M{LF)zx`~?TjzL3Xjl& z-@sU-=46IzyHVtJgWKl@8fQh3)oYEwh9T6I>58W(ErTL*u-R-DPztZ0VQbI_&E z^~>h0jXxsD=zStkMTxoJ1z- z9LV*|qo%yKXq-E9Ls_yQZKk8U=D81haBhx;0)A2Hh05@z1xHz0kgzUg#(pRHuQr7zdYBbo}GvP$NZ!*Tifv2q4vV z^<$nGMCR1LxQaa96011)@6M{p$zjxa>~Q==9s|OXv9Ynv57!4rFz=R$qConbo68NA z6B;hfW`9Ni%wQ|v`;3la)7ot1ZHm*@_%!L+NGv~5cQC=$Vk(x>6;Nl}tQ|f3 z<_*Q#MAgW%h|xk)$uOLf7bQ;XaVc=;zUdIL0x~&XE(6KifL-T#R!eXWOl=l63R^5I zUEmMN$H$%ScPVnzHR82aut-l`tE(w>XZVD(X&0T9Vv`d@!Qiw|^VP+%>;AreHLm>0 zb}S5yW-66NOR6xi`H)!0-gek8u!peRTn8=syfS`z`z9jB!-ZEG+IWo8*o=%GgjLtg z)Mt4@MD$b66xIEx4~1dP&GkjW^G~;sV61Mo58yGBey))Hl}xThIvEXCH}tAb`B=jh zn(;i)>2D7pdtSJsj2??WlUr-nHo{(*bU;^c@_+g%8~BKjfR=ZT=CHzW%s%yh**zHK zGL<8K{hBIXm`!VFuuz+!D@g#HiL$xLh5+*e_CZ(D4c)smJVPetj$bfg*J%*0ZQg*{ zFPHVu4%oK04CDr6aODkuh2PN;#_$d6b1m#i?b%ugwDiG0EmBg_Ux25c{VRN|lrqq= zmyPa#cmcCR&5EP`5&)5HW(xjKjCu`8d!o{cUFTb1Rw?!6-$HFppt*Qnfn&9b3i>@Z zwulH)P9Eza7SJ|wr6?(7iD&q1*M^Dvo!30{hqs`jT9E8!H#_bmIC@4vjMrQN=Iz5D zA2USJ^rWn2n%w-3t$$>S@ldalW!N+HBp#=EG8Wr+=M>7F`ACZ8)1b{Mp+vt6nf>EQ z158ZrCDNT4vDeATX)&e=3GLY*SzcDN0ZHTGVWU=Iw$BL$$wO<&Vm<%U(=PyTv%fe- zx9BAj!qml3?S)YvIsfK8N&&TJskj zTW@1d@?BPUFD1}#ugSx4wFIjSHU)?wWqReIVpBX7#yC>OO^j+zz%EC^1F6T$mLSS;GvL~b#&ZrCsYr_rQF3wv z-2jMv_7MioodXA6(?8NN?&R?Q-C$a-wB|eb;X3~_nY(*?Dg^)+RW|lW>y{SY5}nw5 z5f8BHdI-#RT*w^>s)wzUa_DngV>tSC5_!4H<+kJgo9-RyRvF4Y$=t<)-iNwxa2;fH zlB0pYQ70M#2&-y=2KX+V?Y2qCJ>w(Q<$&6!NZ0Lc#DQ$7HmE=VrQ)a&rJ;K|eg}K_ z70-CtI8ko~Tk;v)K|tEyWM!en%fAAmgYUT&Rs?C5$-zq3*w#n2$F7z0XvMQX5R+Cq zIz9NIzupm=B=amA`ug$)(yLysA(D|4pg}S;s+uLm3O`5xcdGa*cV$`zWxy6j~2sZB7cLw@3I8kgsRm zoNrIBg8dXOx%lNBfS0ZcTUDAh!8s|1RA2pZY!r?Ja&G>t6zz6GiuavQZ@P)mt1PJ#Ncc_ zKMTkX5Yd`?ZUmS^Dn6s^YT14I9VK(Jr8qz1lhj{0$_mu_?f@}i;YcXa1|fA^Uh4a} zqziJB1V4_NE&&$Rd?;!3H)~BEEt`32eQY#7&98zo7UAAT7^>o8r!N_RRzxJNX({tY z0kyF)da_}<O^%iiqf^x{6pk054?F4*~OaZ(ltY^>3ZkLhOX}x!&gD1u zMIH74MhmEX4rJX5HC?WF?dU>$Ds4#LDCf5tmmLhMkV8ePcMTq)=I=AM*8?B{v=d)wv zBmqC@@}p9${-WCjod&?4&FuUbcp>`Gmqo{U2x zfblglO1Aw*suV`wC!q9h*OIMt3%%=K8|$!Yd!u2?9}0Cbl#juWpH-N*Km~zMxiMi% z$I2S+ee`dB^R$VP*kNJXlJ}= zN{@?!`s-Q&a>e@JPbh%*vwuhqJpoZs+&PNiSEP0or;&|eFvlRz>HiIGy_LtD&=D&^{ zakCJ25vB+L=|bESi=+|z@z<&d&a1$vua9ZuxZ{#nr^{jqGek9{?{DX zlsp>|oPtNytIMH<+R!DJ#EAd-wUHIW=xO-l{EThO>$#5r%fIWFC{wL>;)8VAx+wF4s>P6GZ5 zy83>T7)>VDKVc`c5=l3y?Z&Iybx*ut3Se1PGMTlkvf7u`r!t|$L%`ag2=`?tQX11@_=ock5^)u+}u(qa0VK>0}$xa{4^%4IWbX!Vk{Mdoe z(|iM^F4MDAjW0P}gYY7~`A5IBlwlEn@jK(0)~lTBny8|C@J^GEnP($bmTVvodob+o zd^dT=iRP@dMfuE%vrUBMmviZuy@U=!RcDQh-ZTfinN;Y z#Ky&`z5Gs#fHZ*%fqJ~)d%4$PHQOjQK0Xc@ea^5o0{ky+IHp+ah+*zcAs45Sgxc@Z z7Y$#>QG@QY;} z8m&E1-65NU{IPX5QR$A;BLKGuBm|8PKZUX46S*!n8K(98g1D%Ur?Cff7mZR50W`X8 z2IxJ6-7YgYN?Cw-)id8V4zBDNcZdE~T5;{|^;VU6?93QdK zp;ACx`_qeyLD-b$eX{-R`Sa(WqFetrkpwhR5DndC!)j3>Ekx%&OXIQI(E0(J8RAn? zB$#+%8gPEN{sdm{Se*waz-+KD$=SsP=m(#6u1+c_PU+e10FkoYd=bR3mpf~!0{#@L zGe8Zh=tZ)~V56Wa%JtX@=cudf$#Yx||L~2gPw>7W#=ICXmyCR4!2u!dbq^ZQ>k2g= z=coeCN?HJ!Bgv@bUCUhRlSNwp8UmvLzXvxAwQ0hb>FC)8&Q`#6oLgtpevX{QYu`FNVMZf&b~cITou9bXb=a zC0H8)Oa!G&(G>XXU}w?`fq>Kj`dZUY{o{kh3hyH_*Eyso0aqX7M-#>Kb8}($6K;k5 zv@oFUNk)eGgJ9u827OfFXzA(=4)p?bFLDYh9sX%y67NJ}Z2YlyZc7Loxi$x~`1%=~ zXxF`JV|;@n_WP?QDX<$kY_u_)EG8SpG6Jp-0H$P!|6oQhF!~0_Q#+-Pp%LI22lwc- zS{Icco2kgi6z4~5-tsSE-D@_%6P9xoSJZ#&cDskz-Yzbp97sY;eoSJ-egUZ40ihUy zD*^zR1IFZt<`7_!{%^0IAgI=0+%<5s!xVcPs%7Fmv`XK8LB={^p_gHL74sJm1CMq%A#`z#Clf-xSPSxh0ZdDha<%^u3 zf9u6OY@!p;v$u=&+N35iV>y z0c;2uXnwF+Z1v3-#jK^c>eUYG;Zrf5xbuR7!}CR4@w)8>z$(kU4$KDz2EG}M3d!kH zc`nQ)vS^#4eSG8|Sdm{Pwl7B{oUy?#bA5f`y6G;v)7WXc`iGd!p}{S6Z;?>QjkPox zHdv{?@3&k<)YuML^sfdtG;gC?L2bqAd+B5X%^U(acI*?QQ%cjKjQYjxUFTKth`B@v z`oO)vPn4slSUs117vr@az+sQ7h&t^^{8#!lo~=;w@bDnPP$-g80LRG42xj=|OLWA- z88|Sch2t;KDZ39$0}b6UeI~%Vq8NKpk+~L5_oQ}m^YTbGF9}%yJ&neIT;Y7!MNb*jQ0kwb}5NJ5}4|@U0>;PL`h?)UiW19 z#N8oPO74liKs?9Z^#%6Y1mCUV?{lQRyN+V~X|J;-flZR@B)Tgp*wUh`EG2=Y@3g)Q z=f*^_hCx=PH!@VZ0}(6^@%=uarw=Y1{Z5PoOEJtZPxlZcHkgygf*Ev-#C6qoqyH$( zfxvKsdFvO^Eh1;qSp5M$ar>!c{fy||&dwoc53Yr1I_kjoaZJJSvzclK=|k_)s}F{a zw)2->^hnSXi=ThN7xR%>Sj>?r)_TRy2GqTlzn{=S+0JQPB`o7Xj0%C1cQB8U+e(dq zBw`cyUPxeDScQ<|JvNC~J}W8KU>a)H~Wsd#| zWQp3tefT~Pa3xWERr7IDGTl$ZI+o&u5eFAEH}?|it~>Q3HBKgoWDYmb>ufn`@91j7 zbrTodp+%gOGp>^&-QJ$bQQXFe)h+jOv>CN+Wh3K{nmr zPd_!UC$+>qtrfjX_f+>?1ly&a90pX0Mgos2*3L)oiu;f#F^L~nE;rG9P}E|1uh@7p zql-g@h|e3#OG|S*J7f7Af`T>8cbg@|_J7m+9`p!^0+7O6_dU{O_^T$O+=VPgNJ~5F z?&?JVK$eYJ+ZzNOBG^@!z}VQ{a7?;S(W>vxq)XlmA7Fcr>X4a_iBZ@3=?8N2tB@Uw;i{s?%M5n#-IdeYQ~&GE z(nZH(6&nwF$p;1@THSx};GMRS--p0JB=zfcF8?hAej8BiCw=d zWn0ib1YaA!ZB5Ad=F)FF5vq+#nBb+hG+m)Je|>{p<~dMa=Nt#OArpFjB*aFZey|LN zF&AWAL1=rB()jJN0bb&@9(w!vGs6$pb*Z7M=u{Yry+hFUY)06no;2K;+QEhB%G0XI z^Y@e4ndxZ`Mt7Kjm9cjKev4wbrM&Gkm8*!!f3E>mU{XRW_jQRuo7E^s0^%5ZGsty{ zqtmt|u2pM?jDhVY0qiDlx$1()h-YTr`$^aj=o$`9xABF0M?;$>^m|-i5d6NqMVpVK zNizeb5(4$Jm7VY6=gR|gBpVPjWz}BGEq59*SByXv3O;8S-T->UxV7~In>HeXt^NIk z1n2`!Ak31>joU%NaUW4YQS#e<^f}o+%Lr(?I;I2V{COkiMy1||Ws=9d|seDRc8!^>TAA$ZF# zwkEE59ca4yB#h`D_H?&~S|Fq5^hZ0}E!4Dp1YzR=jErkmGt0?4w?|6}X8n@hOs72C z4`|6j)RjJBj+cTT$}5DZ@LOj7(2VFZ!qd=ja&yOqgxr>iBzp{$ojdi~1!|0}T1CGf z^@*Z1gKiaA8t5QfHUVxzlD45&=-Ajm+VqMQq?`r=&99EEya^QK^DB6>2;7wt=S>|Pcaf)0*Vf1SkJ5^;=>9Z0Em}iK{uq!Z zb`lXViEtI>12784;CHEXQp~z2KIpchMXS&2RlDzdGZQ-+2O`QTGT%9*z*XvN1jCJn z6EX@Ss6uZIwsH4+vm}h>u0DReS6+Ud`il}DAC$-ouwwvGAA!w$wD*zd7v_RUn1<uO}b0Q6$r~PoMA8pIlXPF)}?=gntC5WF?di@?GLavRIbbKm@_{@ zNw412GZ z4}*m~xnSW*-&=W%`C4NWzjskb4Y@zeD_&;{Du=m#c!P~nU^t!h$YMX7vz~VC_L{!C z7u{2#q2-^Lmp$h0ngy-2j~@fGkrRQYaBNOi#{l1xEHFRIKNay75n^WNrQer4qqLh& z%YTTWGkscW*sulz$&`)_#LdV+A!gh6F=aSXS6>IRmQj0qtq8+>E})k?I7l+9;qE&$ z^W|MMVySHwS-Fn?G-&+&t%W^s@@+;jT!mL3 zV!;Xtu>^870le=T)5?<|^j6*SCH+0rsAjs4>vl$JfN30wdlLn^?d{n|FFE`tpQgBN%GsX9)8AjYE`5xW z=P=&d`~4iE~&L;Pe`St;{9^ZFGjq@Pe}SYFEj===vYARqw8pn6p=L)gu7re5d4>Q-_z&wC;#7j$l?rvC1C=e(t-;5+=1G-;1X#34;tj(wv;G~zJ6{W2V#)m~F0 zczJobHd)OHAQ^%-)RQI)ZEa9)OSUJpvEA>!aUE-wC>`7(U8^xcr_9c|LsHYex{NLF zGc!Gd4f*0IeX11o?* zd8LlpsOzmMA$|Z{A|JCuiPtKDp$3pkA0vL~#|NO1#YCDs*+1dL4{iH*gSkJ>* z4BomTUCSf;dz4sSog@GJIW_Sne-y~^goVT01n|5pDx&ji%P~<$?dIzHvM!^gD!KO4 z6xDuWuowq!Wz;*un7B-PxS5b^hCtZ}Qd!WolCn?|FFzT~dwhAQZhnnXVi@4l>110( z>-O)|<wpZxjq{;`TGL=OeNwTSyaTH%4-!j+g}ajUoZ{siX?yZcU^R;@~t!AHZQ7y<{JXb zs4+#=m2{1Y6EC2R78gzDGBSd#qwlP&Y!#omx!?a$gCdVUm!*uXoxwIyRcMo#ieO^Y zi-IjELfS#>3H6p7+!h(tmpe0TELfL9Yo=u^;OnOP!z1P+2qu2NOaRwH5>9bh^A#h^ z$w3wE#l{Q!dfDMxm+1HrBGe%ch0Gsr5sn;IT`f*KCF`jhkif!zNwPZvZ#3(s@#&uo zgh+y(TG;h105pUI1X4;$cM-dJ#Kqw+ZtRbl#Hd1Mg@qAv05cz`oLn6asz764l+0&C zf)?D;ll9RzR)2qFt5`oJArR@SnT2{*c1HqCDLKJ0xyx?SxNLH7c>Qm|@ECEZZ3Ves zso~|{d|W6!R@SQ8%0o`$!w%hi0)u;rACV1J+EXvYDKarG-$H1X^s459+eftl0|F52 zquK*1k>gS9&8C}%-zks0>Myo+M~dX#<=KJ81n5nM$Y7ZcLc?2sZe5(lWZRXL#r&|R zOx`J1!Mjp#)Hm36l;f_1M3hTtM!g5c=>Fy5*v+v zMU{-XKckIYNaLSO3j2Mv^XY$gpcgAhe;<$R2Y2e67TLmF$djAXbxBZRCR$y#9>}BL z3nZ3vEwS7fp#vA%YooMIQ)afV*9xeQA4{wJv>jw3GBSF0{p$-75K`cof7yP|>94WB zt&2eiyO|#6yV%~FZScAMER`tZP>&rkcU|t{REMbs6eu)4-ENd$!1{2tiHiA_^Yc_Z zj|2%3B(Z;oM$q={vOvLSHg!|sF}tU#xxUyT;bG1bZ%Fq+QVv5->fOD!7;YdW7QfOF3pYz&6ZRDjCzZX?meEA9PR`4ot+qY8L5fT zgxYw~olzU3WD&@{anDx752jo)AK8%fiJeeEhZ69B)tNI~gD4cp0qB9GhMqwlGhQ7B z6wN?~_5w0NibR08-%(}D`Ur4xR{jIJo{G`tvGJkp(^{)v(tsd$p37(T{B_3G8rWN z)rz_7Gv1GV7>Mq}hXW=VoCG8!za(zXR5XSS=p`5!LeOb_-@_dTS7%jV&mcj`iVk*I z_ko>8_gG~a)%X3+xO{sv1uXaApo$6t2XeE=vtyJ0;Ulnw~afu-dafkxs_PvVen_YC^CwJJqYje89?FD^b5JzIJS z3yBKaN3X818JN*;J=ZV=Y=f2GzUb%tb4)Cr{S6~oj|rU+y!(877Z;;h+? zGpIElDN~INsbMsK7Row~)%0!Kt=%MwsYUqHFSa)>ap&n}-w@z`Dx3QrooJ6i_hY2C zCP~sSK0R{ybI#8XKjWm1lP1ZXS!}XE%$hmi2h!8422tKz7~#;0j9Amc zA`DqtzXSwX^zYy2_6mB_$?w6MzOL{}U zzV81rx0>&`7=@|t>on@?$xHTf;U|XpRb|c9ukjj-8M!EXI`4Wb>>L01^vz)>UOL2` z04@W9>nGx|Z3-qanTu9dR{AbIeC!545)cyy${C4X!Nt2sIJDy3i!lv@X0Zhe=DXR^}&F^}Z#w*EW>Pnf%Qe%9fz@>1Jap3e1C zd3hWp5tpN3?Fy3)9Pp_UEd`=UFsz^3PindhJztDt&dtq5%qcfY>Z11+JA6#W#G-%3 zQIG1N?@FaI!IF33+s#5KXqNvhU__1}1iCG(g>c4`2U2+aijJswpGq-SWn%UC=K4BW z3GLs8!I&)vSf`ZOhtK8g9Q+h&7O`jVablLARyWH6AUHjc%@AJ8`5-NSXql_dRNM-jdUwP}A z`FoU16xMPW?H`yq7O3aQDGhZ_nbJLtS=w=!TS>ccI_SCjHm=cazVi@2jrTzu;0{y% zZC5oOj)OY?q%r1EM-3-0b=>*cUyNMW78EEwQwc*sKXspz)R1OY)Mf1WS=9ZxPprDOs!uHTm*n6s zP};wzE(pP!?npzXO#g{v?|!dZG3l+T7DaZ6dy^RJ7NrY1+@sqvq#E}^Z;LD-#C zI^Gl@@dp#P-Cx9&Wp>t;klw_2S0Lq^P{vp~g^lK0nqm)Tq!Vi!5>ku3fAItF@#s&c z;(ywdM%@z}TdQ&ccSsKysb?Xh+^XaoInCq<*%gzSOGiOR(#g%g{Sgr#N7njtYB$Tf z5R6KkFce4T=P>7c-D$c2r(mBbh%XjX`YUesXa~1>939u#xmL8};NXB9#%5^(4ls;Ar-Q2_8-3qSV@^T5GAv_b<5kM zQ46DAB#N96M!jxZ0#gwe4F<2h=)BWakB*)W4VQ89#ML|c{WK#`#QGE$tF z6n|l|Q&`%lU}nY$aJZmM4nv#I9ivFbnA_;_)Wp)(RuAZ-sa|zCl@b#XaoJA^%0yFj z5^L+Xz^?1DM!&k%BjB-P=+=C@K!503dLn}yM*L-91l<3}8DaHyz4U?dhvAyp$xuA8 z-b&#U^lFE=_y*CqMLG5dA=@cROhBu<)eH(oMBao@&thIN-bGJ1-KlNT`Aau2p2EC2 z%Mw`Lh@f+G(R8!X`wEkG#D@?9itQat?$|_CWGK8pB)l zog~oV=zk)c?=Qq`yTTm%V5Ntih2{5T8~$`R{D2*_8V}p7F@;;t-^LFk{+~DBWMgpJ zErejDO@aiw52+!Vl4d;6r0xboo|7a0o^423Y zDM?p0qbNp73naL3c(oC4d;f|M23ASNe$VqR7zZ6iL&{1nW$4!xMlUIhS+2Vn&b4Et z#Od=OL`1e6d(q+6vy1W}NXl8^>P>6DU2DQN}i1_cD^ z1}SOj?(XicZ|(d3{@)naaj#w-p0oG!te9)gxe6zuP;Ka3V>&YQUcGVz>nq)`cGR#b zT_Gv*rFy&z^ViY&x*MW4DS3F8=28+{D}2$-&)!OQ8`-Uoh>3`}uStxy902EerorC< z*eQ}PU+x`PdPW=@vo5P$)6`s>|Mn$5(SGAfY+9C@y845sPxA#4dnOI}uipv_b&D-> z%&V>Le(mn3Arg%(Tw7acVrIU_UDV#&NJ9GTJzdP~Y=xn2+C4c9PG35gQD{Af!A^~i zjt% z)2C0!92XYP#h#rx!v!llS;?&2BJK@_ov_Gj)NhY&0P0hv5M>g26@|3xV72gTV4&1L z^Z8g5cS?tvo@Sf0koz%x!E%0V>6Y~sL-)3L(07JnQOqP#y+%(XoRJ^0`GhBhrfR!- zzkXS+7n#NLK){7avd@Dqj}A{^a257(!3SttFPW4zHDv`l8eQ4PGfJ)r0d;dV2a)N%c7!5KmRJR3<=siZpbvND-bEQgFZ{++$!uBEvnSyuG?UT?&Qb zY?fwO2qH&}&~Y7BmQ_2kfoP^13Ou)$*T2@32iF!2Bb zAz`oFdvy(u0t4wzm^e7D*MPzYSPHSS4A9Hb?UxQynG9yX2e)3tIRMvC0u^gJpa!m- z0dPt{p@G=cBku=<--t&JjOO7Nt~+iAC545BAprH{*#hs&SiWuuECRFsd2=10DmyzT zSJjczwB`1BCW>liW}@!u49@f+Slr6ftBxfk$Kuf_a0LWL1V%H^VPy-VF*^R7h=9w? zh8ENC_8zw~gI6l76aV_1L`33??~3t@(?EhNbrsGMqF>l~%5w=rTN^s9ton|R9h~^g z9q#45>-?F)44uCL3^8SR0)e}YNU%_l9{qZHUUh)o8Vb$_%j;}fP=`r#RQ6fRf@#w; zZ`^I#OH@Wi#$)M^w?`vi(uc?nO`muWJeex&mEEPi{P*wQM<_-yad7mY#*bgU`}pJ6 zQS%DC(3bN&cHqjv(Ud*&Jqj8bQAc295JyEmaVanHp|NQu)su`!-m=!DR6N*ZNJ(!F zMV%dQy;0JI;z-&J(q|lA9{JYckrOTsph|E?d)9Knyv#PVRAnY)FHr+-0FX=gA{ULRnh`< zPf)@*MLl}&m!<_@HI!g9BjW?&LXA&3^h4(D+xxCfbfy0O{w=Mo&yWT%c8H*_Wn{nRTN1&LRPjFn@awg7srOP!C8&GG|S78d*GO`Yga;jjF2ZvpHP zPr@|wwxnmMCuL|~>O-o2Svi;k-)7V_^!xXEXgXyL4H-dzOUIaQ^r}|BKtW!tQMPRGM@D?4BImJ~OoPK3(;s>exY_byWy^^!|F-2W z2dpsw^;~-T7G=S(DIyR=v=l#n`~bsIIcStZ)jmf>MfLUfTQ!m!psL$COpMAbX7eW+ z?E)9U!0a^$2Z@P^J-Q8Pxwr~j@QV?)?qaMpK1jynFW~(x4TqKTzETdWK3})!8yMID z7SiELf>&1~sa{JK9#%~NF_F8@;zG!c+pV?#q@D~FwYoeIy#3@TvB4G8uZYD>TAUq4 zg4C7V*DG3BHO^f`xmPjBBqXuccBUbJ^6|H{pkZK;rDs|f^}ezaE|XaeQoy1v7gaK2 zLvL;UwZE%pf4d;B9J*j3Z5tadQcX*=&C0{OwY9ZmxYxiDkr)X$a*sCct55GBMU6$( zF+D(LskymdVTiZW^^Cyb1PE@_jErA~W_fa2z|!#EJ$EE6fg3#~s$dwlEIdT;I@%*J zmIK-m69VZy1{d#Ui7J!G?%v2VlRu4M;!!c%l&m2g!9EZF4U&!;#p?=Ria~;3mT945 zDo*1eEsd2woNhG4bhh1}>EOI?+Q@C~nAA4S zhDu}tT#;-V86y_IL*Y$Z89(y#lXp*;ow1C49+<*Tm-jBm66D;lOHUZYG%}W!5A4Tn zUxz-QfDeJF;MIT-1(5SSaA^dEre2=vV>4O7b*{UvN7MA2JrIJM!1y@2Fh*;UTOKlZatvA(x8ccIy|K7tM^!AsC5#@8JWaZ~t0P ze476b%;fis;l6yjxFMqPiye9gL!&Zyqt_D?=Bw`ksvwa2rtTWhn=ZHd z6yW@yYEZ3hq=X8;^#v5M99%_r zp}as00KO$gw14vKgf#y_<0USNrl4R{_UK1yv2(SM!tFzy<<6#)7{QV_ojIMQABj@D zU3@OQ^o=i7RX1Dwv8g?C@>Fr_n>0o&Fy;GPiK#uGI1srzMximnH`5LS-IdP84k;Xi zH^9e)5^K5+o|)+w)<@b(CSMu>jm_in?$UQO+{)Kaonb|$Vd%mzH^t&PUs0G>)Bvo~0?+J^5M?(yxW1@SkV!l>WPDn)y}Sua2jtb&|A7M# z_rBgk3Ub0*;<=`=y)66j7>SK(#s7OL9QNyhEaM1^G)t zLPCgu9nro&sM86GZ1}sopCOkkEs3@~pwR#OJtBhm z#*J>glofSbTia4i_RpW4XAcWAGW>wQZP`K>VF|KJM<>4I>+p6S@!tPz#1)68s-hz9 z0uvQ#YG)w(lbxS|Y9C_I%9>q<8BfN_DpO8QT48q3PPqW;zaWvjGIn3l zm1jUy{%f8|6SPvvb)P)~_tr;GcD(6r_U2SDlVsHEs>_k1_AVHC>p(!4gMuHt z0Ca0VUu9J<{8D|fpMwm378Bg=Mzqcw>AZUN7lzskx&>lawH>DL)P`1<{OpNj`+c^5o%x{>JpO{%VNOMvC1o4*+E1ZcS@0fF%gBH|-lFWKQ&*5AnDxfq z7eF{*(@I+9J+b(jk+B1I`)_$-%4UNEksILwOn@k2axAU{w8*fqt2Ho5|F=)@q&a88 z(f{G)3F+qA5L!)}+>=_syPga0;@0Uncokj8*Oe!cL>-7$(jei>O!RYORt*%QALABA z*xn>fPiN{ z9ek{mp79T|BH%YSk+$X9vqcxptlz)qIs`Y@3NJi2cZ*aXEtWzp^!le3I3<8>hdzwd zWkwdcSvO_O`Eq)U>2i`k%YYlhUa8ORWS7d6YsmFKKWR}J0(%-3A|kFTgH>8X;^e{B z4s+Mv$yZ(}#!yP-jy{~5w_>Elc){R$v#@) zb0$1o+Kl4xrMY)OWaD%U_~<@3IJKtUTb9io3wu9k&B-5Lao?StRkIuuIKtjkQ=M+v&+uDyd8&OCc5X?8qO^o9*qs4 z;+*`1Hf~yChR*?x=;Aks{*a z*AU2dVBnEeGvNgZc?-1HvNAGwv#Byr)PL^jje&37(qVpl;gWo7W3fl4WIqkHZf1bK z=Z%qg=P+A{qB$QAV&I+aZHmc)Oyyjr4O=f!%<}658i5>=FLJgXU3_bw+lE zTq#|3;dbRf26jN;isu2p9fBuE?m|unQy@j{Mip> z%^e*JaBFAaoY2zE*Jt6l<{9@hBjj_$>qu2q)!)q6*!XBJRE~_#@*Z^W7#I?NwQK?q zr0B+t0DhY618^2>h{Nk)QYvSPE&x&~;^z zbT@}NS*OWw8q$o1zntfqZ?x%KXJXX><8Ebj75X6KgAuqlWiU2qZf>4Jux4=J0d@Iy zJMU!d32)audV24zElastH+RIa44hC<@;W-5=md{N{tuQ!b{BZxHlL~^5H@`!4V(D1 zz`(~y_Dg&KfFB@+Yye-lvYme{4uHrl!;-$3mTH*F5&4cQ|35B3p3U+rU~>#EL;`-q z2kpei<)0Cy5dM)i5hSw&{FYPh3we@wB36$fKixK&P5sUt7hZbw8E1*=miU)yVL+i^ zdG2Q@YN0)Q4seNh3b^tF)au@YIpD~Noqi}rT?}moXo}j zvW#>V0#Eg>Y<<-ZUy+1x532frWXA8`3(wpZfT&L;B_&n5S#^p!B$|S4vbQ4ovw^Ic zoO~aKpdC$AZf#|b1k7livd)^@mpJ4vd7wR!e%5<`tRT0xOGds z+Vva-wA4!(xCkX%&G)r~a?64R&xN;2ck!R}`Zh8O`Mz1i^)6(Yt-wY3w8vMZ9hY!pS_nfnX&jaFF ziGZNIG0HC-DzV|x8xkKJdIRRBSB$R!Ls3Vw?ay_pImpXR`UPkY-u%S?eOxE>>oQ=< z!Z&nd zFT3gv`$w^{v5)GgF1qIa^z|vd8fDt30xk%W?!gvm#FY14Ga=Z_n!yQ10y=WI&_Mcw zsLpUW{^YhSkOLkBMB2e!TNRaCFM=q$H3{vgwXJFv@av(uB`_!Ni9| z>_1x@dU|94Nq_q-O!4wS*Fe9x38V)I;akwY!XbeIZFZ-XV-enHT4CXLpz1|Jd_=GA zTj|Y!pTnIBhPEzayci&++G)$JV7D_5z;8QuCPA1B&vdl%06EnF6G}jxxUkLLv7-U? z6a>hh85yvh;7d{1$s0IY)*bvlz;1_WPw(3pKR;{){RF+KDAdTA>m!f!8gY@A1iJf- z745Xi(gG`p*3d04f?3&LL#~k6*fy}hisZ9O?!zaMfrIJ5^?=ZQDLPfMb+E*|VZ~%Z)mS1*N{i;4FpNxIHJYfDVX)QkBwUy78^wi8;Diy{Qjg%aT3UCm zUcCyc4*&->#?0)1SAt;ma|;Xb_u-aC+znbB?$Ea2Y3D=61JGb_h9BXbfFHI20F7A(;MgrI_aV2qIQ;8Z!i&8$ zVeVlzUVeUZ08e0Y0O1Zb=34=3t=+-ui!cOQ`Sa&70DO7$`=}zI*9k-OE`Jy^~`Caq+KT^YO@yr4+@dymwrEIp4*Ic7nM$A4mncU z2qW(%xDHTnOe0>ZP_-;TX<^z!&&nDAv!_tt*uGL#{n9$0oS5hiZ6_3`f7J})`jg7t znsf}nE)K>gXc4Vq;EyMKzDEqG`On;3LjML)ctCI=&%j{9JOra~*c7pI0Dla*olSsf zDfvHOxbN-l(eLAE0Cd&*?;m0e_$Vq@l@&f9T!=;pxO`9yYmEI=gZM@a@oo7586yGa zz5MK;FXaMKx5F`TlEgZLNHj&Vic`ORyQ5S55Hwzr$47brc#1Q3K7E?{;P9Ed->`mu z(Z~3K?(fXHDa)_9`gjW~#;%XwNPYrd?17ihX%b_Xd0D8yO-d=b>Q$^H3%2%hYyyjX zO{U^E5d)%?&Jq!-`L9<;OEx8oUXyqsPb5G85kTNTAhZZobIgkCjfa>GhH_5<^%~T) zmhtyxbBEw)1y#SIyu1kfDqPn1i{KoqAvKUmf?D)#SK?Dma7u#qz5otb)#Zf~h?eOHfj`A%2 z*vJi%clDFidU8>0H*fxMKB5+n!AooS+ubXdru&bCSy3_1$8&1yu*tAs`n8sfrRx){ zNtYLA(cENNDkm3boHr`$6`$A``ZR)FS7l(!4?;@Qg zKLipRgkt>gKL7)uj(B>>&Vmks)=*Y1ia@gii-KX;`TY8ezrP;HM&G@AR~U_JCW%ys zk9Q6lq`H2FwRhwZfieDyiuJMa;v4dVIzo%=!CAtRgWrb;$%YrDqEuD|{Xea$@5 zh{G{0J`UBVSy(pvH0EdWm6Y+I)^{__LwV61Om}#28cnZ)}l4l;HLIvPC0Y zU3Kowz0M1);)o3*sFbj~sgV*5Cg{jUVaQleWg=dj%>X&yzyBEk*L>*cz@;Cz1|*!v zz;6Syf`!x=^PN3w&{89FLkqXlQN_D3OMHbcU)VhOwxu!7U4!}6*Pd$OgbAzb=c3QB z9>xe^?M8dY{UuORvK;ig`8#C%vlCsM((8@;6gakajoD_!UGlN?#2K|BeFy8&9aya$ z;@o8NH@!~M)A56!ehFWjr22PpF7Q!_?l~zI!C}@+yXcpJW%mD&L(?I`R#5sdxJ;1h zIMzoVMX72oVM0+!YlS#gn_ke(L}VZa-u^ypHE~9mdUPP|r?* zf53X*rt}x_s$0@L^eDMlG%|3OAlR&IGIBW~H04n=D^O6-kqc}WPi%SqHG#^=<#fkw zP_xc@P>VtE?V+fU)3roz+9#!)7k6yAXwVzx|ElVAZbj(Ozdba^W{~~yq3fPK+Tyjw z6UWau*k81&<3C*w0u~x6DZk&IX~4bvI1)H6XqKDJ zG2jFNV|DTex+v7sr%z*njfr3s;9lqf#Z@dkuP5iP{|;%-S)U3+D^&Jbz2itp z_o-Z)UsS}H6Xe^hs-UiU`xMN5#woSzx`&hs+b~+o2bT|XvZ5}J_(}{_y{=niL)(dX zx`XY!*1$HiQfEzMj5IcR2&H>knM!7bxPPzjui{&p?6DUY5Fm0LI$~wZs-Vgdk4_jF zuwCc#B)qejiNFP3mZPA?>U_M5i&P9S<%yrwxE(?OlX}3U78grO(VAgSf`yL{McEB1 zs!1ljPzv{CZa9?#QDd`seA6ER9|7z@EEc%a%vNBLMWx}@y`up=B zADP1}ncmEd=eBe>>onkeb3Y@rXJB7Df_-cTSv=i)g?#>#G6UB5NEA5S!1S@y z_VC-`q``uk0Z<#B0^31MY$W0cXR;rT)A(6mv4V{A;|hyE-^THHIX%XMfMGqqxagY9 z0^zJzm6d{_0Kw%%3uW#9d$3(FK=fpY|M+NH})=S>(|%+_qe%fQRs4fRlpPg$ul3#lX$$V zSIrKlEd|uT2BZ48-Gc0ib15y#2}=^ybNqDFSJTzC^h`jTQXRNo)>XF(vARv(8}JIN zD4_lN70*#eK#7XU8e~Ap(dPZ=DgYQ986CiLLj1$kO`%JD_vCbqGv0Ye63{|91%(>` z+B5pis4@S}U`EIo2+swWq$o|8rk!mEyUqPdi=Tn=9QX-`{-Jc-C@~YLD)(5?4i0_l zpLcE(RGo)IyQUp05QZi9_)}4mxv4)hb1wH|d2A{HkkqQ1lir=!Ij``#=-N4CI=7WW z_$v1Z$%YD~sj;b_%Pnl?YhOdr(4bpz0TEvsFjq!^jId%_zN_##V1c5^Zz5N6G-Y$dsH`(agq%=^Al zt5T(~p6-;SqUxNrweZbJwmthZRdu>^TQN86M579Ncp>|8W&ldt+|h9|X7MzPOX$UN zA5RSRj0R#>;lF9iT&Su5U}=L7(`)WjFg#}JV5vLB;ZG(*ujnsX1@M85bFOG%Eu^!P zMsoLqRP>B|_2c~zI%h|)nIU`l8A%`Yv-+4<5UvvVAG=zkhG4-b{1~LLMi=(0Q%p{1B!gO{P2t;o)}2kzP;s z*2vw>SRI7p7nrK!YIIA8l~lhNKaeM;3O4@kt^nB5-$@<4uGG-?w;^?sYq6tZ9VKC` z!1SCG<^qTnyrN=VEWh=bV9*Kb|MJ1RS^9en9Vk;U4`YUbLUR!tD^q)Wd&B&PH(XKa z)_g~nha2p7GP@#>Dx?sbLV&Xoce22T8Zd3gDOB;4F1}2Z=thoPUIg?Xc*5BI>pcnMlC7|E6**d1ky8(Q)P?6Dh0Z~yI53@n(dO!R)gDtH z>w%h8-oGV^wQs$i@;|U4{V^vZ;$nbDn%Uwht&qz{Nv4&p7|pGtuJCj@=~)~P{q${{ zosUKShOWk=+xL2>EGdl8lHr_|Xt=Thr5(;U*)2DYSHZ$3`RrV^QG~eIvr_GC|UGgMY z68(}rFNs<)MGir7NoMv0Y;LaZ0CP5Ep-ZJutm1uclv9p*ARU`ZWEqKe1(sAwjlLZf zN8snc*{QVd4Gi5LG>J~nTBq?=Z@G{SDSga@E)yd6;DYjfyUoJ!z}9!hyoNZ;%%WBT zRwt(gyFr5K=0oOAu-faP{)O|Iu`wUtdp|*4ba|2kO*bKQmESc}mW1VQ)r}TXd*Y{u zK0s+myJfmQaucg&XPzm|=3=S)1v#I5u{Y@iaa2^xl>LZnitC^D*9;XNJaKcxo`h_i z<(iD82A97CULtpG?>=y=V0IHKuz0#T3nb%u#Xs>>wzfsFb|Vxpe_RTEaye$b3#P6P zALi2%l7|Zz&b~L!wbIL+MCRs(@Qi|E0p0iTM%&&mj#bSs1zn0uN-*ptZs*XIU8ad@ zlzgUtby%CHYe_zKiEc?zV`O!CIHA-mX~lq!ZcJ@P8gQa!y)H5y)<*awX^|dP;UE^N zBZKGH>x->g_xEv=+4MAHh97jtfnN+i1kIL~lQ*7pWMbWOOpT`4Wr{N>xh-f@MF?c~ z7os0u8yoNHO;3M~!&|aH(6I-Cs-c3GRy)9*O*FxeKlCi#6|^(X(@o_3Lee;6Ibgju z#AHhyG`p$u%+m7b;;Jw4W$VE@ar*DIS$_Qo&H1ugJuT~!3d#ZOq|8%oE!&jUy7id) z6Rv_ejM$kl608WF-KaLpNH;vbU^`z<6J}fFUV@jH*2sMsOztsPKF8#GLqVFsE z{Gkx9e30!R$P9dRouLSQ(-X@_Bi1XefhIV%;RroxjC1+{f5c*;8@S)RAmwzlu}a$? zjEAwrU5B|F;D$VJUZLOG$aDP9@Qg@Vh(PT4z4wB{V*eGQ3j6Tpw#q$8i%O+uPI*5J zt|fjOFuy9(uc5mvqg!|bE5O%H!Z;d@eBVxVfdf4@B z?n>r$Jmdd8Jt-Np|2;im*>el$uW@6EbY8C^jtsy~$tLfgZdE3r{4!(nwosjXd#CmJ zs}oaJ1{V@=ep@PDHTTb?e(!*NH54aT zT(x4oJWeu)8x<(d($V-nDOuXagjLPr)1ZF2$pwGllz}}1T8h+dB3CDFj$O0Bw2Mis zCbnCLo89{~FNjQe3Ya;9_m7V$&EKz>!?XZWX?lif`k=<%7)GLa+d(^a^f=vO_-rr~*-VOv7+!3{KLe2;4 zWBAuP$fHq+nF_80_B!ocgmnBtc0cPipJZPm8|%bUZw^Kn@#L23Uitt zm;&Ouvo@1js%cuWc=vZwQa~Ipfk)jZxZqRlnCm;cdb@hT4&l!K(boWZjr+|^B3jrM zbXpgX(CgbWzjN_Q7ZO_s$m%e} zFIbo;&wv2!Mey6-IZf}mW-xJoFf;kWjrMyH+}K^4ST`TS{KtV4-^Zy#4wwYMS$X~<;Vk=4+P@o9x|`fi~`XN37(cm_0QSKxW43VZy!NER}RxHAQw|0 z3;XVwkpWbhmG{KIv{MWiQ0HAFg=$%G#D!>yjNkF@NWoEU*UktGd=FNfL;QoFUWmg6 z{cgZwJPjmSk~CtE@rmCubFk!9qmrUwnf5Thb;zlmJ3WnWG_9&CZka#O@!*c!m%B;$ z_E#R%m=C_Vg4{ov|M-Han_|;Q*^=zfzB2G|E+IkglH-)Pnmzt6me;uBdQguZo`~D! zqu&FTO3L9(lyYxdii^TgxVX3&iGQl%_pe_4&A~V|yuXSjflXlG{PuomXh>xA_ve?n z4^~V}fC8kNRi!ql82dQx4BP%jAPe=%YTU?egsi13;rhftcnj57E}jBC;5Ja0wuXMMp}ctvE54EHC+)AEL&RzD5$eRP*+7? zfuc%-wH{_TSiOJzuy>f5KRPwx+ryfpow{?7Z)Sz zwm=>LWUDrPrIc^r6T>H9Oj7)naE+RpY|ZX0BNK~}J#})W-xIV65Luez1bqR%1+?e! zvWYSN$UECW!t%jL6t3xXo&RfqZfs_t?}S168{rKLz0PiFj@EVE^rahJ9L!Z4@D2Wl2piBcy?qS1Rajsq3Vn#EKI-7U zkRUK|v<-`-&KaR;PY2@{EM^;y>lw0AZ_h*JW(o`MGR?~*$ij(<<#*yqJ#jp7JAR*o z3FP7|lUR?bO+8Me%hv)AZd>5oa`WpyiW-8&aNzK`cCfv6QD;s+!TIg%*KwcNV3FHr z{H45WiB8vasVoSd@zRF((f_7?V?U$v7{n8a85l>$NvQSlD0VRCfrR)1$Plk_6_>u! zqKq^VB1tmMl_1L6_m7e&0_QYc9b(WlQt}JAjDd(hUY(FQ8_p9K5KS=&yyvB&{DK&& z%yjoYrOpW3<70UpId^S@2gPIq9euI+_{iEvAhxXz<{Sb|H(TzG1L?fgh@0%};&s=J zgVh9VmjTpcDJ`vl5}%~oMAF8@6S?n7?%zY5?C(+%eDM=iAX#`BU7r98;4j{{9-Z<| z7Or=!?EXJ4z?fv+c?l|dulwvRC_1V&mUGT)rQODRbXbrR5^e@(qr~bOMk3S}bxHgv z#aLOGTA(bs)->(%S5~;HeEvrmQZN2}oY$vRdY}&9!Qv0v>EUYHe+|xc08@QNr1}YSiCIMr z(8bE$DsbS8c$v^a*PGUB(a)R{@D#d3Y1_B=p%U!Yr`aF3mpopgkrT1I-!Ok4(96d5 z_`q&sF>VT`mS(=6t0yDChEVZg`Z*3)uw1w%LzA2_}B8ap8 zf~JF?ILUk7EX-Ri-PEPvn2AP4_K_s5_j5nR!g|sY=t4(40Y=IkQN15G{^@;k^5V)c zC(5IUJ2SnjsEj1cR4V$oX2Y|NnWwZ|K(mE^0zf3GqVMh4={R1=AiMj zfFdFMeq>3h>-h=$9ghU*S~+F1oq?|l9L!%Gr0LTt9Vk*MTsqmhHSlV>x->H~LMnxD z$3a5jas#;X`HGr5td1Nm)zbD#UyJqQw)=Q!IfA?0j&b}HPl*WiT!gNr5i5UV+D%@K zwN?36;&adOM!&A^XyxH6Af)1+Ora;+t<}8eg0%<#br*@Hnq=Ud^X3i7%lMZY7Hg8ADvyX_nqW>DY}LfKS{0le;bpV8-)*Tcq;o* z-{-5@Lg9-Aa-vwcO+)V2Z^M1gy`3-;{afWsTIxaEU*c6oHWg;iTjt&~Sl)qMDjy0*H>CD0@s8Fez(Uy9*cK=&}%bbImh|?jY!IN%tKZ)2h~&gfH4ZY zJ09SdHJ~hJBqvggv1Gs%N!*tFoi{D>5|i5TzOq7kpl=cneQImAf(nq^H5mYsO16b3 zkm59rK`^y<@33{}Y zQ)jj~3|O+1MJztDS(bM_a}&1vrz#K=Z;YbA<@x(JpNU2K@Ic-M3Wo)CDO5D>wF`hN z|G-r~lWxr}NPfLC{2yO{TkhEGnT#f-c+BZFBOJWym~Maus1xg^RjNN^#lK6@M4#}v`$cvz=&7M zV{XR`nB5d1^*SYfRAuIMz@Cf0qXO{o^;c>>;g-%3UCd{F!Wv)w-$%*JpyZ2V7N7k! zC|XCuN0n&7%?d`F|7~iZF6u4&#z)pd%CX}Gw{TWxIQB$Ozc@nqoDR=U;1wV zwPdD#6o$i!O?y%Ck*HdVcFB@ZaC2yQ<`;XY|2XeD{dzywKvnLoeozID1@0-K=gK9R zeg7V?cklqCiX8c1FAa~zH(&=O;v5RK8LJ?gzdjtxE`nUt`tJaF({ULU@xCKD=K-v+fVwI^ofC* zD#kIdvm$qPxLuzU$lz?j2k-AiBjuaR_ookENAsT#_qLQj@h@LW+lUn>Qho%Gvxq*F0HmypX-$JqjrQ z6bww0xTGX~v+AB|)Rrxl+rQ6bBj3>ZVk_+{{NFH z@MWtgU`<^~h8aw`Cf{x283!OcB$N7$kc+KU{Gxoa`ao^aKtUjxq<^cG^;hZUESaDi ztBJO1uc>HXc8vYQjc-;Yvds0jk`pkBw2e{MFi42WK7QZ%a2(T*4)|-kEQ5=Qu_fxo zlapra$JCEPL<-0&>OS4UJUC>inM|lKFZ~qtS|{*|b9`KTg`oY8vN?MR9#zLPQk^#C z*IEr=`q6cARZ&r+$}M5Z^R#SlFz~!RF4Ljhc2fcsUOf3bz4>3_(@%HGl_2z!$VMiX zxoAyRQJ(eZ2-wI#4cG3>h72~^vA(0ZD1|kb3k2Eq;0NEipZ8JVUG!CyTLgF_U>zdZqqM{7Uj24DD7atoOw?(naNY>6+66$loMh@ZTwz+?W zTmgP4@?3QCHd zsqwzolQ=iOXVi8Utk&_7b$^80Q|KzavWK!=?K`Wf6Fl3oJj0JV@P=L+qv+|)Q!|Wz zmDCZAi>tFojg4T795an7Dk>@{hoP61{jr)tUBYCAu*~>o_4$cOY=()uYDK?PVgeP~ zHS`-#pMtm+Xj4AN#F!Qo=QJp8db55=^mfowZ!v|1QB+%=HfMko{8K+#uazxo;iDiK z7?1`S`DGAB5li+g&=M8X>zZ=+#CEqOB~T^LBx5VNTmrp@ng_c|M`R)TrQPFly~vaU zEo$m842;6AKCbc6q%Y<)Y!Qzq&^{WMi~|kEQXo!gU_exp5~W`e=Qp4NY&;8FZsE&0 z;wnKi3gNbY_nBxhl$C#?TLzHBN2GyLc7?-pt14qdxXIqF zWgF~a8_4ucALdUH;CyNG|FJb9I#8V-pLJOfmf!l%@?>9F=%}6Nc_hfFrqZ)2^vnk>t$Mf6_KI?xREHUVo3ktZ{_sA!9hqZvi3y6?4_Kzv zx`!K+j%?Su2PInRnqppxOybu7v2gH9)rflYzqiP`r#~A4rm_s!@s|L8HRHMt!au{0|1ZJ}{eEPJ*C5}lg{<%^7c3fQ0r`s!AQEA2SevdV;C(ebu z4PdECC99SdM*YS48@1EPRKF42&}D?Ws@|i)cjA%K*PgRlU{Tk0ZRFKRWT82c*CY$& zMwipJ9bS#qY}L<9mRq4lJGlvh%qy4|7c%J?RNUM+*DI@K4eFNnc17Mza1&X#%%;q; z$d25)dpAfs=S5m?-f>pRk+dv+MP^2`>`M%htLE{X*WD`PD=yA0LPVc+GhqYAq3#mR z^L5|_ZUa?Uu6t}oxrzlb+?_{;*~3Iw&7w}C0c1@Tn6Kn0vZj@BeTRzM7CTf6%`UC=z6tWL z^4nMz@v$>t8&ZY^{A?Gq^JiuNYE4@)M zE-UqlXz*p+zl&%J^N*J<7q)wh`Z0m&H6rFM9oIBz0HR0&(O&}Rmu}NNd(>wV3m8f( zNLaUrlXW&yds=cN+(yF;k;X==Uk|F|YN$_LV(;Yu1JKH9HFkV0)UFapb z3P&S{GbwaOy0zsaXC010!c;qjds5Oo#`V{)v?`lf7IV@|34Oppz{qdGg+%QA!0$BJ zMp5Ft-JpSSeK6#EVYi0@e)YFV=>y)YrFnVZq}j_nfn`y(>#wu*H(RSvBkPat65;FW zbDn8%@Of`h)pA-^cDDT&M=d(!v#bImGxN$N?b|+zb4B;su);V2$ttR74iwzPKeD@u z8dPBVP#^hPzRO-i8t2E){Sl?Bk->Lpsw(3MGsEmstUk^N61UKKCEALzyzzQ-K5)iq zL-F86bc<%FWJANvq0eTO6C6iR(MZqEuH47IZzyR(p8eHnTOY4RGIT&e#qMgxN@dRE zn>S)guQ>+Bv~x-l2Q`e0B%dkobMea2J+QQ4BYW8Mp#@bDHxz_#>L)t>y(+FutES26 zP}IpOXPsv%^URrk)bwnBA;u~L`l!B)i5%Q9AA9=?c4Fo_%rHj&jg=7%^oq2;T85DzYAh}A#pvHtgOma z0&%fBZ+d*8q`Uv72mCHYMSAPSC*m5Tv>~C@Z%+@J9`BXR-GMOu z(!}&RnqNw?W$cH|H3j*u%kx`Duo-9qA9pSzGy6U?0soj3PsTj1TmPA;-LFh&-S%Gp zh@Jf^7@gv_qWf$icPN-PQi})myb2sNrE-ADbyxO-fBmxyoW1T~)Otl(Vc352$yxbX z>0GLG=~1eG)WwcX+c$l?Gpp-5)d$=!%%6PbZX4OWn2-3L!bcLq!+>W!HxU+ofdBL7 z>$gSTho-xSyjC6jheUVc>Lw}=!N!TIYnfHZOkIQFTS9egWaRmeAI?u5j>SxecS!Jk z+~k_3to&wZSyshT<=njf{JDL6Fe>~?-SMhp<;@Bql>63}sFLyvlT}})k=e#|kkSdu ztA1n?w7&>q(}=(KAUDXUS9{e61YGD`Ty5gYZ<>Od3@xZOTdFhO@WSCU!ox$&H8$cK zU4p;HRtnYm7Z5OaR9-k1e-A6;eEjfAK;R8`tdZ#cKGh{Ct0~uLZa#sj{$A$K2H9sG zW>el%oXD7e}DH}Ki{bp5U_tSYFp>!_&_Xbc>!1+fX)c^aeaLWfI0b~YdW-9PB=iHQ_v zX95qRUZGhE;9*?tM}3Vr)EgP0w{i1Ux_>|DK;VV?h+uuwrv7Z>V(zF1>b1{gOD3L= z4{6Utd_di_`j>{u>Zsv@gw*sU3U&1!GnV(Y>zN->iQfP_Owx zz0w5R&b)2->YRtw|8&qK^R?Npz2~GM}XPU2memWspgSVXBcM@vqG^N5=BrU2(jcy}c49rZOVf zebP5;HETym9wjZ?(dk(11s@hpc0Yw(Pw{>DY6mtKAaCdD>i#ygJ2F`fo5?REwI_m| z1THmC@2)Pt#K6R1`BAiAzgl0Ax%6cPJmC9+*3E?D^hCF8b>sO; zA(WGnLV&{NG`P4bT#ZkOPlJayY&x>{G6%n@8_9MX6ljc%*?HY)m>v=%|C3gf>osvb zDcVnh3!bF)v@mn(mH46I^#s_NNrrZDGFY8&(0Lc!WxQn5Qa~MnklheY`sBqyNqvJ6 ztKlyNRVy-o*8C zx1F?$OyuD5UBTf+Wn@ZQt)Dr*T08rPb>;m z2obtnhHIPE{grC&ytL{pPD~up=0>aKrXyS84jVKFLbK^J1v3D+a;@}HW~RMUcI7&I~nYtQR3y|88I~OQ7u%PCAFjWw6I#Tp$zhWhNcfd zksu{06yTVI#Kg~>ot<;cU}yOlaJz?0d6=1*J2o(w+gy!#wDPh$o}|@EHi+GH5x7LP zb?fiA#=cl+jdGc=Cc86tP8;0D9mUv@WG{i=XxWeAB5Qk@aKZcGgZVS%Q`hm1&gxH| zo>^@%hYa}zuWt~|obX0Hns>v(V?ztd8Ocn`GJD(U+Vpy-z2kyv&+)a7v1H35N_^oC zp~K5ZP6xehk$KTULG@2kpsVQo;}8s63{Z^B<>AG}Bpv*Vu06ez`U`EO5)wl%mHS^2 zoM#<{!^M|67oNt~Gr-Wrow|;@<+Nd$PC{z`&^9Aj3F$<-{TI5q-?)FDCVE>xB5Y2H z!^{$;tkDWfBP;I&!To<;3bsqfKmkHj365ri%Qi3L1j0Z`0mL}rx!Fv|u#>fu_z@Sn z*AWk9y~w|7Yx~t*)@M}RctImE7Ax^L9OKGubgbV5Ys*}ZvseBw)4TF~+g@!_v@;t1 zs@G#&YK%(#St;Xk&Kez^f8tV|s()j3uv%O~f^L1?cgU2Qg!Ga@q*G~PWaKK8g6fp` zdY!Hf4XuviBm$IZC>y)R0;^enPw!i^mKfaw;cX41pp@?}5<0zkQ|p;zOBia%v{qRsfU}K+{xr!`O@N;ISHijw~fr~L2nxCH^vP}qdhO?lWz9%FEyN!jTqoeuk z*2uuGtxhdrcF49#!j0wsF(}M>3Hbw5b2Z- z0qO4U?)ohlGAAcX zm0X)v`JcNi?VNY)>^B>QcC18pSnKZQYgz)EHN2VDCks_o^-zCua&-HY$?ju|BjyQqr!bcDtaj_i^GHIveY3NBRM`)N^#&h*4s>T zRU-J5Ylii$)C!&RPvMz2|(|55LLR3#%6lt_-iV6HJog0=XOX0uMMvh|FL!X8HenInG4f?`Z^!`b#?QzaQ~;EB_ipA z`$got@9hlO9<@Jr$|Vh_J`uP~2lmFWL-h2n(6Ma2B%zP1QETZDGlc##P1@gwxktl6 z24-N+;O)TcEHvO%>d)0&IRS(J>N8w894Eh9o#eAs#W4#aT8*(OK3Xq@dJu-C;LiY4 zf(mK7XBf)uACu>e__MB$1u#j1nd|QC1VOz6D39^uN^5Jp3x;Befk$+b<*Jc+TNu)gWgCLe_MY+96E>v3->mW|4!v{zrNKF18t>IM3=EX zV^q;~^);5K|3CeGNr`{g>l{>~YZcnhYr6T5G+b=%b7TOiA3h~w!&8c)nrpX1$2V|J zJ}D?taC583Z!I+*wTO!bZskqGhG_|=g<3Wzf_mOKX}0~cr{=6{mTCHN+rdGw0@^k! zw8_VkKkOmp8$-rPM0z$Mf$b`28??}-|Dh5%iqsOz=U07jJWQviZ;H>$+p*xUISvC+ zf2h0&mQ67OeKo9m5=qF4!rT?n!r|JAx9C-f;h`YN`4IX{?4#4mPeKR4lfDN}%1`9g z@*6#9J-R)RIz(7a?X5#&^Kk6q(2!IFG5k)8E3}tFbT-F{gmC>-bz}fuD zic&=&bK$->iU-y$LBsP6ydZrBL$0H!#6i32bF>dmm&|ceshrb0`;5}|hE+2wn=C3T z>!|LcuANoHgpq~};@=4NW?S%Va&`3#4HIWfH0JV%6_DRDibIk z4uDn#!-t-)ERDpd-&h*d9ggMKr*6$hcdR1f$~${dOfna%>Dhw3R4hh-lJ6d0t@d%o zyazk&8TXM1^#{kHgog+*g+Lc?^>w!LhNspGN?B(Kjo<`#U|kyZin{?F1=5Rh1anJ6oui5C+U^#?SihFtzc zX1*#xBexcJy)iWNK@lpz6#dl?ge6+QEJX|P!M)OGh43cAN#Ge1k z(o|#jRR6o=Z?W|`@DVyDg@J)70h)cLW%U7IGTauZfmnkF{RJkh!GuB6=uJN79`}~F zZQXTzsF*t^j(kxtQRLzB9=n#jwJbb@bc2+-$W+17$e3EEO9w*uFd~atLxHY@xjC6Q z58we%{Bzr;X%DB}?d+d>2Vx3Wf&FVneRWhVM!S`NM9%)+Q9LUR-PMz=QN^ z)RpHwI7x>8CJm^Vy6Y)^{x286a(%)KLpUWTBjczh9`~y_@0tZvlF~y#xd-UxX(n?H zfBJ(m`WYm)0$oOIHhZPDz_?=o*wl0Y;}Mk_vp0o>h5Y6KGX>&g9hi}1Z695Qc_qh^ zd!J+liZU(v+t$ltcE0Xr+(+Bw-P^tzLCn6{4KJ_opQgUnff<{UFzm_ZoyU#g1w9Hx zWmd~YGD03ZL`lgcix7#|flM3q5e0eRkdwL&|0-Ld# zJn!k^(AeMNUP`Zm$xR4^%KW&(7aG;9xo$n2w?84~IPnpZcFL4!%sHy55&*%;?gfsC zsSac&D^26VK-jmi0IG>h<}fFCmUahxi>(=8F;Z0(1NxaUV7v%0T84ngRrrVzVf^<~ z%fE*6HP#?Y^(poN@vgUyXzh6KINL>x{qAT!QY%nP8ahh%P3(rx-+Hb`wrZL`6q0I= z(&ptQg3EZ%aC0M=muFC^rivdw#LIFW4v$RtN! zNUsWx8T+eDhRbqZqr?B438uMv`A?M$UgSdk<}X=_*1J3ZEgwnSn9^aXsZs|A9Xosl z071F|GkzUNET8`XHW4LIC`m~nBt-40=++6Yka5W^UK7Y5_3|@+Np2?gj+W__X+d1F ztw}*$1+1$V5q3pD`uFos6NQBJ2S}{xP_c!1o)nQIMvvvArN3EU&}8L)g`J*?HxY#5 zCxb0VSzYsCQNR5KAyHn0D@#N8AgYj;9UFytqa)Oc=OZUaF$HMgP0bw8x?Y)-WXB!O z044SgX+`Xs?rs~&FYsIOaW^7}@4$s9;s?ehfM6x)ULM)24!RiN_GwY+Ay>*)C%_oBFR0f3RO&4W?&146hJj~sLR_BG zjQA8rtXB)ijDa*VX*b0f-r*16pSp#iR7!IcG8mOG=^)v{e7JuJO0e#JjcZ9~orLGO{2DA8{N_A8_HvgbKO`RRX0G~Q*C1$vv_BMY zN!t3vQ%=EdP$gZF{Vlr6^wPa^Sj;*b}rsBHlT&0(~TTlhgw?PjtHHGa`gG=j?9?^5zevl~FGl7}y|z z%|v1N?A;cK?~KwKWYy=t{K%cDss!P6JG-DDrh#X#4dqY%e_mQMIR2K_7xk&~nuiBg zQlR^UG>F~U9(@;Iv0WRA#DJ2!j0j)iY0f`KJSQ^Z7*dd`HQ+Z)bv`pptWEXQbEDsq zQfQqz@CbyLm4G#vDOAevXpE7?n)PgxzdiF)Yfjc`duF=KwI2vPn)Cb*j{I^@(sjer zhme%8%^xxx<|da$)P}281;1-~WhScX*1%*e(r@?1ZmJp>p%BqeVD5Bg^H7j!I}LLK z3xrHz*5)tLU!9SlPrs5Fq%AVHdA}s;N!f+rX{dcxR#$Gli`PK|`kNQ;hV7xs1IX|Vw}QnKo5C2V*hoy8_AkISkPU2l7@!>N#-@n~+x!F} z=spbzOEKXW@0V4zYc#aIKy%2%^ zKHdFn-vZxTPFAt-iHc9x%n<@B@kxGENy8ijK3|}u92qb+X|P4|RG|BCivTH^j7c9a z+Ml0k2lXT0jXuK5myg8YOp-RyaMq?4(T3J^6XdVF1TCG?bRTC73>g{b;}!-6H)yrcz6ywha5W5!6Sa4@bjkSb-UBaYvT34PCX%Pd0>w3UA%Js6zJVYB9&*MNo2k@ z=h8ftG9sa;L?*uo6@EOuC+z_|FBgNsTjc8MGb^5OKYyH<)aH=9yf^!Ej!aVdZeNHQ zK$^u}ToVtP3;nMVUQtQfm=ktB{8|E0eBCK~%SrWek5ajIr_InSAn+?#c2_pzxth`> z!*m8DIT7EzRT~V!veeude2+G)_gkSB)Al2(El3P zasB?^BJrT@E-!cGdrOKZ7>g7Hv{^djSJ$ECc94h+^U(2bOwfgR3C;#xUT8&og#eKkq+W1vqe&}O^d@)1uG=1UcOH=0z*J$v`WDoh2Sq_i z^RvzAlmzsWGlH-_uD}0mc(>~1604kTUueYC6O;w6Y)8}E1^sHk16;__YvE~Y{Pz`` zx5T3`_%9@2*!Vur{w@rLT6`1P^6n1?wpM*q>Ek+;b>G|&UTg=4vYy7IlSicz1^mfa zwrgLD#QSBM5S&bad~-u2k-9sR-wSps3b@hZ83^`%6PYccrMNG`D2lOeuDt*t~8%}`ZvPjHg?u^jNezkeuCOo9vS(F)h?L>hpvr~ z99@$~`8E)(mc`bfKu!8-Qfi48_I%!c>htC>+R=nmzVDH{B_SxDbgGNi zH^fFM{qR#S56yF{tB?BK9+Fp{uf3MFGa7lTZMzg@)o%q|!qC=837t6L-}!OCjUpz< z2kG)*$z35;-rwXOM^Nr@qrdubC~}Yhp`@Ntb^yPE!C$A~_4V?RJ!uKVgWZrgn%3-T z5Xa%nIT)#FKEh9mBW74tRW`pmwwAZXv7XfKKw#i}a}W~J;PmuB0Gz&IV0eC2bpTJ) z5`mX<);Kr@DN>N?#>6Th$jc9v+*k=jc6zw@_SYc4wqwMj6s0pi&kTu_ub77UCsAMD z_1uB_Jil-|)$^KXaEGB5#Vg4=YyN0W^(4h1?IaA_sai0$i*}SJPBQ%?O(F78|Sy?>|pvA={f#?6w&_Ia)n&-oZ_25!;;4)}N zi^i|emifut?Oc`tOvfiS@Dxw2?(EwE?G%Pt0%_6iU&t)oZnGNqw?)~ah(_FDAkOLj zi_mZkn|81CQwTUWLoPzm?HA0qS}Y%0^U+clniN-|zHCW#Q`}P0LH@<^7LET9wR!z!v{VQS-u=;FozLMfOh?#c3Q&p)h3Ict3 z9wKte+n9LV^>`p`pf{JyzCp-4>D`fuiJq~g+?p(;o-$&3Vzw~r)?XB7$UOFZQ@Rc3 z@9f+gKe&|9QVYo{Drmjwem1@L9gQFDz7(yEx&26saf5Nqd55Kd=f^((?IPL)^=Y4Z zFln&h+Y|RkKsBIub0VD(FRp|K(J+4ss#14+_4zY)##sGgXt1{=RQ-r#2^U*I95jP+ za+^P?&Ao^qe!!TR2<0}%5FTObqgeQKWM^Z4)xod>!A^TeXAyYk5EZw&`;d5bDo31DR>h22%1JXh|?|E5bBQoUw%B;3?O7J)Vqz4kZ9Jp1wZ)=g(Kz8=a@~ zA+Q)2FwH?k)3G0kCH4**&Q*-jt9^}V%#y(BAH2VWy#obly2e64D;6|P-E#6pq zvJg`I18x9j>KBN6&g)Tj-Qj0ZSyRG67zc66v=!gg<$DerEq_g6)nsKcMiA|dPdZVa zdT9o+?1Jb~=YC}YKJalWst_nz@cG~)=3V^2HMZH7N)_<$7J47t8~Lt60Npk=DS#Vg z8t#^H`={e4V!U~4m>&rVBWdGO+S&}_35&iX(;-E>m2+?-J7#wFT_f`;ALZq785jzG zSLbFFohnWf0WZV!wK2~nD97MHRM5z`G8ZbSe_jsC^4ahnkk@=^=-y9q|1JuYS(V>Y zfB*@pjt)XYL&~(7REiW1bnxPw?wwH2`3@;iogi=T*hmL5%9p#lC9w&PnMGxV+A}jc z&5N8M_vW4Ko3Gc&=k~dCKNU;8>=yW~3q{v;a!-!$K4^5Tq8CgT9pW9HTS)=3%_YtgG; zGxMaT?(R~IPZ{cckj$)}n3ysAkmR)NjrhIUrJ7ScXO5OhlRWF^WUjI zs5zlm$G2A6!W0gQ+1RMoW2WXJw0gX8&(CT;{RR)^pD!h`f&OiKc)%oPSZMC>17a2d|VYSN}EFp zz`B5wUy`OcqAD|v15#!L1UzmeMz4Q@H7Ywud%TlX#v7_#+?~@7x*8Y*8ByLEjaQzc zC9qyqVD)112H3a9tuc|Z=9{(neDkxdKvqu=E{Dbtsr0WB$^az~9Vg^9R-+^Mwi@I)4kN`*zh4AnU07Y34k z!&Z}UP}H8eI*}JAA>X#ze@p>R0w6gIL^j_&%NMXb(7ytseIn0dahfhW6ilDDGyzg8 zl^v4|&;HOt@*OXT?BB;*wH?>+43}cg@jX2mGNhV_%VeAWKtT8{+cesrE(HhUPDTIm6~?_YQ&`m*5vMR*_4kkwas@ucFc+7(2frqtaLt zV!vks10UKItcgbACNnT!zw#UK263&T&nHAFACo?K@U!ASbQu;yO z9!oDfEZ=?#ydLbrbLGy80qNU3@UCS6w%Vl7udQnz}d3?j|p`oc4B<&CZ7vO_o`=g%0rhr z;eoR;Q42%3C-1ZFRi{r#F&TOx%r;H5cv|yDpt>)~Qis@u z$*I2%r#ed6&D}iR3@0DLjuKpd|6@Sv=V*>V>jkVB=u1lUMQwi7e&TuVLQ>Am%z)u7 zpwWJCa8OVbGP}SF1qW+{tD!&NuG{gK{e+S#6_}Lfb@$2GRWS4BU~D*ePmh6Xf;%ZA zSesU!puoE3uY#}cJAy>_@{{3|7?BWKw7ShUZbAZUb*4A%@>@$pG75pD4dME)9X*hznPsj1Nll-jj2@EqtwspDXuMMY@Bn`6`A0+ zwR*R}kdGrAhAFk|+4%Hy`$<4a0Kf$+lmN))r@QA#9ZDM#1Rl`wx1+FJ7UR*2qs3># zMjxVYHEGX?Q+ojB#Jp9=-Rb#OdSD#af$x`ZTY!+e)XT|8qr`8%P&^z;ajg?_I#p*`F5Z#>`wp(b>q=wx6+eZ7prZ+q>UZTV3REesWLYGWNzhAKqLHyG$~ z@BU9%Xw5fxSOBmx1|QrnLBV{o>?_Iwl~y0WzgK@UE8106dQcdM?}DK9ReBqN#A8X?-utDYFok6^w#&=-(CWg|+`m(+H^K~s8Cp$Ft9@Ikj%ZP`K zFFh|5$%>T|V2>~7Cg$zrF(FAwq#z9v7V?S!IW=&TyTXbspcWMVgaXJlfPdO%=5Ps} zf4MRMy01teRx>83%Y9UcRT&d-Xl!qNWRC*&nrruGbijWEkoac!2@8)*Egg^hsObnx)7dCa7S?j_Uv;n$Cj-dcnPdHMKwUzr>4 zcs^Miv2mQr$YTwl5$QgxXYvD+E>Ltpfok;%pRr%DRQ_AV;-|ET5q;p_5lc@Hse2*tp+Ud=eki~5P*RMk}*NeuKit>S>lCQC>aP!ka6mszzl^j#jE zJb{m>kAgqj@YYh|^=FZ^`by|wf=!dG6CcB!eGF=wcZ%=c$ghCCeo>MMn?d#y3-O=0 zOcC0H$u>N^L~j3+REfJaMIE_Or8T>%fx;iC{rvcw95=I-Vr?ywA{B>2NBOm#QY7d4 zT8go?DU5TmclogK3T@is=@DPkgFAHFh&58MCH!P5opH5Mro$dIweR9ym{ckFY9`u+~yf=GUFJ$im1Bm!b3@vAV@D5?zCqBRQNG20-{0A z7)lJYD(g>IL9fzDK{g))lw0vUJ(a0K2Mx&R=mrKbP~hNCE&h@{m{0Yi#D7J82K>+e z7!BPWoqc_H7uRlz?0PVYGuO3g$T5a9=0CRFZ*FJ6U)UpeR|-Q7W;w(dcen-l-0(d? zl<@T_cvEmDjl>y+D#Q>E>GvvyI2|<;lqg+kTr)P($M=4PLk;`}_&b59)s=?QboKQI z)FFFWDd|gp$~{w;_I#j8Z+z0zyEFWcWno|(ESgv%*#QnVu_!ovaNyB&Z$k;DY=Mkv zI0(;_n}cK5*j8ac9EWmt?%?`v?|U7y54)+s@u+yxymiluJSh}P5WdF>bt?;iRvMAx zLL4uBv5YFc)Z@)Cfq6KNdbXh-x-Nui&=$w>_U3Q_kV;8F+m91y<#(@G*^lSt=3W%O zt-5_EA*%ndp!7-vFJqg* z*jYRB+w1Zt+D`4`%s3MF&Ugk%fCLeu)}0LngYblbrMKR6_WtH9oz)2-By#e;NZ>bB zaut@a*U?dJ$%gU_)wAt|Fu$B*Zu*7z|O39qPTTt=I@=u%onFe$gJHZV#bI z7ze$s;Y3CGj@45ei8j#>x6-f4b|B-s>Iae_XCj!LTc{0DQ&K`=HShyK&a~N3n($vS zF&Lm)XAGS13OhT)!l}G;_hqr`4r&NBJ>3a-9lL>!rua+~cT^l*>qZ1GDkibTg+q`) z@s&xmyJ(C=D#2fQY00&Kx0nF+T(K%hlyD$+Evb-JbKKdsI)1z(NT2pG9S;Ni4ehZ# zX9jj0ueq!J6C1XNXB^-UpliS+0wJsfvNs-5*=J!y9uJiPDl@n1N~(H)*?8Vw&qz9c zW8?-?B`)1eji%0zDBB9_e?svEz?W4-Nj32OUoHS9vzXf0r32zoGiOj}G=kuhGXN-o zJ@j){IqVS+q-2sLpm`6$-hKL87gKaDA+@hq7czZbTe(p9PCveP-x)k zaM(U%eky1aUqlrN;~s_K!rwBsY_QN^2oKLEi7%Pj6O)#nx<6-R9O?xCg>4s3B~bNe ztv??%LO83?24Dm5cti(v$jRf~AynzTA63$z%c2Wi>eHELe1*OkJ5TC2lOl3cRSoAK z^d25%G+J7o3%z^g%FBF%jx~S(qFc1O1APb=fU_@o%zY@Z1;u705ZHemFvi5VG_JoE zBaI-dW{5tePU;7tMn>IS@@nn)6OM@L#GBFrZiNS+s}E{G{$$NzAgNtk*6_{tuJUo# zZ1OD9Q(`&3@o1&2SloExOH}me^5j{#0YI3SN?oro&8ki;-!0Ak31Sf~uit>j@5S>cIk#kEA z9vy&_9VUw0F28-n8G}igW$px9(L2NxSD=>B0HwU~^P2{?U=Bcxo}G)32iUm<=ZY6M z6RifJ<7|k^$E2Q~GJ==y>e2wP^xqN{9pIQDS*EM^;QaIe2&Qp0tc?Ay0jQu$ahedGBHU?HQS#nzvPu$SG;CH?V7ILyB99H0kCde-a9V-fPO9k+~( zFxzgn9V90k3EBnid5>=zq^VVSeY~)7PF|1BBH>8|$!{Yq zC#C><((q_eg4kJKATv|SqLINzylh(+T2!Gk<^+19NVTb!Y@m8?##Y?8h!l9=P#oIm zoy}Zu2W>oh&O&UOKCVZ9fVHY%^nTnWIo}#!dJCw}S4|ONVe816$>^zJO(f%z!bRAe~-pj5$Jk2BdwnU?`2xfkW8)%qDlUY{gI0${XQ#(0>^YkP#Hug>)jskv4 zXHUR*0qiayp(G3zbNI4>hYkqcW}F1ksu$dx1OD+qz7WmN+40UVU0sW)`2d{nqQU+` zNti*EX?Y}3C>U8P7oiaK!0CNcS2*_4vPGq@KQ0M8#LtxZMu_)}*(UIOj!i(5 zhQ%SV>@;%-pINLP=p4x=%E?DW8>sik|Ei}40fMK0{`j)YJLwVQX?`Cu{1=d(9+Q4g z4ld2Sv;8XQzrAXAZ-N1Ac#nrYvHPQ^$>YODcF-X$QHl$H3!QGNPx5;~R%PHnHlkxV z5N|+_I~DR1PaVDVh7g!lW|Wovw-xZWzg@n6|NdF#0*nkk`w2yQV(ZnK-e2`As8|02 z!AAW5qpa~9$1NBb4@XPGCxphvO_SrD{oNuKKHjxTU8>|XH{lwY;5h?Ier3KA?Ny}t#qc`y1LLZM&&;WU%X>uh0Rh?e!0%{303$e}90Yt%mx$-Gi>($SIdgd}=Svf<FMmwu8lU^t_=3n zzl&K_13i=PN#jP_v=*kaFk|{+64!{YSS@eQ&!YZvDrO- zFTKHy#7695^s36R(L@Lye&;2s!vh}nx+;zh^~<+)EkAK_alw2Y0xhjn3HH`j{?_AN z!cV9xBIhF4-rtS7&1Kt{pcS!R_zGpi*Ldt0$btU23PMf?{dIH;7Q%XcXJ=|H5ANgG zrGNk-fyeJ_a!UfczG!kZOo9*n%V1F!LNprx71CN7{z%=v$I?yg!(PthA>l$wIfdvB zrC9Tw{oP1$T=dhNqoYlxrW*k4jWe<6j?B}WEtLC*Bb@02TBTwD5Nos1s#||~y_HTf z2#2=*40}}N`E-Sny+r!iqRrw~RO|}?FBLn7UEnVCp#KBq@ajE9Zg^LyDUdm5vuIZA zAfz1`_?wjZH|0&pM3J1rcyOOS72kZ@dY?CbxS=NlFwEOuYE1`Lf6+1dAFQ+JUP?%z z0>|5y4kE|DTSL5phCLA>i@XHKeG@=XiEJz;6wg*e3RQ5a87i8?R~=AL0?erEbBYm`i_)f4ZTgs6@FTlcRSz2K>Ym7RGv0w`Na_NM zLPnWqik{wnC6PMYzTQVEa4(~FpwLHAU2lJ+`Tnm#O*qN$qTdTJhttix1L1os?seD| zuB+>Fy(4XyJyzdMHfJW4=6y0F>=e-`!%a>G2p^YcqfUDtvY;0x% zE(%Ju^@6>BiAu~)cdsAs!^2S=K+>FUHu!V$1P1!!-d28BugDp2X3qPo)4zD zRfbp1D)5MVH!EmZ`V9g2BV{cOiFuTs4hJD;4%DmIJrVY&N1mMLO%|55r^g*{fiN`t zQH$#fudVc@zLk!JY!${AIfQ_HH7L;EyZl`NJ0=-=Bc+*E+p!}KHcHd3ME&}lW&T;} z5q4DkWEi*^v$9%J9p`GPWYh_}a}(k(%;*?UHU>FauNRJR0g=c<(2RpfT7bK8=?m+8 zE|8d*C^iIkMq{oug|tm)QUpNATi1@jQ}MzjZqwk&`>o5gQ6GgRpOqJOOz@|Z6StH! zz@+QMr*hn{szwiTd^iH%5_r5+tGnz7_VyJXjg4RU6})y7@Z!M7wy~M5P)+3`q!r0- z_s0`C+bsqz;kbdCOvS%~N5spOK?{^{vZQZctitaKbf@UbW3Qm=xY%qb4@a#7ILaj( zXr9yCv-pUANhZ<#(e?b~Wt|#av6sth%|I!W59)mMj`sg3_#v8eQVHTp3Vt%*ub*Zb zkFN8IA0pSv_oW)Bi_NIT^XR|GU^Gc^q6WBTY986E&%^aJN2DW{TPdPbefsj_B^SCM z?E8$cU#hCAv!kOLvw334>vwl#xiV_AIpl-eTQ^SUI$|wb>sT-Qc(?BOw?5nKW6z`&h0xix~DxQ>6-Tu-0 zP?pN3d=^ll+ngKH755vPW1Ohh$12$`nlF~ zqxLPNcA!x5R}Q-5YPl&SO-?ypy{-byao#$^rFN!FL%eqYIkQAU**$D9Z*^EuZM4?% zW2wN}YCj+kOMtP(G{>cb;ohj3*97Z}p0)NnBiTWta{N7!>1iG*X^TFK&8b?pyu7@A z1qBV9yvDTN(G-@`t?Ac3uyWa1*SmZwHD8_5(H>b(KBanl3`GK)H)q_gE)+}Yqw@|& zRD;>y4lm#fS)d1hp$XlG3%M41T1Z-sQyQQz-%wRMfG*_G;_r{l`c~jL)`NC?{8$I1 zw%;jB;~g36AYNOX7Uvc$hGTE~qJ^ENwWc6^V@WDDJrPR!`hEbUc|8zsuQ&6{0vr29 zCiTx`ms{Glloa&-0efJFaHZ(ZxezO1T!`AJ(FKpUKJF}`s>)TYWY1ko-d=457al0@&2sIR=Oq{{q&KcEQfaC~1lG*>)wk#Bu3uy;O_k~7j-qSr{+Cdf=;T=+x-zca_$_c-XZ;v>g-R5n z`#16R>6tGz?T3Gjj}?5oaTakn`)N+kTQ#&C5yaz4#WNk`mjQ zv2XU_lkhb?+xdRF{nqsj<%5`~RCV!tIIlxY1a;W^<@uGlTD&T-64|0Xb)|lHhkIYa zm(F;H;D%Ddz~6&^)a1x!1Wc`XtW zOmFVbG}+4_eC$MZWjnt@@vh!6mW36{qXBR!;bbG>>pit6t0%e6}mhNtW21dSBsDq~4B@)5_~Z+&I36~pfw z_Km*S{SFpzPf7o@(ay0$CXMaY@l8HQh_mGXyXzhN5 z#O>!t503}S}8n;!|PV_N1MIDLIlet~LSZd@UqpL;Uy3h8e5 zFO$cvluLKRR8e9mb1{fD`|PK3fd?efOiiieMMh><7AXx)G>C3Np>%88Be$ZJ5|k)c zi@Xg(3n5QMqLJ@M$2x%HX0k@3ZW1$T>1|6iCR}bVPXG$9w^H%XRCkv-^)Ip~Ymupm z0{kyaCw=E|(!ad>(KjL*`Qbg8FQ2w|Z79a->kp7^DMR|z{jgJ;w`ZF~rq@Exih*aF zx$>&J?Jf#fQKtX=(ItzJt}Q2yn9Qe_2jzyOKrADcUn20Lpg_1hiUeXTRa`E=H(5lo zBlul)Z|0UhJjdhpbtFiGJzeG(WbyD~Sn0I!>=A0vW|6xvSJrfnH7ygPprLtHJaKa2 zdUMLC?qZDl;|C9q13ei#d)DHt=S?mggPIa>Jvc!~H!Roeq7DgB)*|`~hqg~ay?t&s zYuU2Xoyd|Do3ID0On-N;F={QwO;5k-jupjUt~VYvoc?9y{kQj4^E6Mb7W22NKL**a;wicp zU&VqmvV_Hjh1DP+g&QBo4I^|;L3z76U0;PWEYO(UP?m@NRmJ9fBs)w}GWT=7p2d%c zu?Bx56C3ypsxUa=R6(~#w=1b7Ak?2Hr*5|4i>6+8OHSD1ngfiJKVlp^OdLIFwk|?* z$ECsdvrq=!)4(_JXi|VmN9#`CbY%H&OnkF9o)^BLlz~&hQ*&Z>qNZq%K?35Da00^TUjT!=veT z!s+8PU)xw$1xq7dgzf*N;9k?@u;`5KT2D;+_zeNVPl{dFe$z29VE#8LCL)XNVFnj` z5c)5&PFD+TQfYRi^ir@s{7TX2!fe|N@1(PJ)+_bE+g~_v+s6O{g1L!Wgys4~HkxpY zg_K4Y2GUF-@F@%o@Rz>}S`DY+2cQoAxVxORuX)2p9T^lf%Zrq*TV2EqW#>ET`~ut( zwRQC*K|kPV+b+Kx_x_|O0{^vxREkx}jj~c6=x~HFYDh)LV6}G!8ym4nK0RU>shr-z zA=bTPjage+`MWbSHn)K!8!7>F8LKIz^{z4#j>zFipl`PN22exx`ij6_GLL5({?UVq zmuGt3ak2c0zif?Y3?gyAkjz;0XEuv+R z^PFIz#Ir!A?>|3&3mMVd06g|aa;k*08AFvJP9&Ia*AhaYaMb6DfuSE5$jZkWLxYIQ zHs7X3F8+!XRw3g@AMewB3^6=Bp~*}%NMoEE2}yU!;k?qYeZCan!sQ)L z@reO9ZK)2!E5AGJPf@%M?h16hK|y-&eyo3R-T;dVe@m9eNdjVp^BV z`86K9oq?|!A;U@oyp?FJdA6j=o7SGr3iV=pH%;f0Gs)YS#~~2}2(;bl9S+xBwtDM0 z$on*ec(`Hn`Cdaf1glYPqq@@PU%r}h(@x;^{`i-^cy^R%tp)sYun%mke7d6My<5y< zvW6#ZTj7B5#_V_=dKg$*2rhjuIlJPd75Fs~VXv`(ndyo!GJM&e+zSwuvS>;n9B`E) zWRXKH z?b(LFw{xKDXXW!6!jWq&q_%}7=rRA-^(gm$Hc>!U8`Lr{I%=g|mBG602Qi%(xFQXB zk6&t6%s3e?@GvQlK|o%FB#2$0Vl&iWzirMT0C(x!h)&JA=Mr zR3cqDIZP_={ATd(QqkbuaZ%KFRAYt(25b&cfbq+`KKNNJ_aEk}MU){d#5AH{f4;|a zYT3PVoGc~lHMub0zIa~BV=}OmzI1fXcY!33p5^q=VJW2YC>SA2E;Rhr`;`z_0GNJL zRrT-r28gAt{eRg`Ce=h`Q)cCh`fr2;r4`Bj(9>A)rs3=uXjdy4)S5J;9{zhup$vmQ zDlE)xIfYJvWp_(FGCyQ}$Un92wNV1#S)7`n$s;TljFujSEBqqt*N3-EElw}8M>gHE zzk~e-eic&WFBl*KbKJQ(Xh%bPYV!r<=kvqrcqdad;^2NT9l*t2KJseHe&q==yTvT{ zyk+on>+5l!KXma#oIEu+qXdman!sXo->m8^{B;|O*O0s-`0!iiFt~7kl;|uUud_jU zlK%YRBVVo4bLX2R1x0#GE;5QB;Tbn;2vybd*=7~-61Z4GliivZe%cBcx8!a)Xy z4_A>VTj^A(mKm^Rf2=2!kVuCp|4**$n$aq1&Ow=dy5+9Jq~L{}dXG{u38Bp&TH{>cLn4DR6SB4N-6@rxkKwd1;oD8 zWC5O4rO(r)3YdV6Ik#f*=MKigNU*%(0vgpE`y>c( zB(I704{ZF5uy1~!!_zLSw)w|Yguos(Ck&NoFsiE_P#9FDZlw#hKRsxHVb1vIbW2i( zQlDJ$NYJ;s(--9-b!&?tq5xOv;Vh#$gSEtz%#DLKnB!JfG-11UU;T`|oTTNMYiUtd zD_#V?xMc$M=PJBjm0wT6Sbt}K!Sfyq6)R1Te+YYjAJb&x?hljr%8zHM(?k)NUSgvX z(_bklZv6%SI_)FJ#1aQ1Q=oEu2`niwvqW;`WaV@>cJgDWnH+T-sY(6RD5%~#KU^r7 zao}O9F*Bni;HKjVBYFPH6vtbPjO@{_I+<}?%B;F^Qi`JAIgs-=s)6MeH#u;?E&J}h zXrRY=NG@x8)*B1W|FDZlxY`K@v+g zQ7G<(;mN8unC!rIX(p(e8A21RtCIqkFvG8^L7)}?fih;{MkK$CE%*}bU!;|{2C1F` zG;N?%GBCH-iQ>160%yxe*E@|O9Zcc>>4~((cIuz&Lb8qk&oE{8g0f*Ur)j=Bl!=&> zX?Qg%n!xmEQI5l$7W7zBfSOwws=B?RDS!(I!b1w>=d$FueZbsuyi21xDS>_^H9+lp z^dgB?4;!%nuTj6of@lm!o+#QLqe?khQ=8=KHmk8Uxp`4F6Qd*I_|1@{JWuDIq!T*l6Ae^brm=47_0 z-q{xu2QjLqC3eoSE!Dd`Vp>xO0Fy^Oc%JBks-O;~O6QZ1jap+jXD%=v5f+#ENf6UF z6h$Ti+-%Tsa2`)Kvg@Y%W2A{G$vW0mJ6h`86obJz^HEvWlK1`yvRi@Azw~hg`=f^+ zZ|Qs^NvLp~y1|EBp#;Uw|KsT^!>Wvywh8GHB&4NLO1eW*KoIE;=`QJRX#we!lx{ZN zodP1wrn|fO7Uz8D-Pgq*!Dl~ftyvTI+%r@BxBWtdZaRgO_bV8z6-Uo>VPmIN$Cw(1 z%J1G1#!zl0As$%Q`w*55nhIh9d0W=U0I=a|iI)Z=>SrOhq;!5+0iC*+PPf-4BITD?R9r<);7Uzj>7p8&gHG#h z*hMx- z28y`+u%La&@OA~r1)=w}j<`!qj+ zGm-2#XpCy-^Q|SL@HO4cFaqqPUyw))SgjI+>t-^wuKU{ze5RDka?s0*q(xW4n5Mfg z1cyxb?1X^bhcw-lR|Rjn7Hsh}@e>RfW*aI8;=CHT#k)lk!6h{--M z_}29p-~00y9z!*D6(@cEjW7nylZ)wD-?e%y;o;@%aFQmR+gK0QqPsz}=J%!b$;o>!_b%(WxIG(a_k*Af7yF9Olc9n$*V9~MyqaXBMLm}7*%>3R zzDPYd)@f?lRW*&%S)g!%dZq5^KHeWr&YGMOXqOU-&K2G{LVrgRhfB1sb@VRVW~F^Z zB*_x2I1)rAJGHbaGHwkRO^f!y#Xe7SldM8F)Ya|<^pS}9^440mK2O(DreFpg*|+`I z5xV8QR;t%GTb_sYhUAvhn}%1>d2E51iiN*hZ$A_$ReHFL=pc4=a?ppZ@xTFA#H{S^Xx_G>=>X% zV%BN~Ws68lkF?jDKXc4C47uh}P!%2Ltq&|qcN7!J1VwL-d^{YV9!P;5$yO|UPh`!g zozyX$9J)WRHm6T6%JENvKmw?*-@hwPM)}Qu#;5BNfN^-JfA*$cAXy?~Oo0rGMibXq z_|(5=O;uQc8JD*IRey3ViR)k0FZiIB*=`!pT81NSR|@yk$UHDL(7?f-l+pHNh;c`q z;NTPRM1*4*ckZ$o-lu-YRQWmBfKX{z98Fl>^-ggx5rl>@)Ye?g1#)c z=t*%9;k}DrW4qb6Vy`y6>y2{i6b7tz0Jk#grj5kX^v$;18MT-`+1CHU&@44nXsY=; zxadN6`glhuaHY+5w#A?S#+>7w6<1&UbaFDDI^$AX+HyAvTC||^_rJ;n)8^xA*Rk{s zz`5N$zn-bQ|JN$06CMV7ZskFS>@&zs1^|m!78OdRQ3dOrK%)}YDaD}rr!qGXy0+?S zb8cpvNF6BEPvrZU&mKj(*b1lJPu~}n?0SFF1+1ok^?al2?z9AAK#IrFLI2$md6!Yu z*|=0PeHc}D@`&@fJE!$Lk?U?@*>7bGTln}GgJ=I}rYi48O${ozm*95dZk(^__;?X( zbV=~gP<3^K8DF9XzYwZ5K77IT_y617z3sMJX!C7b!NV^$f$0LwR!j$DDmjKt_~YYM zTc3mo>^@B+qbiA=owD5k*=#9|zGG2V+N3_*7G4t)*BjB%! zOYVM;#UEMa8N%j24><9tcD<4RmRzp~uH24lq)1O!R$c0nH8Eb6C6mqEg&5nkzl zwXh#$8NUHY0XJDCf$Oyq+&vL z+TNWtS=my7hi^E>#!=KnxVib(^KZ%;@;L*LAXySl6yJ!7WItqnZVj*uDzoBgEJ@EmzN%h^k{d?$B-sx_!;NHGe zp5l0`*9Z%lYH???+m6Z}r2S?~Dr<`CL1R9W7%iEd4x@OgP-pq`Bn&s4pum@S;3d_C z^hTSy%Amr7rUiCW@ABo7SAnvp)2PyorRhngmi^cDxq2O`Sam!n%U7p;jp@M%f-UYVBF~Goo z;3lzTV(iGPhJ?X^SHYcz8B>+r(FDo;qNv3?xVkse5>WV~ z8XPCzvOo;jW-*ou0h+oQ2;mYR%7q_3Kq0m~hP~Yt z-d?b@aghjU&%pR@$rCe3&~D7zepW7puBs=}Q;T<1k2#-RuWp+bl_&$+^EdCCy!MM; zJ`yF)d&UYBihE^G&x3hNDhl3)mAalDC&*RIV=VBn#~V4xGkH3ir;2CC%Se$74T%q- zY9A9y;*6y2X$NARjwcys!8A~a_cg3L^%`}wko%7a z^th&Chk@t&Gg-)*Y{jS%dvHs$?WA5s-E=z)!cn4t50SH0Tm3N(s^voVqYr3L_Or&U zKvzXb@@IM_1ZDsA^a={LND^qkb8krj@dR+k(re4J-f#lm{Fu^bClH;&3Y;r!(PCIh zMXMhF5kn#-nCbMJKWS>G1$oB9N9nkaR#Ra@Zf=aXo5X*^GUf2%88ztsyE2t~j_3F| zfmuuPs#EmQY(Bv!iu~vxHqcCw4d%5OADjzJWKxXXeSNYN8E^l;(u;Dn6=^VenkZd9 zXk>H7`?2-zvf4zB?B*suQqz`(VQ6?vc*~%Y9>nl&tD$AhkM1mu&KSUDbUYi8YikWY z&H#=xT-5XzdwZJsy7<3*CKI_cyN2=y-OgMs9wBV{B0Pv?w>xd9fr-Eq}x?Y^|pM^&{iRnsna-0O7JYD<)rqoMO zd3jBqW7cH$R}F`a!u2b`i|d49Hqs-r&oKT>Xk$jjg>i`4{+s)w}IoEoZ zg2M0lc-X&;I|C<8jiFxLk#TgToKfbpil6N&)||kVUUb;- zghU357Xz`eG!p65vW*QDwC_Pu5KFZjkwli$YIoh#F)_&Q6?k)_4?O?udCTobAl3}e zHb`7mb+UW|hqxH@Xlr8i@fJR;&k@X#lmK?DJY8vM7#bdj zkb)2xXy$r8UIuOpNFiX7(60p%#1^+@?azDx0O;B$n-I(oX0=OLHgDfblDTicK|zU3 zQ=CGpC+zd^2k%bHYP+qlM9voYrZ|2>HgV!{9e`KseE)fUfF?f3HccqDKJGH013**H zl>%*47&=dbvcg$~W|uVyr-b`mxdVSXwV*%^Fi=UB|7p!TZp4=^=<14P=Qx2}4Hz_0 z$y}?|!k0Lq*k^p8S(=h+YqJ%48kk8WP>(RJ2Td>@sseb|K2#5Inmv%QrWG|UdaUXI z@YHa?byU80HpGH3oSquhGts|8)#Yd3ze5JHsQx~ml0?S*;Uvig2g7J&Upw`YzJ9PC zdHa8_EoNs-GXw~HI_7VMo%VVS6ZHpu=(U_(b!VTi1X_G&(?Ld3KZ?x-fFZr5wGTxyVa2LF`8)Rh4Tb z{UzK;8k(<&3oyBkKP8M&k`k;3je8YE567X%E0PWf`i^XHeVwIH7`!rWD8M}*?qriW ziy2zngBlxnt~Bc3ztWmYsr&MU4|Et$SYrBkU1C{g-t&Wk>3TDjEm+22OF=Xnps?|G6eZJJ}4&w|9JTv(M-n3m?D}X*;3Q1Sxb{+UU4uHT*U#+md$it0kO#?bNyEc-z)4DewG|w$BEx1-##&YDOO1n&s!yI7SgUo#XDZ^4)r7_+_}mm2lR?* zk>@-Ywh#2C22XAXW+As7AFrfuAW>G1-zDL_qX{KsiKy@Tq>QP=bFkeHeqeBrlBGPR z;K!JPy1KMY8DWbqFuHwaHLRxce5#g20Bt)i_i>_mnc$@`YlZH8z^Qq-6xnMen#c2a zs%ZlHy=NCrvfWCXm2{ou9_cDl0O=qW~T6a1mnXkd~^!>(LitK(C~1> ztHZ@ei_9Mi-3tvnKjUYK^t$cz1rR!i*@5$OBKDE{+i$~mab(!*4Tp?QYvp&ZL)UPQB$>Z_ zQ8h6c4Tg%o?KQ_nx+ie_erwjRmTJQe#5!c73DrGMojuRy|4B^?fx< z%im{3>$r|80xRe{?^o_8Y4V4ZUj_ui4+~x{NRrV}=Ets)l49k$Ek#e-s;d9$ksi@n zbbD&d59)XFovCRPs=QkaD|fVP><_yBsv&G`O`e31|4AB|K}W0`%aAjGwg#s0bo5J+ zeegM@Hb_pcnQMq!_$9WtFQ%qB=nJSn=h(R7o5qPT-_|0Na&lO4@h9A;nfc0e=DWv+ zebR5{4i=lZd3kwftT2!&F80upgoOi6PaS!b=JD&vzT0>L6-beikgaGxhNt$@nC&@F zb$>o<8c}~H&qhhvtfRRG@-)P;G+xn01C9hPr_`4COq9UGR1x%Wc*>PtVwOhE#C@|> z+0AQ-u>g;5%0P8H~H-c=X%LQWbl8ToJgp zGX=FlQtC-(mdV#u&Z*q|qy0t7>zIV1VAU|7S1+v_DCb9n2Pe+=aNMPFw|zbN`L{I} zZf(lF_rr_})GH~6H1l?I+bl}Qn-|5lWr})??j;GY!waRUnnWNQ0|HVKm8j`a1C#lc5GTvq&CM#4aZ1s5I;n7bj^LsS{O6(?ts$tXR#^<- zAg-@hw5c%A%4J4fBbhdH)ASsEM&gVqQ##ZGnGeHibelH&f z2i~VUC~It7q!PHPK7tTeRR@nT@ONrv0on>{OuKb^(4XJdi$&CQ#L1j{FQ30f zMz&O3N@}vsdVcrr>Ika0m8|oHTW;$7P5ekO4P(i_2d;p%Z%sPI5?XzlJdLLg@}>Hv zmFgrus<^ndbK|{6*%F#WRHh@M9=$d;*#_Vd<&P~oP0roj-3kDUO?R099-r9O>lxg> zQ7hQ@&ubBvBQ*82Zvk+dkZvVh)_k>;75K?{Mr=YjEl)uWx3ImvV3FN_Jl{lON=msCj@RHAYe;@#hO#k85KbUKxSdZtu+{R3@T-hwBjQ0KZhARQc*%yoV zc4rxae(cEf8WUU3PDm_GdQR>9&HcP>11oDxY}OlE`OMLd8Fkx4nm|2dUkJ>Ky^ddU z`&D~KuZ!cP9Q^j*0am=Ms)^oTVj&A(bgI8jTa3emsfL#|lkDmJL*jMHS22c6lkTD; zDy!(x17%-0tu3~h#OiA}7qZ!Ux6SRsteF#2A4$y1W*lakso=}&diiaNFa5{6K0~D*rQBrvn?KCh*R# zuN&u))P1z9>p?h2uCiC(hViD0~b@q-~YAC z0F70-DP-3|=+>JBcxX0z&$NJYY)oGciWFtN<)e1}=@h}Idzu>awWPb482eam=mN-@ z1%XCEl#W|uITe4#Tv{wC^V0d@qjrd6q@_6zE$!DoUNkao{-(#ZJ~;7`C@rgeQ@vY$ zh5`WccY^QYn+7q>5D?-)Kp25UF3?_Q-P8Pdt2!|e25UC;?x$%+L%ko_t#NCCa}`QKrfI1c>8W|8G22~KEs?kjJ(1|2!mUO z)@v_mPPE*uS-jXJb=D5wRrGYw>r@( z5s`9Oledr0#=sI1fB5EC;YgHjcK@I-Jpv;_6gY@D@X;!L{-!Cutah<=QfIK8?0xwB z#uxZf*XNUrpf3nH$ov>o^RAW+7;RMcc^3&Cb|8g}SDSw7A`M=xXIpiDlj~;)nl8Vn zu~yNugLi(ZP?b9kt`sS_QcBayP+Onb4o&1060m^CY52a`JlG5J%TfL{*4G>`R|xP-G~vFs=UfpSO@{?5+%{k>x+8~aX$w_tkP6IuLJ zm`(we^+ay{k28tytuJy%_iT-;;+e2w#MuJ|Y z`p@0z-6~^Vr&iUr$6J`T#}rIo-SU-4?%g||!gi5m*er;Y3_g&*kUB85ZzjO^jm88T zwX8efT5Jt0XTCfH!13zB3;1c6Nk2aMPm#pakr*CF>Ys2S=zl1WjFnbhAL{vHty7eDk*eJzvXpJK~znc+93kUJ*Ou5cNLfF zn54>E=f*>3KaBxsCtIU>o79*9i%pJcyI`1D?9;>1 zYnO$}Xb`$`U&GF(8AXweJT@J6n!L|4;{b-Tz4Fz3W!pn!_uZjoMYPytL7c-uE%0L% z3Ki5;{j)*Q{Qx=7kJ9qiu$Cw%y%egP@!rAshUfcswq>fIu)IJd*5tBvJTB#f|FZdq69%*|!wCGvF!mLU8>}E?Lint`hf4%OmFNauA%Fx>{4yk3iKox_W zEU=^iM9}ko;8eOgSj+8r6W}9SAKJ`-b~O$|u&nNSX{sMBYF`;jmvNo^S$I*-yLEhn zSyrY5poJr+8+5Pv>u9ERrh}7Sr>CM_3HS9zu3gh4{&Bdn@kd1~L`S1)(-R*4@@3R1 zOEHGS>77)0y?=to)mM7vd^YO9Y~7akgYHZ)xCB}n)wGH6435Ev^xyu+1t4z8_`^PS z-^qV;-`f#jy6-;?pA?~FNd`2*OPHp)TEo@z9nUs1Y&9~WVJtn*j(DX4MH1ZggNX%M zaA<&K;}%OpO!w@$h7+&@tOtb2&lU>w@B$V}T;vBhLhluxd1o9JhKiSlIm)LOjTw%i&o1^a=p4j!oz$h`Fr4Lee8y-(w9wZD&|_ql5=IIZ>^{ms zYzBo!)yZ5!LKXOvZJ*T_J25d4sjLBARrBR9ZK!~OapZ%)f@^~(hMjD1F|U1RHKWj9 z-i8m_bA16Ij%=H^!S5n`cKmEsFt8Td$_7Ao!@Ymm?$h`V8pw96@6k2BeL$w@=H-1& zJQU=z*fUqe(vJcjW)X?p@{*^DOLo16RNo2_q*Z&yUD7}rdP-%wF@ z&Ksj(E2KT;rV47+P2fbTVOk+N!>L|5Fa8pH`HHsN0bs#_!4?bi4ajD|eFO-;FK{3G z`|Y|QVeC8hpA3m$U(BF0Q3Mi?WGs40k^&2rP7@wZ@wRZKE+*zrj#O74XWU~pBfct_ ztJB{sfEp0c@O6%(&UyQfUEAX)z@PXKOS5Qbriu?`(G)Kk@4x(`Kr5Fd;`hss;hWd_ zg9ae8rZl%ngr|+hvcb@&sG?M$T)(nA%eMkxv_ThT{pq0U`621%(x?Q;$g@`2=m-&W z$_Ot^Veo^3>;agt;V#In z?IUQpx<-6B4+YStkVsYT9Ux_I%(JvnFIbtVjAbnFn7zc4P2^hm69Uc56W%Egy;D+B z>n#fS1dA`n09Oy!H(R3T8-Q9CAvWFjwKDF9g1D$CwxCBan}H}Jm83W}2}%3(AX)*S z+@x|7Q~}glT6%-b^##JHQirif1XAO3&^D@%Xk#^>@KkHovDoBX`E>xtL_T9!YAf^T zU_t=g<71qG*h6k$&Yvk|qb6(Bu<-R~Ma32Qxvl`=flEM#K|T78VDq9%xq|GYlkHUq zR-)sz9WSVXFl_g=13hPg(U`xB7hB5{Xd+Aa0df?e_Wh7cMP(%-hQMnDG{PCG{266m zL<85)sS@@|KI4<_N951eOT+i^4CX4jqYOEcZcQ9xfL)s6Ya~6U@D}wmE%ou~?Zt0j zKo(iu8DbWTspSberUzzi2@h$(pQ^?hZen4+rROUs_r-DEr>CG49Ri6IP#b~%jHzAu z1%BrBtWVSPVKO?~6b%bsY*zS_+z6NB%bei>;)IvkLSZsJlZL%NUg7uh@BKT;yx7}G zO&!uv)0GaA-#R!I0L1@eK*-H_rL8g0iN{d?mKD26rble8@9gk+Wr}D2 z&5Jl#YM78k?)0^vu{aD+pUl21=+<~$sUK)ev6&s7y}iIYQyNXxOa-#}`EpS@4}f8p z;qeCV4;lbFWJ7?}Sb=}!_vCpyKF;{KN&K99%WM`XOW}(*95E)40~rkx5LGuj=jAc# zHU9jiq49I)V!`vEmhot62;8%AtA3cQV_U~!OHLa({BCycs15< z*xOZP%gPKdKu>&`&HAsqkA45JNu$9C1>Vu&+PVX-tmQ<~+Y-7opT|i$5NkuDF%g;K zme367{#;LRUv#HYhnD7nI7(OjR zqN7zy-hhVQjs^1CE?pSwL4zFb6e%e_K9r&D1b$S_I)LVFkAIcBMK)^0*D^YEcVr5R z$zFr^1AKQh_e*q%0<<*t#z&DaZvdlovFUS_qbbVWRU&ZPYP)V4EMd_RgW)LT&VGRR z3gpK{L}K^uMSpx4ViCyr(f%w-V3Uw&|MRezRN2<61 zd4OC$+zoyF#JB;-2cKv?CJAuR(O(3^u*y9h1E__uyKlOci47F@6WeHMYrA;tly^Mh z2ZlJBUE8(ZJh=3d@+!74>sRY|081?bEOqMW(8xw=d26<*w~!kV#&oUq&}NPm2fgVpGUO zj?`~x`NJwRuuBt@3`PF7ykJcOgKP#@qLRh`F#G;Sc=P--1w-*xcqa?MtMU@!Gg;JI zdwMP&sihQ@4m%?g)nB;5vL4&j9=Q>?Sr zrwlMws-;xRaq4ejZaUEdvhS4=2old49!5Y8P($$eXKeNV}@4l6c+N@(=?cLubq& z+5PoZ`jKYhAe=5R;zTfm&>|oxzmFG4K zpt-r>J0BD!Q;LalboUT~*Gh6eK=1C|4Go*Xew9PTrzz!HZ~J&wqlp(5&hVE0cL}B` z&{k38+%f6ao9oiW5ZMwY3pZR$bsRmO0ZgR7NJJvo)kVHn&f!+>12y z+cF~AYtCJss&2q|j=9*gBRNy8GRkkg24byDSY|geRz2e}w>x**j@}$4P=VdNE~@GO z$P99Ex=%ZFWDB5J|6i%$H%%fJZ6~~-5&OjD+m8t^sAa=aG?PX=>n-rOX=&k(Z+u~g zK@uhZ9(AP)oI3|g2hZs01=798 z+F5iOE9`nu%fRdp;p*yS=S3&0otg3ZjT^wa@B=A(FxDm;JvX%sv zyUPmzHGW3~rp>JNuSj1}W+e~4mrw*%H)$XCZXlN88~F`nb3tD&nFmK@uqNa$<#;Xb zto3rl3En3NU1w*rpq1qP)@u08)$cFL792~=V*oQdR{~zWEFfLGioyZ5`1etpEtlo| zC{o^cAaJ=x0KUcQPo;1ny$C}-DZU@77jf`BEe&;cO=cu3jqHDP5DZM0-ui)o;DJ19 zAiW*Yc<=C7ZG;j%b0E-WPo+l6*KMt)H-0^Mi4x3Ao4A-gNTECt-N#Lf#|@ zuCH8ie*b*iCVGtlzAKyggUDDBISl&`gk04JBPxo~xNIIT$rj?5JBy%{TJ-y7mSU+1 z{xQ=r>w7?WPAB*7PozpdHyqqm(<$O;MwfSD^^r?d-tBw zUrMVk_mh`9#LTu$Pud4$v$h1DSIH{sdtH>NBx4^4v64q>sLE#%?WuzlpqSiJ%I%H>(*d{gYS?iA(KB&NahGAf5yLP>CxJ~Ejutmc^{ue|rIOTiz zMxzSkl(<57i$N!}ZvEO=e8PcrHJu(HYJY`hke12;XSh81s-Sbga?lt?0oetmU{e{( z*MWq;a|0g1^j`N<93y&5%xHU_>HU(p=5mrdw$6p)yWh2DjX2NJWPb=kiT3tncDKiA zz2|%uC?tFTYuBP(c*8>EDwfd=aM8PkS_RfN%-eYYKt4HM<3q zdNvT)ARahvY&)Dj4d?{BHzfV8%Qm;#v{Mr~Y70+(#LjtF>K_~cKq%lOgXH^O8TOru zL2Nv09B3Xsr|E-sEzLp>)a4N*(m_^m%e;Vk@Cv0$(~XkCuYk*1)D#j|G-P7BZNuZi|M9pNy%Pa_B07HuYf0+0S8RdYdBU7k zyjG_#k5v7Vq$w{*Ws$bp`&r&hOvMtJ&)bfKbf0c5O=#)P_RHJY49CdGQr`Q;3wm%Z z_}P&IwqGPI9nA?SQ2WNfC=R;>pRqj?<3M=-iZTma)|aij${#J(4n&`Kk%DCK-2IT8 zD*{v@CZnMR;ld!$uo;j0Z}Sh97+{5BY_{ z_@36TEhpdliEOuoznQ>83v0uiJ0&=d^un@zi z$u)}xD@sMjpD?)C;1gr53fmkwq5+!QF_CQMpR7S>@x*fvdCd>CO$1L~KzP~jThYJ4 z2gB#pYH?r}8pyzeeFvX@=OOqqSWE;H{Y6w^_XAEL*9RxQt*vRB74a9ohi+~Wo*Q^V z-yT^C;KlsTe5Y!)xv*z>|M!)oTx73bXrtl6wI%Z>W|I4)Aqm|@EUd21F{SmB6`dq7 zEj(-_-k-0>k=zZjteYCyabC9Z{i;KwqvVgLh5gT4r%bna+*hTMBnh|eTBD)*L#7{h z7eIdkDPQg`gTuG)Ru@1RlF1VjULd#D8i2LALLo*k|GE73HD#3;Tc<%;l0b4>G_h3m z>eqLo6pxdo#E@@?!*f01#Y-PZ@4d$#YlIJ2^nC`bwvcIBHjh_ga;Nd0H>(JPJj0W* zt{5$hW@{`2^saHAKU`e7YAbgaJSZPMC_gGLci^^5t2Q%s=7L}m_ntl6DV1qRN)+kP zWnZWeHhrq`9auIVK zpG%Rmo`ur!SYKL+V%M_1EM)F`JVlEGEVOB;TL|;b%`luiT<{9@lekfIK6CqjpODiF zcLy&8hXs3AqSeQ5+tRaMXWg*VPenM{;8>dQ*+|X#cp`6s)t#d&t*nK?*9UG4c14ph z@%vw<{~fOU3C(+$`q$S;?_B{3*>+8-_w8U%M=XS`PN_hXDYL(9z1?`I-tgQEQ?CZu zx3;~d{Z;$s9Anb=ztaEr2qi=Tgyx8m*Pezls8USo?O%Wjw7$Ds;QU6P>3k$lU9*KA z^R|j9m`Qi|DU!G^28{sjhh8}umHYWJl-;DFGGU08(kT(g_djc@nzV*{L=aeNU{`b5 z@8^Vi_4y4YoSayev$m)(9Fp<t@m^ad4`ESr8)^6OYgAQU{@v-=PWXFL|G!d8@ddyx^c1xj7bM|YN#Xfpr$zW?t3 zo(*|R6%c~S<4cE#wRum-UT=Qy>b|~la*ss*-g94FlEn4R7{+T6dv|wh0+rlePDZAU zRrAUE&AX$Wv`nn_qJ699KlzMB(w`p@@t;Rq{O{3xIn+#%rihs9H;)gzmYbg*xx58h zrb||!R8kIiNvs0G`Y@j{iMsvs<(^-As%#_}<9_GvsKIIwH^piet{p6mOkf#CcYivX z$-FU$Am$*)7VG(56}p{m^|3I}`yMV9FLBY)xq2MfLYDM+k7Ziio1NEV?oDnSY;I4a zf^l(=6F~y6G4vJTR4H-v0fao$X)oU%&NvZ2Oq}QII3;r`TTtBAFhxr?obSoSE^D?9 zzYvkYjL_PsRh!@L%u_iKdvl-K`nDIbZHk!WWV44k&wAx!^GerMZi$2^<7^B6{o|F2 zEw7Id=xI8&XYSMV@Q6s}{8~*eV|Z5hL0r|17p9HFdJxpJoq0Yz;+hF?%m#5VFmL+r zOg4PmRc_qcfK|wd?ey?C8i7Y5X}>y{J5YUU`_F}&>VH&34y%Owjga;Ht>5=?^6SjI zB)i(Ty|uCT!!$U z_f)n(-dNX$ndRzWh~e&VXf-WOlc{{4?6ypIWR~63;oorbH%9uIMo-LR#ADQotU6RW zO8@`qiBwGlf$jTqxX~A*NZ_*B_ic|qYr5)G?ya1b%T=(Af7ul3r2G8gy!lNrx5kn_ zJgF4dG3#O8W66p}mzQ>ie!r%NrT>r8X=<5mw_C;;-u+Xy}GB$3o9GS?x9kOUFvB|M)^YE>#}L@D-!_Z%vT{K; zXO@*Ul$4<~i>(i(Z?RRrK1;fC4m;8TuNMZM?6VzLF1HS)nabCB7SrdC5qJKJ|K14j z%YK_r|No$X7{n|l{r^3F-kT=Y5je)G@YF}9pH_YkSkOnW5?#b0f{wZP9|^E>sbV2E zf0~^x;vHQSst{Be!}OMN2|3JL&xWYL|8;`qJo%m~-nBe^c)y=p1VKscnu%UMhIZC{ z!c$g7&C|jWAoNF^9XPW5tlErCiPtffm;XWaVOQ9M8ZNH4eN0$n#XXz_2{ULZpy)}R zvdUBuPQi#^x&{Hg4fkKU-`eP0owXWMkm*sKh+*c3AM+D%88^ZomWa$|F_|03{Z%T@ zPS4XTDv`OYefN76+9=Yz@JL+0StrVa_3x(G@uKr}zq9J|M84ZkTyWknKHedIZ_205 zD{w=-Y#H4_S5D(CMD^-+AIayMz2+coLFkHO!`N^ORQ@zg+YNr-;XLqYSfZuOYH>p8sZ`jdXA>2Y7`iZ7LAlQP&xMYX(qjgt44VGoOL zKW*=wp7QX z@HH>5s~FnZ&9eL}b!FLbWz0n~b4&}~R?rw_k$+3eDk-MHu7^mX}ijB)Hg?d@x&|qd;Q-!soW^7 z>Iuy~mB7*_+tjF&MG>}YtA*A~TADWK4s_1&N~mMZW#53af0nmnETpUATdPxu^}=6G zGMk~-ob%bPRE!S@py1|WYrR(}vu(7Iy&(TXI2ZmhZIxTxL2)yQLki!PBXN;v9d1{V zF@A2XnbyUvTie|0aHjbW)vDtgsa)#3M4Xi{!g*nAKjS;A5bAU^iE8#@uUqW#Y-_A# zWJ?emjOSv~Q&AT&=tlm=A;-9EI9Qa}<9$Ig4PQXL*zdo^nc72L zu}l?({kZQP1|(ReC-L?H!D#BFp_-ZMb}`Oqh{kVR-prqs4eohN-t`8it4q zRoB!orYF$rQr7eE&26KS;xGHS^|fiHo_{G7($&jX4ocX#wla?`h<6dV8+2D>;_voJ za&u{~gskWTV@K+2R5oT6%og__t`I44fWnC3qbCU-gZh2egS2VY_#sp?{W@Dv<2wAV zr^$EUxZodSgkw(}zJJnpWN`fJWNfR>_thv0^E?tuXJ5Jc@xLmj;Z&4JhY}C*Y27;A zN6q^E`fX>Q1{UY+*i$y1Cj~T0=0iv|vw{t>L*9sA{7tlM#C zK*h1CWu%&>MQsIXV`m{jpYs?~e?TIcf8iQqLvjM9qp7;+u-0J_V}_~UrvkFdEw>J< z`kUr$==2f-duu=?`TXrKT%J8to(<7G@3VjG_zS*~XKeS$%Paw>I@AMx( z5j!5wHTe(m_|P^#px?8-nsW)L!r^DZAfDao(>kO%TM0ticXHY>@3_2A{$ogfJ@kP3 z8>krPzk@W+UIz=WTJKPGeHPv^!)n%s6x%@5-+WAogVCtvxOuVMDdYam>TR%|+RRb9 zd$$m`Q`!Zsyy6bs79|y)$=J4KsDT=PxWn zw`m758mZ={nso?>GmjfQO8rErzlJtSK_O>^g}!4;eqU@gs~`qcmf!xAa%;N=2*M4g zS*__cm9-GJ-r-2LSR42E*Ib>}gs+WtmNPZjq6$WQ>nQT-XFPLuj=p@h%*w-nhNtnJg&;mt?_1a-onx=_Tg@H zdHGa|tc1;HO~YtCjxjKH0EY!0jk43AiJn%;W7>@c?U?Moctq0W+V;1*ESE4Nbm7XPF7 zX$k_L;9b{4xmM}QL83%J3E`_!#s|#60x8LW))cJ&aRE#XQ~59tTgdQ7qiA8&SOVsm zYgIk2T5P0ceK*inf~%K9=U4own?AG1{2|S?WMR1bPF%WRDCGaEPeZ@a3U{}d{oU@N;*6PewR}L-C@eZ(iy&0x;@GQPp1%C z5AjN8SIO|wIy4%p)!>d5*e6_r539dMEOhE~yxVq=|LiT)WfJo3{c$&IzJ@vHN5&MM#mUcXHmNiyXerV5@oINB6mThzU;7T7OA6HwEp00E8zE-$ zwwmiqh$csPdgMpv;c0lW+&Go6Z8hE->#4iq;JT%8_wYA-b?vZ{Tw}s&`{X!ttkjA| zYx!4O$56CLs{Cb2s5;Gg64pvJ+;Dto|&o zT|(SP!80~>2c8A5$l76#b5+@zbo*qL{IN7EJm{f1RQL%-Z2=XD#CV=XOaG{&Wx8WB zhtXiBl3&{eOW@|SdSiQRxsFGNa7IP7pD=f>j+G%MHTg`Dc&l_CqC`rtZ}TDQNWJ-LJM;ukQ3Qsj1AR{O8H70%E?m=vUCKez5Y;z2YzZ4P9vcfIb+m*)I^ zb3Q|S`;IR94&Xd4RVoL72$woRe?#5@P%ga zL$k5)uJX*$`#V9pX-(46yYWH$0jBW_B&=#1a*3PDyPFlQrnfwoE_NMy*+UR#DHI;t zqc(l^ULB{VDO8UklF)9OxVC?Azt7RNpmL8NIP5fA>909~oBQ!}VJ6F7>3WiM9CXX8 z%{*%Lm(E%F^J)#E(=H#H?MBBUj!Lp`2j{Z~geyV?biHsJX=iW8 zBCm*yw5;|t+j?<4_omx}xI69J!WV50(Je!#TZy&3Eo(fiOcHtqCwsN9BK^clx1u6NcYeY?23}t zjz(pb-R4*x37jr~f4I-xXf;j5TF&y0|MQDMydPfgx`kR4ErjzAcHC6bSdAyE?S^rHh&OPnRD?AfmWu}kCS&U?5Gai zt;qgsxoY0~+N4~fXSgW3%UJ<4Hbxq4vk|*pB_~lgwiK`$XBmz|T}6qFhPgKt68Hbu zd&{7@3UWyfIfnseb5L|*4*C4?uZUu@vrNtq^-61%oSkO?sCAb6# z^5uT!eg1sE-=FW9Ofqxkli&E9)_vlGKKx_HgxijY4%#U7%Kc=X9MV*O)=^u0Mv<>4erD}S!yda zWs;FJU4p{(sz*2G9mM=JhQ!*gr&HcbtlyQ7#?jM< zZ#<0qEO`cNnr(l02fF?mri5B-<7$+!1bHAGJ02RZfH7(UnE2;kG$}r)7dhMS0PR?b z^LuYV28ojf#5Fl5=UX;TMCIG}E=h4Xuk>O(o)CIBH*vb_Lw*g>OL~Tt(O=c1lf&^s z%S)#Mg)4D8cvF$6eGfIX_8>O7V$E)XPpDJ`vWc17V8TAYvd}KLOQV>+RX6Si&oH2KoKiI_e?A$PtnLJt zC)gSI;fZvgQQkrOLz9;Nu9nB8!f?=&DCfOztlT~ONrSK?jFFn>W*gv(0U6^_4{~;b zM3_nG5i?cbWS&WlT{rwx?-M|lV0ts0>zM+WSl)LerMUY-FI_m_5l!!6{cpP;S=L!?Nt>a6{R6 zN*v{klO&mEMHRW`+{Q(hbiA;w-)>qP zBX~EMQfLase?)(X-XhCI8bOC~=pHJK`!|;rdzOf6HvWfyz&RiH_S&%B}N}e z8f6u-u$GsnyP++^I)~0`ld8+|#QItGrM?*4lRE0d(d{mcS~Wg5T=VUNjOe!1vFoX` z*f-NeXzrlTo6l;@Y|)hqSY!{Rx$d8xr0jf#3-u4ErkZ3>s$c;V3~GPh)@OB1^z z7#b0xV_uK4xP6ZPyh!HKV%}+>Qc;XosK)$<`y`BeX)TVc1?e4oo<(ojQWxiaN#gV2desMC zCrs=RR#1fa+MTn{)^V41|ZSS7LQk}C`og*`kUv6D!f*O6tqf^3V0n9KvDM(|!} z@bC(prA}65s;4oo0&L;**HT3D^SKSRop_(%?-!Gv>`rLyNsth(bltxUVnlUTA$r=h zuAJ8zoT)}JqfzYz%82#b_|*-teTUV{Dc}by0RP1Rh`#z=@fX9d-jxT?a^aC?P#PCE znqVM5#^1+jb+>j>-grO(bwJx|v)nOa)O^7}j-Yh^!&C`5Tz6cgK7U0!(HOI_a#;KM zujI%ZZLu7!CUzzh+wReg&iAo;ElJnEQgqhv3UgjBgI{~qrC29zCsC|s*1XBNI{8jT zlzlr`YYE&Z@;IlTKB=n|_&&3}%xXt4*nB9hCjNOswH8hnu3B*Ttu)zNM*dIk`c(Wv z?BIO(aDu6>?m?%^Doc$F$2H2pTIXl}DZBTV9B~gGCoGNka=`^$O_caXE~f`23Y;<8 z;ut$Dm$g?x@iGRLAR0&&fJrO6P2O*n0RJ)(T!(=T4TlYwI(AqIw3> zii3<}Ew_KKr+X=`#Bk~R)m&3kPsa#Q4t`dw?lo}{otEKcg732`{7&(>7r}6}q=XK3 zYwQ^7q-Y}OViX0LyRT=5U}wggpVW95Xs2o`SXf<>az1YYGmgaI8=cn*gRW;2YAuK7 zdjccINfHZfcxaw6d&C@HXU08c_rz%gCeu4D(qkG|sWypo?oOHBJsxk$QVyYyG7l67 zUAN6iYTFb~g+2H#CI}7*09-ez{U@>?*UB+4K51VC@1jSk$oh{p{&YUP&Cp^10$Fcb zk6eGzMX*!y7m{j0#DtjTI|#R^sD*h7I${(iFYD*CohQ8*m0bpl;Ufa0 z@BWeK7#6xun{V1}I4qAOK1`_X>$m%H z1Sl}%cg+knwY#eXOjz6-wZnB-9BX&`Gpd?|zFAe{#+@EaGjnjdCXlAAfXSJj{t_ic zN`U@ZQiW>fVEz58&vyfO|L16+xaPn(Go{6_yS0Rt^sMvVHLS_o%&FI&sj4xGW6qFmZl0mGHhXd0RK23mrQF$;nlT}XX)5rGe} zXNoUve4Q1)T2}5&Z3(=M9elrVTltSZM2e<&c?w|CWS_`|CG`}5)LXphP#236vDInR z2Wjl|?>(v0dFb)W3FZlq<~?%Ma+%~L&ZjyM3{sN`5)ef8^{p-lkf{0u&g0(P7yH?aj`1_8LHf=EMd9K8u)nO5AFzGL9NB2^CY`D&M zAwgr=tIlI8&oXT?!cWo+5vrat#&wK-Y2s zUa(MlFLT|cGDpf#$!SEEn9$SM=vk)ILewWlC&VxB&Q1=h6bhz_8 zUl7*uk*ccQgX1#qrK~oKBat>_=>a#XDP)3q#tp%i{>dw1%z3_1T1;SXU!tc?&K#VL ze>9bp$a?0E33j~3zAxBs2@CS2iuLm9Cas-BymORNv~&*L;~mB$(%~(gk^%Z7)ye+g9(K&I3ID zwIB@R>dUotk|mj|`<^;o%S;)K`(2I1pjv;>$@@-U<|ThV`8{1~oRoYjYP<_ayxB|` z0SfA$3wciUFBHJz+ty;9^;t5aCM3298JldCL%A4t@2pdGt*wo$-1gi-U6rR3YL)LV zWNy4Pto;%K#9rl_#Ysv+nE+L?L7V~TAA{xz*?^3dew{>}Eul8XTv4AsAePi)ab`;2W#lp!LvKEx+(h#*AU3!jDWP%`OE!- z%~+N71fK6FC+o^U9yh}#^0%FqNm&<#$_D!&CUFrh#r!}sn(-!pL^Br&9VVkj&)Dv= zWHGW~s9RO(^R6Nfjhh5AGCveC&`ky`Q)=*GKd+0sK??eA@>WWdF?1MSGVLz_1Zx!R zjho2tJ-C@XWKHg-mUwfbKWSrd&y!JeVjnZ->b{yTxmTeX$e_1fL=T+^?j4QUvo|Uw ze3(1_OJT1g_CMpLllpCR&wI^-X|Ui!2Rp_7WKJ?sshNq)HYEl)-KqwV1b4%Y#Cflq z(K%NU-U}?^4gb8~s8od8V$&?*lfI;z?9kL&9cCR)uKn_SXw7>x>kkUc2PCkV&$4)lli^IHO(;3pet=q1rnFioDF*8g67l z<=-Ke`53LK2+=*c@*w3<&0W+{C}|^r1_Qy*Lwo2fgdiloOl94viGh^I5l6f4rp{Qe z@|SC~6TvSa9od(9IroaU*Pg*^1TOg5pUy;du*`;1R8d#??Q~Z(!xcNg(L_g5S<)&j zngy2+Dk>%E+c-&B3c!UgN06MOydrt%$!MIqlV_T1j;*?r82-yZ#!+vfV=@|qNj>TE zTnUN5ynlHU@yD1V&crtg*!QF)Wjny89;@uM0hl-#n<})w@;Wm}80$$wzxw{oIg%9=hh{LXJZ|T?6 z#QGe7vG^2Io8O7o>nMgH?-Z$XezX%$YG4 z=T|rySog%w*;^MbYdJ9u>WCdIYgclbdy3gFP3C*3z1zx&v5=q|(+sl86T~|Ip3R$w z*;NO^CuzTV=D5ez2lL=!?~E-?;&Hk)UzA=n1RIo=5n3CC!oS zlhrX1uXognP*qYSSTurzv~sry$RMicX^dVfX_r$r;gVsSl7BQF&^^UqWz%W7BM%pGs#Vpvapw?<(*PP0= zP4D4dVrt^Wv(E{Gc)HL`h-ha>4IJD|Qwi7R20aM6k!L(n+_`Y&AKgMDvi@*;9eYlc7#UcW;i}Oqa!5Xh%j46MuOL(;|Gg2p^OrMg-q8 zF2$uG-UjwhTqR|N<*`P0>ZtK7l@*OQBR=h7a1*%T@?D#o2(b5=L|)?2+M1i z=-M@YwU0Mgo&ZJv9D@6-3y7yTMk9xoa5kaB1GG@?qe|#A7cf(N;O8~!;}y9{&qq$X zUCncMlP5R8k^04+MWXpT4hUX**_AmO5##)Zu7sDyX%dDLG6HyEqBpTh0gtF4xnioE zFbOr)><9RS2f+caH1bXbpZN+5b^)r-pTJw5BV^F_>#_3h?k;qJ0>xLObbu4?CuZbDF-}82BdySIcLac8X0qo7g zhC6F2%rRWiFe~6-Kq7vx4$p_k9XPm)PQyYW4u4M!!uZ%gSb#1+G4D(m(t~R5y1Sd> zHD;Wu`(&462#`93L8cH%fcFCI?2WrdNSSM`bupyOEm2djeUdBmil@K1Bdh+%r`fZ6 zxgtV0(M#YGt|?CDK{{yE)95jJ`IZt*iVXt-jcKh;P6@4Q!D)u19W0PrCV@jVVY~KZ zuT_YOX~tAfO(h4^@!`p&BV1}^;YIlR<3(4f%FpF9Aol!)WSA+M(W?45-AX-QRDkTn z5l=Rn%hAj&h`r~{oNkHmFmEOG#xL_Vlx(PKK2BV%Q*YJG|dxv-6Ph6 zo(v*8t4fU-RN#Vl{-Ud*-ai-^67Pfp0;w+VTeLa-@9&hE^7aH2mg=jpX~0@TlhgHZ zJ8!So*E*o42dy4Y3Flw|pv;O^H&lq)jA(N0d|u^^iibZ0SMyy$&7omb5>1 zqq#L#3b!!3$R>LzU())e%f)h$btd{W1rJ}#eBp|}-!T@(m7%>aED=jzG1hQ{_z8l9 z5>WzZLgG)R2N2>LlnNCKr<3mg)&eA#1IRz@@aF8Rm5%eE(-D6JT>lx%=fDk@|H*83 z_BO8>^qAwAg)g`RD8;i1>?+{2aA|%XNvw&!utR0Ju}I5WXYT2fFn=pWEe0C$bPCq> zjwsT2)2yHHT`Tr!cM1e#nHLDs`b%-HEhlS?AnpolTyzB zH&Q9Nl#O5A^5+l8=airRO;XuWUGcF+LSOOPu*Wkz_wL>fOx&K3*t;PNiIoh#{hDBE zj2cS$Kv6|mDS7}ISR|>UL=y{4Uh{zDZo$;c&FXHsl@QEsY*Y(Hy2b5qvkPIISO!qA z+9b(RebU-L@4{#FPg0c05fF+9RG|{DCD&SSgL(6Z6`VOEu;Y5yo-HXMpV_SjdlRK{CWML3cJjFT_ z!qs}KzOshrBk>SbzheC7o{2^o%=qXw`Ra=RfKu@J$=`+0t<722O3Vv=fcZPAvDCVT zDEQsG#O6(H!&~ve=8qu{f>MzIq424lgHLjXR(v1?grxn*%^Q^XcMW&jO7JlcxpNWG zyu~vmjSO)7BSmuFA*lex`V$6u9!cnLJPk<|2&bV<7c9j^ zQE>L>%c*O}C`Tni4e^%n*GWJAEpbEEN2}RhQEB}Aq_?)F@(Axz2gid(?~#p*n^(8% zwO7?pb*tUt-vJ)LBa6n2`>gFD;HvKJkR`U6Y8C%jbcpxLGk08l;ts5Ki(O#ocZI(M z`pbrj0nXcxcVE^RKntB&5&jueCLGB5`y1gQR-i?m zABxx9*)73CAK&owsvplpYkf0SbrR$Qyl!|hy>;v}!1G&(UEcl-Oam^sZOoa7=GImQ zyl#tx7d{sF{EwB^b~8_K+qI7gK8qrDrDN_tw_M*8^lX<qnUyLK_`tHdXf$5vaQcGuo5xBS4a-iv*T%X~QJi;Gs;a;%ZK8V=dv?zWkh`EhfZ($a=K3t=fiwexRxUAlkWNMkH zM>21;S9OPV@ZhPs>dks4P@uc!hGwA?uFAQHY=Fx8Eb9)mP0{> zG7nOsBbG~){Zn8sw&S}lY~mL~lnCb%zDK&=6X}RKm3BUGHBXSfo|MQ|H3ee=zQme} z#^cLZVGe$)E=!)!6ZbG9pee>r6rs^)EGg>uPQ{i5^ zch=V^h+HwuhfTTSpNKWIj?C7}j`;&az37ic=i6%PX!0cfnp6e60c=Qout14k-rL~I z?h?E;z?U^h;|BbaZ;ZWInNs^zwR*VQlebk$K@+n2*Z9cPuJc;k&=?c8HXc}3r6nq` zc`}{!J2NGiK3dX)>PQ(}Bm^LBcfpJ$_iY-07@$q?ci$=dy1y8B~Yyogf@kwNLMS7>RYdZ3}l^Eu;#&E5!<=*SY#{(&rU3%6se8a243%rBPU8*||qMvCd$MrsB3wtDta>L7leN zUQ*uK$Eu4pHayt4l*RTL55lb}=Bvq6=Cf{#nAY)k^CRA)bmC0OIamR|>YcDpMhsA3 zN774$CF=j`vB7LI0_&|2fI?`sdWw@>LBS*0-T4N+Ij!Qhmc}jv%SKRTjF!=-oxje2 z=2x;w_||J@t0TPq7hT@w14e&Z)!SY0npwQs?U=M*Nb&xwRR_uK$RcK%0|e1$kT|<|j3fFE$(>fZJ$A3n32WRh_M`C| zM{YS^Ed+JL!c3dJ|24zWdlJO$>O>pd^OxGEzGjCHMcqU5NBVZ1g(70CJeTeLr03da z)fox+zYgh?4zIqX;d^1S5%oLdvY!U1;XW5O%h0J(H74Ehz7$!R@2E%ci&bN?W`i*( z-0^77&xIwuto-v4g+lM>(<&R|_ixS~Tk)K?#jhV02Ig*Oa2qD-;rU2K*c1Pv3LNX^ zk{{U^0@ULZ3Yh*G^L*HrRhgPQN|DVscx1O+_y@0J1r0BpN<=?wG@Uz#-PK+*c9vLm z+U~sEH?Zi81A%_)saTh~!F2ZbjMr8T4-0yw=o50C{|nvlt9}jzcVusL$v1O*lzH9? z!q=N(m?9Inpakt#+%wL;s&^sYS;w#N`5#^&PFZ7^Gma?3964)ygsc@;d29NFklSz) zU&XFLqr&Ud9v7><$B5JRXsz?sLoN_|vSW0Uz&NOq4OFrx0 z9D&BWG+?Nk9&lO@MHgb$38kr^uyW+um)R!%mrV*vWLL3!yhh{l{*#`g8Om13zAxVo zfFBADK*=32L4*Jy-Z+eEUE3XAX2fuL z-<7_8-7SqiZOYXc9O^&Q5xNYXY;zgAADZmCbAK;HGj#=g3yEDS2b?FxbXEkqj4KBE}}o>2}buzFT<1tbYT^hgU)Czcz?$-ux(wZGQ( zZ5@C(aLIj6c3yEPg4MZXdE%3KrE)!mCv}B|W>P7;4dPG6&2_HK{#8@=IL;@!`nkgR z^|C@}-b2fwwOW#svfrDHS$!$7iX}@6!n-$qFl3Kq6-~`(0$N zq6xt(BTp1l1x!~y;d=*Sz+FPQbv2p4Dh4mf$73$9zA#6jz2x`V`fLi zG}X{gnH=2HmLkb1|9O|?(ZI#crj=(9m)ogXav-$m25U^6mg z8c*+Lns1$}(qDYg;HcFbkQ#Z!Ncbwubi9M;8;dsmDz=LlH146o`8n#6ZtojRVI9dc z;G+dkx>9ss?e*^z^IVPQ0wOM)gGr#93?R;+c_73vj%qF>0uo|D1r_|Y;{Io)hNB!X zVM7F!$Yh4bUC^q)1d#6<^p?50Hd{A2ZrX?2s3J{vZ&&m8e0kSA3KBb`NaeDtHngJyHiRHQD zcxEzvd7t45^93?Og+5A&n~<|T*0lj=%fFKj*^gHe2K{FO_wyr7(Z*IW{c~_Pp)9}# z3Oj59#wXXgLL_vX8Y#fpw5ud1aLKA6?)MvESQ`)b6`{>(7-*jof!qB^J$fkynNt4x zDEi3u-%zG7Rf2n>$K@ZLfS_K$Ra(yAz-2?|-c|IyW&BFbkImeJdI-uz8anbz zyz2KX+EAm{XmygKOUXx6#&z7Q))SKD)A_*93_;CGTRfyvZ| zwL@%Vrw=%{Mg7`uKwrr`!F$g8$kGGia(YA+SX&RBy0@}|eG5ptIvjPSK)|;HkY~Dc zCGzZzKdI-x-F1JGQ~nyAA>(`G3?B@l0rhv$R|=kMb5E!3A&p18q9%H?XN3ohI3@-i zO!zAgPCV^4E)s(?Vz??#%K}70eV|*~c*Mo?Kwz{lN-Wvl=c^s$%de*!R6@Ic^D=SS ze?WgOriR;6u4-moepg1@pYl;V{xb{hjHHLJFZjW)v)8Mn@HFbKVM2cJMLT(jaJsz|JwiKDhE=}qWTjGN6o(LlA{bXdiBafy4MAt9YktCf9n~lLj0rgL}fZvfvXD!F|aZ(5WT5syXC4|yvOV8HVFpgdEYgVQ*BA!ypn0a#RyJsCS1(RGZh1))Jj!SrC5Z`H64{4cI5K)r^ zt%87~`hb)H<|)5dm-NSuD*x5MRDF1hME~LLY_d2>+Yhi?{D?d|r=;oEBTwLBw4h4% zwNoaD`@j!r`EvwtYF#tbKfFEE>1thl6$gC@OZe;3OPS{hjlH7)2z-nj9CC>`mIpWi zkl#?M$Om?NLK>fd0j+@~EfglVkQh9;meHE;f$HCY3PT?nQMt}ReJKX_MahYv(QM7; z!+#*k>8y0~zC&dis}ToR&3}o_tDPx0i>0$$+C$8C@#DA@~|L0pdcEHk@h2~ z=XUpl%wsf5PNa9gS=iw9{Yy*9X;i;6sju+mgBVMka97{G!mV7cHOf<#Wn)fgjP^9uq#+jx$=~FCeOBWsEb=q z;FvJ?bKcr<(AsOjp{z1{kBt^n4mq6p^)GyvGi&4pW?J)?TlB+Cex%-S#Ev|Y<$ia{ z^}W2l;E+?>_VSthU*c((HQX32vYR=WyaDdwrN|>j3j}lchf0M-_kKtwPuS|$m83xx znNx)Zp30~}EFH?cGCR_f>S`O*MxI3l1&CB#{LF@IS$^@8B&d2dt^x)pt&=)Av6TZI zMUquR@!)Hpf+jygFp_2hiSDp>XH5`Us!FB~GL5c4RVN(O6o7Kv{EvYtg9TCg0ljM7 zD~Tbiq>4lO-%u4}RuIzYckiN(p4<-x85qOsW4cvA=;NhA5h|Z_avHItq&wClwQ=Oo zSM=Abu0rM*1z|bpQR=AeU+w-b)=2UIZT?ina~8NlYY}oysGpB+PcMqFiSywNA%D7n*Ff6(hmR< z!)W|&YCs$>*8|A)5Kni+>qlA}P`HY^2qVRdGIJF@(g6r(tl{x=|AwU73+s8(+rTb* zDbHy!2u$>+I0edTfKacI2CZdhX>Zy49md3v^>Uy6a_$NPKbM>Dfxed9J56G z^XX-dAMt7Ue^?Op%0N$C40r&+KEFx#34H126Ds4^v);13`ZgX6!3#&Oy#kIDPC;`R z7bO~c)|%%5AA@n{wa$%;>lgjK`;4&Ct$@?zeda2h&``KaRt#UlYCff9Rp^==K;z$+ zg%4UBg5J|*OF|)-7ec1i#NAZAFy>hTw_BjS^ln$=KEVr1l}HBDAa>LAf>VL zr40*%T@L5lJnvnVn8kmY-%NZQFpCesV88?3L=wO7eN`KAgs|j6kDK%NIG^QAll;d^ zQD;Z@RyMh#j0V7Ojo*F?M_DG;|?! zCb}TGOTWY_+#C@%x78+=PEt82is?bovkjIi{I7R`&|kfrEW(C-22U8DTz$5{2%j$$ za{jk}8Pgj%UezF;z)hF}9UE2DJ&YgSXPB1!4?)IqnJ~@1Nr=()+|y?7busuB2G+r} zFJ}`9D4lFLrTSm2`~S{w`IwSSTR5RLjw)7osQzm)3l0cLCUF2m*e$bM;(stX(v1CU z#9%THHW*hhl)I<4$HPMOSdsAOoDti9>;ae76nhMzv>flBhN^KX*ic*v;3zw`kN@|` zlx2-)^|~sBig@=Fp?!QCYA8Dpp7x^Q_J2)S+qK~zeD4Nky#TYCm6uawOCdDJ(g(M;zJ1LzecK=T;|r+8vp!nwzNI2s`HMV2D}&tH*$8?0VcXDW-S z^%jSLdaw#z57Iq-W*j!(5>%V0ch6O-SC(NFVyFh9R1+%rANJ02VJs5fA@YHz>~`C7 zFs(`#Hi?g2t7yZ#wR8m^|1@dCzzV2W8gT@>ND?pa)qSGx{DlJT-Lh$Io%hNee)Xn; z+4H9z3Bll_8^!K8HLJgWsjY1z%MEG+_JR8Pnd6#hb)DL0a&nq)-$tB)@jrj2ZZvgD zX8zrJ_DI0U%fp!#m@(t__aj;B;j54DH26)AUL|h-nPqcxlwk6@IxYc@G*}yqlhK|c zB6xncTHjw%k0u*;#2R;B$u%=yb8C2BF6|s}biL$yT4zH|?adWLL$N55_bQ>Jm_4F_X?xeNv9zVR2gmwn?|j2OYeBq(sfVEG>S1;T0Zn4DmAG4i=$ zMM}L5v8sT{FowB8tVx$ApG7?S!)jY^*@s3`afnY_>MrVFYEo~bs>9Kq8t)O=*9~pmhXTj$C=MfmuO+G#)6?V2fyTt84%%BMJukej-vq zp7hO3*FtX$TYVYX^)CjI!Cl2lv@#TnfnSs;j2beP{QS}>Ly`&Eb~O|}nYnbUvX{K< zF8!9~Y%2UiHoKNEEkpUa3MW^@drl?HcWi?=dl5PH-@l(qN~zQ}I8suS2C}DShblE< zjYp`-l=bx=U+kCuE>z^pk(_&9*+>5V-|e?TJPQfF;nCt3{BdDb0v=6HMRP+5ji#Kn zY$3}gHo+E3-mK4Xl;0Vc7&xQHh-!C>xOP2V7Cty>mzz7ItNAIpj@XmQi{4v1$}+WU z6Gl6&%3u1SGT_cW3j_Iwqz?O?t4(KS#s%HZaxQNoBqWKVl#OBR?>DIy^BNs4nCa=? zh}%QLv~rf_LGBKwWyN9N>O_A_IWPG?P)rUNHn;=XdG+j0D1&xq`xeyditebRoUUX~ z>PaE3%VgNuxQrpZJr5ysy*c8`4Jl_qEpe(*vUF}rNKN02(w|GLE}jmkqxkq2hK81+ zqJ1Sl-_E8fs(?OAOP>)&@YyeUft+c7?7WQWeE(8Y-;5<|e_;m0XXmjqReBPJZ~c@e zrO8k1vvHG(>K%^8jv|uTwHU*#b1IBWXlMIzz7Tu+;vcm24RO=fP94R3OqFG9Tpq9FL~T^fymRR~+0rw1T6Rk<__ z$H;j_4MPS(6`?M(tPb(6DnPuSAnJ*pb5}^C;3YC++hV$4vM_fdTi5GZ=n;DzR@={F zZ0mmC2J@>JOqerVIr#X2B6h#dc+o$tx}IYN&+^k~EQKaQlw;3n+GGwpAa6rLW~rz&?p+?Ts%-0h~T%P-rl zx{;24Ad7e=)Bf$|Vr*oXkRQV|(%wKL$c_Cqtua47Ug@0%_&qrf;|11}fc&!YJL7v$X zK<#>462q?Cu1bR$&(*fJ6fD^Ud)05cp*aAuj9{u&C9^6%!z4bmeHT! z+5D*6EJ)uhht{-hA8k@sk8xr?6PD}j`yBF7`|Vrt>s|S!tDH90G*g3j?|2s%0sR%`|)Gh@NnU(f%!CQT9tQd+!~`G zz`0_;NlA3rn`&5J%cdqOh$T#5geUJQ_abayA@Zi@;I-?z(*{oS`;xGk9fgt9D7l74 z5Portg6nVLD?j7(JkvJs_xhwQeC+LYlFr;%6nuQYF)JYfzy8%xtdA+Ljg2+U)2|-@ zY8d0jo_l@N5E%QEoZP#!Gx6U<-&bS02(MvgeC1VGqMqs?4Z>VCn?i|MUex)8xC8qM zWI)eV4ErN7_i#F}A|am~4SOGrxj>Zov4aG5W?I??CpJG}6bEJ<8y;3GYG}x=_2Ghh zzru|p8-?hH7|ww+{^sqDiqvrk!?}viUv&5wD z9cK?J<8DFz*oY7C6o8Lv*9JCZz+Ym zCS)U;vj`J$q2t6s5y&L|~PXBg;FQ@R-OcrMN*kPdaP7ajJ; z9Cn|0!|INuE*|t@`4&>tR;$TG-bN;iTaUd*h8UM@k?gC!XxKu+tj<$CywI{^9(BHy z5=%*bwU5XSzS!h$;AUiKXs^o1_$|4f1V^kWiw{03j*b2|4ED&;(md=HBL$~G2}26hjc!EFW$J*}p=bdJ@zvn33Y!GiR9jTB z(YW%L&Z~vuGVWPJ0f%$HTjs2*Dmwzq0i&YP5C(zyvAA`=c69h?KgWI##b~5V{#203 zu`pt|la@Xo&kDypfE|z{@h5jKDd|(El`>;gjFmvm+kpz#o)qEx6}mQXhw?DmTz0J#sn{?q8nVeJ++jSWxKDQUNc% zC;Vu~W$nB>oxPWdKhR=AJ0FLI#=1K8n-Z(AGuAvarY{66&HEYrI|8Y z)2aOzwHj;6fDbmO1-w^={u_LeFKE;x_ zTSK;$r1^+-Mcfnm((S1WG)1Bfm!N5*t)-Ttp8*2@qOA(n-l~&7;!qg)AIpg?F1Ekd zBl<8KK4xp1PKpOs2t9Nl$$fceXn0j$Xa8z5{)@xN5e#`@b-3R@zZlb4NnF1W$NN<2 zn~mvLsxS5eJ!SmIAVJUj!;= z=Wo8BbZ}q1=f?>;f7w;{b2$QghO+1ik5httJ-be{Mu;DGeb+9x_b6RBO6DkcC(Ru{ z2GeD6ZMt(xPNsMkgNyO^q@rQ{I%<4aLWjWxPk-c?>HcdVlv5QdAuZ?tR%HcHEfd)% z!^``u3BQi)<}kc9-!&7tp zjMvLM0=lSaZD%|(-tcQy93T5;JmgWJ-8$7dr&;(Wnn5$uB`2YjR(Obe%tY=P9s%d) z-=CU@tgP(Ms+bI91S>1SOZxd_Qq^%SfI?cILi4?x5V!H)&_k5j#Ax%H6gzDe^b3_`}dw5l0UMym(}!Rol_mOw4zJ>h7r+`rVQpBiwPe3edU z8$3~ukV$JcC%Q1BYK{Dygd|aDaZx7fTb8C`?j%7#SE>}_adJuuy9h8cZD>eQ>bUfe zoufGRudD{I;;7JXmfRn1j(wFr#C2O2n`>wgQ&Ur41<0SCof$URQ&_DC&b)rs^N2Oz zwW{hPm*$)_euE8AJ9b%h^^eL*VnuR5n-}l)_O`f$gow|f$-8&w>tca{fuHpCKN=Xo z>TJfI^Yiz+G>Zk_-|jJ0S66@f^y$~~vPMvlyheu58*(qHxYJV)EKyO>;qh_n-O0T3 z%gc{OMx(jXp4?ZV^mKH&0wq87UtGOrClvMbGk)o|PCQfpJRBHV%r4{Yjs5CXA7)S! zMKzYYV;?H|VAD)*WN^K;| z-E^qScPV-t3lDTtOj`#@DxUG|TbcolcbWo5oNR>e^?n@xiHaFYC@;s+$apuN$@Y7# z2I}XTY4QFcOwg3?k4Gq?_GDVsa#D6i$-iy5#?;cm@xss3Lq)%~Y2A$wegLseh^P@t ztKgG%A*GC?H73U^Dme1jM$T@{oaCL(ZX_4H+nVQ;YK5qN5N-GEwlFrl6D);71S{<3`LNX6PFO8BIm_N2_pby$+*#Y$U}W8T z9cw$^g25O~?wU7xdJGH3tuCxz(Jt*a(IKfr#)E_6?IxIyiLU-zcOR(&4CZbcd3bxEoK#av9!GRV zzYb1)p?Ye%SwxhWK5+A-a3VLSVdW2b%Yh^hJw48p0_(s5&DF&J$J1LtW%WJZ!+@ZK zGy($B-AI4v25IT;lJ0JhmXaF)0C?(Xi+_xSy-|LbBY;lq0Fy>rg&*?Z3!>*ePo z9U`linGfxGyhb~3FMM3y_d-6oo|#G@lFd(I>R? z+~r(!BD`=vni3ow5a*>C?^IL&J{g*7?D?B(~^P;UrX-Um|a zwih;J-g`o)Ca+la7}8pB+9|(~&^zZ9N31y=Z=Qc)0}+PBV7%2EalG1+a&t6izv{Yo z@%nUTe}Aq=-*WxEvZ^ZDC~1fRXorQ=m~`sGwzf<|@pJ}#zrHNHY(?0nklqjJymqEo zw+?h6^WoJ{A0HlWUi1-&DJdO0aj9t9!gxOn>6|~kEV~_*BubHglaw47k!~eoWn^Rw zreHYJf))@}qBBhnCZr73$5x8#AAI!r`4i|QXo$IR2}1#MG?P;#Qwvlip^Y>G)@P)7 z`%2?~lUW>|-V`0g+ z;Uiv(=gX=;qMcXS{!)B*EU7(1i+IC=30=R1M6s|ytfI3L_TL|AL&NUMixMsK-8?== zyAjrw-*E?P1-DLd6d6)_tK8^K&O_XGWX4oHikOsppxyRcNS`$HUMGWvI5c`j6e?D$9Ryf`|xT)^@rF;sotu zCtaNbF)WU>^j8AU-`FhNNl&NUG48PMUTOk(tPO_;j4Np$ehF`+ z)gAlnXMrvYWI2?niH%FA*ShU`%2uKoMLC_Tl8KqwriB$K~hKa`rTy|nusKCI$iAoR;qda$-AV47HFknRF#U&*rO_|MSivuF$ zyuJBkd2TSUv>fCWpAn#;ny*H=FfcJiSE7oFiogcL;B^s}_}(ebB*XI-n-33U?%2;^ zf3bqHVU%jtZ$?Qm?50**e>d2_g_AxE3@z!y`cN?OX808fD#r&_vxE$OGrH{I8~?&L zH8Hl_!q47_Ti%hwSeEV2nU1t#htz73mY zy~Bd6>SYWgxc^V$j=uFX^EoC4=}E2Qkun$|wlf$9w?m(RkT4WTJ7lren#O6rTkd*g zoSd9I-|YGiEi5}sNe`zLi6!1Xc(AauQ;^=}m(5v=V}ZfWLxqKfiR{+eotj+Er=%G0 z8#WwZCf;0raWRgJn=$Oad-DC-> zNz8rS6uf#wc(e5ff7C|T`+$xZR)EWXaBx*P`S-4%=-`J600$jr9{lmDg&Tb|FD}vMMWi1z8R*vCxYfBJZQm&`|#k# zC@CV(;joW_rR}1(`G|Af9=KtX2%zU?PuRoq9&ds!C-!FsFOPqyydoy0iHG`ipps5~ zb+$J23zyZ-Z-rB^QL$7)X5o1sm8qLIENxJf$@UB zhnKke6a<67kgJ_ktpNrX?i!ON4;wIwh&)<4OZ#6t_$K27;#wbP=aSoIO@2rB^u)Qj zsknqekWy4Sfa8LOyu6aGUxE67)DNexDd4-x&b1^g8##z;4PC#NuI<6ArHd+}^*e=q zY&e}Kpn&$b{VxS1 z^0U?_1UI+cb(`+ayV)5nAIibuq^oC^()0V=GTGcbijX@Qd@-eGe2#L1rSgkp%s9> zD#L-8eQYcp58LXtEJ~02jUZaJO49$dm6SdK5c%b{1snV!6{_2mn{T{nL+fsXwX`gn zZ@6On`qc>+YF#39%1lt6<@V%iVi}JVThW$7>i%VLyWteByAncUBGx-6v+s>L5rb4| zr-su$Usgg-NdbL9n*mEj@x1+-&W!ZJn%lCs)7m#hVwe3AwH&%0^`5)@Sx3i$;f#!ZjVhbWZq~W^``5b`2Zw!~KXcj$6=n)j9vZb$Sy_S| zXLCoAl4Q3hk{{Q#)RXs5xvbLzas@;J!$-)=b$x|hT@y>`EeVrS*{Q2J)1dzT-OWcR zA0TBk`PF?j=KgtfgA$S>CM;UnPGBD%rYh?GN39d7P5O$(5lAFT|@BkBcr!K^TZF~I53@ueWZDX#JitNh}zPBLfqXVc;i3{@^5=N zu?`R<0yrLop*zRjvVDbm$^41aY?;m&t~EG2PUu}>VWs_^jMvMNjzLYYCOz1Xe;RI< z6c%>w*vV^^Ffd|FvU@2P#honGT@5pj5yC>5q&Z@O1rEvy@65I~f{d}g>`2~kuC5lc zc<_PwWo7J@FaP#w+}HtGwS~IqoeghTy%Xq>{tdo<&IXU9c z{)gMWCzHWs&;8Kf$F=-o18A5Mu`4Mj_nk<>h!GYS?;}ez)MgU7=N3bL{&};0WOuB$ zG(lOxx24k+8WTtjO%HN`z9<{ujt#16W43t7c*7%QR@lx8qfHzsH;wK-spE1vEPzOU z|8#d$@z#0{Lz9$5Y|O0b)ewhkU5yUg-KvX#l{{a^VEjS>+X#V;B&3%KCyidd0PQER z(sEmsQDeUm_=uQ>rG0Kt1qWXCE=+`wM{B!wi5mm6_p}4+lY}a5 zUm<10aoC7AUvc05YxS`4v zYb>*rd+u2Zuj7ryl##)xHu09%Jkp1$qhlwdb$R?rQHHRY9==2G!S;;QbN2fy0EHQ` zfA#h)C6X?&s}zWAUMAqVo=c088b@Iibp{Qr?1CB`wM8h?tEJH zywehv-!|8I!a)+F6|prj0n?uuA{(DX2SHJ3T$R+>DaehFTuFP?i)%f;wl;>yzU(t% z-1Vcz?yw-Q(*4d#+w(^0_HjOY>h+44R zgQaj3UmM;jd+#Z$OdZ=@{E&cKqNefwZ{-MQ{n)p!E?56NqqAc;m0-1Xw$AmsH~W|f z(l09lH!NeP+~{6+nvRZ|%lYR6sM|btnH&4>iga%5*ZHM}-LFPaU|`5gn%x zChm6_p3nnok1e9v*FH`y7GnLE2IbVm&zP_AnT@Tmx;j56H&oLpDPmPSA_)JIXb4J6 zi@M1vkaG`@2201nWJ8eI`^B73qqckcrkVvcLw09`{T+X^621gMP!VpaRNZ};>I<3r zo5*7LF;uGNIWA(XM5GD!19Ot1u)O3w?jrf^qJ>N`a|-&?QJI)ESG|_uukO9Wc6++h zhw~FM32SuMX_)rREfM^!o__Hr7XjPq#>_~eC(+exUqC0gOjHZ2^;_J2wcjQG@q?FB zpUc03Xb9)+&RfFjF*n|=OJF&}+L2WYAGy8$Q6^vc$#{49!;m2(} zvZgB6U2o{fvAxX{(rhq6{>R#M`oa8TZL}Y@2qNP!XzGyNQXS&y&E{HX9JuDH36i#| zR2;6-I{Owjad6U%sYB`qdc%wWqma0ti})MaE3H{;`{sPhl;l=|&Dx`BVi1PN>$D$v zuv^ou?`V`u&Gsp`GtRkk>n4JNDrlqATvwNIg#%AI)$P!-`C*r2s^vHOPxI0R9u_!p z_;Z3-#`}}HNLL2V((zT~?dK?C6;!_B7bIg=*FT#R`47{1_xp`Uz|!TDgLN72;U_^j&xtv@`M$g&%^zdx)Brwm-6h06 zA^PgCR^6L_g2){lkR};>s5_0{wNwbmnTwn_KVClh&O?8 zoWgaf!~FB(e{5yBJ)5vd>3nKgQ3EJ1y~)A`)vXFd_Ys(N3=MzSTWOoO(4i1J#sKHL zE=-Cy%a{~nf%nKsUIjsMJ~m9lnc9?yi@Y*$n9JU`T;_ahajRvIXi1|S?)(ibz<=cw zW}8lr1*W(pvq4?h{R_NrJ4QW(`Tl7e+x3dC_n+l{C~hiM44Bwlq8~UbY`8pZxGS}p zA>K0YwWXRuElVS94UTv;7jMLbEw77bd2(6s$DY~Khnu7S=zghrQDjt}K)P1-B!Tlp z&7{9fq#Y2ud?1P;HLQomN3CE=5>Jw94#%Pp+Y*Ov>nNijVLo$!_cD;|)>FL$6d`u% zF*MY-OWO9+?6!C~%OmqN`-ieAe7&SMp4l(2Tr`KPq%F?*vi9>QxkfiXl4beQ;%m$& zdfl6*!OZ}-gH&`1TO3a}w}v%ftqhO@VuAh=eMpo(ST!FNhVIRjOhN~#bDzh(qcy2 za15NaMr7lgyLWQQN&62D8?j(9Y%9%qN0C&=6jVnM)e#w~q8htJF?0VcDg#RnEIMdZ zXwNB-e|>$v5&khjonlA(F&X{`T~yHdMrlIJoAtWh=Y6bTzo8(e2vkgfbbQ6&S2ow} z;xdYN;BBXm)~Dw&mwvc@`KxupN8jD*(z}bvT`#chxS2_qh1`qad|~9j7e0q>;Fpdv zN8j*QS3h1?Pq#T!KjGEwQlyQf;u2SO>7w^MCHVipl8-?%)cPP=Jp8%wb2la#i69v( zCxQ*rDpfHAM={*AoD@}f=~b|sR_3PxAozFbRLSqPwDjEEI`3bo$z#3bG88Y6uT{Nq zK;8`z14VnRs9elGzRlCfjhh4_bpMUp0^bS(*U#W%hDeGFYZipYkZuGi-d|QDSk^7< z_4L}X;Ti1Ol+#-fP^SKaH^Vg-TQW8K>?_J%1`>-*yiAPB*05gxTe7I+<_wIVrBorp zgT14}G@G$aE5h-Ic1*JhsW;`zg}K$Q{`Uq`xnZFK1Rs5;^igd%q@ew&GedSZaqtmW zUf4MXws3?wehv`Ile6dQ*>7!T*=#Vk;k6X4=Y4{V?#TCyVY54xP@(dsa#!DbtRt5fBVCgqT zcY?&1c@E>wfM=2Z$C)+1+%8qu)Sw~-4Ga$I55$nA+V+0V`TLiw`t0OnrywtVGu3`n z?{v8V;`;9HYT16w_IzEyuY(Xk@103WhA%M>w4eWxdMRv{#MmEWfMD)8rOvAQmvY~e%&D;5i+i%{-Ih_yrnNmV zirKL7o+~hroEFpNw1E(CgNY*?YT>-GaP)1|L{@+6uOUZGY zx*&mo_b-Mp*v#np3X=rq3m7WE9qB~H#B?UKJsVwKUPc)u-L1Mu{;PWSGQ86%(p`u% zUo7iZdL!6Zu|K^%K0em(#A~Ql86)yNEsX7h+nloYOb(zDA}(7v$Ja}Ec(=#v5x=U*=-UuYMIaTlu{wMzCNuq z1_t928MR+Cx7-n3eh>0n^aN4ch2stx?8&}%+WQh&Wzdpp@&aqfCP zHhHP8D^e|iO3?nX^NTB0(;+$#*J?kkmVt`N_HKp#b&IcA{-UgYzI!XO$#or)&v|u0 zRwAT7<1O`@dsF9V+D5*}nyxUa*98J{^82+XZSXfTZ{lFvTT@EY*=aYi8*G zi{pzdO7%<6QI>$k&vg*_g^!}7+JFLMm4Qz6fMmq}Xm?an_gzk|-MRHDE#Hk=0xd7y zjT)EDV*Pxh%hp`60mOO3x*q~19bH5`-~GBjN19A&>*EgyfGvTNWHgm4O#<(;RA;@{ zgQc^*5kx>vMh4@1cUe-NC}};? z3JWD8O;fW&2q}v-?s%XD-cA;4Ph>jv_Uij2q)P~SJPEYVq|`N3q;J0>%D55Zen1qN zkei|62>7v|m0`9n|M{L-`c;vFL?AXqrYX&bGd=Sah92!CJTb1_zds?>(gvdPG zk?|k=ab$TutzS=#OwaaOb>-#2azB@+5WJ3yX{Bk?huVzs(64%N4ePuWJ`JcSQ7I}7 zSj_8!P2#-#%KJbP36p{CYCzTr1=ci}7-$&+rERMNW8SM=C{qf5TDA4wypqBgYOn6M zJmCyTd+)+j@8SHd-gi@629sgSD@BpA9{wusd&E_XlB9={NeeqO?7dF0xYHK8X6C>j z7^cmxzP>wNeUSzz(6NvTE(+&$6l`TBUg z3OlBGL>FrMn15=7w6yfHZQmCOX$n9NEAEb@V0pg$t1@P0dSJk;a5}&Z8vt$Ld0&k0 z+y0SV!~K4Cq-g4!toI{&UYZjQkeVjG<|$yoE-o%+K@svRD`RTZT6|u^W#KsOAN4|( zfXA!aB=A{T{U$$Al#_SX^W!9|;K1SW(O3kg9r#QrDP6t@$bmO3CDgTmjsZck<_cNW zkl}juit!18 zu&LCq*e`AKBP5i7iXqK4mfH=x z=X&}eF#)oEula^c{z{*V^H*}_w3+^1Mzt%ZovOx~50g z`_@MDcliqu@XFkr?J;O5wXM^P_}UBw*_OEU^o4ngwBhs@sIyjg?GTTvR88M#r2eImDh`#RBqxzXRYN@ z6luuLPy)sE$?0kDjvXSGH_*IiW@bDdr!r(H&khbC#TVI8U_VkZb3~7yyA(#c(lC_O z`Dit@jxCsYf01UcFrP!ta?GM6k??9>O#*DWGwk~*QEW3qcmy4z-Ql|X^Db)?c+PC+ zSa4U$4F^CE!He{NT#;H~s?z8OXJb7Zra5^gxAjj5e!YG$ZF~O6t&;Xv1sr%Ksh+nH ziYng8t*u#9suvf5S*F+5{Q-j1##Q3qLRr@JF~fBJ60k)^gl$%Q>pqcHVihF%q?YdI zZ`KX*4GPZ(kp~^f7XM18i9MB*1tI%4}^*0R&n6KsyUh@%NbhW*C;^q6c zQ174jEdL#CFG!H;UK+Tl9+-?n)-l2kxQq3U{&uM76n#|r)87iTfVNCwr!bzAkj0W$ z+CRc=bRO+zL`;D-wAqa6aE#_ftzghz4g-kuSHnxMrVq)BLyv89rqWV)rU(X!M z%g2un#G5)C$LXhkKZfNdxd0bRg~h^4{fgu7I8TH&K60xNeeCi1${noh>)%o?>A!#f zP%e3daliG5tF2X{4E-nK*sxR>4p^I6>j)^#n2>LLk^bW4P0pslwNY*^n04Ch>b*Ih zi3kpwr^~|LEUvO5=X;YrJfu(co56o`aQZ1BG4c1SL~<(gHxBOM8?sf?H%glT34XMm zwgQ{Cm-8-UIB2L;yFn_0AKv@pMCuwEYPA+>f)Ar1^;%0_;yW%E-bSXRqUIRNcj3T8JlMrA&Jq@C_nqv*2Y<^d3{KB zGNgFU&1J4obyI7)WlK($dFQ}9Rqmrg1nGm#e<@}b+~&)kB22-g4+keR zJ*}^=wBWRVWpiXt&ujasISOPv4wz%7XxFP$TAg$- ztxo3aS6V=uC6afHC{DE>#T^`foLcxyjv{w(2tT!oFB-3eA=35ZQxeZoM`s{C;Mf$< zC9TmWwBE5EJE3ESiE|Vq6jm0K8$PA7K<(qAG6U#6!TjrD?7)S8n#K6~2GndQf=2=DN+b<5!cV0Hj9WIbG zAh_Usg_g+N@ljzZ(8{clcdX@PCDS_$1)LlCwtX zVbrL7##6&@bC%)u^bEw~zE{Jf_XuxoWk(SS+}!kzimgiP3L4ux->|3HvXtV)mz`;U zuzybZ`l9*$qfepwx!YBRx;weEF9j?vyVLo)f6Z{(5g_%xMdfr0eWT2&bTnuGfOLO< zsDjYz5HE*;*v2=YB~H*61cANa(v9YmuYgICU0RCdlf-QDtKg+ns|jp7FbHU1y3f%O z=TUKYmnR|0pVHD_G-b_p^B3Tow*RFW8XJ@UCg8B~d47I2m1>6tB8s7*VYpez`#xm9 zKhd#O{^8+vlT(ff7oDARHciMtQ+N9hoRo0|9~&FPk)6>AfvJD5ei5b?&-QB65!>CAH1;x*_j*c0+Bgq-MY00Am|G6kDLf{^Y=4cxZ_~` zLf0}zGKFyW_f_G2vgW}*!!cyY-xaQ?Dyy8c%reL8*L@eU5UEmZYMnwSK? zdTHfiMde2hoA#g{;!TI-a&-|* zI=c#e5%|2+&5+PAKM1S3fFUxVVebOsccHc*0ZI za*~ub-e75Z1jvFmi8c*V3JJ6V5S{#dC`?{oV|=A>3JIeY*2bt15&x-4BlK96l$RSI zA!F-O3lWW`m%NQmPlwaZtTsBjaktm9u{M@gvqV?3_zn(sGwqHr>s7)1jtdM@Jr>a( zOE${N6%|l|49Is}+3Z1Uaz_3{h5#>Rv6QQUAllu%vFx+OR~M|5fqy0|X_|-NTd{Ys zslDw=`dM69ZrZ@Z++Vn^0R6QWt8T3PmYGpp^v5BjoxSt=1zz`$6H)*`fdrbGn>%It ztSr#!#Xo~dkXe={x!+=)f*4(1j38Xhrj@Z_vsXzRwab(SugRe5-iyWDi(9wZ>y3-M2OiXsLsC#0BfhmhlR`(si z;GYssPM(!la^wUqUf6`9^x4@sp+|LE9t^BE|KVYtL@6)74#ni;QE?PD4Gk4$=Tn9L z%1=!#5y!{K94_Zq23}_r=x41Z;3aj~A1kLEmFWkaup2)BSIhU3pYB*sBHO39v{-qwllU}0m6Nk|ClLAx?R4(bAS zI6HfL^u^PaCM>mhAaRYX>t#7OJ0lt-W?cS4IG(e%dMrOGw<83O^Nvq z!>^-*8ivW^x8xaIqH%^ZsUlwt?Oy;OBg@JP+4M}$rpeDP8F+Z@o-hU zt=c6auMRJl(=&z|?*kOLd(cqSz(2{u1K3hT=_wQup3^{D^Xr>|>$@Rn{~zBW<);4B zselRL5Kp%^70zV|ySuv6Cra^37HsI+W#P19%hLe?uYbyf;%^#Cl%sX!M3ip+y!rZs zu9YF-*-7AN+^PyrweKk~COIGsPAi7w=B{stksCYAtudkqx6!yByCHo^@c13qV@^hP ztyYrn*Z%97M6%hC@jvAvA6g;nv-wuWo*r^)nz(>7715usxbiv~ln|v_=Hz%k=`_#+ zo5gjMX0$wMsL@K^zA{T=U`cX67{2klYt0W0V+;&1$t$ygbE`UaXyJlM$YJ~@@jW4#gb|=+!w=Ta-M^<_y z5B9y-?Ye!_k!r)G)#GDmesS~f*H>;3w3xKP5-WCb+tQyzM$X( z$IfpqQ!_OopaQ}ME@OOZ8Ll+CBY~xMbliIJHD&=E@$D-|y_ST;C2t`$wA>LWJ{_u9dsrk}zAPp`fEdkX)n?I?1Pn-g`s9z`#J< zzYM%%e*=nVyK$B6X+vY@%EH1x_-AIcMaodWT(iXY4~Z?nlmL|X6t$|KZ?-W;pC!IM zCpsO^`_3KhfY-SQx;i?tYL_J_75zGyw|T#1@Nnr4%KP<_IG|HxeDG$z?B1hs^Qe=82ipVPAiD z)H4|%K{zN~$swv@%>!JvUpm^WY?D)W<&H<*#6xWG2<(>|L2HC`mIRXV&+(uba&U|z zKPkFf>l}=0Gn^~cFtyU=DnI?kFInGTQ(Fr5n6&*X;CX`_U*bwRK28Ib1>6>>nx6i!hM=4Yiq1Ls1|hF<_TWctr-PO=jbNnD44vU-2%l)`;mW zy&VkDKjvP&KCR*2@}$!OHPhYtM`8D7j};RBwY=JbtfXYr=qQS%rNHg!$<|K7k{pIj zleD3+x=jczP>lc~f_z{AFR9@4iDv7Dn(`YhQGZS! zsZ zWB<>wJYWO>;(b=dqjG8WpMM5D%Kt5oMg z6GtlMeHG}QBmTar2Jm$)j;$LSj;6LTf@Qh@Ob+VmGJu^mfiN}K5MWFcl^I0}4SVb8 z@K-^D{~P{w@f;YI6uw^`CoU>0dRR$8>24Q)HRv^_jmKxRbR#W@OU+U>Gri}y+T{^Z zUwjQ{45m;vF}b|@IixfOD3)@Qu{lsN4RY>j%4)3yPEUKp^n?)*^S#j(76qvz_1^Kl zT%RduxD$bljOas{&w)1rr|h({awQ?b3C&L!HJZ-D4mCc0ZVL~;+HPh2`Rgr!Xi;e` zVRRZ^pIK``#R7p=$?ncQBQ#h%OFvuuK&5RB+2s6&i<%IzxQO^Wo>#!_F+Cr!ea5#Z zO}{|$z`gav+1Iocp}$*k4%T^VjGxo7&MPj)5

0f_{BjQ#9EG$?oR);K9p(`Cauet{Dy&T9c1J-t; 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%0Arfhr|wm> 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 vF3OvIy`WPMWd_cJs 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%0D?H=TJS(aZE?#w|zt7;TYD2IX=3Zmo&Aw zT7q_M_?f8S#ghOl#>qA1zcLhKQU&tl9Xi*j)tHUB0X1iJ#qT-|yvp7(9mGMWgf~Q+5 zx&kN?cDPQK|L;xZ6yeH4`@e(@(+eu)NMq-awu7X+9l4#rg&<0w4|=ANS1S^S4ng#s zOl^kzS)mmDbLY~_-l4Fym*&DT0Q3Ozu4LVn9pa`G+|pI-zfS=c+EihT(`4Pcbye{l z470cl5ZEOlDY;?C4h;y95Ie;D{Q=DGcz-L)i^4v7ea@(a(pYpr-B!nR#IHVTy+s6RZAf}y2#dhtYiKt2XD<36GWpe3KJoO(1Ma9qx#CG*NK+S~% zGtIq-rZkEVX^V&h^rjZp({mgie)04qC+D_Eu9vhgX?oA?(Yzm%L4S(r%!%?BEGm+6 zI=lG(`hHZpuC5xGv?J_5j!LDuC7p-6|B8LCK93J|9jz7h9-45~yLgX6K`s#!%AGL1Zye7$MzLFcaq8#SG*`EP#U{yXhD#`Ig(j!L0LQU2`kV1w<} zA8Lz}6LUIsIt4RybmyWO?3l?zlb^Zl<7FUc>Eqc(&dC*1C%Y3CdX!>)jg(OrvV4u-x zz0lwX*;yrtzk{w<&ofPKM0R$?)!c9O^`7OXAU}}O1r-x04!tvJNN|Y%hRBRf1?M2M zft3j!VodKFvXA>_7IKurEcY@aLyr<)bCp#6SOEBA@KbRcf^WxR2Rjb_0ozI4&%(@1 zfc_2@%F8onIPim*zfaHH%1kM2^{LtO?XEN3aQGUy?n$9Z7&*zB=2#DQaWmaFFa$GK)II;ZJvLbr1 z$kOYmbCid8%Adjv9*+OYLh0pKhQ_*jc}vb4S-w)0&<|cSHM`$ya~OTjh4GHEjVw+V z-?r|a@of^7GdMAqC9`CgvSY?&@T?w(k|X7x66HteCr)o1i)DY2#d7+$V?p8(r)&X# zDk;B%oR8{uZu0sXEX-XnbL`6gXKb|cP5SO|Qzd$bz}=XkpDy>|e{-(z#4rd?M`t6R zVU^9+we(7-`DA6c%d^3$&&;uoi3tvAp=oFckwgu7qCm_aBWiF}!D@-PL^XI&`VE#g?n$9P7IGC!Yf$1fqF%2V%V z&hRi=r>Zur%%nwsW=#Dc@2A_*I?~2prPvCLuE}>i6QMNRf1Tq$JZuY5SX@a7CHzDY z@A@4-@BRM0#_yqQR!zQlOnFbr?DL7O(xYpb^EdU5l&o9ru3Np~lrmU1Huy6?FLLo! z^I#<1ost)>D{Ymg^>$IKlctZlEa`gwR~pO;@F^)`cRzV@H9>CeHgOt@b3Du05;5zQ zQ!-FnAFO`e63gJoveR47w|9|X5l$~vSJ;b z?G=uWDQL`Us^K58_msbWrQ>Z`wA(qEw;1u9;xTp$4^!6?=V!>j8E*S)W`tpR@q~`T`_x9i zwze{Q)y~*_;YIqUU-ti~9+X9Tbe6Jeo{Gr-Shpc4n19x8ZnFK1h%j)|^*ueq-?w?k zR9Iz=e0RSR$;?4JVQu34?s4fqE@lzS_Cql^WmyI7U<2>})7D z*CKgRcG3Ojf2Cw+Vqf2xg};SfadCgjSa`Usy{iX|X{v|rzLo$dnSaPU&oNDmi{5jE zp1FbP+oEXn+ihFt@{Th97~ARcj=s3FDPBHi^zz@Y)#SV;Oh;$N=i~e=_f)Y6-z&fr z{omT)T>phGQP_(y!6he>Y2$Y@9znI|pC1JeG&QLes-tqQ;NIP0YA&>vgNLg8=Q|mV z{kFDzEj?Gly#iz-I^z~xn3k63cIg^KN4e2A?Xnl*%{5NU6!`h=9i1F)@2?7|YPjJh zOtxsV=Wk3FJMBYvLqggj-&ZpKoAW%)9Z$`}zmKl!cE=37+H18|m@8<==w590$J4@{^|e?u5Aaz7p9{bSJ6u?*y`NhSM%z zE;Q2ik9@e6WByQ)$E}IwoUxIoBNjX?F2WpojGav;aZJnOgX8h3LDM{uYA+FQfG zrBIx?)Es(t60MNHgHP9oS7~Wo-4`>7g}v@1lRmFP*}~OT z7WxIQ!_=#`(vk4KoHjCgSlz!94F?pU_197$u>HfFcMKDELS!8P)ffd_P6k|rSsfn- zul6K=l75Jvk?DjU{QK~lX@m1nP*CTHJvY1&Pj>XTX5ZWlPErZ(oWMYKqjS?c^- zj?5Cyk)RRL&W%GkwUgx=M^DS9z`$L7r zIrs`P_0wmc(PS6*uVHbiowc8-oR(d^(b?&iG1f-o9m#NarC@N3`ma&TF~09}&$w0F z|HVe%Ud(S^Bh5rktf-_nf9*G5Vn#4zeU(shIG6n|nAS9}YBlwAnFyQcogA5joZYV< z@3oYyq=Qa+u2?jr-CoN$N~G#)V~U2EMskd2iT;mddN0Eaq{x(;Z`#BU5ayo%hX5mW zvqqap9X%Alf8b=whT;N44*tI;n2;?fN{C`Aqu{4HDt-c(@8?tj=K$ zdjho?Si7AE4s1kR3j{&bkD&?{5EQ)7@y14W>dP*wd-enU{bbe^`~_wf7MO5de$C{> zi4*hCm#q75ngt>|(3}zlDibWpfzHt3YB&5OkqUy+Z3JMA$B(}$jD^mEg7F>b(;JZ(GHv%jqsrYyU#0U&} z5_%*f>vB3md_wN{elUl4enG`it5GkY9`gW_O-GMhojBx^9M<3DWT(P~L_kHb-lTCrVy6d(oT)MdP z)H|1+{T$M3=?+S6Tkxg-J2S(FfqWBgi+)wL$IU9UdKyM-I3G!0+6HEDv%*j4jme?TfH_(s9=~qobqQ)dLM4jlHBUWruh-eOlV%sb2wg`)zu6 zQY1KOSnkc9`W_XNzy0njS9yiHNt4vb*=YOQT3Sam$GYvDC`F}K-0TbVZc$loAC7hf zie=|p-Z?fq=%pwBZ$jX&gT;TBU}R9YeZ#dyN9~r3_^!6R?W>&=*&Wt2aqV3B=P?cU z&0uu0?QgArZ|5!+x7$lABSzqRlXHjc<285EGrcQ=FVyY0zJ0`2ji=t+XWh2$=QoP} z%~2cM%uO<%W;0S!`f>lU)t>#YEGr(Y9lz|yuXyCq=l+e8Ti1#@4Tp#d3TwFzi=67s^1pV#VBJtoiye>u zb|V5u1DOU%C|k_l^IRY@exfb~0#^<8Aj|L{x~f-*6eHFOz`(JF{{Z6IPW7pYmGxU6 zCTS6f_Ju6u9vGmyiIQWOeTyA&YcSI3_n`imEf&`jWQLTGK$`H#hd`!v@)?QffExt5Z;wv@ zaa9)_NKo2{ob46U)J%8BgmFj)%kTkfEekrEV~;Ls+u0q!58nv_0Rvh*Vl|_WR_#B{ zPD0M+p{pfc`@-LG4|FZJAkzY4!XbH0tr{E3Bs8s*-GKEs^(6$w}rudn~qhywaXcCKi@O3Wg)X`e#EottFI-XYalkxnOw;$iN@cFp?x^=%f zw|zUCVV0p!$6|QtV#<*TSs{-Z;b9$ZGgXbxoZE!u6*EdhHfA)mS>V6ihkSxJ*I1d3 zEy*caWqxNpoxr;;i++hHV`) zGW&V@SJu$cQz?2SWOkh@vt{t6qtnva<-^RnopCUdVSF&G?kG*}Sx$)|`zHq`TT1D< z2a`2YZ}*ruE!5NU-QDKbIea#tLbL_Y=0$^n-jN^coF|s)+kTqJv(8$65zmZQmg{KG zYx;aUYQn83Yw)J=?6UpM!`XbvxzDgD%s&Tsg#LV2F;%)+!zb;+7=FGerG3_IPd}^b z{PPK>Kdu=qk|JwI9ZWM7y0Vt3O7ojXM8qv_ZnLENkl)NIy@p)L{}S?ApYFf815fU` z%goN5VgavmF3n$GaecA(m%6deMxDXhPn)+^*0z{bG(Dz@PpzyRZ9V!qa9`OjtE_FD z317mvJwkYZV7Sey9r}1=W;Ay^i+aa;hjWErnzK#hZI;wbHRIn_HXG$2L0chHWW{}|GGcSua{n_j2m1`-3UHjv%c-mTo3A_#W5yWG(DRnqVxGfpRAllE(IkRXv*gMQhifV| zC1rBtZ8|baISXVcaRQ(nKVW?2+irkSgnNgT=V**ub;W*&WLaif!=aaiD0dIkss%q? zs)hd=veAxXQfqUTNgWAWfcrtO8l)YtNcW!T4?R3$VwyuYu3SlMu~}HKz_sZ2;DL^5 z!l#S!?4LXX&a$-6<|g(>Fyt2nnX zYA1$y#p|#8W6py@F_#W=*|IJ_s;%8qWwGbw8xDE)^-4hlPdPX@Zb;EQm58OChG^q` zyi{(Nb}h6S#^t{9lW~3e`=to3uaDe^<=+2%w|CnXv*FH&HuvQeuET+!KPqu<*m(W% z{qpsjeHB;S)_C{Iu^;5z$;|BcwUW2t;_2?_Ml+>fwihss!m5li+S7An!wMCkxRZO< zRRo;iEjx9J1^*~{Zp%GNyJ6Cgu+%NuXR>|Am33G8>Uhm^%JMB^n(~Wi#EMT=G5oey z&wu*Yes2ESn<;fckvU!6GXk5I4%_y94;cD8B52Ah&M?>a)p2)9R6-*rW2GMi@%$?x zc{Q?HY?VEu*{`wn0GFq6s+_{(bBTY7qW%od-6`{o&2k>Ml3N|2rC#^WPGG^MvpK(r zlXKzrjm?M=hFh>~vj;V^aiM~FV7>XWMnd1fAQ!2&WClGLVmJ>;VlI5ZE@KA1`!Jko(uEZUA1XnQh-7R9 zV09q!(*~;D{)XGtM=#00LADU$YCggRrCSYUkUS7w6P~8^Z~9rUIv$7G(-dmu4lt7L zT{OV-z_~#f3=CH|wgCj9x3{;Xmp+8Gix=KpyfM7zu6y0Uw zDV+883GNcvm|wrGDn&~JU+s^3m3#lF`}Ww~ITzv{m|fmoaVRt8*9FQKP=86!Ndub+0kx@hFt4>iLx`{5XtrO;NV5ZRVtVyBUL({4Ah&RQvX;UF1jm=bK<%@f%sRqGOB~ShR zKm4}ev;A?>zirF!zn?b!Et;VpNmJh?`+KeI-^`@ZEMq4rmLmn5%!)JD=!9j8IY`fc zOFVqzAm?eD<{}x3+vbnI0RT#~th`Ep!$Rb7z19>SXoJl!j@b^ohv(jCovp+7r3(1+ zF`s>F>NLIQzPZ{wF3vV)YNxR$Rtm)`HCL`V&Aqwo5J6L~^J<$`$%oxEN6OX=pUud~ zuCpuTr)8%NnzY6iVNv?#b$&v7#j{x3Fyr3~8c$SG#8OLOfwLIrvd0%C%50kR{xee| zS9$z*l4=4UA)sz2tEHOnt#L{=;v8~Yzanw+GlX`!nF6QTL3Sq!sk{(zV(5jyvlSkY z%@02D%R%vwl#}y~U*sHE3vV8j%q>{YqOVaGnh0v~-hghC0%iO=8kGs|_ZU{DNxH+W z2d>T;dDO?qQ{7C@a8prMcHl5{QD;|%5lom?Ud!j_!jlg@a{tkLo1TWl6@Vav+^(y+ zg{QKISnQ8P21T`dl^F%>fBKj95f4=xXu?l>g$N{1{G0F&IOqLg;6`L8DG8D06B>X_ z9iX*ezI-u-&Zz?xuF$;%jpUKZiHzdDh9T=A`|tloDsrUkz93#!pOGPBeu*}=ro%l> z|G_RkS`}5s-M=bydV8kWUue*tR=QLWpVM03X3-Ge`S`PyinX-O^*lf6NZJ(z1?#PA z51&l(e1Gru6C=@}fva2g1pB@@OtWc|?hTME6FD~~xR4jS=ztD@rBV%I|Z$c8vvUXG}) ze?u~$uOA17_2|J(Dj>nzUoXxd6Yrf6JF9IbVB}snJJ%d9a8ccSdL7tEe3mDPGiBhIp0zN(1l5VPjIn$bc-#3>HGveV} z0BdmR?;UxF;~0H4>50em6GM+(n~mG+B`1~J+A&~Lx#@X3&222d8m&uCd31aFk4|(J zhl9)3eAd;`@fDV+rSWYEv*%Z8L&L*~>jL$~90=4jA@jJ#A!60Kg{qN zI|p8$JfbIg?#8XVqf67fPlt4P7CWj*>GheHkAcZ`kS^{Y={v+ESbd3YB~so&@?v7L z+`GqV9;;_vXFG5D1#m0dNLzX!zv9jI*t%_TPcZ5&ZPxrf2A znEu_*#FP6O*_D}?qcTd#fyK=B=g0F)|EC3@HFCGwEQ7T^S5?vS_<01_n)&R@GViX< zha{)=+vD&}HjL$&lTN)wtuX7%`N*%b&tm>kGuxcZ);G1v4BZH!q(aug8kr8H&y;|x zf+iKg3ssA`fLZirem+)BZ^8)7*uxZvwh@CJNUaAOIkf!Wo0~UaFgAJ}XN0QhwX-P) zp^q`?mkWu7*W_{Ca+TFf#GwMi@`ctD-xe+eYl8k)dccIxnl7g$USh< z;Io9JRoCaIe{+k(l-Nb%9jazG@#g_yF~WE;%YTizCYI&RM4CHumPA6hcj-L%1QYje z$V?Eq1IdCE0t1nI)0-H6erjl-7(S4#@R36*b^$>VBw-JI+!RSha&mu{V1J)f+@wdZHY z+H`&S+Rd^Wx`@{$%rBisP4ZAC6bVqdCnO|CZ<2n z?A9k3-P-&h(O8brl3NpY2GMZg?n_o{gr3)21w9WH=iN6_-ypwUem{c`1gR4767JW` z(~0e-rnTw@e(1VbU7u{pR==kPJfTDVy?b)|!r=&(_jo#H8q+5v20=GJWH+dN;Ffi9y9CG5 zQpF1|ou0Ealy+?=_T|YCjbxcYm<7G*f+AnKN&zH<5e0dYu$GbVgP$&G%?l+ z07l~DA!d=L{ehHj90Sm_K2Ed5-owM&=gl(-M_g*y{W!l)tK{tLdf~3vPZwix#4s<> zya7Ul*;2D4X_sIh=3724nusZg?VUCXwU*@O;+Ijb9yK58Gf>laii~@7CVj zGa``MrFV0eaj(v)M7JYgA_n@T>Ktg?PQpuF4kUbuTJEf2Mi`uq*yUy`kP<%uG>wu! zO{;DwtlKsgZ~w>GU+G(cA*UjKzw;=iMJWrKLc1s6{5v!MfMh{YmUFu7s3R?cf)1bD z^Wyj}jrjH9<(`eEa^KCQw~zc=ZIzjrJX~dWvr8xcdQ-%eYOXsn`Q_}5HrC>NcLOP2 zfrq!7D=08p^MojV4X0(fORKO!{R`7x+M^q^&3LyT-KJ<^bn(u%u$;YxU-B=9hQ4lV z`uA)i;M>c5HA6Mw43T%U4mEkj2SDVEzkIz|d(*vcS~bXT-(yp@^!8J=LA!oz+xE!F zt4BO+%66x|u$MRW(y}1)zK^O;dPKDJ?yD-PG}VeE3Q5C6PP# z1t~i^OBXe%T1;Kjgsf$)nI?C2N0j-Gt~(`eC@3rwbcex!jfJ~u^&GW4d(em`4~P73 z>57#h&6CTEU8%;e?iMv_Rvd7bEvJ3=@n^@$@~9&MsX}`b%PtNLxa?VT%x9MZWpoV} z7Z(~QmCg(BM4m{W^!jvhs||HG&^HqJR#Q{c8HMQq&c0z`o5w+ACU`UF_{d3Gwtc)3 zZoE0XF5}qK_qF8BBA{c#rjUyTmOrwoluth~G9|NJ;F}hLPv2O(l<1}Kc>YV;p*97S zVO0(0oyZ_sk1)bM43kH-vI9j{o9*Fw;GB_F3aKz;2hanWk z4rctMgQ9k_(0O#`w<4ART2SOH?%p0@U6BwUzbn)B=1!u~Muk0LLy}ogW2CAa>WHeX zQcJCkt{eP?ddRqq5B9{#Yni_ULgV1tMN4~%}|Vq%7s zhn|LCdnqQs^E6x~WqSLUNIHcCj@z!I{K>*qG3?YqcjTF8M|n$=e3y`ZoRS)AO3^FY zFu&8+@o{ZcDP?!rm9jxER`C_OB+B3g zKku6~$utqK4$77PPIzg-%f;ou=oHdzc1d6@KeZQ6wd#gP{4YG4#;$&aBMdl1J(Y(V zlZu9v&w!Mj+34;u?Vl^lFC41(ss_#ZMSi>)c2IdoSL{AQ+N|n+sGwUd(y;hOHasQcpwyM39RQQtgDX)y2})YJ^&R&~%>) z4p9gfq^zKLB*J<)D%{F0?N<(foEI+eLmw>xwG2GHc-_K+=!|V1m!J7smj|vb^SPDg z#a1=`NHUuI#~YhVFDSPV?6l#lXwpCg^1CP%(8HD|L z$Q_W(@ANWr8?`Z?_Xb9e2VDW%S>orG&%8Y^a$YRIS>Hl*OYMToXiZHY*I~TG$0I5l zA}c&<-?A^+zZ*Fd$y-@}R{rpld2z!U^G|@lGu`|2PTjL?Z#$b4_iU5!bB4rKfgFvp zZ~o3SyzLiehNh)Vr6z3#FVg5!Pkega+FB^fB+IzO{>Ieoo*>8AnT+|v+ppYuckk5^ zcCQ#sv*#(JylfBYk?Iq3<@4G%e~!PjI#gRE{rROyUC5!X%MCIUJoi2*x%fHWh?clt zfaW`4W{a_e?0Dghg9qB9RA<-B*UC&l;I+qC0A?L>KM;-ivujb6=)dE7a`x;xP1%0P zYCEzy4wNo5Wo4fc0kgsZJ0xHp;w!+|vtC$HYzjh8CZBxf&8POpC^Lkme8seA3Bc@o zzC*EvW4Iq5ZEM8ELr9dTaDb6>08ubDi)4}jPC5#V>z|RELdX}4g1(AhmNRJTYSfU~ zThs;8PfITp9rixlU@%pFg-Ivwla6;e59w-Pg1Ek^UG)=w@h}F@ff|HO9zPD2-)q3u z1lwC$TCk9I9G&mmSjM&s&}_wayS31Nj&_wsgQ;OZ8-_qAhlUlDRh;8*k$OHnJj_Uc zhxU#kTur$`LXl*5?ct)O2>C~xTqH2InL)i9HI?_Oj=0)Moj_i z4pl^8DcBt~H9Lfr^M!xrG^rMZ^3>_oCA<4U_ck5bQBM7AAkj`_lC(LCqCbt z>(P9x&MM43yGG`s!&~*NdGLV6Z}v3~XOHKeiK~6*#lvt%z>BguYm3UIT~aEKyUonX z#%(X$G^aLJVe(;=io7K({3kqw&GE3W$e|v&dI_#mG!dtcpXL+U>}>tsQ}1Cfw<)71 zmG4cCNz+ROidLC_er(+*{`EQyv*$#^!Gh@v>iD|)oi}e% zLfE=JG-Lg#1(=P%o0vlKioRH)LcNx&d=L7Gt(jnZTH0!H{)Jj?{rnU zd?70GUua!NVNH?9jlKb20g<(V(cIg=+U&lducQ8w)*{b5BxFudY&Ix-%g3R$!ND7c z4R{0p{d0_Rol@(tIt0rF_rIroJzyZV_{R}T!`h{qwFl5d#rNbqPa>%f9ffvM0Iz=4 z$_tUyEg0PzS=Ns|B5eSom?t0Ibls))+osTnMDt?L92S}yDyoHJ%jf6NC@M%6gnc`9 zxD)G5UY_yBQ};fU!|_uA)4|pjQ86(wq2{McLz*7`zPV8@!>Qjo9CC~tTd%-jGCQ)I zX;iphNcSjIt?`Ldjmq%+83AnUOssd(X_u-Xe;O z?CcfU3YpntZ?gXPbH4xIb)9ovr#kZSJnwPeulqIZT)fp%5IccE=KG?hKn_L(^-$2# zRy6>>8ySBhL1;%5uUwz(K!Oy4=0YX&cK-+wu~vKf)E57j#~_z4ya6sltnfD?0(&UH zuU)?mL}bLv32E1?5}q_f{+8881OM7XRyv$R#_T9(TwF`~Hm zj$wu>_oEMAh;pm63+YW^3NV_Sis|w(6y~Nn=CHptFmy7WY8>oKNA3S-m0I$TurGFX zV|nj60h!Y>-&)c))y;{g2D=W!Q!_m~FQ%7y4LUdNg0Yj=YG?94=?k6aK2PxM8FMY| z47a)Nk=o`!2tq88*7tWB|CIgU%PDNF7>_Yz9Y}cDRKS6jV$;jfE&2j3cjwLs@4oZsGko%AK!GluIliih|gJ|!47D&nfBcku9 znF0w$5**Cc`5h?>Yl49>YSU9!Vg{dev&)Nz?AOiO6GJJ`$hq%zxMajREvOsV;rOQT z6T9-nG^=jk_7%r4N2fHTEI|om?K#i~|HPL$U)FE(HWZaaDGn;*_$DoE&k}<`=z8@^ z_NAImu1mv0QqrAxHuq#MW9w4_PVGbI>T zS~iHBHYz5zPstl5I#4sKvLWKGah=uOCQ9#Ox{zeSxIAJEl-XP+-sB7FXff zR9Z=8w&pWWX0ziHwYgMh0aM;y67&azj!suUYb6iowGrWO9=n+Kmte2W<#7#Q5@ z>gRX-^Sa(e5=9$qs_;=EUrB{o-|maY-%t6j;l?;Sg@v+T9%%lu$K(hP=1dv=_}Y9T z=k!vYk;FOMlH#eRTB$7^)~{bjqw&~e*t};$12$|doU^w#yLO=?D zSk`>H&t~J`p)#TbX*=e23@z>0wwloJUTtLCkKTnMXKZ{t60hlX53BC`H{X22{YR3n zt3K7_jc6y?;iPO46qNa3r1_xo7G5pq^>$HbI;iveT0=_R>OXpm7xstH;!sz$Inya= zhK*TES@Xf?9~SZ8+bmGWrMNoFb(j8acT|B=}=?4aDHZPdyXVm&taU5#z9{m15 zRo8D%fuGjrfN~Q#rMbVfz!`038e4qKml{~t5b8D+<|=xS)OQh9kQbM6eKfJ~C5~5V zc82?grI78LOa9pla-1kL4)7lQ4W>)&YtrSkr9!V-t9VObdTAp*WME^2 zR8?>t8`@j!(MMqdH%SR>(FaUYw!miY)~8bX4cOy|pZn1mGABe}zDK;-7sKP@-CW)~ z5%d$B+9iyC6R$=-Hx6nXvYB9?sg9jf5r4q3_3~QQq@D=*%|CR)@AGP$ER!DKtGsxz z^hMQ0^luQ?bmbd|PfyiLU2VRq%C*T9;4_o_`KkUUB`ynjY8CkMUttqCu*fbU$y2(I=Vv{gN^Q$C>5fK?eTG?0 z`DjHrlBYK{oQc5Ixvt9a`}aV(geX-3y*3H?xLDSp_wNg*uSZMX+h|&g4o$FG*7w2s zHnv=UFsNQP_Ex=g!uZh<7JBpdw!yLQlWggkIoba2K!Z3N*piD{5z4si;7OG$|}rD!X@9~eA;N(&85T=aA zmUX%x)gj|(Wz{8Yk6O-p^nI4wF+W1sxFWlNW3wyXQec%eIZ8ZT)%NZa)_a`#zR&G2 ztArzm3%G4l)6P%5czLDn`7mCW(GnmuksJz*O)>p?-}@WWSx{>*j+^t&Ow$DQFTZ|_ zn;3*mcD@W|cG~{dIhMJuECi%w*3I*RG4*H!OaU9+Ybq(uY0hC^LZ0-j6-7%ieW~*D zAiIEbvq_5R3N8f&V~`}ADuee-u4GM4t{hGVU?*J+DSV`(qZK?cW!0D6THJi*;gKl8 z7-U)W_5#;;zVpb0E#M(3NqCZ$pi|i87atBt|3ON$fw+#+R{9fvX9%{j!TC}4GTgt{Jt~iH$ua4TpV6d+2 zcjv@2XS!Zvp4|&U+T-r-kK&6I-yma6Lt{Y9fw{RwQc_T`^~t(I&~U-P07-7atRP+P0zeVbgixKRzp2LFV= zex8~pw%AOpHF3@iLEDD}T-oPywG9IM|HzGnDK@`poZ>%JVI(1VFx~yQ(q~z?=OW{B zHW!hh?(3c#)WsBL&Cp4O*eMsv39k4RmR!;3}_|^5fE) zjPRPCs+?^?>N`ZTpU|*>g9(L)iT;p*r@bl9eQ$0=Ar{9`z*;0&QZ708?hnQvfg7&Q z(mXA}!V_I-{Ynn12`}K6yH^Td^1fm$v);eol6bGZxxq{9?-~XeiO3F9r;_~9%FNtz zf3a+miYFYNBto<9s`@L3hgO>#ebtUMcGmaTGYQ6lxDBIR*7&G;#gG{yS)(siE~^3u zL!@X}=zfMDE%Zu!HC06X+UI$S`AumeIv=&YyfH~k?w2k1^=s}xoF2i6h;RoaFIWoD!I33h%btag|mgg6$GR{O57gzplQ-leA< zLU}uo@IY-DLx+*=RlBnldE0{_lF}?|)O#6Ld1ePdt}32QJ+Y zTY@_DzDDospne|wWLZ}_i|}$5U~YYWd_R^o3@CrGAogUA9rUK*fJ(_f>n8ux_O&+y zLuA<>ZUh!S1|{*=iWkRu8aN+Y?NP}JI5~LR+!XRW{*t*jw}&2}#G(xyiLvQCv*)W{Vr* z1|L3tm(OwV{9R+_a596bQHsm;L;KVL^9Fj`tOijY$W4Ju z!MAu#rnqp{tq$2&m@H%&Dvva8AgfK_kI9j(-BP>0>ixd)y9lLY#wY{RC*rZ(O0I>d&ryZFt33QShW}c21!x+PT%LZbD2I z+d##5ZqS~P4Zck)S_W4f=LOo^0r4H;$gjNTj4Vt|;X|4m{H|eFFBL}(KA&z`Ab!W+ z&USyGj?cYmiDci)vLX+4(7%;wcqkjJ#B*u{fpiz%pFitru8m26t|URD8pw3z3JRZl zcZkC*c<9MI(fUGHFiy3XN2M(5_j`HN=6F_lRs)_>2LdJA^V5gXR}ablvJys=ESHsG z`6{!{$*R3>43%fAnl{AqS`|8ZJw9TPQHk~Z|@ zHWn6#$Dy<7^D~S`3%5H-&P1rO9&(V(83-w+j8s@p6PzBt@Q}*!&mt=ya_BnX?|d$F z`e6%mJtc)Jg{fD0Sqk+`S3D;-_miB4kL0UpzAQWLy`2MT3JT^7DA5TBH#TNX;jy~A z`m~GtDsTlYXKW4M#h^qf9T|K+Hm^mK^*_dzp>Kj#u?({KV6;okZ>v`s^55fC^B*qA zv=kD4_1f|!Ubdx>pdg-@0qdTouP*93H+>Fc=#7B$=qpS8AvE`ETm0A7%0-!*)g*K9q&nP+NQPS1R zCY*=%=powz3SsHlXT@Gu)gYi(BdGKpQFpT~G$F2%WLyp0ea5Lgxp{s|x@`KnIdkNz z>M$?S3Q}X_1=7}kER<4EV0RA)@XH^s*%Ye2yx8x&*VKBja#23f$|8A&0W5l{QJ3-Y zaRjV`FNq{$#kJ;3Iy~eqDl!sD=Y|DVTMUibJs$~TLu?M7Hi_6vuKPVnCY+~-E;Z;_ z{=6&lsXwHcViY0iL8(cBV#(35d;9hE+Nj6pPs?;n5&3>fl)@yqChJon#SNayZIvl6n^)&;e)0=X_8*t24wb1*_m}2|} zo;Gtico@x^KGQuq{QFtKb86;g?drNP$twc`$3xswxHxfSi2ZznIr9@0PpRE->={-Q zP!_?oNi7*PSFFQ*^R~@P3H*hb6u>`?LOLrei|PN~8#Bp3$+H)D_;=*u0{f|$NT>r- ztb}4*FaLFs3j5eouDz}c8gKN;?eyZ69F`f1Tr^fFAkHsBpJPW zF%paI1xN@e@p+l>b!C; z0}gYlPeACMRAXj#>dIV}m=}f2cG*tcQ#%B~iNAI4Hu_O)Ch~3QX??k%i4Dd6^nk5c z-$%O9FL)oX8F^HgNgcKcxIs@mw{)p@orN*TP$qj9Nz8`U0^4#dkd+bL8NXo!tJ=@- zEu*|)>38423A(%-7XM!yIhG`NmKI68=!Mk&2AC}SPg`&}7LuuIo)wlnCAvcv z{OdtELGU)^jL*z2%5`~tO@Y42na;hwV#89`XjU6_xOwi=leE|V{AerU$Coeu28FK7 zxljN5R8246IS813n_jmv^-6b7rnsR& zsOFljKfiiTCM_Ucs;XWd=f2l4V0GGn=T_Q(dVSD2;SQItd)~k4sYr9=M8fW zp70MjUbf$Z)NWuGmx&Vmx5JoOanHO7HQ#;je`;y>6c>}%KR^{b(0-ZhVc;bZbCIj? zDIWgsr`k9W65=7?FBYfFMB-GIQ7mT>?zp<1zRFcD&PXh#a2`k|i`rkzB@!me%t_Dw4K z`o1G0B;m}Yc&l&UY9|8LCg|jtB=jJp?A~pnkfBdjAH)-xuTfLgm3i)aM!&jxPThvD zOjClP+!Sn&A|f;S_FVZ>(PEj3crU!sv|JCC>@UodhTJjShU&-n>4FOj+YcV7W__uP znN1(>PpwH5^|%PiJ1Nm#uis3#HOQs^D%1W1IoelDesNH#h?Hh@#nYV~cXrO&vl=8y zF$;yqO%waD4)xlF*f8d-Gn~7k9>>uinNX)-+vkGnMG6HsBA6@v*tI}5h1=Yb)z_*J zOIsr7YHw$F&gE5(U{h0N1_e<@3HNp3vQcoq2oET`hmVEz{%v+f@goI=(AruQl%wme zH1hru5|84VW>xKluEJr+!D0RJ5#KPQCa=}o-ikX$O~C`B75Z`eD@R4QFq6I7!~K(7Pj84lrAX5$ z?_28SH@dudL;GsdQhq{xV|dEp-r_!aHgf1kJ|CZe0J{DI_VBhlRf-+6+}U;`MOMGGSJKzS>GI8$+uwT4({`O z{b5%=YYP)tS@bH25)z#+-?6ios6KlsfV14+A5DG<0xYbMM>i>ky1LY2Uf^oJ8{nOn z6(AXaZ(+Zk$&jz!Y*ro{e_!OsG)FkoGmdc5DcQ2ms@*DWH_?kTOdP9N!S})OV{YdV!lRab2`M)`e zw=W1oSg>`pz;tI6Qg7A16gN&|e$!a{M>c(13OQD&r@mGMSz6(%Ju%M8Z6nh^I-WnJ zzTeTYnop&sYWOgY_1iReR!me86m?nk-yRSgR(e5M~y^0)H`CTZsen8ZDf zTvgSFn?d~K|Bz5Vu4Li`Gy;kl=|9$g*F@5ou<*ZftGz^VQqm|5;|3ATI;sv0CSysM zGGaf%p%`rn=(tR~-|1FnuHuT#yh0^DZhA~tB&WsRe#e{ z>`iNk7ob=&jG42JSb_&XB~$zMdoY>}`H3Xbn3U><&C$3uFB%8uP?#kkF9!YRL@RQl z8ufp3ckf9_=zK65X$}*R5TX-@8cANhE5GZiFsg(h8u2-wohvyGHI-4VZQ#MPA~FC= zUE13z^Ax*`CIujz*A<@s&!5gECLtk3x)Z<4+FO@;H;z5^sdAF@WVb4l&fmU&Mk71| z1cVw|Cq*KYjxlyl4F`eXFWcsnXHalZw3Db!j7tVeK2v<&L_oIwl~f0X-4Q6&N`i$& zW1?lkLbX2K>jD$Ez2EeanJNUl#D)f~zNb$J1zhRVSB@1@b2{<-cKQ!iJXXGJk3LQK zv(xDlrTOVON|HT%$maAS_!w{SzpLJB_P6=+?py@+?~<%{m*+D#JKmH#v=Wj-7S|Pe z&ys7>vEU2e2hTxe?HV%~4|8rD&fiRV8O%N?WUw>yXvp6VvZI!kmcV)?@xP*=SuJ4d zuG86$JFSoB^D3L3Z?3C1hxJPsGro8~@J=g!wKytgSuXx~&?W86Gw7ShgVzaaakWwb zkxXbtT_4fcH#}{mDKKa-UEjWoWx(N{-U!aivnG~pYI4NQW5GM*Cm74E;x^RT#JjrL zw}TyK4DKi4anJr-m(!e1A5U``83mf@G8lq!IX>&r{U?8XYrtxor6s%!f6OpYgx;krSc_`$*R>^LkKA@0pnO(ud?qeq< zKr5m6-dQb8y`snVotjiJ53#Vs zb(jmo(&p?E|C?+kwUXxHB6wJ8`Y{Acv z8v_yy(lfLcVyEt!l;$QXdhpmb5g*a|8V1v}O>D|yz_?xn1w}KMDVn+S!YLZ#)ideg z-Pmz)F2-l$SpFg+MNTR@T=T;Rtte5x5G;H=fcYL;7F0}JKm(hcOeA*x69@!Fv_cD= zYi~%xB)l6Q>mMM_Z!9cNlxS0+`*9x}(7&{r!VDliyWsZrsa9CG!Widi@lC_o;c7kB ze3!7?_n~=pVcuchaIxE(Sbjj>C$P;=3u7|^pPP@LfpvL1;_7h^56#{|ad(5hviP0F zhBE71suJye<u;?-mvob`lyzx^CsC-VXd<4wyXXC0LZX!m! zz2DtuT|)$&*?n1S0H{_>dEc5VPh`!9tIu`~{qvg8-KU{{{}Q=w9S)69LbW8^`q~9* z4~efY?FFpYb@i;nqUN_}!JN?jcg2q%>7viCUGq<)`bu_k!U2~cOw8n@I+r725=OT? zj2zg*{Xu&O1NFH%V=&%@Ji#}3-f^rD*BHYZCdVoX@voa;CWsr-8Yr37=fsg!$Pu3X z=Lj1o*}-eP@{Q<#txpE^en6w4 z;^js1*2+c?%^I0|{@0wss1PuZmoIr?^W1kSB+Z!^q3l>59xMBhW)jtvRoETS&P+~l zlMTaFfEF?#F?8PJ21%~eI?(OyWiY5HM+HeRN?Lu&@YvL8&X}3uS%~GcoLNp4uF^?h zC9D&bv@D1YBNtUn9aC0Q^UcmiDVu*hQkKDi$OInqG#5%B(|J^eFvG3T8Xgse)7#4g z7z&(TWAzgXE-u&y2M?J^)9kgQektO0M2Jvj@Cmr`^qxhp;dB`GPjF0M~! zY$rM__1TPI-#&UibD5zYox^qBw$!VjXMPyZp<*!ST`G7)HsKoPp#P<=#kImhycA2q zc(gOzJv_Vfz=RTmNBZG>4gJxi+|i?-SQh&e^(-Y^HOEgj_R_ZW4MdkORL0qL4Jf_70cmXCHMTr<$>)t2Vo^8+~g#@$<`*UrqeAIkHaCmi2%VGY8xU6 zZf^~6xcy)IPwfg$yzq}=qTyJFb3G@=ZjBz3kP!1=Hf2^!aBtopM=abc4>UB5*R^$d zMYP}F;H1QjknXVE`uBo2!r*%ujGIXb{tluuz_pV}9!4#h%}T@cUG{!B`nz|0f7i~x zmjUQP7~cPeLt2^)%EGw#j&#{uNmV9CQiJWW3CT5 z&6_7#m;VV_7hAg^jw>_iyt&jTnx&G}kes)JWM*k-b5eHy_#t?4Jb#OeE4tVR)EomXL;5CMzq zY>B@d(z`*z5(-5kkBK#0{wuGaQao9&khg=Y*xRQ}m;0Hs9nR|LS1~@L5*-{OQnpAWzEEZHx z(cDEDr*qgX=Mb_tCEf^SW~6x(&q}nkytn+j9QPKU!9;`T#3M2w)QI>7=n&+7Dg;+G z7FUM*{Fyx1Dpz+WTtuY9dbjdrKVhaMo?Mc(*N>I_kuu^reckTN z5BO|iz|Y!Jqk1YNcmaqXghtH%e})udbqG4FY|Cq4&ySF#;QD*dWkBD%>IG!E`w-Ad z@Ad~RN^mKWUX1ji0TM=!5Ks~YoyLir?gs5@OJYCC(0QY#2>$lDv6?*7MDP z=20gJS{n6cBT*)nNjh^|W2Dn=)}vI%ZN|O!-nK}d)XU2UMIO?n_l-&Q6SAXAFDIsI zP`!Mm?UH2CG%1Z-l>;Gp?O*O=iL2{HxZFwJJ0IJg)kfoTjeT*aK*CT(;nfC%_pv;$ z()@efVwpH*ODZ~$uyN|wQb?--ITNwu{h*NG2-f(HAjB*KK@~#J)G7*}_)=SYO+GGB z$mL~~7yiEvBsK+vzA!3QlR5q6lIC+Z&wwySCmeFU7QM?U`CVP=hD+;w9L-K4pU_V@HHzNkj&{X6Rqc@kx3_FjH zw*cy|S4={$0z-8vSky~qEKmPjoHz8PddVn@=eUJZf=4X{W^Y*iY90@lqh^Jb0YDKi z-wpDn%^3qpG#>HPJM(7&S*prq8iBSLum^=FE)W(Ld$d9O)9Q$^Xlnt%6s%>`CEYg zTCaQE>Tbj<)L(}=gV9rkFW2l1^n9jlZnJ-1oc8ePR`Gew#Xq@y#~XIDn#S7<=i=HN zU@C*FP;jN+`CrQBH+ST&@m+XWwkfYc6s`r#PE zDz>LqyRYln!{Z!v=XQXni2d^>Y28%%`^>+4CnXabmiVr){GFYhbJvBb2^=BBu3S=sU3 zkjDQ05i3dLP1x+wVlQXUkM!3kSDC1P=8WFZ`Xu!{J?O{XPll^QLtp>lUvZ%&x&c8C z{5SzyL1G~&tK`69g|t`LvKgnuh>wa~T-$hsRS=3D?$=xPHImTTt7x92&@ANunLp;nj=`?C`$==@z)^IgcR8Joyj%njEh06^o}gcAktClshVQ45dA zs0}u?#@~NK^KxLC=c5cTRhUON(=T zyh*T1X;xDs{GxtfaBOgRdW`FQ&#&mV)gXiLHgRIG!~Z zgolSP$Ua^URf6ag#ac52o)(Z;q_uz0{q8mr6oAqO`Z474y>Om@*Y%(0G4MGBKwOf& z24VEb2K){7u%L7TXI=2tuK^=oof5-`-K8BvBO@J2!3If}Sn5kl+4TYu=I%VhB{kGx z%-)CP8E7RC&$+S(d3%m<`|Sbs^@*--#FXta;#m$MWLrD5qF^Lt{ToKch00Lw%9k-n>H&QvxX~f` zR^T4QAc`$I>saFkrZs>ls(@ox7Fgke|G~$#pShqt0NeL4FmO->eTj|Do%`l}3y}Sn z2X9P&^knl@qXN4r1va9~&7O~Ykp!KkBe2Dx_V#YfKqy~8#zi5yR4~N^{w#$0vcK*D z)mR3S3JXmb)a0e5vB18~fV>zuRG(akio%@*PX>J(9)1Fxz=yAiF#TiY*mIrwMKjdY z=S}|Y(^7KXHJWWfzp3O%f+J;N6;WdJ=(dVzMaEQJ{iNq!?(j#taeS1Nnk^ni0i9zwfBBw|x7cvL zFwBcjQx$SDeFcu58yS_^QxUv$cDCT<1-hOfaB-)gt%8PKk}*^LDV4-%voTL#I~2iy ztQJ0QEfgv#Ca>4k*0a9BrPBWL9Zt}GPlOLg2Wu`JcXlKplRb4>bgZv|=85UL_OAa! zUU@R~KRCvWcbnSg7|c?nnu~uNnA6_od1`1Z)|l>ydF`qX`6x|vX?7~eTT2s}TFu_g z_S9S$JB6pLQQi?sf>@_yc+q>{Y8DSNU2GJn8DNvSkpnf5iVDu~Gw%|7OD&_)Lg_JQ8Vv z#2^C25C39b`~m|aVZlb~JKd{Ezif6Sol!$eYY52yKIfx8q(mX^3$e0Dd^`}66FP86~Z9P9@d`&Sfx3EFoRj1 zj6OPK%WKPnR>=9IE}A`9{3A|Ula4>`I7D@WY#9+cBH@O}hDBUE!1Zc?_YF3^n=hO% zK@jlyLsZM?;;^c*7Yc$lUAuY+ClRG|DM;$%5kG~1L|LqPB$Zd>biEvLWJjv6!3H=O zYG6ksLWXZ6NQ1!enF)Rp_&mE{X|*?`z;&=PBn-+9pxP5d4BK2)<2l4srAaV0A&y?) zE0vA@2RYavPV(gM)5dQ2i9=ZB5#r>AolgqlH-RK+pw8CK#pg#GFCIYl^aAYUWni2m zn{x@2WhTE0HLYhF(oXi4P0D|}fyldNqjCaj77pZ_N=(j-Lg;2ML<01K_%o;F5Y7{o zbhkO&DB#_~N{D>xqXO&5e1GfK;g&8VwGDDrJ*6^i_V?Uu@Oa64HQFzz)C9n=meVbM zq-}$qPz!%E>g{YJiYeFwr{tkEPO}9CsyR^`(rLK4{J~Dk{8z=LPi) z5&gc?aY+WTn8i(TgBRTt*jQMU6w;EKHy%IcgmN7-;F-q46N-YpITqSG-bSU=vkiCd zFcC2v4iAzxo5c_E<_INB&}}-O(NGn~hAP_@Kb8-B*Zo*nJzq#*iJI-|RV|pgL;sZ2 zTaduS+Er~ujn@U=)&F7I;h~%vP>kBdoXFxLn9c;hYdGgJVqNFBU0`k355VnIAR6%p zd~U7nh^WVZe{YOV?X|gd6-$`tCa@=n&<}5zgQ)Q8^+A(#^XUVsx;xYaW!~p9ki7;d z1;mn*5QX>^4~%FeG7o?+S{ov0v9Po2+&XfCqn)iL85%s)9GPdo=J3kzk$8{10OL8P|>Ar2stA8o67)+@=mG~*)VqXNXX7iVt5@izsJj~aF1 zM7oxz(tm??1Q-$k4767q_rbN;-%Te!>4#S`)Y=$W#{wR{15W?Pl?%+L47d z($bW8_@_3n`#G{=lwnxq%mH1lyE`6CG3^Cf8yoM*RDT(%!4xvMjYDM^oCGg;Kv&J@Rlyy*3+ydT?2#I&{#$#;Y#TEbq;U7V8G{vp%p8h=Ta82!k`@s;wJ` zw5zr0&dR+`Ud>okZEt2aT%n2_zVI}mOAR}R{Pm8Yt>mmS5SR_RfG8;kZc0RJ0CpBD z|B7_05N;cANC!>&zJac-92&V|5KQIjxkC!4{QiB9wW6x+*Y%zkdl}JP`k(jU1bd&m$C?zC{F= zB!>E1$zyF7_R)NOB72IEFG8qQ^sF6v*)maDWE46AV^@=&#C?v(1R)W}vw?-z+)+xS z28@|E*hu>@pDdGY>M>K7WA5mfruJUF`g3v7p#bNSj%U9UYwTSeS0&jOO7%bNT3^@3 zXDF~tZXb38A3T0ihBNj{rL4)k8ndE0)wiHcynH6Tt~Bb_N_WQLfwg2~Gr-O7QVKPj%RK{s&g&K)JPRYZCSMfRNSF6cag(UiJvTuT7G zqc#LcLihJszwSLOAK-Gff_Lt?3HvG(op!!&-O&1H4w*^YSKXDda)A&j)QM|g2HZBrl*EkRi99Aq;5ZWL z4eQSsoJtVO9Vjj;IvsLPlae~2Vwepe7DF7$klb@PWJ5NiB~8i0y~G5sJBVNeYkyTedBmvxB4_6tHra1fv6e>O%;Y=_d-c7=XiGS zOT!e;vjGR%O-{;!`#nPO*ey61e0ylg?c&aXIEfD(10E`W{xmh+RZkGF*N|;N$rn9F>2B!RlD?FgM{2S-O@&;#?m#h ze=96V2?<$(hpeQm`aPcBQ@Gd6s4c7$E#bY!#XlZ(fxOz3g+O3Qq0deE!-Kp+pq5ur z@eaB&WH~n+)oI8= z#=&I95p;+j4lbB}7vTo0Qi4ufNbrVyxURv|r`Xh+y|5O*ng`KVBEj}F;@+NL=H-s= zgGXbhZIvv386bAM0IbE6D+@5m+i!M-2|++Wb>nY%mFun^Lp!}kSD`9~3X+|jJu^Go z9|=-*-&?w&NnQ+rJ%4q9N=6j-Qz>ePMCNBNNgmT*pd~6lW+t`#8SWdNt*WEb1@hVd zqih;7lhWz%IkGM-uv1*s!3{!ptDl;bUqA9&A-i-YpfV%@QiUl&^sjF0_?v3_8f^(+ z>Pmq|^DuV}J@SLX%3Aj?bIRYoZcKM;wiaTh-1vbIe@oyQX9v%d8Vr+86MA8tY6Wku z*wDaV$$HeRX)y-UgGd$~vZ2Hwn|(g@nb!w4KMPpLP*8B&jDP)zTHJAibK7uduHC@~ zr1IX4;$42#0GH)nDD5EmR|-i9#r%q$+Sxe6P^cpn6(Tq=)sY!>fl5jM8rRdGD$s!= zIdZTsp*;;88PP)i2#%AI-_}Tpf;cmH0@N85o&?lrC`+Ru{nxN+0(mQfP`}rJnkL)k zwK1gcDy9iN=sMBX*H2q`23#VBSUJ`^*oG<@cCRLSQs0!$wl4|RLT>JS+jr;HO})`y zze>Th+Cr`fOj4?=6QK|IGAd^E5~f_V4(P=vNo-n0#RUaM-EVKnFOSlWE{h!r0tygL zA8mf<1*+$LAwJ-)+QVe!o5(vjdK;Tlorsw*hOS+ezFvXO2!7@nD(nVdxg(+<|LN<0nWO1`_0ZE$0bF8cHU%k1%G&YTxOO6#Y1~m!W+fod4l`gX^8} zs9etQ)k7<-gCI8}rQt}If?bS`N}dSML}nw79p%c$EBH{3^~-| zglZh`rLRZU{!n@lW^03gOE5?;8C@O{b4!&V=rAbAD@LDR9~INQ`=D`#Si;K6 z%6SSj;NYBqgey7-jw@Ep!8uAfis*p5Kr8ZVEwT5!w={sX?;pIXImen9;i6mw!mpox zJNMLD+|2FcZ^R}!0OE>4--JSf0cYWkj+)@7CYalC69C~iiY4{<-P5`9_$%mW-=5o5 zp_^LQ!M%9{_chd@9UUFEt^VYr`H<|94yna(I^%@2>iL`>3?Av~>%S>1g!|-H!DXA% z$dvhELgQHwkjgGsU1;-Kc@OX7hqS_h&jSqq$`K7nue%b&)$MDDqrT*x|Ogv~w zIK!FYi;Oq#Iyq~g@zHD;JzGw7B0|bwL|gwOfvf+}{=fGu38<}{6dNsHcqR;Kir12^ z3Y$i*dG9UdCIKkx@K{)gddsyutBg#Dd=I}&=`Z)6hM{=;0gAK8<lAO3l+!K`>#N%O*5)IO1r1_&T zzc1>#IoSmca(!SlhlV)Ecfi&q=2gl8YzTbU!Doj6>HWbDj()12A_K7!0ym4ClX)=h z08&3Ka)?5>JxmhqAvq49CSR~knGIoBs$DAv0YPASpHKv#d)r{kr3$ir02UDQIdDTn z+WY#bb8w$WOfk-&{WS)Z5Gr~kcMlO`LwYNn&1hP+tjkOTnGAft~+}fm#JVbHh*-AI0Znv9ZvrR{s{V$UAV>XS&eXl&iMAzV$;4< zK{)O|cOD@X8?TZHSUQVbp6v~a)m?8qp+StXkttME@U8spj~{UwXZn%#43})8h`XbP z07UJYfpL|CQ8BnK{53m6phM`%iK*ZDiNk$H?{nq=6&^ZZF=I7OY_Qxdz03^G=BN<& z`(DHx65OKQVZ4a=N8UH<`BV6*IK1+7q^hC4FHN`xUXCEF6F|p5Kd(`&~x$JHY}LnYWbRJb^hM(5qN2l9kQP zQ$;=gxgSkEue2j3BPe7gdtJu;{bMXQrUaKN)@Rfb+At5tTio65vvhi~QXg@u&6)mS zQIDJ5bF&^%Hq$yayVYX!pQd8DI?ICo5-lIEwhK3LL|R(f{h*8SVr z5PfT1=d_2fd?3WjXIPkP&qICxeieQ6`;n!Cyl77}_5TG_Au*HBQiC{un%48#FaRXl_RQR=d$_3z(5WFiN?>zN=P(3y1s zYa01d`B4`n8S&-ImaU`v5J&(v<;iLP4EfULFqyUx1k>h*ZHw zgUABwPvauo+%XhEkPIrY_*Om6tG2iteyV5Bp23>}Wv?&rNtVxqhk4&XH#j&nBnd&R zaOAz}ZKNg&L4v{IyXHfA15uYeurVhRwK+SWa7hGnvO9L!C&Jh{hG8`ZuU_$kI|&ng zG(d~pUmyRHjiNPz&B{uK3$4LP6Si24mXYA-f9r}tLvwjA;|m+DYpAbu)6DWLYUcEL z->0`m_`c7-Jl5A2kDxp#GnMDBsK|S3x4eYC!|;u|HZQ$-{0__1Z{@^J4MvVW6- z55Mr=Ab944UK{3PNbw6n){hstd<4G{|HlvUmzNSLE_axB^=}TWZ^bxsq9@`eK(lWn z?M!lfqxb-VFCZ=j7a~6;vXp?dhu(}Ed}|vE9na4sKtPq4ovcl!Lvpkd@t=!r^&ijjj^L#?=t$6=lgX|My<;?&C`T`{3aNG@O8s% zQ{1Y;fZR&EtVXF~RR?5Va5UL{Pj&ncP*-$~#P$xVY%y#TL`@a?Drwq&+mW%YS)>Gv z_=VVRY;@#m>6I&2;%2e6&b%9~+**+%6r62P+TeH#MZ#g?IR85svb=r!mX(}0`T?=n zG2_(K6v}$6r1`;5IIvO^<(@qDRi(gvF!MmdIiV={JDPw@&+3|qw+gX&ZQva|JSA@@ zG@-qVRUy89@l$ONCK4;^FZI{#3wy`nMiO?`?K#sXv3<}t?9t#Zft*%Ecg`Z{ z3x7KfX8e`C@r-Gn%{&4FRL}Y9+|Svs!^$SmLc&Si_@|ZOVmlF6GEB<L*P;T?c)9ow%yT{uW2kA<#LT}|yFkn50lc@s07`G&N_m#56v z=yEgz!kI2Csqx7jYWjskesl}yX?468bZUAc|0G8I-rdSh2W6Aq)C-@N2b&6uDBgdc zgCxp&}4q1mcThiaT9U(0XHD5(8nq#ZEFYrHPan5<_lh%V9b>U?Tm2IIam@&{8!Igzx$>v z6-6)FO~^mlWc8(9%R(K~-`{xJ8an`2lIg0_aG1;k)?58^!4I%A3uwMmGiMqq3W(TT z6P1<@;(PSxvG+yIWcCZzTL&ciagp2lr(y*m8!>p-UCICTs2bhJ9DA*pKgK__g|B|* zRD9CQXJzo1w}`95WuYu(uYU7YVD zjcrU!OvgDW=4+g=GAJzl+N~r~I_3Oifx(S{UDZ`X-5@57YcJ{ruc}WL~#j-0DJn zO-u8`f@pv`rnRLd>Dm)y;H8LbN<)U5Abk)@zWXK>op!fv@!MWsPEpYtn9PO32ril7 zd_`76Lu289y0CEQ=g+o+{Pbkky-}e=1q-N;Di2{2$o*<_(ln|GjD_G*Li<=$^rAQU zL074nsxo}4y9*GW-gmOP0r!(TT!{dK=YReB7W|qVVFAFN zTUlG1heH=L6Iv%|(?a;C-2&h~LEFwE_6miY08M7I9_nx>Fkz#RHi8Qg!S5_H{;LB3 z*C^)#79bxk9o(C6f56-Z)0gvyCk%zLBPS!li|Y!(RulNk zooq~9F8gAiwLDdvZEc3d#ZqBRUm9R2x|gy4$c>wR{JJQjn{9mM;O z6(|L;p20ZAXH1h|Wqo}C%-AxEiU^@71OVyy54QM9GS|=>cti-WCL|;TsvZ--u~K0+ zYuUJm1Q!9<7?RQ)VB+?lnXy*U6^N!&P+=PbN zEI-J+8{rP1KnrXC+RV)8?ulcr{DI)Y;yuH|=~Y5Z_BZVU1yxl8d8q@DcL@ZX?l$Qy zRYW=bK(naKryBWw2Xl;d5pCrzy4l)wJg0A?pRz1rv}T5XqWP<*54Gd~>_&ErC~@Z% z5-_5BqU?%PW)j>c$d-!84kr9;m8s6P#fWp>#Bq8$Jz@?0>x;KE z82Q?y1Ma%}$>2Qv;=)_^6h_6J$Y1%|!$YUhTNJ_u7Lgg-KO=!i13OJ6Wos zfX^bpvz__kb0}R!n{lSOD za;IuCt|HsX$44AyAV{bbGMwx>^z%c5_YdOR)03^s3p?O75CQT_2ShLATt$3?{*vgN z!Xo$$R|>+_1)>XBr^QmRD1E7hX;9<&MC0JEU+n;MomBap@?Ss{O@8muPjwXs7;t_|5X>w#NIK#h~h8*eYu>2?u>;#+6fp0Pt??!VdUEm6?XzHd35Iq7{$(j+T`m}g?+XX zj1$~uy8fV9=zE5e7`{RRzMzTgpN|$-hFaUk#s(-n(7bfRE|+=m3OqyRX8ul+27-Ay1U{$}mkU1a4U zHfA>_h#{{6`CjJc<|C4X2w>KDI<G4(SHzMnD=wLTQka?uPe`_r0~=TDO+h8JT~+IA`yD z_P!;J5xO7*`bb!!k=#5eMPOE`AmIq62w4Mi5m5L(dcDsAWeRAB#aLRlsbR@xz}gQc znS>Q0Ks3M)ff){Njb#q@Z36d0u-+fKK6c*f0VaiOo^ZEW01z<7z||Gl9-=mky8v3! zYv;AW8o)XV0ar(2-$bSJt#|hvXgbFy7Z)?noo|5i?ik2M03A1mww@~ z#Q5IP0MUrZ^6kd1LAH^K$6rZH~|$rcq?`4fxoKmUU%~jXXpi-eAwt zwUb)_#R9;#hCzigdUt(VQdU-XFLZwtB4P^Ks=@I?u%AZV4xrtV5}K~mSWzmnfE|>j zbqNp0?O7E}hQ1PdP{3jnl}ErGzdh-%&6l}8TWa@mpMOP7jupy2gZl$@f>^;Y+-;_Z zbga!=OSx0y%d$e2H+FdZ$;hyMNEWHZBKpSD?M=AtZ_K8~<46qo3~$pevt5^x@K@nr z60(32G3s2JVU~zsg!PUw^68-|uW$jETX$^MFTmE{k-!eBqVmLJ%G6YmkBUjFn0tp zNV)+)is7P0)Y7saf-Ae@_P_*O#;=YsR)8^UqtHF@wH2QN4izQJzXAsjfna01WsIle z_!;OYoAzplZBJ8Bzk>jRT9+L)z+psH?zVvgF5|;*E4jFBaPGYRZ5<7RiGg>!T(}(& zagc$iBBF7m$m-uqOH1|R2S=;DpgaY}A%iud2YpZfGdF_9cJN50>C;q5J(1=k)GNeC*OJ`Cya&$Q?t)t zu7A3~kE-El6a0aH9{o-iKv0?CtpLaPl(jEtI`#DQD%~*wKqCgi7RNwsYKZE-1khnW z#k*IJSujq!;0mc9pnPnpphJ<8yKl!pE2hQ%ox>J84sXOPx%TNDW|(-tUw({apS4j z`fdy*0!`3A!3;RdoPmbyq$b8Y5}Yga|KcC;@bF-%k}#VVuRk;ts{k-;j2e`rQ=PW` zsP*JvdmC7UgE9VCSA9)QKDVPB#d_zlPO$XSzfVt2!U5%%UhO_O3+QlBoWR-!LZP%m z7ytwF$^_ifFw81c6XFG6oCKpzB?SPq>v}_WXRDARC;q_p4Dg4=l8cYm_c092q!97R z07umNtJSg52L(h?&>Vrjrx290K>h?TJ$D9}>Mr2X15OQ8-9CrLPND9rI9WnX8x!^@ zLzU;aYEKbNnV8zn&c02$GBB#9uuEtJj7U>bs%sQrB7gs!=#KnECR>gAS*8Y7EFmUb zp=vCO89kG~WWZOMXh$gt_(u!yb2|z$U}f;WN%k*PVUW8Z^&5i{&&=8fwVXmus6Wnch#_#`?504PemQGMbaBdNOIjM-r&3cr8=Ok>n9 zm>iZm?f@K+!O?(rT-Mf>0qS5-iP=F{K*{mr8+~0`xn`u5ogI*O%?DP1E*HKUj9Pa9 zWjT<5`HydzfbSk?RYVNW|4!@J`2eqZxF2oZ3jkdNMlnsnD{18V_NOV=aEe$Z08fKa zVW2k8g6R}t5rm5AuZ{s=k_uET5CARrE`D4dg?#}q)hA7iU=NJ(*Y3R06u#e4w)o1K zAZiv~F~;U#f!?oB-_U>^(Wm=jIk?vdSe*R$Rt{D-^aJ~kyOBoV<_qqE*WmgD+F+Qk zGjJKKG42a5|6qDszSu7W*5cjGY-b@r#bEX}ASwkM2x{pAWsLngh>}weK;xNylqP4$ z{U}_dm=4hNbrJAs#n=c z5~ralqe?6P8qcf4sROzt%T|v<1vS%|T%4PeH8V5&y&P#Z3$s=RmnW=$1QliFbWDYFOd?NZ7nvSU+rz~H*~)&Sr`zp5 z`OOWsW!h@4n%1V-QX6#=E34UJ3y1mW2@W!YTl-F@j2;iU7pX8QXs5}SJgbuLZzX84 z`KPD#y@Y{4xTwZ@nk$K!F}Hl=(|}3f@Lzt({NPI?PftK#QMP_KcfN9@b??>F+BBLj zwJLw7J+{{Od?YRL_Hht+R1AMk@=(!SuX`4xfgQ%)q&nkww4ycO##BQ2ty6Gqk}HW^ zpdT?R%C;ONA7PY;A*@RsK;?X^g|NZvG*e@?gOPqoxo&kc#Lwo(`9yjJ|MMg09_#mCR-5<+^hIueT@+qtd$942@K zbu-9cZ5)ug`?Lq0gf)&`T@Y}d_^9OoGMNz6pjLUW!Q~$&*@NFg0^Dwa058t$R}$;! z*&0|s#-Jn~Y!(m@a0f#o!S%luI$K-kXC8nO(-AncW5o=><=@x5 zJup9Euv$SLH%tv+X9BBB!QBuaFazNDDW=s*p!onD!ZSt>|6@X1itUhRIYW_l4a1&GlNzA|bxOsT!C1xaYF=6mWX(>#9 zPAdm6K42gYmf-7fUzo)wxH|{=f^R&rBgx_c?CErKivvo%vmO2Lh$uEz#i?UATA;Ly z?O*3F4KKU00A>)Y)7q`T34olKq}MXdscvzRY+yI>=$e-4h0t~jdr_*Pc6?;DPK-=m zBMrUDSv{8h&H={P+?xqH4X7|xj@)RC*Aq# z`u{cvW?%g6Dj8}inZ0O!K6n-V)r0D7qdlKw#r1;%`#A1S2F63hw0Fh*jCJRxa;e_t zO1Jk&dLx5fxhpvgOG8ExV@sjLWHaSB)vx>VoP&_tG&1$oXm6LFynA!9o7Xm?G;QAV zt@>4(sk%OP69jU<1A@nrZ$O6f3rO%qZhwt)cnEGJfH4yrn-_rofdD-c+UWky&MFWA zufrs~fd7O|N5~ymgi8x&$6Q=o6odjUB^*ee0smqQZbzU40@qq-9)pIa<|MFC1@|k+ zs9p;|Wm%~iAUA=9MgzeEtP&X;Q-aB9BAfq~>$*%z!Su?&WyRNgsm&c!#!KFpdN7>2 z1I#_r29*JFZ|%6r=ITXPi0~N|%otwZ>sU(osvAS??b{)M*TZlF*gOO*3kHtH)EzXC z!1clpsQ>eJ`C)GN%N^c#y&`uK??(VZYHI?cXo0}$dH_s7mTyhX&%d^?pa+yqen|-< zqXwCf$LEKKhe&8nvje~f`kTS}6VAqvQndt0836Tq4w4~1zRv>c{daFF82Kv!q2@^CgFv4P3l{$d za??NGr9X~X2=~HzcVI`($kO}=`=4i*KTOsD#t23m_!hrSZf=?ba38cHq(Gp_D0p#s zNiQ`a0%`}_`GzQ12MY$f0BX4f3xsq8GZb}>tK#4V0P8UZ9}ot{4K|N<(o;e3gNZo3 zK7VEabL=K#8IZ${`Qfq5d%#^fIAk0g@SdN03tqfI63&j37%HZ6JJ1j7;aKmak#{~D`2s&K=Y^P*3 z;qfEW0+~;L-(9;TeV))&?Y`*^LACqw*_c_vKY>P9+~-+L$Ip(IgM;Um71(>5-WJFK zB>@yOM@D5b*+eb7NvLeD<)7!azA-}Io<8tNNtPvNPv4GTFD-zj>vU#`1fapveR68` ztLmdC|BMOUI2`n`TwUQl?El?*VQ_5#&I3^IsA^_by!+(!cze6^H#|Ys5;SFJ83z`U=%Z;J+7TTSwd#0~n;hA;kK*DpohNe_WacK0HD4b~U*pa{q3#xcN zmVtRdxC7wK@og*EC|X(^-Zw6QC(C4xG(7oRRz-)(4TEK09dE%vtT5otTU8YU=1xw4 z+AazhLL>v?vupW&arwDK7-);H0kIEqg>V2G3BZZt5@l~DojW52(9wqimSxGLo0lmI!=2!4*sBH*#82UN2CeIB*5gsCh~;@7cFql>cSJ^g&u@tz0^J-oN)Yhv`vbrbLogNqfk`YF!h1Be^%6;!7Z*nX zWv||aJbMqs28ny~tshxo01=Q#{rve8rW`8*Eq%S?kpfVke}WB00AL^H_grlVmu%nz z^0()lDPghQt3XLv)Y+LmG$aojZ+gXoA8`z;n!x55z()ba(KsyQ2LglCEQC*qATWg= zOcenn0zlNK3#L;C9am&&K_v6y0FXik0k$0IL_kKy@hq4MX}I&8B#QakPrOzdtD!BbN9>4cPMuGA!- zI{p^))oOWd?Tncjg)X6+?b*)etF8A zqvr9^p=QzVU4BEF+WR?GwSd50=4OFn zS*T)pA%G}qq9Fh6^;e>I>In50?+`_AJzEK_zB({q9c6jin@yLVgVS|@Y@Gwuf29`b&>VHak>{_gCL0s@5?5rc|8zs6D z67T>IW2`5Fu_=tmA(|S~P5yRPPeDZvu1tiu(Eb_|_O$fgt9z7Mw3-x9abQJQU3qbU z-Ns1lC1jsw$1K!wGWY==gND}5Wy&=LK@%o$`<6SvZ^KCt@ zxa7Fz;~@kdo+&f4=8i&gpsAC!@8~MQk1`l3hoK;o$5hYa1KamVf4C$Hp`n_!HSu(= z=S1EtqBxhN9`<%)9SQ@pu2$7KamPzKUwF>bOgY}$cow$#iPqLuxe8mPmliU?k=$+r z%RpuuLiaB92IA&>Q(URKr(vmcZPz+lm4ct*DGO4(uTeBxmux;m5hD(Z)fc@A36$g3DNS9yQl4?&=Rh^8B_UD%G!-HTD zMFY8U1tgO>-=EJC{D!$Hro@tpkel3IP28nTIjBS1w~N)=6+ph~-ci<1d{ zxK`4xA|{U-F56~;g;`&>hp`Bk{>2kz7mexf5S@uem*f@w5))XAZx+v#U3ym80Be<3TMXXxjfy4^E9Q4DW3D}H z`FdDcB4eYIKoe=@nDyQcwYYA8rm=q{)#uKKj}dtjNAXi-C846C5fIb>nNv(d1A|Po zB#1$&wb2&Q)YMlJZcaJheetHYAkb>+WSy#*0R0T zfWKgk36+N@jcmN6nVFwXUE$>9q_TqpuHNkNHSW+b{HMh6bTDj82ioPR!a~qs=Y3lz z)-cq7To?sH2iQv?s3+1EPVDb2Mvaf#+{>*UkW`;u1@`D1&sx?+c=hipaK0%+d_B0} zw)uAcY>%`3ZbTS(WXe}_{#IZ8HuJZ=)Y|RITLS?p5uKSySF4Fn^9NLxA_ir1$-g`g zONx93etg+Y74pO~tis=;offX=$@!{Q^AAPIry|vI2hCKTYUc8z&vP@ggG*$QTOFKq zo{z_IF&Z_tIwcjr*UJ$UrN9LmJe8eTP*=z>GM!+D6}z|wU5$OzUnzNcsB8*rhQ8#dEvIvc;uJ1_n^gpgd|CL0&=) z0AqQ0thsy~NSO9dPw(AZ6!0q~a_6Ca%JicBf9qmY0(?&I7FLHf3cu3QKyfMvD5gOZ z4!&9AniNF{*DbfAL_967lw5egq$Mu+ipRG=y~L$RLyDdtyUoQj0NjYA-@OY2j>JMj zSYE9fyh#M|7zL*qSU*V^IXN=}va+%I`t$|KQzgao^YgPmA$iKua`mhR zQavz=5^ndqQR{>;K;kVxAISpPDprU2{`fH^a{ZdT2|7h9>0QK>mp^&t+cr6VFro2Z z^y9*fayROr^}gJXR>yS-Mwpip*6j_b(D%`=iY^@dv^@Uyt-Wa3_7?6@hEX@<_M&}Y zrh@epGQsim(krnWr-(?hu%4SC06B0phB3F6RgZB4a0fJ z^914v06%G4a)OJ}P~1qX`Lh`q@Q~MOYf4eEq|?)L;^)r;_|WQH4Pj;`do%@4+v&{> zn$g6OJUjLrN!aeWm;;W9eg5KGc6E7yhCD*59>YKa<#h9=ohp63{y} zv}Z(soS9;5#6)2@#5qy^kj{vav!iOciNF=qtdM8WLZ9u#0W^hw9&S6w@w68LmJOo$ zBdcCo5FR@Qb}3|s{o7Efv1UydzncM?`t3C<+19x40WJA#tQn(w=lbcO*S18Wu2Y|_ z`G_n51P+~)*U+=7ls`tOfs>JzjAJtbX3*qT zLP_yawWE=0e@$3m7VaIeW4zSREb26nnjLj75If|}=MAMLk^_xt9cE${?vqn8U{%G2 zT7rwm2+n12B4R~tHgi?EUuOl^aD>9c6N=|xKAy;H@+vsH^VJ224dqXYr_&hzq0ZsV z(2nOAH*4VgBpd8(Th?S2?wi`w zT#tWUxejbZBU|3P5ACWDo#E3GQD;Ws+&@UdZr> zXfx4+C1~SU-)asuZ2=>Gq#Wj=EV{Q+T{!KSvOpsN8*|GY1+NdlfyT)6xKFF&4t}++ z$|KbD2XaZ3>G6Qs7wY;4xdoEl>v5rdTwHc&_Ll9UXxj+ZPka|BY*D2B>EuQZcUF59 z6`6PT{yehQi$M*qK($!aY3n`4K33Xgzu#iddSQfr2NZ^e(PM*LUUQzO`t2dL`AfwH)I)^f?OP;8Wy0K}f2J<7#`J~L+z(Q8Ufu1 zu@9@Jequ7kzdHh*YZRCk(v|BR*oEDm@XmCtI!uR zG5uGo7#P6VmO73N1>ZU?diDiY3W=gnJADUsbNZeW}n!kw1Zv$wRU z?ClKrj_sU30h18Lbz-LB6FicBQO&XI(2%uG>jejxHUA(; z{+L5=G?pD`bskH@8FabHU*+t(iU+$Hp)W!(WSWlqg*3E0nh#p8GrT__3TJ1GyhC>c z1Xx+s5{UY2Jihepbo`DK5>BnEyGMoZj0?wT{5}vuf*Sw%hzIWkasZrCz(`T^ggLAS z43wUI=J0iMlWla=2$aA;>HSH0oE8d~3TopFCuzjp+2r-hVL8^$+-fbj2JLS@6Ph6c z0zgku40_EDZ}`36)8if9RMc26cj6f2uve==52mV7prW^*Uo4wCvDzI>Y2?O%k2i>h z_B|B`B?h;S_dV(MKrvJ|ZCOIW)f^2CQxg|3ZU?%ZSv*@~c+eFDv-)ZO#cu*z8DrGc z%`3>xLqq?k1;BlldHU`Yu_Y|vmmsu4O6=zLU6^!hXx~kkqz4h-+1sVtx z)q$vy4;4RSP{-n)Vrbanogj*{2*toJ9sT*v<@Z>38Eg8L`u<~=;>ZAr3n&4AESln{ zA$iuVtaqtx1F>f7#Kb5i0N2SJTxe+4?;V8(TPZw&!>kVT0fp;h-#UkXS7_A@P8yhO z1hS&H|65pqM>UeJEeU*8>c%Tg$H~Sob4nk2eNe>odlcT-J-Z(DI?gX}Az2~i3QP3L(`QQ77dUgio9A7Xf!DJIqD zwK*yfk(MU)IdK%Krth38*_qoDQs)KzG(UpDAB=M7N+D2BXzAvTTm|c@Qo_r1`Jy6N z(#8^$KOFJ+s%MY%k)hE6XG*sPM@kSaNDK^C?UkHMt)Em~L3t_A-a)tssQq5v&0<0~ za9*LgfuTb$pnYWduhU;;KT!p=3yRHb67YT}iba{`?i1FWwz7%%@r!7Edy;T*@mLH) zNJ1730auisd=}Kz*iUJe`_FcK0NG28^-Rit%@`EjscFO%0199(Tt5Xx#`_;xgUWvy z^O<8N`BE?Enfiqq#fM&~#PZD4H=eE*(v8_zuO(ie=9ZLzja(ZWVaOwhA>2C9=a`~=Fjjg`cIBtpGUrLD&iY>#c?|u;22&g%NEpi7!_lQo z_*i3tAI!U1--SBd%;laUqOikcc7^!0%z&RCUyU%x7+q?I2cyYnYU=AiI+eo1+GSOg zSoDQvC@Ac`2!}C-Xc@>RW<-E89XEN22g5ZsHsYX%q>A|Z{F`kEkc-d>njOgoR1vIn z3qX`|7m7YaID5<4TQHi<&Irvj(SSyCq-ER%Fe6|;9kaFD7@5(6ELE1J=RtFJtoiw> zwQ(9zEu~w9LY7x7PrRdly@#4(!&h8brcoK|^a-mUarDW^4Ke>AGENnov#27qJ>X0- z#erWG59AE&(VT1=IQi z4($2mrQ-VrB`a53OW5tH4GT*6shgd#kTo9eIKRC38vqv1FD*gMC9eWYPIjH zG=J8G`)g4-I?ntlQ_%Nsj(ul@;cV;kO?1~uCXI7KP#bouAaks?_@tl#^|*$nQn;@< zx@g_LWDBPKui7A>m#+VJH2NE&7;kcZrp+HZ0h|`|t0ycT9Ma#bC``ntv)nhx+$Rzh z5@~O|g|UCF3nAhVHU@bWI_eh1T7cPzF-qQDFaFsS$G*nYr8O>M0(NO3 zrd!@0I9rfZ`{hf}SDV@YDh^BqG0-_OwE+V9=sNOGui-**D;+L5BU3Q)b~h$eGjbvj zhq*$AO4Tg2ctGOkx>$l)IChwLIxXRIB_pQvi0wRu!o z^7ktn$oaKJhfKULj`{CVhrdyv!FHPLM{(pMtbs7d8JWY(D7R*Qz zu#Xnn;VZV*H&-o%w98WH5yW8Y^p7|=yN+cCcO|gvj+S`M1BqOJ)&LLOwd|y`J9XU5 zHwr|!5PA!ICr!<3KxdBqXY0mN&-d>K&O?B5#DxNoKSNfM1~ZnCNewyV)XO{353}D` z5>ejuNd97tGC=jX2F!98-+q7%24Yma>1G}0g>SHXQLhs~I=HE~^{t(wdOqXgSnG!~ zO5yK{!>O1|?<|G&x+sz;!fn!QpP~e8gpi@jtylKE0Xcd{>dY6LGMHQgsRKOGFaLdt zl%cEpe)zlS=;HQ#$hf}@GlX~=c^}VjloZV7W7tQ{Ca~jPf#;kH)J#CrpEFSiwgT9F zK(Y@y>a;XkK(GgjGld&36mM~(&3#gZ(DGj4B#H_?4!x)_GqcU+OW>A?Rv|-2#psfg zXW_f$*f$9mOx=>L!nQr1b57?;cTC2{e=hSNa{A_?xnh~IIn@7}ibss?UE+$DJF>Vu zCfChKMj23FsH?a%dK^y@b8Cyr{i#>|avQV94x?IN2skW4Qk5TMTJR z$Xfz<`<`rO5`DjZPqS*f_d!q*kSYy}n+HtKK+r2GupE9;9NGDjrW~5#VHfJhQCbR~M=+(OZgKrn-`wy% zW7zojDv*rAG-x@+#l>LP{rf&l{>)EXImEo*dxNHvR9taBHAgt)fN01j*~!p9^<5rp z1441g2+jVNFKv3-18ZYSl|b{-(cV5mhZnoIHv8?HeVtwoC;mW7rNues$d|tkEq=*X z2P4@=LqJA_{8p-GFSkL7#u*3Ubd_uy_kv5Y=GR}XiC#N{B1&Ym`PUPcb-~w#o=>Bt zaqB(dQI!9EBrG{v7XY3C5@wH#olY5Dl=Dv)@e|u~sDgn8EuD*S7tCxAHfIcT7y*iU z#ZcdWTLbgzo&#Wbyl!j?78akgvUow6z+1j4g20PTie$~+2G{q6?GW}c0OXbA^5MO? zjSZEe&NHq*MkBa1dM+gPW9_=V?u-4Y##vv-n>WX#Ou>rJ?UHz!OoNADWU0zF+vfX0 z?c-}Lu?fCxPFtP?21~N!!Td?mq{MiR$84Q(5Y-uzen^S!@^1Nv6T(W- z9(4`cA^^4IUoA;uz%|h1mZF9G4jCR})ZJ7a2adRl@k9hF-~u3~3#Q})=07l}0YGx< z=PF{u_6?=nKN18C5Bv3oL|8h+0Or|tn=B+E7%N;QVD;%-SRBqo@}q>JCir?ROuU6o zJw2KnMu`vf>Ye}>M)6c2x}v} zH$8c}$M;^74eObH^|1f)Blx`ly9 zCeZ$aob;LFU*kSWU@nL3*UN-j*!7Em1K8lc^|%!77oyJ2z;#FBn&1)AM%esF8_CqA z*R^m*Va|ke?1ok)Vz{2eV+e=XwZ(QPkd4SvTc6D{w@E@uLuruc8}g#KDWtz;19?P? zagNl)@V9Zpv+=?jY{bP)Cmh5@Cb(92)PUBIY<6MSA~R%Le5=E9>A?4#jM*sBW z&`0>1_NK9_Xo4$P0%0T>6J(NO)OudpgQ*`ds08#oz@`9fB<90l358@~yvqVsOk_Gq5NHD~QI3IW9p_|?0`yVC*4h`PJ?{b%ahw(WC zU9hk&Ck)DDQ^uVKKS#J&vj5;4-wqUW^!Q_TaWq_SP^e;T5}BlW^jf50N`2D1e7bJj zLl-uIK>m+z#VoY=we6A<8lMh`}2w4jVa&(0n7Oc^b4J*yK%smqDacMSsQ}f>OP<9O@oJA z(ZF}v810n4{5#89z4l-o7kS^i=M$&}74&XyHCtNOcgUs{STICo-QoVWxWmaS_V-skFtcYJ&hPdmdsaz!hdwXwo@b`b@i zFpSE^6Z}yrHQcRWH0{DS<({`hmP~ix8Qv?wr5;0TpV=9zP2#tdBXsEE=Kd4S+3J)o z2POv=eZ)gH9Ur4>JP=#j$8o7`y&a+>-W_mOWP#88w4#dhyfw^orzbn^#4-ZDns0I}4y9Hmd0$)Gu)&M5?qYTENNZE;o8bWBSWKl5YEDs9Dv zD2;y&g8zzSZV96TLje%F0{Rd#I=Xrn?rXRpqAe#4hw0Z#s7&|z)GLE=sl-ShP7UqJ`1^RkNG(V~DYhm>2qK5Ovq~1%? zC5T#PIxzTS{y2RQGmo1Ha~5$nz~PCT;OozrXF2+{Y=MIJ;kQ|~_TU_kTJ8kDd2w@) zOfIM{CK*{T+1PS^lavi;-+dC)gbQ|27FFbA2?m<3!|`429^X+%180(m9jmH<)#Hg49y610_Xjait-2NkiadM-Y3814YY6<436lG z&5gd*b{VN&)Hz}5vBO_fLgYLuI~Pt6%*)JpG`6dzr8(p26ZA}^Sg3Q22EISg1>Y{F z@Gt8I^_Z6J&Pj^DzeijACf>-lq_E^W<217tk&4jUM6>Z(GnT~qLE$ijl^DIsp+G-) z=3>=@sAYeb^pLp}#5^E0tLfSnoIVX93pbdhMTQGLL(OSLMm9w84}RB7H8c2a-9zpB z>o6Y=4$?W>I+TDJr!k*SgT5{GW4A~!nZOL*Apj>VI-0P(y+3nd@0U+BSp;@ew7-m3 ziK*KoqMr%jv|kW`q5k$$gsWev7AN20pTkb;<<1BG?4>&T(ep}(V1&2OHr#_Qp*md^ z^0p~2^@{9PNN!A=(15{3hc40lDe2Om_2-1d0|Be3!GlZnNs{8VBQ~*$Y+O#k*J(`= zo;yQMuN)+9o9@Cx#vWE9N2LTugjsm1By3s-@}DhP5D&x^{G7p^s#v`=d6|cb5HKiZ z_Jv*#!ko}AGAbR?GQvb_Ho8?YJQOf47WRIJJRvky5=q`aHT`tCV1~jH{;6ACQ zn?Z>wyK-(l$Z7~XrjY3bfNTrB3>^1Ae_m}LMB|`Dsq#lsM|O>qN48WanmDJFjJPW* zdNq}Vg%0$Voo*4dAR~(kNcRsUAT2jSWl(_kG&Y<}-O`A*Y$Yf4z&>w3?_$F!0nNE2 zd3r`@e!2^9_UN`?^;BQS>bMOWSCGW~9#K!?VxahUQtaIkoD{n|Ni6ITVi9a*$D9|$FzFRs|VKk9Hb;9Gj+x4A(N8Ec_qpc9##+t zoxYy(vh%I_a_)Z|w12$)Ik7Lc;PYiRy+i6V*s`W%V2%q7&XfK8nGo+=o@&$^TQmgG z<&{_ARL~nXK{!PBbpSz)S^h(!vfk7NHtzmKv5Oz1@P8Dzx~UN-Ha5g#p_@^x=hXOE zaIrz{!zYD)TO)I@^Xl#Vsg$r9;h%Ssq!oVKrVLmN6x4b5ZZzpU&#C!8DvpedPWL*KcOHJ?Xk_YTZ~j+KF3G^UqI6F)|R1rPO_mVa=W)YGZ<*8m^9+bw!WXbySOS?-C?HjLj4a}h= zabgaxUo-AOt*c|)k7p|D3*Y#P2)7ivP4+(mRn7o9kI04FQ*AA}(rsRH>UBp)0#{V$ z$AouMo3@{7=Y`_Om)u!XFuE7l+1u_T7cQ9mA%v5*H!F{&PqrDtxvpAM41Kx4utUz3 z7g0xO&$Zg*`R~6lk^9l9 zAph1Ec!Ox%-;n=a0d`{?6`>BSwEyqD|NB=4@_)vZ|Nj?x{jsRJ0&ubx=U3*icrVu$ zE`PO>`8+24ye)eq!e>@$*VepRep&7I3>R-}d`8@<0I>)Dz&ji|{Z-}dtCQ=;tHUFa zD&nfw!zr50~#iLA|g>cfw}S~cx?5j>o3m0T{jA^ydW_F4MmDK@)j zC-t1o=3sm4-?Zh5domRr&K5q`(KiJAj4wlo>STBt!MQ^UvfeX}G-kTU9w7t2SLz<=8@8PSi29JVzQP(1&h+L{^=j?>S_Dkd zfp1j_L0&$}=EV1&xS<_RlY8fW`JQRPg`QbIaX!Psd%^AdU3;0~uitm`g18?aB5Lq? zmy8TvSP{FBA?k&=ZV_+k>2u#*i!^k{G|^MhuR znjRA)RY9oQQ>i4=|wn?OVHgM+2+Xh6AA6AtqG``Q$A(Q)ll{^nOx1Q`* zrAa%~i@L~O2%kL{gkS8ni*_Z6bHXh%1kGiWuUmZaT#{18j0>#D|Of}Y(|OH(NB z`@e6BST<^e?;O%Tsp}U|-N+PZ>6sT~3Bz$&Db*>BpCERjUc$?uBR*txbMrnKqU}6J ze|Wi>O^F;p$*V3Dn8tp~rSheeo8~bXj%#?y8_O{n;UX(4jhzxzmvoWq7-!`;*{#!? zAd}_pNlG31_8i$SMH`>2+qgs85?7`UQn z_=GGZloOVvj+=aYcsf?oOt`$?5SHZQV^(uDf-Hq+cS5~Ad{20m`#O;@ww8?_o{INL zqlvC6ce{G)l(u>qtyJ+j$ERw1=-Hj|^qUp#sF$bFOzZ6UNtBa9cH`TY?Sa6X_1@?( zJ8$Wcn#9lVL-~iix<^dnt}phK>=&1dRi~?eoXq!skx87e67K$STee|6eH0YKL=eLa zZ3Qnyla#KLoKeUYL;KxVj(R6_Z=gI0Vt#xO3;{eDiqtSvLsv+GWW_})3>02TH)Y{Oh}b*-VNRn>lz zRn>)D3BJQbosfLkclQs9&mWLqM+)3>(`YJg<#yl{*FnMaJ z{|ZwhY_jvj!{?7#T_dV4^K;Gi`_ETlwd_7;Ce~vR<`?kMbWp@=Wzu z6Gom0p{I+__gJUexM}K@+}gWpvfXrD|H7}T?)_TB@Et&5RauLeK$>;*iHUSEN7kxD z;j-Vvm?;L<8wN#48`_1U>i<4Yf?!KfH@mQ($^>26Sh z-8g?wckU)6dZS9Y%Qc=UJvzk7{W1CIQZ078b2kWXHSTR;Nmib7*JQTe4{RT0#r(Z& zda%%tH&)NpJU2|=cc7qdEq}2`(t~?xNJ`S%z~FyWr*+IpVPVcz_JSeQgK?t6ONVI0 z`o+r)(#3kjt@o|tjZ=0{^tQQ$H(87f+IyfmJ~YlcK=p3nFa#~Q9hkJ?PMrDJuQ)&8e(16J`?{+TuWgxaKn@Qc0-;cnlN8g)cwQTB zad<*xW7uyr>(iCNlPZO*Qs2grfRjyLg>>}+u6hqgxX8#v=_jIvPBfoeitFq=Pn8rU5;()cpPEpC+s z!DV~B2^|*sQi6?-PD>84o<+<`>v~Uk>h>hW5xa4HK+)FF>o2dAyfktC1`R#Dp2snt zL(G$giq(6%IPhNnmj>pK;(Z0(W}R!It*04vIexh7&MrU%*^}lCe4osc;eNW@@4pj z{VPscf;4d*>cK(z;-jPMwYP`-qNp`?)ZfCF_50))Y;8p|m|hcX9kY2mzZ+QE{k9&E z_Lk8Vvb!Qs{iOc{^4+zkF!B#LTkc~&L`&>eGrH}2be-W{fG|6hH(Z~dRi!sTO0_of zgud7to=~qJzF%pB{?e_{XJFGPa4s(7jwP5FNp|UL;no5j*3TSs8aBS}j?rl2VJ7SK z1>25SFH;MD1@i5ITvUhA?Lp0QN~ zy&i|_>g*>HIrJS@H}I*>STC=>?dTUAIfNKi>+kdoX}($7W9>qBT;|~PYk3w$TuVve zR$OKNuyl*7q5)yP4_t?^?VcYe`@JlSnw5x3gR2_-YT(E!LhweAWbWu?0)K#npG2$9 z%w2!c#jV>K;draiJ1cY~P3YR?$&K|4u?g$mhrY+;C6CKk9{_Z=0dFo=)n;jUSpQiNqcStBP(EsWqNE z&gR57kHhCmY)Bv8zmruo?Dp(xG3)xvI%lHPseBmu;I7eUP`Jf0>g43C+~}x z7?(WSIymUbAWzV~gt{g}9E1m+e)vPXQo4KPW{*E$zBbk6`T8p`Nv5V03c9t8?nz37 ztD}RaYr|ngA$UCdg#wWt=A(w~l3uz^ni(6d_a$PTd;e&OlTCgW3OUX%H`^`0ioO>a zP(gs=%2Pz<%N5m%W&7aGwMIoH?Ng5r9t&!D2a|Q3PHk|QlL)foZ_mWsqatB&URXUf zMQr^^gKIyzA31rRLut5V&f;}CI4|0xzfxM+^)BLSQHi`yGpjRAipJ**w-TGj7X|SS zW7x0re(FkRAi*zeyjthx1!w)?{;JQ|uMp1$$l)E*_CkV?=VwB)|0(J^qnZl3ZRlMT zkX}?on)D(dRRlzO?@b`|E}hUprK&~4sbM`)a?i|_7If9GiiV5CX`7T3e`&Iefo;4={(N%BOexsahrAK%d5eop| zphQ0MTB_R(YSgCfTFl3mM`9&wnFO0-ZllWjJiS6F_b$L)v27Wqpl!00ysE$N&iBP- zY~go&C+r&bvDbp~i5eObFLwRM$ny^31JOc{OW&DrPqwdm_}wQu0Qlmr<}tkT-(*jF zvC-3J{CE}?edtl$eO-=fX=)$c@0ufDA&6LPXw)oZdjFZ*R0o&iDEiN* z=>o-KTv+cEf(CZzs4LBvx@)Cx_#u+;Qc&~+XDgruXW8q~_)+Ky*gb5N)USHdI+5T+algPc| zpCaTv`2izXqUW)lGU;tDSuP_fqpjB4=`X7arf>NI&K(v}#6mdW;NX)2!hdC2hRVrn5) zwFT?Gs3=4>5fCgFdb4@GPwY{kn=mNFcDBG zht)d2-I5MlS+FmY&W2)~>xIC}B-y=&dAFr^{ohTlbV~rX#oj}5c#J=uY2?O`4OgE_ z#m@>~w*YC{5G=f~cDkTHowmbEejPD>kkqxjkIIYs4ef_gFFQgM5H+wC z&%tX|!of{La4^Z(kRk3v9)af#r|W2L)#B6)n;k4b0SON(in*Wein0*~#y482)0;IP z)4N+rkpcq$`5e7=HPkbAx$T}yYxja%HmRsZo=e@KM86k0#S#FChf#tyAtxsYM0hAX zl3Vx-Y{kkQCN?374F4`92|%`so{)>~`7Qq%uD>+se;@YaIv8+p;kL!RJp3m2`NZ!Lf=3EMy7&BjuF8*FhJr#q!Uzdut`LRTHNPyt`2sA?erF4MRh7 z^4E1XBLeI@1ISktYf?|lxdM_B|8g0r=Y495h6S>@qbQGBhT2uC@X00Ef%NUx`62jo z>&HlD0Gv3mSca}plLNXsR-Q7U?~Xc#wv@m%^6H%-y(G zQWAk`gQGqKdTL8qeYBbz$Uq*f=#)yx%PZsZgTOjf+h;xT$&-9T-I|%1+7S$e{V^7y zONsoDu`_7Gq+8zBxx26K_vfUkf=CpoS1haf?eN4Je~j!nxP90)pRk?8P`f`|{@thH z$DO(*rR1J7ER2zZB+4J@L(nvw-V3&`(_nFLSZHQfpP}<{hPqs|40pfOtN9>gcf&Qs zBs}n7o>tK(VrSC<_+iTq;wUueVrk>RQ6ASJ6S;!yy`;xuB0|SM8zLmeIsA@)VFbU zAdaKA%`oda!85S@At-X5g4V@_YlykC(NW}w|hDz@2#6CR_gYIH(;JCX0ylr8zMS91(hXyIT+XH zfBe7>#oUE&J``m1Rs0}IgiQ*XAv`qVu=IhO^!rrTwI66(QP}l3q1+?wsHi zm8;>Eh#Pawq1v1+LM`w}(&Qk^YbT)@rj`T;xj-E!aE^0{DBT=JI;~()EMd}#mQF$Q z77&u*P?ILo5_F#II=eC=|5&)=J|Bp) zD1duJyYY(=o5BuyR*3vmQqgUSW%g=qCh(iCpg0fLxv=$-TDJ*0HPCg&+N{VtmzC)u z)QA?>D;HNwt4Y_1KEtS? zqM;z6FhjZ;JQXKt)Ngp3l)DH$c06_Mtg0SsVh<5HI448Y&%}&W6V03wTr4!6NEp`? z$2;hF9e2m+`j5}q(xy%v02motzLyBg2YggtkWy%ve=L+x;vzjYZWK~Clc40idWepM zw~E-mjD;dni?fnls}$vbg$?5~4S5^1>sK44a{{y1KZ}^_NJPY+Fq5npKBrbLdv-XX zf`+<9MS_!2NYo%v%HCOWNaYU+f9GL$!>XyN87p4y4r+zK#|b0|t(#KK+j3J17x<~@W%)r&PGxm^3h4#f zL9)`PoxW{HKs^lB2+Uqi{Nvejb@@=|acyxt9zYcYJ#7GN8sjrls_tm_9UX+2f3~Up z0{W@_%R#X}LYTj7zAY~sWRH%ziu5+wXx3p+;xAqWt2nL&1?~l((4WslB??r|b)@DI zv;6fmw-HGJy&^?>NO6(iP32qK>H{P~qCg4&0RuJ^odLcBFnzUB3w2HDtEhBdKf5jI zCg6R-$2r6)7lQo7d3uXDD;z7+Z@bzzP1pjpyp(Ntaw%&+!>>dyZOOFLNo#x7|XM3@z&^DAi&*iDTD;{uV{rX))RB*Rk)4I}gMqPTJ zlsV=&Y?n!74j#AhER+A}uhVRC`Uj6kLJ4aVov9$8OH$m~@Qd;nJEO>p{NKbLK$Qhf zbUqww_(bIW5Nhz3d8{!krj@H=W-y@grHN3-%r?nU1iax|b#@r}>HS0UNnGTXTE4y84uM;ZK!g$_DLY@=OA!o+}NCT4IqRKD&h9 za8OL!&b)U8kI_=RMiv}?eJXgxN7FDWx1&>ET$1N7^;^K4%d4CUyMK`P`Vq~?{O4D` z_uI)v8M!H_V5DN@^SQ& znJ_b&jHuymj7aL^*uKUTdAOTkbwZf{){DNj7B% zQT3D%uobA>zHX~|;o!`+ebJwq(o@?_pVUKm&w-1njZcJL_ruQncfTh+Xh*5(F!9x< z{t_;mwT^Beo{0^Vb+0W*Mdfj`(7;5om1*BQ(H5vwhc70$(75Q=gIHCWIXS;|;-wD1 z_|{3pEh&rntkBD*%#29*(^mEG?#>pNYyLwgU2JepQ!}^$;U`)~_$OB+xgnGdcLks4 z%@6jG_BQKhXB_^R3N3P7H>FyiW%_;i)CkXsO|L2SsZUudve?aL@)E1{4xq*SN4ZTU z`(qVfr<}BpY+mFhB+DsHktFti2Vp|$``sV)-Vdwy-CEmp%B~ygW6WWbpz@bEhn(UF*k6@@0nn%O-3YOU~ii{eA)*V?vzLGQvkuHzw zHKu&i=!kA%sZ@*gJl)3ic5<8rdld&!>I&MJ4_44p9@PvES3i{2|26p97`Vj=5k3Yn ztr#fhpm*-hN+yMkc$9ao>#VFYB)NaH1~g@WADWclmn=3(mx`;lcS`}rY-_Tm7u@+Y zj?sy1r9}l>7d;W2C<9x%n2A|gFSESV_1(}pRF2aU5IwMo z$K-G9s{i4Wkg34VTlyPbW3uk5Drb;;q^0_0n>&M-hAg0@9SKC?jaZmd8mX7{x0_iq zw2Mgo5X0|)qgHzQ>o1puoJOR%q2W2`PLnxrN-$Hd^sU^BkI)7~9_h4UMMs9)Zu|(k zr6gzIiiI_Kq0E+N5Q)EbP|Z$9Tt^B@kDZ7SXX@FZ0b|X{xb3cdU zLB)O*e!dM^OFv38Q7d;0){hXJ53JghZ$Y(jltxDa-#+4$=RA$loOOw?wcv+vZ%c~` zYnP>{b~%K|apYoe?H8m=@n&p9FN*O=7-Ye`FK(U9aHt22Q&be7f zLoS6A!?xkroe9J_fSx1yFL^1bOF!|yBr*5UoADz?x`pm)>hR;c@*Qb;eq?iC;aKuoz+<$S`z4x z1lv8m4&Qe7V@99J#)x3bx#JOlSY? z4*8nrDN{efP-l<ZsybJ zLyWxhWB9-eGU4FOeX^!W@e^`nWq=F6OmIC3P}`nyZ9voVlnYUh;C^$~S)rQ$lM!8L zVTXeS+@y1?f4YaXG}Qk_@^EjhyYB7!5sBoly>M1?zuWUco_16bVi_elB~+Ogj0ZJ$ z+=s;LjkwHV3$3ixHu|fm8*2tvibdk@=4@) z*;yB&--kff0x|Hj@8c|MS*OekUHg&thPt_cs_oRvOYtSFzq5<_+qF~iZF*bVw=Hg9 zwI3PuA=Xo>xh&W@GK5XK4E7Jf?2Ge)(94}3LiJ}@Z|6xXHAk(*g`4#Ti>gm9bMi@z zE8Hn}c5(wHmtQ8u{J3J*i0<(keA)OSw}4~^P5jtyKpRj0DgQveT9)YLB=@cDAtQ87 z-A*IVft+lSyn8OtxX4QQrr?>4j|K8Ygzlpe2n&7NIC|M3hJ=WC1-qP_=h$z%13K%v zEyQnZ%qrzfi^>fgGM|T~QpvsEe2FQ&YPIyBRjAcOT=FA!v2$2osN*-wC{_H_M>oN>XhP;xVpR&>jJ!v7Y z?n~?&(nbF;-x`0PKWWKk*2Gmhqs7tj>VCi9q?1sb$O*a9K0=pM^^^r&f_aqg_}i)6 z&8k7}1h-ve)+&nq>z0dc8^E#mo+yg871OnCc<#>`YA%P)z4?|{oRRSh zjIK>V{PcP*zfBuR$Sls=j|F0Y35X!A9wDzcyvxVGseSCGFEVQ!4&%SRv^Y>iu?lc&H@24tstWSqS3G;YE;XxqBo9>EWngnk~m9LZJ zh(dr~=_Pwo>oJ2Z-(>BG>+e9&E{VG#d%7%+8e$$!bNp^8Za%=fGtOXW^5H!PFtlq% zS!XjVi?9y<>R77cQ35v0<}w|*hnznzuQAT!8N>r7AX3U5Xk+iR?OvST<@3Z_Z?;*!LPWhES!cEuR$-@S|b=@*2 z-$VAKXb)}(RL;8EIxr>uX^i+eGW|SsG+HxQ?*)9hh{$~t8nyF= z`Vnalx}iIvPuX#xUQn-kB1FzFrO&bsx|6Y<8DsulqaiE%S2f8f&FM z+;+{ld(LJy>NM^{Mcg$#F;NL??fNxLL!C)96x5+ULnZ2`6!$Sy_OXq(pDfMGfbHy^ ziHH*V{usNaK2@A3wujPc+ zYECvR`izH($u)z7um$p;oEz-?E4$*4G{9XIX+=~pxA8yY>&h!$m6x(Ayk0fkFM;(_N zoNX;6H@n389?EbD@hbolv_ASMIm1)^AU`hYV{RL=1(Zj_8&Z#`ZlWsUYCy7%LaPBaj zEk?ucw*VZ!PlTHX@t+sYjtA{v{8w|qJKW5!Q)vp``Oj^4y6EHW(lP;5u?JTA??<}F zn#HX7$|~N1(x0B#A84P@GR7yx&J25p0PWR3BfCj#v^ot`k_(Zx8C{y%+{ zxQq}FMgMI|!H2xdUeGH417H7N0B;HS{`2g=HSUq;NaAI|f0h5Q^zfwMhwlIG{?iNv Z<|e1*R%c1pRUrU>X{zZyZ+vDS`#*_j+=&1H literal 0 HcmV?d00001 diff --git a/modules/imgproc/doc/pics/polar_remap_doc.svg b/modules/imgproc/doc/pics/polar_remap_doc.svg new file mode 100644 index 0000000000..544221569d --- /dev/null +++ b/modules/imgproc/doc/pics/polar_remap_doc.svg @@ -0,0 +1,3776 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + maxRadius + angle° + magnitude + + + + + + dx + dy + centerC(xc , yc) + A(xA , yA) + + BOUNDING CIRCLE + + + + + + a) Source Image + + Ï: 0 .. Kx * maxRadius = src.cols + centerC(0,0) + + + centerC(0,0) + + ÏA = Kx * magnitude + + Ï•A = Ky * angle° + + A(ÏA , Ï•A) + if 2 * maxRadius > min(srcSize)CV_WARP_FILL_OUTLIERS + + + M = src.cols / loge(maxRadius)Ky = src.rows / 360.0 + + Blue cross in the center + + + if 2 * maxRadius > min(srcSize)CV_WARP_FILL_OUTLIERS + Blue cross in the center + + + + c) linearPolar Result Image + + d) logPolar Result Image + + + + + + Ï•A = Ky * angle° + + A(ÏA , Ï•A) + + + Kx = src.cols / maxRadiusKy = src.rows / 360.0 + + Ï: 0 .. M * loge(maxRadius) = src.cols + + Ï•: 0 .. Ky * 360 = src.rows + + ÏA = M * loge(magnitude ) + + + + + + + + + + + + + + + + + + 270 + 240 + 210 + 180 + 150 + 120 + 90 + 60 + 30 + 300 + 330 + 0 + + + + + + + + + + + Size: W:600 H:440 pxCenter = x:240, y:220magnitude=100pxangle = 60degmaxRadius= 230px + Kx = 600px / 230px = 2.609 => rho = 260.869pxKy = 440px / 360deg = 1.222 pix/deg = phi = 73.333pxM = 600px / ln(230px) = 110.33 pn/ln(px) => rho = 508.103px + + + b) Params References + + + + + image/svg+xml + + + + + OpenCV + + + + 2016-08-08 + + + + + PkLab.net + + + + + linearPolar + logPolar + image processing + OpenCV + + + + + + + + + + + diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index ee022476f0..b8d95e3fc1 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -284,9 +284,9 @@ enum InterpolationFlags{ WARP_FILL_OUTLIERS = 8, /** flag, inverse transformation - For example, polar transforms: - - flag is __not__ set: \f$dst( \phi , \rho ) = src(x,y)\f$ - - flag is set: \f$dst(x,y) = src( \phi , \rho )\f$ + For example, @ref cv::linearPolar or @ref cv::logPolar transforms: + - flag is __not__ set: \f$dst( \rho , \phi ) = src(x,y)\f$ + - flag is set: \f$dst(x,y) = src( \rho , \phi )\f$ */ WARP_INVERSE_MAP = 16 }; @@ -2418,41 +2418,78 @@ CV_EXPORTS_W void getRectSubPix( InputArray image, Size patchSize, An example using the cv::linearPolar and cv::logPolar operations */ -/** @brief Remaps an image to log-polar space. +/** @brief Remaps an image to semilog-polar coordinates space. + +Transform the source image using the following transformation (See @ref polar_remaps_reference_image "Polar remaps reference image"): +\f[\begin{array}{l} + dst( \rho , \phi ) = src(x,y) \\ + dst.size() \leftarrow src.size() +\end{array}\f] -transforms the source image using the following transformation: -\f[dst( \phi , \rho ) = src(x,y)\f] where -\f[\rho = M \cdot \log{\sqrt{x^2 + y^2}} , \phi =atan(y/x)\f] +\f[\begin{array}{l} + I = (dx,dy) = (x - center.x,y - center.y) \\ + \rho = M \cdot log_e(\texttt{magnitude} (I)) ,\\ + \phi = Ky \cdot \texttt{angle} (I)_{0..360 deg} \\ +\end{array}\f] + +and +\f[\begin{array}{l} + M = src.cols / log_e(maxRadius) \\ + Ky = src.rows / 360 \\ +\end{array}\f] The function emulates the human "foveal" vision and can be used for fast scale and -rotation-invariant template matching, for object tracking and so forth. The function can not operate -in-place. - +rotation-invariant template matching, for object tracking and so forth. @param src Source image -@param dst Destination image +@param dst Destination image. It will have same size and type as src. @param center The transformation center; where the output precision is maximal -@param M Magnitude scale parameter. +@param M Magnitude scale parameter. It determines the radius of the bounding circle to transform too. @param flags A combination of interpolation methods, see cv::InterpolationFlags - */ + +@note +- The function can not operate in-place. +- To calculate magnitude and angle in degrees @ref cv::cartToPolar is used internally thus angles are measured from 0 to 360 with accuracy about 0.3 degrees. +*/ CV_EXPORTS_W void logPolar( InputArray src, OutputArray dst, Point2f center, double M, int flags ); -/** @brief Remaps an image to polar space. +/** @brief Remaps an image to polar coordinates space. + +@anchor polar_remaps_reference_image +![Polar remaps reference](pics/polar_remap_doc.png) + +Transform the source image using the following transformation: +\f[\begin{array}{l} + dst( \rho , \phi ) = src(x,y) \\ + dst.size() \leftarrow src.size() +\end{array}\f] -transforms the source image using the following transformation: -\f[dst( \phi , \rho ) = src(x,y)\f] where -\f[\rho = (src.width/maxRadius) \cdot \sqrt{x^2 + y^2} , \phi =atan(y/x)\f] +\f[\begin{array}{l} + I = (dx,dy) = (x - center.x,y - center.y) \\ + \rho = Kx \cdot \texttt{magnitude} (I) ,\\ + \phi = Ky \cdot \texttt{angle} (I)_{0..360 deg} +\end{array}\f] + +and +\f[\begin{array}{l} + Kx = src.cols / maxRadius \\ + Ky = src.rows / 360 +\end{array}\f] -The function can not operate in-place. @param src Source image -@param dst Destination image +@param dst Destination image. It will have same size and type as src. @param center The transformation center; -@param maxRadius Inverse magnitude scale parameter +@param maxRadius The radius of the bounding circle to transform. It determines the inverse magnitude scale parameter too. @param flags A combination of interpolation methods, see cv::InterpolationFlags - */ + +@note +- The function can not operate in-place. +- To calculate magnitude and angle in degrees @ref cv::cartToPolar is used internally thus angles are measured from 0 to 360 with accuracy about 0.3 degrees. + +*/ CV_EXPORTS_W void linearPolar( InputArray src, OutputArray dst, Point2f center, double maxRadius, int flags ); diff --git a/samples/cpp/polar_transforms.cpp b/samples/cpp/polar_transforms.cpp index 3cbc431c3c..adbc955b17 100644 --- a/samples/cpp/polar_transforms.cpp +++ b/samples/cpp/polar_transforms.cpp @@ -34,10 +34,10 @@ int main( int argc, char** argv ) return -1; } - namedWindow( "Linear-Polar", WINDOW_NORMAL ); - namedWindow( "Log-Polar", WINDOW_NORMAL ); - namedWindow( "Recovered Linear-Polar", WINDOW_NORMAL ); - namedWindow( "Recovered Log-Polar", WINDOW_NORMAL ); + namedWindow( "Linear-Polar", WINDOW_AUTOSIZE ); + namedWindow( "Log-Polar", WINDOW_AUTOSIZE); + namedWindow( "Recovered Linear-Polar", WINDOW_AUTOSIZE); + namedWindow( "Recovered Log-Polar", WINDOW_AUTOSIZE); moveWindow( "Linear-Polar", 20,20 ); moveWindow( "Log-Polar", 700,20 ); @@ -53,13 +53,14 @@ int main( int argc, char** argv ) break; Point2f center( (float)frame.cols / 2, (float)frame.rows / 2 ); - double M = (double)frame.cols / 8; + double radius = (double)frame.cols / 4; + double M = (double)frame.cols / log(radius); logPolar(frame,log_polar_img, center, M, INTER_LINEAR + WARP_FILL_OUTLIERS); - linearPolar(frame,lin_polar_img, center, M, INTER_LINEAR + WARP_FILL_OUTLIERS); + linearPolar(frame,lin_polar_img, center, radius, INTER_LINEAR + WARP_FILL_OUTLIERS); logPolar(log_polar_img, recovered_log_polar, center, M, WARP_INVERSE_MAP + INTER_LINEAR); - linearPolar(lin_polar_img, recovered_lin_polar_img, center, M, WARP_INVERSE_MAP + INTER_LINEAR + WARP_FILL_OUTLIERS); + linearPolar(lin_polar_img, recovered_lin_polar_img, center, radius, WARP_INVERSE_MAP + INTER_LINEAR + WARP_FILL_OUTLIERS); imshow("Log-Polar", log_polar_img ); imshow("Linear-Polar", lin_polar_img ); From ca318e709914632e78fd925e08c8d04b27aed724 Mon Sep 17 00:00:00 2001 From: Morrison Date: Tue, 16 Aug 2016 14:59:24 -0700 Subject: [PATCH 071/178] handle images with alpha better MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UIImages with alpha were ending up with garbage pixels in background (random memory values). Need to initialize matrix pixels before drawing UIImage with alpha on it. Note: didn’t fix Grayscale image with alpha stripping alpha in UIImage -> Mat conversion. --- modules/imgcodecs/src/ios_conversions.mm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/imgcodecs/src/ios_conversions.mm b/modules/imgcodecs/src/ios_conversions.mm index 8f2b4e84fc..17fb18e229 100644 --- a/modules/imgcodecs/src/ios_conversions.mm +++ b/modules/imgcodecs/src/ios_conversions.mm @@ -106,6 +106,8 @@ void UIImageToMat(const UIImage* image, bitmapInfo = kCGImageAlphaNone; if (!alphaExist) bitmapInfo = kCGImageAlphaNone; + else + m = cv::Scalar(0); contextRef = CGBitmapContextCreate(m.data, m.cols, m.rows, 8, m.step[0], colorSpace, bitmapInfo); @@ -116,6 +118,8 @@ void UIImageToMat(const UIImage* image, if (!alphaExist) bitmapInfo = kCGImageAlphaNoneSkipLast | kCGBitmapByteOrderDefault; + else + m = cv::Scalar(0); contextRef = CGBitmapContextCreate(m.data, m.cols, m.rows, 8, m.step[0], colorSpace, bitmapInfo); From a3b4d4608d4c1d0db5b6b01e48bbf9ac7a541ee9 Mon Sep 17 00:00:00 2001 From: Sovrasov Date: Wed, 10 Aug 2016 12:56:04 +0100 Subject: [PATCH 072/178] Static Lapack linkage --- cmake/OpenCVFindLibsPerf.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/OpenCVFindLibsPerf.cmake b/cmake/OpenCVFindLibsPerf.cmake index 0364847329..82afd390ae 100644 --- a/cmake/OpenCVFindLibsPerf.cmake +++ b/cmake/OpenCVFindLibsPerf.cmake @@ -4,6 +4,9 @@ # --- Lapack --- if(WITH_LAPACK) + if(WIN32) + set(BLA_STATIC 1) + endif() find_package(LAPACK) if(LAPACK_FOUND) find_path(LAPACKE_INCLUDE_DIR "lapacke.h") From e4cf3297c7604cffba8dca79c16111a1e58a72e9 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Wed, 17 Aug 2016 14:29:28 +0200 Subject: [PATCH 073/178] highgui: allow specifying that a button should create a new buttonbar --- modules/highgui/include/opencv2/highgui.hpp | 11 +++++++---- modules/highgui/src/window_QT.cpp | 7 ++++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index 7f963a5cdf..b5c22a19ee 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -239,9 +239,10 @@ enum QtFontStyles { //! Qt "button" type enum QtButtonTypes { - QT_PUSH_BUTTON = 0, //!< Push button. - QT_CHECKBOX = 1, //!< Checkbox button. - QT_RADIOBOX = 2 //!< Radiobox button. + QT_PUSH_BUTTON = 0, //!< Push button. + QT_CHECKBOX = 1, //!< Checkbox button. + QT_RADIOBOX = 2, //!< Radiobox button. + QT_NEW_BUTTONBAR = 1024 //!< Button should create a new buttonbar }; /** @brief Callback function for mouse events. see cv::setMouseCallback @@ -719,7 +720,8 @@ CV_EXPORTS void stopLoop(); The function createButton attaches a button to the control panel. Each button is added to a buttonbar to the right of the last button. A new buttonbar is created if nothing was attached to the -control panel before, or if the last element attached to the control panel was a trackbar. +control panel before, or if the last element attached to the control panel was a trackbar or if the +QT_NEW_BUTTONBAR flag is added to the type. See below various examples of the cv::createButton function call: : @code @@ -728,6 +730,7 @@ See below various examples of the cv::createButton function call: : createButton("button3",callbackButton,&value); createButton("button5",callbackButton1,NULL,QT_RADIOBOX); createButton("button6",callbackButton2,NULL,QT_PUSH_BUTTON,1); + createButton("button6",callbackButton2,NULL,QT_PUSH_BUTTON|QT_NEW_BUTTONBAR);// create a push button in a new row @endcode @param bar_name Name of the button. diff --git a/modules/highgui/src/window_QT.cpp b/modules/highgui/src/window_QT.cpp index 7388a44b8d..92c4ce1d6f 100644 --- a/modules/highgui/src/window_QT.cpp +++ b/modules/highgui/src/window_QT.cpp @@ -1139,13 +1139,18 @@ void GuiReceiver::addButton(QString button_name, int button_type, int initial_bu { CvBar* lastbar = (CvBar*) global_control_panel->myLayout->itemAt(global_control_panel->myLayout->count() - 1); - if (lastbar->type == type_CvTrackbar) //if last bar is a trackbar, create a new buttonbar, else, attach to the current bar + // if last bar is a trackbar or the user requests a new buttonbar, create a new buttonbar + // else, attach to the current bar + if (lastbar->type == type_CvTrackbar || cv::QT_NEW_BUTTONBAR & button_type) b = CvWindow::createButtonBar(button_name); //the bar has the name of the first button attached to it else b = (CvButtonbar*) lastbar; } + // unset buttonbar flag + button_type = button_type & ~cv::QT_NEW_BUTTONBAR; + b->addButton(button_name, (CvButtonCallback) on_change, userdata, button_type, initial_button_state); } From a462d76a955a6e4a82f2e0f6adad8ac91afe2656 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Mon, 15 Aug 2016 17:12:45 +0300 Subject: [PATCH 074/178] Implementations instrumentation framework for OpenCV performance system; --- CMakeLists.txt | 1 + cmake/templates/cvconfig.h.in | 3 + modules/core/include/opencv2/core/private.hpp | 135 ++++++++- modules/core/include/opencv2/core/utility.hpp | 131 +++++++++ modules/core/src/parallel.cpp | 17 ++ modules/core/src/stat.cpp | 41 +-- modules/core/src/system.cpp | 204 ++++++++++++++ modules/ts/include/opencv2/ts/ocl_perf.hpp | 6 +- modules/ts/include/opencv2/ts/ts_perf.hpp | 21 +- modules/ts/src/ts_perf.cpp | 263 +++++++++++++++++- 10 files changed, 790 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 05d88544c8..c9568546f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -286,6 +286,7 @@ OCV_OPTION(ENABLE_NOISY_WARNINGS "Show all warnings even if they are too no OCV_OPTION(OPENCV_WARNINGS_ARE_ERRORS "Treat warnings as errors" OFF ) OCV_OPTION(ANDROID_EXAMPLES_WITH_LIBS "Build binaries of Android examples with native libraries" OFF IF ANDROID ) OCV_OPTION(ENABLE_IMPL_COLLECTION "Collect implementation data on function call" OFF ) +OCV_OPTION(ENABLE_INSTRUMENTATION "Instrument functions to collect calls trace and performance" OFF ) OCV_OPTION(GENERATE_ABI_DESCRIPTOR "Generate XML file for abi_compliance_checker tool" OFF IF UNIX) OCV_OPTION(DOWNLOAD_EXTERNAL_TEST_DATA "Download external test data (Python executable and OPENCV_TEST_DATA_PATH environment variable may be required)" OFF ) diff --git a/cmake/templates/cvconfig.h.in b/cmake/templates/cvconfig.h.in index 4012f69426..56d415b400 100644 --- a/cmake/templates/cvconfig.h.in +++ b/cmake/templates/cvconfig.h.in @@ -212,3 +212,6 @@ /* FP16 */ #cmakedefine HAVE_FP16 + +/* Library was compiled with functions instrumentation */ +#cmakedefine ENABLE_INSTRUMENTATION diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index c884815d2e..6fcd1713c2 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -344,7 +344,7 @@ static struct __IppInitializer__ __ipp_initializer__; #ifdef CV_IPP_RUN_VERBOSE #define CV_IPP_RUN_(condition, func, ...) \ { \ - if (cv::ipp::useIPP() && (condition) && func) \ + if (cv::ipp::useIPP() && (condition) && (func)) \ { \ printf("%s: IPP implementation is running\n", CV_Func); \ fflush(stdout); \ @@ -376,7 +376,7 @@ static struct __IppInitializer__ __ipp_initializer__; } #else #define CV_IPP_RUN_(condition, func, ...) \ - if (cv::ipp::useIPP() && (condition) && func) \ + if (cv::ipp::useIPP() && (condition) && (func)) \ { \ CV_IMPL_ADD(CV_IMPL_IPP); \ return __VA_ARGS__; \ @@ -393,7 +393,7 @@ static struct __IppInitializer__ __ipp_initializer__; #define CV_IPP_RUN_FAST(func, ...) #endif -#define CV_IPP_RUN(condition, func, ...) CV_IPP_RUN_(condition, func, __VA_ARGS__) +#define CV_IPP_RUN(condition, func, ...) CV_IPP_RUN_((condition), (func), __VA_ARGS__) #ifndef IPPI_CALL @@ -449,6 +449,135 @@ CV_EXPORTS void setUseTegra(bool flag); } #endif +#ifdef ENABLE_INSTRUMENTATION +namespace cv +{ +namespace instr +{ +struct InstrTLSStruct +{ + InstrTLSStruct() + { + pCurrentNode = NULL; + } + InstrNode* pCurrentNode; +}; + +class InstrStruct +{ +public: + InstrStruct() + { + useInstr = false; + enableMapping = true; + + rootNode.m_payload = NodeData("ROOT", NULL, 0, TYPE_GENERAL, IMPL_PLAIN); + tlsStruct.get()->pCurrentNode = &rootNode; + } + + Mutex mutexCreate; + Mutex mutexCount; + + bool useInstr; + bool enableMapping; + InstrNode rootNode; + TLSData tlsStruct; +}; + +class CV_EXPORTS IntrumentationRegion +{ +public: + IntrumentationRegion(const char* funName, const char* fileName, int lineNum, int instrType = TYPE_GENERAL, int implType = IMPL_PLAIN); + ~IntrumentationRegion(); + +private: + bool m_disabled; // region status + uint64 m_regionTicks; +}; + +InstrStruct& getInstrumentStruct(); +InstrTLSStruct& getInstrumentTLSStruct(); +CV_EXPORTS InstrNode* getCurrentNode(); +} +} + +///// General instrumentation +// Instrument region +#define CV_INSTRUMENT_REGION_META(TYPE, IMPL, ...) ::cv::instr::IntrumentationRegion __instr_region__(__FUNCTION__, __FILE__, __LINE__, TYPE, IMPL); +// Instrument functions with non-void return type +#define CV_INSTRUMENT_FUN_RT_META(TYPE, IMPL, ERROR_COND, FUN, ...) ([&]()\ +{\ + if(::cv::instr::useInstrumentation()){\ + ::cv::instr::IntrumentationRegion __instr__(#FUN, __FILE__, __LINE__, TYPE, IMPL);\ + try{\ + auto status = ((FUN)(__VA_ARGS__));\ + if(ERROR_COND){\ + ::cv::instr::getCurrentNode()->m_payload.m_funError = true;\ + CV_INSTRUMENT_MARK_META(IMPL, ##FUN - BadExit);\ + }\ + return status;\ + }catch(...){\ + ::cv::instr::getCurrentNode()->m_payload.m_funError = true;\ + CV_INSTRUMENT_MARK_META(IMPL, ##FUN - BadExit);\ + throw;\ + }\ + }else{\ + return ((FUN)(__VA_ARGS__));\ + }\ +}()) +// Instrument functions with void return type +#define CV_INSTRUMENT_FUN_RV_META(TYPE, IMPL, FUN, ...) ([&]()\ +{\ + if(::cv::instr::useInstrumentation()){\ + ::cv::instr::IntrumentationRegion __instr__(#FUN, __FILE__, __LINE__, TYPE, IMPL);\ + try{\ + (FUN)(__VA_ARGS__);\ + }catch(...){\ + ::cv::instr::getCurrentNode()->m_payload.m_funError = true;\ + CV_INSTRUMENT_MARK_META(IMPL, ##FUN - BadExit);\ + throw;\ + }\ + }else{\ + (FUN)(__VA_ARGS__);\ + }\ +}()) +// Instrumentation information marker +#define CV_INSTRUMENT_MARK_META(IMPL, NAME, ...) {::cv::instr::IntrumentationRegion __instr_mark__(#NAME, __FILE__, __LINE__, ::cv::instr::TYPE_MARKER, IMPL);} + +///// General instrumentation +// General OpenCV region instrumentation macro +#define CV_INSTRUMENT_REGION() CV_INSTRUMENT_REGION_META(cv::instr::TYPE_GENERAL, cv::instr::IMPL_PLAIN) +// Parallel OpenCV region instrumentation macro +#define CV_INSTRUMENT_REGION_MT() CV_INSTRUMENT_REGION_MT_META(cv::instr::TYPE_GENERAL, cv::instr::IMPL_PLAIN) + +///// IPP instrumentation +// Wrapper region instrumentation macro +#define CV_INSTRUMENT_REGION_IPP() CV_INSTRUMENT_REGION_META(::cv::instr::TYPE_WRAPPER, ::cv::instr::IMPL_IPP) +// Function instrumentation macro +#define CV_INSTRUMENT_FUN_IPP(FUN, ...) CV_INSTRUMENT_FUN_RT_META(::cv::instr::TYPE_FUN, ::cv::instr::IMPL_IPP, status < 0, FUN, __VA_ARGS__) +// Diagnostic markers +#define CV_INSTRUMENT_MARK_IPP(NAME) CV_INSTRUMENT_MARK_META(::cv::instr::IMPL_IPP, NAME) + +///// OpenCL instrumentation +// Wrapper region instrumentation macro +#define CV_INSTRUMENT_REGION_OPENCL() CV_INSTRUMENT_REGION_META(::cv::instr::TYPE_WRAPPER, ::cv::instr::IMPL_OPENCL) +// Function instrumentation macro +#define CV_INSTRUMENT_FUN_OPENCL_KERNEL(FUN, ...) CV_INSTRUMENT_FUN_RT_META(::cv::instr::TYPE_FUN, ::cv::instr::IMPL_OPENCL, status == 0, FUN, __VA_ARGS__) +// Diagnostic markers +#define CV_INSTRUMENT_MARK_OPENCL(NAME) CV_INSTRUMENT_MARK_META(::cv::instr::IMPL_OPENCL, NAME) +#else +#define CV_INSTRUMENT_REGION() +#define CV_INSTRUMENT_REGION_MT() + +#define CV_INSTRUMENT_REGION_IPP() +#define CV_INSTRUMENT_FUN_IPP(FUN, ...) ((FUN)(__VA_ARGS__)) +#define CV_INSTRUMENT_MARK_IPP(NAME) + +#define CV_INSTRUMENT_REGION_OPENCL() +#define CV_INSTRUMENT_FUN_OPENCL_KERNEL(FUN, ...) ((FUN)(__VA_ARGS__)) +#define CV_INSTRUMENT_MARK_OPENCL(NAME) +#endif + //! @endcond #endif // __OPENCV_CORE_PRIVATE_HPP__ diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index 768c4d5223..911f779f38 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -1002,6 +1002,137 @@ template<> inline std::string CommandLineParser::get(const String& //! @endcond + +// Basic Node class for tree building +template +class CV_EXPORTS Node +{ +public: + Node() + { + m_pParent = 0; + } + Node(OBJECT& payload) : m_payload(payload) + { + m_pParent = 0; + } + ~Node() + { + removeChilds(); + if (m_pParent) + { + int idx = m_pParent->findChild(this); + if (idx >= 0) + m_pParent->m_childs.erase(m_pParent->m_childs.begin() + idx); + } + } + + Node* findChild(OBJECT& payload) const + { + for(int i = 0; i < this->m_childs.size(); i++) + { + if(this->m_childs[i]->m_payload == payload) + return this->m_childs[i]; + } + return NULL; + } + + int findChild(Node *pNode) const + { + for (int i = 0; i < this->m_childs.size(); i++) + { + if(this->m_childs[i] == pNode) + return i; + } + return -1; + } + + void addChild(Node *pNode) + { + if(!pNode) + return; + + CV_Assert(pNode->m_pParent == 0); + pNode->m_pParent = this; + this->m_childs.push_back(pNode); + } + + void removeChilds() + { + for(int i = 0; i < m_childs.size(); i++) + { + m_childs[i]->m_pParent = 0; // avoid excessive parent vector trimming + delete m_childs[i]; + } + m_childs.clear(); + } + +public: + OBJECT m_payload; + Node* m_pParent; + std::vector*> m_childs; +}; + +// Instrumentation external interface +namespace instr +{ +enum +{ + TYPE_GENERAL = 0, // OpenCV API function, e.g. exported function + TYPE_MARKER, // Information marker + TYPE_WRAPPER, // Wrapper function for implementation + TYPE_FUN, // Simple function call +}; + +enum +{ + IMPL_PLAIN = 0, + IMPL_IPP, + IMPL_OPENCL, +}; + +enum +{ + FLAGS_MAPPING = 0x01, +}; + +enum +{ + COMMAND_RESET = 0x01, +}; + +class CV_EXPORTS NodeData +{ +public: + NodeData(const char* funName = 0, const char* fileName = NULL, int lineNum = 0, int instrType = TYPE_GENERAL, int implType = IMPL_PLAIN); + NodeData(NodeData &ref); + ~NodeData(); + NodeData& operator=(const NodeData&); + + cv::String m_funName; + int m_instrType; + int m_implType; + cv::String m_fileName; + int m_lineNum; + + bool m_funError; + volatile int m_counter; + bool m_stopPoint; + uint64 m_ticksMean; + +}; +bool operator==(const NodeData& lhs, const NodeData& rhs); + +typedef Node InstrNode; + +CV_EXPORTS bool useInstrumentation(); +CV_EXPORTS void setUseInstrumentation(bool flag); +CV_EXPORTS InstrNode* getTrace(); +CV_EXPORTS void resetTrace(); +CV_EXPORTS void setFlags(int modeFlags); +CV_EXPORTS int getFlags(); +}; + } //namespace cv #ifndef DISABLE_OPENCV_24_COMPATIBILITY diff --git a/modules/core/src/parallel.cpp b/modules/core/src/parallel.cpp index b805ab46b0..d4968652a3 100644 --- a/modules/core/src/parallel.cpp +++ b/modules/core/src/parallel.cpp @@ -149,13 +149,25 @@ namespace public: ParallelLoopBodyWrapper(const cv::ParallelLoopBody& _body, const cv::Range& _r, double _nstripes) { + body = &_body; wholeRange = _r; double len = wholeRange.end - wholeRange.start; nstripes = cvRound(_nstripes <= 0 ? len : MIN(MAX(_nstripes, 1.), len)); + +#ifdef ENABLE_INSTRUMENTATION + pThreadRoot = cv::instr::getInstrumentTLSStruct().pCurrentNode; +#endif } void operator()(const cv::Range& sr) const { +#ifdef ENABLE_INSTRUMENTATION + { + cv::instr::InstrTLSStruct *pInstrTLS = &cv::instr::getInstrumentTLSStruct(); + pInstrTLS->pCurrentNode = pThreadRoot; // Initialize TLS node for thread + } +#endif + cv::Range r; r.start = (int)(wholeRange.start + ((uint64)sr.start*(wholeRange.end - wholeRange.start) + nstripes/2)/nstripes); @@ -169,6 +181,9 @@ namespace const cv::ParallelLoopBody* body; cv::Range wholeRange; int nstripes; +#ifdef ENABLE_INSTRUMENTATION + cv::instr::InstrNode *pThreadRoot; +#endif }; #if defined HAVE_TBB @@ -252,6 +267,8 @@ static SchedPtr pplScheduler; void cv::parallel_for_(const cv::Range& range, const cv::ParallelLoopBody& body, double nstripes) { + CV_INSTRUMENT_REGION() + #ifdef CV_PARALLEL_FRAMEWORK if(numThreads != 0) diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index be0f89e1a2..727d89554d 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -1522,6 +1522,8 @@ namespace cv { static bool ocl_meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray _mask ) { + CV_INSTRUMENT_REGION_OPENCL() + bool haveMask = _mask.kind() != _InputArray::NONE; int nz = haveMask ? -1 : (int)_src.total(); Scalar mean, stddev; @@ -1585,7 +1587,8 @@ static bool ocl_meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv k.args(srcarg, src.cols, (int)src.total(), groups, dbarg); size_t globalsize = groups * wgs; - if (!k.run(1, &globalsize, &wgs, false)) + + if(!CV_INSTRUMENT_FUN_OPENCL_KERNEL(k.run, 1, &globalsize, &wgs, false)) return false; typedef Scalar (* part_sum)(Mat m); @@ -1641,6 +1644,8 @@ namespace cv { static bool ipp_meanStdDev(Mat& src, OutputArray _mean, OutputArray _sdv, Mat& mask) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 700 int cn = src.channels(); size_t total_size = src.total(); @@ -1679,29 +1684,29 @@ static bool ipp_meanStdDev(Mat& src, OutputArray _mean, OutputArray _sdv, Mat& m if( !mask.empty() ) { typedef IppStatus (CV_STDCALL* ippiMaskMeanStdDevFuncC1)(const void *, int, const void *, int, IppiSize, Ipp64f *, Ipp64f *); - ippiMaskMeanStdDevFuncC1 ippFuncC1 = + ippiMaskMeanStdDevFuncC1 ippiMean_StdDev_C1MR = type == CV_8UC1 ? (ippiMaskMeanStdDevFuncC1)ippiMean_StdDev_8u_C1MR : type == CV_16UC1 ? (ippiMaskMeanStdDevFuncC1)ippiMean_StdDev_16u_C1MR : type == CV_32FC1 ? (ippiMaskMeanStdDevFuncC1)ippiMean_StdDev_32f_C1MR : 0; - if( ippFuncC1 ) + if( ippiMean_StdDev_C1MR ) { - if( ippFuncC1(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, pmean, pstddev) >= 0 ) + if( CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C1MR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, pmean, pstddev) >= 0 ) { return true; } } typedef IppStatus (CV_STDCALL* ippiMaskMeanStdDevFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *, Ipp64f *); - ippiMaskMeanStdDevFuncC3 ippFuncC3 = + ippiMaskMeanStdDevFuncC3 ippiMean_StdDev_C3CMR = type == CV_8UC3 ? (ippiMaskMeanStdDevFuncC3)ippiMean_StdDev_8u_C3CMR : type == CV_16UC3 ? (ippiMaskMeanStdDevFuncC3)ippiMean_StdDev_16u_C3CMR : type == CV_32FC3 ? (ippiMaskMeanStdDevFuncC3)ippiMean_StdDev_32f_C3CMR : 0; - if( ippFuncC3 ) + if( ippiMean_StdDev_C3CMR ) { - if( ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 1, &pmean[0], &pstddev[0]) >= 0 && - ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 2, &pmean[1], &pstddev[1]) >= 0 && - ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 3, &pmean[2], &pstddev[2]) >= 0 ) + if( CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C3CMR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 1, &pmean[0], &pstddev[0]) >= 0 && + CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C3CMR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 2, &pmean[1], &pstddev[1]) >= 0 && + CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C3CMR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 3, &pmean[2], &pstddev[2]) >= 0 ) { return true; } @@ -1710,31 +1715,31 @@ static bool ipp_meanStdDev(Mat& src, OutputArray _mean, OutputArray _sdv, Mat& m else { typedef IppStatus (CV_STDCALL* ippiMeanStdDevFuncC1)(const void *, int, IppiSize, Ipp64f *, Ipp64f *); - ippiMeanStdDevFuncC1 ippFuncC1 = + ippiMeanStdDevFuncC1 ippiMean_StdDev_C1R = type == CV_8UC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_8u_C1R : type == CV_16UC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_16u_C1R : #if (IPP_VERSION_X100 >= 810) type == CV_32FC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_32f_C1R ://Aug 2013: bug in IPP 7.1, 8.0 #endif 0; - if( ippFuncC1 ) + if( ippiMean_StdDev_C1R ) { - if( ippFuncC1(src.ptr(), (int)src.step[0], sz, pmean, pstddev) >= 0 ) + if( CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C1R, src.ptr(), (int)src.step[0], sz, pmean, pstddev) >= 0 ) { return true; } } typedef IppStatus (CV_STDCALL* ippiMeanStdDevFuncC3)(const void *, int, IppiSize, int, Ipp64f *, Ipp64f *); - ippiMeanStdDevFuncC3 ippFuncC3 = + ippiMeanStdDevFuncC3 ippiMean_StdDev_C3CR = type == CV_8UC3 ? (ippiMeanStdDevFuncC3)ippiMean_StdDev_8u_C3CR : type == CV_16UC3 ? (ippiMeanStdDevFuncC3)ippiMean_StdDev_16u_C3CR : type == CV_32FC3 ? (ippiMeanStdDevFuncC3)ippiMean_StdDev_32f_C3CR : 0; - if( ippFuncC3 ) + if( ippiMean_StdDev_C3CR ) { - if( ippFuncC3(src.ptr(), (int)src.step[0], sz, 1, &pmean[0], &pstddev[0]) >= 0 && - ippFuncC3(src.ptr(), (int)src.step[0], sz, 2, &pmean[1], &pstddev[1]) >= 0 && - ippFuncC3(src.ptr(), (int)src.step[0], sz, 3, &pmean[2], &pstddev[2]) >= 0 ) + if( CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C3CR, src.ptr(), (int)src.step[0], sz, 1, &pmean[0], &pstddev[0]) >= 0 && + CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C3CR, src.ptr(), (int)src.step[0], sz, 2, &pmean[1], &pstddev[1]) >= 0 && + CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C3CR, src.ptr(), (int)src.step[0], sz, 3, &pmean[2], &pstddev[2]) >= 0 ) { return true; } @@ -1751,6 +1756,8 @@ static bool ipp_meanStdDev(Mat& src, OutputArray _mean, OutputArray _sdv, Mat& m void cv::meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray _mask ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(OCL_PERFORMANCE_CHECK(_src.isUMat()) && _src.dims() <= 2, ocl_meanStdDev(_src, _mean, _sdv, _mask)) diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index edf9e0ebd7..cc60cf792c 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -1300,6 +1300,210 @@ void setUseCollection(bool flag) } #endif +namespace instr +{ +bool useInstrumentation() +{ +#ifdef ENABLE_INSTRUMENTATION + return getInstrumentStruct().useInstr; +#else + return false; +#endif +} + +void setUseInstrumentation(bool flag) +{ +#ifdef ENABLE_INSTRUMENTATION + getInstrumentStruct().useInstr = flag; +#else + CV_UNUSED(flag); +#endif +} + +InstrNode* getTrace() +{ +#ifdef ENABLE_INSTRUMENTATION + return &getInstrumentStruct().rootNode; +#else + return NULL; +#endif +} + +void resetTrace() +{ +#ifdef ENABLE_INSTRUMENTATION + getInstrumentStruct().rootNode.removeChilds(); + getInstrumentTLSStruct().pCurrentNode = &getInstrumentStruct().rootNode; +#endif +} + +void setFlags(int modeFlags) +{ +#ifdef ENABLE_INSTRUMENTATION + getInstrumentStruct().enableMapping = (modeFlags & FLAGS_MAPPING); +#else + CV_UNUSED(modeFlags); +#endif +} +int getFlags() +{ +#ifdef ENABLE_INSTRUMENTATION + int flags = 0; + if(getInstrumentStruct().enableMapping) + flags |= FLAGS_MAPPING; + return flags; +#else + return 0; +#endif +} + +NodeData::NodeData(const char* funName, const char* fileName, int lineNum, int instrType, int implType) +{ + m_instrType = TYPE_GENERAL; + m_implType = IMPL_PLAIN; + + m_funError = false; + m_counter = 0; + m_stopPoint = false; + m_ticksMean = 0; + + m_funName = funName; + m_instrType = instrType; + m_implType = implType; + m_fileName = fileName; + m_lineNum = lineNum; +} +NodeData::NodeData(NodeData &ref) +{ + *this = ref; +} +NodeData& NodeData::operator=(const NodeData &right) +{ + this->m_funName = right.m_funName; + this->m_instrType = right.m_instrType; + this->m_implType = right.m_implType; + this->m_funError = right.m_funError; + this->m_counter = right.m_counter; + this->m_stopPoint = right.m_stopPoint; + this->m_ticksMean = right.m_ticksMean; + this->m_fileName = right.m_fileName; + this->m_lineNum = right.m_lineNum; + + return *this; +} +NodeData::~NodeData() +{ +} +bool operator==(const NodeData& left, const NodeData& right) +{ + if(left.m_lineNum == right.m_lineNum && left.m_funName == right.m_funName && left.m_fileName == right.m_fileName) + return true; + return false; +} + +#ifdef ENABLE_INSTRUMENTATION +InstrStruct& getInstrumentStruct() +{ + static InstrStruct instr; + return instr; +} + +InstrTLSStruct& getInstrumentTLSStruct() +{ + return *getInstrumentStruct().tlsStruct.get(); +} + +InstrNode* getCurrentNode() +{ + return getInstrumentTLSStruct().pCurrentNode; +} + +IntrumentationRegion::IntrumentationRegion(const char* funName, const char* fileName, int lineNum, int instrType, int implType) +{ + m_disabled = false; + m_regionTicks = 0; + + InstrStruct *pStruct = &getInstrumentStruct(); + if(pStruct->useInstr) + { + InstrTLSStruct *pTLS = &getInstrumentTLSStruct(); + + // Disable in case of failure + if(!pTLS->pCurrentNode) + { + m_disabled = true; + return; + } + + m_disabled = pTLS->pCurrentNode->m_payload.m_stopPoint; + if(m_disabled) + return; + + NodeData payload(funName, fileName, lineNum, instrType, implType); + Node* pChild = NULL; + + if(pStruct->enableMapping) + { + // Critical section + cv::AutoLock guard(pStruct->mutexCreate); // Guard from concurrent child creation + pChild = pTLS->pCurrentNode->findChild(payload); + if(!pChild) + { + pChild = new Node(payload); + pTLS->pCurrentNode->addChild(pChild); + } + } + else + { + pChild = pTLS->pCurrentNode->findChild(payload); + if(!pChild) + { + pTLS->pCurrentNode->m_payload.m_stopPoint = true; + return; + } + } + pTLS->pCurrentNode = pChild; + + m_regionTicks = getTickCount(); + } +} + +IntrumentationRegion::~IntrumentationRegion() +{ + InstrStruct *pStruct = &getInstrumentStruct(); + if(pStruct->useInstr) + { + if(!m_disabled) + { + InstrTLSStruct *pTLS = &getInstrumentTLSStruct(); + if(pTLS->pCurrentNode->m_payload.m_stopPoint) + { + pTLS->pCurrentNode->m_payload.m_stopPoint = false; + } + else + { + if(pTLS->pCurrentNode->m_payload.m_implType == cv::instr::IMPL_OPENCL && + pTLS->pCurrentNode->m_payload.m_instrType == cv::instr::TYPE_FUN) + cv::ocl::finish(); + + uint64 ticks = (getTickCount() - m_regionTicks); + { + cv::AutoLock guard(pStruct->mutexCount); // Concurrent ticks accumulation + pTLS->pCurrentNode->m_payload.m_counter++; + if(pTLS->pCurrentNode->m_payload.m_counter <= 1) + pTLS->pCurrentNode->m_payload.m_ticksMean = ticks; + else + pTLS->pCurrentNode->m_payload.m_ticksMean = (pTLS->pCurrentNode->m_payload.m_ticksMean*(pTLS->pCurrentNode->m_payload.m_counter-1) + ticks)/pTLS->pCurrentNode->m_payload.m_counter; + } + + pTLS->pCurrentNode = pTLS->pCurrentNode->m_pParent; + } + } + } +} +#endif +} + namespace ipp { diff --git a/modules/ts/include/opencv2/ts/ocl_perf.hpp b/modules/ts/include/opencv2/ts/ocl_perf.hpp index c2e860067b..2f2f55ccaf 100644 --- a/modules/ts/include/opencv2/ts/ocl_perf.hpp +++ b/modules/ts/include/opencv2/ts/ocl_perf.hpp @@ -97,13 +97,13 @@ using std::tr1::tuple; // TODO Replace finish call to dstUMat.wait() #define OCL_TEST_CYCLE() \ - for (cvtest::ocl::perf::safeFinish(); startTimer(), next(); cvtest::ocl::perf::safeFinish(), stopTimer()) + for (cvtest::ocl::perf::safeFinish(); next() && startTimer(); cvtest::ocl::perf::safeFinish(), stopTimer()) #define OCL_TEST_CYCLE_N(n) \ - for(declare.iterations(n), cvtest::ocl::perf::safeFinish(); startTimer(), next(); cvtest::ocl::perf::safeFinish(), stopTimer()) + for (declare.iterations(n), cvtest::ocl::perf::safeFinish(); next() && startTimer(); cvtest::ocl::perf::safeFinish(), stopTimer()) #define OCL_TEST_CYCLE_MULTIRUN(runsNum) \ - for (declare.runs(runsNum), cvtest::ocl::perf::safeFinish(); startTimer(), next(); cvtest::ocl::perf::safeFinish(), stopTimer()) \ + for (declare.runs(runsNum), cvtest::ocl::perf::safeFinish(); next() && startTimer(); cvtest::ocl::perf::safeFinish(), stopTimer()) \ for (int r = 0; r < runsNum; cvtest::ocl::perf::safeFinish(), ++r) diff --git a/modules/ts/include/opencv2/ts/ts_perf.hpp b/modules/ts/include/opencv2/ts/ts_perf.hpp index 09998998b5..d1a726a486 100644 --- a/modules/ts/include/opencv2/ts/ts_perf.hpp +++ b/modules/ts/include/opencv2/ts/ts_perf.hpp @@ -354,6 +354,15 @@ typedef struct ImplData } ImplData; #endif +#ifdef ENABLE_INSTRUMENTATION +class InstumentData +{ +public: + static ::cv::String treeToString(); + static void printTree(); +}; +#endif + class CV_EXPORTS TestBase: public ::testing::Test { public: @@ -382,7 +391,7 @@ protected: virtual void SetUp(); virtual void TearDown(); - void startTimer(); + bool startTimer(); // bool is dummy for conditional loop void stopTimer(); bool next(); @@ -406,6 +415,10 @@ protected: #ifdef CV_COLLECT_IMPL_DATA ImplData implConf; #endif +#ifdef ENABLE_INSTRUMENTATION + InstumentData instrConf; +#endif + private: typedef std::vector > SizeVector; typedef std::vector TimeVector; @@ -645,9 +658,9 @@ int main(int argc, char **argv)\ CV_PERF_TEST_MAIN_INTERNALS(modulename, plain_only, __VA_ARGS__)\ } -#define TEST_CYCLE_N(n) for(declare.iterations(n); startTimer(), next(); stopTimer()) -#define TEST_CYCLE() for(; startTimer(), next(); stopTimer()) -#define TEST_CYCLE_MULTIRUN(runsNum) for(declare.runs(runsNum); startTimer(), next(); stopTimer()) for(int r = 0; r < runsNum; ++r) +#define TEST_CYCLE_N(n) for(declare.iterations(n); next() && startTimer(); stopTimer()) +#define TEST_CYCLE() for(; next() && startTimer(); stopTimer()) +#define TEST_CYCLE_MULTIRUN(runsNum) for(declare.runs(runsNum); next() && startTimer(); stopTimer()) for(int r = 0; r < runsNum; ++r) namespace perf { diff --git a/modules/ts/src/ts_perf.cpp b/modules/ts/src/ts_perf.cpp index 1a959f176d..50e23548fe 100644 --- a/modules/ts/src/ts_perf.cpp +++ b/modules/ts/src/ts_perf.cpp @@ -45,6 +45,9 @@ static bool param_verify_sanity; #ifdef CV_COLLECT_IMPL_DATA static bool param_collect_impl; #endif +#ifdef ENABLE_INSTRUMENTATION +static bool param_instrument; +#endif extern bool test_ipp_check; #ifdef HAVE_CUDA @@ -727,7 +730,219 @@ public: } }; +#ifdef ENABLE_INSTRUMENTATION +static void printShift(cv::instr::InstrNode *pNode, cv::instr::InstrNode* pRoot) +{ + // Print empty line for a big tree nodes + if(pNode->m_pParent) + { + int parendIdx = pNode->m_pParent->findChild(pNode); + if(parendIdx > 0 && pNode->m_pParent->m_childs[parendIdx-1]->m_childs.size()) + { + printShift(pNode->m_pParent->m_childs[parendIdx-1]->m_childs[0], pRoot); + printf("\n"); + } + } + // Check if parents have more childs + std::vector cache; + cv::instr::InstrNode *pTmpNode = pNode; + while(pTmpNode->m_pParent && pTmpNode->m_pParent != pRoot) + { + cache.push_back(pTmpNode->m_pParent); + pTmpNode = pTmpNode->m_pParent; + } + for(int i = (int)cache.size()-1; i >= 0; i--) + { + if(cache[i]->m_pParent) + { + if(cache[i]->m_pParent->findChild(cache[i]) == cache[i]->m_pParent->m_childs.size()-1) + printf(" "); + else + printf("| "); + } + } +} + +static double calcLocalWeight(cv::instr::InstrNode *pNode) +{ + if(pNode->m_pParent && pNode->m_pParent->m_pParent) + return ((double)pNode->m_payload.m_ticksMean*100/pNode->m_pParent->m_payload.m_ticksMean); + else + return 100; +} + +static double calcGlobalWeight(cv::instr::InstrNode *pNode) +{ + cv::instr::InstrNode* globNode = pNode; + + while(globNode->m_pParent && globNode->m_pParent->m_pParent) + globNode = globNode->m_pParent; + + return ((double)pNode->m_payload.m_ticksMean*100/(double)globNode->m_payload.m_ticksMean); +} + +static void printNodeRec(cv::instr::InstrNode *pNode, cv::instr::InstrNode *pRoot) +{ + printf("%s", (pNode->m_payload.m_funName.substr(0, 40) + ((pNode->m_payload.m_funName.size()>40)?"...":"")).c_str()); + + // Write instrumentation flags + if(pNode->m_payload.m_instrType != cv::instr::TYPE_GENERAL || pNode->m_payload.m_implType != cv::instr::IMPL_PLAIN) + { + printf("<"); + if(pNode->m_payload.m_instrType == cv::instr::TYPE_WRAPPER) + printf("W"); + else if(pNode->m_payload.m_instrType == cv::instr::TYPE_FUN) + printf("F"); + else if(pNode->m_payload.m_instrType == cv::instr::TYPE_MARKER) + printf("MARK"); + + if(pNode->m_payload.m_instrType != cv::instr::TYPE_GENERAL && pNode->m_payload.m_implType != cv::instr::IMPL_PLAIN) + printf("_"); + + if(pNode->m_payload.m_implType == cv::instr::IMPL_IPP) + printf("IPP"); + else if(pNode->m_payload.m_implType == cv::instr::IMPL_OPENCL) + printf("OCL"); + + printf(">"); + } + + if(pNode->m_pParent) + { + printf(" - C:%d", pNode->m_payload.m_counter); + printf(" T:%.4fms", (double)pNode->m_payload.m_ticksMean/cv::getTickFrequency()*1000); + if(pNode->m_pParent->m_pParent) + printf(" L:%.0f%% G:%.0f%%", calcLocalWeight(pNode), calcGlobalWeight(pNode)); + } + printf("\n"); + + // Group childes + std::vector groups; + { + bool bFound = false; + for(size_t i = 0; i < pNode->m_childs.size(); i++) + { + bFound = false; + for(size_t j = 0; j < groups.size(); j++) + { + if(groups[j] == pNode->m_childs[i]->m_payload.m_funName) + { + bFound = true; + break; + } + } + if(!bFound) + groups.push_back(pNode->m_childs[i]->m_payload.m_funName); + } + } + + for(size_t g = 0; g < groups.size(); g++) + { + for(size_t i = 0; i < pNode->m_childs.size(); i++) + { + if(pNode->m_childs[i]->m_payload.m_funName == groups[g]) + { + printShift(pNode->m_childs[i], pRoot); + + if(pNode->m_childs.size()-1 == pNode->m_childs[i]->m_pParent->findChild(pNode->m_childs[i])) + printf("\\---"); + else + printf("|---"); + printNodeRec(pNode->m_childs[i], pRoot); + } + } + } +} + +template +std::string to_string_with_precision(const T value, const int p = 3) +{ + std::ostringstream out; + out << std::fixed << std::setprecision(p) << value; + return out.str(); +} + +static cv::String nodeToString(cv::instr::InstrNode *pNode) +{ + cv::String string; + if (pNode->m_payload.m_funName == "ROOT") + string = pNode->m_payload.m_funName; + else + { + string = "#"; + string += std::to_string(pNode->m_payload.m_instrType); + string += pNode->m_payload.m_funName; + string += " - L:"; + string += to_string_with_precision(calcLocalWeight(pNode)); + string += ", G:"; + string += to_string_with_precision(calcGlobalWeight(pNode)); + } + string += "("; + for(size_t i = 0; i < pNode->m_childs.size(); i++) + string += nodeToString(pNode->m_childs[i]); + string += ")"; + + return string; +} + +static uint64 getNodeTimeRec(cv::instr::InstrNode *pNode, int type, int impl) +{ + uint64 ticks = 0; + + if(pNode->m_pParent && pNode->m_payload.m_instrType == type && pNode->m_payload.m_implType == impl) + ticks = pNode->m_payload.m_ticksMean; + + for(size_t i = 0; i < pNode->m_childs.size(); i++) + ticks += getNodeTimeRec(pNode->m_childs[i], type, impl); + + return ticks; +} + +static uint64 getImplTime(int impl) +{ + uint64 ticks = 0; + cv::instr::InstrNode *pRoot = cv::instr::getTrace(); + + ticks = getNodeTimeRec(pRoot, cv::instr::TYPE_FUN, impl); + + return ticks; +} + +static uint64 getTotalTime() +{ + uint64 ticks = 0; + cv::instr::InstrNode *pRoot = cv::instr::getTrace(); + + for(size_t i = 0; i < pRoot->m_childs.size(); i++) + ticks += pRoot->m_childs[i]->m_payload.m_ticksMean; + + return ticks; +} + +::cv::String InstumentData::treeToString() +{ + cv::String string = nodeToString(cv::instr::getTrace()); + return string; +} + +void InstumentData::printTree() +{ + if(cv::instr::getTrace()->m_childs.size()) + { + printf("[ TRACE ]\n"); + printNodeRec(cv::instr::getTrace(), cv::instr::getTrace()); +#ifdef HAVE_IPP + printf("\nIPP weight: %.1f%%", ((double)getImplTime(cv::instr::IMPL_IPP)*100/(double)getTotalTime())); +#endif +#ifdef HAVE_OPENCL + printf("\nOPENCL weight: %.1f%%", ((double)getImplTime(cv::instr::IMPL_OPENCL)*100/(double)getTotalTime())); +#endif + printf("\n[/TRACE ]\n"); + fflush(stdout); + } +} +#endif /*****************************************************************************************\ * ::perf::TestBase @@ -774,6 +989,9 @@ void TestBase::Init(const std::vector & availableImpls, #endif #ifdef CV_COLLECT_IMPL_DATA "{ perf_collect_impl |false |collect info about executed implementations}" +#endif +#ifdef ENABLE_INSTRUMENTATION + "{ perf_instrument |false |instrument code to collect implementations trace}" #endif "{ help h |false |print help info}" #ifdef HAVE_CUDA @@ -826,6 +1044,9 @@ void TestBase::Init(const std::vector & availableImpls, #ifdef CV_COLLECT_IMPL_DATA param_collect_impl = args.get("perf_collect_impl"); #endif +#ifdef ENABLE_INSTRUMENTATION + param_instrument = args.get("perf_instrument"); +#endif #ifdef ANDROID param_affinity_mask = args.get("perf_affinity_mask"); log_power_checkpoints = args.has("perf_log_power_checkpoints"); @@ -856,6 +1077,12 @@ void TestBase::Init(const std::vector & availableImpls, else cv::setUseCollection(0); #endif +#ifdef ENABLE_INSTRUMENTATION + if(param_instrument) + cv::instr::setUseInstrumentation(true); + else + cv::instr::setUseInstrumentation(false); +#endif #ifdef HAVE_CUDA @@ -969,13 +1196,13 @@ int64 TestBase::_calibrate() cv::Mat b(2048, 2048, CV_32S, cv::Scalar(2)); declare.time(30); double s = 0; - for(declare.iterations(20); startTimer(), next(); stopTimer()) + for(declare.iterations(20); next() && startTimer(); stopTimer()) s+=a.dot(b); declare.time(s); //self calibration SetUp(); - for(declare.iterations(1000); startTimer(), next(); stopTimer()){} + for(declare.iterations(1000); next() && startTimer(); stopTimer()){} } }; @@ -1242,8 +1469,6 @@ bool TestBase::next() } #endif - if (has_next) - startTimer(); // really we should measure activity from this moment, so reset start time return has_next; } @@ -1281,9 +1506,17 @@ unsigned int TestBase::getTotalOutputSize() const return res; } -void TestBase::startTimer() +bool TestBase::startTimer() { +#ifdef ENABLE_INSTRUMENTATION + if(currentIter == 0) + { + cv::instr::setFlags(cv::instr::getFlags()|cv::instr::FLAGS_MAPPING); // enable mapping for the first run + cv::instr::resetTrace(); + } +#endif lastTime = cv::getTickCount(); + return true; // dummy true for conditional loop } void TestBase::stopTimer() @@ -1297,6 +1530,10 @@ void TestBase::stopTimer() if (lastTime < 0) lastTime = 0; times.push_back(lastTime); lastTime = 0; + +#ifdef ENABLE_INSTRUMENTATION + cv::instr::setFlags(cv::instr::getFlags()&~cv::instr::FLAGS_MAPPING); // disable mapping to decrease overhead for +1 run +#endif } performance_metrics& TestBase::calcMetrics() @@ -1469,6 +1706,16 @@ void TestBase::reportMetrics(bool toJUnitXML) RecordProperty("gstddev", cv::format("%.6f", m.gstddev).c_str()); RecordProperty("mean", cv::format("%.0f", m.mean).c_str()); RecordProperty("stddev", cv::format("%.0f", m.stddev).c_str()); +#ifdef ENABLE_INSTRUMENTATION + if(cv::instr::useInstrumentation()) + { + cv::String tree = InstumentData::treeToString(); + RecordProperty("functions_hierarchy", tree.c_str()); + RecordProperty("total_ipp_weight", cv::format("%.1f", ((double)getImplTime(cv::instr::IMPL_IPP)*100/(double)getTotalTime()))); + RecordProperty("total_opencl_weight", cv::format("%.1f", ((double)getImplTime(cv::instr::IMPL_OPENCL)*100/(double)getTotalTime()))); + cv::instr::resetTrace(); + } +#endif #ifdef CV_COLLECT_IMPL_DATA if(param_collect_impl) { @@ -1639,6 +1886,12 @@ void TestBase::TearDown() fflush(stdout); } #endif + +#ifdef ENABLE_INSTRUMENTATION + if(cv::instr::useInstrumentation()) + InstumentData::printTree(); +#endif + reportMetrics(true); } From fde4e8fed9542ac27f2727204a08c968e9c07fe4 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 17 Aug 2016 13:34:59 +0300 Subject: [PATCH 075/178] cmake: add /usr/local/lib on Apple platform --- cmake/OpenCVCompilerOptions.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake index a2c118db43..350eb8c48c 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -384,3 +384,7 @@ if(NOT OPENCV_FP16_DISABLE) set(HAVE_FP16 1) endif() endif() + +if(APPLE AND NOT CMAKE_CROSSCOMPILING AND NOT DEFINED ENV{LDFLAGS} AND EXISTS "/usr/local/lib") + link_directories("/usr/local/lib") +endif() From 46bfdbaf82f783b36a0462f7e71e261ccbf60da2 Mon Sep 17 00:00:00 2001 From: Alexandr Kondratev Date: Sat, 23 Jul 2016 18:10:36 +0300 Subject: [PATCH 076/178] highgui: window_QT mousecallback code refactored using DRY --- modules/highgui/src/window_QT.cpp | 284 +++++++++++------------------- modules/highgui/src/window_QT.h | 41 +++-- 2 files changed, 122 insertions(+), 203 deletions(-) diff --git a/modules/highgui/src/window_QT.cpp b/modules/highgui/src/window_QT.cpp index 7388a44b8d..e5a25f4717 100644 --- a/modules/highgui/src/window_QT.cpp +++ b/modules/highgui/src/window_QT.cpp @@ -2295,11 +2295,90 @@ void CvWindow::icvSaveTrackbars(QSettings* settings) } +////////////////////////////////////////////////////// +// OCVViewPort + +OCVViewPort::OCVViewPort() +{ + mouseCallback = 0; + mouseData = 0; +} + +void OCVViewPort::setMouseCallBack(CvMouseCallback callback, void* param) +{ + mouseCallback = callback; + mouseData = param; +} + +void OCVViewPort::icvmouseEvent(QMouseEvent* evnt, type_mouse_event category) +{ + int cv_event = -1, flags = 0; + + icvmouseHandler(evnt, category, cv_event, flags); + icvmouseProcessing(QPointF(evnt->pos()), cv_event, flags); +} + +void OCVViewPort::icvmouseHandler(QMouseEvent* evnt, type_mouse_event category, int& cv_event, int& flags) +{ + Qt::KeyboardModifiers modifiers = evnt->modifiers(); + Qt::MouseButtons buttons = evnt->buttons(); + + // This line gives excess flags flushing, with it you cannot predefine flags value. + // icvmouseHandler called with flags == 0 where it really need. + //flags = 0; + if(modifiers & Qt::ShiftModifier) + flags |= CV_EVENT_FLAG_SHIFTKEY; + if(modifiers & Qt::ControlModifier) + flags |= CV_EVENT_FLAG_CTRLKEY; + if(modifiers & Qt::AltModifier) + flags |= CV_EVENT_FLAG_ALTKEY; + + if(buttons & Qt::LeftButton) + flags |= CV_EVENT_FLAG_LBUTTON; + if(buttons & Qt::RightButton) + flags |= CV_EVENT_FLAG_RBUTTON; + if(buttons & Qt::MidButton) + flags |= CV_EVENT_FLAG_MBUTTON; + + if (cv_event == -1) { + if (category == mouse_wheel) { + QWheelEvent *we = (QWheelEvent *) evnt; + cv_event = ((we->orientation() == Qt::Vertical) ? CV_EVENT_MOUSEWHEEL : CV_EVENT_MOUSEHWHEEL); + flags |= (we->delta() & 0xffff)<<16; + return; + } + switch(evnt->button()) + { + case Qt::LeftButton: + cv_event = tableMouseButtons[category][0]; + flags |= CV_EVENT_FLAG_LBUTTON; + break; + case Qt::RightButton: + cv_event = tableMouseButtons[category][1]; + flags |= CV_EVENT_FLAG_RBUTTON; + break; + case Qt::MidButton: + cv_event = tableMouseButtons[category][2]; + flags |= CV_EVENT_FLAG_MBUTTON; + break; + default: + cv_event = CV_EVENT_MOUSEMOVE; + } + } +} + +void OCVViewPort::icvmouseProcessing(QPointF pt, int cv_event, int flags) +{ + if (mouseCallback) + mouseCallback(cv_event, pt.x(), pt.y(), flags, mouseData); +} + + ////////////////////////////////////////////////////// // DefaultViewPort -DefaultViewPort::DefaultViewPort(CvWindow* arg, int arg2) : QGraphicsView(arg), image2Draw_mat(0) +DefaultViewPort::DefaultViewPort(CvWindow* arg, int arg2) : QGraphicsView(arg), OCVViewPort(), image2Draw_mat(0) { centralWidget = arg; param_keepRatio = arg2; @@ -2315,12 +2394,10 @@ DefaultViewPort::DefaultViewPort(CvWindow* arg, int arg2) : QGraphicsView(arg), connect(timerDisplay, SIGNAL(timeout()), this, SLOT(stopDisplayInfo())); drawInfo = false; + mouseCoordinate = QPoint(-1, -1); positionGrabbing = QPointF(0, 0); - positionCorners = QRect(0, 0, size().width(), size().height()); + positionCorners = QRect(0, 0, size().width(), size().height()); - on_mouse = 0; - on_mouse_param = 0; - mouseCoordinate = QPoint(-1, -1); //no border setStyleSheet( "QGraphicsView { border-style: none; }" ); @@ -2348,13 +2425,6 @@ QWidget* DefaultViewPort::getWidget() } -void DefaultViewPort::setMouseCallBack(CvMouseCallback m, void* param) -{ - on_mouse = m; - - on_mouse_param = param; -} - void DefaultViewPort::writeSettings(QSettings& settings) { settings.setValue("matrix_view.m11", param_matrixWorld.m11()); @@ -2629,13 +2699,10 @@ void DefaultViewPort::resizeEvent(QResizeEvent* evnt) void DefaultViewPort::wheelEvent(QWheelEvent* evnt) { - int delta = evnt->delta(); - int cv_event = ((evnt->orientation() == Qt::Vertical) ? CV_EVENT_MOUSEWHEEL : CV_EVENT_MOUSEHWHEEL); - int flags = (delta & 0xffff)<<16; - QPoint pt = evnt->pos(); + icvmouseEvent((QMouseEvent *)evnt, mouse_wheel); - icvmouseHandler((QMouseEvent*)evnt, mouse_wheel, cv_event, flags); - icvmouseProcessing(QPointF(pt), cv_event, flags); + scaleView(evnt->delta() / 240.0, evnt->pos()); + viewport()->update(); QWidget::wheelEvent(evnt); } @@ -2643,12 +2710,7 @@ void DefaultViewPort::wheelEvent(QWheelEvent* evnt) void DefaultViewPort::mousePressEvent(QMouseEvent* evnt) { - int cv_event = -1, flags = 0; - QPoint pt = evnt->pos(); - - //icvmouseHandler: pass parameters for cv_event, flags - icvmouseHandler(evnt, mouse_down, cv_event, flags); - icvmouseProcessing(QPointF(pt), cv_event, flags); + icvmouseEvent(evnt, mouse_down); if (param_matrixWorld.m11()>1) { @@ -2662,12 +2724,7 @@ void DefaultViewPort::mousePressEvent(QMouseEvent* evnt) void DefaultViewPort::mouseReleaseEvent(QMouseEvent* evnt) { - int cv_event = -1, flags = 0; - QPoint pt = evnt->pos(); - - //icvmouseHandler: pass parameters for cv_event, flags - icvmouseHandler(evnt, mouse_up, cv_event, flags); - icvmouseProcessing(QPointF(pt), cv_event, flags); + icvmouseEvent(evnt, mouse_up); if (param_matrixWorld.m11()>1) setCursor(Qt::OpenHandCursor); @@ -2678,30 +2735,20 @@ void DefaultViewPort::mouseReleaseEvent(QMouseEvent* evnt) void DefaultViewPort::mouseDoubleClickEvent(QMouseEvent* evnt) { - int cv_event = -1, flags = 0; - QPoint pt = evnt->pos(); - - //icvmouseHandler: pass parameters for cv_event, flags - icvmouseHandler(evnt, mouse_dbclick, cv_event, flags); - icvmouseProcessing(QPointF(pt), cv_event, flags); - + icvmouseEvent(evnt, mouse_dbclick); QWidget::mouseDoubleClickEvent(evnt); } void DefaultViewPort::mouseMoveEvent(QMouseEvent* evnt) { - int cv_event = CV_EVENT_MOUSEMOVE, flags = 0; - QPoint pt = evnt->pos(); - - //icvmouseHandler: pass parameters for cv_event, flags - icvmouseHandler(evnt, mouse_move, cv_event, flags); - icvmouseProcessing(QPointF(pt), cv_event, flags); + icvmouseEvent(evnt, mouse_move); if (param_matrixWorld.m11() > 1 && evnt->buttons() == Qt::LeftButton) { + QPoint pt = evnt->pos(); QPointF dxy = (pt - positionGrabbing)/param_matrixWorld.m11(); - positionGrabbing = evnt->pos(); + positionGrabbing = pt; moveView(dxy); } @@ -2848,48 +2895,6 @@ void DefaultViewPort::scaleView(qreal factor,QPointF center) } -//up, down, dclick, move -void DefaultViewPort::icvmouseHandler(QMouseEvent *evnt, type_mouse_event category, int &cv_event, int &flags) -{ - Qt::KeyboardModifiers modifiers = evnt->modifiers(); - Qt::MouseButtons buttons = evnt->buttons(); - - // This line gives excess flags flushing, with it you cannot predefine flags value. - // icvmouseHandler called with flags == 0 where it really need. - //flags = 0; - if(modifiers & Qt::ShiftModifier) - flags |= CV_EVENT_FLAG_SHIFTKEY; - if(modifiers & Qt::ControlModifier) - flags |= CV_EVENT_FLAG_CTRLKEY; - if(modifiers & Qt::AltModifier) - flags |= CV_EVENT_FLAG_ALTKEY; - - if(buttons & Qt::LeftButton) - flags |= CV_EVENT_FLAG_LBUTTON; - if(buttons & Qt::RightButton) - flags |= CV_EVENT_FLAG_RBUTTON; - if(buttons & Qt::MidButton) - flags |= CV_EVENT_FLAG_MBUTTON; - - if (cv_event == -1) - switch(evnt->button()) - { - case Qt::LeftButton: - cv_event = tableMouseButtons[category][0]; - flags |= CV_EVENT_FLAG_LBUTTON; - break; - case Qt::RightButton: - cv_event = tableMouseButtons[category][1]; - flags |= CV_EVENT_FLAG_RBUTTON; - break; - case Qt::MidButton: - cv_event = tableMouseButtons[category][2]; - flags |= CV_EVENT_FLAG_MBUTTON; - break; - default: - cv_event = CV_EVENT_MOUSEMOVE; - } -} void DefaultViewPort::icvmouseProcessing(QPointF pt, int cv_event, int flags) @@ -2901,9 +2906,7 @@ void DefaultViewPort::icvmouseProcessing(QPointF pt, int cv_event, int flags) mouseCoordinate.rx()=floor(pfx/ratioX); mouseCoordinate.ry()=floor(pfy/ratioY); - if (on_mouse) - on_mouse( cv_event, mouseCoordinate.x(), - mouseCoordinate.y(), flags, on_mouse_param ); + OCVViewPort::icvmouseProcessing(QPointF(mouseCoordinate), cv_event, flags); } @@ -3108,11 +3111,8 @@ void DefaultViewPort::setSize(QSize /*size_*/) #ifdef HAVE_QT_OPENGL -OpenGlViewPort::OpenGlViewPort(QWidget* _parent) : QGLWidget(_parent), size(-1, -1) +OpenGlViewPort::OpenGlViewPort(QWidget* _parent) : QGLWidget(_parent), OCVViewPort(), size(-1, -1) { - mouseCallback = 0; - mouseData = 0; - glDrawCallback = 0; glDrawData = 0; } @@ -3126,11 +3126,6 @@ QWidget* OpenGlViewPort::getWidget() return this; } -void OpenGlViewPort::setMouseCallBack(CvMouseCallback callback, void* param) -{ - mouseCallback = callback; - mouseData = param; -} void OpenGlViewPort::writeSettings(QSettings& /*settings*/) { @@ -3191,116 +3186,37 @@ void OpenGlViewPort::paintGL() glDrawCallback(glDrawData); } + void OpenGlViewPort::wheelEvent(QWheelEvent* evnt) { - int delta = evnt->delta(); - int cv_event = ((evnt->orientation() == Qt::Vertical) ? CV_EVENT_MOUSEWHEEL : CV_EVENT_MOUSEHWHEEL); - int flags = (delta & 0xffff)<<16; - QPoint pt = evnt->pos(); - - icvmouseHandler((QMouseEvent*)evnt, mouse_wheel, cv_event, flags); - icvmouseProcessing(QPointF(pt), cv_event, flags); - - QWidget::wheelEvent(evnt); + icvmouseEvent((QMouseEvent *)evnt, mouse_wheel); + QGLWidget::wheelEvent(evnt); } void OpenGlViewPort::mousePressEvent(QMouseEvent* evnt) { - int cv_event = -1, flags = 0; - QPoint pt = evnt->pos(); - - icvmouseHandler(evnt, mouse_down, cv_event, flags); - icvmouseProcessing(QPointF(pt), cv_event, flags); - + icvmouseEvent(evnt, mouse_down); QGLWidget::mousePressEvent(evnt); } - void OpenGlViewPort::mouseReleaseEvent(QMouseEvent* evnt) { - int cv_event = -1, flags = 0; - QPoint pt = evnt->pos(); - - icvmouseHandler(evnt, mouse_up, cv_event, flags); - icvmouseProcessing(QPointF(pt), cv_event, flags); - + icvmouseEvent(evnt, mouse_up); QGLWidget::mouseReleaseEvent(evnt); } - void OpenGlViewPort::mouseDoubleClickEvent(QMouseEvent* evnt) { - int cv_event = -1, flags = 0; - QPoint pt = evnt->pos(); - - icvmouseHandler(evnt, mouse_dbclick, cv_event, flags); - icvmouseProcessing(QPointF(pt), cv_event, flags); - + icvmouseEvent(evnt, mouse_dbclick); QGLWidget::mouseDoubleClickEvent(evnt); } - void OpenGlViewPort::mouseMoveEvent(QMouseEvent* evnt) { - int cv_event = CV_EVENT_MOUSEMOVE, flags = 0; - QPoint pt = evnt->pos(); - - //icvmouseHandler: pass parameters for cv_event, flags - icvmouseHandler(evnt, mouse_move, cv_event, flags); - icvmouseProcessing(QPointF(pt), cv_event, flags); - + icvmouseEvent(evnt, mouse_move); QGLWidget::mouseMoveEvent(evnt); } -void OpenGlViewPort::icvmouseHandler(QMouseEvent* evnt, type_mouse_event category, int& cv_event, int& flags) -{ - Qt::KeyboardModifiers modifiers = evnt->modifiers(); - Qt::MouseButtons buttons = evnt->buttons(); - - // This line gives excess flags flushing, with it you cannot predefine flags value. - // icvmouseHandler called with flags == 0 where it really need. - //flags = 0; - if(modifiers & Qt::ShiftModifier) - flags |= CV_EVENT_FLAG_SHIFTKEY; - if(modifiers & Qt::ControlModifier) - flags |= CV_EVENT_FLAG_CTRLKEY; - if(modifiers & Qt::AltModifier) - flags |= CV_EVENT_FLAG_ALTKEY; - - if(buttons & Qt::LeftButton) - flags |= CV_EVENT_FLAG_LBUTTON; - if(buttons & Qt::RightButton) - flags |= CV_EVENT_FLAG_RBUTTON; - if(buttons & Qt::MidButton) - flags |= CV_EVENT_FLAG_MBUTTON; - - if (cv_event == -1) - switch(evnt->button()) - { - case Qt::LeftButton: - cv_event = tableMouseButtons[category][0]; - flags |= CV_EVENT_FLAG_LBUTTON; - break; - case Qt::RightButton: - cv_event = tableMouseButtons[category][1]; - flags |= CV_EVENT_FLAG_RBUTTON; - break; - case Qt::MidButton: - cv_event = tableMouseButtons[category][2]; - flags |= CV_EVENT_FLAG_MBUTTON; - break; - default: - cv_event = CV_EVENT_MOUSEMOVE; - } -} - - -void OpenGlViewPort::icvmouseProcessing(QPointF pt, int cv_event, int flags) -{ - if (mouseCallback) - mouseCallback(cv_event, pt.x(), pt.y(), flags, mouseData); -} - QSize OpenGlViewPort::sizeHint() const { diff --git a/modules/highgui/src/window_QT.h b/modules/highgui/src/window_QT.h index 16cc9e3853..df80568cf0 100644 --- a/modules/highgui/src/window_QT.h +++ b/modules/highgui/src/window_QT.h @@ -403,10 +403,26 @@ public: }; +class OCVViewPort : public ViewPort +{ +public: + explicit OCVViewPort(); + ~OCVViewPort() {}; + void setMouseCallBack(CvMouseCallback callback, void* param); + +protected: + void icvmouseEvent(QMouseEvent* event, type_mouse_event category); + void icvmouseHandler(QMouseEvent* event, type_mouse_event category, int& cv_event, int& flags); + void icvmouseProcessing(QPointF pt, int cv_event, int flags); + + CvMouseCallback mouseCallback; + void* mouseData; +}; + #ifdef HAVE_QT_OPENGL -class OpenGlViewPort : public QGLWidget, public ViewPort +class OpenGlViewPort : public QGLWidget, public OCVViewPort { public: explicit OpenGlViewPort(QWidget* parent); @@ -414,8 +430,6 @@ public: QWidget* getWidget(); - void setMouseCallBack(CvMouseCallback callback, void* param); - void writeSettings(QSettings& settings); void readSettings(QSettings& settings); @@ -448,20 +462,14 @@ protected: private: QSize size; - CvMouseCallback mouseCallback; - void* mouseData; - CvOpenGlDrawCallback glDrawCallback; void* glDrawData; - - void icvmouseHandler(QMouseEvent* event, type_mouse_event category, int& cv_event, int& flags); - void icvmouseProcessing(QPointF pt, int cv_event, int flags); }; #endif // HAVE_QT_OPENGL -class DefaultViewPort : public QGraphicsView, public ViewPort +class DefaultViewPort : public QGraphicsView, public OCVViewPort { Q_OBJECT @@ -471,8 +479,6 @@ public: QWidget* getWidget(); - void setMouseCallBack(CvMouseCallback callback, void* param); - void writeSettings(QSettings& settings); void readSettings(QSettings& settings); @@ -510,6 +516,7 @@ protected: void contextMenuEvent(QContextMenuEvent* event); void resizeEvent(QResizeEvent* event); void paintEvent(QPaintEvent* paintEventInfo); + void wheelEvent(QWheelEvent* event); void mouseMoveEvent(QMouseEvent* event); void mousePressEvent(QMouseEvent* event); @@ -526,17 +533,13 @@ private: QImage image2Draw_qt; int nbChannelOriginImage; - //for mouse callback - CvMouseCallback on_mouse; - void* on_mouse_param; - void scaleView(qreal scaleFactor, QPointF center); void moveView(QPointF delta); - QPoint mouseCoordinate; + QPoint mouseCoordinate; QPointF positionGrabbing; - QRect positionCorners; + QRect positionCorners; QTransform matrixWorld_inv; float ratioX, ratioY; @@ -555,7 +558,7 @@ private: void draw2D(QPainter *painter); void drawStatusBar(); void controlImagePosition(); - void icvmouseHandler(QMouseEvent *event, type_mouse_event category, int &cv_event, int &flags); + void icvmouseProcessing(QPointF pt, int cv_event, int flags); private slots: From ce818dc01f7eaffc970857ce6a8e5be90ad3383a Mon Sep 17 00:00:00 2001 From: sourin Date: Thu, 18 Aug 2016 17:24:43 +0530 Subject: [PATCH 077/178] respective changes added --- modules/features2d/src/matchers.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/features2d/src/matchers.cpp b/modules/features2d/src/matchers.cpp index 11dfa6d388..2519dc2d40 100644 --- a/modules/features2d/src/matchers.cpp +++ b/modules/features2d/src/matchers.cpp @@ -613,8 +613,7 @@ void DescriptorMatcher::checkMasks( InputArrayOfArrays _masks, int queryDescript { int rows = trainDescCollection[i].empty() ? utrainDescCollection[i].rows : trainDescCollection[i].rows; CV_Assert( masks[i].rows == queryDescriptorsCount && - (masks[i].cols == rows || masks[i].cols == rows) && - masks[i].type() == CV_8UC1 ); + masks[i].cols == rows && masks[i].type() == CV_8UC1); } } } @@ -1357,5 +1356,4 @@ void FlannBasedMatcher::radiusMatchImpl( InputArray _queryDescriptors, std::vect convertToDMatches( mergedDescriptors, indices, dists, matches ); } - } From 680ca88ce06ed5d7ef7d232c1f6233650ca1991c Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Wed, 17 Aug 2016 10:25:19 +0300 Subject: [PATCH 078/178] Outdated ICV restrictions were removed; --- modules/core/include/opencv2/core/private.hpp | 11 ----------- modules/core/src/copy.cpp | 2 +- modules/core/src/stat.cpp | 8 ++------ modules/imgproc/perf/perf_houghLines.cpp | 2 +- modules/imgproc/src/color.cpp | 2 +- modules/imgproc/src/deriv.cpp | 5 +---- modules/imgproc/src/filter.cpp | 4 ---- modules/imgproc/src/hough.cpp | 4 ++-- modules/imgproc/src/imgwarp.cpp | 4 ++-- modules/imgproc/src/smooth.cpp | 7 ++----- modules/imgproc/src/sumpixels.cpp | 2 +- modules/imgproc/src/thresh.cpp | 16 ++-------------- modules/imgproc/test/test_houghLines.cpp | 2 +- 13 files changed, 16 insertions(+), 53 deletions(-) diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index 6fcd1713c2..c839327823 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -288,17 +288,6 @@ private: #define IPP_VERSION_X100 0 #endif -// There shoud be no API difference in OpenCV between ICV and IPP since 9.0 -#if (defined HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 900 -#undef HAVE_IPP_ICV_ONLY -#endif - -#ifdef HAVE_IPP_ICV_ONLY -#define HAVE_ICV 1 -#else -#define HAVE_ICV 0 -#endif - #if defined HAVE_IPP #if IPP_VERSION_X100 >= 900 #define IPP_INITIALIZER(FEAT) \ diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index f2201e66fe..5acb1dac0a 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -375,7 +375,7 @@ Mat& Mat::operator = (const Scalar& s) if( is[0] == 0 && is[1] == 0 && is[2] == 0 && is[3] == 0 ) { -#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY && IPP_DISABLE_BLOCK +#if defined HAVE_IPP && IPP_DISABLE_BLOCK CV_IPP_CHECK() { if (dims <= 2 || isContinuous()) diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 727d89554d..b586fe2aca 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -1299,7 +1299,6 @@ namespace cv { static bool ipp_countNonZero( Mat &src, int &res ) { -#if !defined HAVE_IPP_ICV_ONLY Ipp32s count = 0; IppStatus status = ippStsNoErr; @@ -1323,9 +1322,6 @@ static bool ipp_countNonZero( Mat &src, int &res ) res = ((Ipp32s)src.total() - count); return true; } -#else - CV_UNUSED(src); CV_UNUSED(res); -#endif return false; } } @@ -2282,10 +2278,10 @@ static bool ipp_minMaxIdx( Mat &src, double* minVal, double* maxVal, int* minIdx depth == CV_8S ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_8s_C1R : #endif depth == CV_16U ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_16u_C1R : -#if !((defined _MSC_VER && defined _M_IX86) || defined __i386__) +#if IPP_DISABLE_BLOCK && !((defined _MSC_VER && defined _M_IX86) || defined __i386__) // See bug #4955: the function fails with SEGFAULT when the source matrix contains NANs // IPPICV version is 9.0.1. - // depth == CV_32F ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_32f_C1R : + depth == CV_32F ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_32f_C1R : #endif 0; CV_SUPPRESS_DEPRECATED_END diff --git a/modules/imgproc/perf/perf_houghLines.cpp b/modules/imgproc/perf/perf_houghLines.cpp index 6dfaa56aa3..a6ab50e644 100644 --- a/modules/imgproc/perf/perf_houghLines.cpp +++ b/modules/imgproc/perf/perf_houghLines.cpp @@ -37,7 +37,7 @@ PERF_TEST_P(Image_RhoStep_ThetaStep_Threshold, HoughLines, TEST_CYCLE() HoughLines(image, lines, rhoStep, thetaStep, threshold); transpose(lines, lines); -#if (0 && defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 810) +#if (0 && defined(HAVE_IPP) && IPP_VERSION_X100 >= 810) SANITY_CHECK_NOTHING(); #else SANITY_CHECK(lines); diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index af75445e61..1d83577b95 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -393,7 +393,7 @@ static ippiGeneralFunc ippiHLS2RGBTab[] = 0, (ippiGeneralFunc)ippiHLSToRGB_32f_C3R, 0, 0 }; -#if !defined(HAVE_IPP_ICV_ONLY) && IPP_DISABLE_BLOCK +#if IPP_DISABLE_BLOCK static ippiGeneralFunc ippiRGBToLUVTab[] = { (ippiGeneralFunc)ippiRGBToLUV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToLUV_16u_C3R, 0, diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index e660d2e3b0..06592d8b2d 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -359,7 +359,6 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, return true; } -#if !defined(HAVE_IPP_ICV_ONLY) if ((dx == 2) && (dy == 0)) { #if IPP_VERSION_X100 >= 900 @@ -397,7 +396,6 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, return false; return true; } -#endif } if (src.type() == CV_32F && dst.type() == CV_32F) @@ -445,7 +443,7 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, return true; } #endif -#if !defined(HAVE_IPP_ICV_ONLY) + if((dx == 2) && (dy == 0)) { #if IPP_VERSION_X100 >= 900 @@ -488,7 +486,6 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); return true; } -#endif } return false; } diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 1a7f27af3b..e2c79a6bfd 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -4540,7 +4540,6 @@ struct ReplacementFilter : public hal::Filter2D }; #ifdef HAVE_IPP -#if !HAVE_ICV typedef IppStatus(CV_STDCALL* ippiFilterBorder)( const void* pSrc, int srcStep, void* pDst, int dstStep, IppiSize dstRoiSize, IppiBorderType border, const void* borderValue, @@ -4702,7 +4701,6 @@ struct IppFilter : public hal::Filter2D } }; #endif -#endif struct DftFilter : public hal::Filter2D { @@ -4907,7 +4905,6 @@ Ptr Filter2D::create(uchar* kernel_data, size_t kernel_step, int } #ifdef HAVE_IPP -#if !HAVE_ICV if (kernel_type == CV_32FC1) { IppFilter* impl = new IppFilter(); if (impl->init(kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, @@ -4929,7 +4926,6 @@ Ptr Filter2D::create(uchar* kernel_data, size_t kernel_step, int } delete impl; } -#endif #endif if (DftFilter::isAppropriate(stype, dtype, kernel_width, kernel_height)) diff --git a/modules/imgproc/src/hough.cpp b/modules/imgproc/src/hough.cpp index e77544e902..d2d215489c 100644 --- a/modules/imgproc/src/hough.cpp +++ b/modules/imgproc/src/hough.cpp @@ -96,7 +96,7 @@ HoughLinesStandard( const Mat& img, float rho, float theta, int numangle = cvRound((max_theta - min_theta) / theta); int numrho = cvRound(((width + height) * 2 + 1) / rho); -#if defined HAVE_IPP && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK +#if defined HAVE_IPP && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK CV_IPP_CHECK() { IppiSize srcSize = { width, height }; @@ -429,7 +429,7 @@ HoughLinesProbabilistic( Mat& image, int numangle = cvRound(CV_PI / theta); int numrho = cvRound(((width + height) * 2 + 1) / rho); -#if defined HAVE_IPP && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK +#if defined HAVE_IPP && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK CV_IPP_CHECK() { IppiSize srcSize = { width, height }; diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index ff96c2fe1e..d103a4ab28 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -4740,7 +4740,7 @@ static bool ocl_logPolar(InputArray _src, OutputArray _dst, } #endif -#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY && IPP_DISABLE_BLOCK +#if defined HAVE_IPP && IPP_DISABLE_BLOCK typedef IppStatus (CV_STDCALL * ippiRemap)(const void * pSrc, IppiSize srcSize, int srcStep, IppiRect srcRoi, const Ipp32f* pxMap, int xMapStep, const Ipp32f* pyMap, int yMapStep, @@ -4848,7 +4848,7 @@ void cv::remap( InputArray _src, OutputArray _dst, int type = src.type(), depth = CV_MAT_DEPTH(type); -#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY && IPP_DISABLE_BLOCK +#if defined HAVE_IPP && IPP_DISABLE_BLOCK CV_IPP_CHECK() { if ((interpolation == INTER_LINEAR || interpolation == INTER_CUBIC || interpolation == INTER_NEAREST) && diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 8245a62057..034a2c0923 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -1783,7 +1783,6 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, } IppStatus status = ippStsErr; -#if !HAVE_ICV #if IPP_VERSION_X100 > 900 // Buffer overflow may happen in IPP 9.0.0 and less if (type == CV_8UC1) IPP_FILTER_GAUSS_C1(8u) @@ -1801,9 +1800,7 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, IPP_FILTER_GAUSS_CN(16s, 3) else if (type == CV_32FC3) IPP_FILTER_GAUSS_CN(32f, 3) - else -#endif - if (type == CV_32FC1) + else if (type == CV_32FC1) IPP_FILTER_GAUSS_C1(32f) if(status >= 0) @@ -3060,7 +3057,7 @@ private: float *space_weight, *color_weight; }; -#if defined (HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_DISABLE_BLOCK +#if defined (HAVE_IPP) && IPP_DISABLE_BLOCK class IPPBilateralFilter_8u_Invoker : public ParallelLoopBody { diff --git a/modules/imgproc/src/sumpixels.cpp b/modules/imgproc/src/sumpixels.cpp index 7771d2cab4..348ac18ecf 100755 --- a/modules/imgproc/src/sumpixels.cpp +++ b/modules/imgproc/src/sumpixels.cpp @@ -425,7 +425,7 @@ namespace cv { static bool ipp_integral(InputArray _src, OutputArray _sum, OutputArray _sqsum, OutputArray _tilted, int sdepth, int sqdepth) { -#if !defined(HAVE_IPP_ICV_ONLY) && (IPP_VERSION_X100 != 900) // Disabled on ICV due invalid results +#if IPP_VERSION_X100 != 900 // Disabled on ICV due invalid results int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); if( sdepth <= 0 ) sdepth = depth == CV_8U ? CV_32S : CV_64F; diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index 804e7616c7..1513bdafa1 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -91,13 +91,11 @@ thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type ) switch( type ) { case THRESH_TRUNC: -#ifndef HAVE_IPP_ICV_ONLY if (_src.data == _dst.data && ippiThreshold_GT_8u_C1IR(_dst.ptr(), (int)dst_step, sz, thresh) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; } -#endif if (ippiThreshold_GT_8u_C1R(_src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); @@ -106,13 +104,11 @@ thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type ) setIppErrorStatus(); break; case THRESH_TOZERO: -#ifndef HAVE_IPP_ICV_ONLY if (_src.data == _dst.data && ippiThreshold_LTVal_8u_C1IR(_dst.ptr(), (int)dst_step, sz, thresh+1, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; } -#endif if (ippiThreshold_LTVal_8u_C1R(_src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh+1, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); @@ -121,13 +117,11 @@ thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type ) setIppErrorStatus(); break; case THRESH_TOZERO_INV: -#ifndef HAVE_IPP_ICV_ONLY if (_src.data == _dst.data && ippiThreshold_GTVal_8u_C1IR(_dst.ptr(), (int)dst_step, sz, thresh, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; } -#endif if (ippiThreshold_GTVal_8u_C1R(_src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); @@ -434,13 +428,11 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) switch( type ) { case THRESH_TRUNC: -#ifndef HAVE_IPP_ICV_ONLY if (_src.data == _dst.data && ippiThreshold_GT_16s_C1IR(dst, (int)dst_step*sizeof(dst[0]), sz, thresh) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; } -#endif if (ippiThreshold_GT_16s_C1R(src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); @@ -449,13 +441,11 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) setIppErrorStatus(); break; case THRESH_TOZERO: -#ifndef HAVE_IPP_ICV_ONLY if (_src.data == _dst.data && ippiThreshold_LTVal_16s_C1IR(dst, (int)dst_step*sizeof(dst[0]), sz, thresh + 1, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; } -#endif if (ippiThreshold_LTVal_16s_C1R(src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh+1, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); @@ -464,13 +454,11 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) setIppErrorStatus(); break; case THRESH_TOZERO_INV: -#ifndef HAVE_IPP_ICV_ONLY if (_src.data == _dst.data && ippiThreshold_GTVal_16s_C1IR(dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; } -#endif if (ippiThreshold_GTVal_16s_C1R(src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); @@ -1188,7 +1176,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type) #ifdef HAVE_IPP static bool ipp_getThreshVal_Otsu_8u( const unsigned char* _src, int step, Size size, unsigned char &thresh) { -#if IPP_VERSION_X100 >= 810 && !HAVE_ICV +#if IPP_VERSION_X100 >= 810 int ippStatus = -1; IppiSize srcSize = { size.width, size.height }; CV_SUPPRESS_DEPRECATED_START @@ -1218,7 +1206,7 @@ getThreshVal_Otsu_8u( const Mat& _src ) #ifdef HAVE_IPP unsigned char thresh; - CV_IPP_RUN(IPP_VERSION_X100 >= 810 && !HAVE_ICV, ipp_getThreshVal_Otsu_8u(_src.ptr(), step, size, thresh), thresh); + CV_IPP_RUN(IPP_VERSION_X100 >= 810, ipp_getThreshVal_Otsu_8u(_src.ptr(), step, size, thresh), thresh); #endif const int N = 256; diff --git a/modules/imgproc/test/test_houghLines.cpp b/modules/imgproc/test/test_houghLines.cpp index a508841714..93a1202ee1 100644 --- a/modules/imgproc/test/test_houghLines.cpp +++ b/modules/imgproc/test/test_houghLines.cpp @@ -189,7 +189,7 @@ void BaseHoughLineTest::run_test(int type) else if (type == PROBABILISTIC) count = countMatIntersection(exp_lines, lines, 1e-4f, 0.f); -#if defined HAVE_IPP && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK +#if defined HAVE_IPP && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK EXPECT_GE( count, (int) (exp_lines.total() * 0.8) ); #else EXPECT_EQ( count, (int) exp_lines.total()); From 86a515fdae7cfd705c412192bced041e9200255c Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 19 Aug 2016 17:30:57 +0300 Subject: [PATCH 079/178] imgproc: fix accuracy check for HLS cvtColor --- modules/imgproc/test/ocl/test_color.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/modules/imgproc/test/ocl/test_color.cpp b/modules/imgproc/test/ocl/test_color.cpp index 160c035345..c0218cca3f 100644 --- a/modules/imgproc/test/ocl/test_color.cpp +++ b/modules/imgproc/test/ocl/test_color.cpp @@ -98,7 +98,29 @@ PARAM_TEST_CASE(CvtColor, MatDepth, bool) OCL_OFF(cv::cvtColor(src_roi, dst_roi, code, channelsOut)); OCL_ON(cv::cvtColor(usrc_roi, udst_roi, code, channelsOut)); - Near(threshold); + int h_limit = 256; + switch (code) + { + case COLOR_RGB2HLS: case COLOR_BGR2HLS: + h_limit = 180; + case COLOR_RGB2HLS_FULL: case COLOR_BGR2HLS_FULL: + { + ASSERT_EQ(dst_roi.type(), udst_roi.type()); + ASSERT_EQ(dst_roi.size(), udst_roi.size()); + Mat gold, actual; + dst_roi.convertTo(gold, CV_32FC3); + udst_roi.getMat(ACCESS_READ).convertTo(actual, CV_32FC3); + Mat absdiff1, absdiff2, absdiff3; + cv::absdiff(gold, actual, absdiff1); + cv::absdiff(gold, actual + h_limit, absdiff2); + cv::absdiff(gold, actual - h_limit, absdiff3); + Mat diff = cv::min(cv::min(absdiff1, absdiff2), absdiff3); + EXPECT_LE(cvtest::norm(diff, NORM_INF), threshold); + break; + } + default: + Near(threshold); + } } } }; From 30a6cee2fe71045afd498027ecaab34647469c01 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Thu, 18 Aug 2016 09:53:00 +0300 Subject: [PATCH 080/178] Instrumentation for OpenCV API regions and IPP functions; --- modules/calib3d/src/calibinit.cpp | 6 + modules/calib3d/src/calibration.cpp | 22 +++ modules/calib3d/src/fisheye.cpp | 26 +++ modules/calib3d/src/five-point.cpp | 8 + modules/calib3d/src/fundam.cpp | 17 +- modules/calib3d/src/p3p.cpp | 2 + modules/calib3d/src/ptsetreg.cpp | 2 + modules/calib3d/src/quadsubpix.cpp | 2 + modules/calib3d/src/solvepnp.cpp | 3 + modules/calib3d/src/stereobm.cpp | 2 + modules/calib3d/src/stereosgbm.cpp | 12 +- modules/calib3d/src/triangulate.cpp | 4 + modules/core/include/opencv2/core/utility.hpp | 5 - modules/core/src/arithm.cpp | 56 +++++- modules/core/src/convert.cpp | 42 ++++- modules/core/src/copy.cpp | 122 +++++++----- modules/core/src/dxt.cpp | 66 ++++--- modules/core/src/glob.cpp | 2 + modules/core/src/kmeans.cpp | 2 + modules/core/src/lapack.cpp | 24 +++ modules/core/src/lda.cpp | 2 + modules/core/src/mathfuncs.cpp | 46 ++++- modules/core/src/mathfuncs_core.cpp | 46 ++++- modules/core/src/matmul.cpp | 32 +++- modules/core/src/matop.cpp | 92 +++++++++ modules/core/src/matrix.cpp | 174 +++++++++++------- modules/core/src/matrix_decomp.cpp | 8 + modules/core/src/pca.cpp | 8 + modules/core/src/persistence.cpp | 4 + modules/core/src/rand.cpp | 6 + modules/core/src/stat.cpp | 163 +++++++++------- modules/core/src/types.cpp | 4 + modules/core/src/umatrix.cpp | 10 + modules/features2d/src/agast.cpp | 5 + modules/features2d/src/akaze.cpp | 2 + modules/features2d/src/bagofwords.cpp | 8 + modules/features2d/src/blobdetector.cpp | 4 + modules/features2d/src/draw.cpp | 2 + modules/features2d/src/evaluation.cpp | 12 ++ modules/features2d/src/fast.cpp | 6 + modules/features2d/src/feature2d.cpp | 10 + modules/features2d/src/gftt.cpp | 2 + modules/features2d/src/kaze.cpp | 2 + modules/features2d/src/matchers.cpp | 18 ++ modules/features2d/src/mser.cpp | 4 + modules/features2d/src/orb.cpp | 2 + modules/flann/src/miniflann.cpp | 10 + modules/imgproc/src/accum.cpp | 110 ++++++----- modules/imgproc/src/approx.cpp | 2 + modules/imgproc/src/blend.cpp | 2 + modules/imgproc/src/canny.cpp | 10 +- modules/imgproc/src/clahe.cpp | 2 + modules/imgproc/src/color.cpp | 118 ++++++++---- modules/imgproc/src/colormap.cpp | 2 + modules/imgproc/src/contours.cpp | 4 + modules/imgproc/src/convhull.cpp | 4 + modules/imgproc/src/corner.cpp | 34 ++-- modules/imgproc/src/cornersubpix.cpp | 2 + modules/imgproc/src/demosaicing.cpp | 2 + modules/imgproc/src/deriv.cpp | 54 ++++-- modules/imgproc/src/distransform.cpp | 12 +- modules/imgproc/src/drawing.cpp | 36 ++++ modules/imgproc/src/emd.cpp | 2 + modules/imgproc/src/featureselect.cpp | 2 + modules/imgproc/src/filter.cpp | 50 +++-- modules/imgproc/src/floodfill.cpp | 4 + modules/imgproc/src/generalized_hough.cpp | 2 + modules/imgproc/src/geometry.cpp | 4 + modules/imgproc/src/grabcut.cpp | 2 + modules/imgproc/src/histogram.cpp | 23 ++- modules/imgproc/src/hough.cpp | 10 +- modules/imgproc/src/imgwarp.cpp | 62 +++++-- modules/imgproc/src/intersection.cpp | 2 + modules/imgproc/src/linefit.cpp | 2 + modules/imgproc/src/lsd.cpp | 6 + modules/imgproc/src/matchcontours.cpp | 2 + modules/imgproc/src/moments.cpp | 8 +- modules/imgproc/src/morph.cpp | 16 +- modules/imgproc/src/phasecorr.cpp | 4 + modules/imgproc/src/pyramids.cpp | 12 ++ modules/imgproc/src/rotcalipers.cpp | 4 + modules/imgproc/src/samplers.cpp | 10 +- modules/imgproc/src/segmentation.cpp | 4 + modules/imgproc/src/shapedescr.cpp | 10 + modules/imgproc/src/smooth.cpp | 28 ++- modules/imgproc/src/spatialgradient.cpp | 1 + modules/imgproc/src/subdivision2d.cpp | 10 + modules/imgproc/src/sumpixels.cpp | 16 +- modules/imgproc/src/templmatch.cpp | 20 +- modules/imgproc/src/thresh.cpp | 38 ++-- modules/imgproc/src/undistort.cpp | 2 + modules/objdetect/src/cascadedetect.cpp | 24 +++ .../objdetect/src/detection_based_tracker.cpp | 2 + modules/objdetect/src/haar.cpp | 14 +- modules/objdetect/src/hog.cpp | 20 ++ modules/photo/src/align.cpp | 10 + modules/photo/src/calibrate.cpp | 4 + modules/photo/src/contrast_preserve.cpp | 2 + modules/photo/src/denoising.cpp | 12 ++ modules/photo/src/inpaint.cpp | 2 + modules/photo/src/merge.cpp | 12 ++ modules/photo/src/npr.cpp | 8 + modules/photo/src/seamless_cloning.cpp | 8 + modules/photo/src/seamless_cloning_impl.cpp | 2 + modules/photo/src/tonemap.cpp | 10 + modules/shape/src/aff_trans.cpp | 6 + modules/shape/src/emdL1.cpp | 2 + modules/shape/src/haus_dis.cpp | 2 + modules/shape/src/hist_cost.cpp | 8 + modules/shape/src/sc_dis.cpp | 4 + modules/shape/src/tps_trans.cpp | 6 + modules/stitching/src/exposure_compensate.cpp | 4 + modules/stitching/src/matchers.cpp | 6 + modules/stitching/src/seam_finders.cpp | 2 + modules/stitching/src/stitcher.cpp | 14 ++ modules/stitching/src/timelapsers.cpp | 2 + modules/superres/src/btv_l1.cpp | 8 + modules/superres/src/input_array_utility.cpp | 4 + modules/superres/src/optical_flow.cpp | 8 + modules/superres/src/super_resolution.cpp | 2 + modules/video/src/bgfg_KNN.cpp | 4 + modules/video/src/bgfg_gaussmix2.cpp | 4 + modules/video/src/camshift.cpp | 4 + modules/video/src/kalman.cpp | 4 + modules/video/src/lkpyramid.cpp | 8 + modules/video/src/optflowgf.cpp | 4 + modules/video/src/tvl1flow.cpp | 2 + modules/videoio/src/cap.cpp | 20 ++ modules/videostab/src/deblurring.cpp | 4 + modules/videostab/src/global_motion.cpp | 6 + modules/videostab/src/inpainting.cpp | 14 ++ modules/videostab/src/motion_stabilizing.cpp | 4 + modules/videostab/src/outlier_rejection.cpp | 4 + 133 files changed, 1691 insertions(+), 456 deletions(-) diff --git a/modules/calib3d/src/calibinit.cpp b/modules/calib3d/src/calibinit.cpp index 55fadcb4f0..d6f5995587 100644 --- a/modules/calib3d/src/calibinit.cpp +++ b/modules/calib3d/src/calibinit.cpp @@ -2120,6 +2120,8 @@ cvDrawChessboardCorners( CvArr* _image, CvSize pattern_size, bool cv::findChessboardCorners( InputArray _image, Size patternSize, OutputArray corners, int flags ) { + CV_INSTRUMENT_REGION() + int count = patternSize.area()*2; std::vector tmpcorners(count+1); Mat image = _image.getMat(); CvMat c_image = image; @@ -2149,6 +2151,8 @@ void cv::drawChessboardCorners( InputOutputArray _image, Size patternSize, InputArray _corners, bool patternWasFound ) { + CV_INSTRUMENT_REGION() + Mat corners = _corners.getMat(); if( corners.empty() ) return; @@ -2162,6 +2166,8 @@ void cv::drawChessboardCorners( InputOutputArray _image, Size patternSize, bool cv::findCirclesGrid( InputArray _image, Size patternSize, OutputArray _centers, int flags, const Ptr &blobDetector ) { + CV_INSTRUMENT_REGION() + bool isAsymmetricGrid = (flags & CALIB_CB_ASYMMETRIC_GRID) ? true : false; bool isSymmetricGrid = (flags & CALIB_CB_SYMMETRIC_GRID ) ? true : false; CV_Assert(isAsymmetricGrid ^ isSymmetricGrid); diff --git a/modules/calib3d/src/calibration.cpp b/modules/calib3d/src/calibration.cpp index 313c14ac05..fae4f601d7 100644 --- a/modules/calib3d/src/calibration.cpp +++ b/modules/calib3d/src/calibration.cpp @@ -2750,6 +2750,8 @@ void cv::reprojectImageTo3D( InputArray _disparity, OutputArray __3dImage, InputArray _Qmat, bool handleMissingValues, int dtype ) { + CV_INSTRUMENT_REGION() + Mat disparity = _disparity.getMat(), Q = _Qmat.getMat(); int stype = disparity.type(); @@ -3178,6 +3180,8 @@ static Mat prepareDistCoeffs(Mat& distCoeffs0, int rtype, int outputSize = 14) void cv::Rodrigues(InputArray _src, OutputArray _dst, OutputArray _jacobian) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); bool v2m = src.cols == 1 || src.rows == 1; _dst.create(3, v2m ? 3 : 1, src.depth()); @@ -3196,6 +3200,8 @@ void cv::Rodrigues(InputArray _src, OutputArray _dst, OutputArray _jacobian) void cv::matMulDeriv( InputArray _Amat, InputArray _Bmat, OutputArray _dABdA, OutputArray _dABdB ) { + CV_INSTRUMENT_REGION() + Mat A = _Amat.getMat(), B = _Bmat.getMat(); _dABdA.create(A.rows*B.cols, A.rows*A.cols, A.type()); _dABdB.create(A.rows*B.cols, B.rows*B.cols, A.type()); @@ -3330,6 +3336,8 @@ cv::Mat cv::initCameraMatrix2D( InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, Size imageSize, double aspectRatio ) { + CV_INSTRUMENT_REGION() + Mat objPt, imgPt, npoints, cameraMatrix(3, 3, CV_64F); collectCalibrationData( objectPoints, imagePoints, noArray(), objPt, imgPt, 0, npoints ); @@ -3346,6 +3354,8 @@ double cv::calibrateCamera( InputArrayOfArrays _objectPoints, Size imageSize, InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs, OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, int flags, TermCriteria criteria ) { + CV_INSTRUMENT_REGION() + return calibrateCamera(_objectPoints, _imagePoints, imageSize, _cameraMatrix, _distCoeffs, _rvecs, _tvecs, noArray(), noArray(), noArray(), flags, criteria); } @@ -3358,6 +3368,8 @@ double cv::calibrateCamera(InputArrayOfArrays _objectPoints, OutputArray stdDeviationsExtrinsics, OutputArray _perViewErrors, int flags, TermCriteria criteria ) { + CV_INSTRUMENT_REGION() + int rtype = CV_64F; Mat cameraMatrix = _cameraMatrix.getMat(); cameraMatrix = prepareCameraMatrix(cameraMatrix, rtype); @@ -3470,6 +3482,8 @@ void cv::calibrationMatrixValues( InputArray _cameraMatrix, Size imageSize, double& fovx, double& fovy, double& focalLength, Point2d& principalPoint, double& aspectRatio ) { + CV_INSTRUMENT_REGION() + if(_cameraMatrix.size() != Size(3, 3)) CV_Error(CV_StsUnmatchedSizes, "Size of cameraMatrix must be 3x3!"); @@ -3609,6 +3623,8 @@ bool cv::stereoRectifyUncalibrated( InputArray _points1, InputArray _points2, InputArray _Fmat, Size imgSize, OutputArray _Hmat1, OutputArray _Hmat2, double threshold ) { + CV_INSTRUMENT_REGION() + int rtype = CV_64F; _Hmat1.create(3, 3, rtype); _Hmat2.create(3, 3, rtype); @@ -3626,6 +3642,8 @@ cv::Mat cv::getOptimalNewCameraMatrix( InputArray _cameraMatrix, Size imgSize, double alpha, Size newImgSize, Rect* validPixROI, bool centerPrincipalPoint ) { + CV_INSTRUMENT_REGION() + Mat cameraMatrix = _cameraMatrix.getMat(), distCoeffs = _distCoeffs.getMat(); CvMat c_cameraMatrix = cameraMatrix, c_distCoeffs = distCoeffs; @@ -3646,6 +3664,8 @@ cv::Vec3d cv::RQDecomp3x3( InputArray _Mmat, OutputArray _Qy, OutputArray _Qz ) { + CV_INSTRUMENT_REGION() + Mat M = _Mmat.getMat(); _Rmat.create(3, 3, M.type()); _Qmat.create(3, 3, M.type()); @@ -3677,6 +3697,8 @@ void cv::decomposeProjectionMatrix( InputArray _projMatrix, OutputArray _cameraM OutputArray _rotMatrixX, OutputArray _rotMatrixY, OutputArray _rotMatrixZ, OutputArray _eulerAngles ) { + CV_INSTRUMENT_REGION() + Mat projMatrix = _projMatrix.getMat(); int type = projMatrix.type(); _cameraMatrix.create(3, 3, type); diff --git a/modules/calib3d/src/fisheye.cpp b/modules/calib3d/src/fisheye.cpp index 45fe230db9..f7e210e153 100644 --- a/modules/calib3d/src/fisheye.cpp +++ b/modules/calib3d/src/fisheye.cpp @@ -62,12 +62,16 @@ namespace cv { namespace void cv::fisheye::projectPoints(InputArray objectPoints, OutputArray imagePoints, const Affine3d& affine, InputArray K, InputArray D, double alpha, OutputArray jacobian) { + CV_INSTRUMENT_REGION() + projectPoints(objectPoints, imagePoints, affine.rvec(), affine.translation(), K, D, alpha, jacobian); } void cv::fisheye::projectPoints(InputArray objectPoints, OutputArray imagePoints, InputArray _rvec, InputArray _tvec, InputArray _K, InputArray _D, double alpha, OutputArray jacobian) { + CV_INSTRUMENT_REGION() + // will support only 3-channel data now for points CV_Assert(objectPoints.type() == CV_32FC3 || objectPoints.type() == CV_64FC3); imagePoints.create(objectPoints.size(), CV_MAKETYPE(objectPoints.depth(), 2)); @@ -249,6 +253,8 @@ void cv::fisheye::projectPoints(InputArray objectPoints, OutputArray imagePoints void cv::fisheye::distortPoints(InputArray undistorted, OutputArray distorted, InputArray K, InputArray D, double alpha) { + CV_INSTRUMENT_REGION() + // will support only 2-channel data now for points CV_Assert(undistorted.type() == CV_32FC2 || undistorted.type() == CV_64FC2); distorted.create(undistorted.size(), undistorted.type()); @@ -311,6 +317,8 @@ void cv::fisheye::distortPoints(InputArray undistorted, OutputArray distorted, I void cv::fisheye::undistortPoints( InputArray distorted, OutputArray undistorted, InputArray K, InputArray D, InputArray R, InputArray P) { + CV_INSTRUMENT_REGION() + // will support only 2-channel data now for points CV_Assert(distorted.type() == CV_32FC2 || distorted.type() == CV_64FC2); undistorted.create(distorted.size(), distorted.type()); @@ -401,6 +409,8 @@ void cv::fisheye::undistortPoints( InputArray distorted, OutputArray undistorted void cv::fisheye::initUndistortRectifyMap( InputArray K, InputArray D, InputArray R, InputArray P, const cv::Size& size, int m1type, OutputArray map1, OutputArray map2 ) { + CV_INSTRUMENT_REGION() + CV_Assert( m1type == CV_16SC2 || m1type == CV_32F || m1type <=0 ); map1.create( size, m1type <= 0 ? CV_16SC2 : m1type ); map2.create( size, map1.type() == CV_16SC2 ? CV_16UC1 : CV_32F ); @@ -497,6 +507,8 @@ void cv::fisheye::initUndistortRectifyMap( InputArray K, InputArray D, InputArra void cv::fisheye::undistortImage(InputArray distorted, OutputArray undistorted, InputArray K, InputArray D, InputArray Knew, const Size& new_size) { + CV_INSTRUMENT_REGION() + Size size = new_size.area() != 0 ? new_size : distorted.size(); cv::Mat map1, map2; @@ -511,6 +523,8 @@ void cv::fisheye::undistortImage(InputArray distorted, OutputArray undistorted, void cv::fisheye::estimateNewCameraMatrixForUndistortRectify(InputArray K, InputArray D, const Size &image_size, InputArray R, OutputArray P, double balance, const Size& new_size, double fov_scale) { + CV_INSTRUMENT_REGION() + CV_Assert( K.size() == Size(3, 3) && (K.depth() == CV_32F || K.depth() == CV_64F)); CV_Assert(D.empty() || ((D.total() == 4) && (D.depth() == CV_32F || D.depth() == CV_64F))); @@ -609,6 +623,8 @@ void cv::fisheye::stereoRectify( InputArray K1, InputArray D1, InputArray K2, In InputArray _R, InputArray _tvec, OutputArray R1, OutputArray R2, OutputArray P1, OutputArray P2, OutputArray Q, int flags, const Size& newImageSize, double balance, double fov_scale) { + CV_INSTRUMENT_REGION() + CV_Assert((_R.size() == Size(3, 3) || _R.total() * _R.channels() == 3) && (_R.depth() == CV_32F || _R.depth() == CV_64F)); CV_Assert(_tvec.total() * _tvec.channels() == 3 && (_tvec.depth() == CV_32F || _tvec.depth() == CV_64F)); @@ -691,6 +707,8 @@ double cv::fisheye::calibrate(InputArrayOfArrays objectPoints, InputArrayOfArray InputOutputArray K, InputOutputArray D, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags , cv::TermCriteria criteria) { + CV_INSTRUMENT_REGION() + CV_Assert(!objectPoints.empty() && !imagePoints.empty() && objectPoints.total() == imagePoints.total()); CV_Assert(objectPoints.type() == CV_32FC3 || objectPoints.type() == CV_64FC3); CV_Assert(imagePoints.type() == CV_32FC2 || imagePoints.type() == CV_64FC2); @@ -828,6 +846,8 @@ double cv::fisheye::stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayO InputOutputArray K1, InputOutputArray D1, InputOutputArray K2, InputOutputArray D2, Size imageSize, OutputArray R, OutputArray T, int flags, TermCriteria criteria) { + CV_INSTRUMENT_REGION() + CV_Assert(!objectPoints.empty() && !imagePoints1.empty() && !imagePoints2.empty()); CV_Assert(objectPoints.total() == imagePoints1.total() || imagePoints1.total() == imagePoints2.total()); CV_Assert(objectPoints.type() == CV_32FC3 || objectPoints.type() == CV_64FC3); @@ -1150,6 +1170,8 @@ void cv::internal::projectPoints(cv::InputArray objectPoints, cv::OutputArray im cv::InputArray _rvec,cv::InputArray _tvec, const IntrinsicParams& param, cv::OutputArray jacobian) { + CV_INSTRUMENT_REGION() + CV_Assert(!objectPoints.empty() && objectPoints.type() == CV_64FC3); Matx33d K(param.f[0], param.f[0] * param.alpha, param.c[0], 0, param.f[1], param.c[1], @@ -1202,6 +1224,8 @@ void cv::internal::ComputeExtrinsicRefine(const Mat& imagePoints, const Mat& obj cv::Mat cv::internal::ComputeHomography(Mat m, Mat M) { + CV_INSTRUMENT_REGION() + int Np = m.cols; if (m.rows < 3) @@ -1301,6 +1325,8 @@ cv::Mat cv::internal::ComputeHomography(Mat m, Mat M) cv::Mat cv::internal::NormalizePixels(const Mat& imagePoints, const IntrinsicParams& param) { + CV_INSTRUMENT_REGION() + CV_Assert(!imagePoints.empty() && imagePoints.type() == CV_64FC2); Mat distorted((int)imagePoints.total(), 1, CV_64FC2), undistorted; diff --git a/modules/calib3d/src/five-point.cpp b/modules/calib3d/src/five-point.cpp index 92e652b0e8..1d39e20f87 100644 --- a/modules/calib3d/src/five-point.cpp +++ b/modules/calib3d/src/five-point.cpp @@ -405,6 +405,8 @@ protected: cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, InputArray _cameraMatrix, int method, double prob, double threshold, OutputArray _mask) { + CV_INSTRUMENT_REGION() + Mat points1, points2, cameraMatrix; _points1.getMat().convertTo(points1, CV_64F); _points2.getMat().convertTo(points2, CV_64F); @@ -450,6 +452,8 @@ cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, InputArr cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, double focal, Point2d pp, int method, double prob, double threshold, OutputArray _mask) { + CV_INSTRUMENT_REGION() + Mat cameraMatrix = (Mat_(3,3) << focal, 0, pp.x, 0, focal, pp.y, 0, 0, 1); return cv::findEssentialMat(_points1, _points2, cameraMatrix, method, prob, threshold, _mask); } @@ -457,6 +461,8 @@ cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, double f int cv::recoverPose( InputArray E, InputArray _points1, InputArray _points2, InputArray _cameraMatrix, OutputArray _R, OutputArray _t, InputOutputArray _mask) { + CV_INSTRUMENT_REGION() + Mat points1, points2, cameraMatrix; _points1.getMat().convertTo(points1, CV_64F); _points2.getMat().convertTo(points2, CV_64F); @@ -616,6 +622,8 @@ int cv::recoverPose( InputArray E, InputArray _points1, InputArray _points2, Out void cv::decomposeEssentialMat( InputArray _E, OutputArray _R1, OutputArray _R2, OutputArray _t ) { + CV_INSTRUMENT_REGION() + Mat E = _E.getMat().reshape(1, 3); CV_Assert(E.cols == 3 && E.rows == 3); diff --git a/modules/calib3d/src/fundam.cpp b/modules/calib3d/src/fundam.cpp index 4a7db9689d..cdcbeadd77 100644 --- a/modules/calib3d/src/fundam.cpp +++ b/modules/calib3d/src/fundam.cpp @@ -343,6 +343,8 @@ cv::Mat cv::findHomography( InputArray _points1, InputArray _points2, int method, double ransacReprojThreshold, OutputArray _mask, const int maxIters, const double confidence) { + CV_INSTRUMENT_REGION() + const double defaultRANSACReprojThreshold = 3; bool result = false; @@ -714,6 +716,8 @@ cv::Mat cv::findFundamentalMat( InputArray _points1, InputArray _points2, int method, double param1, double param2, OutputArray _mask ) { + CV_INSTRUMENT_REGION() + Mat points1 = _points1.getMat(), points2 = _points2.getMat(); Mat m1, m2, F; int npoints = -1; @@ -783,6 +787,8 @@ cv::Mat cv::findFundamentalMat( InputArray _points1, InputArray _points2, void cv::computeCorrespondEpilines( InputArray _points, int whichImage, InputArray _Fmat, OutputArray _lines ) { + CV_INSTRUMENT_REGION() + double f[9]; Mat tempF(3, 3, CV_64F, f); Mat points = _points.getMat(), F = _Fmat.getMat(); @@ -856,6 +862,8 @@ void cv::computeCorrespondEpilines( InputArray _points, int whichImage, void cv::convertPointsFromHomogeneous( InputArray _src, OutputArray _dst ) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); if( !src.isContinuous() ) src = src.clone(); @@ -955,6 +963,8 @@ void cv::convertPointsFromHomogeneous( InputArray _src, OutputArray _dst ) void cv::convertPointsToHomogeneous( InputArray _src, OutputArray _dst ) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); if( !src.isContinuous() ) src = src.clone(); @@ -1036,6 +1046,8 @@ void cv::convertPointsToHomogeneous( InputArray _src, OutputArray _dst ) void cv::convertPointsHomogeneous( InputArray _src, OutputArray _dst ) { + CV_INSTRUMENT_REGION() + int stype = _src.type(), dtype = _dst.type(); CV_Assert( _dst.fixedType() ); @@ -1045,7 +1057,10 @@ void cv::convertPointsHomogeneous( InputArray _src, OutputArray _dst ) convertPointsToHomogeneous(_src, _dst); } -double cv::sampsonDistance(InputArray _pt1, InputArray _pt2, InputArray _F) { +double cv::sampsonDistance(InputArray _pt1, InputArray _pt2, InputArray _F) +{ + CV_INSTRUMENT_REGION() + CV_Assert(_pt1.type() == CV_64F && _pt2.type() == CV_64F && _F.type() == CV_64F); CV_DbgAssert(_pt1.rows() == 3 && _F.size() == Size(3, 3) && _pt1.rows() == _pt2.rows()); diff --git a/modules/calib3d/src/p3p.cpp b/modules/calib3d/src/p3p.cpp index 882868d6b8..f91925b219 100644 --- a/modules/calib3d/src/p3p.cpp +++ b/modules/calib3d/src/p3p.cpp @@ -33,6 +33,8 @@ p3p::p3p(double _fx, double _fy, double _cx, double _cy) bool p3p::solve(cv::Mat& R, cv::Mat& tvec, const cv::Mat& opoints, const cv::Mat& ipoints) { + CV_INSTRUMENT_REGION() + double rotation_matrix[3][3], translation[3]; std::vector points; if (opoints.depth() == ipoints.depth()) diff --git a/modules/calib3d/src/ptsetreg.cpp b/modules/calib3d/src/ptsetreg.cpp index 463027d510..830fa8ae1a 100644 --- a/modules/calib3d/src/ptsetreg.cpp +++ b/modules/calib3d/src/ptsetreg.cpp @@ -507,6 +507,8 @@ int cv::estimateAffine3D(InputArray _from, InputArray _to, OutputArray _out, OutputArray _inliers, double param1, double param2) { + CV_INSTRUMENT_REGION() + Mat from = _from.getMat(), to = _to.getMat(); int count = from.checkVector(3); diff --git a/modules/calib3d/src/quadsubpix.cpp b/modules/calib3d/src/quadsubpix.cpp index 2e98a462b5..a640a67e40 100644 --- a/modules/calib3d/src/quadsubpix.cpp +++ b/modules/calib3d/src/quadsubpix.cpp @@ -163,6 +163,8 @@ static int segment_hist_max(const Mat& hist, int& low_thresh, int& high_thresh) bool cv::find4QuadCornerSubpix(InputArray _img, InputOutputArray _corners, Size region_size) { + CV_INSTRUMENT_REGION() + Mat img = _img.getMat(), cornersM = _corners.getMat(); int ncorners = cornersM.checkVector(2, CV_32F); CV_Assert( ncorners >= 0 ); diff --git a/modules/calib3d/src/solvepnp.cpp b/modules/calib3d/src/solvepnp.cpp index 12dcb4a6ca..84a3256739 100644 --- a/modules/calib3d/src/solvepnp.cpp +++ b/modules/calib3d/src/solvepnp.cpp @@ -56,6 +56,8 @@ bool solvePnP( InputArray _opoints, InputArray _ipoints, InputArray _cameraMatrix, InputArray _distCoeffs, OutputArray _rvec, OutputArray _tvec, bool useExtrinsicGuess, int flags ) { + CV_INSTRUMENT_REGION() + Mat opoints = _opoints.getMat(), ipoints = _ipoints.getMat(); int npoints = std::max(opoints.checkVector(3, CV_32F), opoints.checkVector(3, CV_64F)); CV_Assert( npoints >= 0 && npoints == std::max(ipoints.checkVector(2, CV_32F), ipoints.checkVector(2, CV_64F)) ); @@ -214,6 +216,7 @@ bool solvePnPRansac(InputArray _opoints, InputArray _ipoints, int iterationsCount, float reprojectionError, double confidence, OutputArray _inliers, int flags) { + CV_INSTRUMENT_REGION() Mat opoints0 = _opoints.getMat(), ipoints0 = _ipoints.getMat(); Mat opoints, ipoints; diff --git a/modules/calib3d/src/stereobm.cpp b/modules/calib3d/src/stereobm.cpp index c4278b3617..3c868b97a7 100644 --- a/modules/calib3d/src/stereobm.cpp +++ b/modules/calib3d/src/stereobm.cpp @@ -1061,6 +1061,8 @@ public: void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) { + CV_INSTRUMENT_REGION() + int dtype = disparr.fixedType() ? disparr.type() : params.dispType; Size leftsize = leftarr.size(); diff --git a/modules/calib3d/src/stereosgbm.cpp b/modules/calib3d/src/stereosgbm.cpp index c7dd8b9fcd..cb14a1c89a 100644 --- a/modules/calib3d/src/stereosgbm.cpp +++ b/modules/calib3d/src/stereosgbm.cpp @@ -1494,6 +1494,8 @@ public: void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) { + CV_INSTRUMENT_REGION() + Mat left = leftarr.getMat(), right = rightarr.getMat(); CV_Assert( left.size() == right.size() && left.type() == right.type() && left.depth() == CV_8U ); @@ -1728,6 +1730,8 @@ void filterSpecklesImpl(cv::Mat& img, int newVal, int maxSpeckleSize, int maxDif #ifdef HAVE_IPP static bool ipp_filterSpeckles(Mat &img, int maxSpeckleSize, int newVal, int maxDiff) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 810 int type = img.type(); Ipp32s bufsize = 0; @@ -1745,12 +1749,12 @@ static bool ipp_filterSpeckles(Mat &img, int maxSpeckleSize, int newVal, int max if (type == CV_8UC1) { - status = ippiMarkSpeckles_8u_C1IR(img.ptr(), (int)img.step, roisize, + status = CV_INSTRUMENT_FUN_IPP(ippiMarkSpeckles_8u_C1IR, img.ptr(), (int)img.step, roisize, (Ipp8u)newVal, maxSpeckleSize, (Ipp8u)maxDiff, ippiNormL1, pBuffer); } else { - status = ippiMarkSpeckles_16s_C1IR(img.ptr(), (int)img.step, roisize, + status = CV_INSTRUMENT_FUN_IPP(ippiMarkSpeckles_16s_C1IR, img.ptr(), (int)img.step, roisize, (Ipp16s)newVal, maxSpeckleSize, (Ipp16s)maxDiff, ippiNormL1, pBuffer); } if(pBuffer) ippFree(pBuffer); @@ -1769,6 +1773,8 @@ static bool ipp_filterSpeckles(Mat &img, int maxSpeckleSize, int newVal, int max void cv::filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSize, double _maxDiff, InputOutputArray __buf ) { + CV_INSTRUMENT_REGION() + Mat img = _img.getMat(); int type = img.type(); Mat temp, &_buf = __buf.needed() ? __buf.getMatRef() : temp; @@ -1787,6 +1793,8 @@ void cv::filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSi void cv::validateDisparity( InputOutputArray _disp, InputArray _cost, int minDisparity, int numberOfDisparities, int disp12MaxDiff ) { + CV_INSTRUMENT_REGION() + Mat disp = _disp.getMat(), cost = _cost.getMat(); int cols = disp.cols, rows = disp.rows; int minD = minDisparity, maxD = minDisparity + numberOfDisparities; diff --git a/modules/calib3d/src/triangulate.cpp b/modules/calib3d/src/triangulate.cpp index 0fa5e3d9ef..33c7fd774d 100644 --- a/modules/calib3d/src/triangulate.cpp +++ b/modules/calib3d/src/triangulate.cpp @@ -393,6 +393,8 @@ void cv::triangulatePoints( InputArray _projMatr1, InputArray _projMatr2, InputArray _projPoints1, InputArray _projPoints2, OutputArray _points4D ) { + CV_INSTRUMENT_REGION() + Mat matr1 = _projMatr1.getMat(), matr2 = _projMatr2.getMat(); Mat points1 = _projPoints1.getMat(), points2 = _projPoints2.getMat(); @@ -414,6 +416,8 @@ void cv::triangulatePoints( InputArray _projMatr1, InputArray _projMatr2, void cv::correctMatches( InputArray _F, InputArray _points1, InputArray _points2, OutputArray _newPoints1, OutputArray _newPoints2 ) { + CV_INSTRUMENT_REGION() + Mat F = _F.getMat(); Mat points1 = _points1.getMat(), points2 = _points2.getMat(); diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index 911f779f38..ba1f5c3c74 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -1096,11 +1096,6 @@ enum FLAGS_MAPPING = 0x01, }; -enum -{ - COMMAND_RESET = 0x01, -}; - class CV_EXPORTS NodeData { public: diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index fc20a18311..4b1c67339b 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -369,58 +369,78 @@ static BinaryFuncC* getMinTab() void cv::bitwise_and(InputArray a, InputArray b, OutputArray c, InputArray mask) { + CV_INSTRUMENT_REGION() + BinaryFuncC f = (BinaryFuncC)GET_OPTIMIZED(cv::hal::and8u); binary_op(a, b, c, mask, &f, true, OCL_OP_AND); } void cv::bitwise_or(InputArray a, InputArray b, OutputArray c, InputArray mask) { + CV_INSTRUMENT_REGION() + BinaryFuncC f = (BinaryFuncC)GET_OPTIMIZED(cv::hal::or8u); binary_op(a, b, c, mask, &f, true, OCL_OP_OR); } void cv::bitwise_xor(InputArray a, InputArray b, OutputArray c, InputArray mask) { + CV_INSTRUMENT_REGION() + BinaryFuncC f = (BinaryFuncC)GET_OPTIMIZED(cv::hal::xor8u); binary_op(a, b, c, mask, &f, true, OCL_OP_XOR); } void cv::bitwise_not(InputArray a, OutputArray c, InputArray mask) { + CV_INSTRUMENT_REGION() + BinaryFuncC f = (BinaryFuncC)GET_OPTIMIZED(cv::hal::not8u); binary_op(a, a, c, mask, &f, true, OCL_OP_NOT); } void cv::max( InputArray src1, InputArray src2, OutputArray dst ) { + CV_INSTRUMENT_REGION() + binary_op(src1, src2, dst, noArray(), getMaxTab(), false, OCL_OP_MAX ); } void cv::min( InputArray src1, InputArray src2, OutputArray dst ) { + CV_INSTRUMENT_REGION() + binary_op(src1, src2, dst, noArray(), getMinTab(), false, OCL_OP_MIN ); } void cv::max(const Mat& src1, const Mat& src2, Mat& dst) { + CV_INSTRUMENT_REGION() + OutputArray _dst(dst); binary_op(src1, src2, _dst, noArray(), getMaxTab(), false, OCL_OP_MAX ); } void cv::min(const Mat& src1, const Mat& src2, Mat& dst) { + CV_INSTRUMENT_REGION() + OutputArray _dst(dst); binary_op(src1, src2, _dst, noArray(), getMinTab(), false, OCL_OP_MIN ); } void cv::max(const UMat& src1, const UMat& src2, UMat& dst) { + CV_INSTRUMENT_REGION() + OutputArray _dst(dst); binary_op(src1, src2, _dst, noArray(), getMaxTab(), false, OCL_OP_MAX ); } void cv::min(const UMat& src1, const UMat& src2, UMat& dst) { + CV_INSTRUMENT_REGION() + OutputArray _dst(dst); binary_op(src1, src2, _dst, noArray(), getMinTab(), false, OCL_OP_MIN ); } @@ -901,12 +921,16 @@ static BinaryFuncC* getAbsDiffTab() void cv::add( InputArray src1, InputArray src2, OutputArray dst, InputArray mask, int dtype ) { + CV_INSTRUMENT_REGION() + arithm_op(src1, src2, dst, mask, dtype, getAddTab(), false, 0, OCL_OP_ADD ); } void cv::subtract( InputArray _src1, InputArray _src2, OutputArray _dst, InputArray mask, int dtype ) { + CV_INSTRUMENT_REGION() + #ifdef HAVE_TEGRA_OPTIMIZATION if (tegra::useTegra()) { @@ -965,6 +989,8 @@ void cv::subtract( InputArray _src1, InputArray _src2, OutputArray _dst, void cv::absdiff( InputArray src1, InputArray src2, OutputArray dst ) { + CV_INSTRUMENT_REGION() + arithm_op(src1, src2, dst, noArray(), -1, getAbsDiffTab(), false, 0, OCL_OP_ABSDIFF); } @@ -1016,6 +1042,8 @@ static BinaryFuncC* getRecipTab() void cv::multiply(InputArray src1, InputArray src2, OutputArray dst, double scale, int dtype) { + CV_INSTRUMENT_REGION() + arithm_op(src1, src2, dst, noArray(), dtype, getMulTab(), true, &scale, std::abs(scale - 1.0) < DBL_EPSILON ? OCL_OP_MUL : OCL_OP_MUL_SCALE); } @@ -1023,12 +1051,16 @@ void cv::multiply(InputArray src1, InputArray src2, void cv::divide(InputArray src1, InputArray src2, OutputArray dst, double scale, int dtype) { + CV_INSTRUMENT_REGION() + arithm_op(src1, src2, dst, noArray(), dtype, getDivTab(), true, &scale, OCL_OP_DIV_SCALE); } void cv::divide(double scale, InputArray src2, OutputArray dst, int dtype) { + CV_INSTRUMENT_REGION() + arithm_op(src2, src2, dst, noArray(), dtype, getRecipTab(), true, &scale, OCL_OP_RECIP_SCALE); } @@ -1056,6 +1088,8 @@ static BinaryFuncC* getAddWeightedTab() void cv::addWeighted( InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype ) { + CV_INSTRUMENT_REGION() + double scalars[] = {alpha, beta, gamma}; arithm_op(src1, src2, dst, noArray(), dtype, getAddWeightedTab(), true, scalars, OCL_OP_ADDW); } @@ -1194,6 +1228,8 @@ static bool ocl_compare(InputArray _src1, InputArray _src2, OutputArray _dst, in void cv::compare(InputArray _src1, InputArray _src2, OutputArray _dst, int op) { + CV_INSTRUMENT_REGION() + CV_Assert( op == CMP_LT || op == CMP_LE || op == CMP_EQ || op == CMP_NE || op == CMP_GE || op == CMP_GT ); @@ -1889,6 +1925,8 @@ static bool ocl_inRange( InputArray _src, InputArray _lowerb, void cv::inRange(InputArray _src, InputArray _lowerb, InputArray _upperb, OutputArray _dst) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_src.dims() <= 2 && _lowerb.dims() <= 2 && _upperb.dims() <= 2 && OCL_PERFORMANCE_CHECK(_dst.isUMat()), ocl_inRange(_src, _lowerb, _upperb, _dst)) @@ -2274,7 +2312,7 @@ static inline void fixSteps(int width, int height, size_t elemSize, size_t& step CV_IPP_CHECK() \ { \ fixSteps(width, height, sizeof(dst[0]), step1, step2, step); \ - if (0 <= fun(src1, (int)step1, src2, (int)step2, dst, (int)step, ippiSize(width, height), 0)) \ + if (0 <= CV_INSTRUMENT_FUN_IPP(fun, src1, (int)step1, src2, (int)step2, dst, (int)step, ippiSize(width, height), 0)) \ { \ CV_IMPL_ADD(CV_IMPL_IPP); \ return; \ @@ -2286,7 +2324,7 @@ static inline void fixSteps(int width, int height, size_t elemSize, size_t& step CV_IPP_CHECK() \ { \ fixSteps(width, height, sizeof(dst[0]), step1, step2, step); \ - if (0 <= fun(src2, (int)step2, src1, (int)step1, dst, (int)step, ippiSize(width, height), 0)) \ + if (0 <= CV_INSTRUMENT_FUN_IPP(fun, src2, (int)step2, src1, (int)step1, dst, (int)step, ippiSize(width, height), 0)) \ { \ CV_IMPL_ADD(CV_IMPL_IPP); \ return; \ @@ -2298,7 +2336,7 @@ static inline void fixSteps(int width, int height, size_t elemSize, size_t& step CV_IPP_CHECK() \ { \ fixSteps(width, height, sizeof(dst[0]), step1, step2, step); \ - if (0 <= fun(src1, (int)step1, src2, (int)step2, dst, (int)step, ippiSize(width, height))) \ + if (0 <= CV_INSTRUMENT_FUN_IPP(fun, src1, (int)step1, src2, (int)step2, dst, (int)step, ippiSize(width, height))) \ { \ CV_IMPL_ADD(CV_IMPL_IPP); \ return; \ @@ -2310,7 +2348,7 @@ static inline void fixSteps(int width, int height, size_t elemSize, size_t& step CV_IPP_CHECK() \ { \ fixSteps(width, height, sizeof(dst[0]), step1, step2, step); \ - if (0 <= fun(src2, (int)step2, src1, (int)step1, dst, (int)step, ippiSize(width, height))) \ + if (0 <= CV_INSTRUMENT_FUN_IPP(fun, src2, (int)step2, src1, (int)step1, dst, (int)step, ippiSize(width, height))) \ { \ CV_IMPL_ADD(CV_IMPL_IPP); \ return; \ @@ -2467,7 +2505,7 @@ void sub64f( const double* src1, size_t step1, int i = 0; \ for(; i < height; i++) \ { \ - if (0 > fun(s1, s2, d, width)) \ + if (0 > CV_INSTRUMENT_FUN_IPP(fun, s1, s2, d, width)) \ break; \ s1 = (type*)((uchar*)s1 + step1); \ s2 = (type*)((uchar*)s2 + step2); \ @@ -2684,7 +2722,7 @@ void absdiff64f( const double* src1, size_t step1, CV_IPP_CHECK() \ { \ fixSteps(width, height, sizeof(dst[0]), step1, step2, step); (void)src2; \ - if (0 <= fun(src1, (int)step1, dst, (int)step, ippiSize(width, height))) \ + if (0 <= CV_INSTRUMENT_FUN_IPP(fun, src1, (int)step1, dst, (int)step, ippiSize(width, height))) \ { \ CV_IMPL_ADD(CV_IMPL_IPP); \ return; \ @@ -2750,7 +2788,7 @@ inline static IppCmpOp convert_cmp(int _cmpop) if( op >= 0 ) \ { \ fixSteps(width, height, sizeof(dst[0]), step1, step2, step); \ - if (0 <= fun(src1, (int)step1, src2, (int)step2, dst, (int)step, ippiSize(width, height), op)) \ + if (0 <= CV_INSTRUMENT_FUN_IPP(fun, src1, (int)step1, src2, (int)step2, dst, (int)step, ippiSize(width, height), op)) \ { \ CV_IMPL_ADD(CV_IMPL_IPP); \ return; \ @@ -3023,7 +3061,7 @@ void cmp64f(const double* src1, size_t step1, const double* src2, size_t step2, { \ if (std::fabs(fscale - 1) <= FLT_EPSILON) \ { \ - if (fun(src1, (int)step1, src2, (int)step2, dst, (int)step, ippiSize(width, height), 0) >= 0) \ + if (CV_INSTRUMENT_FUN_IPP(fun, src1, (int)step1, src2, (int)step2, dst, (int)step, ippiSize(width, height), 0) >= 0) \ { \ CV_IMPL_ADD(CV_IMPL_IPP); \ return; \ @@ -3037,7 +3075,7 @@ void cmp64f(const double* src1, size_t step1, const double* src2, size_t step2, { \ if (std::fabs(fscale - 1) <= FLT_EPSILON) \ { \ - if (fun(src1, (int)step1, src2, (int)step2, dst, (int)step, ippiSize(width, height)) >= 0) \ + if (CV_INSTRUMENT_FUN_IPP(fun, src1, (int)step1, src2, (int)step2, dst, (int)step, ippiSize(width, height)) >= 0) \ { \ CV_IMPL_ADD(CV_IMPL_IPP); \ return; \ diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 1b7f77cb8d..a547777cba 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -84,6 +84,8 @@ static MergeFunc getMergeFunc(int depth) void cv::split(const Mat& src, Mat* mv) { + CV_INSTRUMENT_REGION() + int k, depth = src.depth(), cn = src.channels(); if( cn == 1 ) { @@ -176,6 +178,8 @@ static bool ocl_split( InputArray _m, OutputArrayOfArrays _mv ) void cv::split(InputArray _m, OutputArrayOfArrays _mv) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_m.dims() <= 2 && _mv.isUMatVector(), ocl_split(_m, _mv)) @@ -201,6 +205,8 @@ void cv::split(InputArray _m, OutputArrayOfArrays _mv) void cv::merge(const Mat* mv, size_t n, OutputArray _dst) { + CV_INSTRUMENT_REGION() + CV_Assert( mv && n > 0 ); int depth = mv[0].depth(); @@ -345,6 +351,8 @@ static bool ocl_merge( InputArrayOfArrays _mv, OutputArray _dst ) void cv::merge(InputArrayOfArrays _mv, OutputArray _dst) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_mv.isUMatVector() && _dst.isUMat(), ocl_merge(_mv, _dst)) @@ -439,6 +447,8 @@ static MixChannelsFunc getMixchFunc(int depth) void cv::mixChannels( const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const int* fromTo, size_t npairs ) { + CV_INSTRUMENT_REGION() + if( npairs == 0 ) return; CV_Assert( src && nsrcs > 0 && dst && ndsts > 0 && fromTo && npairs > 0 ); @@ -615,6 +625,8 @@ static bool ocl_mixChannels(InputArrayOfArrays _src, InputOutputArrayOfArrays _d void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, const int* fromTo, size_t npairs) { + CV_INSTRUMENT_REGION() + if (npairs == 0 || fromTo == NULL) return; @@ -644,6 +656,8 @@ void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, const std::vector& fromTo) { + CV_INSTRUMENT_REGION() + if (fromTo.empty()) return; @@ -672,6 +686,8 @@ void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, void cv::extractChannel(InputArray _src, OutputArray _dst, int coi) { + CV_INSTRUMENT_REGION() + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); CV_Assert( 0 <= coi && coi < cn ); int ch[] = { coi, 0 }; @@ -693,6 +709,8 @@ void cv::extractChannel(InputArray _src, OutputArray _dst, int coi) void cv::insertChannel(InputArray _src, InputOutputArray _dst, int coi) { + CV_INSTRUMENT_REGION() + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype); int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype); CV_Assert( _src.sameSize(_dst) && sdepth == ddepth ); @@ -4777,7 +4795,7 @@ dtype* dst, size_t dstep, Size size, double* scale) \ static void cvt##suffix( const stype* src, size_t sstep, const uchar*, size_t, \ dtype* dst, size_t dstep, Size size, double*) \ { \ - CV_IPP_RUN(src && dst, ippiConvert_##ippFavor(src, (int)sstep, dst, (int)dstep, ippiSize(size.width, size.height)) >= 0)\ + CV_IPP_RUN(src && dst, CV_INSTRUMENT_FUN_IPP(ippiConvert_##ippFavor, src, (int)sstep, dst, (int)dstep, ippiSize(size.width, size.height)) >= 0) \ cvt_(src, sstep, dst, dstep, size); \ } @@ -4785,7 +4803,7 @@ static void cvt##suffix( const stype* src, size_t sstep, const uchar*, size_t, \ static void cvt##suffix( const stype* src, size_t sstep, const uchar*, size_t, \ dtype* dst, size_t dstep, Size size, double*) \ { \ - CV_IPP_RUN(src && dst, ippiConvert_##ippFavor(src, (int)sstep, dst, (int)dstep, ippiSize(size.width, size.height), ippRndFinancial, 0) >= 0)\ + CV_IPP_RUN(src && dst, CV_INSTRUMENT_FUN_IPP(ippiConvert_##ippFavor, src, (int)sstep, dst, (int)dstep, ippiSize(size.width, size.height), ippRndFinancial, 0) >= 0) \ cvt_(src, sstep, dst, dstep, size); \ } #else @@ -5112,6 +5130,8 @@ static bool ocl_convertScaleAbs( InputArray _src, OutputArray _dst, double alpha void cv::convertScaleAbs( InputArray _src, OutputArray _dst, double alpha, double beta ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), ocl_convertScaleAbs(_src, _dst, alpha, beta)) @@ -5142,6 +5162,8 @@ void cv::convertScaleAbs( InputArray _src, OutputArray _dst, double alpha, doubl void cv::convertFp16( InputArray _src, OutputArray _dst) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); int ddepth = 0; @@ -5184,6 +5206,8 @@ void cv::convertFp16( InputArray _src, OutputArray _dst) void cv::Mat::convertTo(OutputArray _dst, int _type, double alpha, double beta) const { + CV_INSTRUMENT_REGION() + bool noScale = fabs(alpha-1) < DBL_EPSILON && fabs(beta) < DBL_EPSILON; if( _type < 0 ) @@ -5408,7 +5432,7 @@ public: CV_DbgAssert(lutcn == 3 || lutcn == 4); if (lutcn == 3) { - IppStatus status = ippiCopy_8u_C3P3R(lut.ptr(), (int)lut.step[0], lutTable, (int)lut.step[0], sz256); + IppStatus status = CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C3P3R, lut.ptr(), (int)lut.step[0], lutTable, (int)lut.step[0], sz256); if (status < 0) { setIppErrorStatus(); @@ -5418,7 +5442,7 @@ public: } else if (lutcn == 4) { - IppStatus status = ippiCopy_8u_C4P4R(lut.ptr(), (int)lut.step[0], lutTable, (int)lut.step[0], sz256); + IppStatus status = CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C4P4R, lut.ptr(), (int)lut.step[0], lutTable, (int)lut.step[0], sz256); if (status < 0) { setIppErrorStatus(); @@ -5451,7 +5475,7 @@ public: if (lutcn == 3) { - if (ippiLUTPalette_8u_C3R( + if (CV_INSTRUMENT_FUN_IPP(ippiLUTPalette_8u_C3R, src.ptr(), (int)src.step[0], dst.ptr(), (int)dst.step[0], ippiSize(dst.size()), lutTable, 8) >= 0) { @@ -5461,7 +5485,7 @@ public: } else if (lutcn == 4) { - if (ippiLUTPalette_8u_C4R( + if (CV_INSTRUMENT_FUN_IPP(ippiLUTPalette_8u_C4R, src.ptr(), (int)src.step[0], dst.ptr(), (int)dst.step[0], ippiSize(dst.size()), lutTable, 8) >= 0) { @@ -5480,6 +5504,8 @@ private: static bool ipp_lut(Mat &src, Mat &lut, Mat &dst) { + CV_INSTRUMENT_REGION_IPP() + int lutcn = lut.channels(); if(src.dims > 2) @@ -5565,6 +5591,8 @@ private: void cv::LUT( InputArray _src, InputArray _lut, OutputArray _dst ) { + CV_INSTRUMENT_REGION() + int cn = _src.channels(), depth = _src.depth(); int lutcn = _lut.channels(); @@ -5712,6 +5740,8 @@ static bool ocl_normalize( InputArray _src, InputOutputArray _dst, InputArray _m void cv::normalize( InputArray _src, InputOutputArray _dst, double a, double b, int norm_type, int rtype, InputArray _mask ) { + CV_INSTRUMENT_REGION() + double scale = 1, shift = 0; if( norm_type == CV_MINMAX ) { diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index 5acb1dac0a..7149b8f37f 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -82,7 +82,7 @@ copyMask_(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, ucha template<> void copyMask_(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size) { - CV_IPP_RUN(true, ippiCopy_8u_C1MR(_src, (int)sstep, _dst, (int)dstep, ippiSize(size), mask, (int)mstep) >= 0) + CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1MR, _src, (int)sstep, _dst, (int)dstep, ippiSize(size), mask, (int)mstep) >= 0) for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep ) { @@ -122,7 +122,7 @@ copyMask_(const uchar* _src, size_t sstep, const uchar* mask, size_t mste template<> void copyMask_(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size) { - CV_IPP_RUN(true, ippiCopy_16u_C1MR((const Ipp16u *)_src, (int)sstep, (Ipp16u *)_dst, (int)dstep, ippiSize(size), mask, (int)mstep) >= 0) + CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiCopy_16u_C1MR, (const Ipp16u *)_src, (int)sstep, (Ipp16u *)_dst, (int)dstep, ippiSize(size), mask, (int)mstep) >= 0) for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep ) { @@ -194,7 +194,7 @@ static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \ uchar* dst, size_t dstep, Size size, void*) \ { \ - CV_IPP_RUN(true, ippiCopy_##ippfavor((const ipptype *)src, (int)sstep, (ipptype *)dst, (int)dstep, ippiSize(size), (const Ipp8u *)mask, (int)mstep) >= 0)\ + CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiCopy_##ippfavor, (const ipptype *)src, (int)sstep, (ipptype *)dst, (int)dstep, ippiSize(size), (const Ipp8u *)mask, (int)mstep) >= 0)\ copyMask_(src, sstep, mask, mstep, dst, dstep, size); \ } #else @@ -251,6 +251,8 @@ BinaryFunc getCopyMaskFunc(size_t esz) /* dst = src */ void Mat::copyTo( OutputArray _dst ) const { + CV_INSTRUMENT_REGION() + int dtype = _dst.type(); if( _dst.fixedType() && dtype != type() ) { @@ -296,7 +298,7 @@ void Mat::copyTo( OutputArray _dst ) const (size_t)step <= (size_t)INT_MAX && (size_t)dst.step <= (size_t)INT_MAX , - ippiCopy_8u_C1R(sptr, (int)step, dptr, (int)dst.step, ippiSize((int)(cols*elemSize()), rows)) >= 0 + CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1R, sptr, (int)step, dptr, (int)dst.step, ippiSize((int)(cols*elemSize()), rows)) >= 0 ) Size sz = getContinuousSize(*this, dst); @@ -327,6 +329,8 @@ void Mat::copyTo( OutputArray _dst ) const void Mat::copyTo( OutputArray _dst, InputArray _mask ) const { + CV_INSTRUMENT_REGION() + Mat mask = _mask.getMat(); if( !mask.data ) { @@ -367,6 +371,8 @@ void Mat::copyTo( OutputArray _dst, InputArray _mask ) const Mat& Mat::operator = (const Scalar& s) { + CV_INSTRUMENT_REGION() + const Mat* arrays[] = { this }; uchar* dptr; NAryMatIterator it(arrays, &dptr, 1); @@ -435,6 +441,8 @@ Mat& Mat::operator = (const Scalar& s) #if defined HAVE_IPP static bool ipp_Mat_setTo(Mat *src, Mat &value, Mat &mask) { + CV_INSTRUMENT_REGION_IPP() + int cn = src->channels(), depth0 = src->depth(); if (!mask.empty() && (src->dims <= 2 || (src->isContinuous() && mask.isContinuous())) && @@ -460,13 +468,13 @@ static bool ipp_Mat_setTo(Mat *src, Mat &value, Mat &mask) /*if (depth0 == CV_8U) status = ippiSet_8u_C1MR(*(Ipp8u *)buf, (Ipp8u *)data, dstep, roisize, mask.data, mstep); else*/ if (depth0 == CV_16U) - status = ippiSet_16u_C1MR(*(Ipp16u *)buf, (Ipp16u *)src->data, dstep, roisize, mask.data, mstep); + status = CV_INSTRUMENT_FUN_IPP(ippiSet_16u_C1MR, *(Ipp16u *)buf, (Ipp16u *)src->data, dstep, roisize, mask.data, mstep); else if (depth0 == CV_16S) - status = ippiSet_16s_C1MR(*(Ipp16s *)buf, (Ipp16s *)src->data, dstep, roisize, mask.data, mstep); + status = CV_INSTRUMENT_FUN_IPP(ippiSet_16s_C1MR, *(Ipp16s *)buf, (Ipp16s *)src->data, dstep, roisize, mask.data, mstep); else if (depth0 == CV_32S) - status = ippiSet_32s_C1MR(*(Ipp32s *)buf, (Ipp32s *)src->data, dstep, roisize, mask.data, mstep); + status = CV_INSTRUMENT_FUN_IPP(ippiSet_32s_C1MR, *(Ipp32s *)buf, (Ipp32s *)src->data, dstep, roisize, mask.data, mstep); else if (depth0 == CV_32F) - status = ippiSet_32f_C1MR(*(Ipp32f *)buf, (Ipp32f *)src->data, dstep, roisize, mask.data, mstep); + status = CV_INSTRUMENT_FUN_IPP(ippiSet_32f_C1MR, *(Ipp32f *)buf, (Ipp32f *)src->data, dstep, roisize, mask.data, mstep); } else if (cn == 3 || cn == 4) { @@ -476,7 +484,7 @@ static bool ipp_Mat_setTo(Mat *src, Mat &value, Mat &mask) { \ typedef Ipp##ippfavor ipptype; \ ipptype ippvalue[4] = { ((ipptype *)buf)[0], ((ipptype *)buf)[1], ((ipptype *)buf)[2], ((ipptype *)buf)[3] }; \ - status = ippiSet_##ippfavor##_C##ippcn##MR(ippvalue, (ipptype *)src->data, dstep, roisize, mask.data, mstep); \ + status = CV_INSTRUMENT_FUN_IPP(ippiSet_##ippfavor##_C##ippcn##MR, ippvalue, (ipptype *)src->data, dstep, roisize, mask.data, mstep); \ } while ((void)0, 0) #define IPP_SET_CN(ippcn) \ @@ -515,6 +523,8 @@ static bool ipp_Mat_setTo(Mat *src, Mat &value, Mat &mask) Mat& Mat::setTo(InputArray _value, InputArray _mask) { + CV_INSTRUMENT_REGION() + if( empty() ) return *this; @@ -523,7 +533,7 @@ Mat& Mat::setTo(InputArray _value, InputArray _mask) CV_Assert( checkScalar(value, type(), _value.kind(), _InputArray::MAT )); CV_Assert( mask.empty() || (mask.type() == CV_8U && size == mask.size) ); - CV_IPP_RUN(true, ipp_Mat_setTo((cv::Mat*)this, value, mask), *this) + CV_IPP_RUN_FAST(ipp_Mat_setTo((cv::Mat*)this, value, mask), *this) size_t esz = elemSize(); BinaryFunc copymask = getCopyMaskFunc(esz); @@ -700,65 +710,67 @@ static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode ) #if defined HAVE_IPP static bool ipp_flip( Mat &src, Mat &dst, int flip_mode ) { + CV_INSTRUMENT_REGION_IPP() + int type = src.type(); - typedef IppStatus (CV_STDCALL * ippiMirror)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize, IppiAxis flip); - typedef IppStatus (CV_STDCALL * ippiMirrorI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize, IppiAxis flip); - ippiMirror ippFunc = 0; - ippiMirrorI ippFuncI = 0; + typedef IppStatus (CV_STDCALL * IppiMirror)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize, IppiAxis flip); + typedef IppStatus (CV_STDCALL * IppiMirrorI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize, IppiAxis flip); + IppiMirror ippiMirror = 0; + IppiMirrorI ippiMirror_I = 0; if (src.data == dst.data) { CV_SUPPRESS_DEPRECATED_START - ippFuncI = - type == CV_8UC1 ? (ippiMirrorI)ippiMirror_8u_C1IR : - type == CV_8UC3 ? (ippiMirrorI)ippiMirror_8u_C3IR : - type == CV_8UC4 ? (ippiMirrorI)ippiMirror_8u_C4IR : - type == CV_16UC1 ? (ippiMirrorI)ippiMirror_16u_C1IR : - type == CV_16UC3 ? (ippiMirrorI)ippiMirror_16u_C3IR : - type == CV_16UC4 ? (ippiMirrorI)ippiMirror_16u_C4IR : - type == CV_16SC1 ? (ippiMirrorI)ippiMirror_16s_C1IR : - type == CV_16SC3 ? (ippiMirrorI)ippiMirror_16s_C3IR : - type == CV_16SC4 ? (ippiMirrorI)ippiMirror_16s_C4IR : - type == CV_32SC1 ? (ippiMirrorI)ippiMirror_32s_C1IR : - type == CV_32SC3 ? (ippiMirrorI)ippiMirror_32s_C3IR : - type == CV_32SC4 ? (ippiMirrorI)ippiMirror_32s_C4IR : - type == CV_32FC1 ? (ippiMirrorI)ippiMirror_32f_C1IR : - type == CV_32FC3 ? (ippiMirrorI)ippiMirror_32f_C3IR : - type == CV_32FC4 ? (ippiMirrorI)ippiMirror_32f_C4IR : 0; + ippiMirror_I = + type == CV_8UC1 ? (IppiMirrorI)ippiMirror_8u_C1IR : + type == CV_8UC3 ? (IppiMirrorI)ippiMirror_8u_C3IR : + type == CV_8UC4 ? (IppiMirrorI)ippiMirror_8u_C4IR : + type == CV_16UC1 ? (IppiMirrorI)ippiMirror_16u_C1IR : + type == CV_16UC3 ? (IppiMirrorI)ippiMirror_16u_C3IR : + type == CV_16UC4 ? (IppiMirrorI)ippiMirror_16u_C4IR : + type == CV_16SC1 ? (IppiMirrorI)ippiMirror_16s_C1IR : + type == CV_16SC3 ? (IppiMirrorI)ippiMirror_16s_C3IR : + type == CV_16SC4 ? (IppiMirrorI)ippiMirror_16s_C4IR : + type == CV_32SC1 ? (IppiMirrorI)ippiMirror_32s_C1IR : + type == CV_32SC3 ? (IppiMirrorI)ippiMirror_32s_C3IR : + type == CV_32SC4 ? (IppiMirrorI)ippiMirror_32s_C4IR : + type == CV_32FC1 ? (IppiMirrorI)ippiMirror_32f_C1IR : + type == CV_32FC3 ? (IppiMirrorI)ippiMirror_32f_C3IR : + type == CV_32FC4 ? (IppiMirrorI)ippiMirror_32f_C4IR : 0; CV_SUPPRESS_DEPRECATED_END } else { - ippFunc = - type == CV_8UC1 ? (ippiMirror)ippiMirror_8u_C1R : - type == CV_8UC3 ? (ippiMirror)ippiMirror_8u_C3R : - type == CV_8UC4 ? (ippiMirror)ippiMirror_8u_C4R : - type == CV_16UC1 ? (ippiMirror)ippiMirror_16u_C1R : - type == CV_16UC3 ? (ippiMirror)ippiMirror_16u_C3R : - type == CV_16UC4 ? (ippiMirror)ippiMirror_16u_C4R : - type == CV_16SC1 ? (ippiMirror)ippiMirror_16s_C1R : - type == CV_16SC3 ? (ippiMirror)ippiMirror_16s_C3R : - type == CV_16SC4 ? (ippiMirror)ippiMirror_16s_C4R : - type == CV_32SC1 ? (ippiMirror)ippiMirror_32s_C1R : - type == CV_32SC3 ? (ippiMirror)ippiMirror_32s_C3R : - type == CV_32SC4 ? (ippiMirror)ippiMirror_32s_C4R : - type == CV_32FC1 ? (ippiMirror)ippiMirror_32f_C1R : - type == CV_32FC3 ? (ippiMirror)ippiMirror_32f_C3R : - type == CV_32FC4 ? (ippiMirror)ippiMirror_32f_C4R : 0; + ippiMirror = + type == CV_8UC1 ? (IppiMirror)ippiMirror_8u_C1R : + type == CV_8UC3 ? (IppiMirror)ippiMirror_8u_C3R : + type == CV_8UC4 ? (IppiMirror)ippiMirror_8u_C4R : + type == CV_16UC1 ? (IppiMirror)ippiMirror_16u_C1R : + type == CV_16UC3 ? (IppiMirror)ippiMirror_16u_C3R : + type == CV_16UC4 ? (IppiMirror)ippiMirror_16u_C4R : + type == CV_16SC1 ? (IppiMirror)ippiMirror_16s_C1R : + type == CV_16SC3 ? (IppiMirror)ippiMirror_16s_C3R : + type == CV_16SC4 ? (IppiMirror)ippiMirror_16s_C4R : + type == CV_32SC1 ? (IppiMirror)ippiMirror_32s_C1R : + type == CV_32SC3 ? (IppiMirror)ippiMirror_32s_C3R : + type == CV_32SC4 ? (IppiMirror)ippiMirror_32s_C4R : + type == CV_32FC1 ? (IppiMirror)ippiMirror_32f_C1R : + type == CV_32FC3 ? (IppiMirror)ippiMirror_32f_C3R : + type == CV_32FC4 ? (IppiMirror)ippiMirror_32f_C4R : 0; } IppiAxis axis = flip_mode == 0 ? ippAxsHorizontal : flip_mode > 0 ? ippAxsVertical : ippAxsBoth; IppiSize roisize = { dst.cols, dst.rows }; - if (ippFunc != 0) + if (ippiMirror != 0) { - if (ippFunc(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), axis) >= 0) + if (CV_INSTRUMENT_FUN_IPP(ippiMirror, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), axis) >= 0) return true; } - else if (ippFuncI != 0) + else if (ippiMirror_I != 0) { - if (ippFuncI(dst.ptr(), (int)dst.step, roisize, axis) >= 0) + if (CV_INSTRUMENT_FUN_IPP(ippiMirror_I, dst.ptr(), (int)dst.step, roisize, axis) >= 0) return true; } @@ -769,6 +781,8 @@ static bool ipp_flip( Mat &src, Mat &dst, int flip_mode ) void flip( InputArray _src, OutputArray _dst, int flip_mode ) { + CV_INSTRUMENT_REGION() + CV_Assert( _src.dims() <= 2 ); Size size = _src.size(); @@ -794,7 +808,7 @@ void flip( InputArray _src, OutputArray _dst, int flip_mode ) _dst.create( size, type ); Mat dst = _dst.getMat(); - CV_IPP_RUN(true, ipp_flip(src, dst, flip_mode)); + CV_IPP_RUN_FAST(ipp_flip(src, dst, flip_mode)); size_t esz = CV_ELEM_SIZE(type); @@ -839,6 +853,8 @@ static bool ocl_repeat(InputArray _src, int ny, int nx, OutputArray _dst) void repeat(InputArray _src, int ny, int nx, OutputArray _dst) { + CV_INSTRUMENT_REGION() + CV_Assert( _src.dims() <= 2 ); CV_Assert( ny > 0 && nx > 0 ); @@ -890,6 +906,8 @@ Mat repeat(const Mat& src, int ny, int nx) */ int cv::borderInterpolate( int p, int len, int borderType ) { + CV_INSTRUMENT_REGION() + if( (unsigned)p < (unsigned)len ) ; else if( borderType == BORDER_REPLICATE ) @@ -1119,6 +1137,8 @@ static bool ocl_copyMakeBorder( InputArray _src, OutputArray _dst, int top, int void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom, int left, int right, int borderType, const Scalar& value ) { + CV_INSTRUMENT_REGION() + CV_Assert( top >= 0 && bottom >= 0 && left >= 0 && right >= 0 ); CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2, diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index 162052667b..b52ba93032 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -469,53 +469,53 @@ template<> struct DFT_VecR4 static IppStatus ippsDFTFwd_CToC( const Complex* src, Complex* dst, const void* spec, uchar* buf) { - return ippsDFTFwd_CToC_32fc( (const Ipp32fc*)src, (Ipp32fc*)dst, + return CV_INSTRUMENT_FUN_IPP(ippsDFTFwd_CToC_32fc, (const Ipp32fc*)src, (Ipp32fc*)dst, (const IppsDFTSpec_C_32fc*)spec, buf); } static IppStatus ippsDFTFwd_CToC( const Complex* src, Complex* dst, const void* spec, uchar* buf) { - return ippsDFTFwd_CToC_64fc( (const Ipp64fc*)src, (Ipp64fc*)dst, + return CV_INSTRUMENT_FUN_IPP(ippsDFTFwd_CToC_64fc, (const Ipp64fc*)src, (Ipp64fc*)dst, (const IppsDFTSpec_C_64fc*)spec, buf); } static IppStatus ippsDFTInv_CToC( const Complex* src, Complex* dst, const void* spec, uchar* buf) { - return ippsDFTInv_CToC_32fc( (const Ipp32fc*)src, (Ipp32fc*)dst, + return CV_INSTRUMENT_FUN_IPP(ippsDFTInv_CToC_32fc, (const Ipp32fc*)src, (Ipp32fc*)dst, (const IppsDFTSpec_C_32fc*)spec, buf); } static IppStatus ippsDFTInv_CToC( const Complex* src, Complex* dst, const void* spec, uchar* buf) { - return ippsDFTInv_CToC_64fc( (const Ipp64fc*)src, (Ipp64fc*)dst, + return CV_INSTRUMENT_FUN_IPP(ippsDFTInv_CToC_64fc, (const Ipp64fc*)src, (Ipp64fc*)dst, (const IppsDFTSpec_C_64fc*)spec, buf); } static IppStatus ippsDFTFwd_RToPack( const float* src, float* dst, const void* spec, uchar* buf) { - return ippsDFTFwd_RToPack_32f( src, dst, (const IppsDFTSpec_R_32f*)spec, buf); + return CV_INSTRUMENT_FUN_IPP(ippsDFTFwd_RToPack_32f, src, dst, (const IppsDFTSpec_R_32f*)spec, buf); } static IppStatus ippsDFTFwd_RToPack( const double* src, double* dst, const void* spec, uchar* buf) { - return ippsDFTFwd_RToPack_64f( src, dst, (const IppsDFTSpec_R_64f*)spec, buf); + return CV_INSTRUMENT_FUN_IPP(ippsDFTFwd_RToPack_64f, src, dst, (const IppsDFTSpec_R_64f*)spec, buf); } static IppStatus ippsDFTInv_PackToR( const float* src, float* dst, const void* spec, uchar* buf) { - return ippsDFTInv_PackToR_32f( src, dst, (const IppsDFTSpec_R_32f*)spec, buf); + return CV_INSTRUMENT_FUN_IPP(ippsDFTInv_PackToR_32f, src, dst, (const IppsDFTSpec_R_32f*)spec, buf); } static IppStatus ippsDFTInv_PackToR( const double* src, double* dst, const void* spec, uchar* buf) { - return ippsDFTInv_PackToR_64f( src, dst, (const IppsDFTSpec_R_64f*)spec, buf); + return CV_INSTRUMENT_FUN_IPP(ippsDFTInv_PackToR_64f, src, dst, (const IppsDFTSpec_R_64f*)spec, buf); } #endif @@ -1564,6 +1564,8 @@ public: virtual void operator()(const Range& range) const { + CV_INSTRUMENT_REGION_IPP(); + IppStatus status; Ipp8u* pBuffer = 0; Ipp8u* pMemInit= 0; @@ -1645,6 +1647,8 @@ public: virtual void operator()(const Range& range) const { + CV_INSTRUMENT_REGION_IPP(); + IppStatus status; Ipp8u* pBuffer = 0; Ipp8u* pMemInit= 0; @@ -1728,30 +1732,32 @@ bool Dft_R_IPPLoop(const uchar * src, size_t src_step, uchar * dst, size_t dst_s struct IPPDFT_C_Functor { - IPPDFT_C_Functor(ippiDFT_C_Func _func) : func(_func){} + IPPDFT_C_Functor(ippiDFT_C_Func _func) : ippiDFT_CToC_32fc_C1R(_func){} bool operator()(const Ipp32fc* src, size_t srcStep, Ipp32fc* dst, size_t dstStep, const IppiDFTSpec_C_32fc* pDFTSpec, Ipp8u* pBuffer) const { - return func ? func(src, static_cast(srcStep), dst, static_cast(dstStep), pDFTSpec, pBuffer) >= 0 : false; + return ippiDFT_CToC_32fc_C1R ? CV_INSTRUMENT_FUN_IPP(ippiDFT_CToC_32fc_C1R, src, static_cast(srcStep), dst, static_cast(dstStep), pDFTSpec, pBuffer) >= 0 : false; } private: - ippiDFT_C_Func func; + ippiDFT_C_Func ippiDFT_CToC_32fc_C1R; }; struct IPPDFT_R_Functor { - IPPDFT_R_Functor(ippiDFT_R_Func _func) : func(_func){} + IPPDFT_R_Functor(ippiDFT_R_Func _func) : ippiDFT_PackToR_32f_C1R(_func){} bool operator()(const Ipp32f* src, size_t srcStep, Ipp32f* dst, size_t dstStep, const IppiDFTSpec_R_32f* pDFTSpec, Ipp8u* pBuffer) const { - return func ? func(src, static_cast(srcStep), dst, static_cast(dstStep), pDFTSpec, pBuffer) >= 0 : false; + return ippiDFT_PackToR_32f_C1R ? CV_INSTRUMENT_FUN_IPP(ippiDFT_PackToR_32f_C1R, src, static_cast(srcStep), dst, static_cast(dstStep), pDFTSpec, pBuffer) >= 0 : false; } private: - ippiDFT_R_Func func; + ippiDFT_R_Func ippiDFT_PackToR_32f_C1R; }; static bool ippi_DFT_C_32F(const uchar * src, size_t src_step, uchar * dst, size_t dst_step, int width, int height, bool inv, int norm_flag) { + CV_INSTRUMENT_REGION_IPP() + IppStatus status; Ipp8u* pBuffer = 0; Ipp8u* pMemInit= 0; @@ -1787,9 +1793,9 @@ static bool ippi_DFT_C_32F(const uchar * src, size_t src_step, uchar * dst, size } if (!inv) - status = ippiDFTFwd_CToC_32fc_C1R( (Ipp32fc*)src, static_cast(src_step), (Ipp32fc*)dst, static_cast(dst_step), pDFTSpec, pBuffer ); + status = CV_INSTRUMENT_FUN_IPP(ippiDFTFwd_CToC_32fc_C1R, (Ipp32fc*)src, static_cast(src_step), (Ipp32fc*)dst, static_cast(dst_step), pDFTSpec, pBuffer); else - status = ippiDFTInv_CToC_32fc_C1R( (Ipp32fc*)src, static_cast(src_step), (Ipp32fc*)dst, static_cast(dst_step), pDFTSpec, pBuffer ); + status = CV_INSTRUMENT_FUN_IPP(ippiDFTInv_CToC_32fc_C1R, (Ipp32fc*)src, static_cast(src_step), (Ipp32fc*)dst, static_cast(dst_step), pDFTSpec, pBuffer); if ( sizeBuffer > 0 ) ippFree( pBuffer ); @@ -1806,6 +1812,8 @@ static bool ippi_DFT_C_32F(const uchar * src, size_t src_step, uchar * dst, size static bool ippi_DFT_R_32F(const uchar * src, size_t src_step, uchar * dst, size_t dst_step, int width, int height, bool inv, int norm_flag) { + CV_INSTRUMENT_REGION_IPP() + IppStatus status; Ipp8u* pBuffer = 0; Ipp8u* pMemInit= 0; @@ -1841,9 +1849,9 @@ static bool ippi_DFT_R_32F(const uchar * src, size_t src_step, uchar * dst, size } if (!inv) - status = ippiDFTFwd_RToPack_32f_C1R( (float*)src, static_cast(src_step), (float*)dst, static_cast(dst_step), pDFTSpec, pBuffer ); + status = CV_INSTRUMENT_FUN_IPP(ippiDFTFwd_RToPack_32f_C1R, (float*)src, static_cast(src_step), (float*)dst, static_cast(dst_step), pDFTSpec, pBuffer); else - status = ippiDFTInv_PackToR_32f_C1R( (float*)src, static_cast(src_step), (float*)dst, static_cast(dst_step), pDFTSpec, pBuffer ); + status = CV_INSTRUMENT_FUN_IPP(ippiDFTInv_PackToR_32f_C1R, (float*)src, static_cast(src_step), (float*)dst, static_cast(dst_step), pDFTSpec, pBuffer); if ( sizeBuffer > 0 ) ippFree( pBuffer ); @@ -3318,6 +3326,8 @@ Ptr DFT2D::create(int width, int height, int depth, void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) { + CV_INSTRUMENT_REGION() + #ifdef HAVE_CLAMDFFT CV_OCL_RUN(ocl::haveAmdFft() && ocl::Device::getDefault().type() != ocl::Device::TYPE_CPU && _dst.isUMat() && _src0.dims() <= 2 && nonzero_rows == 0, @@ -3363,6 +3373,8 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) void cv::idft( InputArray src, OutputArray dst, int flags, int nonzero_rows ) { + CV_INSTRUMENT_REGION() + dft( src, dst, flags | DFT_INVERSE, nonzero_rows ); } @@ -3407,6 +3419,8 @@ static bool ocl_mulSpectrums( InputArray _srcA, InputArray _srcB, void cv::mulSpectrums( InputArray _srcA, InputArray _srcB, OutputArray _dst, int flags, bool conjB ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_dst.isUMat() && _srcA.dims() <= 2 && _srcB.dims() <= 2, ocl_mulSpectrums(_srcA, _srcB, _dst, flags, conjB)) @@ -3795,6 +3809,8 @@ public: virtual void operator()(const Range& range) const { + CV_INSTRUMENT_REGION_IPP() + if(*ok == false) return; @@ -3818,7 +3834,7 @@ public: ippFree(pInitBuf); \ return; - ippiDCTFunc ippDctFun = inv ? (ippiDCTFunc)ippiDCTInv_32f_C1R : (ippiDCTFunc)ippiDCTFwd_32f_C1R; + ippiDCTFunc ippiDCT_32f_C1R = inv ? (ippiDCTFunc)ippiDCTInv_32f_C1R : (ippiDCTFunc)ippiDCTFwd_32f_C1R; ippiDCTInit ippDctInit = inv ? (ippiDCTInit)ippiDCTInvInit_32f : (ippiDCTInit)ippiDCTFwdInit_32f; ippiDCTGetSize ippDctGetSize = inv ? (ippiDCTGetSize)ippiDCTInvGetSize_32f : (ippiDCTGetSize)ippiDCTFwdGetSize_32f; @@ -3856,7 +3872,7 @@ public: for(int i = range.start; i < range.end; ++i) { - if(ippDctFun((float*)(src + src_step * i), static_cast(src_step), (float*)(dst + dst_step * i), static_cast(dst_step), pDCTSpec, pBuffer) < 0) + if(CV_INSTRUMENT_FUN_IPP(ippiDCT_32f_C1R, (float*)(src + src_step * i), static_cast(src_step), (float*)(dst + dst_step * i), static_cast(dst_step), pDCTSpec, pBuffer) < 0) { *ok = false; IPP_RETURN @@ -3925,6 +3941,8 @@ static bool DctIPPLoop(const uchar * src, size_t src_step, uchar * dst, size_t d static bool ippi_DCT_32f(const uchar * src, size_t src_step, uchar * dst, size_t dst_step, int width, int height, bool inv, bool row) { + CV_INSTRUMENT_REGION_IPP() + if(row) return DctIPPLoop(src, src_step, dst, dst_step, width, height, inv); else @@ -3948,7 +3966,7 @@ static bool ippi_DCT_32f(const uchar * src, size_t src_step, uchar * dst, size_t if(pInitBuf) \ ippFree(pInitBuf); \ - ippiDCTFunc ippDctFun = inv ? (ippiDCTFunc)ippiDCTInv_32f_C1R : (ippiDCTFunc)ippiDCTFwd_32f_C1R; + ippiDCTFunc ippiDCT_32f_C1R = inv ? (ippiDCTFunc)ippiDCTInv_32f_C1R : (ippiDCTFunc)ippiDCTFwd_32f_C1R; ippiDCTInit ippDctInit = inv ? (ippiDCTInit)ippiDCTInvInit_32f : (ippiDCTInit)ippiDCTFwdInit_32f; ippiDCTGetSize ippDctGetSize = inv ? (ippiDCTGetSize)ippiDCTInvGetSize_32f : (ippiDCTGetSize)ippiDCTFwdGetSize_32f; @@ -3978,7 +3996,7 @@ static bool ippi_DCT_32f(const uchar * src, size_t src_step, uchar * dst, size_t return false; } - if(ippDctFun((float*)src, static_cast(src_step), (float*)dst, static_cast(dst_step), pDCTSpec, pBuffer) < 0) + if(CV_INSTRUMENT_FUN_IPP(ippiDCT_32f_C1R, (float*)src, static_cast(src_step), (float*)dst, static_cast(dst_step), pDCTSpec, pBuffer) < 0) { IPP_RELEASE return false; @@ -4218,6 +4236,8 @@ Ptr DCT2D::create(int width, int height, int depth, int flags) void cv::dct( InputArray _src0, OutputArray _dst, int flags ) { + CV_INSTRUMENT_REGION() + Mat src0 = _src0.getMat(), src = src0; int type = src.type(), depth = src.depth(); @@ -4240,6 +4260,8 @@ void cv::dct( InputArray _src0, OutputArray _dst, int flags ) void cv::idct( InputArray src, OutputArray dst, int flags ) { + CV_INSTRUMENT_REGION() + dct( src, dst, flags | DCT_INVERSE ); } diff --git a/modules/core/src/glob.cpp b/modules/core/src/glob.cpp index e0c7f66a3a..9bd3bdbfca 100644 --- a/modules/core/src/glob.cpp +++ b/modules/core/src/glob.cpp @@ -259,6 +259,8 @@ static void glob_rec(const cv::String& directory, const cv::String& wildchart, s void cv::glob(String pattern, std::vector& result, bool recursive) { + CV_INSTRUMENT_REGION() + result.clear(); String path, wildchart; diff --git a/modules/core/src/kmeans.cpp b/modules/core/src/kmeans.cpp index a81334aa8f..df017adca3 100644 --- a/modules/core/src/kmeans.cpp +++ b/modules/core/src/kmeans.cpp @@ -219,6 +219,8 @@ double cv::kmeans( InputArray _data, int K, TermCriteria criteria, int attempts, int flags, OutputArray _centers ) { + CV_INSTRUMENT_REGION() + const int SPP_TRIALS = 3; Mat data0 = _data.getMat(); bool isrow = data0.rows == 1; diff --git a/modules/core/src/lapack.cpp b/modules/core/src/lapack.cpp index 3711ca9e17..eed86b4d55 100644 --- a/modules/core/src/lapack.cpp +++ b/modules/core/src/lapack.cpp @@ -52,21 +52,29 @@ namespace cv int LU(float* A, size_t astep, int m, float* b, size_t bstep, int n) { + CV_INSTRUMENT_REGION() + return hal::LU32f(A, astep, m, b, bstep, n); } int LU(double* A, size_t astep, int m, double* b, size_t bstep, int n) { + CV_INSTRUMENT_REGION() + return hal::LU64f(A, astep, m, b, bstep, n); } bool Cholesky(float* A, size_t astep, int m, float* b, size_t bstep, int n) { + CV_INSTRUMENT_REGION() + return hal::Cholesky32f(A, astep, m, b, bstep, n); } bool Cholesky(double* A, size_t astep, int m, double* b, size_t bstep, int n) { + CV_INSTRUMENT_REGION() + return hal::Cholesky64f(A, astep, m, b, bstep, n); } @@ -746,6 +754,8 @@ SVBkSb( int m, int n, const double* w, size_t wstep, double cv::determinant( InputArray _mat ) { + CV_INSTRUMENT_REGION() + Mat mat = _mat.getMat(); double result = 0; int type = mat.type(), rows = mat.rows; @@ -822,6 +832,8 @@ double cv::determinant( InputArray _mat ) double cv::invert( InputArray _src, OutputArray _dst, int method ) { + CV_INSTRUMENT_REGION() + bool result = false; Mat src = _src.getMat(); int type = src.type(); @@ -1080,6 +1092,8 @@ double cv::invert( InputArray _src, OutputArray _dst, int method ) bool cv::solve( InputArray _src, InputArray _src2arg, OutputArray _dst, int method ) { + CV_INSTRUMENT_REGION() + bool result = true; Mat src = _src.getMat(), _src2 = _src2arg.getMat(); int type = src.type(); @@ -1356,6 +1370,8 @@ bool cv::solve( InputArray _src, InputArray _src2arg, OutputArray _dst, int meth bool cv::eigen( InputArray _src, OutputArray _evals, OutputArray _evects ) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); int type = src.type(); int n = src.rows; @@ -1464,11 +1480,15 @@ static void _SVDcompute( InputArray _aarr, OutputArray _w, void SVD::compute( InputArray a, OutputArray w, OutputArray u, OutputArray vt, int flags ) { + CV_INSTRUMENT_REGION() + _SVDcompute(a, w, u, vt, flags); } void SVD::compute( InputArray a, OutputArray w, int flags ) { + CV_INSTRUMENT_REGION() + _SVDcompute(a, w, noArray(), noArray(), flags); } @@ -1517,11 +1537,15 @@ void SVD::backSubst( InputArray rhs, OutputArray dst ) const void cv::SVDecomp(InputArray src, OutputArray w, OutputArray u, OutputArray vt, int flags) { + CV_INSTRUMENT_REGION() + SVD::compute(src, w, u, vt, flags); } void cv::SVBackSubst(InputArray w, InputArray u, InputArray vt, InputArray rhs, OutputArray dst) { + CV_INSTRUMENT_REGION() + SVD::backSubst(w, u, vt, rhs, dst); } diff --git a/modules/core/src/lda.cpp b/modules/core/src/lda.cpp index c52833b41c..4ccbf8a834 100644 --- a/modules/core/src/lda.cpp +++ b/modules/core/src/lda.cpp @@ -898,6 +898,8 @@ public: // National Institute of Standards and Technology (NIST). void compute(InputArray src) { + CV_INSTRUMENT_REGION() + if(isSymmetric(src)) { // Fall back to OpenCV for a symmetric matrix! cv::eigen(src, _eigenvalues, _eigenvectors); diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index f69381061b..b9bdf49eb3 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -101,6 +101,8 @@ static bool ocl_math_op(InputArray _src1, InputArray _src2, OutputArray _dst, in \* ************************************************************************** */ float cubeRoot( float value ) { + CV_INSTRUMENT_REGION() + float fr; Cv32suf v, m; int ix, s; @@ -142,6 +144,8 @@ float cubeRoot( float value ) void magnitude( InputArray src1, InputArray src2, OutputArray dst ) { + CV_INSTRUMENT_REGION() + int type = src1.type(), depth = src1.depth(), cn = src1.channels(); CV_Assert( src1.size() == src2.size() && type == src2.type() && (depth == CV_32F || depth == CV_64F)); @@ -176,6 +180,8 @@ void magnitude( InputArray src1, InputArray src2, OutputArray dst ) void phase( InputArray src1, InputArray src2, OutputArray dst, bool angleInDegrees ) { + CV_INSTRUMENT_REGION() + int type = src1.type(), depth = src1.depth(), cn = src1.channels(); CV_Assert( src1.size() == src2.size() && type == src2.type() && (depth == CV_32F || depth == CV_64F)); @@ -260,6 +266,8 @@ static bool ocl_cartToPolar( InputArray _src1, InputArray _src2, void cartToPolar( InputArray src1, InputArray src2, OutputArray dst1, OutputArray dst2, bool angleInDegrees ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(dst1.isUMat() && dst2.isUMat(), ocl_cartToPolar(src1, src2, dst1, dst2, angleInDegrees)) @@ -492,6 +500,8 @@ static bool ocl_polarToCart( InputArray _mag, InputArray _angle, void polarToCart( InputArray src1, InputArray src2, OutputArray dst1, OutputArray dst2, bool angleInDegrees ) { + CV_INSTRUMENT_REGION() + int type = src2.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); CV_Assert((depth == CV_32F || depth == CV_64F) && (src1.empty() || src1.type() == type)); @@ -509,14 +519,14 @@ void polarToCart( InputArray src1, InputArray src2, { if (Mag.isContinuous() && Angle.isContinuous() && X.isContinuous() && Y.isContinuous() && !angleInDegrees) { - typedef IppStatus (CV_STDCALL * ippsPolarToCart)(const void * pSrcMagn, const void * pSrcPhase, + typedef IppStatus (CV_STDCALL * IppsPolarToCart)(const void * pSrcMagn, const void * pSrcPhase, void * pDstRe, void * pDstIm, int len); - ippsPolarToCart ippFunc = - depth == CV_32F ? (ippsPolarToCart)ippsPolarToCart_32f : - depth == CV_64F ? (ippsPolarToCart)ippsPolarToCart_64f : 0; - CV_Assert(ippFunc != 0); + IppsPolarToCart ippsPolarToCart = + depth == CV_32F ? (IppsPolarToCart)ippsPolarToCart_32f : + depth == CV_64F ? (IppsPolarToCart)ippsPolarToCart_64f : 0; + CV_Assert(ippsPolarToCart != 0); - IppStatus status = ippFunc(Mag.ptr(), Angle.ptr(), X.ptr(), Y.ptr(), static_cast(cn * X.total())); + IppStatus status = CV_INSTRUMENT_FUN_IPP(ippsPolarToCart, Mag.ptr(), Angle.ptr(), X.ptr(), Y.ptr(), static_cast(cn * X.total())); if (status >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); @@ -620,6 +630,8 @@ void polarToCart( InputArray src1, InputArray src2, void exp( InputArray _src, OutputArray _dst ) { + CV_INSTRUMENT_REGION() + int type = _src.type(), depth = _src.depth(), cn = _src.channels(); CV_Assert( depth == CV_32F || depth == CV_64F ); @@ -651,6 +663,8 @@ void exp( InputArray _src, OutputArray _dst ) void log( InputArray _src, OutputArray _dst ) { + CV_INSTRUMENT_REGION() + int type = _src.type(), depth = _src.depth(), cn = _src.channels(); CV_Assert( depth == CV_32F || depth == CV_64F ); @@ -1160,6 +1174,8 @@ static void Sqrt_64f(const double* src, double* dst, int n) { hal::sqrt64f(src, void pow( InputArray _src, double power, OutputArray _dst ) { + CV_INSTRUMENT_REGION() + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), ipower = cvRound(power); bool is_ipower = fabs(ipower - power) < DBL_EPSILON; @@ -1245,12 +1261,12 @@ void pow( InputArray _src, double power, OutputArray _dst ) { int bsz = std::min(len - j, blockSize); - #if defined(HAVE_IPP) +#if defined(HAVE_IPP) CV_IPP_CHECK() { IppStatus status = depth == CV_32F ? - ippsPowx_32f_A21((const float*)ptrs[0], (float)power, (float*)ptrs[1], bsz) : - ippsPowx_64f_A50((const double*)ptrs[0], (double)power, (double*)ptrs[1], bsz); + CV_INSTRUMENT_FUN_IPP(ippsPowx_32f_A21, (const float*)ptrs[0], (float)power, (float*)ptrs[1], bsz) : + CV_INSTRUMENT_FUN_IPP(ippsPowx_64f_A50, (const double*)ptrs[0], (double)power, (double*)ptrs[1], bsz); if (status >= 0) { @@ -1261,7 +1277,7 @@ void pow( InputArray _src, double power, OutputArray _dst ) } setIppErrorStatus(); } - #endif +#endif if( depth == CV_32F ) { @@ -1327,6 +1343,8 @@ void pow( InputArray _src, double power, OutputArray _dst ) void sqrt(InputArray a, OutputArray b) { + CV_INSTRUMENT_REGION() + cv::pow(a, 0.5, b); } @@ -1412,6 +1430,8 @@ check_range_function check_range_functions[] = bool checkRange(InputArray _src, bool quiet, Point* pt, double minVal, double maxVal) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); if ( src.dims > 2 ) @@ -1549,6 +1569,8 @@ static bool ocl_patchNaNs( InputOutputArray _a, float value ) void patchNaNs( InputOutputArray _a, double _val ) { + CV_INSTRUMENT_REGION() + CV_Assert( _a.depth() == CV_32F ); CV_OCL_RUN(_a.isUMat() && _a.dims() <= 2, @@ -1714,6 +1736,8 @@ CV_IMPL int cvCheckArr( const CvArr* arr, int flags, int cv::solveCubic( InputArray _coeffs, OutputArray _roots ) { + CV_INSTRUMENT_REGION() + const int n0 = 3; Mat coeffs = _coeffs.getMat(); int ctype = coeffs.type(); @@ -1859,6 +1883,8 @@ int cv::solveCubic( InputArray _coeffs, OutputArray _roots ) http://en.wikipedia.org/wiki/Durand%E2%80%93Kerner_method */ double cv::solvePoly( InputArray _coeffs0, OutputArray _roots0, int maxIters ) { + CV_INSTRUMENT_REGION() + typedef Complex C; double maxDiff = 0; diff --git a/modules/core/src/mathfuncs_core.cpp b/modules/core/src/mathfuncs_core.cpp index 25fb951775..c021812247 100644 --- a/modules/core/src/mathfuncs_core.cpp +++ b/modules/core/src/mathfuncs_core.cpp @@ -203,12 +203,16 @@ namespace cv { namespace hal { void fastAtan32f(const float *Y, const float *X, float *angle, int len, bool angleInDegrees ) { + CV_INSTRUMENT_REGION() + CALL_HAL(fastAtan32f, cv_hal_fastAtan32f, Y, X, angle, len, angleInDegrees); atanImpl(Y, X, angle, len, angleInDegrees); } void fastAtan64f(const double *Y, const double *X, double *angle, int len, bool angleInDegrees) { + CV_INSTRUMENT_REGION() + CALL_HAL(fastAtan64f, cv_hal_fastAtan64f, Y, X, angle, len, angleInDegrees); atanImpl(Y, X, angle, len, angleInDegrees); } @@ -216,13 +220,17 @@ void fastAtan64f(const double *Y, const double *X, double *angle, int len, bool // deprecated void fastAtan2(const float *Y, const float *X, float *angle, int len, bool angleInDegrees ) { + CV_INSTRUMENT_REGION() + fastAtan32f(Y, X, angle, len, angleInDegrees); } void magnitude32f(const float* x, const float* y, float* mag, int len) { + CV_INSTRUMENT_REGION() + CALL_HAL(magnitude32f, cv_hal_magnitude32f, x, y, mag, len); - CV_IPP_RUN_FAST(ippsMagnitude_32f(x, y, mag, len) >= 0); + CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippsMagnitude_32f, x, y, mag, len) >= 0); int i = 0; @@ -247,8 +255,10 @@ void magnitude32f(const float* x, const float* y, float* mag, int len) void magnitude64f(const double* x, const double* y, double* mag, int len) { + CV_INSTRUMENT_REGION() + CALL_HAL(magnitude64f, cv_hal_magnitude64f, x, y, mag, len); - CV_IPP_RUN_FAST(ippsMagnitude_64f(x, y, mag, len) >= 0); + CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippsMagnitude_64f, x, y, mag, len) >= 0); int i = 0; @@ -274,8 +284,10 @@ void magnitude64f(const double* x, const double* y, double* mag, int len) void invSqrt32f(const float* src, float* dst, int len) { + CV_INSTRUMENT_REGION() + CALL_HAL(invSqrt32f, cv_hal_invSqrt32f, src, dst, len); - CV_IPP_RUN_FAST(ippsInvSqrt_32f_A21(src, dst, len) >= 0); + CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippsInvSqrt_32f_A21, src, dst, len) >= 0); int i = 0; @@ -296,8 +308,10 @@ void invSqrt32f(const float* src, float* dst, int len) void invSqrt64f(const double* src, double* dst, int len) { + CV_INSTRUMENT_REGION() + CALL_HAL(invSqrt64f, cv_hal_invSqrt64f, src, dst, len); - CV_IPP_RUN_FAST(ippsInvSqrt_64f_A50(src, dst, len) >= 0); + CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippsInvSqrt_64f_A50, src, dst, len) >= 0); int i = 0; @@ -314,8 +328,10 @@ void invSqrt64f(const double* src, double* dst, int len) void sqrt32f(const float* src, float* dst, int len) { + CV_INSTRUMENT_REGION() + CALL_HAL(sqrt32f, cv_hal_sqrt32f, src, dst, len); - CV_IPP_RUN_FAST(ippsSqrt_32f_A21(src, dst, len) >= 0); + CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippsSqrt_32f_A21, src, dst, len) >= 0); int i = 0; @@ -336,8 +352,10 @@ void sqrt32f(const float* src, float* dst, int len) void sqrt64f(const double* src, double* dst, int len) { + CV_INSTRUMENT_REGION() + CALL_HAL(sqrt64f, cv_hal_sqrt64f, src, dst, len); - CV_IPP_RUN_FAST(ippsSqrt_64f_A50(src, dst, len) >= 0); + CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippsSqrt_64f_A50, src, dst, len) >= 0); int i = 0; @@ -458,8 +476,10 @@ static const double exp_max_val = 3000.*(1 << EXPTAB_SCALE); // log10(DBL_MAX) < void exp32f( const float *_x, float *y, int n ) { + CV_INSTRUMENT_REGION() + CALL_HAL(exp32f, cv_hal_exp32f, _x, y, n); - CV_IPP_RUN_FAST(ippsExp_32f_A21(_x, y, n) >= 0); + CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippsExp_32f_A21, _x, y, n) >= 0); static const float A4 = (float)(1.000000000000002438532970795181890933776 / EXPPOLY_32F_A0), @@ -660,8 +680,10 @@ void exp32f( const float *_x, float *y, int n ) void exp64f( const double *_x, double *y, int n ) { + CV_INSTRUMENT_REGION() + CALL_HAL(exp64f, cv_hal_exp64f, _x, y, n); - CV_IPP_RUN_FAST(ippsExp_64f_A50(_x, y, n) >= 0); + CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippsExp_64f_A50, _x, y, n) >= 0); static const double A5 = .99999999999999999998285227504999 / EXPPOLY_32F_A0, @@ -1107,8 +1129,10 @@ static const double ln_2 = 0.69314718055994530941723212145818; void log32f( const float *_x, float *y, int n ) { + CV_INSTRUMENT_REGION() + CALL_HAL(log32f, cv_hal_log32f, _x, y, n); - CV_IPP_RUN_FAST(ippsLn_32f_A21(_x, y, n) >= 0); + CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippsLn_32f_A21, _x, y, n) >= 0); static const float shift[] = { 0, -1.f/512 }; static const float @@ -1254,8 +1278,10 @@ void log32f( const float *_x, float *y, int n ) void log64f( const double *x, double *y, int n ) { + CV_INSTRUMENT_REGION() + CALL_HAL(log64f, cv_hal_log64f, x, y, n); - CV_IPP_RUN_FAST(ippsLn_64f_A50(x, y, n) >= 0); + CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippsLn_64f_A50, x, y, n) >= 0); static const double shift[] = { 0, -1./512 }; static const double diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index 88097ca00b..477d4ab9e6 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -868,6 +868,8 @@ static bool ocl_gemm( InputArray matA, InputArray matB, double alpha, static void gemmImpl( Mat A, Mat B, double alpha, Mat C, double beta, Mat D, int flags ) { + CV_INSTRUMENT_REGION() + const int block_lin_size = 128; const int block_size = block_lin_size * block_lin_size; @@ -2082,6 +2084,8 @@ static TransformFunc getDiagTransformFunc(int depth) void cv::transform( InputArray _src, OutputArray _dst, InputArray _mtx ) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(), m = _mtx.getMat(); int depth = src.depth(), scn = src.channels(), dcn = m.rows; CV_Assert( scn == m.cols || scn + 1 == m.cols ); @@ -2260,6 +2264,8 @@ perspectiveTransform_64f(const double* src, double* dst, const double* m, int le void cv::perspectiveTransform( InputArray _src, OutputArray _dst, InputArray _mtx ) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(), m = _mtx.getMat(); int depth = src.depth(), scn = src.channels(), dcn = m.rows-1; CV_Assert( scn + 1 == m.cols ); @@ -2454,6 +2460,8 @@ static bool ocl_scaleAdd( InputArray _src1, double alpha, InputArray _src2, Outp void cv::scaleAdd( InputArray _src1, double alpha, InputArray _src2, OutputArray _dst ) { + CV_INSTRUMENT_REGION() + int type = _src1.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); CV_Assert( type == _src2.type() ); @@ -2499,6 +2507,8 @@ void cv::scaleAdd( InputArray _src1, double alpha, InputArray _src2, OutputArray void cv::calcCovarMatrix( const Mat* data, int nsamples, Mat& covar, Mat& _mean, int flags, int ctype ) { + CV_INSTRUMENT_REGION() + CV_Assert( data && nsamples > 0 ); Size size = data[0].size(); int sz = size.width * size.height, esz = (int)data[0].elemSize(); @@ -2539,6 +2549,8 @@ void cv::calcCovarMatrix( const Mat* data, int nsamples, Mat& covar, Mat& _mean, void cv::calcCovarMatrix( InputArray _src, OutputArray _covar, InputOutputArray _mean, int flags, int ctype ) { + CV_INSTRUMENT_REGION() + if(_src.kind() == _InputArray::STD_VECTOR_MAT) { std::vector src; @@ -2626,6 +2638,8 @@ void cv::calcCovarMatrix( InputArray _src, OutputArray _covar, InputOutputArray double cv::Mahalanobis( InputArray _v1, InputArray _v2, InputArray _icovar ) { + CV_INSTRUMENT_REGION() + Mat v1 = _v1.getMat(), v2 = _v2.getMat(), icovar = _icovar.getMat(); int type = v1.type(), depth = v1.depth(); Size sz = v1.size(); @@ -2916,6 +2930,8 @@ typedef void (*MulTransposedFunc)(const Mat& src, Mat& dst, const Mat& delta, do void cv::mulTransposed( InputArray _src, OutputArray _dst, bool ata, InputArray _delta, double scale, int dtype ) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(), delta = _delta.getMat(); const int gemm_level = 100; // boundary above which GEMM is faster. int stype = src.type(); @@ -3059,9 +3075,9 @@ static double dotProd_8u(const uchar* src1, const uchar* src2, int len) #if ARITHM_USE_IPP && IPP_DISABLE_BLOCK CV_IPP_CHECK() { - if (0 <= ippiDotProd_8u64f_C1R(src1, (int)(len*sizeof(src1[0])), + if (0 <= CV_INSTRUMENT_FUN_IPP(ippiDotProd_8u64f_C1R, (src1, (int)(len*sizeof(src1[0])), src2, (int)(len*sizeof(src2[0])), - ippiSize(len, 1), &r)) + ippiSize(len, 1), &r))) { CV_IMPL_ADD(CV_IMPL_IPP); return r; @@ -3258,7 +3274,7 @@ static double dotProd_16u(const ushort* src1, const ushort* src2, int len) CV_IPP_CHECK() { double r = 0; - if (0 <= ippiDotProd_16u64f_C1R(src1, (int)(len*sizeof(src1[0])), src2, (int)(len*sizeof(src2[0])), ippiSize(len, 1), &r)) + if (0 <= CV_INSTRUMENT_FUN_IPP(ippiDotProd_16u64f_C1R, src1, (int)(len*sizeof(src1[0])), src2, (int)(len*sizeof(src2[0])), ippiSize(len, 1), &r)) { CV_IMPL_ADD(CV_IMPL_IPP); return r; @@ -3275,7 +3291,7 @@ static double dotProd_16s(const short* src1, const short* src2, int len) CV_IPP_CHECK() { double r = 0; - if (0 <= ippiDotProd_16s64f_C1R(src1, (int)(len*sizeof(src1[0])), src2, (int)(len*sizeof(src2[0])), ippiSize(len, 1), &r)) + if (0 <= CV_INSTRUMENT_FUN_IPP(ippiDotProd_16s64f_C1R, src1, (int)(len*sizeof(src1[0])), src2, (int)(len*sizeof(src2[0])), ippiSize(len, 1), &r)) { CV_IMPL_ADD(CV_IMPL_IPP); return r; @@ -3292,7 +3308,7 @@ static double dotProd_32s(const int* src1, const int* src2, int len) CV_IPP_CHECK() { double r = 0; - if (0 <= ippiDotProd_32s64f_C1R(src1, (int)(len*sizeof(src1[0])), src2, (int)(len*sizeof(src2[0])), ippiSize(len, 1), &r)) + if (0 <= CV_INSTRUMENT_FUN_IPP(ippiDotProd_32s64f_C1R, src1, (int)(len*sizeof(src1[0])), src2, (int)(len*sizeof(src2[0])), ippiSize(len, 1), &r)) { CV_IMPL_ADD(CV_IMPL_IPP); return r; @@ -3311,7 +3327,7 @@ static double dotProd_32f(const float* src1, const float* src2, int len) #if (ARITHM_USE_IPP == 1) CV_IPP_CHECK() { - if (0 <= ippsDotProd_32f64f(src1, src2, len, &r)) + if (0 <= CV_INSTRUMENT_FUN_IPP(ippsDotProd_32f64f, src1, src2, len, &r)) { CV_IMPL_ADD(CV_IMPL_IPP); return r; @@ -3349,7 +3365,7 @@ static double dotProd_64f(const double* src1, const double* src2, int len) CV_IPP_CHECK() { double r = 0; - if (0 <= ippsDotProd_64f(src1, src2, len, &r)) + if (0 <= CV_INSTRUMENT_FUN_IPP(ippsDotProd_64f, src1, src2, len, &r)) { CV_IMPL_ADD(CV_IMPL_IPP); return r; @@ -3378,6 +3394,8 @@ static DotProdFunc getDotProdFunc(int depth) double Mat::dot(InputArray _mat) const { + CV_INSTRUMENT_REGION() + Mat mat = _mat.getMat(); int cn = channels(); DotProdFunc func = getDotProdFunc(depth()); diff --git a/modules/core/src/matop.cpp b/modules/core/src/matop.cpp index 2a6ec2635c..e7cfa01730 100644 --- a/modules/core/src/matop.cpp +++ b/modules/core/src/matop.cpp @@ -333,6 +333,8 @@ void MatOp::augAssignXor(const MatExpr& expr, Mat& m) const void MatOp::add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const { + CV_INSTRUMENT_REGION() + if( this == e2.op ) { double alpha = 1, beta = 1; @@ -364,6 +366,8 @@ void MatOp::add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const void MatOp::add(const MatExpr& expr1, const Scalar& s, MatExpr& res) const { + CV_INSTRUMENT_REGION() + Mat m1; expr1.op->assign(expr1, m1); MatOp_AddEx::makeExpr(res, m1, Mat(), 1, 0, s); @@ -372,6 +376,8 @@ void MatOp::add(const MatExpr& expr1, const Scalar& s, MatExpr& res) const void MatOp::subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const { + CV_INSTRUMENT_REGION() + if( this == e2.op ) { double alpha = 1, beta = -1; @@ -403,6 +409,8 @@ void MatOp::subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const void MatOp::subtract(const Scalar& s, const MatExpr& expr, MatExpr& res) const { + CV_INSTRUMENT_REGION() + Mat m; expr.op->assign(expr, m); MatOp_AddEx::makeExpr(res, m, Mat(), -1, 0, s); @@ -411,6 +419,8 @@ void MatOp::subtract(const Scalar& s, const MatExpr& expr, MatExpr& res) const void MatOp::multiply(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale) const { + CV_INSTRUMENT_REGION() + if( this == e2.op ) { Mat m1, m2; @@ -462,6 +472,8 @@ void MatOp::multiply(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double void MatOp::multiply(const MatExpr& expr, double s, MatExpr& res) const { + CV_INSTRUMENT_REGION() + Mat m; expr.op->assign(expr, m); MatOp_AddEx::makeExpr(res, m, Mat(), s, 0); @@ -470,6 +482,8 @@ void MatOp::multiply(const MatExpr& expr, double s, MatExpr& res) const void MatOp::divide(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale) const { + CV_INSTRUMENT_REGION() + if( this == e2.op ) { if( isReciprocal(e1) && isReciprocal(e2) ) @@ -510,6 +524,8 @@ void MatOp::divide(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double sc void MatOp::divide(double s, const MatExpr& expr, MatExpr& res) const { + CV_INSTRUMENT_REGION() + Mat m; expr.op->assign(expr, m); MatOp_Bin::makeExpr(res, '/', m, Mat(), s); @@ -518,6 +534,8 @@ void MatOp::divide(double s, const MatExpr& expr, MatExpr& res) const void MatOp::abs(const MatExpr& expr, MatExpr& res) const { + CV_INSTRUMENT_REGION() + Mat m; expr.op->assign(expr, m); MatOp_Bin::makeExpr(res, 'a', m, Mat()); @@ -526,6 +544,8 @@ void MatOp::abs(const MatExpr& expr, MatExpr& res) const void MatOp::transpose(const MatExpr& expr, MatExpr& res) const { + CV_INSTRUMENT_REGION() + Mat m; expr.op->assign(expr, m); MatOp_T::makeExpr(res, m, 1); @@ -590,6 +610,8 @@ Size MatOp::size(const MatExpr& expr) const int MatOp::type(const MatExpr& expr) const { + CV_INSTRUMENT_REGION() + return !expr.a.empty() ? expr.a.type() : expr.b.empty() ? expr.b.type() : expr.c.type(); } @@ -1038,6 +1060,8 @@ MatExpr operator > (double s, const Mat& a) MatExpr min(const Mat& a, const Mat& b) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Bin::makeExpr(e, 'm', a, b); return e; @@ -1045,6 +1069,8 @@ MatExpr min(const Mat& a, const Mat& b) MatExpr min(const Mat& a, double s) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Bin::makeExpr(e, 'n', a, s); return e; @@ -1052,6 +1078,8 @@ MatExpr min(const Mat& a, double s) MatExpr min(double s, const Mat& a) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Bin::makeExpr(e, 'n', a, s); return e; @@ -1059,6 +1087,8 @@ MatExpr min(double s, const Mat& a) MatExpr max(const Mat& a, const Mat& b) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Bin::makeExpr(e, 'M', a, b); return e; @@ -1066,6 +1096,8 @@ MatExpr max(const Mat& a, const Mat& b) MatExpr max(const Mat& a, double s) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Bin::makeExpr(e, 'N', a, s); return e; @@ -1073,6 +1105,8 @@ MatExpr max(const Mat& a, double s) MatExpr max(double s, const Mat& a) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Bin::makeExpr(e, 'N', a, s); return e; @@ -1150,6 +1184,8 @@ MatExpr operator ~(const Mat& a) MatExpr abs(const Mat& a) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Bin::makeExpr(e, 'a', a, Scalar()); return e; @@ -1157,6 +1193,8 @@ MatExpr abs(const Mat& a) MatExpr abs(const MatExpr& e) { + CV_INSTRUMENT_REGION() + MatExpr en; e.op->abs(e, en); return en; @@ -1179,6 +1217,8 @@ Size MatExpr::size() const int MatExpr::type() const { + CV_INSTRUMENT_REGION() + if( isInitializer(*this) ) return a.type(); if( isCmp(*this) ) @@ -1261,6 +1301,8 @@ void MatOp_AddEx::assign(const MatExpr& e, Mat& m, int _type) const void MatOp_AddEx::add(const MatExpr& e, const Scalar& s, MatExpr& res) const { + CV_INSTRUMENT_REGION() + res = e; res.s += s; } @@ -1268,6 +1310,8 @@ void MatOp_AddEx::add(const MatExpr& e, const Scalar& s, MatExpr& res) const void MatOp_AddEx::subtract(const Scalar& s, const MatExpr& e, MatExpr& res) const { + CV_INSTRUMENT_REGION() + res = e; res.alpha = -res.alpha; res.beta = -res.beta; @@ -1276,6 +1320,8 @@ void MatOp_AddEx::subtract(const Scalar& s, const MatExpr& e, MatExpr& res) cons void MatOp_AddEx::multiply(const MatExpr& e, double s, MatExpr& res) const { + CV_INSTRUMENT_REGION() + res = e; res.alpha *= s; res.beta *= s; @@ -1284,6 +1330,8 @@ void MatOp_AddEx::multiply(const MatExpr& e, double s, MatExpr& res) const void MatOp_AddEx::divide(double s, const MatExpr& e, MatExpr& res) const { + CV_INSTRUMENT_REGION() + if( isScaled(e) ) MatOp_Bin::makeExpr(res, '/', e.a, Mat(), s/e.alpha); else @@ -1293,6 +1341,8 @@ void MatOp_AddEx::divide(double s, const MatExpr& e, MatExpr& res) const void MatOp_AddEx::transpose(const MatExpr& e, MatExpr& res) const { + CV_INSTRUMENT_REGION() + if( isScaled(e) ) MatOp_T::makeExpr(res, e.a, e.alpha); else @@ -1301,6 +1351,8 @@ void MatOp_AddEx::transpose(const MatExpr& e, MatExpr& res) const void MatOp_AddEx::abs(const MatExpr& e, MatExpr& res) const { + CV_INSTRUMENT_REGION() + if( (!e.b.data || e.beta == 0) && fabs(e.alpha) == 1 ) MatOp_Bin::makeExpr(res, 'a', e.a, -e.s*e.alpha); else if( e.b.data && e.alpha + e.beta == 0 && e.alpha*e.beta == -1 ) @@ -1361,6 +1413,8 @@ void MatOp_Bin::assign(const MatExpr& e, Mat& m, int _type) const void MatOp_Bin::multiply(const MatExpr& e, double s, MatExpr& res) const { + CV_INSTRUMENT_REGION() + if( e.flags == '*' || e.flags == '/' ) { res = e; @@ -1372,6 +1426,8 @@ void MatOp_Bin::multiply(const MatExpr& e, double s, MatExpr& res) const void MatOp_Bin::divide(double s, const MatExpr& e, MatExpr& res) const { + CV_INSTRUMENT_REGION() + if( e.flags == '/' && (!e.b.data || e.beta == 0) ) MatOp_AddEx::makeExpr(res, e.a, Mat(), s/e.alpha, 0); else @@ -1427,12 +1483,16 @@ void MatOp_T::assign(const MatExpr& e, Mat& m, int _type) const void MatOp_T::multiply(const MatExpr& e, double s, MatExpr& res) const { + CV_INSTRUMENT_REGION() + res = e; res.alpha *= s; } void MatOp_T::transpose(const MatExpr& e, MatExpr& res) const { + CV_INSTRUMENT_REGION() + if( e.alpha == 1 ) MatOp_Identity::makeExpr(res, e.a); else @@ -1457,6 +1517,8 @@ void MatOp_GEMM::assign(const MatExpr& e, Mat& m, int _type) const void MatOp_GEMM::add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const { + CV_INSTRUMENT_REGION() + bool i1 = isIdentity(e1), i2 = isIdentity(e2); double alpha1 = i1 ? 1 : e1.alpha, alpha2 = i2 ? 1 : e2.alpha; @@ -1474,6 +1536,8 @@ void MatOp_GEMM::add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const void MatOp_GEMM::subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const { + CV_INSTRUMENT_REGION() + bool i1 = isIdentity(e1), i2 = isIdentity(e2); double alpha1 = i1 ? 1 : e1.alpha, alpha2 = i2 ? 1 : e2.alpha; @@ -1491,6 +1555,8 @@ void MatOp_GEMM::subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) co void MatOp_GEMM::multiply(const MatExpr& e, double s, MatExpr& res) const { + CV_INSTRUMENT_REGION() + res = e; res.alpha *= s; res.beta *= s; @@ -1498,6 +1564,8 @@ void MatOp_GEMM::multiply(const MatExpr& e, double s, MatExpr& res) const void MatOp_GEMM::transpose(const MatExpr& e, MatExpr& res) const { + CV_INSTRUMENT_REGION() + res = e; res.flags = (!(e.flags & CV_GEMM_A_T) ? CV_GEMM_B_T : 0) | (!(e.flags & CV_GEMM_B_T) ? CV_GEMM_A_T : 0) | @@ -1577,6 +1645,8 @@ void MatOp_Initializer::assign(const MatExpr& e, Mat& m, int _type) const void MatOp_Initializer::multiply(const MatExpr& e, double s, MatExpr& res) const { + CV_INSTRUMENT_REGION() + res = e; res.alpha *= s; } @@ -1595,6 +1665,8 @@ inline void MatOp_Initializer::makeExpr(MatExpr& res, int method, int ndims, con MatExpr Mat::t() const { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_T::makeExpr(e, *this); return e; @@ -1602,6 +1674,8 @@ MatExpr Mat::t() const MatExpr Mat::inv(int method) const { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Invert::makeExpr(e, method, *this); return e; @@ -1610,6 +1684,8 @@ MatExpr Mat::inv(int method) const MatExpr Mat::mul(InputArray m, double scale) const { + CV_INSTRUMENT_REGION() + MatExpr e; if(m.kind() == _InputArray::EXPR) { @@ -1623,6 +1699,8 @@ MatExpr Mat::mul(InputArray m, double scale) const MatExpr Mat::zeros(int rows, int cols, int type) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Initializer::makeExpr(e, '0', Size(cols, rows), type); return e; @@ -1630,6 +1708,8 @@ MatExpr Mat::zeros(int rows, int cols, int type) MatExpr Mat::zeros(Size size, int type) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Initializer::makeExpr(e, '0', size, type); return e; @@ -1637,6 +1717,8 @@ MatExpr Mat::zeros(Size size, int type) MatExpr Mat::zeros(int ndims, const int* sizes, int type) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Initializer::makeExpr(e, '0', ndims, sizes, type); return e; @@ -1644,6 +1726,8 @@ MatExpr Mat::zeros(int ndims, const int* sizes, int type) MatExpr Mat::ones(int rows, int cols, int type) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Initializer::makeExpr(e, '1', Size(cols, rows), type); return e; @@ -1651,6 +1735,8 @@ MatExpr Mat::ones(int rows, int cols, int type) MatExpr Mat::ones(Size size, int type) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Initializer::makeExpr(e, '1', size, type); return e; @@ -1658,6 +1744,8 @@ MatExpr Mat::ones(Size size, int type) MatExpr Mat::ones(int ndims, const int* sizes, int type) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Initializer::makeExpr(e, '1', ndims, sizes, type); return e; @@ -1665,6 +1753,8 @@ MatExpr Mat::ones(int ndims, const int* sizes, int type) MatExpr Mat::eye(int rows, int cols, int type) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Initializer::makeExpr(e, 'I', Size(cols, rows), type); return e; @@ -1672,6 +1762,8 @@ MatExpr Mat::eye(int rows, int cols, int type) MatExpr Mat::eye(Size size, int type) { + CV_INSTRUMENT_REGION() + MatExpr e; MatOp_Initializer::makeExpr(e, 'I', size, type); return e; diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 02160ecd61..f98155cd3c 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -130,6 +130,8 @@ void MatAllocator::copy(UMatData* usrc, UMatData* udst, int dims, const size_t s const size_t srcofs[], const size_t srcstep[], const size_t dstofs[], const size_t dststep[], bool /*sync*/) const { + CV_INSTRUMENT_REGION() + if(!usrc || !udst) return; int isz[CV_MAX_DIM]; @@ -1056,6 +1058,8 @@ int Mat::checkVector(int _elemChannels, int _depth, bool _requireContinuous) con void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to) { + CV_INSTRUMENT_REGION() + int i, depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); CV_Assert(cn <= 4); switch(depth) @@ -2802,6 +2806,8 @@ InputOutputArray noArray() { return _none; } void cv::hconcat(const Mat* src, size_t nsrc, OutputArray _dst) { + CV_INSTRUMENT_REGION() + if( nsrc == 0 || !src ) { _dst.release(); @@ -2829,12 +2835,16 @@ void cv::hconcat(const Mat* src, size_t nsrc, OutputArray _dst) void cv::hconcat(InputArray src1, InputArray src2, OutputArray dst) { + CV_INSTRUMENT_REGION() + Mat src[] = {src1.getMat(), src2.getMat()}; hconcat(src, 2, dst); } void cv::hconcat(InputArray _src, OutputArray dst) { + CV_INSTRUMENT_REGION() + std::vector src; _src.getMatVector(src); hconcat(!src.empty() ? &src[0] : 0, src.size(), dst); @@ -2842,6 +2852,8 @@ void cv::hconcat(InputArray _src, OutputArray dst) void cv::vconcat(const Mat* src, size_t nsrc, OutputArray _dst) { + CV_INSTRUMENT_REGION() + if( nsrc == 0 || !src ) { _dst.release(); @@ -2869,12 +2881,16 @@ void cv::vconcat(const Mat* src, size_t nsrc, OutputArray _dst) void cv::vconcat(InputArray src1, InputArray src2, OutputArray dst) { + CV_INSTRUMENT_REGION() + Mat src[] = {src1.getMat(), src2.getMat()}; vconcat(src, 2, dst); } void cv::vconcat(InputArray _src, OutputArray dst) { + CV_INSTRUMENT_REGION() + std::vector src; _src.getMatVector(src); vconcat(!src.empty() ? &src[0] : 0, src.size(), dst); @@ -2924,6 +2940,8 @@ static bool ocl_setIdentity( InputOutputArray _m, const Scalar& s ) void cv::setIdentity( InputOutputArray _m, const Scalar& s ) { + CV_INSTRUMENT_REGION() + CV_Assert( _m.dims() <= 2 ); CV_OCL_RUN(_m.isUMat(), @@ -2969,6 +2987,8 @@ void cv::setIdentity( InputOutputArray _m, const Scalar& s ) cv::Scalar cv::trace( InputArray _m ) { + CV_INSTRUMENT_REGION() + Mat m = _m.getMat(); CV_Assert( m.dims <= 2 ); int i, type = m.type(); @@ -3170,62 +3190,64 @@ static bool ocl_transpose( InputArray _src, OutputArray _dst ) #ifdef HAVE_IPP static bool ipp_transpose( Mat &src, Mat &dst ) { + CV_INSTRUMENT_REGION_IPP() + int type = src.type(); - typedef IppStatus (CV_STDCALL * ippiTranspose)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize); - typedef IppStatus (CV_STDCALL * ippiTransposeI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize); - ippiTranspose ippFunc = 0; - ippiTransposeI ippFuncI = 0; + typedef IppStatus (CV_STDCALL * IppiTranspose)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize); + typedef IppStatus (CV_STDCALL * IppiTransposeI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize); + IppiTranspose ippiTranspose = 0; + IppiTransposeI ippiTranspose_I = 0; if (dst.data == src.data && dst.cols == dst.rows) { CV_SUPPRESS_DEPRECATED_START - ippFuncI = - type == CV_8UC1 ? (ippiTransposeI)ippiTranspose_8u_C1IR : - type == CV_8UC3 ? (ippiTransposeI)ippiTranspose_8u_C3IR : - type == CV_8UC4 ? (ippiTransposeI)ippiTranspose_8u_C4IR : - type == CV_16UC1 ? (ippiTransposeI)ippiTranspose_16u_C1IR : - type == CV_16UC3 ? (ippiTransposeI)ippiTranspose_16u_C3IR : - type == CV_16UC4 ? (ippiTransposeI)ippiTranspose_16u_C4IR : - type == CV_16SC1 ? (ippiTransposeI)ippiTranspose_16s_C1IR : - type == CV_16SC3 ? (ippiTransposeI)ippiTranspose_16s_C3IR : - type == CV_16SC4 ? (ippiTransposeI)ippiTranspose_16s_C4IR : - type == CV_32SC1 ? (ippiTransposeI)ippiTranspose_32s_C1IR : - type == CV_32SC3 ? (ippiTransposeI)ippiTranspose_32s_C3IR : - type == CV_32SC4 ? (ippiTransposeI)ippiTranspose_32s_C4IR : - type == CV_32FC1 ? (ippiTransposeI)ippiTranspose_32f_C1IR : - type == CV_32FC3 ? (ippiTransposeI)ippiTranspose_32f_C3IR : - type == CV_32FC4 ? (ippiTransposeI)ippiTranspose_32f_C4IR : 0; + ippiTranspose_I = + type == CV_8UC1 ? (IppiTransposeI)ippiTranspose_8u_C1IR : + type == CV_8UC3 ? (IppiTransposeI)ippiTranspose_8u_C3IR : + type == CV_8UC4 ? (IppiTransposeI)ippiTranspose_8u_C4IR : + type == CV_16UC1 ? (IppiTransposeI)ippiTranspose_16u_C1IR : + type == CV_16UC3 ? (IppiTransposeI)ippiTranspose_16u_C3IR : + type == CV_16UC4 ? (IppiTransposeI)ippiTranspose_16u_C4IR : + type == CV_16SC1 ? (IppiTransposeI)ippiTranspose_16s_C1IR : + type == CV_16SC3 ? (IppiTransposeI)ippiTranspose_16s_C3IR : + type == CV_16SC4 ? (IppiTransposeI)ippiTranspose_16s_C4IR : + type == CV_32SC1 ? (IppiTransposeI)ippiTranspose_32s_C1IR : + type == CV_32SC3 ? (IppiTransposeI)ippiTranspose_32s_C3IR : + type == CV_32SC4 ? (IppiTransposeI)ippiTranspose_32s_C4IR : + type == CV_32FC1 ? (IppiTransposeI)ippiTranspose_32f_C1IR : + type == CV_32FC3 ? (IppiTransposeI)ippiTranspose_32f_C3IR : + type == CV_32FC4 ? (IppiTransposeI)ippiTranspose_32f_C4IR : 0; CV_SUPPRESS_DEPRECATED_END } else { - ippFunc = - type == CV_8UC1 ? (ippiTranspose)ippiTranspose_8u_C1R : - type == CV_8UC3 ? (ippiTranspose)ippiTranspose_8u_C3R : - type == CV_8UC4 ? (ippiTranspose)ippiTranspose_8u_C4R : - type == CV_16UC1 ? (ippiTranspose)ippiTranspose_16u_C1R : - type == CV_16UC3 ? (ippiTranspose)ippiTranspose_16u_C3R : - type == CV_16UC4 ? (ippiTranspose)ippiTranspose_16u_C4R : - type == CV_16SC1 ? (ippiTranspose)ippiTranspose_16s_C1R : - type == CV_16SC3 ? (ippiTranspose)ippiTranspose_16s_C3R : - type == CV_16SC4 ? (ippiTranspose)ippiTranspose_16s_C4R : - type == CV_32SC1 ? (ippiTranspose)ippiTranspose_32s_C1R : - type == CV_32SC3 ? (ippiTranspose)ippiTranspose_32s_C3R : - type == CV_32SC4 ? (ippiTranspose)ippiTranspose_32s_C4R : - type == CV_32FC1 ? (ippiTranspose)ippiTranspose_32f_C1R : - type == CV_32FC3 ? (ippiTranspose)ippiTranspose_32f_C3R : - type == CV_32FC4 ? (ippiTranspose)ippiTranspose_32f_C4R : 0; + ippiTranspose = + type == CV_8UC1 ? (IppiTranspose)ippiTranspose_8u_C1R : + type == CV_8UC3 ? (IppiTranspose)ippiTranspose_8u_C3R : + type == CV_8UC4 ? (IppiTranspose)ippiTranspose_8u_C4R : + type == CV_16UC1 ? (IppiTranspose)ippiTranspose_16u_C1R : + type == CV_16UC3 ? (IppiTranspose)ippiTranspose_16u_C3R : + type == CV_16UC4 ? (IppiTranspose)ippiTranspose_16u_C4R : + type == CV_16SC1 ? (IppiTranspose)ippiTranspose_16s_C1R : + type == CV_16SC3 ? (IppiTranspose)ippiTranspose_16s_C3R : + type == CV_16SC4 ? (IppiTranspose)ippiTranspose_16s_C4R : + type == CV_32SC1 ? (IppiTranspose)ippiTranspose_32s_C1R : + type == CV_32SC3 ? (IppiTranspose)ippiTranspose_32s_C3R : + type == CV_32SC4 ? (IppiTranspose)ippiTranspose_32s_C4R : + type == CV_32FC1 ? (IppiTranspose)ippiTranspose_32f_C1R : + type == CV_32FC3 ? (IppiTranspose)ippiTranspose_32f_C3R : + type == CV_32FC4 ? (IppiTranspose)ippiTranspose_32f_C4R : 0; } IppiSize roiSize = { src.cols, src.rows }; - if (ippFunc != 0) + if (ippiTranspose != 0) { - if (ippFunc(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize) >= 0) + if (CV_INSTRUMENT_FUN_IPP(ippiTranspose, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize) >= 0) return true; } - else if (ippFuncI != 0) + else if (ippiTranspose_I != 0) { - if (ippFuncI(dst.ptr(), (int)dst.step, roiSize) >= 0) + if (CV_INSTRUMENT_FUN_IPP(ippiTranspose_I, dst.ptr(), (int)dst.step, roiSize) >= 0) return true; } return false; @@ -3237,6 +3259,8 @@ static bool ipp_transpose( Mat &src, Mat &dst ) void cv::transpose( InputArray _src, OutputArray _dst ) { + CV_INSTRUMENT_REGION() + int type = _src.type(), esz = CV_ELEM_SIZE(type); CV_Assert( _src.dims() <= 2 && esz <= 32 ); @@ -3261,7 +3285,7 @@ void cv::transpose( InputArray _src, OutputArray _dst ) return; } - CV_IPP_RUN(true, ipp_transpose(src, dst)) + CV_IPP_RUN_FAST(ipp_transpose(src, dst)) if( dst.data == src.data ) { @@ -3283,6 +3307,8 @@ void cv::transpose( InputArray _src, OutputArray _dst ) void cv::completeSymm( InputOutputArray _m, bool LtoR ) { + CV_INSTRUMENT_REGION() + Mat m = _m.getMat(); size_t step = m.step, esz = m.elemSize(); CV_Assert( m.dims <= 2 && m.rows == m.cols ); @@ -3458,43 +3484,43 @@ static inline bool ipp_reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat IppiSize roisize = { srcmat.size().width, 1 }; - typedef IppStatus (CV_STDCALL * ippiSum)(const void * pSrc, int srcStep, IppiSize roiSize, Ipp64f* pSum); - typedef IppStatus (CV_STDCALL * ippiSumHint)(const void * pSrc, int srcStep, IppiSize roiSize, Ipp64f* pSum, IppHintAlgorithm hint); - ippiSum ippFunc = 0; - ippiSumHint ippFuncHint = 0; + typedef IppStatus (CV_STDCALL * IppiSum)(const void * pSrc, int srcStep, IppiSize roiSize, Ipp64f* pSum); + typedef IppStatus (CV_STDCALL * IppiSumHint)(const void * pSrc, int srcStep, IppiSize roiSize, Ipp64f* pSum, IppHintAlgorithm hint); + IppiSum ippiSum = 0; + IppiSumHint ippiSumHint = 0; if(ddepth == CV_64F) { - ippFunc = - stype == CV_8UC1 ? (ippiSum)ippiSum_8u_C1R : - stype == CV_8UC3 ? (ippiSum)ippiSum_8u_C3R : - stype == CV_8UC4 ? (ippiSum)ippiSum_8u_C4R : - stype == CV_16UC1 ? (ippiSum)ippiSum_16u_C1R : - stype == CV_16UC3 ? (ippiSum)ippiSum_16u_C3R : - stype == CV_16UC4 ? (ippiSum)ippiSum_16u_C4R : - stype == CV_16SC1 ? (ippiSum)ippiSum_16s_C1R : - stype == CV_16SC3 ? (ippiSum)ippiSum_16s_C3R : - stype == CV_16SC4 ? (ippiSum)ippiSum_16s_C4R : 0; - ippFuncHint = - stype == CV_32FC1 ? (ippiSumHint)ippiSum_32f_C1R : - stype == CV_32FC3 ? (ippiSumHint)ippiSum_32f_C3R : - stype == CV_32FC4 ? (ippiSumHint)ippiSum_32f_C4R : 0; + ippiSum = + stype == CV_8UC1 ? (IppiSum)ippiSum_8u_C1R : + stype == CV_8UC3 ? (IppiSum)ippiSum_8u_C3R : + stype == CV_8UC4 ? (IppiSum)ippiSum_8u_C4R : + stype == CV_16UC1 ? (IppiSum)ippiSum_16u_C1R : + stype == CV_16UC3 ? (IppiSum)ippiSum_16u_C3R : + stype == CV_16UC4 ? (IppiSum)ippiSum_16u_C4R : + stype == CV_16SC1 ? (IppiSum)ippiSum_16s_C1R : + stype == CV_16SC3 ? (IppiSum)ippiSum_16s_C3R : + stype == CV_16SC4 ? (IppiSum)ippiSum_16s_C4R : 0; + ippiSumHint = + stype == CV_32FC1 ? (IppiSumHint)ippiSum_32f_C1R : + stype == CV_32FC3 ? (IppiSumHint)ippiSum_32f_C3R : + stype == CV_32FC4 ? (IppiSumHint)ippiSum_32f_C4R : 0; } - if(ippFunc) + if(ippiSum) { for(int y = 0; y < srcmat.size().height; y++) { - if(ippFunc(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y)) < 0) + if(CV_INSTRUMENT_FUN_IPP(ippiSum, srcmat.ptr(y), sstep, roisize, dstmat.ptr(y)) < 0) return false; } return true; } - else if(ippFuncHint) + else if(ippiSumHint) { for(int y = 0; y < srcmat.size().height; y++) { - if(ippFuncHint(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y), ippAlgHintAccurate) < 0) + if(CV_INSTRUMENT_FUN_IPP(ippiSumHint, srcmat.ptr(y), sstep, roisize, dstmat.ptr(y), ippAlgHintAccurate) < 0) return false; } return true; @@ -3505,7 +3531,7 @@ static inline bool ipp_reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat) { - CV_IPP_RUN(true, ipp_reduceSumC_8u16u16s32f_64f(srcmat, dstmat)); + CV_IPP_RUN_FAST(ipp_reduceSumC_8u16u16s32f_64f(srcmat, dstmat)); cv::ReduceFunc func = 0; @@ -3555,7 +3581,7 @@ static inline bool ipp_reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& IppiSize roisize = ippiSize(srcmat.size().width, 1);\ for(int y = 0; y < srcmat.size().height; y++)\ {\ - if(ippi##optype##_##favor##_C1R(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y)) < 0)\ + if(CV_INSTRUMENT_FUN_IPP(ippi##optype##_##favor##_C1R, srcmat.ptr(y), sstep, roisize, dstmat.ptr(y)) < 0)\ return false;\ }\ return true;\ @@ -3564,7 +3590,7 @@ static inline bool ipp_reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& } \ static inline void reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstmat) \ { \ - CV_IPP_RUN(true, ipp_reduce##optype##C##favor(srcmat, dstmat)); \ + CV_IPP_RUN_FAST(ipp_reduce##optype##C##favor(srcmat, dstmat)); \ cv::reduceC_ < type1, type2, cv::Op##optype < type2 > >(srcmat, dstmat); \ } #endif @@ -3704,6 +3730,8 @@ static bool ocl_reduce(InputArray _src, OutputArray _dst, void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype) { + CV_INSTRUMENT_REGION() + CV_Assert( _src.dims() <= 2 ); int op0 = op; int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); @@ -3948,7 +3976,7 @@ template static void sort_( const Mat& src, Mat& dst, int flags ) } #ifdef USE_IPP_SORT - if (!ippSortFunc || ippSortFunc(ptr, len) < 0) + if (!ippSortFunc || CV_INSTRUMENT_FUN_IPP(ippSortFunc, ptr, len) < 0) #endif { #ifdef USE_IPP_SORT @@ -3959,7 +3987,7 @@ template static void sort_( const Mat& src, Mat& dst, int flags ) if( sortDescending ) { #ifdef USE_IPP_SORT - if (!ippFlipFunc || ippFlipFunc(ptr, len) < 0) + if (!ippFlipFunc || CV_INSTRUMENT_FUN_IPP(ippFlipFunc, ptr, len) < 0) #endif { #ifdef USE_IPP_SORT @@ -4120,6 +4148,8 @@ typedef void (*SortFunc)(const Mat& src, Mat& dst, int flags); void cv::sort( InputArray _src, OutputArray _dst, int flags ) { + CV_INSTRUMENT_REGION() + static SortFunc tab[] = { sort_, sort_, sort_, sort_, @@ -4135,6 +4165,8 @@ void cv::sort( InputArray _src, OutputArray _dst, int flags ) void cv::sortIdx( InputArray _src, OutputArray _dst, int flags ) { + CV_INSTRUMENT_REGION() + static SortFunc tab[] = { sortIdx_, sortIdx_, sortIdx_, sortIdx_, @@ -5341,6 +5373,8 @@ SparseMatConstIterator& SparseMatConstIterator::operator ++() double norm( const SparseMat& src, int normType ) { + CV_INSTRUMENT_REGION() + SparseMatConstIterator it = src.begin(); size_t i, N = src.nzcount(); @@ -5390,6 +5424,8 @@ double norm( const SparseMat& src, int normType ) void minMaxLoc( const SparseMat& src, double* _minval, double* _maxval, int* _minidx, int* _maxidx ) { + CV_INSTRUMENT_REGION() + SparseMatConstIterator it = src.begin(); size_t i, N = src.nzcount(), d = src.hdr ? src.hdr->dims : 0; int type = src.type(); @@ -5453,6 +5489,8 @@ void minMaxLoc( const SparseMat& src, double* _minval, double* _maxval, int* _mi void normalize( const SparseMat& src, SparseMat& dst, double a, int norm_type ) { + CV_INSTRUMENT_REGION() + double scale = 1; if( norm_type == CV_L2 || norm_type == CV_L1 || norm_type == CV_C ) { diff --git a/modules/core/src/matrix_decomp.cpp b/modules/core/src/matrix_decomp.cpp index 5b0d62a967..58829b56f8 100644 --- a/modules/core/src/matrix_decomp.cpp +++ b/modules/core/src/matrix_decomp.cpp @@ -109,6 +109,8 @@ LUImpl(_Tp* A, size_t astep, int m, _Tp* b, size_t bstep, int n, _Tp eps) int LU32f(float* A, size_t astep, int m, float* b, size_t bstep, int n) { + CV_INSTRUMENT_REGION() + int output; CALL_HAL_RET(LU32f, cv_hal_LU32f, output, A, astep, m, b, bstep, n) output = LUImpl(A, astep, m, b, bstep, n, FLT_EPSILON*10); @@ -118,6 +120,8 @@ int LU32f(float* A, size_t astep, int m, float* b, size_t bstep, int n) int LU64f(double* A, size_t astep, int m, double* b, size_t bstep, int n) { + CV_INSTRUMENT_REGION() + int output; CALL_HAL_RET(LU64f, cv_hal_LU64f, output, A, astep, m, b, bstep, n) output = LUImpl(A, astep, m, b, bstep, n, DBL_EPSILON*100); @@ -205,6 +209,8 @@ CholImpl(_Tp* A, size_t astep, int m, _Tp* b, size_t bstep, int n) bool Cholesky32f(float* A, size_t astep, int m, float* b, size_t bstep, int n) { + CV_INSTRUMENT_REGION() + bool output; CALL_HAL_RET(Cholesky32f, cv_hal_Cholesky32f, output, A, astep, m, b, bstep, n) return CholImpl(A, astep, m, b, bstep, n); @@ -212,6 +218,8 @@ bool Cholesky32f(float* A, size_t astep, int m, float* b, size_t bstep, int n) bool Cholesky64f(double* A, size_t astep, int m, double* b, size_t bstep, int n) { + CV_INSTRUMENT_REGION() + bool output; CALL_HAL_RET(Cholesky64f, cv_hal_Cholesky64f, output, A, astep, m, b, bstep, n) return CholImpl(A, astep, m, b, bstep, n); diff --git a/modules/core/src/pca.cpp b/modules/core/src/pca.cpp index f8730475f6..0fa470005a 100644 --- a/modules/core/src/pca.cpp +++ b/modules/core/src/pca.cpp @@ -351,6 +351,8 @@ Mat PCA::backProject(InputArray data) const void cv::PCACompute(InputArray data, InputOutputArray mean, OutputArray eigenvectors, int maxComponents) { + CV_INSTRUMENT_REGION() + PCA pca; pca(data, mean, 0, maxComponents); pca.mean.copyTo(mean); @@ -360,6 +362,8 @@ void cv::PCACompute(InputArray data, InputOutputArray mean, void cv::PCACompute(InputArray data, InputOutputArray mean, OutputArray eigenvectors, double retainedVariance) { + CV_INSTRUMENT_REGION() + PCA pca; pca(data, mean, 0, retainedVariance); pca.mean.copyTo(mean); @@ -369,6 +373,8 @@ void cv::PCACompute(InputArray data, InputOutputArray mean, void cv::PCAProject(InputArray data, InputArray mean, InputArray eigenvectors, OutputArray result) { + CV_INSTRUMENT_REGION() + PCA pca; pca.mean = mean.getMat(); pca.eigenvectors = eigenvectors.getMat(); @@ -378,6 +384,8 @@ void cv::PCAProject(InputArray data, InputArray mean, void cv::PCABackProject(InputArray data, InputArray mean, InputArray eigenvectors, OutputArray result) { + CV_INSTRUMENT_REGION() + PCA pca; pca.mean = mean.getMat(); pca.eigenvectors = eigenvectors.getMat(); diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 6f9f992983..e9a7e7a175 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -5823,6 +5823,8 @@ FileStorage::~FileStorage() bool FileStorage::open(const String& filename, int flags, const String& encoding) { + CV_INSTRUMENT_REGION() + release(); fs.reset(cvOpenFileStorage( filename.c_str(), 0, flags, !encoding.empty() ? encoding.c_str() : 0)); @@ -5860,6 +5862,8 @@ FileNode FileStorage::root(int streamidx) const FileStorage& operator << (FileStorage& fs, const String& str) { + CV_INSTRUMENT_REGION() + enum { NAME_EXPECTED = FileStorage::NAME_EXPECTED, VALUE_EXPECTED = FileStorage::VALUE_EXPECTED, INSIDE_MAP = FileStorage::INSIDE_MAP }; diff --git a/modules/core/src/rand.cpp b/modules/core/src/rand.cpp index 5d389c56d4..5247af8771 100644 --- a/modules/core/src/rand.cpp +++ b/modules/core/src/rand.cpp @@ -742,11 +742,15 @@ void cv::setRNGSeed(int seed) void cv::randu(InputOutputArray dst, InputArray low, InputArray high) { + CV_INSTRUMENT_REGION() + theRNG().fill(dst, RNG::UNIFORM, low, high); } void cv::randn(InputOutputArray dst, InputArray mean, InputArray stddev) { + CV_INSTRUMENT_REGION() + theRNG().fill(dst, RNG::NORMAL, mean, stddev); } @@ -793,6 +797,8 @@ typedef void (*RandShuffleFunc)( Mat& dst, RNG& rng, double iterFactor ); void cv::randShuffle( InputOutputArray _dst, double iterFactor, RNG* _rng ) { + CV_INSTRUMENT_REGION() + RandShuffleFunc tab[] = { 0, diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index b586fe2aca..abd7fef214 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -1137,6 +1137,8 @@ static bool ocl_sum( InputArray _src, Scalar & res, int sum_op, InputArray _mask #ifdef HAVE_IPP static bool ipp_sum(Mat &src, Scalar &_res) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 700 int cn = src.channels(); size_t total_size = src.total(); @@ -1147,12 +1149,12 @@ static bool ipp_sum(Mat &src, Scalar &_res) int type = src.type(); typedef IppStatus (CV_STDCALL* ippiSumFuncHint)(const void*, int, IppiSize, double *, IppHintAlgorithm); typedef IppStatus (CV_STDCALL* ippiSumFuncNoHint)(const void*, int, IppiSize, double *); - ippiSumFuncHint ippFuncHint = + ippiSumFuncHint ippiSumHint = type == CV_32FC1 ? (ippiSumFuncHint)ippiSum_32f_C1R : type == CV_32FC3 ? (ippiSumFuncHint)ippiSum_32f_C3R : type == CV_32FC4 ? (ippiSumFuncHint)ippiSum_32f_C4R : 0; - ippiSumFuncNoHint ippFuncNoHint = + ippiSumFuncNoHint ippiSum = type == CV_8UC1 ? (ippiSumFuncNoHint)ippiSum_8u_C1R : type == CV_8UC3 ? (ippiSumFuncNoHint)ippiSum_8u_C3R : type == CV_8UC4 ? (ippiSumFuncNoHint)ippiSum_8u_C4R : @@ -1163,12 +1165,13 @@ static bool ipp_sum(Mat &src, Scalar &_res) type == CV_16SC3 ? (ippiSumFuncNoHint)ippiSum_16s_C3R : type == CV_16SC4 ? (ippiSumFuncNoHint)ippiSum_16s_C4R : 0; - CV_Assert(!ippFuncHint || !ippFuncNoHint); - if( ippFuncHint || ippFuncNoHint ) + CV_Assert(!ippiSumHint || !ippiSum); + if( ippiSumHint || ippiSum ) { Ipp64f res[4]; - IppStatus ret = ippFuncHint ? ippFuncHint(src.ptr(), (int)src.step[0], sz, res, ippAlgHintAccurate) : - ippFuncNoHint(src.ptr(), (int)src.step[0], sz, res); + IppStatus ret = ippiSumHint ? + CV_INSTRUMENT_FUN_IPP(ippiSumHint, src.ptr(), (int)src.step[0], sz, res, ippAlgHintAccurate) : + CV_INSTRUMENT_FUN_IPP(ippiSum, src.ptr(), (int)src.step[0], sz, res); if( ret >= 0 ) { for( int i = 0; i < cn; i++ ) @@ -1188,6 +1191,8 @@ static bool ipp_sum(Mat &src, Scalar &_res) cv::Scalar cv::sum( InputArray _src ) { + CV_INSTRUMENT_REGION() + #if defined HAVE_OPENCL || defined HAVE_IPP Scalar _res; #endif @@ -1299,6 +1304,8 @@ namespace cv { static bool ipp_countNonZero( Mat &src, int &res ) { + CV_INSTRUMENT_REGION_IPP() + Ipp32s count = 0; IppStatus status = ippStsNoErr; @@ -1313,9 +1320,9 @@ static bool ipp_countNonZero( Mat &src, int &res ) } if (depth == CV_8U) - status = ippiCountInRange_8u_C1R((const Ipp8u *)src.data, srcstep, roiSize, &count, 0, 0); + status = CV_INSTRUMENT_FUN_IPP(ippiCountInRange_8u_C1R, (const Ipp8u *)src.data, srcstep, roiSize, &count, 0, 0); else if (depth == CV_32F) - status = ippiCountInRange_32f_C1R((const Ipp32f *)src.data, srcstep, roiSize, &count, 0, 0); + status = CV_INSTRUMENT_FUN_IPP(ippiCountInRange_32f_C1R, (const Ipp32f *)src.data, srcstep, roiSize, &count, 0, 0); if (status >= 0) { @@ -1330,6 +1337,8 @@ static bool ipp_countNonZero( Mat &src, int &res ) int cv::countNonZero( InputArray _src ) { + CV_INSTRUMENT_REGION() + int type = _src.type(), cn = CV_MAT_CN(type); CV_Assert( cn == 1 ); @@ -1365,6 +1374,8 @@ namespace cv { static bool ipp_mean( Mat &src, Mat &mask, Scalar &ret ) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 700 size_t total_size = src.total(); int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; @@ -1375,32 +1386,32 @@ static bool ipp_mean( Mat &src, Mat &mask, Scalar &ret ) if( !mask.empty() ) { typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC1)(const void *, int, const void *, int, IppiSize, Ipp64f *); - ippiMaskMeanFuncC1 ippFuncC1 = + ippiMaskMeanFuncC1 ippiMean_C1MR = type == CV_8UC1 ? (ippiMaskMeanFuncC1)ippiMean_8u_C1MR : type == CV_16UC1 ? (ippiMaskMeanFuncC1)ippiMean_16u_C1MR : type == CV_32FC1 ? (ippiMaskMeanFuncC1)ippiMean_32f_C1MR : 0; - if( ippFuncC1 ) + if( ippiMean_C1MR ) { Ipp64f res; - if( ippFuncC1(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, &res) >= 0 ) + if( CV_INSTRUMENT_FUN_IPP(ippiMean_C1MR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, &res) >= 0 ) { ret = Scalar(res); return true; } } typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *); - ippiMaskMeanFuncC3 ippFuncC3 = + ippiMaskMeanFuncC3 ippiMean_C3MR = type == CV_8UC3 ? (ippiMaskMeanFuncC3)ippiMean_8u_C3CMR : type == CV_16UC3 ? (ippiMaskMeanFuncC3)ippiMean_16u_C3CMR : type == CV_32FC3 ? (ippiMaskMeanFuncC3)ippiMean_32f_C3CMR : 0; - if( ippFuncC3 ) + if( ippiMean_C3MR ) { Ipp64f res1, res2, res3; - if( ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 1, &res1) >= 0 && - ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 2, &res2) >= 0 && - ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 3, &res3) >= 0 ) + if( CV_INSTRUMENT_FUN_IPP(ippiMean_C3MR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 1, &res1) >= 0 && + CV_INSTRUMENT_FUN_IPP(ippiMean_C3MR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 2, &res2) >= 0 && + CV_INSTRUMENT_FUN_IPP(ippiMean_C3MR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 3, &res3) >= 0 ) { ret = Scalar(res1, res2, res3); return true; @@ -1411,12 +1422,12 @@ static bool ipp_mean( Mat &src, Mat &mask, Scalar &ret ) { typedef IppStatus (CV_STDCALL* ippiMeanFuncHint)(const void*, int, IppiSize, double *, IppHintAlgorithm); typedef IppStatus (CV_STDCALL* ippiMeanFuncNoHint)(const void*, int, IppiSize, double *); - ippiMeanFuncHint ippFuncHint = + ippiMeanFuncHint ippiMeanHint = type == CV_32FC1 ? (ippiMeanFuncHint)ippiMean_32f_C1R : type == CV_32FC3 ? (ippiMeanFuncHint)ippiMean_32f_C3R : type == CV_32FC4 ? (ippiMeanFuncHint)ippiMean_32f_C4R : 0; - ippiMeanFuncNoHint ippFuncNoHint = + ippiMeanFuncNoHint ippiMean = type == CV_8UC1 ? (ippiMeanFuncNoHint)ippiMean_8u_C1R : type == CV_8UC3 ? (ippiMeanFuncNoHint)ippiMean_8u_C3R : type == CV_8UC4 ? (ippiMeanFuncNoHint)ippiMean_8u_C4R : @@ -1428,12 +1439,12 @@ static bool ipp_mean( Mat &src, Mat &mask, Scalar &ret ) type == CV_16SC4 ? (ippiMeanFuncNoHint)ippiMean_16s_C4R : 0; // Make sure only zero or one version of the function pointer is valid - CV_Assert(!ippFuncHint || !ippFuncNoHint); - if( ippFuncHint || ippFuncNoHint ) + CV_Assert(!ippiMeanHint || !ippiMean); + if( ippiMeanHint || ippiMean ) { Ipp64f res[4]; - IppStatus status = ippFuncHint ? ippFuncHint(src.ptr(), (int)src.step[0], sz, res, ippAlgHintAccurate) : - ippFuncNoHint(src.ptr(), (int)src.step[0], sz, res); + IppStatus status = ippiMeanHint ? CV_INSTRUMENT_FUN_IPP(ippiMeanHint, src.ptr(), (int)src.step[0], sz, res, ippAlgHintAccurate) : + CV_INSTRUMENT_FUN_IPP(ippiMean, src.ptr(), (int)src.step[0], sz, res); if( status >= 0 ) { for( int i = 0; i < src.channels(); i++ ) @@ -1453,6 +1464,8 @@ static bool ipp_mean( Mat &src, Mat &mask, Scalar &ret ) cv::Scalar cv::mean( InputArray _src, InputArray _mask ) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(), mask = _mask.getMat(); CV_Assert( mask.empty() || mask.type() == CV_8U ); @@ -2216,6 +2229,8 @@ static bool ocl_minMaxIdx( InputArray _src, double* minVal, double* maxVal, int* #ifdef HAVE_IPP static bool ipp_minMaxIdx( Mat &src, double* minVal, double* maxVal, int* minIdx, int* maxIdx, Mat &mask) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 700 int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); size_t total_size = src.total(); @@ -2230,7 +2245,7 @@ static bool ipp_minMaxIdx( Mat &src, double* minVal, double* maxVal, int* minIdx IppiSize, Ipp32f *, Ipp32f *, IppiPoint *, IppiPoint *); CV_SUPPRESS_DEPRECATED_START - ippiMaskMinMaxIndxFuncC1 ippFuncC1 = + ippiMaskMinMaxIndxFuncC1 ippiMinMaxIndx_C1MR = type == CV_8UC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_8u_C1MR : #if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_8s_C1MR : @@ -2239,11 +2254,11 @@ static bool ipp_minMaxIdx( Mat &src, double* minVal, double* maxVal, int* minIdx type == CV_32FC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_32f_C1MR : 0; CV_SUPPRESS_DEPRECATED_END - if( ippFuncC1 ) + if( ippiMinMaxIndx_C1MR ) { Ipp32f min, max; IppiPoint minp, maxp; - if( ippFuncC1(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, &min, &max, &minp, &maxp) >= 0 ) + if( CV_INSTRUMENT_FUN_IPP(ippiMinMaxIndx_C1MR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, &min, &max, &minp, &maxp) >= 0 ) { if( minVal ) *minVal = (double)min; @@ -2270,7 +2285,7 @@ static bool ipp_minMaxIdx( Mat &src, double* minVal, double* maxVal, int* minIdx typedef IppStatus (CV_STDCALL* ippiMinMaxIndxFuncC1)(const void *, int, IppiSize, Ipp32f *, Ipp32f *, IppiPoint *, IppiPoint *); CV_SUPPRESS_DEPRECATED_START - ippiMinMaxIndxFuncC1 ippFuncC1 = + ippiMinMaxIndxFuncC1 ippiMinMaxIndx_C1R = #if IPP_VERSION_X100 != 900 // bug in 9.0.0 avx2 optimization depth == CV_8U ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_8u_C1R : #endif @@ -2286,11 +2301,11 @@ static bool ipp_minMaxIdx( Mat &src, double* minVal, double* maxVal, int* minIdx 0; CV_SUPPRESS_DEPRECATED_END - if( ippFuncC1 ) + if( ippiMinMaxIndx_C1R ) { Ipp32f min, max; IppiPoint minp, maxp; - if( ippFuncC1(src.ptr(), (int)src.step[0], sz, &min, &max, &minp, &maxp) >= 0 ) + if( CV_INSTRUMENT_FUN_IPP(ippiMinMaxIndx_C1R, src.ptr(), (int)src.step[0], sz, &min, &max, &minp, &maxp) >= 0 ) { if( minVal ) *minVal = (double)min; @@ -2324,6 +2339,8 @@ void cv::minMaxIdx(InputArray _src, double* minVal, double* maxVal, int* minIdx, int* maxIdx, InputArray _mask) { + CV_INSTRUMENT_REGION() + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); CV_Assert( (cn == 1 && (_mask.empty() || _mask.type() == CV_8U)) || (cn > 1 && _mask.empty() && !minIdx && !maxIdx) ); @@ -2386,6 +2403,8 @@ void cv::minMaxIdx(InputArray _src, double* minVal, void cv::minMaxLoc( InputArray _img, double* minVal, double* maxVal, Point* minLoc, Point* maxLoc, InputArray mask ) { + CV_INSTRUMENT_REGION() + CV_Assert(_img.dims() <= 2); minMaxIdx(_img, minVal, maxVal, (int*)minLoc, (int*)maxLoc, mask); @@ -2665,6 +2684,8 @@ static bool ocl_norm( InputArray _src, int normType, InputArray _mask, double & #ifdef HAVE_IPP static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 700 int cn = src.channels(); size_t total_size = src.total(); @@ -2680,7 +2701,7 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) if( !mask.empty() ) { typedef IppStatus (CV_STDCALL* ippiMaskNormFuncC1)(const void *, int, const void *, int, IppiSize, Ipp64f *); - ippiMaskNormFuncC1 ippFuncC1 = + ippiMaskNormFuncC1 ippiNorm_C1MR = normType == NORM_INF ? (type == CV_8UC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_8u_C1MR : #if IPP_VERSION_X100 < 900 @@ -2705,10 +2726,10 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) type == CV_16UC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_32f_C1MR : 0) : 0; - if( ippFuncC1 ) + if( ippiNorm_C1MR ) { Ipp64f norm; - if( ippFuncC1(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, &norm) >= 0 ) + if( CV_INSTRUMENT_FUN_IPP(ippiNorm_C1MR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, &norm) >= 0 ) { result = (normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm); return true; @@ -2716,7 +2737,7 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) } #if IPP_DISABLE_BLOCK typedef IppStatus (CV_STDCALL* ippiMaskNormFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *); - ippiMaskNormFuncC3 ippFuncC3 = + ippiMaskNormFuncC3 ippiNorm_C3CMR = normType == NORM_INF ? (type == CV_8UC3 ? (ippiMaskNormFuncC3)ippiNorm_Inf_8u_C3CMR : #if IPP_VERSION_X100 < 900 @@ -2741,12 +2762,12 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) type == CV_16UC3 ? (ippiMaskNormFuncC3)ippiNorm_L2_16u_C3CMR : type == CV_32FC3 ? (ippiMaskNormFuncC3)ippiNorm_L2_32f_C3CMR : 0) : 0; - if( ippFuncC3 ) + if( ippiNorm_C3CMR ) { Ipp64f norm1, norm2, norm3; - if( ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 1, &norm1) >= 0 && - ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 2, &norm2) >= 0 && - ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 3, &norm3) >= 0) + if( CV_INSTRUMENT_FUN_IPP(ippiNorm_C3CMR, (src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 1, &norm1)) >= 0 && + CV_INSTRUMENT_FUN_IPP(ippiNorm_C3CMR, (src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 2, &norm2)) >= 0 && + CV_INSTRUMENT_FUN_IPP(ippiNorm_C3CMR, (src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 3, &norm3)) >= 0) { Ipp64f norm = normType == NORM_INF ? std::max(std::max(norm1, norm2), norm3) : @@ -2763,7 +2784,7 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) { typedef IppStatus (CV_STDCALL* ippiNormFuncHint)(const void *, int, IppiSize, Ipp64f *, IppHintAlgorithm hint); typedef IppStatus (CV_STDCALL* ippiNormFuncNoHint)(const void *, int, IppiSize, Ipp64f *); - ippiNormFuncHint ippFuncHint = + ippiNormFuncHint ippiNormHint = normType == NORM_L1 ? (type == CV_32FC1 ? (ippiNormFuncHint)ippiNorm_L1_32f_C1R : type == CV_32FC3 ? (ippiNormFuncHint)ippiNorm_L1_32f_C3R : @@ -2774,7 +2795,7 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) type == CV_32FC3 ? (ippiNormFuncHint)ippiNorm_L2_32f_C3R : type == CV_32FC4 ? (ippiNormFuncHint)ippiNorm_L2_32f_C4R : 0) : 0; - ippiNormFuncNoHint ippFuncNoHint = + ippiNormFuncNoHint ippiNorm = normType == NORM_INF ? (type == CV_8UC1 ? (ippiNormFuncNoHint)ippiNorm_Inf_8u_C1R : type == CV_8UC3 ? (ippiNormFuncNoHint)ippiNorm_Inf_8u_C3R : @@ -2814,12 +2835,12 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) type == CV_16SC4 ? (ippiNormFuncNoHint)ippiNorm_L2_16s_C4R : 0) : 0; // Make sure only zero or one version of the function pointer is valid - CV_Assert(!ippFuncHint || !ippFuncNoHint); - if( ippFuncHint || ippFuncNoHint ) + CV_Assert(!ippiNormHint || !ippiNorm); + if( ippiNormHint || ippiNorm ) { Ipp64f norm_array[4]; - IppStatus ret = ippFuncHint ? ippFuncHint(src.ptr(), (int)src.step[0], sz, norm_array, ippAlgHintAccurate) : - ippFuncNoHint(src.ptr(), (int)src.step[0], sz, norm_array); + IppStatus ret = ippiNormHint ? CV_INSTRUMENT_FUN_IPP(ippiNormHint, src.ptr(), (int)src.step[0], sz, norm_array, ippAlgHintAccurate) : + CV_INSTRUMENT_FUN_IPP(ippiNorm, src.ptr(), (int)src.step[0], sz, norm_array); if( ret >= 0 ) { Ipp64f norm = (normType == NORM_L2 || normType == NORM_L2SQR) ? norm_array[0] * norm_array[0] : norm_array[0]; @@ -2847,6 +2868,8 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) double cv::norm( InputArray _src, int normType, InputArray _mask ) { + CV_INSTRUMENT_REGION() + normType &= NORM_TYPE_MASK; CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR || @@ -3067,6 +3090,8 @@ namespace cv { static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArray _mask, double &result) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 700 Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat(); @@ -3087,7 +3112,7 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra if( !mask.empty() ) { typedef IppStatus (CV_STDCALL* ippiMaskNormRelFuncC1)(const void *, int, const void *, int, const void *, int, IppiSize, Ipp64f *); - ippiMaskNormRelFuncC1 ippFuncC1 = + ippiMaskNormRelFuncC1 ippiNormDiff_C1MR = normType == NORM_INF ? (type == CV_8UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_8u_C1MR : #if IPP_VERSION_X100 < 900 @@ -3116,10 +3141,10 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra type == CV_16UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_32f_C1MR : 0) : 0; - if( ippFuncC1 ) + if( ippiNormDiff_C1MR ) { Ipp64f norm; - if( ippFuncC1(src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], mask.ptr(), (int)mask.step[0], sz, &norm) >= 0 ) + if( CV_INSTRUMENT_FUN_IPP(ippiNormDiff_C1MR, src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], mask.ptr(), (int)mask.step[0], sz, &norm) >= 0 ) { result = (normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm); return true; @@ -3130,7 +3155,7 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra { typedef IppStatus (CV_STDCALL* ippiNormRelFuncNoHint)(const void *, int, const void *, int, IppiSize, Ipp64f *); typedef IppStatus (CV_STDCALL* ippiNormRelFuncHint)(const void *, int, const void *, int, IppiSize, Ipp64f *, IppHintAlgorithm hint); - ippiNormRelFuncNoHint ippFuncNoHint = + ippiNormRelFuncNoHint ippiNormDiff = normType == NORM_INF ? (type == CV_8UC1 ? (ippiNormRelFuncNoHint)ippiNormRel_Inf_8u_C1R : type == CV_16UC1 ? (ippiNormRelFuncNoHint)ippiNormRel_Inf_16u_C1R : @@ -3147,26 +3172,26 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra type == CV_16UC1 ? (ippiNormRelFuncNoHint)ippiNormRel_L2_16u_C1R : type == CV_16SC1 ? (ippiNormRelFuncNoHint)ippiNormRel_L2_16s_C1R : 0) : 0; - ippiNormRelFuncHint ippFuncHint = + ippiNormRelFuncHint ippiNormDiffHint = normType == NORM_L1 ? (type == CV_32FC1 ? (ippiNormRelFuncHint)ippiNormRel_L1_32f_C1R : 0) : normType == NORM_L2 || normType == NORM_L2SQR ? (type == CV_32FC1 ? (ippiNormRelFuncHint)ippiNormRel_L2_32f_C1R : 0) : 0; - if (ippFuncNoHint) + if (ippiNormDiff) { Ipp64f norm; - if( ippFuncNoHint(src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], sz, &norm) >= 0 ) + if( CV_INSTRUMENT_FUN_IPP(ippiNormDiff, src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], sz, &norm) >= 0 ) { result = (double)norm; return true; } } - if (ippFuncHint) + if (ippiNormDiffHint) { Ipp64f norm; - if( ippFuncHint(src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], sz, &norm, ippAlgHintAccurate) >= 0 ) + if( CV_INSTRUMENT_FUN_IPP(ippiNormDiffHint, src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], sz, &norm, ippAlgHintAccurate) >= 0 ) { result = (double)norm; return true; @@ -3194,7 +3219,7 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra if( !mask.empty() ) { typedef IppStatus (CV_STDCALL* ippiMaskNormDiffFuncC1)(const void *, int, const void *, int, const void *, int, IppiSize, Ipp64f *); - ippiMaskNormDiffFuncC1 ippFuncC1 = + ippiMaskNormDiffFuncC1 ippiNormDiff_C1MR = normType == NORM_INF ? (type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_8u_C1MR : #if IPP_VERSION_X100 < 900 @@ -3221,10 +3246,10 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_32f_C1MR : 0) : 0; - if( ippFuncC1 ) + if( ippiNormDiff_C1MR ) { Ipp64f norm; - if( ippFuncC1(src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], mask.ptr(), (int)mask.step[0], sz, &norm) >= 0 ) + if( CV_INSTRUMENT_FUN_IPP(ippiNormDiff_C1MR, src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], mask.ptr(), (int)mask.step[0], sz, &norm) >= 0 ) { result = (normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm); return true; @@ -3232,7 +3257,7 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra } #ifndef __APPLE__ typedef IppStatus (CV_STDCALL* ippiMaskNormDiffFuncC3)(const void *, int, const void *, int, const void *, int, IppiSize, int, Ipp64f *); - ippiMaskNormDiffFuncC3 ippFuncC3 = + ippiMaskNormDiffFuncC3 ippiNormDiff_C3CMR = normType == NORM_INF ? (type == CV_8UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_8u_C3CMR : #if IPP_VERSION_X100 < 900 @@ -3257,12 +3282,12 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra type == CV_16UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_16u_C3CMR : type == CV_32FC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_32f_C3CMR : 0) : 0; - if( ippFuncC3 ) + if( ippiNormDiff_C3CMR ) { Ipp64f norm1, norm2, norm3; - if( ippFuncC3(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 1, &norm1) >= 0 && - ippFuncC3(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 2, &norm2) >= 0 && - ippFuncC3(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 3, &norm3) >= 0) + if( CV_INSTRUMENT_FUN_IPP(ippiNormDiff_C3CMR, src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 1, &norm1) >= 0 && + CV_INSTRUMENT_FUN_IPP(ippiNormDiff_C3CMR, src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 2, &norm2) >= 0 && + CV_INSTRUMENT_FUN_IPP(ippiNormDiff_C3CMR, src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 3, &norm3) >= 0) { Ipp64f norm = normType == NORM_INF ? std::max(std::max(norm1, norm2), norm3) : @@ -3279,7 +3304,7 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra { typedef IppStatus (CV_STDCALL* ippiNormDiffFuncHint)(const void *, int, const void *, int, IppiSize, Ipp64f *, IppHintAlgorithm hint); typedef IppStatus (CV_STDCALL* ippiNormDiffFuncNoHint)(const void *, int, const void *, int, IppiSize, Ipp64f *); - ippiNormDiffFuncHint ippFuncHint = + ippiNormDiffFuncHint ippiNormDiffHint = normType == NORM_L1 ? (type == CV_32FC1 ? (ippiNormDiffFuncHint)ippiNormDiff_L1_32f_C1R : type == CV_32FC3 ? (ippiNormDiffFuncHint)ippiNormDiff_L1_32f_C3R : @@ -3290,7 +3315,7 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra type == CV_32FC3 ? (ippiNormDiffFuncHint)ippiNormDiff_L2_32f_C3R : type == CV_32FC4 ? (ippiNormDiffFuncHint)ippiNormDiff_L2_32f_C4R : 0) : 0; - ippiNormDiffFuncNoHint ippFuncNoHint = + ippiNormDiffFuncNoHint ippiNormDiff = normType == NORM_INF ? (type == CV_8UC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_8u_C1R : type == CV_8UC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_8u_C3R : @@ -3332,12 +3357,12 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra type == CV_16SC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L2_16s_C4R : 0) : 0; // Make sure only zero or one version of the function pointer is valid - CV_Assert(!ippFuncHint || !ippFuncNoHint); - if( ippFuncHint || ippFuncNoHint ) + CV_Assert(!ippiNormDiffHint || !ippiNormDiff); + if( ippiNormDiffHint || ippiNormDiff ) { Ipp64f norm_array[4]; - IppStatus ret = ippFuncHint ? ippFuncHint(src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], sz, norm_array, ippAlgHintAccurate) : - ippFuncNoHint(src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], sz, norm_array); + IppStatus ret = ippiNormDiffHint ? CV_INSTRUMENT_FUN_IPP(ippiNormDiffHint, src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], sz, norm_array, ippAlgHintAccurate) : + CV_INSTRUMENT_FUN_IPP(ippiNormDiff, src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], sz, norm_array); if( ret >= 0 ) { Ipp64f norm = (normType == NORM_L2 || normType == NORM_L2SQR) ? norm_array[0] * norm_array[0] : norm_array[0]; @@ -3366,6 +3391,8 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask ) { + CV_INSTRUMENT_REGION() + CV_Assert( _src1.sameSize(_src2) && _src1.type() == _src2.type() ); #if defined HAVE_OPENCL || defined HAVE_IPP @@ -3750,6 +3777,8 @@ void cv::batchDistance( InputArray _src1, InputArray _src2, int normType, int K, InputArray _mask, int update, bool crosscheck ) { + CV_INSTRUMENT_REGION() + Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat(); int type = src1.type(); CV_Assert( type == src2.type() && src1.cols == src2.cols && @@ -3859,6 +3888,8 @@ void cv::batchDistance( InputArray _src1, InputArray _src2, void cv::findNonZero( InputArray _src, OutputArray _idx ) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); CV_Assert( src.type() == CV_8UC1 ); int n = countNonZero(src); @@ -3885,6 +3916,8 @@ void cv::findNonZero( InputArray _src, OutputArray _idx ) double cv::PSNR(InputArray _src1, InputArray _src2) { + CV_INSTRUMENT_REGION() + CV_Assert( _src1.depth() == CV_8U ); double diff = std::sqrt(norm(_src1, _src2, NORM_L2SQR)/(_src1.total()*_src1.channels())); return 20*log10(255./(diff+DBL_EPSILON)); diff --git a/modules/core/src/types.cpp b/modules/core/src/types.cpp index 89e0042657..6cd47b6fdf 100644 --- a/modules/core/src/types.cpp +++ b/modules/core/src/types.cpp @@ -63,6 +63,8 @@ size_t KeyPoint::hash() const void KeyPoint::convert(const std::vector& keypoints, std::vector& points2f, const std::vector& keypointIndexes) { + CV_INSTRUMENT_REGION() + if( keypointIndexes.empty() ) { points2f.resize( keypoints.size() ); @@ -89,6 +91,8 @@ void KeyPoint::convert(const std::vector& keypoints, std::vector& points2f, std::vector& keypoints, float size, float response, int octave, int class_id ) { + CV_INSTRUMENT_REGION() + keypoints.resize(points2f.size()); for( size_t i = 0; i < points2f.size(); i++ ) keypoints[i] = KeyPoint(points2f[i], size, -1, response, octave, class_id); diff --git a/modules/core/src/umatrix.cpp b/modules/core/src/umatrix.cpp index 958723b7b5..997ee2b6ef 100644 --- a/modules/core/src/umatrix.cpp +++ b/modules/core/src/umatrix.cpp @@ -773,6 +773,8 @@ void UMat::ndoffset(size_t* ofs) const void UMat::copyTo(OutputArray _dst) const { + CV_INSTRUMENT_REGION() + int dtype = _dst.type(); if( _dst.fixedType() && dtype != type() ) { @@ -816,6 +818,8 @@ void UMat::copyTo(OutputArray _dst) const void UMat::copyTo(OutputArray _dst, InputArray _mask) const { + CV_INSTRUMENT_REGION() + if( _mask.empty() ) { copyTo(_dst); @@ -863,6 +867,8 @@ void UMat::copyTo(OutputArray _dst, InputArray _mask) const void UMat::convertTo(OutputArray _dst, int _type, double alpha, double beta) const { + CV_INSTRUMENT_REGION() + bool noScale = std::fabs(alpha - 1) < DBL_EPSILON && std::fabs(beta) < DBL_EPSILON; int stype = type(), cn = CV_MAT_CN(stype); @@ -924,6 +930,8 @@ void UMat::convertTo(OutputArray _dst, int _type, double alpha, double beta) con UMat& UMat::setTo(InputArray _value, InputArray _mask) { + CV_INSTRUMENT_REGION() + bool haveMask = !_mask.empty(); #ifdef HAVE_OPENCL int tp = type(), cn = CV_MAT_CN(tp), d = CV_MAT_DEPTH(tp); @@ -1062,6 +1070,8 @@ static bool ocl_dot( InputArray _src1, InputArray _src2, double & res ) double UMat::dot(InputArray m) const { + CV_INSTRUMENT_REGION() + CV_Assert(m.sameSize(*this) && m.type() == type()); #ifdef HAVE_OPENCL diff --git a/modules/features2d/src/agast.cpp b/modules/features2d/src/agast.cpp index a419e371e0..618998efc2 100644 --- a/modules/features2d/src/agast.cpp +++ b/modules/features2d/src/agast.cpp @@ -7940,6 +7940,8 @@ static void OAST_9_16(InputArray _img, std::vector& keypoints, int thr void AGAST(InputArray _img, std::vector& keypoints, int threshold, bool nonmax_suppression) { + CV_INSTRUMENT_REGION() + AGAST(_img, keypoints, threshold, nonmax_suppression, AgastFeatureDetector::OAST_9_16); } @@ -7952,6 +7954,8 @@ public: void detect( InputArray _image, std::vector& keypoints, InputArray _mask ) { + CV_INSTRUMENT_REGION() + Mat mask = _mask.getMat(), grayImage; UMat ugrayImage; _InputArray gray = _image; @@ -8007,6 +8011,7 @@ Ptr AgastFeatureDetector::create( int threshold, bool nonm void AGAST(InputArray _img, std::vector& keypoints, int threshold, bool nonmax_suppression, int type) { + CV_INSTRUMENT_REGION() std::vector kpts; diff --git a/modules/features2d/src/akaze.cpp b/modules/features2d/src/akaze.cpp index f4fe27c1e5..d598155275 100644 --- a/modules/features2d/src/akaze.cpp +++ b/modules/features2d/src/akaze.cpp @@ -167,6 +167,8 @@ namespace cv OutputArray descriptors, bool useProvidedKeypoints) { + CV_INSTRUMENT_REGION() + Mat img = image.getMat(); if (img.channels() > 1) cvtColor(image, img, COLOR_BGR2GRAY); diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp index 991a620c8a..31fb19d837 100644 --- a/modules/features2d/src/bagofwords.cpp +++ b/modules/features2d/src/bagofwords.cpp @@ -89,6 +89,8 @@ BOWKMeansTrainer::BOWKMeansTrainer( int _clusterCount, const TermCriteria& _term Mat BOWKMeansTrainer::cluster() const { + CV_INSTRUMENT_REGION() + CV_Assert( !descriptors.empty() ); Mat mergedDescriptors( descriptorsCount(), descriptors[0].cols, descriptors[0].type() ); @@ -106,6 +108,8 @@ BOWKMeansTrainer::~BOWKMeansTrainer() Mat BOWKMeansTrainer::cluster( const Mat& _descriptors ) const { + CV_INSTRUMENT_REGION() + Mat labels, vocabulary; kmeans( _descriptors, clusterCount, labels, termcrit, attempts, flags, vocabulary ); return vocabulary; @@ -139,6 +143,8 @@ const Mat& BOWImgDescriptorExtractor::getVocabulary() const void BOWImgDescriptorExtractor::compute( InputArray image, std::vector& keypoints, OutputArray imgDescriptor, std::vector >* pointIdxsOfClusters, Mat* descriptors ) { + CV_INSTRUMENT_REGION() + imgDescriptor.release(); if( keypoints.empty() ) @@ -168,6 +174,8 @@ int BOWImgDescriptorExtractor::descriptorType() const void BOWImgDescriptorExtractor::compute( InputArray keypointDescriptors, OutputArray _imgDescriptor, std::vector >* pointIdxsOfClusters ) { + CV_INSTRUMENT_REGION() + CV_Assert( !vocabulary.empty() ); int clusterCount = descriptorSize(); // = vocabulary.rows diff --git a/modules/features2d/src/blobdetector.cpp b/modules/features2d/src/blobdetector.cpp index 23b6f2bd72..ac55341be9 100644 --- a/modules/features2d/src/blobdetector.cpp +++ b/modules/features2d/src/blobdetector.cpp @@ -190,6 +190,8 @@ void SimpleBlobDetectorImpl::write( cv::FileStorage& fs ) const void SimpleBlobDetectorImpl::findBlobs(InputArray _image, InputArray _binaryImage, std::vector
¢ers) const { + CV_INSTRUMENT_REGION() + Mat image = _image.getMat(), binaryImage = _binaryImage.getMat(); (void)image; centers.clear(); @@ -304,6 +306,8 @@ void SimpleBlobDetectorImpl::findBlobs(InputArray _image, InputArray _binaryImag void SimpleBlobDetectorImpl::detect(InputArray image, std::vector& keypoints, InputArray) { + CV_INSTRUMENT_REGION() + //TODO: support mask keypoints.clear(); Mat grayscaleImage; diff --git a/modules/features2d/src/draw.cpp b/modules/features2d/src/draw.cpp index 63410e713c..357662fc81 100644 --- a/modules/features2d/src/draw.cpp +++ b/modules/features2d/src/draw.cpp @@ -91,6 +91,8 @@ static inline void _drawKeypoint( InputOutputArray img, const KeyPoint& p, const void drawKeypoints( InputArray image, const std::vector& keypoints, InputOutputArray outImage, const Scalar& _color, int flags ) { + CV_INSTRUMENT_REGION() + if( !(flags & DrawMatchesFlags::DRAW_OVER_OUTIMG) ) { if( image.type() == CV_8UC3 ) diff --git a/modules/features2d/src/evaluation.cpp b/modules/features2d/src/evaluation.cpp index 3863203df7..5ea882153f 100644 --- a/modules/features2d/src/evaluation.cpp +++ b/modules/features2d/src/evaluation.cpp @@ -179,6 +179,8 @@ void EllipticKeyPoint::calcProjection( const Mat_& H, EllipticKeyPoint& void EllipticKeyPoint::convert( const std::vector& src, std::vector& dst ) { + CV_INSTRUMENT_REGION() + if( !src.empty() ) { dst.resize(src.size()); @@ -194,6 +196,8 @@ void EllipticKeyPoint::convert( const std::vector& src, std::vector& src, std::vector& dst ) { + CV_INSTRUMENT_REGION() + if( !src.empty() ) { dst.resize(src.size()); @@ -456,6 +460,8 @@ void cv::evaluateFeatureDetector( const Mat& img1, const Mat& img2, const Mat& H float& repeatability, int& correspCount, const Ptr& _fdetector ) { + CV_INSTRUMENT_REGION() + Ptr fdetector(_fdetector); std::vector *keypoints1, *keypoints2, buf1, buf2; keypoints1 = _keypoints1 != 0 ? _keypoints1 : &buf1; @@ -492,6 +498,8 @@ void cv::computeRecallPrecisionCurve( const std::vector >& m const std::vector >& correctMatches1to2Mask, std::vector& recallPrecisionCurve ) { + CV_INSTRUMENT_REGION() + CV_Assert( matches1to2.size() == correctMatches1to2Mask.size() ); std::vector allMatches; @@ -526,6 +534,8 @@ void cv::computeRecallPrecisionCurve( const std::vector >& m float cv::getRecall( const std::vector& recallPrecisionCurve, float l_precision ) { + CV_INSTRUMENT_REGION() + int nearestPointIndex = getNearestPoint( recallPrecisionCurve, l_precision ); float recall = -1.f; @@ -538,6 +548,8 @@ float cv::getRecall( const std::vector& recallPrecisionCurve, float l_p int cv::getNearestPoint( const std::vector& recallPrecisionCurve, float l_precision ) { + CV_INSTRUMENT_REGION() + int nearestPointIndex = -1; if( l_precision >= 0 && l_precision <= 1 ) diff --git a/modules/features2d/src/fast.cpp b/modules/features2d/src/fast.cpp index 42dacb5387..8fa6b79f77 100644 --- a/modules/features2d/src/fast.cpp +++ b/modules/features2d/src/fast.cpp @@ -331,6 +331,8 @@ static bool ocl_FAST( InputArray _img, std::vector& keypoints, void FAST(InputArray _img, std::vector& keypoints, int threshold, bool nonmax_suppression, int type) { + CV_INSTRUMENT_REGION() + #ifdef HAVE_OPENCL if( ocl::useOpenCL() && _img.isUMat() && type == FastFeatureDetector::TYPE_9_16 && ocl_FAST(_img, keypoints, threshold, nonmax_suppression, 10000)) @@ -360,6 +362,8 @@ void FAST(InputArray _img, std::vector& keypoints, int threshold, bool void FAST(InputArray _img, std::vector& keypoints, int threshold, bool nonmax_suppression) { + CV_INSTRUMENT_REGION() + FAST(_img, keypoints, threshold, nonmax_suppression, FastFeatureDetector::TYPE_9_16); } @@ -373,6 +377,8 @@ public: void detect( InputArray _image, std::vector& keypoints, InputArray _mask ) { + CV_INSTRUMENT_REGION() + Mat mask = _mask.getMat(), grayImage; UMat ugrayImage; _InputArray gray = _image; diff --git a/modules/features2d/src/feature2d.cpp b/modules/features2d/src/feature2d.cpp index 93b650bcb8..a992db7ce3 100644 --- a/modules/features2d/src/feature2d.cpp +++ b/modules/features2d/src/feature2d.cpp @@ -60,6 +60,8 @@ void Feature2D::detect( InputArray image, std::vector& keypoints, InputArray mask ) { + CV_INSTRUMENT_REGION() + if( image.empty() ) { keypoints.clear(); @@ -73,6 +75,8 @@ void Feature2D::detect( InputArrayOfArrays _images, std::vector >& keypoints, InputArrayOfArrays _masks ) { + CV_INSTRUMENT_REGION() + vector images, masks; _images.getMatVector(images); @@ -102,6 +106,8 @@ void Feature2D::compute( InputArray image, std::vector& keypoints, OutputArray descriptors ) { + CV_INSTRUMENT_REGION() + if( image.empty() ) { descriptors.release(); @@ -114,6 +120,8 @@ void Feature2D::compute( InputArrayOfArrays _images, std::vector >& keypoints, OutputArrayOfArrays _descriptors ) { + CV_INSTRUMENT_REGION() + if( !_descriptors.needed() ) return; @@ -141,6 +149,8 @@ void Feature2D::detectAndCompute( InputArray, InputArray, OutputArray, bool ) { + CV_INSTRUMENT_REGION() + CV_Error(Error::StsNotImplemented, ""); } diff --git a/modules/features2d/src/gftt.cpp b/modules/features2d/src/gftt.cpp index 17e26928c0..c61c96f596 100644 --- a/modules/features2d/src/gftt.cpp +++ b/modules/features2d/src/gftt.cpp @@ -75,6 +75,8 @@ public: void detect( InputArray _image, std::vector& keypoints, InputArray _mask ) { + CV_INSTRUMENT_REGION() + std::vector corners; if (_image.isUMat()) diff --git a/modules/features2d/src/kaze.cpp b/modules/features2d/src/kaze.cpp index 64778a08c7..63b48c3b41 100644 --- a/modules/features2d/src/kaze.cpp +++ b/modules/features2d/src/kaze.cpp @@ -110,6 +110,8 @@ namespace cv OutputArray descriptors, bool useProvidedKeypoints) { + CV_INSTRUMENT_REGION() + cv::Mat img = image.getMat(); if (img.channels() > 1) cvtColor(image, img, COLOR_BGR2GRAY); diff --git a/modules/features2d/src/matchers.cpp b/modules/features2d/src/matchers.cpp index 11dfa6d388..379d3a73b9 100644 --- a/modules/features2d/src/matchers.cpp +++ b/modules/features2d/src/matchers.cpp @@ -567,6 +567,8 @@ void DescriptorMatcher::train() void DescriptorMatcher::match( InputArray queryDescriptors, InputArray trainDescriptors, std::vector& matches, InputArray mask ) const { + CV_INSTRUMENT_REGION() + Ptr tempMatcher = clone(true); tempMatcher->add(trainDescriptors); tempMatcher->match( queryDescriptors, matches, std::vector(1, mask.getMat()) ); @@ -576,6 +578,8 @@ void DescriptorMatcher::knnMatch( InputArray queryDescriptors, InputArray trainD std::vector >& matches, int knn, InputArray mask, bool compactResult ) const { + CV_INSTRUMENT_REGION() + Ptr tempMatcher = clone(true); tempMatcher->add(trainDescriptors); tempMatcher->knnMatch( queryDescriptors, matches, knn, std::vector(1, mask.getMat()), compactResult ); @@ -585,6 +589,8 @@ void DescriptorMatcher::radiusMatch( InputArray queryDescriptors, InputArray tra std::vector >& matches, float maxDistance, InputArray mask, bool compactResult ) const { + CV_INSTRUMENT_REGION() + Ptr tempMatcher = clone(true); tempMatcher->add(trainDescriptors); tempMatcher->radiusMatch( queryDescriptors, matches, maxDistance, std::vector(1, mask.getMat()), compactResult ); @@ -592,6 +598,8 @@ void DescriptorMatcher::radiusMatch( InputArray queryDescriptors, InputArray tra void DescriptorMatcher::match( InputArray queryDescriptors, std::vector& matches, InputArrayOfArrays masks ) { + CV_INSTRUMENT_REGION() + std::vector > knnMatches; knnMatch( queryDescriptors, knnMatches, 1, masks, true /*compactResult*/ ); convertMatches( knnMatches, matches ); @@ -623,6 +631,8 @@ void DescriptorMatcher::checkMasks( InputArrayOfArrays _masks, int queryDescript void DescriptorMatcher::knnMatch( InputArray queryDescriptors, std::vector >& matches, int knn, InputArrayOfArrays masks, bool compactResult ) { + CV_INSTRUMENT_REGION() + if( empty() || queryDescriptors.empty() ) return; @@ -637,6 +647,8 @@ void DescriptorMatcher::knnMatch( InputArray queryDescriptors, std::vector >& matches, float maxDistance, InputArrayOfArrays masks, bool compactResult ) { + CV_INSTRUMENT_REGION() + matches.clear(); if( empty() || queryDescriptors.empty() ) return; @@ -1080,6 +1092,8 @@ void FlannBasedMatcher::clear() void FlannBasedMatcher::train() { + CV_INSTRUMENT_REGION() + if( !flannIndex || mergedDescriptors.size() < addedDescCount ) { // FIXIT: Workaround for 'utrainDescCollection' issue (PR #2142) @@ -1332,6 +1346,8 @@ void FlannBasedMatcher::convertToDMatches( const DescriptorCollection& collectio void FlannBasedMatcher::knnMatchImpl( InputArray _queryDescriptors, std::vector >& matches, int knn, InputArrayOfArrays /*masks*/, bool /*compactResult*/ ) { + CV_INSTRUMENT_REGION() + Mat queryDescriptors = _queryDescriptors.getMat(); Mat indices( queryDescriptors.rows, knn, CV_32SC1 ); Mat dists( queryDescriptors.rows, knn, CV_32FC1); @@ -1343,6 +1359,8 @@ void FlannBasedMatcher::knnMatchImpl( InputArray _queryDescriptors, std::vector< void FlannBasedMatcher::radiusMatchImpl( InputArray _queryDescriptors, std::vector >& matches, float maxDistance, InputArrayOfArrays /*masks*/, bool /*compactResult*/ ) { + CV_INSTRUMENT_REGION() + Mat queryDescriptors = _queryDescriptors.getMat(); const int count = mergedDescriptors.size(); // TODO do count as param? Mat indices( queryDescriptors.rows, count, CV_32SC1, Scalar::all(-1) ); diff --git a/modules/features2d/src/mser.cpp b/modules/features2d/src/mser.cpp index d60af8ddae..f16a0d2a8b 100644 --- a/modules/features2d/src/mser.cpp +++ b/modules/features2d/src/mser.cpp @@ -1040,6 +1040,8 @@ extractMSER_8uC3( const Mat& src, void MSER_Impl::detectRegions( InputArray _src, vector >& msers, vector& bboxes ) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); msers.clear(); @@ -1076,6 +1078,8 @@ void MSER_Impl::detectRegions( InputArray _src, vector >& msers, v void MSER_Impl::detect( InputArray _image, vector& keypoints, InputArray _mask ) { + CV_INSTRUMENT_REGION() + vector bboxes; vector > msers; Mat mask = _mask.getMat(); diff --git a/modules/features2d/src/orb.cpp b/modules/features2d/src/orb.cpp index 7775b84f40..219e86e109 100644 --- a/modules/features2d/src/orb.cpp +++ b/modules/features2d/src/orb.cpp @@ -957,6 +957,8 @@ void ORB_Impl::detectAndCompute( InputArray _image, InputArray _mask, std::vector& keypoints, OutputArray _descriptors, bool useProvidedKeypoints ) { + CV_INSTRUMENT_REGION() + CV_Assert(patchSize >= 2); bool do_keypoints = !useProvidedKeypoints; diff --git a/modules/flann/src/miniflann.cpp b/modules/flann/src/miniflann.cpp index b7661752c0..8aca73c230 100644 --- a/modules/flann/src/miniflann.cpp +++ b/modules/flann/src/miniflann.cpp @@ -365,6 +365,8 @@ Index::Index(InputArray _data, const IndexParams& params, flann_distance_t _dist void Index::build(InputArray _data, const IndexParams& params, flann_distance_t _distType) { + CV_INSTRUMENT_REGION() + release(); algo = getParam(params, "algorithm", FLANN_INDEX_LINEAR); if( algo == FLANN_INDEX_SAVED ) @@ -433,6 +435,8 @@ Index::~Index() void Index::release() { + CV_INSTRUMENT_REGION() + if( !index ) return; @@ -563,6 +567,8 @@ static void createIndicesDists(OutputArray _indices, OutputArray _dists, void Index::knnSearch(InputArray _query, OutputArray _indices, OutputArray _dists, int knn, const SearchParams& params) { + CV_INSTRUMENT_REGION() + Mat query = _query.getMat(), indices, dists; int dtype = distType == FLANN_DIST_HAMMING ? CV_32S : CV_32F; @@ -605,6 +611,8 @@ int Index::radiusSearch(InputArray _query, OutputArray _indices, OutputArray _dists, double radius, int maxResults, const SearchParams& params) { + CV_INSTRUMENT_REGION() + Mat query = _query.getMat(), indices, dists; int dtype = distType == FLANN_DIST_HAMMING ? CV_32S : CV_32F; CV_Assert( maxResults > 0 ); @@ -668,6 +676,8 @@ template void saveIndex(const Index* index0, const void* inde void Index::save(const String& filename) const { + CV_INSTRUMENT_REGION() + FILE* fout = fopen(filename.c_str(), "wb"); if (fout == NULL) CV_Error_( Error::StsError, ("Can not open file %s for writing FLANN index\n", filename.c_str()) ); diff --git a/modules/imgproc/src/accum.cpp b/modules/imgproc/src/accum.cpp index dc1807f960..8626187fd8 100644 --- a/modules/imgproc/src/accum.cpp +++ b/modules/imgproc/src/accum.cpp @@ -1869,6 +1869,8 @@ namespace cv { static bool ipp_accumulate(InputArray _src, InputOutputArray _dst, InputArray _mask) { + CV_INSTRUMENT_REGION_IPP() + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype); int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype); @@ -1876,28 +1878,28 @@ static bool ipp_accumulate(InputArray _src, InputOutputArray _dst, InputArray _m if (src.dims <= 2 || (src.isContinuous() && dst.isContinuous() && (mask.empty() || mask.isContinuous()))) { - typedef IppStatus (CV_STDCALL * ippiAdd)(const void * pSrc, int srcStep, Ipp32f * pSrcDst, int srcdstStep, IppiSize roiSize); - typedef IppStatus (CV_STDCALL * ippiAddMask)(const void * pSrc, int srcStep, const Ipp8u * pMask, int maskStep, Ipp32f * pSrcDst, + typedef IppStatus (CV_STDCALL * IppiAdd)(const void * pSrc, int srcStep, Ipp32f * pSrcDst, int srcdstStep, IppiSize roiSize); + typedef IppStatus (CV_STDCALL * IppiAddMask)(const void * pSrc, int srcStep, const Ipp8u * pMask, int maskStep, Ipp32f * pSrcDst, int srcDstStep, IppiSize roiSize); - ippiAdd ippFunc = 0; - ippiAddMask ippFuncMask = 0; + IppiAdd ippiAdd_I = 0; + IppiAddMask ippiAdd_IM = 0; if (mask.empty()) { CV_SUPPRESS_DEPRECATED_START - ippFunc = sdepth == CV_8U && ddepth == CV_32F ? (ippiAdd)ippiAdd_8u32f_C1IR : - sdepth == CV_16U && ddepth == CV_32F ? (ippiAdd)ippiAdd_16u32f_C1IR : - sdepth == CV_32F && ddepth == CV_32F ? (ippiAdd)ippiAdd_32f_C1IR : 0; + ippiAdd_I = sdepth == CV_8U && ddepth == CV_32F ? (IppiAdd)ippiAdd_8u32f_C1IR : + sdepth == CV_16U && ddepth == CV_32F ? (IppiAdd)ippiAdd_16u32f_C1IR : + sdepth == CV_32F && ddepth == CV_32F ? (IppiAdd)ippiAdd_32f_C1IR : 0; CV_SUPPRESS_DEPRECATED_END } else if (scn == 1) { - ippFuncMask = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddMask)ippiAdd_8u32f_C1IMR : - sdepth == CV_16U && ddepth == CV_32F ? (ippiAddMask)ippiAdd_16u32f_C1IMR : - sdepth == CV_32F && ddepth == CV_32F ? (ippiAddMask)ippiAdd_32f_C1IMR : 0; + ippiAdd_IM = sdepth == CV_8U && ddepth == CV_32F ? (IppiAddMask)ippiAdd_8u32f_C1IMR : + sdepth == CV_16U && ddepth == CV_32F ? (IppiAddMask)ippiAdd_16u32f_C1IMR : + sdepth == CV_32F && ddepth == CV_32F ? (IppiAddMask)ippiAdd_32f_C1IMR : 0; } - if (ippFunc || ippFuncMask) + if (ippiAdd_I || ippiAdd_IM) { IppStatus status = ippStsErr; @@ -1913,11 +1915,11 @@ static bool ipp_accumulate(InputArray _src, InputOutputArray _dst, InputArray _m } size.width *= scn; - if (ippFunc) - status = ippFunc(src.ptr(), srcstep, dst.ptr(), dststep, ippiSize(size.width, size.height)); - else if(ippFuncMask) - status = ippFuncMask(src.ptr(), srcstep, mask.ptr(), maskstep, - dst.ptr(), dststep, ippiSize(size.width, size.height)); + if (ippiAdd_I) + status = CV_INSTRUMENT_FUN_IPP(ippiAdd_I, src.ptr(), srcstep, dst.ptr(), dststep, ippiSize(size.width, size.height)); + else if (ippiAdd_IM) + status = CV_INSTRUMENT_FUN_IPP(ippiAdd_IM, src.ptr(), srcstep, mask.ptr(), maskstep, + dst.ptr(), dststep, ippiSize(size.width, size.height)); if (status >= 0) return true; @@ -1930,6 +1932,8 @@ static bool ipp_accumulate(InputArray _src, InputOutputArray _dst, InputArray _m void cv::accumulate( InputArray _src, InputOutputArray _dst, InputArray _mask ) { + CV_INSTRUMENT_REGION() + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype); int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype); @@ -1963,6 +1967,8 @@ namespace cv { static bool ipp_accumulate_square(InputArray _src, InputOutputArray _dst, InputArray _mask) { + CV_INSTRUMENT_REGION_IPP() + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype); int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype); @@ -1973,23 +1979,23 @@ static bool ipp_accumulate_square(InputArray _src, InputOutputArray _dst, InputA typedef IppStatus (CV_STDCALL * ippiAddSquare)(const void * pSrc, int srcStep, Ipp32f * pSrcDst, int srcdstStep, IppiSize roiSize); typedef IppStatus (CV_STDCALL * ippiAddSquareMask)(const void * pSrc, int srcStep, const Ipp8u * pMask, int maskStep, Ipp32f * pSrcDst, int srcDstStep, IppiSize roiSize); - ippiAddSquare ippFunc = 0; - ippiAddSquareMask ippFuncMask = 0; + ippiAddSquare ippiAddSquare_I = 0; + ippiAddSquareMask ippiAddSquare_IM = 0; if (mask.empty()) { - ippFunc = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddSquare)ippiAddSquare_8u32f_C1IR : + ippiAddSquare_I = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddSquare)ippiAddSquare_8u32f_C1IR : sdepth == CV_16U && ddepth == CV_32F ? (ippiAddSquare)ippiAddSquare_16u32f_C1IR : sdepth == CV_32F && ddepth == CV_32F ? (ippiAddSquare)ippiAddSquare_32f_C1IR : 0; } else if (scn == 1) { - ippFuncMask = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddSquareMask)ippiAddSquare_8u32f_C1IMR : + ippiAddSquare_IM = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddSquareMask)ippiAddSquare_8u32f_C1IMR : sdepth == CV_16U && ddepth == CV_32F ? (ippiAddSquareMask)ippiAddSquare_16u32f_C1IMR : sdepth == CV_32F && ddepth == CV_32F ? (ippiAddSquareMask)ippiAddSquare_32f_C1IMR : 0; } - if (ippFunc || ippFuncMask) + if (ippiAddSquare_I || ippiAddSquare_IM) { IppStatus status = ippStsErr; @@ -2005,11 +2011,11 @@ static bool ipp_accumulate_square(InputArray _src, InputOutputArray _dst, InputA } size.width *= scn; - if (ippFunc) - status = ippFunc(src.ptr(), srcstep, dst.ptr(), dststep, ippiSize(size.width, size.height)); - else if(ippFuncMask) - status = ippFuncMask(src.ptr(), srcstep, mask.ptr(), maskstep, - dst.ptr(), dststep, ippiSize(size.width, size.height)); + if (ippiAddSquare_I) + status = CV_INSTRUMENT_FUN_IPP(ippiAddSquare_I, src.ptr(), srcstep, dst.ptr(), dststep, ippiSize(size.width, size.height)); + else if (ippiAddSquare_IM) + status = CV_INSTRUMENT_FUN_IPP(ippiAddSquare_IM, src.ptr(), srcstep, mask.ptr(), maskstep, + dst.ptr(), dststep, ippiSize(size.width, size.height)); if (status >= 0) return true; @@ -2022,6 +2028,8 @@ static bool ipp_accumulate_square(InputArray _src, InputOutputArray _dst, InputA void cv::accumulateSquare( InputArray _src, InputOutputArray _dst, InputArray _mask ) { + CV_INSTRUMENT_REGION() + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype); int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype); @@ -2055,6 +2063,8 @@ namespace cv static bool ipp_accumulate_product(InputArray _src1, InputArray _src2, InputOutputArray _dst, InputArray _mask) { + CV_INSTRUMENT_REGION_IPP() + int stype = _src1.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype); int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype); @@ -2066,23 +2076,23 @@ static bool ipp_accumulate_product(InputArray _src1, InputArray _src2, int src2Step, Ipp32f * pSrcDst, int srcDstStep, IppiSize roiSize); typedef IppStatus (CV_STDCALL * ippiAddProductMask)(const void * pSrc1, int src1Step, const void * pSrc2, int src2Step, const Ipp8u * pMask, int maskStep, Ipp32f * pSrcDst, int srcDstStep, IppiSize roiSize); - ippiAddProduct ippFunc = 0; - ippiAddProductMask ippFuncMask = 0; + ippiAddProduct ippiAddProduct_I = 0; + ippiAddProductMask ippiAddProduct_IM = 0; if (mask.empty()) { - ippFunc = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddProduct)ippiAddProduct_8u32f_C1IR : + ippiAddProduct_I = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddProduct)ippiAddProduct_8u32f_C1IR : sdepth == CV_16U && ddepth == CV_32F ? (ippiAddProduct)ippiAddProduct_16u32f_C1IR : sdepth == CV_32F && ddepth == CV_32F ? (ippiAddProduct)ippiAddProduct_32f_C1IR : 0; } else if (scn == 1) { - ippFuncMask = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddProductMask)ippiAddProduct_8u32f_C1IMR : + ippiAddProduct_IM = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddProductMask)ippiAddProduct_8u32f_C1IMR : sdepth == CV_16U && ddepth == CV_32F ? (ippiAddProductMask)ippiAddProduct_16u32f_C1IMR : sdepth == CV_32F && ddepth == CV_32F ? (ippiAddProductMask)ippiAddProduct_32f_C1IMR : 0; } - if (ippFunc || ippFuncMask) + if (ippiAddProduct_I || ippiAddProduct_IM) { IppStatus status = ippStsErr; @@ -2099,12 +2109,12 @@ static bool ipp_accumulate_product(InputArray _src1, InputArray _src2, } size.width *= scn; - if (ippFunc) - status = ippFunc(src1.ptr(), src1step, src2.ptr(), src2step, dst.ptr(), - dststep, ippiSize(size.width, size.height)); - else if(ippFuncMask) - status = ippFuncMask(src1.ptr(), src1step, src2.ptr(), src2step, mask.ptr(), maskstep, - dst.ptr(), dststep, ippiSize(size.width, size.height)); + if (ippiAddProduct_I) + status = CV_INSTRUMENT_FUN_IPP(ippiAddProduct_I, src1.ptr(), src1step, src2.ptr(), src2step, dst.ptr(), + dststep, ippiSize(size.width, size.height)); + else if (ippiAddProduct_IM) + status = CV_INSTRUMENT_FUN_IPP(ippiAddProduct_IM, src1.ptr(), src1step, src2.ptr(), src2step, mask.ptr(), maskstep, + dst.ptr(), dststep, ippiSize(size.width, size.height)); if (status >= 0) return true; @@ -2120,6 +2130,8 @@ static bool ipp_accumulate_product(InputArray _src1, InputArray _src2, void cv::accumulateProduct( InputArray _src1, InputArray _src2, InputOutputArray _dst, InputArray _mask ) { + CV_INSTRUMENT_REGION() + int stype = _src1.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype); int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype); @@ -2154,6 +2166,8 @@ namespace cv static bool ipp_accumulate_weighted( InputArray _src, InputOutputArray _dst, double alpha, InputArray _mask ) { + CV_INSTRUMENT_REGION_IPP() + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype); int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype); @@ -2166,23 +2180,23 @@ static bool ipp_accumulate_weighted( InputArray _src, InputOutputArray _dst, typedef IppStatus (CV_STDCALL * ippiAddWeightedMask)(const void * pSrc, int srcStep, const Ipp8u * pMask, int maskStep, Ipp32f * pSrcDst, int srcDstStep, IppiSize roiSize, Ipp32f alpha); - ippiAddWeighted ippFunc = 0; - ippiAddWeightedMask ippFuncMask = 0; + ippiAddWeighted ippiAddWeighted_I = 0; + ippiAddWeightedMask ippiAddWeighted_IM = 0; if (mask.empty()) { - ippFunc = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddWeighted)ippiAddWeighted_8u32f_C1IR : + ippiAddWeighted_I = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddWeighted)ippiAddWeighted_8u32f_C1IR : sdepth == CV_16U && ddepth == CV_32F ? (ippiAddWeighted)ippiAddWeighted_16u32f_C1IR : sdepth == CV_32F && ddepth == CV_32F ? (ippiAddWeighted)ippiAddWeighted_32f_C1IR : 0; } else if (scn == 1) { - ippFuncMask = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddWeightedMask)ippiAddWeighted_8u32f_C1IMR : + ippiAddWeighted_IM = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddWeightedMask)ippiAddWeighted_8u32f_C1IMR : sdepth == CV_16U && ddepth == CV_32F ? (ippiAddWeightedMask)ippiAddWeighted_16u32f_C1IMR : sdepth == CV_32F && ddepth == CV_32F ? (ippiAddWeightedMask)ippiAddWeighted_32f_C1IMR : 0; } - if (ippFunc || ippFuncMask) + if (ippiAddWeighted_I || ippiAddWeighted_IM) { IppStatus status = ippStsErr; @@ -2198,11 +2212,11 @@ static bool ipp_accumulate_weighted( InputArray _src, InputOutputArray _dst, } size.width *= scn; - if (ippFunc) - status = ippFunc(src.ptr(), srcstep, dst.ptr(), dststep, ippiSize(size.width, size.height), (Ipp32f)alpha); - else if(ippFuncMask) - status = ippFuncMask(src.ptr(), srcstep, mask.ptr(), maskstep, - dst.ptr(), dststep, ippiSize(size.width, size.height), (Ipp32f)alpha); + if (ippiAddWeighted_I) + status = CV_INSTRUMENT_FUN_IPP(ippiAddWeighted_I, src.ptr(), srcstep, dst.ptr(), dststep, ippiSize(size.width, size.height), (Ipp32f)alpha); + else if (ippiAddWeighted_IM) + status = CV_INSTRUMENT_FUN_IPP(ippiAddWeighted_IM, src.ptr(), srcstep, mask.ptr(), maskstep, + dst.ptr(), dststep, ippiSize(size.width, size.height), (Ipp32f)alpha); if (status >= 0) return true; @@ -2216,6 +2230,8 @@ static bool ipp_accumulate_weighted( InputArray _src, InputOutputArray _dst, void cv::accumulateWeighted( InputArray _src, InputOutputArray _dst, double alpha, InputArray _mask ) { + CV_INSTRUMENT_REGION() + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype); int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype); diff --git a/modules/imgproc/src/approx.cpp b/modules/imgproc/src/approx.cpp index 54b5dd07ab..ec0db30179 100644 --- a/modules/imgproc/src/approx.cpp +++ b/modules/imgproc/src/approx.cpp @@ -674,6 +674,8 @@ approxPolyDP_( const Point_* src_contour, int count0, Point_* dst_contour, void cv::approxPolyDP( InputArray _curve, OutputArray _approxCurve, double epsilon, bool closed ) { + CV_INSTRUMENT_REGION() + Mat curve = _curve.getMat(); int npoints = curve.checkVector(2), depth = curve.depth(); CV_Assert( npoints >= 0 && (depth == CV_32S || depth == CV_32F)); diff --git a/modules/imgproc/src/blend.cpp b/modules/imgproc/src/blend.cpp index 2393f26db7..17e31aa4ab 100644 --- a/modules/imgproc/src/blend.cpp +++ b/modules/imgproc/src/blend.cpp @@ -121,6 +121,8 @@ static bool ocl_blendLinear( InputArray _src1, InputArray _src2, InputArray _wei void cv::blendLinear( InputArray _src1, InputArray _src2, InputArray _weights1, InputArray _weights2, OutputArray _dst ) { + CV_INSTRUMENT_REGION() + int type = _src1.type(), depth = CV_MAT_DEPTH(type); Size size = _src1.size(); diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 8d1f20552c..6ef5dee9e8 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -66,6 +66,8 @@ static void CannyImpl(Mat& dx_, Mat& dy_, Mat& _dst, double low_thresh, double h template static bool ippCanny(const Mat& _src, const Mat& dx_, const Mat& dy_, Mat& _dst, float low, float high) { + CV_INSTRUMENT_REGION_IPP() + #if USE_IPP_CANNY int size = 0, size1 = 0; IppiSize roi = { _src.cols, _src.rows }; @@ -98,13 +100,13 @@ static bool ippCanny(const Mat& _src, const Mat& dx_, const Mat& dy_, Mat& _dst, if (!useCustomDeriv) { Mat _dx(_src.rows, _src.cols, CV_16S); - if( ippiFilterSobelNegVertBorder_8u16s_C1R(_src.ptr(), (int)_src.step, + if( CV_INSTRUMENT_FUN_IPP(ippiFilterSobelNegVertBorder_8u16s_C1R, _src.ptr(), (int)_src.step, _dx.ptr(), (int)_dx.step, roi, ippMskSize3x3, ippBorderRepl, 0, buffer) < 0 ) return false; Mat _dy(_src.rows, _src.cols, CV_16S); - if( ippiFilterSobelHorizBorder_8u16s_C1R(_src.ptr(), (int)_src.step, + if( CV_INSTRUMENT_FUN_IPP(ippiFilterSobelHorizBorder_8u16s_C1R, _src.ptr(), (int)_src.step, _dy.ptr(), (int)_dy.step, roi, ippMskSize3x3, ippBorderRepl, 0, buffer) < 0 ) return false; @@ -118,7 +120,7 @@ static bool ippCanny(const Mat& _src, const Mat& dx_, const Mat& dy_, Mat& _dst, dy = dy_; } - if( ippiCanny_16s8u_C1R(dx.ptr(), (int)dx.step, + if( CV_INSTRUMENT_FUN_IPP(ippiCanny_16s8u_C1R, dx.ptr(), (int)dx.step, dy.ptr(), (int)dy.step, _dst.ptr(), (int)_dst.step, roi, low, high, buffer) < 0 ) return false; @@ -718,6 +720,8 @@ void Canny( InputArray _src, OutputArray _dst, double low_thresh, double high_thresh, int aperture_size, bool L2gradient ) { + CV_INSTRUMENT_REGION() + const int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); const Size size = _src.size(); diff --git a/modules/imgproc/src/clahe.cpp b/modules/imgproc/src/clahe.cpp index 8481834e1b..342b393577 100644 --- a/modules/imgproc/src/clahe.cpp +++ b/modules/imgproc/src/clahe.cpp @@ -351,6 +351,8 @@ namespace void CLAHE_Impl::apply(cv::InputArray _src, cv::OutputArray _dst) { + CV_INSTRUMENT_REGION() + CV_Assert( _src.type() == CV_8UC1 || _src.type() == CV_16UC1 ); #ifdef HAVE_OPENCL diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 1d83577b95..645a891df4 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -226,6 +226,8 @@ public: virtual void operator()(const Range& range) const { + CV_INSTRUMENT_REGION_IPP(); + const void *yS = src_data + src_step * range.start; void *yD = dst_data + dst_step * range.start; if( !cvt(yS, static_cast(src_step), yD, static_cast(dst_step), width, range.end - range.start) ) @@ -278,19 +280,19 @@ bool CvtColorIPPLoopCopy(const uchar * src_data, size_t src_step, int src_type, static IppStatus CV_STDCALL ippiSwapChannels_8u_C3C4Rf(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, IppiSize roiSize, const int *dstOrder) { - return ippiSwapChannels_8u_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP8u); + return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_8u_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP8u); } static IppStatus CV_STDCALL ippiSwapChannels_16u_C3C4Rf(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep, IppiSize roiSize, const int *dstOrder) { - return ippiSwapChannels_16u_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP16u); + return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_16u_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP16u); } static IppStatus CV_STDCALL ippiSwapChannels_32f_C3C4Rf(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, IppiSize roiSize, const int *dstOrder) { - return ippiSwapChannels_32f_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP32f); + return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_32f_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP32f); } static ippiReorderFunc ippiSwapChannelsC3C4RTab[] = @@ -409,18 +411,18 @@ static ippiGeneralFunc ippiLUVToRGBTab[] = struct IPPGeneralFunctor { - IPPGeneralFunctor(ippiGeneralFunc _func) : func(_func){} + IPPGeneralFunctor(ippiGeneralFunc _func) : ippiColorConvertGeneral(_func){} bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const { - return func ? func(src, srcStep, dst, dstStep, ippiSize(cols, rows)) >= 0 : false; + return ippiColorConvertGeneral ? CV_INSTRUMENT_FUN_IPP(ippiColorConvertGeneral, src, srcStep, dst, dstStep, ippiSize(cols, rows)) >= 0 : false; } private: - ippiGeneralFunc func; + ippiGeneralFunc ippiColorConvertGeneral; }; struct IPPReorderFunctor { - IPPReorderFunctor(ippiReorderFunc _func, int _order0, int _order1, int _order2) : func(_func) + IPPReorderFunctor(ippiReorderFunc _func, int _order0, int _order1, int _order2) : ippiColorConvertReorder(_func) { order[0] = _order0; order[1] = _order1; @@ -429,17 +431,17 @@ struct IPPReorderFunctor } bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const { - return func ? func(src, srcStep, dst, dstStep, ippiSize(cols, rows), order) >= 0 : false; + return ippiColorConvertReorder ? CV_INSTRUMENT_FUN_IPP(ippiColorConvertReorder, src, srcStep, dst, dstStep, ippiSize(cols, rows), order) >= 0 : false; } private: - ippiReorderFunc func; + ippiReorderFunc ippiColorConvertReorder; int order[4]; }; struct IPPColor2GrayFunctor { IPPColor2GrayFunctor(ippiColor2GrayFunc _func) : - func(_func) + ippiColorToGray(_func) { coeffs[0] = 0.114f; coeffs[1] = 0.587f; @@ -447,61 +449,61 @@ struct IPPColor2GrayFunctor } bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const { - return func ? func(src, srcStep, dst, dstStep, ippiSize(cols, rows), coeffs) >= 0 : false; + return ippiColorToGray ? CV_INSTRUMENT_FUN_IPP(ippiColorToGray, src, srcStep, dst, dstStep, ippiSize(cols, rows), coeffs) >= 0 : false; } private: - ippiColor2GrayFunc func; + ippiColor2GrayFunc ippiColorToGray; Ipp32f coeffs[3]; }; struct IPPGray2BGRFunctor { IPPGray2BGRFunctor(ippiGeneralFunc _func) : - func(_func) + ippiGrayToBGR(_func) { } bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const { - if (func == 0) + if (ippiGrayToBGR == 0) return false; const void* srcarray[3] = { src, src, src }; - return func(srcarray, srcStep, dst, dstStep, ippiSize(cols, rows)) >= 0; + return CV_INSTRUMENT_FUN_IPP(ippiGrayToBGR, srcarray, srcStep, dst, dstStep, ippiSize(cols, rows)) >= 0; } private: - ippiGeneralFunc func; + ippiGeneralFunc ippiGrayToBGR; }; struct IPPGray2BGRAFunctor { IPPGray2BGRAFunctor(ippiGeneralFunc _func1, ippiReorderFunc _func2, int _depth) : - func1(_func1), func2(_func2), depth(_depth) + ippiColorConvertGeneral(_func1), ippiColorConvertReorder(_func2), depth(_depth) { } bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const { - if (func1 == 0 || func2 == 0) + if (ippiColorConvertGeneral == 0 || ippiColorConvertReorder == 0) return false; const void* srcarray[3] = { src, src, src }; Mat temp(rows, cols, CV_MAKETYPE(depth, 3)); - if(func1(srcarray, srcStep, temp.ptr(), (int)temp.step[0], ippiSize(cols, rows)) < 0) + if(CV_INSTRUMENT_FUN_IPP(ippiColorConvertGeneral, srcarray, srcStep, temp.ptr(), (int)temp.step[0], ippiSize(cols, rows)) < 0) return false; int order[4] = {0, 1, 2, 3}; - return func2(temp.ptr(), (int)temp.step[0], dst, dstStep, ippiSize(cols, rows), order) >= 0; + return CV_INSTRUMENT_FUN_IPP(ippiColorConvertReorder, temp.ptr(), (int)temp.step[0], dst, dstStep, ippiSize(cols, rows), order) >= 0; } private: - ippiGeneralFunc func1; - ippiReorderFunc func2; + ippiGeneralFunc ippiColorConvertGeneral; + ippiReorderFunc ippiColorConvertReorder; int depth; }; struct IPPReorderGeneralFunctor { IPPReorderGeneralFunctor(ippiReorderFunc _func1, ippiGeneralFunc _func2, int _order0, int _order1, int _order2, int _depth) : - func1(_func1), func2(_func2), depth(_depth) + ippiColorConvertReorder(_func1), ippiColorConvertGeneral(_func2), depth(_depth) { order[0] = _order0; order[1] = _order1; @@ -510,18 +512,18 @@ struct IPPReorderGeneralFunctor } bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const { - if (func1 == 0 || func2 == 0) + if (ippiColorConvertReorder == 0 || ippiColorConvertGeneral == 0) return false; Mat temp; temp.create(rows, cols, CV_MAKETYPE(depth, 3)); - if(func1(src, srcStep, temp.ptr(), (int)temp.step[0], ippiSize(cols, rows), order) < 0) + if(CV_INSTRUMENT_FUN_IPP(ippiColorConvertReorder, src, srcStep, temp.ptr(), (int)temp.step[0], ippiSize(cols, rows), order) < 0) return false; - return func2(temp.ptr(), (int)temp.step[0], dst, dstStep, ippiSize(cols, rows)) >= 0; + return CV_INSTRUMENT_FUN_IPP(ippiColorConvertGeneral, temp.ptr(), (int)temp.step[0], dst, dstStep, ippiSize(cols, rows)) >= 0; } private: - ippiReorderFunc func1; - ippiGeneralFunc func2; + ippiReorderFunc ippiColorConvertReorder; + ippiGeneralFunc ippiColorConvertGeneral; int order[4]; int depth; }; @@ -529,7 +531,7 @@ private: struct IPPGeneralReorderFunctor { IPPGeneralReorderFunctor(ippiGeneralFunc _func1, ippiReorderFunc _func2, int _order0, int _order1, int _order2, int _depth) : - func1(_func1), func2(_func2), depth(_depth) + ippiColorConvertGeneral(_func1), ippiColorConvertReorder(_func2), depth(_depth) { order[0] = _order0; order[1] = _order1; @@ -538,18 +540,18 @@ struct IPPGeneralReorderFunctor } bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const { - if (func1 == 0 || func2 == 0) + if (ippiColorConvertGeneral == 0 || ippiColorConvertReorder == 0) return false; Mat temp; temp.create(rows, cols, CV_MAKETYPE(depth, 3)); - if(func1(src, srcStep, temp.ptr(), (int)temp.step[0], ippiSize(cols, rows)) < 0) + if(CV_INSTRUMENT_FUN_IPP(ippiColorConvertGeneral, src, srcStep, temp.ptr(), (int)temp.step[0], ippiSize(cols, rows)) < 0) return false; - return func2(temp.ptr(), (int)temp.step[0], dst, dstStep, ippiSize(cols, rows), order) >= 0; + return CV_INSTRUMENT_FUN_IPP(ippiColorConvertReorder, temp.ptr(), (int)temp.step[0], dst, dstStep, ippiSize(cols, rows), order) >= 0; } private: - ippiGeneralFunc func1; - ippiReorderFunc func2; + ippiGeneralFunc ippiColorConvertGeneral; + ippiReorderFunc ippiColorConvertReorder; int order[4]; int depth; }; @@ -7386,6 +7388,8 @@ void cvtBGRtoBGR(const uchar * src_data, size_t src_step, int width, int height, int depth, int scn, int dcn, bool swapBlue) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtBGRtoBGR, cv_hal_cvtBGRtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, scn, dcn, swapBlue); #if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 @@ -7447,6 +7451,8 @@ void cvtBGRtoBGR5x5(const uchar * src_data, size_t src_step, int width, int height, int scn, bool swapBlue, int greenBits) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtBGRtoBGR5x5, cv_hal_cvtBGRtoBGR5x5, src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, greenBits); #if defined(HAVE_IPP) && IPP_DISABLE_BLOCK // breaks OCL accuracy tests @@ -7493,6 +7499,8 @@ void cvtBGR5x5toBGR(const uchar * src_data, size_t src_step, int width, int height, int dcn, bool swapBlue, int greenBits) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtBGR5x5toBGR, cv_hal_cvtBGR5x5toBGR, src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, greenBits); #if defined(HAVE_IPP) && IPP_VERSION_X100 < 900 @@ -7539,6 +7547,8 @@ void cvtBGRtoGray(const uchar * src_data, size_t src_step, int width, int height, int depth, int scn, bool swapBlue) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtBGRtoGray, cv_hal_cvtBGRtoGray, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue); #if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 @@ -7586,6 +7596,8 @@ void cvtGraytoBGR(const uchar * src_data, size_t src_step, int width, int height, int depth, int dcn) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtGraytoBGR, cv_hal_cvtGraytoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn); #if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 @@ -7620,6 +7632,8 @@ void cvtBGR5x5toGray(const uchar * src_data, size_t src_step, int width, int height, int greenBits) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtBGR5x5toGray, cv_hal_cvtBGR5x5toGray, src_data, src_step, dst_data, dst_step, width, height, greenBits); CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB5x52Gray(greenBits)); } @@ -7630,6 +7644,8 @@ void cvtGraytoBGR5x5(const uchar * src_data, size_t src_step, int width, int height, int greenBits) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtGraytoBGR5x5, cv_hal_cvtGraytoBGR5x5, src_data, src_step, dst_data, dst_step, width, height, greenBits); CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, Gray2RGB5x5(greenBits)); } @@ -7640,6 +7656,8 @@ void cvtBGRtoYUV(const uchar * src_data, size_t src_step, int width, int height, int depth, int scn, bool swapBlue, bool isCbCr) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtBGRtoYUV, cv_hal_cvtBGRtoYUV, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isCbCr); #if defined(HAVE_IPP) && IPP_DISABLE_BLOCK @@ -7693,6 +7711,8 @@ void cvtYUVtoBGR(const uchar * src_data, size_t src_step, int width, int height, int depth, int dcn, bool swapBlue, bool isCbCr) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtYUVtoBGR, cv_hal_cvtYUVtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isCbCr); @@ -7747,6 +7767,8 @@ void cvtBGRtoXYZ(const uchar * src_data, size_t src_step, int width, int height, int depth, int scn, bool swapBlue) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtBGRtoXYZ, cv_hal_cvtBGRtoXYZ, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue); #if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 @@ -7793,6 +7815,8 @@ void cvtXYZtoBGR(const uchar * src_data, size_t src_step, int width, int height, int depth, int dcn, bool swapBlue) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtXYZtoBGR, cv_hal_cvtXYZtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue); #if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 @@ -7840,6 +7864,8 @@ void cvtBGRtoHSV(const uchar * src_data, size_t src_step, int width, int height, int depth, int scn, bool swapBlue, bool isFullRange, bool isHSV) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtBGRtoHSV, cv_hal_cvtBGRtoHSV, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isFullRange, isHSV); #if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 @@ -7925,6 +7951,8 @@ void cvtHSVtoBGR(const uchar * src_data, size_t src_step, int width, int height, int depth, int dcn, bool swapBlue, bool isFullRange, bool isHSV) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtHSVtoBGR, cv_hal_cvtHSVtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isFullRange, isHSV); #if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 @@ -8014,6 +8042,8 @@ void cvtBGRtoLab(const uchar * src_data, size_t src_step, int width, int height, int depth, int scn, bool swapBlue, bool isLab, bool srgb) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtBGRtoLab, cv_hal_cvtBGRtoLab, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isLab, srgb); #if defined(HAVE_IPP) && IPP_DISABLE_BLOCK @@ -8109,6 +8139,8 @@ void cvtLabtoBGR(const uchar * src_data, size_t src_step, int width, int height, int depth, int dcn, bool swapBlue, bool isLab, bool srgb) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtLabtoBGR, cv_hal_cvtLabtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isLab, srgb); #if defined(HAVE_IPP) && IPP_DISABLE_BLOCK @@ -8202,6 +8234,8 @@ void cvtTwoPlaneYUVtoBGR(const uchar * src_data, size_t src_step, int dst_width, int dst_height, int dcn, bool swapBlue, int uIdx) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtTwoPlaneYUVtoBGR, cv_hal_cvtTwoPlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx); int blueIdx = swapBlue ? 2 : 0; const uchar* uv = src_data + src_step * static_cast(dst_height); @@ -8224,6 +8258,8 @@ void cvtThreePlaneYUVtoBGR(const uchar * src_data, size_t src_step, int dst_width, int dst_height, int dcn, bool swapBlue, int uIdx) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtThreePlaneYUVtoBGR, cv_hal_cvtThreePlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx); const uchar* u = src_data + src_step * static_cast(dst_height); const uchar* v = src_data + src_step * static_cast(dst_height + dst_height/4) + (dst_width/2) * ((dst_height % 4)/2); @@ -8249,6 +8285,8 @@ void cvtBGRtoThreePlaneYUV(const uchar * src_data, size_t src_step, int width, int height, int scn, bool swapBlue, int uIdx) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtBGRtoThreePlaneYUV, cv_hal_cvtBGRtoThreePlaneYUV, src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, uIdx); int blueIdx = swapBlue ? 2 : 0; switch(blueIdx + uIdx*10) @@ -8266,6 +8304,8 @@ void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, int width, int height, int dcn, bool swapBlue, int uIdx, int ycn) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtOnePlaneYUVtoBGR, cv_hal_cvtOnePlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, uIdx, ycn); int blueIdx = swapBlue ? 2 : 0; switch(dcn*1000 + blueIdx*100 + uIdx*10 + ycn) @@ -8290,6 +8330,8 @@ void cvtRGBAtoMultipliedRGBA(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtRGBAtoMultipliedRGBA, cv_hal_cvtRGBAtoMultipliedRGBA, src_data, src_step, dst_data, dst_step, width, height); #ifdef HAVE_IPP @@ -8308,6 +8350,8 @@ void cvtMultipliedRGBAtoRGBA(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height) { + CV_INSTRUMENT_REGION() + CALL_HAL(cvtMultipliedRGBAtoRGBA, cv_hal_cvtMultipliedRGBAtoRGBA, src_data, src_step, dst_data, dst_step, width, height); CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, mRGBA2RGBA()); } @@ -8398,6 +8442,8 @@ inline bool isFullRange(int code) void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) { + CV_INSTRUMENT_REGION() + int stype = _src.type(); int scn = CV_MAT_CN(stype), depth = CV_MAT_DEPTH(stype), uidx, gbits, ycn; @@ -8596,8 +8642,8 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) _dst.create(dstSz, CV_MAKETYPE(depth, dcn)); dst = _dst.getMat(); #ifdef HAVE_IPP - if (ippStsNoErr == ippiCopy_8u_C1R(src.data, (int)src.step, dst.data, (int)dst.step, - ippiSize(dstSz.width, dstSz.height))) + if (CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1R, src.data, (int)src.step, dst.data, (int)dst.step, + ippiSize(dstSz.width, dstSz.height)) >= 0) break; #endif src(Range(0, dstSz.height), Range::all()).copyTo(dst); diff --git a/modules/imgproc/src/colormap.cpp b/modules/imgproc/src/colormap.cpp index ec6e005cee..3fc9755403 100644 --- a/modules/imgproc/src/colormap.cpp +++ b/modules/imgproc/src/colormap.cpp @@ -492,6 +492,8 @@ namespace colormap void ColorMap::operator()(InputArray _src, OutputArray _dst) const { + CV_INSTRUMENT_REGION() + if(_lut.total() != 256) CV_Error(Error::StsAssert, "cv::LUT only supports tables of size 256."); Mat src = _src.getMat(); diff --git a/modules/imgproc/src/contours.cpp b/modules/imgproc/src/contours.cpp index 4cb3f55c41..5f08be5fe5 100644 --- a/modules/imgproc/src/contours.cpp +++ b/modules/imgproc/src/contours.cpp @@ -1704,6 +1704,8 @@ cvFindContours( void* img, CvMemStorage* storage, void cv::findContours( InputOutputArray _image, OutputArrayOfArrays _contours, OutputArray _hierarchy, int mode, int method, Point offset ) { + CV_INSTRUMENT_REGION() + // Sanity check: output must be of type vector> CV_Assert((_contours.kind() == _InputArray::STD_VECTOR_VECTOR || _contours.kind() == _InputArray::STD_VECTOR_MAT || _contours.kind() == _InputArray::STD_VECTOR_UMAT)); @@ -1757,6 +1759,8 @@ void cv::findContours( InputOutputArray _image, OutputArrayOfArrays _contours, void cv::findContours( InputOutputArray _image, OutputArrayOfArrays _contours, int mode, int method, Point offset) { + CV_INSTRUMENT_REGION() + findContours(_image, _contours, noArray(), mode, method, offset); } diff --git a/modules/imgproc/src/convhull.cpp b/modules/imgproc/src/convhull.cpp index b870ee4217..f7e7c2291d 100644 --- a/modules/imgproc/src/convhull.cpp +++ b/modules/imgproc/src/convhull.cpp @@ -128,6 +128,8 @@ struct CHullCmpPoints void convexHull( InputArray _points, OutputArray _hull, bool clockwise, bool returnPoints ) { + CV_INSTRUMENT_REGION() + Mat points = _points.getMat(); int i, total = points.checkVector(2), depth = points.depth(), nout = 0; int miny_ind = 0, maxy_ind = 0; @@ -264,6 +266,8 @@ void convexHull( InputArray _points, OutputArray _hull, bool clockwise, bool ret void convexityDefects( InputArray _points, InputArray _hull, OutputArray _defects ) { + CV_INSTRUMENT_REGION() + Mat points = _points.getMat(); int i, j = 0, npoints = points.checkVector(2, CV_32S); CV_Assert( npoints >= 0 ); diff --git a/modules/imgproc/src/corner.cpp b/modules/imgproc/src/corner.cpp index 946625eb0b..7f3bad5012 100644 --- a/modules/imgproc/src/corner.cpp +++ b/modules/imgproc/src/corner.cpp @@ -528,6 +528,8 @@ namespace cv { static bool ipp_cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType ) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 800 Mat src = _src.getMat(); _dst.create( src.size(), CV_32FC1 ); @@ -552,23 +554,23 @@ static bool ipp_cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockS (kerSize == 3 || kerSize == 5) && (blockSize == 3 || blockSize == 5)) { ippiMinEigenValGetBufferSize getBufferSizeFunc = 0; - ippiMinEigenVal minEigenValFunc = 0; + ippiMinEigenVal ippiMinEigenVal_C1R = 0; float norm_coef = 0.f; if (src.type() == CV_8UC1) { getBufferSizeFunc = (ippiMinEigenValGetBufferSize) ippiMinEigenValGetBufferSize_8u32f_C1R; - minEigenValFunc = (ippiMinEigenVal) ippiMinEigenVal_8u32f_C1R; + ippiMinEigenVal_C1R = (ippiMinEigenVal) ippiMinEigenVal_8u32f_C1R; norm_coef = 1.f / 255.f; } else if (src.type() == CV_32FC1) { getBufferSizeFunc = (ippiMinEigenValGetBufferSize) ippiMinEigenValGetBufferSize_32f_C1R; - minEigenValFunc = (ippiMinEigenVal) ippiMinEigenVal_32f_C1R; + ippiMinEigenVal_C1R = (ippiMinEigenVal) ippiMinEigenVal_32f_C1R; norm_coef = 255.f; } norm_coef = kerType == ippKernelSobel ? norm_coef : norm_coef / 2.45f; - if (getBufferSizeFunc && minEigenValFunc) + if (getBufferSizeFunc && ippiMinEigenVal_C1R) { int bufferSize; IppiSize srcRoi = { src.cols, src.rows }; @@ -576,9 +578,9 @@ static bool ipp_cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockS if (ok >= 0) { AutoBuffer buffer(bufferSize); - ok = minEigenValFunc(src.ptr(), (int) src.step, dst.ptr(), (int) dst.step, srcRoi, kerType, kerSize, blockSize, buffer); + ok = CV_INSTRUMENT_FUN_IPP(ippiMinEigenVal_C1R, src.ptr(), (int) src.step, dst.ptr(), (int) dst.step, srcRoi, kerType, kerSize, blockSize, buffer); CV_SUPPRESS_DEPRECATED_START - if (ok >= 0) ok = ippiMulC_32f_C1IR(norm_coef, dst.ptr(), (int) dst.step, srcRoi); + if (ok >= 0) ok = CV_INSTRUMENT_FUN_IPP(ippiMulC_32f_C1IR, norm_coef, dst.ptr(), (int) dst.step, srcRoi); CV_SUPPRESS_DEPRECATED_END if (ok >= 0) { @@ -599,6 +601,8 @@ static bool ipp_cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockS void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, 0.0, borderType, MINEIGENVAL)) @@ -609,7 +613,7 @@ void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, in #endif CV_IPP_RUN(((borderTypeNI == BORDER_REPLICATE && (!_src.isSubmatrix() || isolated)) && (kerSize == 3 || kerSize == 5) && (blockSize == 3 || blockSize == 5)) && IPP_VERSION_X100 >= 800, - ipp_cornerMinEigenVal( _src, _dst, blockSize, ksize, borderType )); + ipp_cornerMinEigenVal( _src, _dst, blockSize, ksize, borderType )); Mat src = _src.getMat(); @@ -625,6 +629,8 @@ namespace cv { static bool ipp_cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksize, double k, int borderType ) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK Mat src = _src.getMat(); _dst.create( src.size(), CV_32FC1 ); @@ -658,11 +664,11 @@ static bool ipp_cornerHarris( InputArray _src, OutputArray _dst, int blockSize, IppStatus status = (IppStatus)-1; if (depth == CV_8U) - status = ippiHarrisCorner_8u32f_C1R((const Ipp8u *)src.data, (int)src.step, (Ipp32f *)dst.data, (int)dst.step, roisize, - filterType, masksize, blockSize, (Ipp32f)k, (Ipp32f)scale, borderTypeIpp, 0, buffer); + status = CV_INSTRUMENT_FUN_IPP(ippiHarrisCorner_8u32f_C1R,((const Ipp8u *)src.data, (int)src.step, (Ipp32f *)dst.data, (int)dst.step, roisize, + filterType, masksize, blockSize, (Ipp32f)k, (Ipp32f)scale, borderTypeIpp, 0, buffer)); else if (depth == CV_32F) - status = ippiHarrisCorner_32f_C1R((const Ipp32f *)src.data, (int)src.step, (Ipp32f *)dst.data, (int)dst.step, roisize, - filterType, masksize, blockSize, (Ipp32f)k, (Ipp32f)scale, borderTypeIpp, 0, buffer); + status = CV_INSTRUMENT_FUN_IPP(ippiHarrisCorner_32f_C1R,((const Ipp32f *)src.data, (int)src.step, (Ipp32f *)dst.data, (int)dst.step, roisize, + filterType, masksize, blockSize, (Ipp32f)k, (Ipp32f)scale, borderTypeIpp, 0, buffer)); ippsFree(buffer); if (status >= 0) @@ -683,6 +689,8 @@ static bool ipp_cornerHarris( InputArray _src, OutputArray _dst, int blockSize, void cv::cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksize, double k, int borderType ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, k, borderType, HARRIS)) @@ -706,6 +714,8 @@ void cv::cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksi void cv::cornerEigenValsAndVecs( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType ) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); Size dsz = _dst.size(); int dtype = _dst.type(); @@ -719,6 +729,8 @@ void cv::cornerEigenValsAndVecs( InputArray _src, OutputArray _dst, int blockSiz void cv::preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int borderType ) { + CV_INSTRUMENT_REGION() + int type = _src.type(); CV_Assert( type == CV_8UC1 || type == CV_32FC1 ); diff --git a/modules/imgproc/src/cornersubpix.cpp b/modules/imgproc/src/cornersubpix.cpp index 1909bbcbb1..1bd30d24c9 100644 --- a/modules/imgproc/src/cornersubpix.cpp +++ b/modules/imgproc/src/cornersubpix.cpp @@ -44,6 +44,8 @@ void cv::cornerSubPix( InputArray _image, InputOutputArray _corners, Size win, Size zeroZone, TermCriteria criteria ) { + CV_INSTRUMENT_REGION() + const int MAX_ITERS = 100; int win_w = win.width * 2 + 1, win_h = win.height * 2 + 1; int i, j, k; diff --git a/modules/imgproc/src/demosaicing.cpp b/modules/imgproc/src/demosaicing.cpp index cec450dc71..296ace8a25 100644 --- a/modules/imgproc/src/demosaicing.cpp +++ b/modules/imgproc/src/demosaicing.cpp @@ -1615,6 +1615,8 @@ static void Bayer2RGB_EdgeAware_T(const Mat& src, Mat& dst, int code) void cv::demosaicing(InputArray _src, OutputArray _dst, int code, int dcn) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(), dst; Size sz = src.size(); int scn = src.channels(), depth = src.depth(); diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index 06592d8b2d..aa9183aceb 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -184,6 +184,8 @@ namespace cv { static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, double scale, double delta, int borderType) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 810 if ((0 > dx) || (0 > dy) || (1 != dx + dy)) return false; @@ -230,7 +232,7 @@ static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) return false; - sts = ippiFilterScharrHorizMaskBorder_8u16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); + sts = CV_INSTRUMENT_FUN_IPP(ippiFilterScharrHorizMaskBorder_8u16s_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } else { @@ -239,7 +241,7 @@ static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) return false; - sts = ippiFilterScharrVertMaskBorder_8u16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); + sts = CV_INSTRUMENT_FUN_IPP(ippiFilterScharrVertMaskBorder_8u16s_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } ippsFree(pBuffer); } @@ -253,7 +255,7 @@ static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) return false; - sts = ippiFilterScharrHorizMaskBorder_16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); + sts = CV_INSTRUMENT_FUN_IPP(ippiFilterScharrHorizMaskBorder_16s_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } else { @@ -262,7 +264,7 @@ static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) return false; - sts = ippiFilterScharrVertMaskBorder_16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); + sts = CV_INSTRUMENT_FUN_IPP(ippiFilterScharrVertMaskBorder_16s_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } ippsFree(pBuffer); } @@ -276,7 +278,7 @@ static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) return false; - sts = ippiFilterScharrHorizMaskBorder_32f_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); + sts = CV_INSTRUMENT_FUN_IPP(ippiFilterScharrHorizMaskBorder_32f_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } else { @@ -285,14 +287,14 @@ static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) return false; - sts = ippiFilterScharrVertMaskBorder_32f_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); + sts = CV_INSTRUMENT_FUN_IPP(ippiFilterScharrVertMaskBorder_32f_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } ippsFree(pBuffer); if (sts < 0) return false;; if (FLT_EPSILON < fabs(scale - 1.0)) - sts = ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, roiSize); + sts = CV_INSTRUMENT_FUN_IPP(ippiMulC_32f_C1R, dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, roiSize); } return (0 <= sts); #else @@ -303,6 +305,8 @@ static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType) { + CV_INSTRUMENT_REGION_IPP() + if ((borderType != BORDER_REPLICATE) || ((3 != ksize) && (5 != ksize))) return false; if (fabs(delta) > FLT_EPSILON) @@ -333,7 +337,7 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, buffer.allocate(bufSize); #endif - if (0 > ippiFilterSobelNegVertBorder_8u16s_C1R(src.ptr(), (int)src.step, + if (0 > CV_INSTRUMENT_FUN_IPP(ippiFilterSobelNegVertBorder_8u16s_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) return false; @@ -352,7 +356,7 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, buffer.allocate(bufSize); #endif - if (0 > ippiFilterSobelHorizBorder_8u16s_C1R(src.ptr(), (int)src.step, + if (0 > CV_INSTRUMENT_FUN_IPP(ippiFilterSobelHorizBorder_8u16s_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) return false; @@ -371,7 +375,7 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, buffer.allocate(bufSize); #endif - if (0 > ippiFilterSobelVertSecondBorder_8u16s_C1R(src.ptr(), (int)src.step, + if (0 > CV_INSTRUMENT_FUN_IPP(ippiFilterSobelVertSecondBorder_8u16s_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) return false; @@ -390,7 +394,7 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, buffer.allocate(bufSize); #endif - if (0 > ippiFilterSobelHorizSecondBorder_8u16s_C1R(src.ptr(), (int)src.step, + if (0 > CV_INSTRUMENT_FUN_IPP(ippiFilterSobelHorizSecondBorder_8u16s_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) return false; @@ -456,12 +460,12 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, buffer.allocate(bufSize); #endif - if (0 > ippiFilterSobelVertSecondBorder_32f_C1R(src.ptr(), (int)src.step, + if (0 > CV_INSTRUMENT_FUN_IPP(ippiFilterSobelVertSecondBorder_32f_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) return false; if(scale != 1) - ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); + CV_INSTRUMENT_FUN_IPP(ippiMulC_32f_C1R, dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); return true; } @@ -477,13 +481,13 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, buffer.allocate(bufSize); #endif - if (0 > ippiFilterSobelHorizSecondBorder_32f_C1R(src.ptr(), (int)src.step, + if (0 > CV_INSTRUMENT_FUN_IPP(ippiFilterSobelHorizSecondBorder_32f_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) return false; if(scale != 1) - ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); + CV_INSTRUMENT_FUN_IPP(ippiMulC_32f_C1R, dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); return true; } } @@ -492,6 +496,8 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, static bool ipp_sobel(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType) { + CV_INSTRUMENT_REGION_IPP() + if (ksize < 0) { if (IPPDerivScharr(_src, _dst, ddepth, dx, dy, scale, delta, borderType)) @@ -510,6 +516,8 @@ static bool ipp_sobel(InputArray _src, OutputArray _dst, int ddepth, int dx, int void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType ) { + CV_INSTRUMENT_REGION() + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if (ddepth < 0) ddepth = sdepth; @@ -549,6 +557,8 @@ void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, double scale, double delta, int borderType ) { + CV_INSTRUMENT_REGION() + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if (ddepth < 0) ddepth = sdepth; @@ -733,6 +743,8 @@ namespace cv static bool ipp_Laplacian(InputArray _src, OutputArray _dst, int ddepth, int ksize, double scale, double delta, int borderType) { + CV_INSTRUMENT_REGION_IPP() + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if (ddepth < 0) ddepth = sdepth; @@ -758,7 +770,7 @@ static bool ipp_Laplacian(InputArray _src, OutputArray _dst, int ddepth, int ksi if (borderTypeIpp >= 0 && ippiFilterLaplacianGetBufferSize_##ippfavor##_C1R(roisize, masksize, &bufsize) >= 0) \ { \ Ipp8u * buffer = ippsMalloc_8u(bufsize); \ - status = ippiFilterLaplacianBorder_##ippfavor##_C1R(src.ptr(), (int)src.step, dst.ptr(), \ + status = CV_INSTRUMENT_FUN_IPP(ippiFilterLaplacianBorder_##ippfavor##_C1R, src.ptr(), (int)src.step, dst.ptr(), \ (int)dst.step, roisize, masksize, borderTypeIpp, 0, buffer); \ ippsFree(buffer); \ } \ @@ -770,18 +782,18 @@ static bool ipp_Laplacian(InputArray _src, OutputArray _dst, int ddepth, int ksi IPP_FILTER_LAPLACIAN(Ipp8u, Ipp16s, 8u16s); if (needScale && status >= 0) - status = ippiMulC_16s_C1IRSfs((Ipp16s)iscale, dst.ptr(), (int)dst.step, roisize, 0); + status = CV_INSTRUMENT_FUN_IPP(ippiMulC_16s_C1IRSfs, (Ipp16s)iscale, dst.ptr(), (int)dst.step, roisize, 0); if (needDelta && status >= 0) - status = ippiAddC_16s_C1IRSfs((Ipp16s)idelta, dst.ptr(), (int)dst.step, roisize, 0); + status = CV_INSTRUMENT_FUN_IPP(ippiAddC_16s_C1IRSfs, (Ipp16s)idelta, dst.ptr(), (int)dst.step, roisize, 0); } else if (sdepth == CV_32F && ddepth == CV_32F) { IPP_FILTER_LAPLACIAN(Ipp32f, Ipp32f, 32f); if (needScale && status >= 0) - status = ippiMulC_32f_C1IR((Ipp32f)scale, dst.ptr(), (int)dst.step, roisize); + status = CV_INSTRUMENT_FUN_IPP(ippiMulC_32f_C1IR, (Ipp32f)scale, dst.ptr(), (int)dst.step, roisize); if (needDelta && status >= 0) - status = ippiAddC_32f_C1IR((Ipp32f)delta, dst.ptr(), (int)dst.step, roisize); + status = CV_INSTRUMENT_FUN_IPP(ippiAddC_32f_C1IR, (Ipp32f)delta, dst.ptr(), (int)dst.step, roisize); } CV_SUPPRESS_DEPRECATED_END @@ -799,6 +811,8 @@ static bool ipp_Laplacian(InputArray _src, OutputArray _dst, int ddepth, int ksi void cv::Laplacian( InputArray _src, OutputArray _dst, int ddepth, int ksize, double scale, double delta, int borderType ) { + CV_INSTRUMENT_REGION() + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if (ddepth < 0) ddepth = sdepth; diff --git a/modules/imgproc/src/distransform.cpp b/modules/imgproc/src/distransform.cpp index cde6ec4eb6..070a649e63 100644 --- a/modules/imgproc/src/distransform.cpp +++ b/modules/imgproc/src/distransform.cpp @@ -693,7 +693,7 @@ static void distanceTransform_L1_8U(InputArray _src, OutputArray _dst) { IppiSize roi = { src.cols, src.rows }; Ipp32s pMetrics[2] = { 1, 2 }; //L1, 3x3 mask - if (ippiDistanceTransform_3x3_8u_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, pMetrics)>=0) + if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_3x3_8u_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, pMetrics) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; @@ -710,6 +710,8 @@ static void distanceTransform_L1_8U(InputArray _src, OutputArray _dst) void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labels, int distType, int maskSize, int labelType ) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(), labels; bool need_labels = _labels.needed(); @@ -754,7 +756,7 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe if (status>=0) { pBuffer = (Ipp8u *)ippMalloc( bufSize ); - status = ippiTrueDistanceTransform_8u32f_C1R(src.ptr(),(int)src.step, dst.ptr(), (int)dst.step, roi, pBuffer); + status = CV_INSTRUMENT_FUN_IPP(ippiTrueDistanceTransform_8u32f_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, pBuffer); ippFree( pBuffer ); if (status>=0) { @@ -789,7 +791,7 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe CV_IPP_CHECK() { IppiSize roi = { src.cols, src.rows }; - if (ippiDistanceTransform_3x3_8u32f_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, _mask)>=0) + if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_3x3_8u32f_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, _mask) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; @@ -806,7 +808,7 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe CV_IPP_CHECK() { IppiSize roi = { src.cols, src.rows }; - if (ippiDistanceTransform_5x5_8u32f_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, _mask)>=0) + if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_5x5_8u32f_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, _mask) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; @@ -848,6 +850,8 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe void cv::distanceTransform( InputArray _src, OutputArray _dst, int distanceType, int maskSize, int dstType) { + CV_INSTRUMENT_REGION() + if (distanceType == CV_DIST_L1 && dstType==CV_8U) distanceTransform_L1_8U(_src, _dst); else diff --git a/modules/imgproc/src/drawing.cpp b/modules/imgproc/src/drawing.cpp index a73a30f9dc..bd3aa903e7 100644 --- a/modules/imgproc/src/drawing.cpp +++ b/modules/imgproc/src/drawing.cpp @@ -79,6 +79,8 @@ FillConvexPoly( Mat& img, const Point* v, int npts, bool clipLine( Size img_size, Point& pt1, Point& pt2 ) { + CV_INSTRUMENT_REGION() + int64 x1, y1, x2, y2; int c1, c2; int64 right = img_size.width-1, bottom = img_size.height-1; @@ -138,6 +140,8 @@ bool clipLine( Size img_size, Point& pt1, Point& pt2 ) bool clipLine( Rect img_rect, Point& pt1, Point& pt2 ) { + CV_INSTRUMENT_REGION() + Point tl = img_rect.tl(); pt1 -= tl; pt2 -= tl; bool inside = clipLine(img_rect.size(), pt1, pt2); @@ -922,6 +926,8 @@ void ellipse2Poly( Point center, Size axes, int angle, int arc_start, int arc_end, int delta, std::vector& pts ) { + CV_INSTRUMENT_REGION() + float alpha, beta; double size_a = axes.width, size_b = axes.height; double cx = center.x, cy = center.y; @@ -1726,6 +1732,8 @@ void drawMarker(Mat& img, Point position, const Scalar& color, int markerType, i void line( InputOutputArray _img, Point pt1, Point pt2, const Scalar& color, int thickness, int line_type, int shift ) { + CV_INSTRUMENT_REGION() + Mat img = _img.getMat(); if( line_type == CV_AA && img.depth() != CV_8U ) @@ -1742,6 +1750,8 @@ void line( InputOutputArray _img, Point pt1, Point pt2, const Scalar& color, void arrowedLine(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness, int line_type, int shift, double tipLength) { + CV_INSTRUMENT_REGION() + const double tipSize = norm(pt1-pt2)*tipLength; // Factor to normalize the size of the tip depending on the length of the arrow line(img, pt1, pt2, color, thickness, line_type, shift); @@ -1761,6 +1771,8 @@ void rectangle( InputOutputArray _img, Point pt1, Point pt2, const Scalar& color, int thickness, int lineType, int shift ) { + CV_INSTRUMENT_REGION() + Mat img = _img.getMat(); if( lineType == CV_AA && img.depth() != CV_8U ) @@ -1792,6 +1804,8 @@ void rectangle( Mat& img, Rect rec, const Scalar& color, int thickness, int lineType, int shift ) { + CV_INSTRUMENT_REGION() + CV_Assert( 0 <= shift && shift <= XY_SHIFT ); if( rec.area() > 0 ) rectangle( img, rec.tl(), rec.br() - Point(1<= 0); fillConvexPoly(img, points.ptr(), points.rows*points.cols*points.channels()/2, color, lineType, shift); @@ -2261,6 +2291,8 @@ void cv::fillConvexPoly(InputOutputArray _img, InputArray _points, void cv::fillPoly(InputOutputArray _img, InputArrayOfArrays pts, const Scalar& color, int lineType, int shift, Point offset) { + CV_INSTRUMENT_REGION() + Mat img = _img.getMat(); int i, ncontours = (int)pts.total(); if( ncontours == 0 ) @@ -2285,6 +2317,8 @@ void cv::polylines(InputOutputArray _img, InputArrayOfArrays pts, bool isClosed, const Scalar& color, int thickness, int lineType, int shift ) { + CV_INSTRUMENT_REGION() + Mat img = _img.getMat(); bool manyContours = pts.kind() == _InputArray::STD_VECTOR_VECTOR || pts.kind() == _InputArray::STD_VECTOR_MAT; @@ -2347,6 +2381,8 @@ void cv::drawContours( InputOutputArray _image, InputArrayOfArrays _contours, int lineType, InputArray _hierarchy, int maxLevel, Point offset ) { + CV_INSTRUMENT_REGION() + Mat image = _image.getMat(), hierarchy = _hierarchy.getMat(); CvMat _cimage = image; diff --git a/modules/imgproc/src/emd.cpp b/modules/imgproc/src/emd.cpp index 4dddbc6f14..96eda61331 100644 --- a/modules/imgproc/src/emd.cpp +++ b/modules/imgproc/src/emd.cpp @@ -1144,6 +1144,8 @@ float cv::EMD( InputArray _signature1, InputArray _signature2, int distType, InputArray _cost, float* lowerBound, OutputArray _flow ) { + CV_INSTRUMENT_REGION() + Mat signature1 = _signature1.getMat(), signature2 = _signature2.getMat(); Mat cost = _cost.getMat(), flow; diff --git a/modules/imgproc/src/featureselect.cpp b/modules/imgproc/src/featureselect.cpp index 2f5f1631de..3f54bef61e 100644 --- a/modules/imgproc/src/featureselect.cpp +++ b/modules/imgproc/src/featureselect.cpp @@ -269,6 +269,8 @@ void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, InputArray _mask, int blockSize, bool useHarrisDetector, double harrisK ) { + CV_INSTRUMENT_REGION() + CV_Assert( qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0 ); CV_Assert( _mask.empty() || (_mask.type() == CV_8UC1 && _mask.sameSize(_image)) ); diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index e2c79a6bfd..3bd5cd0f1e 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -379,6 +379,8 @@ int FilterEngine::proceed( const uchar* src, int srcstep, int count, void FilterEngine::apply(const Mat& src, Mat& dst, const Size & wsz, const Point & ofs) { + CV_INSTRUMENT_REGION() + CV_Assert( src.type() == srcType && dst.type() == dstType ); int y = start(src, wsz, ofs); @@ -1411,6 +1413,8 @@ private: mutable int bufsz; int ippiOperator(const uchar* _src, uchar* _dst, int width, int cn) const { + CV_INSTRUMENT_REGION_IPP() + int _ksize = kernel.rows + kernel.cols - 1; if ((1 != cn && 3 != cn) || width < _ksize*8) return 0; @@ -1432,10 +1436,10 @@ private: float borderValue[] = {0.f, 0.f, 0.f}; // here is the trick. IPP needs border type and extrapolates the row. We did it already. // So we pass anchor=0 and ignore the right tail of results since they are incorrect there. - if( (cn == 1 && ippiFilterRowBorderPipeline_32f_C1R(src, step, &dst, roisz, _kx, _ksize, 0, - ippBorderRepl, borderValue[0], bufptr) < 0) || - (cn == 3 && ippiFilterRowBorderPipeline_32f_C3R(src, step, &dst, roisz, _kx, _ksize, 0, - ippBorderRepl, borderValue, bufptr) < 0)) + if( (cn == 1 && CV_INSTRUMENT_FUN_IPP(ippiFilterRowBorderPipeline_32f_C1R,(src, step, &dst, roisz, _kx, _ksize, 0, + ippBorderRepl, borderValue[0], bufptr)) < 0) || + (cn == 3 && CV_INSTRUMENT_FUN_IPP(ippiFilterRowBorderPipeline_32f_C3R,(src, step, &dst, roisz, _kx, _ksize, 0, + ippBorderRepl, borderValue, bufptr)) < 0)) { setIppErrorStatus(); return 0; @@ -4540,39 +4544,39 @@ struct ReplacementFilter : public hal::Filter2D }; #ifdef HAVE_IPP -typedef IppStatus(CV_STDCALL* ippiFilterBorder)( +typedef IppStatus(CV_STDCALL* IppiFilterBorder)( const void* pSrc, int srcStep, void* pDst, int dstStep, IppiSize dstRoiSize, IppiBorderType border, const void* borderValue, const IppiFilterBorderSpec* pSpec, Ipp8u* pBuffer); -static ippiFilterBorder getIppFunc(int stype) +static IppiFilterBorder getIppFunc(int stype) { switch (stype) { case CV_8UC1: - return reinterpret_cast(ippiFilterBorder_8u_C1R); + return reinterpret_cast(ippiFilterBorder_8u_C1R); case CV_8UC3: - return reinterpret_cast(ippiFilterBorder_8u_C3R); + return reinterpret_cast(ippiFilterBorder_8u_C3R); case CV_8UC4: - return reinterpret_cast(ippiFilterBorder_8u_C4R); + return reinterpret_cast(ippiFilterBorder_8u_C4R); case CV_16UC1: - return reinterpret_cast(ippiFilterBorder_16u_C1R); + return reinterpret_cast(ippiFilterBorder_16u_C1R); case CV_16UC3: - return reinterpret_cast(ippiFilterBorder_16u_C3R); + return reinterpret_cast(ippiFilterBorder_16u_C3R); case CV_16UC4: - return reinterpret_cast(ippiFilterBorder_16u_C4R); + return reinterpret_cast(ippiFilterBorder_16u_C4R); case CV_16SC1: - return reinterpret_cast(ippiFilterBorder_16s_C1R); + return reinterpret_cast(ippiFilterBorder_16s_C1R); case CV_16SC3: - return reinterpret_cast(ippiFilterBorder_16s_C3R); + return reinterpret_cast(ippiFilterBorder_16s_C3R); case CV_16SC4: - return reinterpret_cast(ippiFilterBorder_16s_C4R); + return reinterpret_cast(ippiFilterBorder_16s_C4R); case CV_32FC1: - return reinterpret_cast(ippiFilterBorder_32f_C1R); + return reinterpret_cast(ippiFilterBorder_32f_C1R); case CV_32FC3: - return reinterpret_cast(ippiFilterBorder_32f_C3R); + return reinterpret_cast(ippiFilterBorder_32f_C3R); case CV_32FC4: - return reinterpret_cast(ippiFilterBorder_32f_C4R); + return reinterpret_cast(ippiFilterBorder_32f_C4R); default: return 0; } @@ -4689,12 +4693,14 @@ struct IppFilter : public hal::Filter2D void apply(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int, int, int, int) { + CV_INSTRUMENT_REGION_IPP() + if (dst_data == src_data) CV_Error(Error::StsBadArg, "Inplace IPP Filter2D is not supported"); - ippiFilterBorder ippFunc = getIppFunc(src_type); + IppiFilterBorder ippiFilterBorder = getIppFunc(src_type); IppiSize dstRoiSize = { width, height }; kernel_type borderValue[4] = { 0, 0, 0, 0 }; - IppStatus status = ippFunc(src_data, (int)src_step, dst_data, (int)dst_step, dstRoiSize, ippBorderType, borderValue, spec, buffer); + IppStatus status = CV_INSTRUMENT_FUN_IPP(ippiFilterBorder, src_data, (int)src_step, dst_data, (int)dst_step, dstRoiSize, ippBorderType, borderValue, spec, buffer); if (status >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); } @@ -4988,6 +4994,8 @@ void cv::filter2D( InputArray _src, OutputArray _dst, int ddepth, InputArray _kernel, Point anchor0, double delta, int borderType ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2, ocl_filter2D(_src, _dst, ddepth, _kernel, anchor0, delta, borderType)) @@ -5015,6 +5023,8 @@ void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, InputArray _kernelX, InputArray _kernelY, Point anchor, double delta, int borderType ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && (size_t)_src.rows() > _kernelY.total() && (size_t)_src.cols() > _kernelX.total(), ocl_sepFilter2D(_src, _dst, ddepth, _kernelX, _kernelY, anchor, delta, borderType)) diff --git a/modules/imgproc/src/floodfill.cpp b/modules/imgproc/src/floodfill.cpp index 6d8491a2a6..a818539a86 100644 --- a/modules/imgproc/src/floodfill.cpp +++ b/modules/imgproc/src/floodfill.cpp @@ -459,6 +459,8 @@ int cv::floodFill( InputOutputArray _image, InputOutputArray _mask, Point seedPoint, Scalar newVal, Rect* rect, Scalar loDiff, Scalar upDiff, int flags ) { + CV_INSTRUMENT_REGION() + ConnectedComp comp; std::vector buffer; @@ -629,6 +631,8 @@ int cv::floodFill( InputOutputArray _image, Point seedPoint, Scalar newVal, Rect* rect, Scalar loDiff, Scalar upDiff, int flags ) { + CV_INSTRUMENT_REGION() + return floodFill(_image, Mat(), seedPoint, newVal, rect, loDiff, upDiff, flags); } diff --git a/modules/imgproc/src/generalized_hough.cpp b/modules/imgproc/src/generalized_hough.cpp index a261d644b8..2d0b5bf530 100644 --- a/modules/imgproc/src/generalized_hough.cpp +++ b/modules/imgproc/src/generalized_hough.cpp @@ -415,6 +415,8 @@ namespace void GeneralizedHoughBallardImpl::calcHist() { + CV_INSTRUMENT_REGION() + CV_Assert( imageEdges_.type() == CV_8UC1 ); CV_Assert( imageDx_.type() == CV_32FC1 && imageDx_.size() == imageSize_); CV_Assert( imageDy_.type() == imageDx_.type() && imageDy_.size() == imageSize_); diff --git a/modules/imgproc/src/geometry.cpp b/modules/imgproc/src/geometry.cpp index 2d95853c8a..0377ba3b6b 100644 --- a/modules/imgproc/src/geometry.cpp +++ b/modules/imgproc/src/geometry.cpp @@ -94,6 +94,8 @@ cvBoxPoints( CvBox2D box, CvPoint2D32f pt[4] ) double cv::pointPolygonTest( InputArray _contour, Point2f pt, bool measureDist ) { + CV_INSTRUMENT_REGION() + double result = 0; Mat contour = _contour.getMat(); int i, total = contour.checkVector(2), counter = 0; @@ -504,6 +506,8 @@ static int intersectConvexConvex_( const Point2f* P, int n, const Point2f* Q, in float cv::intersectConvexConvex( InputArray _p1, InputArray _p2, OutputArray _p12, bool handleNested ) { + CV_INSTRUMENT_REGION() + Mat p1 = _p1.getMat(), p2 = _p2.getMat(); CV_Assert( p1.depth() == CV_32S || p1.depth() == CV_32F ); CV_Assert( p2.depth() == CV_32S || p2.depth() == CV_32F ); diff --git a/modules/imgproc/src/grabcut.cpp b/modules/imgproc/src/grabcut.cpp index ca3a89faf0..ca9b05c787 100644 --- a/modules/imgproc/src/grabcut.cpp +++ b/modules/imgproc/src/grabcut.cpp @@ -529,6 +529,8 @@ void cv::grabCut( InputArray _img, InputOutputArray _mask, Rect rect, InputOutputArray _bgdModel, InputOutputArray _fgdModel, int iterCount, int mode ) { + CV_INSTRUMENT_REGION() + Mat img = _img.getMat(); Mat& mask = _mask.getMatRef(); Mat& bgdModel = _bgdModel.getMatRef(); diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 640f07e95f..9b3b1b19a8 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -1188,6 +1188,8 @@ public: virtual void operator() (const Range & range) const { + CV_INSTRUMENT_REGION_IPP() + Ipp32s levelNum = histSize + 1; Mat phist(hist->size(), hist->type(), Scalar::all(0)); #if IPP_VERSION_X100 >= 900 @@ -1226,7 +1228,7 @@ public: return; } - IppStatus status = ippiHistogram_8u_C1R(src->ptr(range.start), (int)src->step, ippiSize(src->cols, range.end - range.start), + IppStatus status = CV_INSTRUMENT_FUN_IPP(ippiHistogram_8u_C1R, src->ptr(range.start), (int)src->step, ippiSize(src->cols, range.end - range.start), phist.ptr(), pSpec, pBuffer); if(pSpec) ippFree(pSpec); @@ -1269,6 +1271,8 @@ static bool ipp_calchist(const Mat* images, int nimages, const int* channels, InputArray _mask, OutputArray _hist, int dims, const int* histSize, const float** ranges, bool uniform, bool accumulate ) { + CV_INSTRUMENT_REGION_IPP() + Mat mask = _mask.getMat(); CV_Assert(dims > 0 && histSize); @@ -1311,6 +1315,7 @@ void cv::calcHist( const Mat* images, int nimages, const int* channels, InputArray _mask, OutputArray _hist, int dims, const int* histSize, const float** ranges, bool uniform, bool accumulate ) { + CV_INSTRUMENT_REGION() CV_IPP_RUN(nimages == 1 && images[0].type() == CV_8UC1 && dims == 1 && channels && channels[0] == 0 && _mask.getMat().empty() && images[0].dims <= 2 && @@ -1602,6 +1607,8 @@ void cv::calcHist( const Mat* images, int nimages, const int* channels, InputArray _mask, SparseMat& hist, int dims, const int* histSize, const float** ranges, bool uniform, bool accumulate ) { + CV_INSTRUMENT_REGION() + Mat mask = _mask.getMat(); calcHist( images, nimages, channels, mask, hist, dims, histSize, ranges, uniform, accumulate, false ); @@ -1614,6 +1621,8 @@ void cv::calcHist( InputArrayOfArrays images, const std::vector& channels, const std::vector& ranges, bool accumulate ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(images.total() == 1 && channels.size() == 1 && images.channels(0) == 1 && channels[0] == 0 && images.isUMatVector() && mask.empty() && !accumulate && histSize.size() == 1 && histSize[0] == BINS && ranges.size() == 2 && @@ -1941,6 +1950,8 @@ void cv::calcBackProject( const Mat* images, int nimages, const int* channels, InputArray _hist, OutputArray _backProject, const float** ranges, double scale, bool uniform ) { + CV_INSTRUMENT_REGION() + Mat hist = _hist.getMat(); std::vector ptrs; std::vector deltas; @@ -2104,6 +2115,8 @@ void cv::calcBackProject( const Mat* images, int nimages, const int* channels, const SparseMat& hist, OutputArray _backProject, const float** ranges, double scale, bool uniform ) { + CV_INSTRUMENT_REGION() + std::vector ptrs; std::vector deltas; std::vector uniranges; @@ -2283,6 +2296,8 @@ void cv::calcBackProject( InputArrayOfArrays images, const std::vector& cha const std::vector& ranges, double scale ) { + CV_INSTRUMENT_REGION() + #ifdef HAVE_OPENCL Size histSize = hist.size(); bool _1D = histSize.height == 1 || histSize.width == 1; @@ -2335,6 +2350,8 @@ void cv::calcBackProject( InputArrayOfArrays images, const std::vector& cha double cv::compareHist( InputArray _H1, InputArray _H2, int method ) { + CV_INSTRUMENT_REGION() + Mat H1 = _H1.getMat(), H2 = _H2.getMat(); const Mat* arrays[] = {&H1, &H2, 0}; Mat planes[2]; @@ -2541,6 +2558,8 @@ double cv::compareHist( InputArray _H1, InputArray _H2, int method ) double cv::compareHist( const SparseMat& H1, const SparseMat& H2, int method ) { + CV_INSTRUMENT_REGION() + double result = 0; int i, dims = H1.dims(); @@ -3685,6 +3704,8 @@ static bool ocl_equalizeHist(InputArray _src, OutputArray _dst) void cv::equalizeHist( InputArray _src, OutputArray _dst ) { + CV_INSTRUMENT_REGION() + CV_Assert( _src.type() == CV_8UC1 ); if (_src.empty()) diff --git a/modules/imgproc/src/hough.cpp b/modules/imgproc/src/hough.cpp index d2d215489c..13c11dbee3 100644 --- a/modules/imgproc/src/hough.cpp +++ b/modules/imgproc/src/hough.cpp @@ -109,7 +109,7 @@ HoughLinesStandard( const Mat& img, float rho, float theta, lines.resize(ipp_linesMax); IppStatus ok = ippiHoughLineGetSize_8u_C1R(srcSize, delta, ipp_linesMax, &bufferSize); Ipp8u* buffer = ippsMalloc_8u(bufferSize); - if (ok >= 0) ok = ippiHoughLine_Region_8u32f_C1R(image, step, srcSize, (IppPointPolar*) &lines[0], dstRoi, ipp_linesMax, &linesCount, delta, threshold, buffer); + if (ok >= 0) {ok = CV_INSTRUMENT_FUN_IPP(ippiHoughLine_Region_8u32f_C1R,(image, step, srcSize, (IppPointPolar*) &lines[0], dstRoi, ipp_linesMax, &linesCount, delta, threshold, buffer))}; ippsFree(buffer); if (ok >= 0) { @@ -443,7 +443,7 @@ HoughLinesProbabilistic( Mat& image, Ipp8u* buffer = ippsMalloc_8u(bufferSize); pSpec = (IppiHoughProbSpec*) malloc(specSize); if (ok >= 0) ok = ippiHoughProbLineInit_8u32f_C1R(srcSize, delta, ippAlgHintNone, pSpec); - if (ok >= 0) ok = ippiHoughProbLine_8u32f_C1R(image.data, image.step, srcSize, threshold, lineLength, lineGap, (IppiPoint*) &lines[0], ipp_linesMax, &linesCount, buffer, pSpec); + if (ok >= 0) {ok = CV_INSTRUMENT_FUN_IPP(ippiHoughProbLine_8u32f_C1R,(image.data, image.step, srcSize, threshold, lineLength, lineGap, (IppiPoint*) &lines[0], ipp_linesMax, &linesCount, buffer, pSpec))}; free(pSpec); ippsFree(buffer); @@ -850,6 +850,8 @@ void cv::HoughLines( InputArray _image, OutputArray _lines, double rho, double theta, int threshold, double srn, double stn, double min_theta, double max_theta ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(srn == 0 && stn == 0 && _image.isUMat() && _lines.isUMat(), ocl_HoughLines(_image, _lines, rho, theta, threshold, min_theta, max_theta)); @@ -869,6 +871,8 @@ void cv::HoughLinesP(InputArray _image, OutputArray _lines, double rho, double theta, int threshold, double minLineLength, double maxGap ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_image.isUMat() && _lines.isUMat(), ocl_HoughLinesP(_image, _lines, rho, theta, threshold, minLineLength, maxGap)); @@ -1322,6 +1326,8 @@ void cv::HoughCircles( InputArray _image, OutputArray _circles, double param1, double param2, int minRadius, int maxRadius ) { + CV_INSTRUMENT_REGION() + Ptr storage(cvCreateMemStorage(STORAGE_SIZE)); Mat image = _image.getMat(); CvMat c_image = image; diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index d103a4ab28..08424363f4 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -69,6 +69,8 @@ namespace cv template bool IPPSetSimple(cv::Scalar value, void *dataPointer, int step, IppiSize &size, ippiSetFunc func) { + CV_INSTRUMENT_REGION_IPP() + Type values[channels]; for( int i = 0; i < channels; i++ ) values[i] = saturate_cast(value[i]); @@ -77,16 +79,18 @@ namespace cv static bool IPPSet(const cv::Scalar &value, void *dataPointer, int step, IppiSize &size, int channels, int depth) { + CV_INSTRUMENT_REGION_IPP() + if( channels == 1 ) { switch( depth ) { case CV_8U: - return ippiSet_8u_C1R(saturate_cast(value[0]), (Ipp8u *)dataPointer, step, size) >= 0; + return CV_INSTRUMENT_FUN_IPP(ippiSet_8u_C1R,(saturate_cast(value[0]), (Ipp8u *)dataPointer, step, size)) >= 0; case CV_16U: - return ippiSet_16u_C1R(saturate_cast(value[0]), (Ipp16u *)dataPointer, step, size) >= 0; + return CV_INSTRUMENT_FUN_IPP(ippiSet_16u_C1R,(saturate_cast(value[0]), (Ipp16u *)dataPointer, step, size)) >= 0; case CV_32F: - return ippiSet_32f_C1R(saturate_cast(value[0]), (Ipp32f *)dataPointer, step, size) >= 0; + return CV_INSTRUMENT_FUN_IPP(ippiSet_32f_C1R,(saturate_cast(value[0]), (Ipp32f *)dataPointer, step, size)) >= 0; } } else @@ -2712,7 +2716,7 @@ static int computeResizeAreaTab( int ssize, int dsize, int cn, double scale, Dec #define CHECK_IPP_STATUS(STATUS) if (STATUS < 0) { *ok = false; return; } #define SET_IPP_RESIZE_LINEAR_FUNC_PTR(TYPE, CN) \ - func = (ippiResizeFunc)ippiResizeLinear_##TYPE##_##CN##R; \ + ippiResize = (ippiResizeFunc)ippiResizeLinear_##TYPE##_##CN##R; \ CHECK_IPP_STATUS(ippiResizeGetSize_##TYPE(srcSize, dstSize, (IppiInterpolationType)mode, 0, &specSize, &initSize));\ specBuf.allocate(specSize);\ pSpec = (uchar*)specBuf;\ @@ -2720,7 +2724,7 @@ static int computeResizeAreaTab( int ssize, int dsize, int cn, double scale, Dec #define SET_IPP_RESIZE_LINEAR_FUNC_64_PTR(TYPE, CN) \ if (mode == (int)ippCubic) { *ok = false; return; } \ - func = (ippiResizeFunc)ippiResizeLinear_##TYPE##_##CN##R; \ + ippiResize = (ippiResizeFunc)ippiResizeLinear_##TYPE##_##CN##R; \ CHECK_IPP_STATUS(ippiResizeGetSize_##TYPE(srcSize, dstSize, (IppiInterpolationType)mode, 0, &specSize, &initSize));\ specBuf.allocate(specSize);\ pSpec = (uchar*)specBuf;\ @@ -2729,7 +2733,7 @@ static int computeResizeAreaTab( int ssize, int dsize, int cn, double scale, Dec getSrcOffsetFunc = (ippiResizeGetSrcOffset) ippiResizeGetSrcOffset_##TYPE; #define SET_IPP_RESIZE_CUBIC_FUNC_PTR(TYPE, CN) \ - func = (ippiResizeFunc)ippiResizeCubic_##TYPE##_##CN##R; \ + ippiResize = (ippiResizeFunc)ippiResizeCubic_##TYPE##_##CN##R; \ CHECK_IPP_STATUS(ippiResizeGetSize_##TYPE(srcSize, dstSize, (IppiInterpolationType)mode, 0, &specSize, &initSize));\ specBuf.allocate(specSize);\ pSpec = (uchar*)specBuf;\ @@ -2752,7 +2756,7 @@ public: IPPresizeInvoker(const Mat & _src, Mat & _dst, double _inv_scale_x, double _inv_scale_y, int _mode, bool *_ok) : ParallelLoopBody(), src(_src), dst(_dst), inv_scale_x(_inv_scale_x), inv_scale_y(_inv_scale_y), pSpec(NULL), mode(_mode), - func(NULL), getBufferSizeFunc(NULL), getSrcOffsetFunc(NULL), ok(_ok) + ippiResize(NULL), getBufferSizeFunc(NULL), getSrcOffsetFunc(NULL), ok(_ok) { *ok = true; IppiSize srcSize, dstSize; @@ -2791,6 +2795,8 @@ public: virtual void operator() (const Range& range) const { + CV_INSTRUMENT_REGION_IPP() + if (*ok == false) return; @@ -2812,7 +2818,7 @@ public: AutoBuffer buf(bufsize + 64); uchar* bufptr = alignPtr((uchar*)buf, 32); - if( func( pSrc, (int)src.step[0], pDst, (int)dst.step[0], dstOffset, dstSize, ippBorderRepl, 0, pSpec, bufptr ) < 0 ) + if( CV_INSTRUMENT_FUN_IPP(ippiResize, pSrc, (int)src.step[0], pDst, (int)dst.step[0], dstOffset, dstSize, ippBorderRepl, 0, pSpec, bufptr) < 0 ) *ok = false; else { @@ -2827,7 +2833,7 @@ private: void *pSpec; AutoBuffer specBuf; int mode; - ippiResizeFunc func; + ippiResizeFunc ippiResize; ippiResizeGetBufferSize getBufferSizeFunc; ippiResizeGetSrcOffset getSrcOffsetFunc; bool *ok; @@ -3095,6 +3101,8 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize, static bool ipp_resize_mt(Mat & src, Mat & dst, double inv_scale_x, double inv_scale_y, int interpolation) { + CV_INSTRUMENT_REGION_IPP() + int mode = -1; if (interpolation == INTER_LINEAR && src.rows >= 2 && src.cols >= 2) mode = ippLinear; @@ -3123,6 +3131,8 @@ void resize(int src_type, uchar * dst_data, size_t dst_step, int dst_width, int dst_height, double inv_scale_x, double inv_scale_y, int interpolation) { + CV_INSTRUMENT_REGION() + CV_Assert((dst_width * dst_height > 0) || (inv_scale_x > 0 && inv_scale_y > 0)); if (inv_scale_x < DBL_EPSILON || inv_scale_y < DBL_EPSILON) { @@ -3475,6 +3485,8 @@ void resize(int src_type, void cv::resize( InputArray _src, OutputArray _dst, Size dsize, double inv_scale_x, double inv_scale_y, int interpolation ) { + CV_INSTRUMENT_REGION() + Size ssize = _src.size(); CV_Assert( ssize.width > 0 && ssize.height > 0 ); @@ -4760,6 +4772,8 @@ public: virtual void operator() (const Range & range) const { + CV_INSTRUMENT_REGION_IPP() + IppiRect srcRoiRect = { 0, 0, src.cols, src.rows }; Mat dstRoi = dst.rowRange(range); IppiSize dstRoiSize = ippiSize(dstRoi.size()); @@ -4772,9 +4786,9 @@ public: return; } - if (ippFunc(src.ptr(), ippiSize(src.size()), (int)src.step, srcRoiRect, + if (CV_INSTRUMENT_FUN_PTR_CALL_IPP(ippFunc,(src.ptr(), ippiSize(src.size()), (int)src.step, srcRoiRect, map1.ptr(), (int)map1.step, map2.ptr(), (int)map2.step, - dstRoi.ptr(), (int)dstRoi.step, dstRoiSize, ippInterpolation) < 0) + dstRoi.ptr(), (int)dstRoi.step, dstRoiSize, ippInterpolation)) < 0) *ok = false; else { @@ -4798,6 +4812,8 @@ void cv::remap( InputArray _src, OutputArray _dst, InputArray _map1, InputArray _map2, int interpolation, int borderType, const Scalar& borderValue ) { + CV_INSTRUMENT_REGION() + static RemapNNFunc nn_tab[] = { remapNearest, remapNearest, remapNearest, remapNearest, @@ -4940,6 +4956,8 @@ void cv::convertMaps( InputArray _map1, InputArray _map2, OutputArray _dstmap1, OutputArray _dstmap2, int dstm1type, bool nninterpolate ) { + CV_INSTRUMENT_REGION() + Mat map1 = _map1.getMat(), map2 = _map2.getMat(), dstmap1, dstmap2; Size size = map1.size(); const Mat *m1 = &map1, *m2 = &map2; @@ -5589,6 +5607,8 @@ public: virtual void operator() (const Range& range) const { + CV_INSTRUMENT_REGION_IPP() + IppiSize srcsize = { src.cols, src.rows }; IppiRect srcroi = { 0, 0, src.cols, src.rows }; IppiRect dstroi = { 0, range.start, dst.cols, range.end - range.start }; @@ -5605,8 +5625,8 @@ public: } // Aug 2013: problem in IPP 7.1, 8.0 : sometimes function return ippStsCoeffErr - IppStatus status = func( src.ptr(), srcsize, (int)src.step[0], srcroi, dst.ptr(), - (int)dst.step[0], dstroi, coeffs, mode ); + IppStatus status = CV_INSTRUMENT_FUN_PTR_CALL_IPP(func,( src.ptr(), srcsize, (int)src.step[0], srcroi, dst.ptr(), + (int)dst.step[0], dstroi, coeffs, mode )); if( status < 0) *ok = false; else @@ -5768,6 +5788,8 @@ void cv::warpAffine( InputArray _src, OutputArray _dst, InputArray _M0, Size dsize, int flags, int borderType, const Scalar& borderValue ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), ocl_warpTransform(_src, _dst, _M0, dsize, flags, borderType, borderValue, OCL_OP_AFFINE)) @@ -6230,6 +6252,8 @@ public: virtual void operator() (const Range& range) const { + CV_INSTRUMENT_REGION_IPP() + IppiSize srcsize = {src.cols, src.rows}; IppiRect srcroi = {0, 0, src.cols, src.rows}; IppiRect dstroi = {0, range.start, dst.cols, range.end - range.start}; @@ -6246,7 +6270,7 @@ public: } } - IppStatus status = func(src.ptr(), srcsize, (int)src.step[0], srcroi, dst.ptr(), (int)dst.step[0], dstroi, coeffs, mode); + IppStatus status = CV_INSTRUMENT_FUN_PTR_CALL_IPP(func,(src.ptr(), srcsize, (int)src.step[0], srcroi, dst.ptr(), (int)dst.step[0], dstroi, coeffs, mode)); if (status != ippStsNoErr) *ok = false; else @@ -6290,6 +6314,8 @@ void warpPerspectve(int src_type, void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0, Size dsize, int flags, int borderType, const Scalar& borderValue ) { + CV_INSTRUMENT_REGION() + CV_Assert( _src.total() > 0 ); CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), @@ -6381,6 +6407,8 @@ void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0, cv::Mat cv::getRotationMatrix2D( Point2f center, double angle, double scale ) { + CV_INSTRUMENT_REGION() + angle *= CV_PI/180; double alpha = cos(angle)*scale; double beta = sin(angle)*scale; @@ -6424,6 +6452,8 @@ cv::Mat cv::getRotationMatrix2D( Point2f center, double angle, double scale ) */ cv::Mat cv::getPerspectiveTransform( const Point2f src[], const Point2f dst[] ) { + CV_INSTRUMENT_REGION() + Mat M(3, 3, CV_64F), X(8, 1, CV_64F, M.ptr()); double a[8][8], b[8]; Mat A(8, 8, CV_64F, a), B(8, 1, CV_64F, b); @@ -6778,6 +6808,8 @@ cvLogPolar( const CvArr* srcarr, CvArr* dstarr, void cv::logPolar( InputArray _src, OutputArray _dst, Point2f center, double M, int flags ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_src.isUMat() && _dst.isUMat(), ocl_logPolar(_src, _dst, center, M, flags)); Mat src_with_border; // don't scope this variable (it holds image data) @@ -6987,6 +7019,8 @@ void cvLinearPolar( const CvArr* srcarr, CvArr* dstarr, void cv::linearPolar( InputArray _src, OutputArray _dst, Point2f center, double maxRadius, int flags ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_src.isUMat() && _dst.isUMat(), ocl_linearPolar(_src, _dst, center, maxRadius, flags)); Mat src_with_border; // don't scope this variable (it holds image data) diff --git a/modules/imgproc/src/intersection.cpp b/modules/imgproc/src/intersection.cpp index dfebd260e7..5da743a0f9 100644 --- a/modules/imgproc/src/intersection.cpp +++ b/modules/imgproc/src/intersection.cpp @@ -49,6 +49,8 @@ namespace cv int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& rect2, OutputArray intersectingRegion ) { + CV_INSTRUMENT_REGION() + const float samePointEps = 0.00001f; // used to test if two points are the same Point2f vec1[4], vec2[4]; diff --git a/modules/imgproc/src/linefit.cpp b/modules/imgproc/src/linefit.cpp index dc71d888ae..c073e26cb0 100644 --- a/modules/imgproc/src/linefit.cpp +++ b/modules/imgproc/src/linefit.cpp @@ -594,6 +594,8 @@ static void fitLine3D( Point3f * points, int count, int dist, void cv::fitLine( InputArray _points, OutputArray _line, int distType, double param, double reps, double aeps ) { + CV_INSTRUMENT_REGION() + Mat points = _points.getMat(); float linebuf[6]={0.f}; diff --git a/modules/imgproc/src/lsd.cpp b/modules/imgproc/src/lsd.cpp index cda073a61e..8791f0aad8 100644 --- a/modules/imgproc/src/lsd.cpp +++ b/modules/imgproc/src/lsd.cpp @@ -412,6 +412,8 @@ LineSegmentDetectorImpl::LineSegmentDetectorImpl(int _refine, double _scale, dou void LineSegmentDetectorImpl::detect(InputArray _image, OutputArray _lines, OutputArray _width, OutputArray _prec, OutputArray _nfa) { + CV_INSTRUMENT_REGION() + Mat_ img = _image.getMat(); CV_Assert(!img.empty() && img.channels() == 1); @@ -1154,6 +1156,8 @@ inline bool LineSegmentDetectorImpl::isAligned(const int& address, const double& void LineSegmentDetectorImpl::drawSegments(InputOutputArray _image, InputArray lines) { + CV_INSTRUMENT_REGION() + CV_Assert(!_image.empty() && (_image.channels() == 1 || _image.channels() == 3)); Mat gray; @@ -1191,6 +1195,8 @@ void LineSegmentDetectorImpl::drawSegments(InputOutputArray _image, InputArray l int LineSegmentDetectorImpl::compareSegments(const Size& size, InputArray lines1, InputArray lines2, InputOutputArray _image) { + CV_INSTRUMENT_REGION() + Size sz = size; if (_image.needed() && _image.size() != size) sz = _image.size(); CV_Assert(sz.area()); diff --git a/modules/imgproc/src/matchcontours.cpp b/modules/imgproc/src/matchcontours.cpp index 1ac6c16627..1a371677bf 100644 --- a/modules/imgproc/src/matchcontours.cpp +++ b/modules/imgproc/src/matchcontours.cpp @@ -43,6 +43,8 @@ double cv::matchShapes(InputArray contour1, InputArray contour2, int method, double) { + CV_INSTRUMENT_REGION() + double ma[7], mb[7]; int i, sma, smb; double eps = 1.e-5; diff --git a/modules/imgproc/src/moments.cpp b/modules/imgproc/src/moments.cpp index fd91f59cf1..d445ed270d 100644 --- a/modules/imgproc/src/moments.cpp +++ b/modules/imgproc/src/moments.cpp @@ -566,6 +566,8 @@ static bool ocl_moments( InputArray _src, Moments& m, bool binary) cv::Moments cv::moments( InputArray _src, bool binary ) { + CV_INSTRUMENT_REGION() + const int TILE_SIZE = 32; MomentsInTileFunc func = 0; uchar nzbuf[TILE_SIZE*TILE_SIZE]; @@ -609,7 +611,7 @@ cv::Moments cv::moments( InputArray _src, bool binary ) if (ippFunc) { - if (ippFunc(mat.data, (int)mat.step, roi, moment) >= 0) + if (CV_INSTRUMENT_FUN_IPP(ippFunc,(mat.data, (int)mat.step, roi, moment)) >= 0) { IppiPoint point = { 0, 0 }; ippiGetSpatialMoment_64f(moment, 0, 0, 0, point, &m.m00); @@ -740,6 +742,8 @@ cv::Moments cv::moments( InputArray _src, bool binary ) void cv::HuMoments( const Moments& m, double hu[7] ) { + CV_INSTRUMENT_REGION() + double t0 = m.nu30 + m.nu12; double t1 = m.nu21 + m.nu03; @@ -767,6 +771,8 @@ void cv::HuMoments( const Moments& m, double hu[7] ) void cv::HuMoments( const Moments& m, OutputArray _hu ) { + CV_INSTRUMENT_REGION() + _hu.create(7, 1, CV_64F); Mat hu = _hu.getMat(); CV_Assert( hu.isContinuous() ); diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 3b799803c3..a0103b3143 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1145,10 +1145,10 @@ struct IppMorphTrait\ IppStatus morphInit(IppiSize roiSize, const Ipp8u* pMask, IppiSize maskSize, IppiMorphState* pMorphSpec, Ipp8u* pBuffer) {return ippiMorphologyBorderInit_##flavor(roiSize, pMask, maskSize, pMorphSpec, pBuffer);}\ IppStatus filterGetMinSize(IppiSize dstRoiSize, IppiSize maskSize, IppDataType dataType, int numChannels, int* pBufferSize) {return ippiFilterMinBorderGetBufferSize(dstRoiSize, maskSize, dataType, numChannels, pBufferSize);}\ IppStatus filterGetMaxSize(IppiSize dstRoiSize, IppiSize maskSize, IppDataType dataType, int numChannels, int* pBufferSize) {return ippiFilterMaxBorderGetBufferSize(dstRoiSize, maskSize, dataType, numChannels, pBufferSize);}\ - IppStatus filterMinBorder(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize dstRoiSize, IppiSize maskSize, IppiPoint, Ipp8u* pBuffer) { ipp_data_type zerodef; return ippiFilterMinBorder_##flavor(pSrc, srcStep, pDst, dstStep, dstRoiSize, maskSize, ippBorderRepl, zero, pBuffer); }\ - IppStatus filterMaxBorder(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize dstRoiSize, IppiSize maskSize, IppiPoint, Ipp8u* pBuffer) { ipp_data_type zerodef; return ippiFilterMaxBorder_##flavor(pSrc, srcStep, pDst, dstStep, dstRoiSize, maskSize, ippBorderRepl, zero, pBuffer); }\ - IppStatus morphDilate(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize roiSize, const IppiMorphState* pMorphSpec, Ipp8u* pBuffer) { ipp_data_type zerodef; return ippiDilateBorder_##flavor(pSrc, srcStep, pDst, dstStep, roiSize, ippBorderRepl, zero, pMorphSpec, pBuffer); }\ - IppStatus morphErode(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize roiSize, const IppiMorphState* pMorphSpec, Ipp8u* pBuffer) { ipp_data_type zerodef; return ippiErodeBorder_##flavor(pSrc, srcStep, pDst, dstStep, roiSize, ippBorderRepl, zero, pMorphSpec, pBuffer); }\ + IppStatus filterMinBorder(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize dstRoiSize, IppiSize maskSize, IppiPoint, Ipp8u* pBuffer) { ipp_data_type zerodef; return CV_INSTRUMENT_FUN_IPP(ippiFilterMinBorder_##flavor, pSrc, srcStep, pDst, dstStep, dstRoiSize, maskSize, ippBorderRepl, zero, pBuffer); }\ + IppStatus filterMaxBorder(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize dstRoiSize, IppiSize maskSize, IppiPoint, Ipp8u* pBuffer) { ipp_data_type zerodef; return CV_INSTRUMENT_FUN_IPP(ippiFilterMaxBorder_##flavor, pSrc, srcStep, pDst, dstStep, dstRoiSize, maskSize, ippBorderRepl, zero, pBuffer); }\ + IppStatus morphDilate(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize roiSize, const IppiMorphState* pMorphSpec, Ipp8u* pBuffer) { ipp_data_type zerodef; return CV_INSTRUMENT_FUN_IPP(ippiDilateBorder_##flavor, pSrc, srcStep, pDst, dstStep, roiSize, ippBorderRepl, zero, pMorphSpec, pBuffer); }\ + IppStatus morphErode(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize roiSize, const IppiMorphState* pMorphSpec, Ipp8u* pBuffer) { ipp_data_type zerodef; return CV_INSTRUMENT_FUN_IPP(ippiErodeBorder_##flavor, pSrc, srcStep, pDst, dstStep, roiSize, ippBorderRepl, zero, pMorphSpec, pBuffer); }\ }; #else @@ -1333,6 +1333,8 @@ struct IppMorphImpl : public IppMorphBaseImpl int roi_width, int roi_height, int roi_x, int roi_y, int roi_width2, int roi_height2, int roi_x2, int roi_y2) { + CV_INSTRUMENT_REGION_IPP() + CV_UNUSED(roi_width); CV_UNUSED(roi_height); CV_UNUSED(roi_x); CV_UNUSED(roi_y); CV_UNUSED(roi_width2); CV_UNUSED(roi_height2); CV_UNUSED(roi_x2); CV_UNUSED(roi_y2); if (src_data == dst_data) @@ -1873,6 +1875,8 @@ void cv::erode( InputArray src, OutputArray dst, InputArray kernel, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { + CV_INSTRUMENT_REGION() + morphOp( MORPH_ERODE, src, dst, kernel, anchor, iterations, borderType, borderValue ); } @@ -1881,6 +1885,8 @@ void cv::dilate( InputArray src, OutputArray dst, InputArray kernel, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { + CV_INSTRUMENT_REGION() + morphOp( MORPH_DILATE, src, dst, kernel, anchor, iterations, borderType, borderValue ); } @@ -1952,6 +1958,8 @@ void cv::morphologyEx( InputArray _src, OutputArray _dst, int op, InputArray _kernel, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { + CV_INSTRUMENT_REGION() + Mat kernel = _kernel.getMat(); if (kernel.empty()) { diff --git a/modules/imgproc/src/phasecorr.cpp b/modules/imgproc/src/phasecorr.cpp index e6416ead59..1770f7aab8 100644 --- a/modules/imgproc/src/phasecorr.cpp +++ b/modules/imgproc/src/phasecorr.cpp @@ -490,6 +490,8 @@ static Point2d weightedCentroid(InputArray _src, cv::Point peakLocation, cv::Siz cv::Point2d cv::phaseCorrelate(InputArray _src1, InputArray _src2, InputArray _window, double* response) { + CV_INSTRUMENT_REGION() + Mat src1 = _src1.getMat(); Mat src2 = _src2.getMat(); Mat window = _window.getMat(); @@ -571,6 +573,8 @@ cv::Point2d cv::phaseCorrelate(InputArray _src1, InputArray _src2, InputArray _w void cv::createHanningWindow(OutputArray _dst, cv::Size winSize, int type) { + CV_INSTRUMENT_REGION() + CV_Assert( type == CV_32FC1 || type == CV_64FC1 ); _dst.create(winSize, type); diff --git a/modules/imgproc/src/pyramids.cpp b/modules/imgproc/src/pyramids.cpp index f7ff60d532..7d1cb67b05 100644 --- a/modules/imgproc/src/pyramids.cpp +++ b/modules/imgproc/src/pyramids.cpp @@ -1187,6 +1187,8 @@ namespace cv { static bool ipp_pyrdown( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType ) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK Size dsz = _dsz.area() == 0 ? Size((_src.cols() + 1)/2, (_src.rows() + 1)/2) : _dsz; bool isolated = (borderType & BORDER_ISOLATED) != 0; @@ -1245,6 +1247,8 @@ static bool ipp_pyrdown( InputArray _src, OutputArray _dst, const Size& _dsz, in void cv::pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType ) { + CV_INSTRUMENT_REGION() + CV_Assert(borderType != BORDER_CONSTANT); CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), @@ -1292,6 +1296,8 @@ namespace cv { static bool ipp_pyrup( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType ) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK Size sz = _src.dims() <= 2 ? _src.size() : Size(); Size dsz = _dsz.area() == 0 ? Size(_src.cols()*2, _src.rows()*2) : _dsz; @@ -1348,6 +1354,8 @@ static bool ipp_pyrup( InputArray _src, OutputArray _dst, const Size& _dsz, int void cv::pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType ) { + CV_INSTRUMENT_REGION() + CV_Assert(borderType == BORDER_DEFAULT); CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), @@ -1396,6 +1404,8 @@ namespace cv { static bool ipp_buildpyramid( InputArray _src, OutputArrayOfArrays _dst, int maxlevel, int borderType ) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK Mat src = _src.getMat(); _dst.create( maxlevel + 1, 1, 0 ); @@ -1506,6 +1516,8 @@ static bool ipp_buildpyramid( InputArray _src, OutputArrayOfArrays _dst, int max void cv::buildPyramid( InputArray _src, OutputArrayOfArrays _dst, int maxlevel, int borderType ) { + CV_INSTRUMENT_REGION() + CV_Assert(borderType != BORDER_CONSTANT); if (_src.dims() <= 2 && _dst.isUMatVector()) diff --git a/modules/imgproc/src/rotcalipers.cpp b/modules/imgproc/src/rotcalipers.cpp index c80636bdc6..d19addd0d7 100644 --- a/modules/imgproc/src/rotcalipers.cpp +++ b/modules/imgproc/src/rotcalipers.cpp @@ -346,6 +346,8 @@ static void rotatingCalipers( const Point2f* points, int n, int mode, float* out cv::RotatedRect cv::minAreaRect( InputArray _points ) { + CV_INSTRUMENT_REGION() + Mat hull; Point2f out[3]; RotatedRect box; @@ -404,6 +406,8 @@ cvMinAreaRect2( const CvArr* array, CvMemStorage* /*storage*/ ) void cv::boxPoints(cv::RotatedRect box, OutputArray _pts) { + CV_INSTRUMENT_REGION() + _pts.create(4, 2, CV_32F); Mat pts = _pts.getMat(); box.points(pts.ptr()); diff --git a/modules/imgproc/src/samplers.cpp b/modules/imgproc/src/samplers.cpp index c89bd32e0b..df9a2ef1de 100644 --- a/modules/imgproc/src/samplers.cpp +++ b/modules/imgproc/src/samplers.cpp @@ -365,6 +365,8 @@ getQuadrangleSubPix_8u32f_CnR( const uchar* src, size_t src_step, Size src_size, void cv::getRectSubPix( InputArray _image, Size patchSize, Point2f center, OutputArray _patch, int patchType ) { + CV_INSTRUMENT_REGION() + Mat image = _image.getMat(); int depth = image.depth(), cn = image.channels(); int ddepth = patchType < 0 ? depth : CV_MAT_DEPTH(patchType); @@ -387,15 +389,15 @@ void cv::getRectSubPix( InputArray _image, Size patchSize, Point2f center, IppiPoint_32f icenter = {center.x, center.y}; IppiSize src_size={image.cols, image.rows}, win_size={patch.cols, patch.rows}; int srctype = image.type(); - ippiGetRectSubPixFunc ippfunc = + ippiGetRectSubPixFunc ippiCopySubpixIntersect = srctype == CV_8UC1 && ddepth == CV_8U ? (ippiGetRectSubPixFunc)ippiCopySubpixIntersect_8u_C1R : srctype == CV_8UC1 && ddepth == CV_32F ? (ippiGetRectSubPixFunc)ippiCopySubpixIntersect_8u32f_C1R : srctype == CV_32FC1 && ddepth == CV_32F ? (ippiGetRectSubPixFunc)ippiCopySubpixIntersect_32f_C1R : 0; - if( ippfunc) + if( ippiCopySubpixIntersect) { - if (ippfunc(image.ptr(), (int)image.step, src_size, patch.ptr(), - (int)patch.step, win_size, icenter, &minpt, &maxpt) >= 0 ) + if (CV_INSTRUMENT_FUN_IPP(ippiCopySubpixIntersect, image.ptr(), (int)image.step, src_size, patch.ptr(), + (int)patch.step, win_size, icenter, &minpt, &maxpt) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; diff --git a/modules/imgproc/src/segmentation.cpp b/modules/imgproc/src/segmentation.cpp index 124aecdb2e..b803770f12 100644 --- a/modules/imgproc/src/segmentation.cpp +++ b/modules/imgproc/src/segmentation.cpp @@ -87,6 +87,8 @@ allocWSNodes( std::vector& storage ) void cv::watershed( InputArray _src, InputOutputArray _markers ) { + CV_INSTRUMENT_REGION() + // Labels for pixels const int IN_QUEUE = -2; // Pixel visited const int WSHED = -1; // Pixel belongs to watershed @@ -332,6 +334,8 @@ void cv::pyrMeanShiftFiltering( InputArray _src, OutputArray _dst, double sp0, double sr, int max_level, TermCriteria termcrit ) { + CV_INSTRUMENT_REGION() + Mat src0 = _src.getMat(); if( src0.empty() ) diff --git a/modules/imgproc/src/shapedescr.cpp b/modules/imgproc/src/shapedescr.cpp index 294f4fa492..56186bb404 100644 --- a/modules/imgproc/src/shapedescr.cpp +++ b/modules/imgproc/src/shapedescr.cpp @@ -206,6 +206,8 @@ static void findMinEnclosingCircle(const PT *pts, int count, Point2f ¢er, fl // see Welzl, Emo. Smallest enclosing disks (balls and ellipsoids). Springer Berlin Heidelberg, 1991. void cv::minEnclosingCircle( InputArray _points, Point2f& _center, float& _radius ) { + CV_INSTRUMENT_REGION() + Mat points = _points.getMat(); int count = points.checkVector(2); int depth = points.depth(); @@ -275,6 +277,8 @@ void cv::minEnclosingCircle( InputArray _points, Point2f& _center, float& _radiu // calculates length of a curve (e.g. contour perimeter) double cv::arcLength( InputArray _curve, bool is_closed ) { + CV_INSTRUMENT_REGION() + Mat curve = _curve.getMat(); int count = curve.checkVector(2); int depth = curve.depth(); @@ -308,6 +312,8 @@ double cv::arcLength( InputArray _curve, bool is_closed ) // area of a whole sequence double cv::contourArea( InputArray _contour, bool oriented ) { + CV_INSTRUMENT_REGION() + Mat contour = _contour.getMat(); int npoints = contour.checkVector(2); int depth = contour.depth(); @@ -339,6 +345,8 @@ double cv::contourArea( InputArray _contour, bool oriented ) cv::RotatedRect cv::fitEllipse( InputArray _points ) { + CV_INSTRUMENT_REGION() + Mat points = _points.getMat(); int i, n = points.checkVector(2); int depth = points.depth(); @@ -668,6 +676,8 @@ static Rect maskBoundingRect( const Mat& img ) cv::Rect cv::boundingRect(InputArray array) { + CV_INSTRUMENT_REGION() + Mat m = array.getMat(); return m.depth() <= CV_8U ? maskBoundingRect(m) : pointSetBoundingRect(m); } diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 034a2c0923..8639f0d243 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -1367,6 +1367,8 @@ static bool ipp_boxfilter( InputArray _src, OutputArray _dst, int ddepth, Size ksize, Point anchor, bool normalize, int borderType ) { + CV_INSTRUMENT_REGION_IPP() + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if( ddepth < 0 ) ddepth = sdepth; @@ -1405,7 +1407,7 @@ static bool ipp_boxfilter( InputArray _src, OutputArray _dst, int ddepth, Ipp8u * buffer = ippsMalloc_8u(bufSize); \ ippType borderValue[4] = { 0, 0, 0, 0 }; \ ippBorderType = ippBorderType == BORDER_CONSTANT ? ippBorderConst : ippBorderRepl; \ - IppStatus status = ippiFilterBoxBorder_##flavor(src.ptr(), (int)src.step, dst.ptr(), \ + IppStatus status = CV_INSTRUMENT_FUN_IPP(ippiFilterBoxBorder_##flavor, src.ptr(), (int)src.step, dst.ptr(), \ (int)dst.step, roiSize, maskSize, \ (IppiBorderType)ippBorderType, borderValue, buffer); \ ippsFree(buffer); \ @@ -1459,6 +1461,8 @@ void cv::boxFilter( InputArray _src, OutputArray _dst, int ddepth, Size ksize, Point anchor, bool normalize, int borderType ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_dst.isUMat(), ocl_boxFilter(_src, _dst, ddepth, ksize, anchor, borderType, normalize)) Mat src = _src.getMat(); @@ -1507,6 +1511,8 @@ void cv::boxFilter( InputArray _src, OutputArray _dst, int ddepth, void cv::blur( InputArray src, OutputArray dst, Size ksize, Point anchor, int borderType ) { + CV_INSTRUMENT_REGION() + boxFilter( src, dst, -1, ksize, anchor, true, borderType ); } @@ -1589,6 +1595,8 @@ void cv::sqrBoxFilter( InputArray _src, OutputArray _dst, int ddepth, Size ksize, Point anchor, bool normalize, int borderType ) { + CV_INSTRUMENT_REGION() + int srcType = _src.type(), sdepth = CV_MAT_DEPTH(srcType), cn = CV_MAT_CN(srcType); Size size = _src.size(); @@ -1733,6 +1741,8 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, double sigma1, double sigma2, int borderType ) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 810 if ((borderType & BORDER_ISOLATED) == 0 && _src.isSubmatrix()) return false; @@ -1771,14 +1781,14 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, #define IPP_FILTER_GAUSS_C1(ippfavor) \ { \ Ipp##ippfavor borderValues = 0; \ - status = ippiFilterGaussianBorder_##ippfavor##_C1R(src.ptr(), (int)src.step, \ + status = CV_INSTRUMENT_FUN_IPP(ippiFilterGaussianBorder_##ippfavor##_C1R, src.ptr(), (int)src.step, \ dst.ptr(), (int)dst.step, roiSize, borderValues, spec, buffer); \ } #define IPP_FILTER_GAUSS_CN(ippfavor, ippcn) \ { \ Ipp##ippfavor borderValues[] = { 0, 0, 0 }; \ - status = ippiFilterGaussianBorder_##ippfavor##_C##ippcn##R(src.ptr(), (int)src.step, \ + status = CV_INSTRUMENT_FUN_IPP(ippiFilterGaussianBorder_##ippfavor##_C##ippcn##R, src.ptr(), (int)src.step, \ dst.ptr(), (int)dst.step, roiSize, borderValues, spec, buffer); \ } @@ -1825,6 +1835,8 @@ void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, double sigma1, double sigma2, int borderType ) { + CV_INSTRUMENT_REGION() + int type = _src.type(); Size size = _src.size(); _dst.create( size, type ); @@ -2768,6 +2780,8 @@ namespace cv { static bool ipp_medianFilter( InputArray _src0, OutputArray _dst, int ksize ) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 810 Mat src0 = _src0.getMat(); _dst.create( src0.size(), src0.type() ); @@ -2780,7 +2794,7 @@ static bool ipp_medianFilter( InputArray _src0, OutputArray _dst, int ksize ) ippDataType, CV_MAT_CN(type), &bufSize) >= 0) \ { \ Ipp8u * buffer = ippsMalloc_8u(bufSize); \ - IppStatus status = ippiFilterMedianBorder_##flavor(src.ptr(), (int)src.step, \ + IppStatus status = CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_##flavor, src.ptr(), (int)src.step, \ dst.ptr(), (int)dst.step, dstRoiSize, maskSize, \ ippBorderRepl, (ippType)0, buffer); \ ippsFree(buffer); \ @@ -2824,6 +2838,8 @@ static bool ipp_medianFilter( InputArray _src0, OutputArray _dst, int ksize ) void cv::medianBlur( InputArray _src0, OutputArray _dst, int ksize ) { + CV_INSTRUMENT_REGION() + CV_Assert( (ksize % 2 == 1) && (_src0.dims() <= 2 )); if( ksize <= 1 ) @@ -3070,6 +3086,8 @@ public: virtual void operator() (const Range& range) const { + CV_INSTRUMENT_REGION_IPP() + int d = radius * 2 + 1; IppiSize kernel = {d, d}; IppiSize roi={dst.cols, range.end - range.start}; @@ -3665,6 +3683,8 @@ void cv::bilateralFilter( InputArray _src, OutputArray _dst, int d, double sigmaColor, double sigmaSpace, int borderType ) { + CV_INSTRUMENT_REGION() + _dst.create( _src.size(), _src.type() ); CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), diff --git a/modules/imgproc/src/spatialgradient.cpp b/modules/imgproc/src/spatialgradient.cpp index 411c29947f..ecf52f9ce1 100644 --- a/modules/imgproc/src/spatialgradient.cpp +++ b/modules/imgproc/src/spatialgradient.cpp @@ -78,6 +78,7 @@ static inline void spatialGradientKernel( T& vx, T& vy, void spatialGradient( InputArray _src, OutputArray _dx, OutputArray _dy, int ksize, int borderType ) { + CV_INSTRUMENT_REGION() // Prepare InputArray src Mat src = _src.getMat(); diff --git a/modules/imgproc/src/subdivision2d.cpp b/modules/imgproc/src/subdivision2d.cpp index d849d2aa10..5917dbd51f 100644 --- a/modules/imgproc/src/subdivision2d.cpp +++ b/modules/imgproc/src/subdivision2d.cpp @@ -275,6 +275,8 @@ void Subdiv2D::deletePoint(int vidx) int Subdiv2D::locate(Point2f pt, int& _edge, int& _vertex) { + CV_INSTRUMENT_REGION() + int vertex = 0; int i, maxEdges = (int)(qedges.size() * 4); @@ -409,6 +411,8 @@ isPtInCircle3( Point2f pt, Point2f a, Point2f b, Point2f c) int Subdiv2D::insert(Point2f pt) { + CV_INSTRUMENT_REGION() + int curr_point = 0, curr_edge = 0, deleted_edge = 0; int location = locate( pt, curr_edge, curr_point ); @@ -479,12 +483,16 @@ int Subdiv2D::insert(Point2f pt) void Subdiv2D::insert(const std::vector& ptvec) { + CV_INSTRUMENT_REGION() + for( size_t i = 0; i < ptvec.size(); i++ ) insert(ptvec[i]); } void Subdiv2D::initDelaunay( Rect rect ) { + CV_INSTRUMENT_REGION() + float big_coord = 3.f * MAX( rect.width, rect.height ); float rx = (float)rect.x; float ry = (float)rect.y; @@ -644,6 +652,8 @@ isRightOf2( const Point2f& pt, const Point2f& org, const Point2f& diff ) int Subdiv2D::findNearest(Point2f pt, Point2f* nearestPt) { + CV_INSTRUMENT_REGION() + if( !validGeometry ) calcVoronoi(); diff --git a/modules/imgproc/src/sumpixels.cpp b/modules/imgproc/src/sumpixels.cpp index 348ac18ecf..d998a7ab05 100755 --- a/modules/imgproc/src/sumpixels.cpp +++ b/modules/imgproc/src/sumpixels.cpp @@ -425,6 +425,8 @@ namespace cv { static bool ipp_integral(InputArray _src, OutputArray _sum, OutputArray _sqsum, OutputArray _tilted, int sdepth, int sqdepth) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 != 900 // Disabled on ICV due invalid results int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); if( sdepth <= 0 ) @@ -452,22 +454,22 @@ static bool ipp_integral(InputArray _src, OutputArray _sum, OutputArray _sqsum, { if( _sqsum.needed() ) { - status = ippiSqrIntegral_8u32f64f_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32f*)sum.data, (int)sum.step, (Ipp64f*)sqsum.data, (int)sqsum.step, srcRoiSize, 0, 0 ); + status = CV_INSTRUMENT_FUN_IPP(ippiSqrIntegral_8u32f64f_C1R, (const Ipp8u*)src.data, (int)src.step, (Ipp32f*)sum.data, (int)sum.step, (Ipp64f*)sqsum.data, (int)sqsum.step, srcRoiSize, 0, 0); } else { - status = ippiIntegral_8u32f_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32f*)sum.data, (int)sum.step, srcRoiSize, 0 ); + status = CV_INSTRUMENT_FUN_IPP(ippiIntegral_8u32f_C1R, (const Ipp8u*)src.data, (int)src.step, (Ipp32f*)sum.data, (int)sum.step, srcRoiSize, 0); } } else if( sdepth == CV_32S ) { if( _sqsum.needed() ) { - status = ippiSqrIntegral_8u32s64f_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32s*)sum.data, (int)sum.step, (Ipp64f*)sqsum.data, (int)sqsum.step, srcRoiSize, 0, 0 ); + status = CV_INSTRUMENT_FUN_IPP(ippiSqrIntegral_8u32s64f_C1R, (const Ipp8u*)src.data, (int)src.step, (Ipp32s*)sum.data, (int)sum.step, (Ipp64f*)sqsum.data, (int)sqsum.step, srcRoiSize, 0, 0); } else { - status = ippiIntegral_8u32s_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32s*)sum.data, (int)sum.step, srcRoiSize, 0 ); + status = CV_INSTRUMENT_FUN_IPP(ippiIntegral_8u32s_C1R, (const Ipp8u*)src.data, (int)src.step, (Ipp32s*)sum.data, (int)sum.step, srcRoiSize, 0); } } if (0 <= status) @@ -486,6 +488,8 @@ static bool ipp_integral(InputArray _src, OutputArray _sum, OutputArray _sqsum, void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, OutputArray _tilted, int sdepth, int sqdepth ) { + CV_INSTRUMENT_REGION() + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); if( sdepth <= 0 ) sdepth = depth == CV_8U ? CV_32S : CV_64F; @@ -559,11 +563,15 @@ void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, Output void cv::integral( InputArray src, OutputArray sum, int sdepth ) { + CV_INSTRUMENT_REGION() + integral( src, sum, noArray(), noArray(), sdepth ); } void cv::integral( InputArray src, OutputArray sum, OutputArray sqsum, int sdepth, int sqdepth ) { + CV_INSTRUMENT_REGION() + integral( src, sum, sqsum, noArray(), sdepth, sqdepth ); } diff --git a/modules/imgproc/src/templmatch.cpp b/modules/imgproc/src/templmatch.cpp index 019c41f33b..5bae692dc7 100644 --- a/modules/imgproc/src/templmatch.cpp +++ b/modules/imgproc/src/templmatch.cpp @@ -566,6 +566,8 @@ typedef IppStatus (CV_STDCALL * ippimatchTemplate)(const void*, int, IppiSize, c static bool ipp_crossCorr(const Mat& src, const Mat& tpl, Mat& dst) { + CV_INSTRUMENT_REGION_IPP() + IppStatus status; IppiSize srcRoiSize = {src.cols,src.rows}; @@ -576,11 +578,11 @@ static bool ipp_crossCorr(const Mat& src, const Mat& tpl, Mat& dst) int depth = src.depth(); - ippimatchTemplate ippFunc = + ippimatchTemplate ippiCrossCorrNorm = depth==CV_8U ? (ippimatchTemplate)ippiCrossCorrNorm_8u32f_C1R: depth==CV_32F? (ippimatchTemplate)ippiCrossCorrNorm_32f_C1R: 0; - if (ippFunc==0) + if (ippiCrossCorrNorm==0) return false; IppEnum funCfg = (IppEnum)(ippAlgAuto | ippiNormNone | ippiROIValid); @@ -591,7 +593,7 @@ static bool ipp_crossCorr(const Mat& src, const Mat& tpl, Mat& dst) pBuffer = ippsMalloc_8u( bufSize ); - status = ippFunc(src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr(), (int)dst.step, funCfg, pBuffer); + status = CV_INSTRUMENT_FUN_IPP(ippiCrossCorrNorm, src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr(), (int)dst.step, funCfg, pBuffer); ippsFree( pBuffer ); return status >= 0; @@ -599,6 +601,8 @@ static bool ipp_crossCorr(const Mat& src, const Mat& tpl, Mat& dst) static bool ipp_sqrDistance(const Mat& src, const Mat& tpl, Mat& dst) { + CV_INSTRUMENT_REGION_IPP() + IppStatus status; IppiSize srcRoiSize = {src.cols,src.rows}; @@ -609,11 +613,11 @@ static bool ipp_sqrDistance(const Mat& src, const Mat& tpl, Mat& dst) int depth = src.depth(); - ippimatchTemplate ippFunc = + ippimatchTemplate ippiSqrDistanceNorm = depth==CV_8U ? (ippimatchTemplate)ippiSqrDistanceNorm_8u32f_C1R: depth==CV_32F? (ippimatchTemplate)ippiSqrDistanceNorm_32f_C1R: 0; - if (ippFunc==0) + if (ippiSqrDistanceNorm==0) return false; IppEnum funCfg = (IppEnum)(ippAlgAuto | ippiNormNone | ippiROIValid); @@ -624,7 +628,7 @@ static bool ipp_sqrDistance(const Mat& src, const Mat& tpl, Mat& dst) pBuffer = ippsMalloc_8u( bufSize ); - status = ippFunc(src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr(), (int)dst.step, funCfg, pBuffer); + status = CV_INSTRUMENT_FUN_IPP(ippiSqrDistanceNorm, src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr(), (int)dst.step, funCfg, pBuffer); ippsFree( pBuffer ); return status >= 0; @@ -1041,6 +1045,8 @@ namespace cv { static bool ipp_matchTemplate( Mat& img, Mat& templ, Mat& result, int method, int cn ) { + CV_INSTRUMENT_REGION_IPP() + bool useIppMT = (templ.rows < img.rows/2 && templ.cols < img.cols/2); if(cn == 1 && useIppMT) @@ -1069,6 +1075,8 @@ static bool ipp_matchTemplate( Mat& img, Mat& templ, Mat& result, int method, in void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method, InputArray _mask ) { + CV_INSTRUMENT_REGION() + if (!_mask.empty()) { cv::matchTemplateMask(_img, _templ, _result, method, _mask); diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index 1513bdafa1..e88d06a6c7 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -91,12 +91,12 @@ thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type ) switch( type ) { case THRESH_TRUNC: - if (_src.data == _dst.data && ippiThreshold_GT_8u_C1IR(_dst.ptr(), (int)dst_step, sz, thresh) >= 0) + if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_8u_C1IR, _dst.ptr(), (int)dst_step, sz, thresh) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; } - if (ippiThreshold_GT_8u_C1R(_src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh) >= 0) + if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_8u_C1R, _src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; @@ -104,12 +104,12 @@ thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type ) setIppErrorStatus(); break; case THRESH_TOZERO: - if (_src.data == _dst.data && ippiThreshold_LTVal_8u_C1IR(_dst.ptr(), (int)dst_step, sz, thresh+1, 0) >= 0) + if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_8u_C1IR, _dst.ptr(), (int)dst_step, sz, thresh+1, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; } - if (ippiThreshold_LTVal_8u_C1R(_src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh+1, 0) >= 0) + if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_8u_C1R, _src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh + 1, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; @@ -117,12 +117,12 @@ thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type ) setIppErrorStatus(); break; case THRESH_TOZERO_INV: - if (_src.data == _dst.data && ippiThreshold_GTVal_8u_C1IR(_dst.ptr(), (int)dst_step, sz, thresh, 0) >= 0) + if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_8u_C1IR, _dst.ptr(), (int)dst_step, sz, thresh, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; } - if (ippiThreshold_GTVal_8u_C1R(_src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh, 0) >= 0) + if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_8u_C1R, _src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; @@ -428,12 +428,12 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) switch( type ) { case THRESH_TRUNC: - if (_src.data == _dst.data && ippiThreshold_GT_16s_C1IR(dst, (int)dst_step*sizeof(dst[0]), sz, thresh) >= 0) + if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_16s_C1IR, dst, (int)dst_step*sizeof(dst[0]), sz, thresh) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; } - if (ippiThreshold_GT_16s_C1R(src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh) >= 0) + if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_16s_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; @@ -441,12 +441,12 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) setIppErrorStatus(); break; case THRESH_TOZERO: - if (_src.data == _dst.data && ippiThreshold_LTVal_16s_C1IR(dst, (int)dst_step*sizeof(dst[0]), sz, thresh + 1, 0) >= 0) + if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_16s_C1IR, dst, (int)dst_step*sizeof(dst[0]), sz, thresh + 1, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; } - if (ippiThreshold_LTVal_16s_C1R(src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh+1, 0) >= 0) + if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_16s_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh + 1, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; @@ -454,12 +454,12 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) setIppErrorStatus(); break; case THRESH_TOZERO_INV: - if (_src.data == _dst.data && ippiThreshold_GTVal_16s_C1IR(dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0) >= 0) + if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_16s_C1IR, dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; } - if (ippiThreshold_GTVal_16s_C1R(src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0) >= 0) + if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_16s_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0) >= 0) { CV_IMPL_ADD(CV_IMPL_IPP); return; @@ -689,7 +689,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) switch( type ) { case THRESH_TRUNC: - if (0 <= ippiThreshold_GT_32f_C1R(src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh)) + if (0 <= CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_32f_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh)) { CV_IMPL_ADD(CV_IMPL_IPP); return; @@ -697,7 +697,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) setIppErrorStatus(); break; case THRESH_TOZERO: - if (0 <= ippiThreshold_LTVal_32f_C1R(src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh+FLT_EPSILON, 0)) + if (0 <= CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_32f_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh + FLT_EPSILON, 0)) { CV_IMPL_ADD(CV_IMPL_IPP); return; @@ -705,7 +705,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) setIppErrorStatus(); break; case THRESH_TOZERO_INV: - if (0 <= ippiThreshold_GTVal_32f_C1R(src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0)) + if (0 <= CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_32f_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0)) { CV_IMPL_ADD(CV_IMPL_IPP); return; @@ -1176,11 +1176,13 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type) #ifdef HAVE_IPP static bool ipp_getThreshVal_Otsu_8u( const unsigned char* _src, int step, Size size, unsigned char &thresh) { + CV_INSTRUMENT_REGION_IPP() + #if IPP_VERSION_X100 >= 810 int ippStatus = -1; IppiSize srcSize = { size.width, size.height }; CV_SUPPRESS_DEPRECATED_START - ippStatus = ippiComputeThreshold_Otsu_8u_C1R(_src, step, srcSize, &thresh); + ippStatus = CV_INSTRUMENT_FUN_IPP(ippiComputeThreshold_Otsu_8u_C1R, _src, step, srcSize, &thresh); CV_SUPPRESS_DEPRECATED_END if(ippStatus >= 0) @@ -1464,6 +1466,8 @@ static bool ocl_threshold( InputArray _src, OutputArray _dst, double & thresh, d double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double maxval, int type ) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN_(_src.dims() <= 2 && _dst.isUMat(), ocl_threshold(_src, _dst, thresh, maxval, type), thresh) @@ -1557,6 +1561,8 @@ double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double m void cv::adaptiveThreshold( InputArray _src, OutputArray _dst, double maxValue, int method, int type, int blockSize, double delta ) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); CV_Assert( src.type() == CV_8UC1 ); CV_Assert( blockSize % 2 == 1 && blockSize > 1 ); diff --git a/modules/imgproc/src/undistort.cpp b/modules/imgproc/src/undistort.cpp index 5e6cf05de4..198b0cbf9b 100644 --- a/modules/imgproc/src/undistort.cpp +++ b/modules/imgproc/src/undistort.cpp @@ -182,6 +182,8 @@ void cv::initUndistortRectifyMap( InputArray _cameraMatrix, InputArray _distCoef void cv::undistort( InputArray _src, OutputArray _dst, InputArray _cameraMatrix, InputArray _distCoeffs, InputArray _newCameraMatrix ) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(), cameraMatrix = _cameraMatrix.getMat(); Mat distCoeffs = _distCoeffs.getMat(), newCameraMatrix = _newCameraMatrix.getMat(); diff --git a/modules/objdetect/src/cascadedetect.cpp b/modules/objdetect/src/cascadedetect.cpp index e206992574..9eef693d70 100644 --- a/modules/objdetect/src/cascadedetect.cpp +++ b/modules/objdetect/src/cascadedetect.cpp @@ -59,6 +59,8 @@ template void copyVectorToUMat(const std::vector<_Tp>& v, UMat& um void groupRectangles(std::vector& rectList, int groupThreshold, double eps, std::vector* weights, std::vector* levelWeights) { + CV_INSTRUMENT_REGION() + if( groupThreshold <= 0 || rectList.empty() ) { if( weights ) @@ -359,23 +361,31 @@ static void groupRectangles_meanshift(std::vector& rectList, double detect void groupRectangles(std::vector& rectList, int groupThreshold, double eps) { + CV_INSTRUMENT_REGION() + groupRectangles(rectList, groupThreshold, eps, 0, 0); } void groupRectangles(std::vector& rectList, std::vector& weights, int groupThreshold, double eps) { + CV_INSTRUMENT_REGION() + groupRectangles(rectList, groupThreshold, eps, &weights, 0); } //used for cascade detection algorithm for ROC-curve calculating void groupRectangles(std::vector& rectList, std::vector& rejectLevels, std::vector& levelWeights, int groupThreshold, double eps) { + CV_INSTRUMENT_REGION() + groupRectangles(rectList, groupThreshold, eps, &rejectLevels, &levelWeights); } //can be used for HOG detection algorithm only void groupRectangles_meanshift(std::vector& rectList, std::vector& foundWeights, std::vector& foundScales, double detectThreshold, Size winDetSize) { + CV_INSTRUMENT_REGION() + groupRectangles_meanshift(rectList, detectThreshold, &foundWeights, foundScales, winDetSize); } @@ -1217,6 +1227,8 @@ void CascadeClassifierImpl::detectMultiScaleNoGrouping( InputArray _image, std:: double scaleFactor, Size minObjectSize, Size maxObjectSize, bool outputRejectLevels ) { + CV_INSTRUMENT_REGION() + Size imgsz = _image.size(); Mat grayImage; @@ -1320,6 +1332,8 @@ void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector 1 && _image.depth() == CV_8U ); if( empty() ) @@ -1352,6 +1366,8 @@ void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector fakeLevels; std::vector fakeWeights; detectMultiScale( _image, objects, fakeLevels, fakeWeights, scaleFactor, @@ -1363,6 +1379,8 @@ void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector 1 && image.depth() == CV_8U ); @@ -1636,6 +1654,8 @@ void CascadeClassifier::detectMultiScale( InputArray image, Size minSize, Size maxSize ) { + CV_INSTRUMENT_REGION() + CV_Assert(!empty()); cc->detectMultiScale(image, objects, scaleFactor, minNeighbors, flags, minSize, maxSize); clipObjects(image.size(), objects, 0, 0); @@ -1648,6 +1668,8 @@ void CascadeClassifier::detectMultiScale( InputArray image, int minNeighbors, int flags, Size minSize, Size maxSize ) { + CV_INSTRUMENT_REGION() + CV_Assert(!empty()); cc->detectMultiScale(image, objects, numDetections, scaleFactor, minNeighbors, flags, minSize, maxSize); @@ -1663,6 +1685,8 @@ void CascadeClassifier::detectMultiScale( InputArray image, Size minSize, Size maxSize, bool outputRejectLevels ) { + CV_INSTRUMENT_REGION() + CV_Assert(!empty()); cc->detectMultiScale(image, objects, rejectLevels, levelWeights, scaleFactor, minNeighbors, flags, diff --git a/modules/objdetect/src/detection_based_tracker.cpp b/modules/objdetect/src/detection_based_tracker.cpp index 040784bc23..8c236c7594 100644 --- a/modules/objdetect/src/detection_based_tracker.cpp +++ b/modules/objdetect/src/detection_based_tracker.cpp @@ -618,6 +618,8 @@ cv::DetectionBasedTracker::~DetectionBasedTracker() void DetectionBasedTracker::process(const Mat& imageGray) { + CV_INSTRUMENT_REGION() + CV_Assert(imageGray.type()==CV_8UC1); if ( separateDetectionWork && !separateDetectionWork->isWorking() ) { diff --git a/modules/objdetect/src/haar.cpp b/modules/objdetect/src/haar.cpp index 66ea517c3e..51843fa488 100644 --- a/modules/objdetect/src/haar.cpp +++ b/modules/objdetect/src/haar.cpp @@ -1275,6 +1275,8 @@ CV_IMPL int cvRunHaarClassifierCascade( const CvHaarClassifierCascade* _cascade, CvPoint pt, int start_stage ) { + CV_INSTRUMENT_REGION() + double stage_sum; return cvRunHaarClassifierCascadeSum(_cascade, pt, stage_sum, start_stage); } @@ -1308,6 +1310,8 @@ public: void operator()( const Range& range ) const { + CV_INSTRUMENT_REGION() + Size winSize0 = cascade->orig_window_size; Size winSize(cvRound(winSize0.width*factor), cvRound(winSize0.height*factor)); int y1 = range.start*stripSize, y2 = std::min(range.end*stripSize, sum1.rows - 1 - winSize0.height); @@ -1322,10 +1326,10 @@ public: if(CV_IPP_CHECK_COND && cascade->hid_cascade->ipp_stages ) { IppiRect iequRect = {equRect.x, equRect.y, equRect.width, equRect.height}; - ippiRectStdDev_32f_C1R(sum1.ptr(y1), (int)sum1.step, + CV_INSTRUMENT_FUN_IPP(ippiRectStdDev_32f_C1R, sum1.ptr(y1), (int)sum1.step, sqsum1.ptr(y1), (int)sqsum1.step, norm1->ptr(y1), (int)norm1->step, - ippiSize(ssz.width, ssz.height), iequRect ); + ippiSize(ssz.width, ssz.height), iequRect); int positive = (ssz.width/ystep)*((ssz.height + ystep-1)/ystep); @@ -1344,7 +1348,7 @@ public: for( int j = 0; j < cascade->count; j++ ) { - if( ippiApplyHaarClassifier_32f_C1R( + if (CV_INSTRUMENT_FUN_IPP(ippiApplyHaarClassifier_32f_C1R, sum1.ptr(y1), (int)sum1.step, norm1->ptr(y1), (int)norm1->step, mask1->ptr(y1), (int)mask1->step, @@ -1441,6 +1445,8 @@ public: void operator()( const Range& range ) const { + CV_INSTRUMENT_REGION() + int iy, startY = range.start, endY = range.end; const int *p0 = p[0], *p1 = p[1], *p2 = p[2], *p3 = p[3]; const int *pq0 = pq[0], *pq1 = pq[1], *pq2 = pq[2], *pq3 = pq[3]; @@ -1500,6 +1506,8 @@ cvHaarDetectObjectsForROC( const CvArr* _img, double scaleFactor, int minNeighbors, int flags, CvSize minSize, CvSize maxSize, bool outputRejectLevels ) { + CV_INSTRUMENT_REGION() + const double GROUP_EPS = 0.2; CvMat stub, *img = (CvMat*)_img; cv::Ptr temp, sum, tilted, sqsum, normImg, sumcanny, imgSmall; diff --git a/modules/objdetect/src/hog.cpp b/modules/objdetect/src/hog.cpp index 1055525a82..84baed6ef8 100644 --- a/modules/objdetect/src/hog.cpp +++ b/modules/objdetect/src/hog.cpp @@ -236,6 +236,8 @@ inline float32x4_t vsetq_f32(float f0, float f1, float f2, float f3) void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle, Size paddingTL, Size paddingBR) const { + CV_INSTRUMENT_REGION() + CV_Assert( img.type() == CV_8U || img.type() == CV_8UC3 ); Size gradsize(img.cols + paddingTL.width + paddingBR.width, @@ -1582,6 +1584,8 @@ static bool ocl_compute(InputArray _img, Size win_stride, std::vector& _d void HOGDescriptor::compute(InputArray _img, std::vector& descriptors, Size winStride, Size padding, const std::vector& locations) const { + CV_INSTRUMENT_REGION() + if( winStride == Size() ) winStride = cellSize; Size cacheStride(gcd(winStride.width, blockStride.width), @@ -1647,6 +1651,8 @@ void HOGDescriptor::detect(const Mat& img, std::vector& hits, std::vector& weights, double hitThreshold, Size winStride, Size padding, const std::vector& locations) const { + CV_INSTRUMENT_REGION() + hits.clear(); weights.clear(); if( svmDetector.empty() ) @@ -1758,6 +1764,8 @@ void HOGDescriptor::detect(const Mat& img, void HOGDescriptor::detect(const Mat& img, std::vector& hits, double hitThreshold, Size winStride, Size padding, const std::vector& locations) const { + CV_INSTRUMENT_REGION() + std::vector weightsV; detect(img, hits, weightsV, hitThreshold, winStride, padding, locations); } @@ -2040,6 +2048,8 @@ void HOGDescriptor::detectMultiScale( double hitThreshold, Size winStride, Size padding, double scale0, double finalThreshold, bool useMeanshiftGrouping) const { + CV_INSTRUMENT_REGION() + double scale = 1.; int levels = 0; @@ -2093,6 +2103,8 @@ void HOGDescriptor::detectMultiScale(InputArray img, std::vector& foundLoc double hitThreshold, Size winStride, Size padding, double scale0, double finalThreshold, bool useMeanshiftGrouping) const { + CV_INSTRUMENT_REGION() + std::vector foundWeights; detectMultiScale(img, foundLocations, foundWeights, hitThreshold, winStride, padding, scale0, finalThreshold, useMeanshiftGrouping); @@ -3489,6 +3501,8 @@ public: void operator()( const Range& range ) const { + CV_INSTRUMENT_REGION() + int i, i1 = range.start, i2 = range.end; Size maxSz(cvCeil(img.cols/(*locations)[0].scale), cvCeil(img.rows/(*locations)[0].scale)); @@ -3531,6 +3545,8 @@ void HOGDescriptor::detectROI(const cv::Mat& img, const std::vector & CV_OUT std::vector& foundLocations, CV_OUT std::vector& confidences, double hitThreshold, cv::Size winStride, cv::Size padding) const { + CV_INSTRUMENT_REGION() + foundLocations.clear(); confidences.clear(); @@ -3641,6 +3657,8 @@ void HOGDescriptor::detectMultiScaleROI(const cv::Mat& img, CV_OUT std::vector& foundLocations, std::vector& locations, double hitThreshold, int groupThreshold) const { + CV_INSTRUMENT_REGION() + std::vector allCandidates; Mutex mtx; @@ -3747,6 +3765,8 @@ void HOGDescriptor::readALTModel(String modelfile) void HOGDescriptor::groupRectangles(std::vector& rectList, std::vector& weights, int groupThreshold, double eps) const { + CV_INSTRUMENT_REGION() + if( groupThreshold <= 0 || rectList.empty() ) { return; diff --git a/modules/photo/src/align.cpp b/modules/photo/src/align.cpp index 4fda881c29..02087117e1 100644 --- a/modules/photo/src/align.cpp +++ b/modules/photo/src/align.cpp @@ -61,11 +61,15 @@ public: void process(InputArrayOfArrays src, std::vector& dst, InputArray, InputArray) { + CV_INSTRUMENT_REGION() + process(src, dst); } void process(InputArrayOfArrays _src, std::vector& dst) { + CV_INSTRUMENT_REGION() + std::vector src; _src.getMatVector(src); @@ -114,6 +118,8 @@ public: Point calculateShift(InputArray _img0, InputArray _img1) { + CV_INSTRUMENT_REGION() + Mat img0 = _img0.getMat(); Mat img1 = _img1.getMat(); CV_Assert(img0.channels() == 1 && img0.type() == img1.type()); @@ -160,6 +166,8 @@ public: void shiftMat(InputArray _src, OutputArray _dst, const Point shift) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); _dst.create(src.size(), src.type()); Mat dst = _dst.getMat(); @@ -203,6 +211,8 @@ public: void computeBitmaps(InputArray _img, OutputArray _tb, OutputArray _eb) { + CV_INSTRUMENT_REGION() + Mat img = _img.getMat(); _tb.create(img.size(), CV_8U); _eb.create(img.size(), CV_8U); diff --git a/modules/photo/src/calibrate.cpp b/modules/photo/src/calibrate.cpp index f945ef1b5b..dd30005f6f 100644 --- a/modules/photo/src/calibrate.cpp +++ b/modules/photo/src/calibrate.cpp @@ -63,6 +63,8 @@ public: void process(InputArrayOfArrays src, OutputArray dst, InputArray _times) { + CV_INSTRUMENT_REGION() + std::vector images; src.getMatVector(images); Mat times = _times.getMat(); @@ -184,6 +186,8 @@ public: void process(InputArrayOfArrays src, OutputArray dst, InputArray _times) { + CV_INSTRUMENT_REGION() + std::vector images; src.getMatVector(images); Mat times = _times.getMat(); diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 55ea32189e..8c6caedbdf 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -52,6 +52,8 @@ using namespace cv; void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) { + CV_INSTRUMENT_REGION() + Mat I = _src.getMat(); _dst.create(I.size(), CV_8UC1); Mat dst = _dst.getMat(); diff --git a/modules/photo/src/denoising.cpp b/modules/photo/src/denoising.cpp index 93d4b4ebbe..ebf345c827 100644 --- a/modules/photo/src/denoising.cpp +++ b/modules/photo/src/denoising.cpp @@ -104,6 +104,8 @@ static void fastNlMeansDenoising_( const Mat& src, Mat& dst, const std::vector(1, h), templateWindowSize, searchWindowSize); } @@ -111,6 +113,8 @@ void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, float h, void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, const std::vector& h, int templateWindowSize, int searchWindowSize, int normType) { + CV_INSTRUMENT_REGION() + int hn = (int)h.size(), type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); CV_Assert(hn == 1 || hn == cn); @@ -169,6 +173,8 @@ void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst, float h, float hForColorComponents, int templateWindowSize, int searchWindowSize) { + CV_INSTRUMENT_REGION() + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); Size src_size = _src.size(); if (type != CV_8UC3 && type != CV_8UC4) @@ -308,6 +314,8 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _ds int imgToDenoiseIndex, int temporalWindowSize, float h, int templateWindowSize, int searchWindowSize) { + CV_INSTRUMENT_REGION() + fastNlMeansDenoisingMulti(_srcImgs, _dst, imgToDenoiseIndex, temporalWindowSize, std::vector(1, h), templateWindowSize, searchWindowSize); } @@ -317,6 +325,8 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _ds const std::vector& h, int templateWindowSize, int searchWindowSize, int normType) { + CV_INSTRUMENT_REGION() + std::vector srcImgs; _srcImgs.getMatVector(srcImgs); @@ -378,6 +388,8 @@ void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, OutputAr float h, float hForColorComponents, int templateWindowSize, int searchWindowSize) { + CV_INSTRUMENT_REGION() + std::vector srcImgs; _srcImgs.getMatVector(srcImgs); diff --git a/modules/photo/src/inpaint.cpp b/modules/photo/src/inpaint.cpp index f91db5f545..0b96f1c057 100644 --- a/modules/photo/src/inpaint.cpp +++ b/modules/photo/src/inpaint.cpp @@ -810,6 +810,8 @@ cvInpaint( const CvArr* _input_img, const CvArr* _inpaint_mask, CvArr* _output_i void cv::inpaint( InputArray _src, InputArray _mask, OutputArray _dst, double inpaintRange, int flags ) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(), mask = _mask.getMat(); _dst.create( src.size(), src.type() ); CvMat c_src = src, c_mask = mask, c_dst = _dst.getMat(); diff --git a/modules/photo/src/merge.cpp b/modules/photo/src/merge.cpp index 9772212d7b..3e59180904 100644 --- a/modules/photo/src/merge.cpp +++ b/modules/photo/src/merge.cpp @@ -58,6 +58,8 @@ public: void process(InputArrayOfArrays src, OutputArray dst, InputArray _times, InputArray input_response) { + CV_INSTRUMENT_REGION() + std::vector images; src.getMatVector(images); Mat times = _times.getMat(); @@ -122,6 +124,8 @@ public: void process(InputArrayOfArrays src, OutputArray dst, InputArray times) { + CV_INSTRUMENT_REGION() + process(src, dst, times, Mat()); } @@ -148,11 +152,15 @@ public: void process(InputArrayOfArrays src, OutputArrayOfArrays dst, InputArray, InputArray) { + CV_INSTRUMENT_REGION() + process(src, dst); } void process(InputArrayOfArrays src, OutputArray dst) { + CV_INSTRUMENT_REGION() + std::vector images; src.getMatVector(images); checkImageDimensions(images); @@ -302,6 +310,8 @@ public: void process(InputArrayOfArrays src, OutputArray dst, InputArray _times, InputArray input_response) { + CV_INSTRUMENT_REGION() + std::vector images; src.getMatVector(images); Mat times = _times.getMat(); @@ -339,6 +349,8 @@ public: void process(InputArrayOfArrays src, OutputArray dst, InputArray times) { + CV_INSTRUMENT_REGION() + process(src, dst, times, Mat()); } diff --git a/modules/photo/src/npr.cpp b/modules/photo/src/npr.cpp index 761f3c73cb..e800ce9a9a 100644 --- a/modules/photo/src/npr.cpp +++ b/modules/photo/src/npr.cpp @@ -51,6 +51,8 @@ using namespace cv; void cv::edgePreservingFilter(InputArray _src, OutputArray _dst, int flags, float sigma_s, float sigma_r) { + CV_INSTRUMENT_REGION() + Mat I = _src.getMat(); _dst.create(I.size(), CV_8UC3); Mat dst = _dst.getMat(); @@ -73,6 +75,8 @@ void cv::edgePreservingFilter(InputArray _src, OutputArray _dst, int flags, floa void cv::detailEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) { + CV_INSTRUMENT_REGION() + Mat I = _src.getMat(); _dst.create(I.size(), CV_8UC3); Mat dst = _dst.getMat(); @@ -118,6 +122,8 @@ void cv::detailEnhance(InputArray _src, OutputArray _dst, float sigma_s, float s void cv::pencilSketch(InputArray _src, OutputArray _dst1, OutputArray _dst2, float sigma_s, float sigma_r, float shade_factor) { + CV_INSTRUMENT_REGION() + Mat I = _src.getMat(); _dst1.create(I.size(), CV_8UC1); Mat dst1 = _dst1.getMat(); @@ -142,6 +148,8 @@ void cv::pencilSketch(InputArray _src, OutputArray _dst1, OutputArray _dst2, flo void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) { + CV_INSTRUMENT_REGION() + Mat I = _src.getMat(); _dst.create(I.size(), CV_8UC3); Mat dst = _dst.getMat(); diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp index 2564145e58..ed02f8cf92 100644 --- a/modules/photo/src/seamless_cloning.cpp +++ b/modules/photo/src/seamless_cloning.cpp @@ -49,6 +49,8 @@ using namespace cv; void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags) { + CV_INSTRUMENT_REGION() + const Mat src = _src.getMat(); const Mat dest = _dst.getMat(); const Mat mask = _mask.getMat(); @@ -116,6 +118,8 @@ void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float r, float g, float b) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); Mat mask = _mask.getMat(); _dst.create(src.size(), src.type()); @@ -142,6 +146,8 @@ void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float a, float b) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); Mat mask = _mask.getMat(); @@ -169,6 +175,8 @@ void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst, float low_threshold, float high_threshold, int kernel_size) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); Mat mask = _mask.getMat(); diff --git a/modules/photo/src/seamless_cloning_impl.cpp b/modules/photo/src/seamless_cloning_impl.cpp index fe2751d143..6073a9bc4c 100644 --- a/modules/photo/src/seamless_cloning_impl.cpp +++ b/modules/photo/src/seamless_cloning_impl.cpp @@ -420,6 +420,8 @@ void Cloning::localColorChange(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float void Cloning::illuminationChange(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alpha, float beta) { + CV_INSTRUMENT_REGION() + computeDerivatives(I,mask,wmask); arrayProduct(patchGradientX,binaryMaskFloat, patchGradientX); diff --git a/modules/photo/src/tonemap.cpp b/modules/photo/src/tonemap.cpp index a3a71fe50c..acfca04c9b 100644 --- a/modules/photo/src/tonemap.cpp +++ b/modules/photo/src/tonemap.cpp @@ -62,6 +62,8 @@ public: void process(InputArray _src, OutputArray _dst) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); CV_Assert(!src.empty()); _dst.create(src.size(), CV_32FC3); @@ -118,6 +120,8 @@ public: void process(InputArray _src, OutputArray _dst) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); CV_Assert(!src.empty()); _dst.create(src.size(), CV_32FC3); @@ -203,6 +207,8 @@ public: void process(InputArray _src, OutputArray _dst) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); CV_Assert(!src.empty()); _dst.create(src.size(), CV_32FC3); @@ -288,6 +294,8 @@ public: void process(InputArray _src, OutputArray _dst) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); CV_Assert(!src.empty()); _dst.create(src.size(), CV_32FC3); @@ -383,6 +391,8 @@ public: void process(InputArray _src, OutputArray _dst) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); CV_Assert(!src.empty()); _dst.create(src.size(), CV_32FC3); diff --git a/modules/shape/src/aff_trans.cpp b/modules/shape/src/aff_trans.cpp index 26644eb3a2..bbcd8abfa7 100644 --- a/modules/shape/src/aff_trans.cpp +++ b/modules/shape/src/aff_trans.cpp @@ -102,6 +102,8 @@ protected: void AffineTransformerImpl::warpImage(InputArray transformingImage, OutputArray output, int flags, int borderMode, const Scalar& borderValue) const { + CV_INSTRUMENT_REGION() + CV_Assert(!affineMat.empty()); warpAffine(transformingImage, output, affineMat, transformingImage.getMat().size(), flags, borderMode, borderValue); } @@ -183,6 +185,8 @@ static Mat _localAffineEstimate(const std::vector& shape1, const std::v void AffineTransformerImpl::estimateTransformation(InputArray _pts1, InputArray _pts2, std::vector& _matches) { + CV_INSTRUMENT_REGION() + Mat pts1 = _pts1.getMat(); Mat pts2 = _pts2.getMat(); CV_Assert((pts1.channels()==2) && (pts1.cols>0) && (pts2.channels()==2) && (pts2.cols>0)); @@ -228,6 +232,8 @@ void AffineTransformerImpl::estimateTransformation(InputArray _pts1, InputArray float AffineTransformerImpl::applyTransformation(InputArray inPts, OutputArray outPts) { + CV_INSTRUMENT_REGION() + Mat pts1 = inPts.getMat(); CV_Assert((pts1.channels()==2) && (pts1.cols>0)); diff --git a/modules/shape/src/emdL1.cpp b/modules/shape/src/emdL1.cpp index 75f1b13ad5..7baa97f0b9 100644 --- a/modules/shape/src/emdL1.cpp +++ b/modules/shape/src/emdL1.cpp @@ -787,6 +787,8 @@ float EmdL1::compuTotalFlow() float cv::EMDL1(InputArray _signature1, InputArray _signature2) { + CV_INSTRUMENT_REGION() + Mat signature1 = _signature1.getMat(), signature2 = _signature2.getMat(); EmdL1 emdl1; return emdl1.getEMDL1(signature1, signature2); diff --git a/modules/shape/src/haus_dis.cpp b/modules/shape/src/haus_dis.cpp index dd67a29982..6f372c416d 100644 --- a/modules/shape/src/haus_dis.cpp +++ b/modules/shape/src/haus_dis.cpp @@ -129,6 +129,8 @@ static float _apply(const Mat &set1, const Mat &set2, int distType, double propR float HausdorffDistanceExtractorImpl::computeDistance(InputArray contour1, InputArray contour2) { + CV_INSTRUMENT_REGION() + Mat set1=contour1.getMat(), set2=contour2.getMat(); if (set1.type() != CV_32F) set1.convertTo(set1, CV_32F); diff --git a/modules/shape/src/hist_cost.cpp b/modules/shape/src/hist_cost.cpp index 7df3c4e589..db1d42e562 100644 --- a/modules/shape/src/hist_cost.cpp +++ b/modules/shape/src/hist_cost.cpp @@ -125,6 +125,8 @@ protected: void NormHistogramCostExtractorImpl::buildCostMatrix(InputArray _descriptors1, InputArray _descriptors2, OutputArray _costMatrix) { + CV_INSTRUMENT_REGION() + // size of the costMatrix with dummies // Mat descriptors1=_descriptors1.getMat(); Mat descriptors2=_descriptors2.getMat(); @@ -251,6 +253,8 @@ protected: void EMDHistogramCostExtractorImpl::buildCostMatrix(InputArray _descriptors1, InputArray _descriptors2, OutputArray _costMatrix) { + CV_INSTRUMENT_REGION() + // size of the costMatrix with dummies // Mat descriptors1=_descriptors1.getMat(); Mat descriptors2=_descriptors2.getMat(); @@ -373,6 +377,8 @@ protected: void ChiHistogramCostExtractorImpl::buildCostMatrix(InputArray _descriptors1, InputArray _descriptors2, OutputArray _costMatrix) { + CV_INSTRUMENT_REGION() + // size of the costMatrix with dummies // Mat descriptors1=_descriptors1.getMat(); Mat descriptors2=_descriptors2.getMat(); @@ -490,6 +496,8 @@ protected: void EMDL1HistogramCostExtractorImpl::buildCostMatrix(InputArray _descriptors1, InputArray _descriptors2, OutputArray _costMatrix) { + CV_INSTRUMENT_REGION() + // size of the costMatrix with dummies // Mat descriptors1=_descriptors1.getMat(); Mat descriptors2=_descriptors2.getMat(); diff --git a/modules/shape/src/sc_dis.cpp b/modules/shape/src/sc_dis.cpp index e55247580b..89c6d91255 100644 --- a/modules/shape/src/sc_dis.cpp +++ b/modules/shape/src/sc_dis.cpp @@ -186,6 +186,8 @@ protected: float ShapeContextDistanceExtractorImpl::computeDistance(InputArray contour1, InputArray contour2) { + CV_INSTRUMENT_REGION() + // Checking // Mat sset1=contour1.getMat(), sset2=contour2.getMat(), set1, set2; if (set1.type() != CV_32F) @@ -492,6 +494,8 @@ void SCDMatcher::matchDescriptors(cv::Mat &descriptors1, cv::Mat &descriptors2, void SCDMatcher::buildCostMatrix(const cv::Mat &descriptors1, const cv::Mat &descriptors2, cv::Mat &costMatrix, cv::Ptr &comparer) const { + CV_INSTRUMENT_REGION() + comparer->buildCostMatrix(descriptors1, descriptors2, costMatrix); } diff --git a/modules/shape/src/tps_trans.cpp b/modules/shape/src/tps_trans.cpp index acff256b74..06cc6d7502 100644 --- a/modules/shape/src/tps_trans.cpp +++ b/modules/shape/src/tps_trans.cpp @@ -146,6 +146,8 @@ static Point2f _applyTransformation(const Mat &shapeRef, const Point2f point, co void ThinPlateSplineShapeTransformerImpl::warpImage(InputArray transformingImage, OutputArray output, int flags, int borderMode, const Scalar& borderValue) const { + CV_INSTRUMENT_REGION() + CV_Assert(tpsComputed==true); Mat theinput = transformingImage.getMat(); @@ -166,6 +168,8 @@ void ThinPlateSplineShapeTransformerImpl::warpImage(InputArray transformingImage float ThinPlateSplineShapeTransformerImpl::applyTransformation(InputArray inPts, OutputArray outPts) { + CV_INSTRUMENT_REGION() + CV_Assert(tpsComputed); Mat pts1 = inPts.getMat(); CV_Assert((pts1.channels()==2) && (pts1.cols>0)); @@ -189,6 +193,8 @@ float ThinPlateSplineShapeTransformerImpl::applyTransformation(InputArray inPts, void ThinPlateSplineShapeTransformerImpl::estimateTransformation(InputArray _pts1, InputArray _pts2, std::vector& _matches ) { + CV_INSTRUMENT_REGION() + Mat pts1 = _pts1.getMat(); Mat pts2 = _pts2.getMat(); CV_Assert((pts1.channels()==2) && (pts1.cols>0) && (pts2.channels()==2) && (pts2.cols>0)); diff --git a/modules/stitching/src/exposure_compensate.cpp b/modules/stitching/src/exposure_compensate.cpp index 1f04fff9f7..6f2562b204 100644 --- a/modules/stitching/src/exposure_compensate.cpp +++ b/modules/stitching/src/exposure_compensate.cpp @@ -147,6 +147,8 @@ void GainCompensator::feed(const std::vector &corners, const std::vector< void GainCompensator::apply(int index, Point /*corner*/, InputOutputArray image, InputArray /*mask*/) { + CV_INSTRUMENT_REGION() + multiply(image, gains_(index, 0), image); } @@ -225,6 +227,8 @@ void BlocksGainCompensator::feed(const std::vector &corners, const std::v void BlocksGainCompensator::apply(int index, Point /*corner*/, InputOutputArray _image, InputArray /*mask*/) { + CV_INSTRUMENT_REGION() + CV_Assert(_image.type() == CV_8UC3); UMat u_gain_map; diff --git a/modules/stitching/src/matchers.cpp b/modules/stitching/src/matchers.cpp index 40988b9888..3cf79822f0 100644 --- a/modules/stitching/src/matchers.cpp +++ b/modules/stitching/src/matchers.cpp @@ -144,6 +144,8 @@ private: void CpuMatcher::match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo& matches_info) { + CV_INSTRUMENT_REGION() + CV_Assert(features1.descriptors.type() == features2.descriptors.type()); CV_Assert(features2.descriptors.depth() == CV_8U || features2.descriptors.depth() == CV_32F); @@ -212,6 +214,8 @@ void CpuMatcher::match(const ImageFeatures &features1, const ImageFeatures &feat #ifdef HAVE_OPENCV_CUDAFEATURES2D void GpuMatcher::match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo& matches_info) { + CV_INSTRUMENT_REGION() + matches_info.matches.clear(); ensureSizeIsEnough(features1.descriptors.size(), features1.descriptors.type(), descriptors1_); @@ -581,6 +585,8 @@ BestOf2NearestMatcher::BestOf2NearestMatcher(bool try_use_gpu, float match_conf, void BestOf2NearestMatcher::match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo &matches_info) { + CV_INSTRUMENT_REGION() + (*impl_)(features1, features2, matches_info); // Check if it makes sense to find homography diff --git a/modules/stitching/src/seam_finders.cpp b/modules/stitching/src/seam_finders.cpp index 4018127774..90bf599937 100644 --- a/modules/stitching/src/seam_finders.cpp +++ b/modules/stitching/src/seam_finders.cpp @@ -203,6 +203,8 @@ void DpSeamFinder::process( const Mat &image1, const Mat &image2, Point tl1, Point tl2, Mat &mask1, Mat &mask2) { + CV_INSTRUMENT_REGION() + CV_Assert(image1.size() == mask1.size()); CV_Assert(image2.size() == mask2.size()); diff --git a/modules/stitching/src/stitcher.cpp b/modules/stitching/src/stitcher.cpp index 7226ac7479..3760c75a63 100644 --- a/modules/stitching/src/stitcher.cpp +++ b/modules/stitching/src/stitcher.cpp @@ -93,12 +93,16 @@ Stitcher Stitcher::createDefault(bool try_use_gpu) Stitcher::Status Stitcher::estimateTransform(InputArrayOfArrays images) { + CV_INSTRUMENT_REGION() + return estimateTransform(images, std::vector >()); } Stitcher::Status Stitcher::estimateTransform(InputArrayOfArrays images, const std::vector > &rois) { + CV_INSTRUMENT_REGION() + images.getUMatVector(imgs_); rois_ = rois; @@ -117,12 +121,16 @@ Stitcher::Status Stitcher::estimateTransform(InputArrayOfArrays images, const st Stitcher::Status Stitcher::composePanorama(OutputArray pano) { + CV_INSTRUMENT_REGION() + return composePanorama(std::vector(), pano); } Stitcher::Status Stitcher::composePanorama(InputArrayOfArrays images, OutputArray pano) { + CV_INSTRUMENT_REGION() + LOGLN("Warping images (auxiliary)... "); std::vector imgs; @@ -365,6 +373,8 @@ Stitcher::Status Stitcher::composePanorama(InputArrayOfArrays images, OutputArra Stitcher::Status Stitcher::stitch(InputArrayOfArrays images, OutputArray pano) { + CV_INSTRUMENT_REGION() + Status status = estimateTransform(images); if (status != OK) return status; @@ -374,6 +384,8 @@ Stitcher::Status Stitcher::stitch(InputArrayOfArrays images, OutputArray pano) Stitcher::Status Stitcher::stitch(InputArrayOfArrays images, const std::vector > &rois, OutputArray pano) { + CV_INSTRUMENT_REGION() + Status status = estimateTransform(images, rois); if (status != OK) return status; @@ -539,6 +551,8 @@ Stitcher::Status Stitcher::estimateCameraParams() Ptr createStitcher(bool try_use_gpu) { + CV_INSTRUMENT_REGION() + Ptr stitcher = makePtr(); stitcher->setRegistrationResol(0.6); stitcher->setSeamEstimationResol(0.1); diff --git a/modules/stitching/src/timelapsers.cpp b/modules/stitching/src/timelapsers.cpp index bc1d62e1a8..b42e79ae1a 100644 --- a/modules/stitching/src/timelapsers.cpp +++ b/modules/stitching/src/timelapsers.cpp @@ -65,6 +65,8 @@ void Timelapser::initialize(const std::vector &corners, const std::vector void Timelapser::process(InputArray _img, InputArray /*_mask*/, Point tl) { + CV_INSTRUMENT_REGION() + dst_.setTo(Scalar::all(0)); Mat img = _img.getMat(); diff --git a/modules/superres/src/btv_l1.cpp b/modules/superres/src/btv_l1.cpp index d47453f0d0..9c863411e8 100644 --- a/modules/superres/src/btv_l1.cpp +++ b/modules/superres/src/btv_l1.cpp @@ -658,6 +658,8 @@ namespace void BTVL1_Base::process(InputArrayOfArrays _src, OutputArray _dst, InputArrayOfArrays _forwardMotions, InputArrayOfArrays _backwardMotions, int baseIdx) { + CV_INSTRUMENT_REGION() + CV_Assert( scale_ > 1 ); CV_Assert( iterations_ > 0 ); CV_Assert( tau_ > 0.0 ); @@ -954,6 +956,8 @@ namespace void BTVL1::processImpl(Ptr& frameSource, OutputArray _output) { + CV_INSTRUMENT_REGION() + if (outPos_ >= storePos_) { _output.release(); @@ -1003,6 +1007,8 @@ namespace void BTVL1::readNextFrame(Ptr& frameSource) { + CV_INSTRUMENT_REGION() + frameSource->nextFrame(curFrame_); if (curFrame_.empty()) return; @@ -1065,6 +1071,8 @@ namespace void BTVL1::processFrame(int idx) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(isUmat_, ocl_processFrame(idx)) diff --git a/modules/superres/src/input_array_utility.cpp b/modules/superres/src/input_array_utility.cpp index a823e43cda..b3ea4bb914 100644 --- a/modules/superres/src/input_array_utility.cpp +++ b/modules/superres/src/input_array_utility.cpp @@ -235,6 +235,8 @@ namespace Mat cv::superres::convertToType(const Mat& src, int type, Mat& buf0, Mat& buf1) { + CV_INSTRUMENT_REGION() + if (src.type() == type) return src; @@ -260,6 +262,8 @@ Mat cv::superres::convertToType(const Mat& src, int type, Mat& buf0, Mat& buf1) UMat cv::superres::convertToType(const UMat& src, int type, UMat& buf0, UMat& buf1) { + CV_INSTRUMENT_REGION() + if (src.type() == type) return src; diff --git a/modules/superres/src/optical_flow.cpp b/modules/superres/src/optical_flow.cpp index 25a10af3f8..b5d1407eee 100644 --- a/modules/superres/src/optical_flow.cpp +++ b/modules/superres/src/optical_flow.cpp @@ -119,6 +119,8 @@ namespace void CpuOpticalFlow::calc(InputArray _frame0, InputArray _frame1, OutputArray _flow1, OutputArray _flow2) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_flow1.isUMat() && (_flow2.isUMat() || !_flow2.needed()), ocl_calc(_frame0, _frame1, _flow1, _flow2)) @@ -214,6 +216,8 @@ namespace void Farneback::calc(InputArray frame0, InputArray frame1, OutputArray flow1, OutputArray flow2) { + CV_INSTRUMENT_REGION() + CpuOpticalFlow::calc(frame0, frame1, flow1, flow2); } @@ -358,6 +362,8 @@ namespace void DualTVL1::calc(InputArray frame0, InputArray frame1, OutputArray flow1, OutputArray flow2) { + CV_INSTRUMENT_REGION() + CpuOpticalFlow::calc(frame0, frame1, flow1, flow2); } @@ -434,6 +440,8 @@ namespace void GpuOpticalFlow::calc(InputArray _frame0, InputArray _frame1, OutputArray _flow1, OutputArray _flow2) { + CV_INSTRUMENT_REGION() + GpuMat frame0 = arrGetGpuMat(_frame0, buf_[0]); GpuMat frame1 = arrGetGpuMat(_frame1, buf_[1]); diff --git a/modules/superres/src/super_resolution.cpp b/modules/superres/src/super_resolution.cpp index 3eae5a6fd2..6055920599 100644 --- a/modules/superres/src/super_resolution.cpp +++ b/modules/superres/src/super_resolution.cpp @@ -61,6 +61,8 @@ void cv::superres::SuperResolution::setInput(const Ptr& frameSource void cv::superres::SuperResolution::nextFrame(OutputArray frame) { + CV_INSTRUMENT_REGION() + isUmat_ = frame.isUMat(); if (firstCall_) diff --git a/modules/video/src/bgfg_KNN.cpp b/modules/video/src/bgfg_KNN.cpp index a532204d42..8c92d77acd 100755 --- a/modules/video/src/bgfg_KNN.cpp +++ b/modules/video/src/bgfg_KNN.cpp @@ -560,6 +560,8 @@ CV_INLINE void void BackgroundSubtractorKNNImpl::apply(InputArray _image, OutputArray _fgmask, double learningRate) { + CV_INSTRUMENT_REGION() + Mat image = _image.getMat(); bool needToInitialize = nframes == 0 || learningRate >= 1 || image.size() != frameSize || image.type() != frameType; @@ -598,6 +600,8 @@ void BackgroundSubtractorKNNImpl::apply(InputArray _image, OutputArray _fgmask, void BackgroundSubtractorKNNImpl::getBackgroundImage(OutputArray backgroundImage) const { + CV_INSTRUMENT_REGION() + int nchannels = CV_MAT_CN(frameType); //CV_Assert( nchannels == 3 ); Mat meanBackground(frameSize, CV_8UC3, Scalar::all(0)); diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index 2720e50e42..f4d2cc237e 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -836,6 +836,8 @@ void BackgroundSubtractorMOG2Impl::create_ocl_apply_kernel() void BackgroundSubtractorMOG2Impl::apply(InputArray _image, OutputArray _fgmask, double learningRate) { + CV_INSTRUMENT_REGION() + bool needToInitialize = nframes == 0 || learningRate >= 1 || _image.size() != frameSize || _image.type() != frameType; if( needToInitialize ) @@ -874,6 +876,8 @@ void BackgroundSubtractorMOG2Impl::apply(InputArray _image, OutputArray _fgmask, template void BackgroundSubtractorMOG2Impl::getBackgroundImage_intern(OutputArray backgroundImage) const { + CV_INSTRUMENT_REGION() + Mat meanBackground(frameSize, frameType, Scalar::all(0)); int firstGaussianIdx = 0; const GMM* gmm = bgmodel.ptr(); diff --git a/modules/video/src/camshift.cpp b/modules/video/src/camshift.cpp index 5449a1b47d..4a7017c82e 100644 --- a/modules/video/src/camshift.cpp +++ b/modules/video/src/camshift.cpp @@ -43,6 +43,8 @@ int cv::meanShift( InputArray _probImage, Rect& window, TermCriteria criteria ) { + CV_INSTRUMENT_REGION() + Size size; int cn; Mat mat; @@ -108,6 +110,8 @@ int cv::meanShift( InputArray _probImage, Rect& window, TermCriteria criteria ) cv::RotatedRect cv::CamShift( InputArray _probImage, Rect& window, TermCriteria criteria ) { + CV_INSTRUMENT_REGION() + const int TOLERANCE = 10; Size size; Mat mat; diff --git a/modules/video/src/kalman.cpp b/modules/video/src/kalman.cpp index 3b86771e87..d0fba8f8fb 100644 --- a/modules/video/src/kalman.cpp +++ b/modules/video/src/kalman.cpp @@ -81,6 +81,8 @@ void KalmanFilter::init(int DP, int MP, int CP, int type) const Mat& KalmanFilter::predict(const Mat& control) { + CV_INSTRUMENT_REGION() + // update the state: x'(k) = A*x(k) statePre = transitionMatrix*statePost; @@ -103,6 +105,8 @@ const Mat& KalmanFilter::predict(const Mat& control) const Mat& KalmanFilter::correct(const Mat& measurement) { + CV_INSTRUMENT_REGION() + // temp2 = H*P'(k) temp2 = measurementMatrix * errorCovPre; diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index b1ad94ddfa..b96a43c5f9 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -223,6 +223,8 @@ typedef float itemtype; void cv::detail::LKTrackerInvoker::operator()(const Range& range) const { + CV_INSTRUMENT_REGION() + Point2f halfWin((winSize.width-1)*0.5f, (winSize.height-1)*0.5f); const Mat& I = *prevImg; const Mat& J = *nextImg; @@ -740,6 +742,8 @@ void cv::detail::LKTrackerInvoker::operator()(const Range& range) const int cv::buildOpticalFlowPyramid(InputArray _img, OutputArrayOfArrays pyramid, Size winSize, int maxLevel, bool withDerivatives, int pyrBorder, int derivBorder, bool tryReuseInputImage) { + CV_INSTRUMENT_REGION() + Mat img = _img.getMat(); CV_Assert(img.depth() == CV_8U && winSize.width > 2 && winSize.height > 2 ); int pyrstep = withDerivatives ? 2 : 1; @@ -1102,6 +1106,8 @@ void SparsePyrLKOpticalFlowImpl::calc( InputArray _prevImg, InputArray _nextImg, InputArray _prevPts, InputOutputArray _nextPts, OutputArray _status, OutputArray _err) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(ocl::useOpenCL() && (_prevImg.isUMat() || _nextImg.isUMat()) && ocl::Image2D::isFormatSupported(CV_32F, 1, false), @@ -1371,6 +1377,8 @@ getRTMatrix( const Point2f* a, const Point2f* b, cv::Mat cv::estimateRigidTransform( InputArray src1, InputArray src2, bool fullAffine ) { + CV_INSTRUMENT_REGION() + Mat M(2, 3, CV_64F), A = src1.getMat(), B = src2.getMat(); const int COUNT = 15; diff --git a/modules/video/src/optflowgf.cpp b/modules/video/src/optflowgf.cpp index b486edaf84..69a7ea6189 100644 --- a/modules/video/src/optflowgf.cpp +++ b/modules/video/src/optflowgf.cpp @@ -1096,6 +1096,8 @@ private: void FarnebackOpticalFlowImpl::calc(InputArray _prev0, InputArray _next0, InputOutputArray _flow0) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_flow0.isUMat() && ocl::Image2D::isFormatSupported(CV_32F, 1, false), calc_ocl(_prev0,_next0,_flow0)) @@ -1184,6 +1186,8 @@ void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0, InputOutputArray _flow0, double pyr_scale, int levels, int winsize, int iterations, int poly_n, double poly_sigma, int flags ) { + CV_INSTRUMENT_REGION() + Ptr optflow; optflow = makePtr(levels,pyr_scale,false,winsize,iterations,poly_n,poly_sigma,flags); optflow->calc(_prev0,_next0,_flow0); diff --git a/modules/video/src/tvl1flow.cpp b/modules/video/src/tvl1flow.cpp index c0299e5c95..03d215d561 100644 --- a/modules/video/src/tvl1flow.cpp +++ b/modules/video/src/tvl1flow.cpp @@ -390,6 +390,8 @@ OpticalFlowDual_TVL1::OpticalFlowDual_TVL1() void OpticalFlowDual_TVL1::calc(InputArray _I0, InputArray _I1, InputOutputArray _flow) { + CV_INSTRUMENT_REGION() + CV_OCL_RUN(_flow.isUMat() && ocl::Image2D::isFormatSupported(CV_32F, 1, false), calc_ocl(_I0, _I1, _flow)) diff --git a/modules/videoio/src/cap.cpp b/modules/videoio/src/cap.cpp index 46cbf42733..55c20bef52 100644 --- a/modules/videoio/src/cap.cpp +++ b/modules/videoio/src/cap.cpp @@ -565,6 +565,8 @@ VideoCapture::~VideoCapture() bool VideoCapture::open(const String& filename, int apiPreference) { + CV_INSTRUMENT_REGION() + if (isOpened()) release(); icap = IVideoCapture_create(filename); if (!icap.empty()) @@ -576,11 +578,15 @@ bool VideoCapture::open(const String& filename, int apiPreference) bool VideoCapture::open(const String& filename) { + CV_INSTRUMENT_REGION() + return open(filename, CAP_ANY); } bool VideoCapture::open(int index) { + CV_INSTRUMENT_REGION() + if (isOpened()) release(); icap = IVideoCapture_create(index); if (!icap.empty()) @@ -602,6 +608,8 @@ void VideoCapture::release() bool VideoCapture::grab() { + CV_INSTRUMENT_REGION() + if (!icap.empty()) return icap->grabFrame(); return cvGrabFrame(cap) != 0; @@ -609,6 +617,8 @@ bool VideoCapture::grab() bool VideoCapture::retrieve(OutputArray image, int channel) { + CV_INSTRUMENT_REGION() + if (!icap.empty()) return icap->retrieveFrame(channel, image); @@ -630,6 +640,8 @@ bool VideoCapture::retrieve(OutputArray image, int channel) bool VideoCapture::read(OutputArray image) { + CV_INSTRUMENT_REGION() + if(grab()) retrieve(image); else @@ -667,6 +679,8 @@ VideoCapture& VideoCapture::operator >> (Mat& image) VideoCapture& VideoCapture::operator >> (UMat& image) { + CV_INSTRUMENT_REGION() + read(image); return *this; } @@ -707,6 +721,8 @@ VideoWriter::~VideoWriter() bool VideoWriter::open(const String& filename, int _fourcc, double fps, Size frameSize, bool isColor) { + CV_INSTRUMENT_REGION() + if (isOpened()) release(); iwriter = IVideoWriter_create(filename, _fourcc, fps, frameSize, isColor); if (!iwriter.empty()) @@ -737,6 +753,8 @@ double VideoWriter::get(int propId) const void VideoWriter::write(const Mat& image) { + CV_INSTRUMENT_REGION() + if( iwriter ) iwriter->write(image); else @@ -748,6 +766,8 @@ void VideoWriter::write(const Mat& image) VideoWriter& VideoWriter::operator << (const Mat& image) { + CV_INSTRUMENT_REGION() + write(image); return *this; } diff --git a/modules/videostab/src/deblurring.cpp b/modules/videostab/src/deblurring.cpp index 2f4cfd0725..dd6cfac825 100644 --- a/modules/videostab/src/deblurring.cpp +++ b/modules/videostab/src/deblurring.cpp @@ -52,6 +52,8 @@ namespace videostab float calcBlurriness(const Mat &frame) { + CV_INSTRUMENT_REGION() + Mat Gx, Gy; Sobel(frame, Gx, CV_32F, 1, 0); Sobel(frame, Gy, CV_32F, 0, 1); @@ -70,6 +72,8 @@ WeightingDeblurer::WeightingDeblurer() void WeightingDeblurer::deblur(int idx, Mat &frame) { + CV_INSTRUMENT_REGION() + CV_Assert(frame.type() == CV_8UC3); bSum_.create(frame.size()); diff --git a/modules/videostab/src/global_motion.cpp b/modules/videostab/src/global_motion.cpp index f7938d5c4c..53603382ad 100644 --- a/modules/videostab/src/global_motion.cpp +++ b/modules/videostab/src/global_motion.cpp @@ -356,6 +356,8 @@ static Mat estimateGlobMotionLeastSquaresAffine( Mat estimateGlobalMotionLeastSquares( InputOutputArray points0, InputOutputArray points1, int model, float *rmse) { + CV_INSTRUMENT_REGION() + CV_Assert(model <= MM_AFFINE); CV_Assert(points0.type() == points1.type()); const int npoints = points0.getMat().checkVector(2); @@ -380,6 +382,8 @@ Mat estimateGlobalMotionRansac( InputArray points0, InputArray points1, int model, const RansacParams ¶ms, float *rmse, int *ninliers) { + CV_INSTRUMENT_REGION() + CV_Assert(model <= MM_AFFINE); CV_Assert(points0.type() == points1.type()); const int npoints = points0.getMat().checkVector(2); @@ -844,6 +848,8 @@ Mat KeypointBasedMotionEstimatorGpu::estimate(const cuda::GpuMat &frame0, const Mat getMotion(int from, int to, const std::vector &motions) { + CV_INSTRUMENT_REGION() + Mat M = Mat::eye(3, 3, CV_32F); if (to > from) { diff --git a/modules/videostab/src/inpainting.cpp b/modules/videostab/src/inpainting.cpp index 991112712d..19f8e519fc 100644 --- a/modules/videostab/src/inpainting.cpp +++ b/modules/videostab/src/inpainting.cpp @@ -103,6 +103,8 @@ void InpaintingPipeline::setStabilizationMotions(const std::vector &val) void InpaintingPipeline::inpaint(int idx, Mat &frame, Mat &mask) { + CV_INSTRUMENT_REGION() + for (size_t i = 0; i < inpainters_.size(); ++i) inpainters_[i]->inpaint(idx, frame, mask); } @@ -124,6 +126,8 @@ ConsistentMosaicInpainter::ConsistentMosaicInpainter() void ConsistentMosaicInpainter::inpaint(int idx, Mat &frame, Mat &mask) { + CV_INSTRUMENT_REGION() + CV_Assert(frame.type() == CV_8UC3); CV_Assert(mask.size() == frame.size() && mask.type() == CV_8U); @@ -336,6 +340,8 @@ MotionInpainter::MotionInpainter() void MotionInpainter::inpaint(int idx, Mat &frame, Mat &mask) { + CV_INSTRUMENT_REGION() + std::priority_queue > neighbors; std::vector vmotions(2*radius_ + 1); @@ -456,6 +462,8 @@ public: void ColorAverageInpainter::inpaint(int /*idx*/, Mat &frame, Mat &mask) { + CV_INSTRUMENT_REGION() + ColorAverageInpaintBody body; body.mask = mask; body.frame = frame; @@ -465,6 +473,8 @@ void ColorAverageInpainter::inpaint(int /*idx*/, Mat &frame, Mat &mask) void ColorInpainter::inpaint(int /*idx*/, Mat &frame, Mat &mask) { + CV_INSTRUMENT_REGION() + bitwise_not(mask, invMask_); cv::inpaint(frame, invMask_, frame, radius_, method_); } @@ -474,6 +484,8 @@ void calcFlowMask( const Mat &flowX, const Mat &flowY, const Mat &errors, float maxError, const Mat &mask0, const Mat &mask1, Mat &flowMask) { + CV_INSTRUMENT_REGION() + CV_Assert(flowX.type() == CV_32F && flowX.size() == mask0.size()); CV_Assert(flowY.type() == CV_32F && flowY.size() == mask0.size()); CV_Assert(errors.type() == CV_32F && errors.size() == mask0.size()); @@ -508,6 +520,8 @@ void completeFrameAccordingToFlow( const Mat &flowMask, const Mat &flowX, const Mat &flowY, const Mat &frame1, const Mat &mask1, float distThresh, Mat &frame0, Mat &mask0) { + CV_INSTRUMENT_REGION() + CV_Assert(flowMask.type() == CV_8U); CV_Assert(flowX.type() == CV_32F && flowX.size() == flowMask.size()); CV_Assert(flowY.type() == CV_32F && flowY.size() == flowMask.size()); diff --git a/modules/videostab/src/motion_stabilizing.cpp b/modules/videostab/src/motion_stabilizing.cpp index d31c420f64..025b7d56de 100644 --- a/modules/videostab/src/motion_stabilizing.cpp +++ b/modules/videostab/src/motion_stabilizing.cpp @@ -637,6 +637,8 @@ static inline void relaxMotion(const float M[], float t, float res[]) Mat ensureInclusionConstraint(const Mat &M, Size size, float trimRatio) { + CV_INSTRUMENT_REGION() + CV_Assert(M.size() == Size(3,3) && M.type() == CV_32F); const float w = static_cast(size.width); @@ -672,6 +674,8 @@ Mat ensureInclusionConstraint(const Mat &M, Size size, float trimRatio) // TODO can be estimated for O(1) time float estimateOptimalTrimRatio(const Mat &M, Size size) { + CV_INSTRUMENT_REGION() + CV_Assert(M.size() == Size(3,3) && M.type() == CV_32F); const float w = static_cast(size.width); diff --git a/modules/videostab/src/outlier_rejection.cpp b/modules/videostab/src/outlier_rejection.cpp index 3ae6e6b271..0e9769c522 100644 --- a/modules/videostab/src/outlier_rejection.cpp +++ b/modules/videostab/src/outlier_rejection.cpp @@ -51,6 +51,8 @@ namespace videostab void NullOutlierRejector::process( Size /*frameSize*/, InputArray points0, InputArray points1, OutputArray mask) { + CV_INSTRUMENT_REGION() + CV_Assert(points0.type() == points1.type()); CV_Assert(points0.getMat().checkVector(2) == points1.getMat().checkVector(2)); @@ -70,6 +72,8 @@ TranslationBasedLocalOutlierRejector::TranslationBasedLocalOutlierRejector() void TranslationBasedLocalOutlierRejector::process( Size frameSize, InputArray points0, InputArray points1, OutputArray mask) { + CV_INSTRUMENT_REGION() + CV_Assert(points0.type() == points1.type()); CV_Assert(points0.getMat().checkVector(2) == points1.getMat().checkVector(2)); From b4b83f2f296d1befd526ded88552f7a62f02955b Mon Sep 17 00:00:00 2001 From: Bleach Date: Sat, 20 Aug 2016 16:29:15 +0300 Subject: [PATCH 081/178] casting to fix vs2010 compile error --- apps/interactive-calibration/frameProcessor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/interactive-calibration/frameProcessor.cpp b/apps/interactive-calibration/frameProcessor.cpp index bef130ef3b..57e1d97d81 100644 --- a/apps/interactive-calibration/frameProcessor.cpp +++ b/apps/interactive-calibration/frameProcessor.cpp @@ -253,8 +253,8 @@ CalibProcessor::CalibProcessor(cv::Ptr data, captureParameters mCapuredFrames = 0; mNeededFramesNum = capParams.calibrationStep; mDelayBetweenCaptures = static_cast(capParams.captureDelay * capParams.fps); - mMaxTemplateOffset = std::sqrt(std::pow(mCalibData->imageSize.height, 2) + - std::pow(mCalibData->imageSize.width, 2)) / 20.0; + mMaxTemplateOffset = std::sqrt(static_cast(mCalibData->imageSize.height * mCalibData->imageSize.height) + + static_cast(mCalibData->imageSize.width * mCalibData->imageSize.width)) / 20.0; mSquareSize = capParams.squareSize; mTemplDist = capParams.templDst; From d482b5c102538c0f23e1830c9c8debaecde3c413 Mon Sep 17 00:00:00 2001 From: Cartucho Date: Mon, 22 Aug 2016 13:45:24 +0200 Subject: [PATCH 082/178] Update hull_demo.cpp The Mat "src_copy" is never used. --- samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp b/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp index 7fe5b71f98..e583791d12 100644 --- a/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp +++ b/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp @@ -49,7 +49,6 @@ int main( int, char** argv ) */ void thresh_callback(int, void* ) { - Mat src_copy = src.clone(); Mat threshold_output; vector > contours; vector hierarchy; From 01d2e7af710e9d2733e733d3c74f01c27dddb8d8 Mon Sep 17 00:00:00 2001 From: mpkh Date: Mon, 22 Aug 2016 17:17:06 +0400 Subject: [PATCH 083/178] fix building on FreeBSD resolve undeclared identifier close error --- modules/core/src/system.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index cc60cf792c..ffca514f8e 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -198,7 +198,7 @@ std::wstring GetTempFileNameWinRT(std::wstring prefix) #include -#if defined __linux__ || defined __APPLE__ || defined __EMSCRIPTEN__ +#if defined __linux__ || defined __APPLE__ || defined __EMSCRIPTEN__ || defined __FreeBSD__ #include #include #include From 767780a4b28d2c75f67f00e5cce9a3a4e13d36df Mon Sep 17 00:00:00 2001 From: yoffy Date: Mon, 9 May 2016 03:50:16 +0900 Subject: [PATCH 084/178] add VideoCapture / VideoWriter AVFoundation implementation for Mac --- CMakeLists.txt | 13 +- cmake/OpenCVFindLibsVideo.cmake | 13 +- cmake/templates/cvconfig.h.in | 3 + modules/videoio/CMakeLists.txt | 4 + modules/videoio/include/opencv2/videoio.hpp | 57 +- .../include/opencv2/videoio/videoio_c.h | 1 + modules/videoio/src/cap.cpp | 16 + modules/videoio/src/cap_avfoundation_mac.mm | 1170 +++++++++++++++++ modules/videoio/src/precomp.hpp | 4 + 9 files changed, 1243 insertions(+), 38 deletions(-) create mode 100644 modules/videoio/src/cap_avfoundation_mac.mm diff --git a/CMakeLists.txt b/CMakeLists.txt index c9568546f7..9681a28810 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -169,7 +169,8 @@ OCV_OPTION(OPENCV_ENABLE_NONFREE "Enable non-free algorithms" OFF) # Optional 3rd party components # =================================================== OCV_OPTION(WITH_1394 "Include IEEE1394 support" ON IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) -OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O" ON IF IOS) +OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O (iOS)" ON IF IOS) +OCV_OPTION(WITH_AVFOUNDATION_MAC "Use AVFoundation for Video I/O (Mac)" ON IF (NOT IOS AND APPLE) ) OCV_OPTION(WITH_CARBON "Use Carbon for UI instead of Cocoa" OFF IF APPLE ) OCV_OPTION(WITH_CAROTENE "Use NVidia carotene acceleration library for ARM platform" ON IF (ARM OR AARCH64) AND NOT IOS AND NOT (CMAKE_VERSION VERSION_LESS "2.8.11")) OCV_OPTION(WITH_VTK "Include VTK library support (and build opencv_viz module eiher)" ON IF (NOT ANDROID AND NOT IOS AND NOT WINRT AND NOT CMAKE_CROSSCOMPILING) ) @@ -1063,10 +1064,6 @@ if(DEFINED WITH_1394) status(" DC1394 2.x:" HAVE_DC1394_2 THEN "YES (ver ${ALIASOF_libdc1394-2_VERSION})" ELSE NO) endif(DEFINED WITH_1394) -if(DEFINED WITH_AVFOUNDATION) - status(" AVFoundation:" WITH_AVFOUNDATION THEN YES ELSE NO) -endif(DEFINED WITH_AVFOUNDATION) - if(DEFINED WITH_FFMPEG) if(WIN32) status(" FFMPEG:" WITH_FFMPEG THEN "YES (prebuilt binaries)" ELSE NO) @@ -1112,10 +1109,12 @@ if(DEFINED WITH_GIGEAPI) status(" GigEVisionSDK:" HAVE_GIGE_API THEN YES ELSE NO) endif(DEFINED WITH_GIGEAPI) -if(DEFINED WITH_QUICKTIME) +if(DEFINED APPLE) status(" QuickTime:" HAVE_QUICKTIME THEN YES ELSE NO) status(" QTKit:" HAVE_QTKIT THEN YES ELSE NO) -endif(DEFINED WITH_QUICKTIME) + status(" AVFoundation:" WITH_AVFOUNDATION THEN YES ELSE NO) + status(" AVFoundationMac:" WITH_AVFOUNDATION_MAC THEN YES ELSE NO) +endif(DEFINED APPLE) if(DEFINED WITH_UNICAP) status(" UniCap:" HAVE_UNICAP THEN "YES (ver ${ALIASOF_libunicap_VERSION})" ELSE NO) diff --git a/cmake/OpenCVFindLibsVideo.cmake b/cmake/OpenCVFindLibsVideo.cmake index 20e31518a4..c23ee06d87 100644 --- a/cmake/OpenCVFindLibsVideo.cmake +++ b/cmake/OpenCVFindLibsVideo.cmake @@ -302,17 +302,24 @@ if(WIN32) endif() endif(WIN32) -# --- Apple AV Foundation --- +# --- Apple AV Foundation (iOS) --- if(WITH_AVFOUNDATION) set(HAVE_AVFOUNDATION YES) endif() -# --- QuickTime --- +# --- Apple AV Foundation (Mac) --- +if(WITH_AVFOUNDATION_MAC) + set(HAVE_AVFOUNDATION_MAC YES) +endif() + +# --- QuickTime, Apple AV Foundation (Mac) --- if (NOT IOS) if(WITH_QUICKTIME) set(HAVE_QUICKTIME YES) - elseif(APPLE AND CMAKE_COMPILER_IS_CLANGCXX) + elseif(WITH_QTKIT) set(HAVE_QTKIT YES) + elseif(APPLE AND CMAKE_COMPILER_IS_CLANGCXX) + set(HAVE_AVFOUNDATION_MAC YES) endif() endif() diff --git a/cmake/templates/cvconfig.h.in b/cmake/templates/cvconfig.h.in index 56d415b400..50b4185e2c 100644 --- a/cmake/templates/cvconfig.h.in +++ b/cmake/templates/cvconfig.h.in @@ -16,6 +16,9 @@ /* AVFoundation video libraries */ #cmakedefine HAVE_AVFOUNDATION +/* AVFoundation (Mac) video libraries */ +#cmakedefine HAVE_AVFOUNDATION_MAC + /* V4L capturing support */ #cmakedefine HAVE_CAMV4L diff --git a/modules/videoio/CMakeLists.txt b/modules/videoio/CMakeLists.txt index 41b0691b75..d75c2d80bb 100644 --- a/modules/videoio/CMakeLists.txt +++ b/modules/videoio/CMakeLists.txt @@ -171,6 +171,10 @@ if(HAVE_AVFOUNDATION) list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_avfoundation.mm) list(APPEND VIDEOIO_LIBRARIES "-framework AVFoundation" "-framework QuartzCore") endif() +if(HAVE_AVFOUNDATION_MAC) + list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_avfoundation_mac.mm) + list(APPEND VIDEOIO_LIBRARIES "-framework Cocoa" "-framework Accelerate" "-framework AVFoundation" "-framework CoreGraphics" "-framework CoreImage" "-framework CoreMedia" "-framework CoreVideo" "-framework QuartzCore") +endif() if(HAVE_QUICKTIME) list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_qt.cpp) diff --git a/modules/videoio/include/opencv2/videoio.hpp b/modules/videoio/include/opencv2/videoio.hpp index b769163cf3..c41d4246d2 100644 --- a/modules/videoio/include/opencv2/videoio.hpp +++ b/modules/videoio/include/opencv2/videoio.hpp @@ -82,34 +82,35 @@ To enable/disable APIs, you have to: 2. rebuild OpenCV itself */ enum VideoCaptureAPIs { - CAP_ANY = 0, //!< Auto detect - CAP_VFW = 200, //!< Video For Windows (platform native) - CAP_V4L = 200, //!< V4L/V4L2 capturing support via libv4l - CAP_V4L2 = CAP_V4L, //!< Same as CAP_V4L - CAP_FIREWIRE = 300, //!< IEEE 1394 drivers - CAP_FIREWARE = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE - CAP_IEEE1394 = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE - CAP_DC1394 = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE - CAP_CMU1394 = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE - CAP_QT = 500, //!< QuickTime - CAP_UNICAP = 600, //!< Unicap drivers - CAP_DSHOW = 700, //!< DirectShow (via videoInput) - CAP_PVAPI = 800, //!< PvAPI, Prosilica GigE SDK - CAP_OPENNI = 900, //!< OpenNI (for Kinect) - CAP_OPENNI_ASUS = 910, //!< OpenNI (for Asus Xtion) - CAP_ANDROID = 1000, //!< Android - not used - CAP_XIAPI = 1100, //!< XIMEA Camera API - CAP_AVFOUNDATION = 1200, //!< AVFoundation framework for iOS (OS X Lion will have the same API) - CAP_GIGANETIX = 1300, //!< Smartek Giganetix GigEVisionSDK - CAP_MSMF = 1400, //!< Microsoft Media Foundation (via videoInput) - CAP_WINRT = 1410, //!< Microsoft Windows Runtime using Media Foundation - CAP_INTELPERC = 1500, //!< Intel Perceptual Computing SDK - CAP_OPENNI2 = 1600, //!< OpenNI2 (for Kinect) - CAP_OPENNI2_ASUS = 1610, //!< OpenNI2 (for Asus Xtion and Occipital Structure sensors) - CAP_GPHOTO2 = 1700, //!< gPhoto2 connection - CAP_GSTREAMER = 1800, //!< GStreamer - CAP_FFMPEG = 1900, //!< FFMPEG - CAP_IMAGES = 2000 //!< OpenCV Image Sequence (e.g. img_%02d.jpg) + CAP_ANY = 0, //!< Auto detect + CAP_VFW = 200, //!< Video For Windows (platform native) + CAP_V4L = 200, //!< V4L/V4L2 capturing support via libv4l + CAP_V4L2 = CAP_V4L, //!< Same as CAP_V4L + CAP_FIREWIRE = 300, //!< IEEE 1394 drivers + CAP_FIREWARE = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE + CAP_IEEE1394 = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE + CAP_DC1394 = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE + CAP_CMU1394 = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE + CAP_QT = 500, //!< QuickTime + CAP_UNICAP = 600, //!< Unicap drivers + CAP_DSHOW = 700, //!< DirectShow (via videoInput) + CAP_PVAPI = 800, //!< PvAPI, Prosilica GigE SDK + CAP_OPENNI = 900, //!< OpenNI (for Kinect) + CAP_OPENNI_ASUS = 910, //!< OpenNI (for Asus Xtion) + CAP_ANDROID = 1000, //!< Android - not used + CAP_XIAPI = 1100, //!< XIMEA Camera API + CAP_AVFOUNDATION = 1200, //!< AVFoundation framework for iOS + CAP_AVFOUNDATION_MAC = 1210, //!< AVFoundation framework for macOS + CAP_GIGANETIX = 1300, //!< Smartek Giganetix GigEVisionSDK + CAP_MSMF = 1400, //!< Microsoft Media Foundation (via videoInput) + CAP_WINRT = 1410, //!< Microsoft Windows Runtime using Media Foundation + CAP_INTELPERC = 1500, //!< Intel Perceptual Computing SDK + CAP_OPENNI2 = 1600, //!< OpenNI2 (for Kinect) + CAP_OPENNI2_ASUS = 1610, //!< OpenNI2 (for Asus Xtion and Occipital Structure sensors) + CAP_GPHOTO2 = 1700, //!< gPhoto2 connection + CAP_GSTREAMER = 1800, //!< GStreamer + CAP_FFMPEG = 1900, //!< FFMPEG + CAP_IMAGES = 2000 //!< OpenCV Image Sequence (e.g. img_%02d.jpg) }; //! generic properties (based on DC1394 properties) diff --git a/modules/videoio/include/opencv2/videoio/videoio_c.h b/modules/videoio/include/opencv2/videoio/videoio_c.h index e502c7be83..1351c4e73a 100644 --- a/modules/videoio/include/opencv2/videoio/videoio_c.h +++ b/modules/videoio/include/opencv2/videoio/videoio_c.h @@ -108,6 +108,7 @@ enum CV_CAP_XIAPI =1100, // XIMEA Camera API CV_CAP_AVFOUNDATION = 1200, // AVFoundation framework for iOS (OS X Lion will have the same API) + CV_CAP_AVFOUNDATION_MAC = 1210, // AVFoundation framework for Mac CV_CAP_GIGANETIX = 1300, // Smartek Giganetix GigEVisionSDK diff --git a/modules/videoio/src/cap.cpp b/modules/videoio/src/cap.cpp index 55c20bef52..8e12b62da0 100644 --- a/modules/videoio/src/cap.cpp +++ b/modules/videoio/src/cap.cpp @@ -266,6 +266,12 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index) if (pref) break; #endif +#ifdef HAVE_AVFOUNDATION_MAC + case CV_CAP_AVFOUNDATION_MAC: + TRY_OPEN(capture, cvCreateCameraCapture_AVFoundation_Mac(index)) + if (pref) break; +#endif + #ifdef HAVE_GIGE_API case CV_CAP_GIGANETIX: TRY_OPEN(capture, cvCreateCameraCapture_Giganetix(index)) @@ -334,6 +340,12 @@ CV_IMPL CvCapture * cvCreateFileCaptureWithPreference (const char * filename, in if (apiPreference) break; #endif +#ifdef HAVE_AVFOUNDATION_MAC + case CV_CAP_AVFOUNDATION_MAC: + TRY_OPEN(result, cvCreateFileCapture_AVFoundation_Mac(filename)) + if (apiPreference) break; +#endif + #ifdef HAVE_OPENNI case CV_CAP_OPENNI: TRY_OPEN(result, cvCreateFileCapture_OpenNI (filename)) @@ -391,6 +403,10 @@ CV_IMPL CvVideoWriter* cvCreateVideoWriter( const char* filename, int fourcc, TRY_OPEN(result, cvCreateVideoWriter_AVFoundation(filename, fourcc, fps, frameSize, is_color)) #endif +#ifdef HAVE_AVFOUNDATION_MAC + TRY_OPEN(result, cvCreateVideoWriter_AVFoundation_Mac(filename, fourcc, fps, frameSize, is_color)) +#endif + #if defined(HAVE_QUICKTIME) || defined(HAVE_QTKIT) TRY_OPEN(result, cvCreateVideoWriter_QT(filename, fourcc, fps, frameSize, is_color)) #endif diff --git a/modules/videoio/src/cap_avfoundation_mac.mm b/modules/videoio/src/cap_avfoundation_mac.mm new file mode 100644 index 0000000000..814e151ccc --- /dev/null +++ b/modules/videoio/src/cap_avfoundation_mac.mm @@ -0,0 +1,1170 @@ +/*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) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * 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 the copyright holders 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 contributor 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 "precomp.hpp" +#include "opencv2/imgproc.hpp" +#include +#import + +/********************** Declaration of class headers ************************/ + +/***************************************************************************** + * + * CaptureDelegate Declaration. + * + * CaptureDelegate is notified on a separate thread by the OS whenever there + * is a new frame. When "updateImage" is called from the main thread, it + * copies this new frame into an IplImage, but only if this frame has not + * been copied before. When "getOutput" is called from the main thread, + * it gives the last copied IplImage. + * + *****************************************************************************/ + + +@interface CaptureDelegate : NSObject +{ + NSCondition *mHasNewFrame; + CVPixelBufferRef mGrabbedPixels; + CVImageBufferRef mCurrentImageBuffer; + IplImage *mDeviceImage; + uint8_t *mOutImagedata; + IplImage *mOutImage; + size_t currSize; +} + +- (void)captureOutput:(AVCaptureOutput *)captureOutput +didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer + fromConnection:(AVCaptureConnection *)connection; + +- (BOOL)grabImageUntilDate: (NSDate *)limit; +- (int)updateImage; +- (IplImage*)getOutput; + +@end + +/***************************************************************************** + * + * CvCaptureCAM Declaration. + * + * CvCaptureCAM is the instantiation of a capture source for cameras. + * + *****************************************************************************/ + +class CvCaptureCAM : public CvCapture { +public: + CvCaptureCAM(int cameraNum = -1) ; + ~CvCaptureCAM(); + virtual bool grabFrame(); + virtual IplImage* retrieveFrame(int); + virtual double getProperty(int property_id) const; + virtual bool setProperty(int property_id, double value); + virtual int didStart(); + + +private: + AVCaptureSession *mCaptureSession; + AVCaptureDeviceInput *mCaptureDeviceInput; + AVCaptureVideoDataOutput *mCaptureVideoDataOutput; + AVCaptureDevice *mCaptureDevice; + CaptureDelegate *mCapture; + + int startCaptureDevice(int cameraNum); + void stopCaptureDevice(); + + void setWidthHeight(); + bool grabFrame(double timeOut); + + int camNum; + int width; + int height; + int settingWidth; + int settingHeight; + OSType mInputPixelFormat; + + int started; +}; + + +/***************************************************************************** + * + * CvCaptureFile Declaration. + * + * CvCaptureFile is the instantiation of a capture source for video files. + * + *****************************************************************************/ + +class CvCaptureFile : public CvCapture { +public: + CvCaptureFile(const char* filename) ; + ~CvCaptureFile(); + virtual bool grabFrame(); + virtual IplImage* retrieveFrame(int); + virtual double getProperty(int property_id) const; + virtual bool setProperty(int property_id, double value); + virtual int didStart(); + + +private: + AVAsset *mAsset; + AVAssetTrack *mAssetTrack; + AVAssetReader *mAssetReader; + AVAssetReaderTrackOutput *mTrackOutput; + + CMSampleBufferRef mCurrentSampleBuffer; + CVImageBufferRef mGrabbedPixels; + IplImage *mDeviceImage; + uint8_t *mOutImagedata; + IplImage *mOutImage; + size_t currSize; + + bool setupReadingAt(CMTime position); + IplImage* retrieveFramePixelBuffer(); + + CMTime mFrameTimestamp; + size_t mFrameNum; + OSType mInputPixelFormat; + + int started; +}; + + +/***************************************************************************** + * + * CvCaptureFile Declaration. + * + * CvCaptureFile is the instantiation of a capture source for video files. + * + *****************************************************************************/ + +class CvVideoWriter_AVFoundation_Mac : public CvVideoWriter{ + public: + CvVideoWriter_AVFoundation_Mac(const char* filename, int fourcc, + double fps, CvSize frame_size, + int is_color=1); + ~CvVideoWriter_AVFoundation_Mac(); + bool writeFrame(const IplImage* image); + private: + IplImage* argbimage; + + AVAssetWriter *mMovieWriter; + AVAssetWriterInput* mMovieWriterInput; + AVAssetWriterInputPixelBufferAdaptor* mMovieWriterAdaptor; + + NSString* path; + NSString* codec; + NSString* fileType; + double mMovieFPS; + CvSize movieSize; + int movieColor; + unsigned long mFrameNum; +}; + +/****************** Implementation of interface functions ********************/ + + +CvCapture* cvCreateFileCapture_AVFoundation_Mac(const char* filename) { + CvCaptureFile *retval = new CvCaptureFile(filename); + + if(retval->didStart()) + return retval; + delete retval; + return NULL; +} + +CvCapture* cvCreateCameraCapture_AVFoundation_Mac(int index ) { + CvCapture* retval = new CvCaptureCAM(index); + if (!((CvCaptureCAM *)retval)->didStart()) + cvReleaseCapture(&retval); + return retval; +} + +CvVideoWriter* cvCreateVideoWriter_AVFoundation_Mac(const char* filename, int fourcc, + double fps, CvSize frame_size, + int is_color) { + return new CvVideoWriter_AVFoundation_Mac(filename, fourcc, fps, frame_size,is_color); +} + +/********************** Implementation of Classes ****************************/ + +/***************************************************************************** + * + * CvCaptureCAM Implementation. + * + * CvCaptureCAM is the instantiation of a capture source for cameras. + * + *****************************************************************************/ + +CvCaptureCAM::CvCaptureCAM(int cameraNum) { + mCaptureSession = nil; + mCaptureDeviceInput = nil; + mCaptureVideoDataOutput = nil; + mCaptureDevice = nil; + mCapture = nil; + + width = 0; + height = 0; + settingWidth = 0; + settingHeight = 0; + + camNum = cameraNum; + + if ( ! startCaptureDevice(camNum) ) { + fprintf(stderr, "OpenCV: camera failed to properly initialize!\n"); + started = 0; + } else { + started = 1; + } +} + +CvCaptureCAM::~CvCaptureCAM() { + stopCaptureDevice(); +} + +int CvCaptureCAM::didStart() { + return started; +} + + +bool CvCaptureCAM::grabFrame() { + return grabFrame(1); +} + +bool CvCaptureCAM::grabFrame(double timeOut) { + NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init]; + + bool isGrabbed = false; + NSDate *limit = [NSDate dateWithTimeIntervalSinceNow: timeOut]; + if ( [mCapture grabImageUntilDate: limit] ) { + [mCapture updateImage]; + isGrabbed = true; + } + + [localpool drain]; + return isGrabbed; +} + +IplImage* CvCaptureCAM::retrieveFrame(int) { + return [mCapture getOutput]; +} + +void CvCaptureCAM::stopCaptureDevice() { + NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init]; + + [mCaptureSession stopRunning]; + + [mCaptureSession release]; + [mCaptureDeviceInput release]; + [mCaptureDevice release]; + + [mCaptureVideoDataOutput release]; + [mCapture release]; + + [localpool drain]; +} + +int CvCaptureCAM::startCaptureDevice(int cameraNum) { + NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init]; + + // get capture device + NSArray *devices = [AVCaptureDevice devicesWithMediaType: AVMediaTypeVideo]; + + if ( devices.count == 0 ) { + fprintf(stderr, "OpenCV: AVFoundation didn't find any attached Video Input Devices!\n"); + [localpool drain]; + return 0; + } + + if ( cameraNum < 0 || devices.count <= NSUInteger(cameraNum) ) { + fprintf(stderr, "OpenCV: out device of bound (0-%ld): %d\n", devices.count-1, cameraNum); + [localpool drain]; + return 0; + } + + mCaptureDevice = devices[cameraNum]; + + if ( ! mCaptureDevice ) { + fprintf(stderr, "OpenCV: device %d not able to use.\n", cameraNum); + [localpool drain]; + return 0; + } + + // get input device + NSError *error = nil; + mCaptureDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice: mCaptureDevice + error: &error]; + if ( error ) { + fprintf(stderr, "OpenCV: error in [AVCaptureDeviceInput initWithDevice:error:]\n"); + NSLog(@"OpenCV: %@", error.localizedDescription); + [localpool drain]; + return 0; + } + + // create output + mCapture = [[CaptureDelegate alloc] init]; + mCaptureVideoDataOutput = [[AVCaptureVideoDataOutput alloc] init]; + dispatch_queue_t queue = dispatch_queue_create("cameraQueue", DISPATCH_QUEUE_SERIAL); + [mCaptureVideoDataOutput setSampleBufferDelegate: mCapture queue: queue]; + dispatch_release(queue); + + OSType pixelFormat = kCVPixelFormatType_32BGRA; + //OSType pixelFormat = kCVPixelFormatType_422YpCbCr8; + NSDictionary *pixelBufferOptions; + if (width > 0 && height > 0) { + pixelBufferOptions = + @{ + (id)kCVPixelBufferWidthKey: @(1.0*width), + (id)kCVPixelBufferHeightKey: @(1.0*height), + (id)kCVPixelBufferPixelFormatTypeKey: @(pixelFormat) + }; + } else { + pixelBufferOptions = + @{ + (id)kCVPixelBufferPixelFormatTypeKey: @(pixelFormat) + }; + } + mCaptureVideoDataOutput.videoSettings = pixelBufferOptions; + mCaptureVideoDataOutput.alwaysDiscardsLateVideoFrames = YES; + + // create session + mCaptureSession = [[AVCaptureSession alloc] init]; + mCaptureSession.sessionPreset = AVCaptureSessionPresetMedium; + [mCaptureSession addInput: mCaptureDeviceInput]; + [mCaptureSession addOutput: mCaptureVideoDataOutput]; + + [mCaptureSession startRunning]; + + // flush old position image + grabFrame(1); + + [localpool drain]; + return 1; +} + +void CvCaptureCAM::setWidthHeight() { + NSMutableDictionary *pixelBufferOptions = [mCaptureVideoDataOutput.videoSettings mutableCopy]; + + while ( true ) { + // auto matching + pixelBufferOptions[(id)kCVPixelBufferWidthKey] = @(1.0*width); + pixelBufferOptions[(id)kCVPixelBufferHeightKey] = @(1.0*height); + mCaptureVideoDataOutput.videoSettings = pixelBufferOptions; + + // compare matched size and my options + CMFormatDescriptionRef format = mCaptureDevice.activeFormat.formatDescription; + CMVideoDimensions deviceSize = CMVideoFormatDescriptionGetDimensions(format); + if ( deviceSize.width == width && deviceSize.height == height ) { + break; + } + + // fit my options to matched size + width = deviceSize.width; + height = deviceSize.height; + } + + // flush old size image + grabFrame(1); + + [pixelBufferOptions release]; +} + + +double CvCaptureCAM::getProperty(int property_id) const{ + NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init]; + + CMFormatDescriptionRef format = mCaptureDevice.activeFormat.formatDescription; + CMVideoDimensions s1 = CMVideoFormatDescriptionGetDimensions(format); + double retval = 0; + + switch (property_id) { + case CV_CAP_PROP_FRAME_WIDTH: + retval = s1.width; + break; + case CV_CAP_PROP_FRAME_HEIGHT: + retval = s1.height; + break; + case CV_CAP_PROP_FPS: + { + CMTime frameDuration = mCaptureDevice.activeVideoMaxFrameDuration; + retval = frameDuration.timescale / double(frameDuration.value); + } + break; + case CV_CAP_PROP_FORMAT: + retval = CV_8UC3; + break; + default: + break; + } + + [localpool drain]; + return retval; +} + +bool CvCaptureCAM::setProperty(int property_id, double value) { + NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init]; + + bool isSucceeded = false; + + switch (property_id) { + case CV_CAP_PROP_FRAME_WIDTH: + width = value; + settingWidth = 1; + if (settingWidth && settingHeight) { + setWidthHeight(); + settingWidth = 0; + settingHeight = 0; + } + isSucceeded = true; + break; + case CV_CAP_PROP_FRAME_HEIGHT: + height = value; + settingHeight = 1; + if (settingWidth && settingHeight) { + setWidthHeight(); + settingWidth = 0; + settingHeight = 0; + } + isSucceeded = true; + break; + case CV_CAP_PROP_FPS: + if ( [mCaptureDevice lockForConfiguration: NULL] ) { + NSArray * ranges = mCaptureDevice.activeFormat.videoSupportedFrameRateRanges; + AVFrameRateRange *matchedRange = ranges[0]; + double minDiff = fabs(matchedRange.maxFrameRate - value); + for ( AVFrameRateRange *range in ranges ) { + double diff = fabs(range.maxFrameRate - value); + if ( diff < minDiff ) { + minDiff = diff; + matchedRange = range; + } + } + mCaptureDevice.activeVideoMinFrameDuration = matchedRange.minFrameDuration; + mCaptureDevice.activeVideoMaxFrameDuration = matchedRange.minFrameDuration; + isSucceeded = true; + [mCaptureDevice unlockForConfiguration]; + } + break; + default: + break; + } + + [localpool drain]; + return isSucceeded; +} + + +/***************************************************************************** + * + * CaptureDelegate Implementation. + * + * CaptureDelegate is notified on a separate thread by the OS whenever there + * is a new frame. When "updateImage" is called from the main thread, it + * copies this new frame into an IplImage, but only if this frame has not + * been copied before. When "getOutput" is called from the main thread, + * it gives the last copied IplImage. + * + *****************************************************************************/ + + +@implementation CaptureDelegate + +- (id)init { + [super init]; + mHasNewFrame = [[NSCondition alloc] init]; + mCurrentImageBuffer = NULL; + mGrabbedPixels = NULL; + mDeviceImage = NULL; + mOutImagedata = NULL; + mOutImage = NULL; + currSize = 0; + return self; +} + +-(void)dealloc { + free(mOutImagedata); + cvReleaseImage(&mOutImage); + cvReleaseImage(&mDeviceImage); + CVBufferRelease(mCurrentImageBuffer); + CVBufferRelease(mGrabbedPixels); + [mHasNewFrame release]; + [super dealloc]; +} + +- (void)captureOutput:(AVCaptureOutput *)captureOutput +didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer + fromConnection:(AVCaptureConnection *)connection { + (void)captureOutput; + (void)sampleBuffer; + (void)connection; + + CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); + CVBufferRetain(imageBuffer); + + [mHasNewFrame lock]; + + CVBufferRelease(mCurrentImageBuffer); + mCurrentImageBuffer = imageBuffer; + [mHasNewFrame signal]; + + [mHasNewFrame unlock]; + +} + +-(IplImage*) getOutput { + return mOutImage; +} + +-(BOOL) grabImageUntilDate: (NSDate *)limit { + BOOL isGrabbed = NO; + [mHasNewFrame lock]; + + if ( mGrabbedPixels ) { + CVBufferRelease(mGrabbedPixels); + } + if ( [mHasNewFrame waitUntilDate: limit] ) { + isGrabbed = YES; + mGrabbedPixels = CVBufferRetain(mCurrentImageBuffer); + } + + [mHasNewFrame unlock]; + return isGrabbed; +} + +-(int) updateImage { + if ( ! mGrabbedPixels ) { + return 0; + } + + CVPixelBufferLockBaseAddress(mGrabbedPixels, 0); + void *baseaddress = CVPixelBufferGetBaseAddress(mGrabbedPixels); + + size_t width = CVPixelBufferGetWidth(mGrabbedPixels); + size_t height = CVPixelBufferGetHeight(mGrabbedPixels); + size_t rowBytes = CVPixelBufferGetBytesPerRow(mGrabbedPixels); + OSType pixelFormat = CVPixelBufferGetPixelFormatType(mGrabbedPixels); + + if ( rowBytes == 0 ) { + fprintf(stderr, "OpenCV: error: rowBytes == 0\n"); + CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); + CVBufferRelease(mGrabbedPixels); + mGrabbedPixels = NULL; + return 0; + } + + if ( currSize != width*3*height ) { + currSize = width*3*height; + free(mOutImagedata); + mOutImagedata = reinterpret_cast(malloc(currSize)); + } + + if (mOutImage == NULL) { + mOutImage = cvCreateImageHeader(cvSize((int)width,(int)height), IPL_DEPTH_8U, 3); + } + mOutImage->width = int(width); + mOutImage->height = int(height); + mOutImage->nChannels = 3; + mOutImage->depth = IPL_DEPTH_8U; + mOutImage->widthStep = int(width*3); + mOutImage->imageData = reinterpret_cast(mOutImagedata); + mOutImage->imageSize = int(currSize); + + if ( pixelFormat == kCVPixelFormatType_32BGRA ) { + if (mDeviceImage == NULL) { + mDeviceImage = cvCreateImageHeader(cvSize(int(width),int(height)), IPL_DEPTH_8U, 4); + } + mDeviceImage->width = int(width); + mDeviceImage->height = int(height); + mDeviceImage->nChannels = 4; + mDeviceImage->depth = IPL_DEPTH_8U; + mDeviceImage->widthStep = int(rowBytes); + mDeviceImage->imageData = reinterpret_cast(baseaddress); + mDeviceImage->imageSize = int(rowBytes*height); + + cvCvtColor(mDeviceImage, mOutImage, CV_BGRA2BGR); + } else if ( pixelFormat == kCVPixelFormatType_422YpCbCr8 ) { + if ( currSize != width*3*height ) { + currSize = width*3*height; + free(mOutImagedata); + mOutImagedata = reinterpret_cast(malloc(currSize)); + } + + if (mDeviceImage == NULL) { + mDeviceImage = cvCreateImageHeader(cvSize(int(width),int(height)), IPL_DEPTH_8U, 2); + } + mDeviceImage->width = int(width); + mDeviceImage->height = int(height); + mDeviceImage->nChannels = 2; + mDeviceImage->depth = IPL_DEPTH_8U; + mDeviceImage->widthStep = int(rowBytes); + mDeviceImage->imageData = reinterpret_cast(baseaddress); + mDeviceImage->imageSize = int(rowBytes*height); + + cvCvtColor(mDeviceImage, mOutImage, CV_YUV2BGR_UYVY); + } else { + fprintf(stderr, "OpenCV: unknown pixel format 0x%08X\n", pixelFormat); + CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); + CVBufferRelease(mGrabbedPixels); + mGrabbedPixels = NULL; + return 0; + } + + CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); + CVBufferRelease(mGrabbedPixels); + mGrabbedPixels = NULL; + + return 1; +} + +@end + + +/***************************************************************************** + * + * CvCaptureFile Implementation. + * + * CvCaptureFile is the instantiation of a capture source for video files. + * + *****************************************************************************/ + +CvCaptureFile::CvCaptureFile(const char* filename) { + NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init]; + + mAsset = nil; + mAssetTrack = nil; + mAssetReader = nil; + mTrackOutput = nil; + mDeviceImage = NULL; + mOutImage = NULL; + mOutImagedata = NULL; + currSize = 0; + mCurrentSampleBuffer = NULL; + mGrabbedPixels = NULL; + mFrameTimestamp = kCMTimeZero; + mFrameNum = 0; + + started = 0; + + mAsset = [[AVAsset assetWithURL:[NSURL fileURLWithPath: @(filename)]] retain]; + + if ( mAsset == nil ) { + fprintf(stderr, "OpenCV: Couldn't read movie file \"%s\"\n", filename); + [localpool drain]; + started = 0; + return; + } + + mAssetTrack = [[mAsset tracksWithMediaType: AVMediaTypeVideo][0] retain]; + + if ( ! setupReadingAt(kCMTimeZero) ) { + fprintf(stderr, "OpenCV: Couldn't read movie file \"%s\"\n", filename); + [localpool drain]; + started = 0; + return; + } + + started = 1; + [localpool drain]; +} + +CvCaptureFile::~CvCaptureFile() { + NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init]; + + free(mOutImagedata); + cvReleaseImage(&mOutImage); + cvReleaseImage(&mDeviceImage); + [mAssetReader release]; + [mTrackOutput release]; + [mAssetTrack release]; + [mAsset release]; + CVBufferRelease(mGrabbedPixels); + if ( mCurrentSampleBuffer ) { + CFRelease(mCurrentSampleBuffer); + } + + [localpool drain]; +} + +bool CvCaptureFile::setupReadingAt(CMTime position) { + if (mAssetReader) { + if (mAssetReader.status == AVAssetReaderStatusReading) { + [mAssetReader cancelReading]; + } + [mAssetReader release]; + mAssetReader = nil; + } + if (mTrackOutput) { + [mTrackOutput release]; + mTrackOutput = nil; + } + + OSType pixelFormat = kCVPixelFormatType_32BGRA; + //OSType pixelFormat = kCVPixelFormatType_422YpCbCr8; + NSDictionary *settings = + @{ + (id)kCVPixelBufferPixelFormatTypeKey: @(pixelFormat) + }; + mTrackOutput = [[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack: mAssetTrack + outputSettings: settings] retain]; + + NSError *error = nil; + mAssetReader = [[AVAssetReader assetReaderWithAsset: mAsset + error: &error] retain]; + if ( error ) { + fprintf(stderr, "OpenCV: error in [AVAssetReader assetReaderWithAsset:error:]\n"); + NSLog(@"OpenCV: %@", error.localizedDescription); + return false; + } + + mAssetReader.timeRange = CMTimeRangeMake(position, kCMTimePositiveInfinity); + mFrameTimestamp = position; + mFrameNum = round((mFrameTimestamp.value * mAssetTrack.nominalFrameRate) / double(mFrameTimestamp.timescale)); + [mAssetReader addOutput: mTrackOutput]; + [mAssetReader startReading]; + + return true; +} + +int CvCaptureFile::didStart() { + return started; +} + +bool CvCaptureFile::grabFrame() { + NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init]; + + CVBufferRelease(mGrabbedPixels); + if ( mCurrentSampleBuffer ) { + CFRelease(mCurrentSampleBuffer); + } + mCurrentSampleBuffer = [mTrackOutput copyNextSampleBuffer]; + mGrabbedPixels = CMSampleBufferGetImageBuffer(mCurrentSampleBuffer); + CVBufferRetain(mGrabbedPixels); + mFrameTimestamp = CMSampleBufferGetOutputPresentationTimeStamp(mCurrentSampleBuffer); + mFrameNum++; + + bool isReading = (mAssetReader.status == AVAssetReaderStatusReading); + [localpool drain]; + return isReading; +} + + +IplImage* CvCaptureFile::retrieveFramePixelBuffer() { + if ( ! mGrabbedPixels ) { + return 0; + } + + NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init]; + + CVPixelBufferLockBaseAddress(mGrabbedPixels, 0); + void *baseaddress = CVPixelBufferGetBaseAddress(mGrabbedPixels); + + size_t width = CVPixelBufferGetWidth(mGrabbedPixels); + size_t height = CVPixelBufferGetHeight(mGrabbedPixels); + size_t rowBytes = CVPixelBufferGetBytesPerRow(mGrabbedPixels); + OSType pixelFormat = CVPixelBufferGetPixelFormatType(mGrabbedPixels); + + if ( rowBytes == 0 ) { + fprintf(stderr, "OpenCV: error: rowBytes == 0\n"); + CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); + CVBufferRelease(mGrabbedPixels); + mGrabbedPixels = NULL; + return 0; + } + + if ( currSize != width*3*height ) { + currSize = width*3*height; + free(mOutImagedata); + mOutImagedata = reinterpret_cast(malloc(currSize)); + } + + if (mOutImage == NULL) { + mOutImage = cvCreateImageHeader(cvSize((int)width,(int)height), IPL_DEPTH_8U, 3); + } + mOutImage->width = int(width); + mOutImage->height = int(height); + mOutImage->nChannels = 3; + mOutImage->depth = IPL_DEPTH_8U; + mOutImage->widthStep = int(width*3); + mOutImage->imageData = reinterpret_cast(mOutImagedata); + mOutImage->imageSize = int(currSize); + + if ( pixelFormat == kCVPixelFormatType_32BGRA ) { + if (mDeviceImage == NULL) { + mDeviceImage = cvCreateImageHeader(cvSize(int(width),int(height)), IPL_DEPTH_8U, 4); + } + mDeviceImage->width = int(width); + mDeviceImage->height = int(height); + mDeviceImage->nChannels = 4; + mDeviceImage->depth = IPL_DEPTH_8U; + mDeviceImage->widthStep = int(rowBytes); + mDeviceImage->imageData = reinterpret_cast(baseaddress); + mDeviceImage->imageSize = int(rowBytes*height); + + cvCvtColor(mDeviceImage, mOutImage, CV_BGRA2BGR); + } else if ( pixelFormat == kCVPixelFormatType_422YpCbCr8 ) { + if ( currSize != width*3*height ) { + currSize = width*3*height; + free(mOutImagedata); + mOutImagedata = reinterpret_cast(malloc(currSize)); + } + + if (mDeviceImage == NULL) { + mDeviceImage = cvCreateImageHeader(cvSize(int(width),int(height)), IPL_DEPTH_8U, 2); + } + mDeviceImage->width = int(width); + mDeviceImage->height = int(height); + mDeviceImage->nChannels = 2; + mDeviceImage->depth = IPL_DEPTH_8U; + mDeviceImage->widthStep = int(rowBytes); + mDeviceImage->imageData = reinterpret_cast(baseaddress); + mDeviceImage->imageSize = int(rowBytes*height); + + cvCvtColor(mDeviceImage, mOutImage, CV_YUV2BGR_UYVY); + } else { + fprintf(stderr, "OpenCV: unknown pixel format 0x%08X\n", pixelFormat); + CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); + CVBufferRelease(mGrabbedPixels); + mGrabbedPixels = NULL; + return 0; + } + + CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); + + [localpool drain]; + + return mOutImage; +} + + +IplImage* CvCaptureFile::retrieveFrame(int) { + return retrieveFramePixelBuffer(); +} + +double CvCaptureFile::getProperty(int property_id) const{ + if (mAsset == nil) return 0; + + CMTime t; + + switch (property_id) { + case CV_CAP_PROP_POS_MSEC: + return mFrameTimestamp.value * 1000.0 / mFrameTimestamp.timescale; + case CV_CAP_PROP_POS_FRAMES: + return mFrameNum; + case CV_CAP_PROP_POS_AVI_RATIO: + t = [mAsset duration]; + return (mFrameTimestamp.value * t.timescale) / double(mFrameTimestamp.timescale * t.value); + case CV_CAP_PROP_FRAME_WIDTH: + return mAssetTrack.naturalSize.width; + case CV_CAP_PROP_FRAME_HEIGHT: + return mAssetTrack.naturalSize.height; + case CV_CAP_PROP_FPS: + return mAssetTrack.nominalFrameRate; + case CV_CAP_PROP_FRAME_COUNT: + t = [mAsset duration]; + return round((t.value * mAssetTrack.nominalFrameRate) / double(t.timescale)); + case CV_CAP_PROP_FORMAT: + return CV_8UC3; + default: + break; + } + + return 0; +} + +bool CvCaptureFile::setProperty(int property_id, double value) { + if (mAsset == nil) return false; + + NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; + + bool retval = false; + CMTime t; + + switch (property_id) { + case CV_CAP_PROP_POS_MSEC: + t = mAsset.duration; + t.value = value * t.timescale / 1000; + setupReadingAt(t); + retval = true; + break; + case CV_CAP_PROP_POS_FRAMES: + setupReadingAt(CMTimeMake(value, mAssetTrack.nominalFrameRate)); + retval = true; + break; + case CV_CAP_PROP_POS_AVI_RATIO: + t = mAsset.duration; + t.value = round(t.value * value); + setupReadingAt(t); + retval = true; + break; + default: + break; + } + + [localpool drain]; + return retval; +} + + +/***************************************************************************** + * + * CvVideoWriter Implementation. + * + * CvVideoWriter is the instantiation of a video output class + * + *****************************************************************************/ + + +CvVideoWriter_AVFoundation_Mac::CvVideoWriter_AVFoundation_Mac(const char* filename, int fourcc, + double fps, CvSize frame_size, + int is_color) { + + NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; + + + mFrameNum = 0; + mMovieFPS = fps; + movieSize = frame_size; + movieColor = is_color; + argbimage = cvCreateImage(movieSize, IPL_DEPTH_8U, 4); + path = [[[NSString stringWithCString:filename encoding:NSASCIIStringEncoding] stringByExpandingTildeInPath] retain]; + + + /* + AVFileTypeQuickTimeMovie + UTI for the QuickTime movie file format. + The value of this UTI is com.apple.quicktime-movie. Files are identified with the .mov and .qt extensions. + + AVFileTypeMPEG4 + UTI for the MPEG-4 file format. + The value of this UTI is public.mpeg-4. Files are identified with the .mp4 extension. + + AVFileTypeAppleM4V + UTI for the iTunes video file format. + The value of this UTI is com.apple.mpeg-4-video. Files are identified with the .m4v extension. + + AVFileType3GPP + UTI for the 3GPP file format. + The value of this UTI is public.3gpp. Files are identified with the .3gp, .3gpp, and .sdv extensions. + */ + + NSString *fileExt =[[[path pathExtension] lowercaseString] copy]; + if ([fileExt isEqualToString:@"mov"] || [fileExt isEqualToString:@"qt"]){ + fileType = [AVFileTypeQuickTimeMovie copy]; + }else if ([fileExt isEqualToString:@"mp4"]){ + fileType = [AVFileTypeMPEG4 copy]; + }else if ([fileExt isEqualToString:@"m4v"]){ + fileType = [AVFileTypeAppleM4V copy]; +#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR + }else if ([fileExt isEqualToString:@"3gp"] || [fileExt isEqualToString:@"3gpp"] || [fileExt isEqualToString:@"sdv"] ){ + fileType = [AVFileType3GPP copy]; +#endif + } else{ + fileType = [AVFileTypeMPEG4 copy]; //default mp4 + } + [fileExt release]; + + char cc[5]; + cc[0] = fourcc & 255; + cc[1] = (fourcc >> 8) & 255; + cc[2] = (fourcc >> 16) & 255; + cc[3] = (fourcc >> 24) & 255; + cc[4] = 0; + int cc2 = CV_FOURCC(cc[0], cc[1], cc[2], cc[3]); + if (cc2!=fourcc) { + fprintf(stderr, "OpenCV: Didn't properly encode FourCC. Expected 0x%08X but got 0x%08X.\n", fourcc, cc2); + //exception; + } + + // Two codec supported AVVideoCodecH264 AVVideoCodecJPEG + // On iPhone 3G H264 is not supported. + if (fourcc == CV_FOURCC('J','P','E','G') || fourcc == CV_FOURCC('j','p','e','g') || + fourcc == CV_FOURCC('M','J','P','G') || fourcc == CV_FOURCC('m','j','p','g') ){ + codec = [AVVideoCodecJPEG copy]; // Use JPEG codec if specified, otherwise H264 + }else if(fourcc == CV_FOURCC('H','2','6','4') || fourcc == CV_FOURCC('a','v','c','1')){ + codec = [AVVideoCodecH264 copy]; + }else{ + codec = [AVVideoCodecH264 copy]; // default canonical H264. + + } + + //NSLog(@"Path: %@", path); + + NSError *error = nil; + + + // Make sure the file does not already exist. Necessary to overwirte?? + /* + NSFileManager *fileManager = [NSFileManager defaultManager]; + if ([fileManager fileExistsAtPath:path]){ + [fileManager removeItemAtPath:path error:&error]; + } + */ + + // Wire the writer: + // Supported file types: + // AVFileTypeQuickTimeMovie AVFileTypeMPEG4 AVFileTypeAppleM4V AVFileType3GPP + + mMovieWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path] + fileType:fileType + error:&error]; + //NSParameterAssert(mMovieWriter); + + NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: + codec, AVVideoCodecKey, + [NSNumber numberWithInt:movieSize.width], AVVideoWidthKey, + [NSNumber numberWithInt:movieSize.height], AVVideoHeightKey, + nil]; + + mMovieWriterInput = [[AVAssetWriterInput + assetWriterInputWithMediaType:AVMediaTypeVideo + outputSettings:videoSettings] retain]; + + //NSParameterAssert(mMovieWriterInput); + //NSParameterAssert([mMovieWriter canAddInput:mMovieWriterInput]); + + [mMovieWriter addInput:mMovieWriterInput]; + + mMovieWriterAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc] initWithAssetWriterInput:mMovieWriterInput sourcePixelBufferAttributes:nil]; + + + //Start a session: + [mMovieWriter startWriting]; + [mMovieWriter startSessionAtSourceTime:kCMTimeZero]; + + + if(mMovieWriter.status == AVAssetWriterStatusFailed){ + NSLog(@"%@", [mMovieWriter.error localizedDescription]); + // TODO: error handling, cleanup. Throw execption? + // return; + } + + [localpool drain]; +} + + +CvVideoWriter_AVFoundation_Mac::~CvVideoWriter_AVFoundation_Mac() { + NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; + + [mMovieWriterInput markAsFinished]; + [mMovieWriter finishWriting]; + [mMovieWriter release]; + [mMovieWriterInput release]; + [mMovieWriterAdaptor release]; + [path release]; + [codec release]; + [fileType release]; + cvReleaseImage(&argbimage); + + [localpool drain]; + +} + +bool CvVideoWriter_AVFoundation_Mac::writeFrame(const IplImage* iplimage) { + NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; + + // writer status check + if (![mMovieWriterInput isReadyForMoreMediaData] || mMovieWriter.status != AVAssetWriterStatusWriting ) { + NSLog(@"[mMovieWriterInput isReadyForMoreMediaData] Not ready for media data or ..."); + NSLog(@"mMovieWriter.status: %d. Error: %@", (int)mMovieWriter.status, [mMovieWriter.error localizedDescription]); + [localpool drain]; + return false; + } + + BOOL success = FALSE; + + if (iplimage->height!=movieSize.height || iplimage->width!=movieSize.width){ + fprintf(stderr, "OpenCV: Frame size does not match video size.\n"); + [localpool drain]; + return false; + } + + if (movieColor) { + //assert(iplimage->nChannels == 3); + cvCvtColor(iplimage, argbimage, CV_BGR2BGRA); + }else{ + //assert(iplimage->nChannels == 1); + cvCvtColor(iplimage, argbimage, CV_GRAY2BGRA); + } + //IplImage -> CGImage conversion + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + NSData *nsData = [NSData dataWithBytes:argbimage->imageData length:argbimage->imageSize]; + CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)nsData); + CGImageRef cgImage = CGImageCreate(argbimage->width, argbimage->height, + argbimage->depth, argbimage->depth * argbimage->nChannels, argbimage->widthStep, + colorSpace, kCGImageAlphaLast|kCGBitmapByteOrderDefault, + provider, NULL, false, kCGRenderingIntentDefault); + + //CGImage -> CVPixelBufferRef coversion + CVPixelBufferRef pixelBuffer = NULL; + CFDataRef cfData = CGDataProviderCopyData(CGImageGetDataProvider(cgImage)); + int status = CVPixelBufferCreateWithBytes(NULL, + movieSize.width, + movieSize.height, + kCVPixelFormatType_32BGRA, + (void*)CFDataGetBytePtr(cfData), + CGImageGetBytesPerRow(cgImage), + NULL, + 0, + NULL, + &pixelBuffer); + if(status == kCVReturnSuccess){ + success = [mMovieWriterAdaptor appendPixelBuffer:pixelBuffer + withPresentationTime:CMTimeMake(mFrameNum, mMovieFPS)]; + } + + //cleanup + CFRelease(cfData); + CVPixelBufferRelease(pixelBuffer); + CGImageRelease(cgImage); + CGDataProviderRelease(provider); + CGColorSpaceRelease(colorSpace); + + [localpool drain]; + + if (success) { + mFrameNum ++; + //NSLog(@"Frame #%d", mFrameNum); + return true; + }else{ + NSLog(@"Frame appendPixelBuffer failed."); + return false; + } + +} diff --git a/modules/videoio/src/precomp.hpp b/modules/videoio/src/precomp.hpp index 45ce1a1f60..50853d0bb9 100644 --- a/modules/videoio/src/precomp.hpp +++ b/modules/videoio/src/precomp.hpp @@ -127,6 +127,7 @@ CvCapture* cvCreateFileCapture_OpenNI( const char* filename ); CvCapture* cvCreateCameraCapture_Android( int index ); CvCapture* cvCreateCameraCapture_XIMEA( int index ); CvCapture* cvCreateCameraCapture_AVFoundation(int index); +CvCapture* cvCreateCameraCapture_AVFoundation_Mac(int index); CvCapture* cvCreateFileCapture_Images(const char* filename); CvVideoWriter* cvCreateVideoWriter_Images(const char* filename); @@ -155,6 +156,9 @@ CvVideoWriter* cvCreateVideoWriter_QT ( const char* filename, int fourcc, CvCapture* cvCreateFileCapture_AVFoundation (const char * filename); CvVideoWriter* cvCreateVideoWriter_AVFoundation( const char* filename, int fourcc, double fps, CvSize frameSize, int is_color ); +CvCapture* cvCreateFileCapture_AVFoundation_Mac(const char * filename); +CvVideoWriter* cvCreateVideoWriter_AVFoundation_Mac( const char* filename, int fourcc, + double fps, CvSize frameSize, int is_color ); CvCapture * cvCreateCameraCapture_Unicap (const int index); From 574f319c7462553077f1ee22092a8bcc4f85f935 Mon Sep 17 00:00:00 2001 From: Valeriy Van Date: Tue, 23 Aug 2016 22:04:41 +0300 Subject: [PATCH 085/178] Fixes spelling in comment --- modules/videoio/src/cap_ios_abstract_camera.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/videoio/src/cap_ios_abstract_camera.mm b/modules/videoio/src/cap_ios_abstract_camera.mm index 328c161513..e580f24250 100644 --- a/modules/videoio/src/cap_ios_abstract_camera.mm +++ b/modules/videoio/src/cap_ios_abstract_camera.mm @@ -170,7 +170,7 @@ } running = YES; - // TOOD update image size data before actually starting (needed for recording) + // TODO: update image size data before actually starting (needed for recording) [self updateSize]; if (cameraAvailable) { From fcc28fecb622a1f474f767311294f99c8a7e71a9 Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Tue, 23 Aug 2016 20:57:20 +0300 Subject: [PATCH 086/178] Make Up --- modules/calib3d/include/opencv2/calib3d.hpp | 2 +- modules/core/include/opencv2/core.hpp | 118 ++++++++++---------- modules/imgproc/include/opencv2/imgproc.hpp | 18 +-- 3 files changed, 69 insertions(+), 69 deletions(-) diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index 3ba7f61ae8..654cc4d3bc 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -320,7 +320,7 @@ mask values are ignored. @param maxIters The maximum number of RANSAC iterations, 2000 is the maximum it can be. @param confidence Confidence level, between 0 and 1. -The functions find and return the perspective transformation \f$H\f$ between the source and the +The function finds and returns the perspective transformation \f$H\f$ between the source and the destination planes: \f[s_i \vecthree{x'_i}{y'_i}{1} \sim H \vecthree{x_i}{y_i}{1}\f] diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index 88b06f3911..48e05ff696 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -426,7 +426,7 @@ CV_EXPORTS_W void multiply(InputArray src1, InputArray src2, /** @brief Performs per-element division of two arrays or a scalar by an array. -The functions divide divide one array by another: +The function cv::divide divides one array by another: \f[\texttt{dst(I) = saturate(src1(I)*scale/src2(I))}\f] or a scalar by an array when there is no src1 : \f[\texttt{dst(I) = saturate(scale/src2(I))}\f] @@ -553,7 +553,7 @@ CV_EXPORTS_W void LUT(InputArray src, InputArray lut, OutputArray dst); /** @brief Calculates the sum of array elements. -The functions sum calculate and return the sum of array elements, +The function cv::sum calculates and returns the sum of array elements, independently for each channel. @param src input array that must have from 1 to 4 channels. @sa countNonZero, mean, meanStdDev, norm, minMaxLoc, reduce @@ -599,10 +599,10 @@ CV_EXPORTS_W void findNonZero( InputArray src, OutputArray idx ); /** @brief Calculates an average (mean) of array elements. -The function mean calculates the mean value M of array elements, +The function cv::mean calculates the mean value M of array elements, independently for each channel, and return it: \f[\begin{array}{l} N = \sum _{I: \; \texttt{mask} (I) \ne 0} 1 \\ M_c = \left ( \sum _{I: \; \texttt{mask} (I) \ne 0}{ \texttt{mtx} (I)_c} \right )/N \end{array}\f] -When all the mask elements are 0's, the functions return Scalar::all(0) +When all the mask elements are 0's, the function returns Scalar::all(0) @param src input array that should have from 1 to 4 channels so that the result can be stored in Scalar_ . @param mask optional operation mask. @@ -612,11 +612,11 @@ CV_EXPORTS_W Scalar mean(InputArray src, InputArray mask = noArray()); /** Calculates a mean and standard deviation of array elements. -The function meanStdDev calculates the mean and the standard deviation M +The function cv::meanStdDev calculates the mean and the standard deviation M of array elements independently for each channel and returns it via the output parameters: \f[\begin{array}{l} N = \sum _{I, \texttt{mask} (I) \ne 0} 1 \\ \texttt{mean} _c = \frac{\sum_{ I: \; \texttt{mask}(I) \ne 0} \texttt{src} (I)_c}{N} \\ \texttt{stddev} _c = \sqrt{\frac{\sum_{ I: \; \texttt{mask}(I) \ne 0} \left ( \texttt{src} (I)_c - \texttt{mean} _c \right )^2}{N}} \end{array}\f] -When all the mask elements are 0's, the functions return +When all the mask elements are 0's, the function returns mean=stddev=Scalar::all(0). @note The calculated standard deviation is only the diagonal of the complete normalized covariance matrix. If the full matrix is needed, you @@ -636,7 +636,7 @@ CV_EXPORTS_W void meanStdDev(InputArray src, OutputArray mean, OutputArray stdde /** @brief Calculates an absolute array norm, an absolute difference norm, or a relative difference norm. -The functions norm calculate an absolute norm of src1 (when there is no +The function cv::norm calculates an absolute norm of src1 (when there is no src2 ): \f[norm = \forkthree{\|\texttt{src1}\|_{L_{\infty}} = \max _I | \texttt{src1} (I)|}{if \(\texttt{normType} = \texttt{NORM_INF}\) } @@ -655,7 +655,7 @@ or { \frac{\|\texttt{src1}-\texttt{src2}\|_{L_1} }{\|\texttt{src2}\|_{L_1}} }{if \(\texttt{normType} = \texttt{NORM_RELATIVE_L1}\) } { \frac{\|\texttt{src1}-\texttt{src2}\|_{L_2} }{\|\texttt{src2}\|_{L_2}} }{if \(\texttt{normType} = \texttt{NORM_RELATIVE_L2}\) }\f] -The functions norm return the calculated norm. +The function cv::norm returns the calculated norm. When the mask parameter is specified and it is not empty, the norm is calculated only over the region specified by the mask. @@ -703,7 +703,7 @@ CV_EXPORTS_W void batchDistance(InputArray src1, InputArray src2, /** @brief Normalizes the norm or value range of an array. -The functions normalize scale and shift the input array elements so that +The function cv::normalize normalizes scale and shift the input array elements so that \f[\| \texttt{dst} \| _{L_p}= \texttt{alpha}\f] (where p=Inf, 1 or 2) when normType=NORM_INF, NORM_L1, or NORM_L2, respectively; or so that \f[\min _I \texttt{dst} (I)= \texttt{alpha} , \, \, \max _I \texttt{dst} (I)= \texttt{beta}\f] @@ -773,11 +773,11 @@ CV_EXPORTS void normalize( const SparseMat& src, SparseMat& dst, double alpha, i /** @brief Finds the global minimum and maximum in an array. -The functions minMaxLoc find the minimum and maximum element values and their positions. The +The function cv::minMaxLoc finds the minimum and maximum element values and their positions. The extremums are searched across the whole array or, if mask is not an empty array, in the specified array region. -The functions do not work with multi-channel arrays. If you need to find minimum or maximum +The function do not work with multi-channel arrays. If you need to find minimum or maximum elements across all the channels, use Mat::reshape first to reinterpret the array as single-channel. Or you may extract the particular channel using either extractImageCOI , or mixChannels , or split . @@ -796,7 +796,7 @@ CV_EXPORTS_W void minMaxLoc(InputArray src, CV_OUT double* minVal, /** @brief Finds the global minimum and maximum in an array -The function minMaxIdx finds the minimum and maximum element values and their positions. The +The function cv::minMaxIdx finds the minimum and maximum element values and their positions. The extremums are searched across the whole array or, if mask is not an empty array, in the specified array region. The function does not work with multi-channel arrays. If you need to find minimum or maximum elements across all the channels, use Mat::reshape first to reinterpret the array as @@ -834,7 +834,7 @@ CV_EXPORTS void minMaxLoc(const SparseMat& a, double* minVal, /** @brief Reduces a matrix to a vector. -The function reduce reduces the matrix to a vector by treating the matrix rows/columns as a set of +The function cv::reduce reduces the matrix to a vector by treating the matrix rows/columns as a set of 1D vectors and performing the specified operation on the vectors until a single row/column is obtained. For example, the function can be used to compute horizontal and vertical projections of a raster image. In case of REDUCE_MAX and REDUCE_MIN , the output image should have the same type as the source one. @@ -853,7 +853,7 @@ CV_EXPORTS_W void reduce(InputArray src, OutputArray dst, int dim, int rtype, in /** @brief Creates one multi-channel array out of several single-channel ones. -The function merge merges several arrays to make a single multi-channel array. That is, each +The function cv::merge merges several arrays to make a single multi-channel array. That is, each element of the output array will be a concatenation of the elements of the input arrays, where elements of i-th input array are treated as mv[i].channels()-element vectors. @@ -878,7 +878,7 @@ CV_EXPORTS_W void merge(InputArrayOfArrays mv, OutputArray dst); /** @brief Divides a multi-channel array into several single-channel arrays. -The functions split split a multi-channel array into separate single-channel arrays: +The function cv::split splits a multi-channel array into separate single-channel arrays: \f[\texttt{mv} [c](I) = \texttt{src} (I)_c\f] If you need to extract a single channel or do some other sophisticated channel permutation, use mixChannels . @@ -990,7 +990,7 @@ CV_EXPORTS_W void insertChannel(InputArray src, InputOutputArray dst, int coi); /** @brief Flips a 2D array around vertical, horizontal, or both axes. -The function flip flips the array in one of three different ways (row +The function cv::flip flips the array in one of three different ways (row and column indices are 0-based): \f[\texttt{dst} _{ij} = \left\{ @@ -1177,7 +1177,7 @@ CV_EXPORTS_W void vconcat(InputArrayOfArrays src, OutputArray dst); Calculates the per-element bit-wise conjunction of two arrays or an array and a scalar. -The function calculates the per-element bit-wise logical conjunction for: +The function cv::bitwise_and calculates the per-element bit-wise logical conjunction for: * Two arrays when src1 and src2 have the same size: \f[\texttt{dst} (I) = \texttt{src1} (I) \wedge \texttt{src2} (I) \quad \texttt{if mask} (I) \ne0\f] * An array and a scalar when src2 is constructed from Scalar or has @@ -1204,7 +1204,7 @@ CV_EXPORTS_W void bitwise_and(InputArray src1, InputArray src2, /** @brief Calculates the per-element bit-wise disjunction of two arrays or an array and a scalar. -The function calculates the per-element bit-wise logical disjunction for: +The function cv::bitwise_or calculates the per-element bit-wise logical disjunction for: * Two arrays when src1 and src2 have the same size: \f[\texttt{dst} (I) = \texttt{src1} (I) \vee \texttt{src2} (I) \quad \texttt{if mask} (I) \ne0\f] * An array and a scalar when src2 is constructed from Scalar or has @@ -1231,7 +1231,7 @@ CV_EXPORTS_W void bitwise_or(InputArray src1, InputArray src2, /** @brief Calculates the per-element bit-wise "exclusive or" operation on two arrays or an array and a scalar. -The function calculates the per-element bit-wise logical "exclusive-or" +The function cv::bitwise_xor calculates the per-element bit-wise logical "exclusive-or" operation for: * Two arrays when src1 and src2 have the same size: \f[\texttt{dst} (I) = \texttt{src1} (I) \oplus \texttt{src2} (I) \quad \texttt{if mask} (I) \ne0\f] @@ -1258,7 +1258,7 @@ CV_EXPORTS_W void bitwise_xor(InputArray src1, InputArray src2, /** @brief Inverts every bit of an array. -The function calculates per-element bit-wise inversion of the input +The function cv::bitwise_not calculates per-element bit-wise inversion of the input array: \f[\texttt{dst} (I) = \neg \texttt{src} (I)\f] In case of a floating-point input array, its machine-specific bit @@ -1275,7 +1275,7 @@ CV_EXPORTS_W void bitwise_not(InputArray src, OutputArray dst, /** @brief Calculates the per-element absolute difference between two arrays or between an array and a scalar. -The function absdiff calculates: +The function cv::absdiff calculates: * Absolute difference between two arrays when they have the same size and type: \f[\texttt{dst}(I) = \texttt{saturate} (| \texttt{src1}(I) - \texttt{src2}(I)|)\f] @@ -1350,7 +1350,7 @@ CV_EXPORTS_W void compare(InputArray src1, InputArray src2, OutputArray dst, int /** @brief Calculates per-element minimum of two arrays or an array and a scalar. -The functions min calculate the per-element minimum of two arrays: +The function cv::min calculates the per-element minimum of two arrays: \f[\texttt{dst} (I)= \min ( \texttt{src1} (I), \texttt{src2} (I))\f] or array and a scalar: \f[\texttt{dst} (I)= \min ( \texttt{src1} (I), \texttt{value} )\f] @@ -1371,7 +1371,7 @@ CV_EXPORTS void min(const UMat& src1, const UMat& src2, UMat& dst); /** @brief Calculates per-element maximum of two arrays or an array and a scalar. -The functions max calculate the per-element maximum of two arrays: +The function cv::max calculates the per-element maximum of two arrays: \f[\texttt{dst} (I)= \max ( \texttt{src1} (I), \texttt{src2} (I))\f] or array and a scalar: \f[\texttt{dst} (I)= \max ( \texttt{src1} (I), \texttt{value} )\f] @@ -1392,7 +1392,7 @@ CV_EXPORTS void max(const UMat& src1, const UMat& src2, UMat& dst); /** @brief Calculates a square root of array elements. -The functions sqrt calculate a square root of each input array element. +The function cv::sqrt calculates a square root of each input array element. In case of multi-channel arrays, each channel is processed independently. The accuracy is approximately the same as of the built-in std::sqrt . @@ -1403,7 +1403,7 @@ CV_EXPORTS_W void sqrt(InputArray src, OutputArray dst); /** @brief Raises every array element to a power. -The function pow raises every element of the input array to power : +The function cv::pow raises every element of the input array to power : \f[\texttt{dst} (I) = \fork{\texttt{src}(I)^{power}}{if \(\texttt{power}\) is integer}{|\texttt{src}(I)|^{power}}{otherwise}\f] So, for a non-integer power exponent, the absolute values of input array @@ -1428,7 +1428,7 @@ CV_EXPORTS_W void pow(InputArray src, double power, OutputArray dst); /** @brief Calculates the exponent of every array element. -The function exp calculates the exponent of every element of the input +The function cv::exp calculates the exponent of every element of the input array: \f[\texttt{dst} [I] = e^{ src(I) }\f] @@ -1444,7 +1444,7 @@ CV_EXPORTS_W void exp(InputArray src, OutputArray dst); /** @brief Calculates the natural logarithm of every array element. -The function log calculates the natural logarithm of every element of the input array: +The function cv::log calculates the natural logarithm of every element of the input array: \f[\texttt{dst} (I) = \log (\texttt{src}(I)) \f] Output on zero, negative and special (NaN, Inf) values is undefined. @@ -1457,7 +1457,7 @@ CV_EXPORTS_W void log(InputArray src, OutputArray dst); /** @brief Calculates x and y coordinates of 2D vectors from their magnitude and angle. -The function polarToCart calculates the Cartesian coordinates of each 2D +The function cv::polarToCart calculates the Cartesian coordinates of each 2D vector represented by the corresponding elements of magnitude and angle: \f[\begin{array}{l} \texttt{x} (I) = \texttt{magnitude} (I) \cos ( \texttt{angle} (I)) \\ \texttt{y} (I) = \texttt{magnitude} (I) \sin ( \texttt{angle} (I)) \\ \end{array}\f] @@ -1480,7 +1480,7 @@ CV_EXPORTS_W void polarToCart(InputArray magnitude, InputArray angle, /** @brief Calculates the magnitude and angle of 2D vectors. -The function cartToPolar calculates either the magnitude, angle, or both +The function cv::cartToPolar calculates either the magnitude, angle, or both for every 2D vector (x(I),y(I)): \f[\begin{array}{l} \texttt{magnitude} (I)= \sqrt{\texttt{x}(I)^2+\texttt{y}(I)^2} , \\ \texttt{angle} (I)= \texttt{atan2} ( \texttt{y} (I), \texttt{x} (I))[ \cdot180 / \pi ] \end{array}\f] @@ -1502,7 +1502,7 @@ CV_EXPORTS_W void cartToPolar(InputArray x, InputArray y, /** @brief Calculates the rotation angle of 2D vectors. -The function phase calculates the rotation angle of each 2D vector that +The function cv::phase calculates the rotation angle of each 2D vector that is formed from the corresponding elements of x and y : \f[\texttt{angle} (I) = \texttt{atan2} ( \texttt{y} (I), \texttt{x} (I))\f] @@ -1521,7 +1521,7 @@ CV_EXPORTS_W void phase(InputArray x, InputArray y, OutputArray angle, /** @brief Calculates the magnitude of 2D vectors. -The function magnitude calculates the magnitude of 2D vectors formed +The function cv::magnitude calculates the magnitude of 2D vectors formed from the corresponding elements of x and y arrays: \f[\texttt{dst} (I) = \sqrt{\texttt{x}(I)^2 + \texttt{y}(I)^2}\f] @param x floating-point array of x-coordinates of the vectors. @@ -1534,11 +1534,11 @@ CV_EXPORTS_W void magnitude(InputArray x, InputArray y, OutputArray magnitude); /** @brief Checks every element of an input array for invalid values. -The functions checkRange check that every array element is neither NaN nor infinite. When minVal \> --DBL_MAX and maxVal \< DBL_MAX, the functions also check that each value is between minVal and +The function cv::checkRange checks that every array element is neither NaN nor infinite. When minVal \> +-DBL_MAX and maxVal \< DBL_MAX, the function also checks that each value is between minVal and maxVal. In case of multi-channel arrays, each channel is processed independently. If some values are out of range, position of the first outlier is stored in pos (when pos != NULL). Then, the -functions either return false (when quiet=true) or throw an exception. +function either returns false (when quiet=true) or throws an exception. @param a input array. @param quiet a flag, indicating whether the functions quietly return false when the array elements are out of range or they throw an exception. @@ -1556,7 +1556,7 @@ CV_EXPORTS_W void patchNaNs(InputOutputArray a, double val = 0); /** @brief Performs generalized matrix multiplication. -The function performs generalized matrix multiplication similar to the +The function cv::gemm performs generalized matrix multiplication similar to the gemm functions in BLAS level 3. For example, `gemm(src1, src2, alpha, src3, beta, dst, GEMM_1_T + GEMM_3_T)` corresponds to @@ -1587,7 +1587,7 @@ CV_EXPORTS_W void gemm(InputArray src1, InputArray src2, double alpha, /** @brief Calculates the product of a matrix and its transposition. -The function mulTransposed calculates the product of src and its +The function cv::mulTransposed calculates the product of src and its transposition: \f[\texttt{dst} = \texttt{scale} ( \texttt{src} - \texttt{delta} )^T ( \texttt{src} - \texttt{delta} )\f] if aTa=true , and @@ -1619,7 +1619,7 @@ CV_EXPORTS_W void mulTransposed( InputArray src, OutputArray dst, bool aTa, /** @brief Transposes a matrix. -The function transpose transposes the matrix src : +The function cv::transpose transposes the matrix src : \f[\texttt{dst} (i,j) = \texttt{src} (j,i)\f] @note No complex conjugation is done in case of a complex matrix. It it should be done separately if needed. @@ -1630,7 +1630,7 @@ CV_EXPORTS_W void transpose(InputArray src, OutputArray dst); /** @brief Performs the matrix transformation of every array element. -The function transform performs the matrix transformation of every +The function cv::transform performs the matrix transformation of every element of the array src and stores the results in dst : \f[\texttt{dst} (I) = \texttt{m} \cdot \texttt{src} (I)\f] (when m.cols=src.channels() ), or @@ -1656,7 +1656,7 @@ CV_EXPORTS_W void transform(InputArray src, OutputArray dst, InputArray m ); /** @brief Performs the perspective matrix transformation of vectors. -The function perspectiveTransform transforms every element of src by +The function cv::perspectiveTransform transforms every element of src by treating it as a 2D or 3D vector, in the following way: \f[(x, y, z) \rightarrow (x'/w, y'/w, z'/w)\f] where @@ -1683,7 +1683,7 @@ CV_EXPORTS_W void perspectiveTransform(InputArray src, OutputArray dst, InputArr /** @brief Copies the lower or the upper half of a square matrix to another half. -The function completeSymm copies the lower half of a square matrix to +The function cv::completeSymm copies the lower half of a square matrix to its another half. The matrix diagonal remains unchanged: * \f$\texttt{mtx}_{ij}=\texttt{mtx}_{ji}\f$ for \f$i > j\f$ if lowerToUpper=false @@ -1698,7 +1698,7 @@ CV_EXPORTS_W void completeSymm(InputOutputArray mtx, bool lowerToUpper = false); /** @brief Initializes a scaled identity matrix. -The function setIdentity initializes a scaled identity matrix: +The function cv::setIdentity initializes a scaled identity matrix: \f[\texttt{mtx} (i,j)= \fork{\texttt{value}}{ if \(i=j\)}{0}{otherwise}\f] The function can also be emulated using the matrix initializers and the @@ -1715,7 +1715,7 @@ CV_EXPORTS_W void setIdentity(InputOutputArray mtx, const Scalar& s = Scalar(1)) /** @brief Returns the determinant of a square floating-point matrix. -The function determinant calculates and returns the determinant of the +The function cv::determinant calculates and returns the determinant of the specified matrix. For small matrices ( mtx.cols=mtx.rows\<=3 ), the direct method is used. For larger matrices, the function uses LU factorization with partial pivoting. @@ -1730,7 +1730,7 @@ CV_EXPORTS_W double determinant(InputArray mtx); /** @brief Returns the trace of a matrix. -The function trace returns the sum of the diagonal elements of the +The function cv::trace returns the sum of the diagonal elements of the matrix mtx . \f[\mathrm{tr} ( \texttt{mtx} ) = \sum _i \texttt{mtx} (i,i)\f] @param mtx input matrix. @@ -1739,7 +1739,7 @@ CV_EXPORTS_W Scalar trace(InputArray mtx); /** @brief Finds the inverse or pseudo-inverse of a matrix. -The function invert inverts the matrix src and stores the result in dst +The function cv::invert inverts the matrix src and stores the result in dst . When the matrix src is singular or non-square, the function calculates the pseudo-inverse matrix (the dst matrix) so that norm(src\*dst - I) is minimal, where I is an identity matrix. @@ -1766,7 +1766,7 @@ CV_EXPORTS_W double invert(InputArray src, OutputArray dst, int flags = DECOMP_L /** @brief Solves one or more linear systems or least-squares problems. -The function solve solves a linear system or least-squares problem (the +The function cv::solve solves a linear system or least-squares problem (the latter is possible with SVD or QR methods, or by specifying the flag DECOMP_NORMAL ): \f[\texttt{dst} = \arg \min _X \| \texttt{src1} \cdot \texttt{X} - \texttt{src2} \|\f] @@ -1791,7 +1791,7 @@ CV_EXPORTS_W bool solve(InputArray src1, InputArray src2, /** @brief Sorts each row or each column of a matrix. -The function sort sorts each matrix row or each matrix column in +The function cv::sort sorts each matrix row or each matrix column in ascending or descending order. So you should pass two operation flags to get desired behaviour. If you want to sort matrix rows or columns lexicographically, you can use STL std::sort generic function with the @@ -1806,7 +1806,7 @@ CV_EXPORTS_W void sort(InputArray src, OutputArray dst, int flags); /** @brief Sorts each row or each column of a matrix. -The function sortIdx sorts each matrix row or each matrix column in the +The function cv::sortIdx sorts each matrix row or each matrix column in the ascending or descending order. So you should pass two operation flags to get desired behaviour. Instead of reordering the elements themselves, it stores the indices of sorted elements in the output array. For example: @@ -1840,7 +1840,7 @@ CV_EXPORTS_W int solveCubic(InputArray coeffs, OutputArray roots); /** @brief Finds the real or complex roots of a polynomial equation. -The function solvePoly finds real and complex roots of a polynomial equation: +The function cv::solvePoly finds real and complex roots of a polynomial equation: \f[\texttt{coeffs} [n] x^{n} + \texttt{coeffs} [n-1] x^{n-1} + ... + \texttt{coeffs} [1] x + \texttt{coeffs} [0] = 0\f] @param coeffs array of polynomial coefficients. @param roots output (complex) array of roots. @@ -1850,7 +1850,7 @@ CV_EXPORTS_W double solvePoly(InputArray coeffs, OutputArray roots, int maxIters /** @brief Calculates eigenvalues and eigenvectors of a symmetric matrix. -The functions eigen calculate just eigenvalues, or eigenvalues and eigenvectors of the symmetric +The function cv::eigen calculates just eigenvalues, or eigenvalues and eigenvectors of the symmetric matrix src: @code src*eigenvectors.row(i).t() = eigenvalues.at(i)*eigenvectors.row(i).t() @@ -1871,7 +1871,7 @@ CV_EXPORTS_W bool eigen(InputArray src, OutputArray eigenvalues, /** @brief Calculates the covariance matrix of a set of vectors. -The functions calcCovarMatrix calculate the covariance matrix and, optionally, the mean vector of +The function cv::calcCovarMatrix calculates the covariance matrix and, optionally, the mean vector of the set of input vectors. @param samples samples stored as separate matrices @param nsamples number of samples @@ -1921,7 +1921,7 @@ CV_EXPORTS_W void SVBackSubst( InputArray w, InputArray u, InputArray vt, /** @brief Calculates the Mahalanobis distance between two vectors. -The function Mahalanobis calculates and returns the weighted distance between two vectors: +The function cv::Mahalanobis calculates and returns the weighted distance between two vectors: \f[d( \texttt{vec1} , \texttt{vec2} )= \sqrt{\sum_{i,j}{\texttt{icovar(i,j)}\cdot(\texttt{vec1}(I)-\texttt{vec2}(I))\cdot(\texttt{vec1(j)}-\texttt{vec2(j)})} }\f] The covariance matrix may be calculated using the cv::calcCovarMatrix function and then inverted using the invert function (preferably using the cv::DECOMP_SVD method, as the most accurate). @@ -1933,7 +1933,7 @@ CV_EXPORTS_W double Mahalanobis(InputArray v1, InputArray v2, InputArray icovar) /** @brief Performs a forward or inverse Discrete Fourier transform of a 1D or 2D floating-point array. -The function performs one of the following: +The function cv::dft performs one of the following: - Forward the Fourier transform of a 1D vector of N elements: \f[Y = F^{(N)} \cdot X,\f] where \f$F^{(N)}_{jk}=\exp(-2\pi i j k/N)\f$ and \f$i=\sqrt{-1}\f$ @@ -2081,7 +2081,7 @@ CV_EXPORTS_W void idft(InputArray src, OutputArray dst, int flags = 0, int nonze /** @brief Performs a forward or inverse discrete Cosine transform of 1D or 2D array. -The function dct performs a forward or inverse discrete Cosine transform (DCT) of a 1D or 2D +The function cv::dct performs a forward or inverse discrete Cosine transform (DCT) of a 1D or 2D floating-point array: - Forward Cosine transform of a 1D vector of N elements: \f[Y = C^{(N)} \cdot X\f] @@ -2132,7 +2132,7 @@ CV_EXPORTS_W void idct(InputArray src, OutputArray dst, int flags = 0); /** @brief Performs the per-element multiplication of two Fourier spectrums. -The function mulSpectrums performs the per-element multiplication of the two CCS-packed or complex +The function cv::mulSpectrums performs the per-element multiplication of the two CCS-packed or complex matrices that are results of a real or complex Fourier transform. The function, together with dft and idft , may be used to calculate convolution (pass conjB=false ) @@ -2159,7 +2159,7 @@ original one. Arrays whose size is a power-of-two (2, 4, 8, 16, 32, ...) are the Though, the arrays whose size is a product of 2's, 3's, and 5's (for example, 300 = 5\*5\*3\*2\*2) are also processed quite efficiently. -The function getOptimalDFTSize returns the minimum number N that is greater than or equal to vecsize +The function cv::getOptimalDFTSize returns the minimum number N that is greater than or equal to vecsize so that the DFT of a vector of size N can be processed efficiently. In the current implementation N = 2 ^p^ \* 3 ^q^ \* 5 ^r^ for some integer p, q, r. @@ -2175,7 +2175,7 @@ CV_EXPORTS_W int getOptimalDFTSize(int vecsize); /** @brief Returns the default random number generator. -The function theRNG returns the default random number generator. For each thread, there is a +The function cv::theRNG returns the default random number generator. For each thread, there is a separate random number generator, so you can use the function safely in multi-thread environments. If you just need to get a single random number using this generator or initialize an array, you can use randu or randn instead. But if you are going to generate many random numbers inside a loop, it @@ -2186,7 +2186,7 @@ CV_EXPORTS RNG& theRNG(); /** @brief Sets state of default random number generator. -The function sets state of default random number generator to custom value. +The function cv::setRNGSeed sets state of default random number generator to custom value. @param seed new state for default random number generator @sa RNG, randu, randn */ @@ -2206,7 +2206,7 @@ CV_EXPORTS_W void randu(InputOutputArray dst, InputArray low, InputArray high); /** @brief Fills the array with normally distributed random numbers. -The function randn fills the matrix dst with normally distributed random numbers with the specified +The function cv::randn fills the matrix dst with normally distributed random numbers with the specified mean vector and the standard deviation matrix. The generated random numbers are clipped to fit the value range of the output array data type. @param dst output array of random numbers; the array must be pre-allocated and have 1 to 4 channels. @@ -2219,7 +2219,7 @@ CV_EXPORTS_W void randn(InputOutputArray dst, InputArray mean, InputArray stddev /** @brief Shuffles the array elements randomly. -The function randShuffle shuffles the specified 1D array by randomly choosing pairs of elements and +The function cv::randShuffle shuffles the specified 1D array by randomly choosing pairs of elements and swapping them. The number of such swap operations will be dst.rows\*dst.cols\*iterFactor . @param dst input/output numerical 1D array. @param iterFactor scale factor that determines the number of random swap operations (see the details diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index b8d95e3fc1..f4698036b6 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -2507,7 +2507,7 @@ CV_EXPORTS_AS(integral2) void integral( InputArray src, OutputArray sum, /** @brief Calculates the integral of an image. -The functions calculate one or more integral images for the source image as follows: +The function calculates one or more integral images for the source image as follows: \f[\texttt{sum} (X,Y) = \sum _{x @@ -3854,7 +3854,7 @@ An example using the convexHull functionality /** @brief Finds the convex hull of a point set. -The functions find the convex hull of a 2D point set using the Sklansky's algorithm @cite Sklansky82 +The function cv::convexHull finds the convex hull of a 2D point set using the Sklansky's algorithm @cite Sklansky82 that has *O(N logN)* complexity in the current implementation. See the OpenCV sample convexhull.cpp that demonstrates the usage of different function variants. @@ -4123,7 +4123,7 @@ CV_EXPORTS_W void circle(InputOutputArray img, Point center, int radius, /** @brief Draws a simple or thick elliptic arc or fills an ellipse sector. -The functions ellipse with less parameters draw an ellipse outline, a filled ellipse, an elliptic +The function cv::ellipse with less parameters draws an ellipse outline, a filled ellipse, an elliptic arc, or a filled ellipse sector. A piecewise-linear curve is used to approximate the elliptic arc boundary. If you need more control of the ellipse rendering, you can retrieve the curve using ellipse2Poly and then render it with polylines or fill it with fillPoly . If you use the first @@ -4344,9 +4344,9 @@ CV_EXPORTS_W void drawContours( InputOutputArray image, InputArrayOfArrays conto /** @brief Clips the line against the image rectangle. -The functions clipLine calculate a part of the line segment that is entirely within the specified -rectangle. They return false if the line segment is completely outside the rectangle. Otherwise, -they return true . +The function cv::clipLine calculates a part of the line segment that is entirely within the specified +rectangle. it returns false if the line segment is completely outside the rectangle. Otherwise, +it returns true . @param imgSize Image size. The image rectangle is Rect(0, 0, imgSize.width, imgSize.height) . @param pt1 First line point. @param pt2 Second line point. From a92da54e79493e50e61527bd2b6ea2ec3e1bd288 Mon Sep 17 00:00:00 2001 From: Matthew Self Date: Tue, 23 Aug 2016 11:11:00 -0700 Subject: [PATCH 087/178] Add support for CAP_PROP_MODE Support setting CAP_PROP_MODE to capture grayscale or YUV frames much faster from CV_CAP_AVFOUNDATION_MAC. --- modules/videoio/src/cap_avfoundation_mac.mm | 231 ++++++++++++++++---- 1 file changed, 187 insertions(+), 44 deletions(-) diff --git a/modules/videoio/src/cap_avfoundation_mac.mm b/modules/videoio/src/cap_avfoundation_mac.mm index 814e151ccc..aa888188c0 100644 --- a/modules/videoio/src/cap_avfoundation_mac.mm +++ b/modules/videoio/src/cap_avfoundation_mac.mm @@ -155,6 +155,8 @@ private: uint8_t *mOutImagedata; IplImage *mOutImage; size_t currSize; + int mMode; + int mFormat; bool setupReadingAt(CMTime position); IplImage* retrieveFramePixelBuffer(); @@ -169,13 +171,13 @@ private: /***************************************************************************** * - * CvCaptureFile Declaration. + * CvVideoWriter_AVFoundation_Mac Declaration. * - * CvCaptureFile is the instantiation of a capture source for video files. + * CvVideoWriter_AVFoundation_Mac is the instantiation of a video output class. * *****************************************************************************/ -class CvVideoWriter_AVFoundation_Mac : public CvVideoWriter{ +class CvVideoWriter_AVFoundation_Mac : public CvVideoWriter { public: CvVideoWriter_AVFoundation_Mac(const char* filename, int fourcc, double fps, CvSize frame_size, @@ -675,6 +677,8 @@ CvCaptureFile::CvCaptureFile(const char* filename) { mOutImage = NULL; mOutImagedata = NULL; currSize = 0; + mMode = CV_CAP_MODE_BGR; + mFormat = CV_8UC3; mCurrentSampleBuffer = NULL; mGrabbedPixels = NULL; mFrameTimestamp = kCMTimeZero; @@ -735,8 +739,27 @@ bool CvCaptureFile::setupReadingAt(CMTime position) { mTrackOutput = nil; } - OSType pixelFormat = kCVPixelFormatType_32BGRA; - //OSType pixelFormat = kCVPixelFormatType_422YpCbCr8; + // Capture in a pixel format that can be converted efficiently to the output mode. + OSType pixelFormat; + if (mMode == CV_CAP_MODE_BGR || mMode == CV_CAP_MODE_RGB) { + // For CV_CAP_MODE_BGR, read frames as BGRA (AV Foundation's YUV->RGB conversion is slightly faster than OpenCV's CV_YUV2BGR_YV12) + // kCVPixelFormatType_32ABGR is reportedly faster on OS X, but OpenCV doesn't have a CV_ABGR2BGR conversion. + // kCVPixelFormatType_24RGB is significanly slower than kCVPixelFormatType_32BGRA. + pixelFormat = kCVPixelFormatType_32BGRA; + mFormat = CV_8UC3; + } else if (mMode == CV_CAP_MODE_GRAY) { + // For CV_CAP_MODE_GRAY, read frames as 420v (faster than 420f or 422 -- at least for H.264 files) + pixelFormat = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; + mFormat = CV_8UC1; + } else if (mMode == CV_CAP_MODE_YUYV) { + // For CV_CAP_MODE_YUYV, read frames directly as 422. + pixelFormat = kCVPixelFormatType_422YpCbCr8; + mFormat = CV_8UC2; + } else { + fprintf(stderr, "VIDEOIO ERROR: AVF Mac: Unsupported mode: %d\n", mMode); + return false; + } + NSDictionary *settings = @{ (id)kCVPixelBufferPixelFormatTypeKey: @(pixelFormat) @@ -744,6 +767,11 @@ bool CvCaptureFile::setupReadingAt(CMTime position) { mTrackOutput = [[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack: mAssetTrack outputSettings: settings] retain]; + if ( !mTrackOutput ) { + fprintf(stderr, "OpenCV: error in [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:outputSettings:]\n"); + return false; + } + NSError *error = nil; mAssetReader = [[AVAssetReader assetReaderWithAsset: mAsset error: &error] retain]; @@ -793,13 +821,23 @@ IplImage* CvCaptureFile::retrieveFramePixelBuffer() { NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init]; CVPixelBufferLockBaseAddress(mGrabbedPixels, 0); - void *baseaddress = CVPixelBufferGetBaseAddress(mGrabbedPixels); + void *baseaddress; + size_t width, height, rowBytes; - size_t width = CVPixelBufferGetWidth(mGrabbedPixels); - size_t height = CVPixelBufferGetHeight(mGrabbedPixels); - size_t rowBytes = CVPixelBufferGetBytesPerRow(mGrabbedPixels); OSType pixelFormat = CVPixelBufferGetPixelFormatType(mGrabbedPixels); + if (CVPixelBufferIsPlanar(mGrabbedPixels)) { + baseaddress = CVPixelBufferGetBaseAddressOfPlane(mGrabbedPixels, 0); + width = CVPixelBufferGetWidthOfPlane(mGrabbedPixels, 0); + height = CVPixelBufferGetHeightOfPlane(mGrabbedPixels, 0); + rowBytes = CVPixelBufferGetBytesPerRowOfPlane(mGrabbedPixels, 0); + } else { + baseaddress = CVPixelBufferGetBaseAddress(mGrabbedPixels); + width = CVPixelBufferGetWidth(mGrabbedPixels); + height = CVPixelBufferGetHeight(mGrabbedPixels); + rowBytes = CVPixelBufferGetBytesPerRow(mGrabbedPixels); + } + if ( rowBytes == 0 ) { fprintf(stderr, "OpenCV: error: rowBytes == 0\n"); CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); @@ -808,63 +846,144 @@ IplImage* CvCaptureFile::retrieveFramePixelBuffer() { return 0; } - if ( currSize != width*3*height ) { - currSize = width*3*height; + // Output image paramaters. + int outChannels; + if (mMode == CV_CAP_MODE_BGR || mMode == CV_CAP_MODE_RGB) { + outChannels = 3; + } else if (mMode == CV_CAP_MODE_GRAY) { + outChannels = 1; + } else if (mMode == CV_CAP_MODE_YUYV) { + outChannels = 2; + } else { + fprintf(stderr, "VIDEOIO ERROR: AVF Mac: Unsupported mode: %d\n", mMode); + CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); + CVBufferRelease(mGrabbedPixels); + mGrabbedPixels = NULL; + return 0; + } + + if ( currSize != width*outChannels*height ) { + currSize = width*outChannels*height; free(mOutImagedata); mOutImagedata = reinterpret_cast(malloc(currSize)); } + // Build the header for the output image. if (mOutImage == NULL) { - mOutImage = cvCreateImageHeader(cvSize((int)width,(int)height), IPL_DEPTH_8U, 3); + mOutImage = cvCreateImageHeader(cvSize((int)width,(int)height), IPL_DEPTH_8U, outChannels); } mOutImage->width = int(width); mOutImage->height = int(height); - mOutImage->nChannels = 3; + mOutImage->nChannels = outChannels; mOutImage->depth = IPL_DEPTH_8U; - mOutImage->widthStep = int(width*3); + mOutImage->widthStep = int(width*outChannels); mOutImage->imageData = reinterpret_cast(mOutImagedata); mOutImage->imageSize = int(currSize); + // Device image paramaters and conversion code. + // (Not all of these conversions are used in production, but they were all tested to find the fastest options.) + int deviceChannels; + int cvtCode; + if ( pixelFormat == kCVPixelFormatType_32BGRA ) { - if (mDeviceImage == NULL) { - mDeviceImage = cvCreateImageHeader(cvSize(int(width),int(height)), IPL_DEPTH_8U, 4); - } - mDeviceImage->width = int(width); - mDeviceImage->height = int(height); - mDeviceImage->nChannels = 4; - mDeviceImage->depth = IPL_DEPTH_8U; - mDeviceImage->widthStep = int(rowBytes); - mDeviceImage->imageData = reinterpret_cast(baseaddress); - mDeviceImage->imageSize = int(rowBytes*height); + deviceChannels = 4; - cvCvtColor(mDeviceImage, mOutImage, CV_BGRA2BGR); - } else if ( pixelFormat == kCVPixelFormatType_422YpCbCr8 ) { - if ( currSize != width*3*height ) { - currSize = width*3*height; - free(mOutImagedata); - mOutImagedata = reinterpret_cast(malloc(currSize)); + if (mMode == CV_CAP_MODE_BGR) { + cvtCode = CV_BGRA2BGR; + } else if (mMode == CV_CAP_MODE_RGB) { + cvtCode = CV_BGRA2RGB; + } else if (mMode == CV_CAP_MODE_GRAY) { + cvtCode = CV_BGRA2GRAY; + } else { + CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); + CVBufferRelease(mGrabbedPixels); + mGrabbedPixels = NULL; + fprintf(stderr, "OpenCV: unsupported pixel conversion mode\n"); + return 0; } + } else if ( pixelFormat == kCVPixelFormatType_24RGB ) { + deviceChannels = 3; - if (mDeviceImage == NULL) { - mDeviceImage = cvCreateImageHeader(cvSize(int(width),int(height)), IPL_DEPTH_8U, 2); + if (mMode == CV_CAP_MODE_BGR) { + cvtCode = CV_RGB2BGR; + } else if (mMode == CV_CAP_MODE_RGB) { + cvtCode = 0; + } else if (mMode == CV_CAP_MODE_GRAY) { + cvtCode = CV_RGB2GRAY; + } else { + CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); + CVBufferRelease(mGrabbedPixels); + mGrabbedPixels = NULL; + fprintf(stderr, "OpenCV: unsupported pixel conversion mode\n"); + return 0; } - mDeviceImage->width = int(width); - mDeviceImage->height = int(height); - mDeviceImage->nChannels = 2; - mDeviceImage->depth = IPL_DEPTH_8U; - mDeviceImage->widthStep = int(rowBytes); - mDeviceImage->imageData = reinterpret_cast(baseaddress); - mDeviceImage->imageSize = int(rowBytes*height); + } else if ( pixelFormat == kCVPixelFormatType_422YpCbCr8 ) { // 422 (2vuy, UYVY) + deviceChannels = 2; - cvCvtColor(mDeviceImage, mOutImage, CV_YUV2BGR_UYVY); + if (mMode == CV_CAP_MODE_BGR) { + cvtCode = CV_YUV2BGR_UYVY; + } else if (mMode == CV_CAP_MODE_RGB) { + cvtCode = CV_YUV2RGB_UYVY; + } else if (mMode == CV_CAP_MODE_GRAY) { + cvtCode = CV_YUV2GRAY_UYVY; + } else if (mMode == CV_CAP_MODE_YUYV) { + cvtCode = 0; // Copy + } else { + CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); + CVBufferRelease(mGrabbedPixels); + mGrabbedPixels = NULL; + fprintf(stderr, "OpenCV: unsupported pixel conversion mode\n"); + return 0; + } + } else if ( pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange || // 420v + pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange ) { // 420f + // cvCvtColor(CV_YUV2GRAY_420) is expecting a single buffer with both the Y plane and the CrCb planes. + // So, lie about the height of the buffer. cvCvtColor(CV_YUV2GRAY_420) will only read the first 2/3 of it. + height = height * 3 / 2; + deviceChannels = 1; + + if (mMode == CV_CAP_MODE_BGR) { + cvtCode = CV_YUV2BGR_YV12; + } else if (mMode == CV_CAP_MODE_RGB) { + cvtCode = CV_YUV2RGB_YV12; + } else if (mMode == CV_CAP_MODE_GRAY) { + cvtCode = CV_YUV2GRAY_420; + } else { + CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); + CVBufferRelease(mGrabbedPixels); + mGrabbedPixels = NULL; + fprintf(stderr, "OpenCV: unsupported pixel conversion mode\n"); + return 0; + } } else { - fprintf(stderr, "OpenCV: unknown pixel format 0x%08X\n", pixelFormat); + fprintf(stderr, "OpenCV: unsupported pixel format 0x%08X\n", pixelFormat); CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); CVBufferRelease(mGrabbedPixels); mGrabbedPixels = NULL; return 0; } + // Build the header for the device image. + if (mDeviceImage == NULL) { + mDeviceImage = cvCreateImageHeader(cvSize(int(width),int(height)), IPL_DEPTH_8U, deviceChannels); + } + mDeviceImage->width = int(width); + mDeviceImage->height = int(height); + mDeviceImage->nChannels = deviceChannels; + mDeviceImage->depth = IPL_DEPTH_8U; + mDeviceImage->widthStep = int(rowBytes); + mDeviceImage->imageData = reinterpret_cast(baseaddress); + mDeviceImage->imageSize = int(rowBytes*height); + + // Convert the device image into the output image. + if (cvtCode == 0) { + // Copy. + cv::cvarrToMat(mDeviceImage).copyTo(cv::cvarrToMat(mOutImage)); + } else { + cvCvtColor(mDeviceImage, mOutImage, cvtCode); + } + + CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); [localpool drain]; @@ -900,7 +1019,9 @@ double CvCaptureFile::getProperty(int property_id) const{ t = [mAsset duration]; return round((t.value * mAssetTrack.nominalFrameRate) / double(t.timescale)); case CV_CAP_PROP_FORMAT: - return CV_8UC3; + return mFormat; + case CV_CAP_PROP_MODE: + return mMode; default: break; } @@ -933,6 +1054,28 @@ bool CvCaptureFile::setProperty(int property_id, double value) { setupReadingAt(t); retval = true; break; + case CV_CAP_PROP_MODE: + int mode; + mode = cvRound(value); + if (mMode == mode) { + retval = true; + } else { + switch (mode) { + case CV_CAP_MODE_BGR: + case CV_CAP_MODE_RGB: + case CV_CAP_MODE_GRAY: + case CV_CAP_MODE_YUYV: + mMode = mode; + setupReadingAt(mFrameTimestamp); + retval = true; + break; + default: + fprintf(stderr, "VIDEOIO ERROR: AVF Mac: Unsupported mode: %d\n", mode); + retval=false; + break; + } + } + break; default: break; } @@ -944,9 +1087,9 @@ bool CvCaptureFile::setProperty(int property_id, double value) { /***************************************************************************** * - * CvVideoWriter Implementation. + * CvVideoWriter_AVFoundation_Mac Implementation. * - * CvVideoWriter is the instantiation of a video output class + * CvVideoWriter_AVFoundation_Mac is the instantiation of a video output class. * *****************************************************************************/ From 0882936707c019a8f12a58519a431e042f03e9be Mon Sep 17 00:00:00 2001 From: Matthew Self Date: Tue, 23 Aug 2016 11:15:24 -0700 Subject: [PATCH 088/178] Fix buffer release issue CvVideoWriter_AVFoundation_Mac had a serious buffer release bug. Also made writeFrame() block until isReadyForMoreMediaData rather than return an error. --- modules/videoio/src/cap_avfoundation_mac.mm | 25 ++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/modules/videoio/src/cap_avfoundation_mac.mm b/modules/videoio/src/cap_avfoundation_mac.mm index aa888188c0..4228bc3735 100644 --- a/modules/videoio/src/cap_avfoundation_mac.mm +++ b/modules/videoio/src/cap_avfoundation_mac.mm @@ -927,7 +927,7 @@ IplImage* CvCaptureFile::retrieveFramePixelBuffer() { } else if (mMode == CV_CAP_MODE_GRAY) { cvtCode = CV_YUV2GRAY_UYVY; } else if (mMode == CV_CAP_MODE_YUYV) { - cvtCode = 0; // Copy + cvtCode = -1; // Copy } else { CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); CVBufferRelease(mGrabbedPixels); @@ -976,7 +976,7 @@ IplImage* CvCaptureFile::retrieveFramePixelBuffer() { mDeviceImage->imageSize = int(rowBytes*height); // Convert the device image into the output image. - if (cvtCode == 0) { + if (cvtCode == -1) { // Copy. cv::cvarrToMat(mDeviceImage).copyTo(cv::cvarrToMat(mOutImage)); } else { @@ -1213,7 +1213,7 @@ CvVideoWriter_AVFoundation_Mac::CvVideoWriter_AVFoundation_Mac(const char* filen if(mMovieWriter.status == AVAssetWriterStatusFailed){ - NSLog(@"%@", [mMovieWriter.error localizedDescription]); + NSLog(@"AVF: AVAssetWriter status: %@", [mMovieWriter.error localizedDescription]); // TODO: error handling, cleanup. Throw execption? // return; } @@ -1239,17 +1239,27 @@ CvVideoWriter_AVFoundation_Mac::~CvVideoWriter_AVFoundation_Mac() { } +static void releaseCallback( void *releaseRefCon, const void * ) { + CFRelease((CFDataRef)releaseRefCon); +} + bool CvVideoWriter_AVFoundation_Mac::writeFrame(const IplImage* iplimage) { NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; // writer status check - if (![mMovieWriterInput isReadyForMoreMediaData] || mMovieWriter.status != AVAssetWriterStatusWriting ) { - NSLog(@"[mMovieWriterInput isReadyForMoreMediaData] Not ready for media data or ..."); + if (mMovieWriter.status != AVAssetWriterStatusWriting ) { NSLog(@"mMovieWriter.status: %d. Error: %@", (int)mMovieWriter.status, [mMovieWriter.error localizedDescription]); [localpool drain]; return false; } + // Make writeFrame() a blocking call. + while (![mMovieWriterInput isReadyForMoreMediaData]) { + fprintf(stderr, "OpenCV: AVF: waiting to write video data.\n"); + // Sleep 1 msec. + usleep(1000); + } + BOOL success = FALSE; if (iplimage->height!=movieSize.height || iplimage->width!=movieSize.width){ @@ -1283,8 +1293,8 @@ bool CvVideoWriter_AVFoundation_Mac::writeFrame(const IplImage* iplimage) { kCVPixelFormatType_32BGRA, (void*)CFDataGetBytePtr(cfData), CGImageGetBytesPerRow(cgImage), - NULL, - 0, + &releaseCallback, + (void *)cfData, NULL, &pixelBuffer); if(status == kCVReturnSuccess){ @@ -1293,7 +1303,6 @@ bool CvVideoWriter_AVFoundation_Mac::writeFrame(const IplImage* iplimage) { } //cleanup - CFRelease(cfData); CVPixelBufferRelease(pixelBuffer); CGImageRelease(cgImage); CGDataProviderRelease(provider); From 47f2e618ee956a0b1dfbf87f3a24f41194d2cab6 Mon Sep 17 00:00:00 2001 From: MYLS Date: Wed, 24 Aug 2016 17:01:57 +0800 Subject: [PATCH 089/178] Add two tests. - one test for type_id; - another for comments in JSON; --- modules/core/src/persistence.cpp | 3 +++ modules/core/test/test_io.cpp | 35 ++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index d6990779a5..d5b90671a5 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -3286,7 +3286,10 @@ icvJSONSkipSpaces( CvFileStorage* fs, char* ptr ) if ( !ptr ) { is_eof = true; break; } } if ( *ptr == '/' ) + { + ptr++; break; + } } else { diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index 5ba4fd1909..a43356f0da 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -643,6 +643,8 @@ TEST(Core_InputOutput, filestorage_base64_basic) cv::Mat _nd_out, _nd_in; cv::Mat _rd_out(64, 64, CV_64FC1), _rd_in; + bool no_type_id = true; + { /* init */ /* a normal mat */ @@ -703,6 +705,12 @@ TEST(Core_InputOutput, filestorage_base64_basic) fs["normal_nd_mat"] >> _nd_in; fs["random_mat"] >> _rd_in; + if ( !fs["empty_2d_mat"]["type_id"].empty() || + !fs["normal_2d_mat"]["type_id"].empty() || + !fs["normal_nd_mat"]["type_id"].empty() || + !fs[ "random_mat"]["type_id"].empty() ) + no_type_id = false; + /* raw data */ std::vector(1000).swap(rawdata); cvReadRawData(*fs, fs["rawdata"].node, rawdata.data(), data_t::signature()); @@ -722,6 +730,8 @@ TEST(Core_InputOutput, filestorage_base64_basic) //EXPECT_EQ(rawdata[i].i4, i); } + EXPECT_TRUE(no_type_id); + EXPECT_EQ(_em_in.rows , _em_out.rows); EXPECT_EQ(_em_in.cols , _em_out.cols); EXPECT_EQ(_em_in.depth(), _em_out.depth()); @@ -893,3 +903,28 @@ TEST(Core_InputOutput, filestorage_yml_vec2i) remove(file_name.c_str()); } + +TEST(Core_InputOutput, filestorage_json_comment) +{ + String mem_str = + "{ /* comment */\n" + " \"key\": \"value\"\n" + " /************\n" + " * multiline comment\n" + " ************/\n" + " // 233\n" + " // \n" + "}\n" + ; + + String str; + + EXPECT_NO_THROW( + { + cv::FileStorage fs(mem_str, cv::FileStorage::READ | cv::FileStorage::MEMORY); + fs["key"] >> str; + fs.release(); + }); + + EXPECT_EQ(str, String("value")); +} From c5d7791b67cb2810bff9a3123f9f640e5dcc7530 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Wed, 24 Aug 2016 18:32:13 +0900 Subject: [PATCH 090/178] brush up fp16 implementation * DRY * switch to Cv32suf and remove fp32Int32 * add Cv16suf --- modules/core/include/opencv2/core/cvdef.h | 21 +++++++++++++ modules/core/src/convert.cpp | 38 ++++------------------- 2 files changed, 27 insertions(+), 32 deletions(-) diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index e3ad5cf902..8011c36ffa 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -307,11 +307,32 @@ enum CpuFeatures { #define CV_2PI 6.283185307179586476925286766559 #define CV_LOG2 0.69314718055994530941723212145818 +typedef union Cv16suf +{ + short i; +#if ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) ) + __fp16 h; +#endif + struct _fp16Format + { + unsigned int significand : 10; + unsigned int exponent : 5; + unsigned int sign : 1; + } fmt; +} +Cv16suf; + typedef union Cv32suf { int i; unsigned u; float f; + struct _fp32Format + { + unsigned int significand : 23; + unsigned int exponent : 8; + unsigned int sign : 1; + } fmt; } Cv32suf; diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 1b7f77cb8d..1ee912aefd 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -4367,39 +4367,13 @@ const unsigned int kShiftSignificand = 13; const unsigned int kMaskFp16Significand = 0x3ff; const unsigned int kBiasFp16Exponent = 15; const unsigned int kBiasFp32Exponent = 127; - -union fp32Int32 -{ - int i; - float f; - struct _fp32Format - { - unsigned int significand : 23; - unsigned int exponent : 8; - unsigned int sign : 1; - } fmt; -}; #endif -union fp16Int16 -{ - short i; -#if ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) ) - __fp16 h; -#endif - struct _fp16Format - { - unsigned int significand : 10; - unsigned int exponent : 5; - unsigned int sign : 1; - } fmt; -}; - #if ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) ) static float convertFp16SW(short fp16) { // Fp16 -> Fp32 - fp16Int16 a; + Cv16suf a; a.i = fp16; return (float)a.h; } @@ -4407,12 +4381,12 @@ static float convertFp16SW(short fp16) static float convertFp16SW(short fp16) { // Fp16 -> Fp32 - fp16Int16 b; + Cv16suf b; b.i = fp16; int exponent = b.fmt.exponent - kBiasFp16Exponent; int significand = b.fmt.significand; - fp32Int32 a; + Cv32suf a; a.i = 0; a.fmt.sign = b.fmt.sign; // sign bit if( exponent == 16 ) @@ -4461,7 +4435,7 @@ static float convertFp16SW(short fp16) static short convertFp16SW(float fp32) { // Fp32 -> Fp16 - fp16Int16 a; + Cv16suf a; a.h = (__fp16)fp32; return a.i; } @@ -4469,12 +4443,12 @@ static short convertFp16SW(float fp32) static short convertFp16SW(float fp32) { // Fp32 -> Fp16 - fp32Int32 a; + Cv32suf a; a.f = fp32; int exponent = a.fmt.exponent - kBiasFp32Exponent; int significand = a.fmt.significand; - fp16Int16 result; + Cv16suf result; result.i = 0; unsigned int absolute = a.i & 0x7fffffff; if( 0x477ff000 <= absolute ) From b0a3b4228791fe4e3d7234dd9a24804e899ca07e Mon Sep 17 00:00:00 2001 From: kurenai Date: Thu, 25 Aug 2016 09:48:46 +0800 Subject: [PATCH 091/178] Update libpng to 1.6.24 Enable SSE optimization --- 3rdparty/libpng/CHANGES | 265 ++++++++++- 3rdparty/libpng/CMakeLists.txt | 5 + 3rdparty/libpng/LICENSE | 34 +- 3rdparty/libpng/README | 2 +- 3rdparty/libpng/arm/arm_init.c | 5 +- 3rdparty/libpng/arm/filter_neon_intrinsics.c | 18 +- 3rdparty/libpng/contrib/intel/INSTALL | 158 +++++++ .../contrib/intel/filter_sse2_intrinsics.c | 381 +++++++++++++++ 3rdparty/libpng/contrib/intel/intel_init.c | 54 +++ 3rdparty/libpng/contrib/intel/intel_sse.patch | 187 ++++++++ 3rdparty/libpng/opencv-libpng.patch | 96 +++- 3rdparty/libpng/png.c | 433 +++++++++--------- 3rdparty/libpng/png.h | 375 ++++++++++----- 3rdparty/libpng/pngconf.h | 46 +- 3rdparty/libpng/pngdebug.h | 2 +- 3rdparty/libpng/pngerror.c | 74 +-- 3rdparty/libpng/pngget.c | 70 +-- 3rdparty/libpng/pnginfo.h | 4 +- 3rdparty/libpng/pnglibconf.h | 5 +- 3rdparty/libpng/pngmem.c | 20 +- 3rdparty/libpng/pngpread.c | 43 +- 3rdparty/libpng/pngpriv.h | 100 +++- 3rdparty/libpng/pngread.c | 385 +++++++++------- 3rdparty/libpng/pngrio.c | 6 +- 3rdparty/libpng/pngrtran.c | 63 +-- 3rdparty/libpng/pngrutil.c | 231 ++++++---- 3rdparty/libpng/pngset.c | 276 +++++++---- 3rdparty/libpng/pngstruct.h | 9 +- 3rdparty/libpng/pngtrans.c | 11 +- 3rdparty/libpng/pngwio.c | 6 +- 3rdparty/libpng/pngwrite.c | 251 ++++++++-- 3rdparty/libpng/pngwtran.c | 8 +- 3rdparty/libpng/pngwutil.c | 316 +++++++------ 33 files changed, 2854 insertions(+), 1085 deletions(-) create mode 100644 3rdparty/libpng/contrib/intel/INSTALL create mode 100644 3rdparty/libpng/contrib/intel/filter_sse2_intrinsics.c create mode 100644 3rdparty/libpng/contrib/intel/intel_init.c create mode 100644 3rdparty/libpng/contrib/intel/intel_sse.patch diff --git a/3rdparty/libpng/CHANGES b/3rdparty/libpng/CHANGES index 2e4d2bb292..d4f0c8ba19 100644 --- a/3rdparty/libpng/CHANGES +++ b/3rdparty/libpng/CHANGES @@ -5063,7 +5063,8 @@ Version 1.6.15beta04 [November 4, 2014] Version 1.6.15beta05 [November 5, 2014] Use png_get_libpng_ver(NULL) instead of PNG_LIBPNG_VER_STRING in example.c, pngtest.c, and applications in the contrib directory. - Avoid out-of-bounds memory access in png_user_version_check(). + Fixed an out-of-range read in png_user_version_check() (Bug report from + Qixue Xiao, CVE-2015-8540). Simplified and future-proofed png_user_version_check(). Fixed GCC unsigned int->float warnings. Various versions of GCC seem to generate warnings when an unsigned value is implicitly @@ -5409,11 +5410,271 @@ Version 1.6.19rc03 [November 3, 2015] Version 1.6.19rc04 [November 5, 2015] Fixed new bug with CRC error after reading an over-length palette - (bug report by Cosmin Truta). + (bug report by Cosmin Truta) (CVE-2015-8126). Version 1.6.19 [November 12, 2015] Cleaned up coding style in png_handle_PLTE(). +Version 1.6.20beta01 [November 20, 2015] + Avoid potential pointer overflow/underflow in png_handle_sPLT() and + png_handle_pCAL() (Bug report by John Regehr). + +Version 1.6.20beta02 [November 23, 2015] + Fixed incorrect implementation of png_set_PLTE() that uses png_ptr + not info_ptr, that left png_set_PLTE() open to the CVE-2015-8126 + vulnerability. Fixes CVE-2015-8472. + +Version 1.6.20beta03 [November 24, 2015] + Backported tests from libpng-1.7.0beta69. + +Version 1.6.20rc01 [November 26, 2015] + Fixed an error in handling of bad zlib CMINFO field in pngfix, found by + American Fuzzy Lop, reported by Brian Carpenter. inflate() doesn't + immediately fault a bad CMINFO field; instead a 'too far back' error + happens later (at least some times). pngfix failed to limit CMINFO to + the allowed values but then assumed that window_bits was in range, + triggering an assert. The bug is mostly harmless; the PNG file cannot + be fixed. + +Version 1.6.20rc02 [November 29, 2015] + In libpng 1.6 zlib initialization was changed to use the window size + in the zlib stream, not a fixed value. This causes some invalid images, + where CINFO is too large, to display 'correctly' if the rest of the + data is valid. This provides a workaround for zlib versions where the + error arises (ones that support the API change to use the window size + in the stream). + +Version 1.6.20 [December 3, 2015] + No changes. + +Version 1.6.21beta01 [December 11, 2015] + Fixed syntax "$(command)" in tests/pngstest that some shells other than + bash could not parse (Bug report by Nelson Beebe). Use `command` instead. + +Version 1.6.21beta02 [December 14, 2015] + Moved png_check_keyword() from pngwutil.c to pngset.c + Removed LE/BE dependencies in pngvalid, to 'fix' the current problem + in the BigEndian tests by not testing it, making the BE code the same + as the LE version. + Fixes to pngvalid for various reduced build configurations (eliminate unused + statics) and a fix for the case in rgb_to_gray when the digitize option + reduces graylo to 0, producing a large error. + +Version 1.6.21beta03 [December 18, 2015] + Widened the 'limit' check on the internally calculated error limits in + the 'DIGITIZE' case (the code used prior to 1.7 for rgb_to_gray error + checks) and changed the check to only operate in non-release builds + (base build type not RC or RELEASE.) + Fixed undefined behavior in pngvalid.c, undefined because + (png_byte) << shift is undefined if it changes the signed bit + (because png_byte is promoted to int). The libpng exported functions + png_get_uint_32 and png_get_uint_16 handle this. (Bug reported by + David Drysdale as a result of reports from UBSAN in clang 3.8). + This changes pngvalid to use BE random numbers; this used to produce + errors but these should not be fixed as a result of the previous changes. + +Version 1.6.21rc01 [January 4, 2016] + In projects/vstudio, combined readme.txt and WARNING into README.txt + +Version 1.6.21rc02 [January 7, 2016] + Relocated assert() in contrib/tools/pngfix.c, bug found by American + Fuzzy Lop, reported by Brian Carpenter. + Marked 'limit' UNUSED in transform_range_check(). This only affects + release builds. + +Version 1.6.21 [January 15, 2016] + Worked around a false-positive Coverity issue in pngvalid.c. + +Version 1.6.22beta01 [January 23, 2016] + Changed PNG_USE_MKSTEMP to __COVERITY__ to select alternate + "tmpfile()" implementation in contrib/libtests/pngstest.c + Fixed NO_STDIO build of pngunknown.c to skip calling png_init_io() + if there is no stdio.h support. + Added a png_image_write_to_memory() API and a number of assist macros + to allow an application that uses the simplified API write to bypass + stdio and write directly to memory. + Added some warnings (png.h) and some check code to detect *possible* + overflow in the ROW_STRIDE and simplified image SIZE macros. This + disallows image width/height/format that *might* overflow. This is + a quiet API change that limits in-memory image size (uncompressed) to + less than 4GByte and image row size (stride) to less than 2GByte. + Revised workaround for false-positive Coverity issue in pngvalid.c. + +Version 1.6.22beta02 [February 8, 2016] + Only use exit(77) in configure builds. + Corrected error in PNG_IMAGE_PNG_SIZE_MAX. This new macro underreported + the palette size because it failed to take into account that the memory + palette has to be expanded to full RGB when it is written to PNG. + Updated CMakeLists.txt, added supporting scripts/gen*.cmake.in + and test.cmake.in (Roger Leigh). + Relaxed limit checks on gamma values in pngrtran.c. As suggested in + the comments gamma values outside the range currently permitted + by png_set_alpha_mode are useful for HDR data encoding. These values + are already permitted by png_set_gamma so it is reasonable caution to + extend the png_set_alpha_mode range as HDR imaging systems are starting + to emerge. + +Version 1.6.22beta03 [March 9, 2016] + Added a common-law trademark notice and export control information + to the LICENSE file, png.h, and the man page. + Restored "& 0xff" in png_save_uint_16() and png_save_uint_32() that + were accidentally removed from libpng-1.6.17. + Changed PNG_INFO_cHNK and PNG_FREE_cHNK from 0xnnnn to 0xnnnnU in png.h + (Robert C. Seacord). + Removed dubious "#if INT_MAX" test from png.h that was added to + libpng-1.6.19beta02 (John Bowler). + Add ${INCLUDES} in scripts/genout.cmake.in (Bug report by Nixon Kwok). + Updated LICENSE to say files in the contrib directory are not + necessarily under the libpng license, and that some makefiles have + other copyright owners. + Added INTEL-SSE2 support (Mike Klein and Matt Sarett, Google, Inc.). + Made contrib/libtests/timepng more robust. The code no longer gives + up/fails on invalid PNG data, it just skips it (with error messages). + The code no longer fails on PNG files with data beyond IEND. Options + exist to use png_read_png (reading the whole image, not by row) and, in + that case, to apply any of the supported transforms. This makes for + more realistic testing; the decoded data actually gets used in a + meaningful fashion (John Bowler). + Fixed some misleading indentation (Krishnaraj Bhat). + +Version 1.6.22beta04 [April 5, 2016] + Force GCC compilation to C89 if needed (Dagobert Michelsen). + SSE filter speed improvements for bpp=3: + memcpy-free implementations of load3() / store3(). + call load3() only when needed at the end of a scanline. + +Version 1.6.22beta05 [April 27, 2016] + Added PNG_FAST_FILTERS macro (defined as + PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_UP). + Various fixes for contrib/libtests/timepng.c + Moved INTEL-SSE code from pngpriv.h into contrib/intel/intel_sse.patch. + Fixed typo (missing underscore) in #define PNG_READ_16_TO_8_SUPPORTED + (Bug report by Y.Ohashik). + +Version 1.6.22beta06 [May 5, 2016] + Rebased contrib/intel_sse.patch. + Quieted two Coverity issues in contrib/libtests/timepng.c. + Fixed issues with scripts/genout.cmake.in (David Capello, Nixon Kwok): + Added support to use multiple directories in ZLIBINCDIR variable, + Fixed CMAKE_C_FLAGS with multiple values when genout is compiled on MSVC, + Fixed pnglibconf.c compilation on OS X including the sysroot path. + +Version 1.6.22rc01 [May 14, 2016] + No changes. + +Version 1.6.22rc02 [May 16, 2016] + Removed contrib/timepng from default build; it does not build on platforms + that don't supply clock_gettime(). + +Version 1.6.22rc03 [May 17, 2016] + Restored contrib/timepng to default build but check for the presence + of clock_gettime() in configure.ac and Makefile.am. + +Version 1.6.22 [May 26, 2016] + No changes. + +Version 1.6.23beta01 [May 29, 2016] + Stop a potential memory leak in png_set_tRNS() (Bug report by Ted Ying). + Fixed the progressive reader to handle empty first IDAT chunk properly + (patch by Timothy Nikkel). This bug was introduced in libpng-1.6.0 and + only affected the libpng16 branch. + Added tests in pngvalid.c to check zero-length IDAT chunks in various + positions. Fixed the sequential reader to handle these more robustly + (John Bowler). + +Version 1.6.23rc01 [June 2, 2016] + Corrected progressive read input buffer in pngvalid.c. The previous version + the code invariably passed just one byte at a time to libpng. The intent + was to pass a random number of bytes in the range 0..511. + Moved sse2 prototype from pngpriv.h to contrib/intel/intel_sse.patch. + Added missing ")" in pngerror.c (Matt Sarrett). + +Version 1.6.23rc02 [June 4, 2016] + Fixed undefined behavior in png_push_save_buffer(). Do not call + memcpy() with a null source, even if count is zero (Leon Scroggins III). + +Version 1.6.23 [June 9, 2016] + Fixed bad link to RFC2083 in png.5 (Nikola Forro). + +Version 1.6.24beta01 [June 11, 2016] + Avoid potential overflow of the PNG_IMAGE_SIZE macro. This macro + is not used within libpng, but is used in some of the examples. + +Version 1.6.24beta02 [June 23, 2016] + Correct filter heuristic overflow handling. This was broken when the + write filter code was moved out-of-line; if there is a single filter and + the heuristic sum overflows the calculation of the filtered line is not + completed. In versions prior to 1.6 the code was duplicated in-line + and the check not performed, so the filter operation completed; however, + in the multi-filter case where the sum is performed the 'none' filter would + be selected if all the sums overflowed, even if it wasn't in the filter + list. The fix to the first problem is simply to provide PNG_SIZE_MAX as + the current lmins sum value; this means the sum can never exceed it and + overflows silently. A reasonable compiler that does choose to inline + the code will simply eliminate the sum check. + The fix to the second problem is to use high precision arithmetic (this is + implemented in 1.7), however a simple safe fix here is to chose the lowest + numbered filter in the list from png_set_filter (this only works if the + first problem is also fixed) (John Bowler). + Use a more efficient absolute value calculation on SSE2 (Matthieu Darbois). + Fixed the case where PNG_IMAGE_BUFFER_SIZE can overflow in the application + as a result of the application using an increased 'row_stride'; previously + png_image_finish_read only checked for overflow on the base calculation of + components. (I.e. it checked for overflow of a 32-bit number on the total + number of pixel components in the output format, not the possibly padded row + length and not the number of bytes, which for linear formats is twice the + number of components.) + MSVC does not like '-(unsigned)', so replaced it with 0U-(unsigned) + MSVC does not like (uInt) = -(unsigned) (i.e. as an initializer), unless + the conversion is explicitly invoked by a cast. + Put the SKIP definition in the correct place. It needs to come after the + png.h include (see all the other .c files in contrib/libtests) because it + depends on PNG_LIBPNG_VER. + Removed the three compile warning options from the individual project + files into the zlib.props globals. It increases the warning level from 4 + to All and adds a list of the warnings that need to be turned off. This is + semi-documentary; the intent is to tell libpng users which warnings have + been examined and judged non-fixable at present. The warning about + structure padding is fixable, but it would be a signficant change (moving + structure members around). + +Version 1.6.24beta03 [July 4, 2016] + Optimized absolute value calculation in filter selection, similar to + code in the PAETH decoder in pngrutil.c. Build with PNG_USE_ABS to + use this. + Added pngcp to the build together with a pngcp.dfa configuration test. + Added high resolution timing to pngcp. + Added "Common linking failures" section to INSTALL. + Relocated misplaced #endif in png.c sRGB profile checking. + Fixed two Coverity issues in pngcp.c. + +Version 1.6.24beta04 [July 8, 2016] + Avoid filter-selection heuristic sum calculations in cases where only one + filter is a candidate for selection. This trades off code size (added + private png_setup_*_row_only() functions) for speed. + +Version 1.6.24beta05 [July 13, 2016] + Fixed some indentation to comply with our coding style. + Added contrib/tools/reindent. + +Version 1.6.24beta06 [July 18, 2016] + Fixed more indentation to comply with our coding style. + Eliminated unnecessary tests of boolean png_isaligned() vs 0. + +Version 1.6.24rc01 [July 25, 2016] + No changes. + +Version 1.6.24rc02 [August 1, 2016] + Conditionally compile SSE2 headers in contrib/intel/intel_sse.patch + Conditionally compile png_decompress_chunk(). + +Version 1.6.24rc03 [August 2, 2016] + Conditionally compile ARM_NEON headers in pngpriv.h + Updated contrib/intel/intel_sse.patch + +Version 1.6.24[August 4, 2016] + No changes. + Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement diff --git a/3rdparty/libpng/CMakeLists.txt b/3rdparty/libpng/CMakeLists.txt index fee9c99bbe..eaf2095b8a 100644 --- a/3rdparty/libpng/CMakeLists.txt +++ b/3rdparty/libpng/CMakeLists.txt @@ -33,6 +33,11 @@ if(ENABLE_NEON) add_definitions(-DPNG_ARM_NEON_OPT=2) endif() +if(ENABLE_SSE) + list(APPEND lib_srcs contrib/intel/intel_init.c contrib/intel/filter_sse2_intrinsics.c) + add_definitions(-DPNG_INTEL_SSE) +endif() + # ---------------------------------------------------------------------------------- # Define the library target: # ---------------------------------------------------------------------------------- diff --git a/3rdparty/libpng/LICENSE b/3rdparty/libpng/LICENSE index 11f6ffe5db..d20f39e2b9 100644 --- a/3rdparty/libpng/LICENSE +++ b/3rdparty/libpng/LICENSE @@ -10,8 +10,8 @@ this sentence. This code is released under the libpng license. -libpng versions 1.0.7, July 1, 2000, through 1.6.19, November 12, 2015, are -Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are +libpng versions 1.0.7, July 1, 2000 through 1.6.24, August 4, 2016 are +Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are derived from libpng-1.0.6, and are distributed according to the same disclaimer and license as libpng-1.0.6 with the following individuals added to the list of Contributing Authors: @@ -32,6 +32,10 @@ and with the following additions to the disclaimer: risk of satisfactory quality, performance, accuracy, and effort is with the user. +Some files in the "contrib" directory and some configure-generated +files that are distributed with libpng have other copyright owners and +are released under other open source licenses. + libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from libpng-0.96, and are distributed according to the same disclaimer and @@ -55,6 +59,9 @@ Contributing Authors: Greg Roelofs Tom Tanner +Some files in the "scripts" directory have other copyright owners +but are released under this license. + libpng versions 0.5, May 1995, through 0.88, January 1996, are Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -95,18 +102,29 @@ appreciated. END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. -A "png_get_copyright" function is available, for convenient use in "about" -boxes and the like: +TRADEMARK: - printf("%s", png_get_copyright(NULL)); +The name "libpng" has not been registered by the Copyright owner +as a trademark in any jurisdiction. However, because libpng has +been distributed and maintained world-wide, continually since 1995, +the Copyright owner claims "common-law trademark protection" in any +jurisdiction where common-law trademark is recognized. -Also, the PNG logo (in PNG format, of course) is supplied in the -files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). +OSI CERTIFICATION: Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a certification mark of the Open Source Initiative. OSI has not addressed the additional disclaimers inserted at version 1.0.7. +EXPORT CONTROL: + +The Copyright owner believes that the Export Control Classification +Number (ECCN) for libpng is EAR99, which means not subject to export +controls or International Traffic in Arms Regulations (ITAR) because +it is open source, publicly available software, that does not contain +any encryption software. See the EAR, paragraphs 734.3(b)(3) and +734.7(b). + Glenn Randers-Pehrson glennrp at users.sourceforge.net -November 12, 2015 +August 4, 2016 diff --git a/3rdparty/libpng/README b/3rdparty/libpng/README index 17484e0fd7..a8fba9168b 100644 --- a/3rdparty/libpng/README +++ b/3rdparty/libpng/README @@ -1,4 +1,4 @@ -README for libpng version 1.6.19 - November 12, 2015 (shared library 16.0) +README for libpng version 1.6.24 - August 4, 2016 (shared library 16.0) See the note about version numbers near the top of png.h See INSTALL for instructions on how to install libpng. diff --git a/3rdparty/libpng/arm/arm_init.c b/3rdparty/libpng/arm/arm_init.c index fb3d50d04a..02df812e77 100644 --- a/3rdparty/libpng/arm/arm_init.c +++ b/3rdparty/libpng/arm/arm_init.c @@ -1,9 +1,9 @@ /* arm_init.c - NEON optimised filter functions * - * Copyright (c) 2014 Glenn Randers-Pehrson + * Copyright (c) 2014,2016 Glenn Randers-Pehrson * Written by Mans Rullgard, 2011. - * Last changed in libpng 1.6.16 [December 22, 2014] + * Last changed in libpng 1.6.22 [May 26, 2016] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -66,6 +66,7 @@ png_init_filter_functions_neon(png_structp pp, unsigned int bpp) * wrong order of the 'ON' and 'default' cases. UNSET now defaults to OFF, * as documented in png.h */ + png_debug(1, "in png_init_filter_functions_neon"); #ifdef PNG_ARM_NEON_API_SUPPORTED switch ((pp->options >> PNG_ARM_NEON) & 3) { diff --git a/3rdparty/libpng/arm/filter_neon_intrinsics.c b/3rdparty/libpng/arm/filter_neon_intrinsics.c index d42c788909..ea7e356bcc 100644 --- a/3rdparty/libpng/arm/filter_neon_intrinsics.c +++ b/3rdparty/libpng/arm/filter_neon_intrinsics.c @@ -1,11 +1,11 @@ /* filter_neon_intrinsics.c - NEON optimised filter functions * - * Copyright (c) 2014 Glenn Randers-Pehrson + * Copyright (c) 2014,2016 Glenn Randers-Pehrson * Written by James Yu , October 2013. * Based on filter_neon.S, written by Mans Rullgard, 2011. * - * Last changed in libpng 1.6.16 [December 22, 2014] + * Last changed in libpng 1.6.22 [May 26, 2016] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -47,6 +47,8 @@ png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row, png_bytep rp_stop = row + row_info->rowbytes; png_const_bytep pp = prev_row; + png_debug(1, "in png_read_filter_row_up_neon"); + for (; rp < rp_stop; rp += 16, pp += 16) { uint8x16_t qrp, qpp; @@ -72,6 +74,8 @@ png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row, uint8x8x4_t vdest; vdest.val[3] = vdup_n_u8(0); + png_debug(1, "in png_read_filter_row_sub3_neon"); + for (; rp < rp_stop;) { uint8x8_t vtmp1, vtmp2; @@ -113,6 +117,8 @@ png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row, uint8x8x4_t vdest; vdest.val[3] = vdup_n_u8(0); + png_debug(1, "in png_read_filter_row_sub4_neon"); + for (; rp < rp_stop; rp += 16) { uint32x2x4_t vtmp = vld4_u32(png_ptr(uint32_t,rp)); @@ -148,6 +154,8 @@ png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row, vrpt = png_ptr(uint8x8x2_t,&vtmp); vrp = *vrpt; + png_debug(1, "in png_read_filter_row_avg3_neon"); + for (; rp < rp_stop; pp += 12) { uint8x8_t vtmp1, vtmp2, vtmp3; @@ -207,6 +215,8 @@ png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row, uint8x8x4_t vdest; vdest.val[3] = vdup_n_u8(0); + png_debug(1, "in png_read_filter_row_avg4_neon"); + for (; rp < rp_stop; rp += 16, pp += 16) { uint32x2x4_t vtmp; @@ -280,6 +290,8 @@ png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row, vrpt = png_ptr(uint8x8x2_t,&vtmp); vrp = *vrpt; + png_debug(1, "in png_read_filter_row_paeth3_neon"); + for (; rp < rp_stop; pp += 12) { uint8x8x2_t *vppt; @@ -339,6 +351,8 @@ png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row, uint8x8x4_t vdest; vdest.val[3] = vdup_n_u8(0); + png_debug(1, "in png_read_filter_row_paeth4_neon"); + for (; rp < rp_stop; rp += 16, pp += 16) { uint32x2x4_t vtmp; diff --git a/3rdparty/libpng/contrib/intel/INSTALL b/3rdparty/libpng/contrib/intel/INSTALL new file mode 100644 index 0000000000..cd5cdd94eb --- /dev/null +++ b/3rdparty/libpng/contrib/intel/INSTALL @@ -0,0 +1,158 @@ +Enabling SSE support + +Copyright (c) 2016 Google, Inc. +Written by Mike Klein, Matt Sarett + +This INSTALL file written by Glenn Randers-Pehrson, 2016. + +If you have moved intel_init.c and filter_sse2_intrinsics.c to a different +directory, be sure to update the '#include "../../pngpriv.h"' line in both +files if necessary to point to the correct relative location of pngpriv.h +with respect to the new location of those files. + +To enable SSE support in libpng, follow the instructions in I, II, or III, +below: + +I. Using patched "configure" scripts: + +First, apply intel_sse.patch in your build directory. + + patch -i contrib/intel/intel_sse.patch -p1 + +Then, if you are not building in a new GIT clone, e.g., in a tar +distribution, remove any existing pre-built configure scripts: + + ./configure --enable-maintainer-mode + make maintainer-clean + ./autogen.sh --maintainer --clean + +Finally, configure libpng with -DPNG_INTEL_SSE in CPPFLAGS: + + ./autogen.sh --maintainer + CPPFLAGS="-DPNG_INTEL_SSE" ./configure [options] + make CPPFLAGS="-DPNG_INTEL_SSE" [options] + make + +II. Using a custom makefile: + +If you are using a custom makefile makefile, you will have to update it +manually to include contrib/intel/*.o in the dependencies, and to define +PNG_INTEL_SSE. + +III. Using manually updated "configure" scripts: + +If you prefer, manually edit pngpriv.h, configure.ac, and Makefile.am, +following the instructions below, then follow the instructions in +section II of INSTALL in the main libpng directory, then configure libpng +with -DPNG_INTEL_SSE in CPPFLAGS. + +1. Add the following code to configure.ac under HOST SPECIFIC OPTIONS +directly beneath the section for ARM: + +-----------------cut---------------- +# INTEL +# ===== +# +# INTEL SSE (SIMD) support. + +AC_ARG_ENABLE([intel-sse], + AS_HELP_STRING([[[--enable-intel-sse]]], + [Enable Intel SSE optimizations: =no/off, yes/on:] + [no/off: disable the optimizations;] + [yes/on: enable the optimizations.] + [If not specified: determined by the compiler.]), + [case "$enableval" in + no|off) + # disable the default enabling: + AC_DEFINE([PNG_INTEL_SSE_OPT], [0], + [Disable Intel SSE optimizations]) + # Prevent inclusion of the assembler files below: + enable_intel_sse=no;; + yes|on) + AC_DEFINE([PNG_INTEL_SSE_OPT], [1], + [Enable Intel SSE optimizations]);; + *) + AC_MSG_ERROR([--enable-intel-sse=${enable_intel_sse}: invalid value]) + esac]) + +# Add Intel specific files to all builds where the host_cpu is Intel ('x86*') +# or where Intel optimizations were explicitly requested (this allows a +# fallback if a future host CPU does not match 'x86*') +AM_CONDITIONAL([PNG_INTEL_SSE], + [test "$enable_intel_sse" != 'no' && + case "$host_cpu" in + i?86|x86_64) :;; + *) test "$enable_intel_sse" != '';; + esac]) +-----------------cut---------------- + +2. Add the following code to Makefile.am under HOST SPECIFIC OPTIONS +directly beneath the "if PNG_ARM_NEON ... endif" statement: + +-----------------cut---------------- +if PNG_INTEL_SSE +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += contrib/intel/intel_init.c\ + contrib/intel/filter_sse2_intrinsics.c +endif +-----------------cut---------------- + +3. Add the following lines to pngpriv.h, following the PNG_ARM_NEON_OPT +code: + +-----------------cut---------------- +#ifndef PNG_INTEL_SSE_OPT +# ifdef PNG_INTEL_SSE + /* Only check for SSE if the build configuration has been modified to + * enable SSE optimizations. This means that these optimizations will + * be off by default. See contrib/intel for more details. + */ +# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \ + defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ + (defined(_M_IX86_FP) && _M_IX86_FP >= 2) +# define PNG_INTEL_SSE_OPT 1 +# endif +# endif +#endif + +#if PNG_INTEL_SSE_OPT > 0 +# ifndef PNG_INTEL_SSE_IMPLEMENTATION +# if defined(__SSE4_1__) || defined(__AVX__) + /* We are not actually using AVX, but checking for AVX is the best + way we can detect SSE4.1 and SSSE3 on MSVC. + */ +# define PNG_INTEL_SSE_IMPLEMENTATION 3 +# elif defined(__SSSE3__) +# define PNG_INTEL_SSE_IMPLEMENTATION 2 +# elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ + (defined(_M_IX86_FP) && _M_IX86_FP >= 2) +# define PNG_INTEL_SSE_IMPLEMENTATION 1 +# else +# define PNG_INTEL_SSE_IMPLEMENTATION 0 +# endif +# endif + +# if PNG_INTEL_SSE_IMPLEMENTATION > 0 +# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2 +# endif +#endif + +-----------------cut---------------- + +4. Add the following lines to pngpriv.h, following the prototype for +png_read_filter_row_paeth4_neon: + +-----------------cut---------------- +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); + +-----------------cut---------------- diff --git a/3rdparty/libpng/contrib/intel/filter_sse2_intrinsics.c b/3rdparty/libpng/contrib/intel/filter_sse2_intrinsics.c new file mode 100644 index 0000000000..2bde138719 --- /dev/null +++ b/3rdparty/libpng/contrib/intel/filter_sse2_intrinsics.c @@ -0,0 +1,381 @@ + +/* filter_sse2_intrinsics.c - SSE2 optimized filter functions + * + * Copyright (c) 2016 Google, Inc. + * Written by Mike Klein and Matt Sarett + * Derived from arm/filter_neon_intrinsics.c, which was + * Copyright (c) 2014,2016 Glenn Randers-Pehrson + * + * Last changed in libpng 1.6.24 [August 4, 2016] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "../../pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +#if PNG_INTEL_SSE_IMPLEMENTATION > 0 + +#include + +/* Functions in this file look at most 3 pixels (a,b,c) to predict the 4th (d). + * They're positioned like this: + * prev: c b + * row: a d + * The Sub filter predicts d=a, Avg d=(a+b)/2, and Paeth predicts d to be + * whichever of a, b, or c is closest to p=a+b-c. + */ + +static __m128i load4(const void* p) { + return _mm_cvtsi32_si128(*(const int*)p); +} + +static void store4(void* p, __m128i v) { + *(int*)p = _mm_cvtsi128_si32(v); +} + +static __m128i load3(const void* p) { + /* We'll load 2 bytes, then 1 byte, + * then mask them together, and finally load into SSE. + */ + const png_uint_16* p01 = p; + const png_byte* p2 = (const png_byte*)(p01+1); + + png_uint_32 v012 = (png_uint_32)(*p01) + | (png_uint_32)(*p2) << 16; + return load4(&v012); +} + +static void store3(void* p, __m128i v) { + /* We'll pull from SSE as a 32-bit int, then write + * its bottom two bytes, then its third byte. + */ + png_uint_32 v012; + store4(&v012, v); + + png_uint_16* p01 = p; + png_byte* p2 = (png_byte*)(p01+1); + *p01 = v012; + *p2 = v012 >> 16; +} + +void png_read_filter_row_sub3_sse2(png_row_infop row_info, png_bytep row, + png_const_bytep prev) +{ + /* The Sub filter predicts each pixel as the previous pixel, a. + * There is no pixel to the left of the first pixel. It's encoded directly. + * That works with our main loop if we just say that left pixel was zero. + */ + (void) prev; //unused parameter + png_debug(1, "in png_read_filter_row_sub3_sse2"); + __m128i a, d = _mm_setzero_si128(); + + png_size_t rb = row_info->rowbytes; + while (rb >= 4) { + a = d; d = load4(row); + d = _mm_add_epi8(d, a); + store3(row, d); + + row += 3; + rb -= 3; + } + if (rb > 0) { + a = d; d = load3(row); + d = _mm_add_epi8(d, a); + store3(row, d); + + row += 3; + rb -= 3; + } +} + +void png_read_filter_row_sub4_sse2(png_row_infop row_info, png_bytep row, + png_const_bytep prev) +{ + /* The Sub filter predicts each pixel as the previous pixel, a. + * There is no pixel to the left of the first pixel. It's encoded directly. + * That works with our main loop if we just say that left pixel was zero. + */ + (void) prev; //unused parameter + png_debug(1, "in png_read_filter_row_sub4_sse2"); + __m128i a, d = _mm_setzero_si128(); + + png_size_t rb = row_info->rowbytes; + while (rb > 0) { + a = d; d = load4(row); + d = _mm_add_epi8(d, a); + store4(row, d); + + row += 4; + rb -= 4; + } +} + +void png_read_filter_row_avg3_sse2(png_row_infop row_info, png_bytep row, + png_const_bytep prev) +{ + /* The Avg filter predicts each pixel as the (truncated) average of a and b. + * There's no pixel to the left of the first pixel. Luckily, it's + * predicted to be half of the pixel above it. So again, this works + * perfectly with our loop if we make sure a starts at zero. + */ + png_debug(1, "in png_read_filter_row_avg3_sse2"); + const __m128i zero = _mm_setzero_si128(); + __m128i b; + __m128i a, d = zero; + + png_size_t rb = row_info->rowbytes; + while (rb >= 4) { + b = load4(prev); + a = d; d = load4(row ); + + /* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */ + __m128i avg = _mm_avg_epu8(a,b); + /* ...but we can fix it up by subtracting off 1 if it rounded up. */ + avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b), + _mm_set1_epi8(1))); + d = _mm_add_epi8(d, avg); + store3(row, d); + + prev += 3; + row += 3; + rb -= 3; + } + if (rb > 0) { + b = load3(prev); + a = d; d = load3(row ); + + /* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */ + __m128i avg = _mm_avg_epu8(a,b); + /* ...but we can fix it up by subtracting off 1 if it rounded up. */ + avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b), + _mm_set1_epi8(1))); + + d = _mm_add_epi8(d, avg); + store3(row, d); + + prev += 3; + row += 3; + rb -= 3; + } +} + +void png_read_filter_row_avg4_sse2(png_row_infop row_info, png_bytep row, + png_const_bytep prev) +{ + /* The Avg filter predicts each pixel as the (truncated) average of a and b. + * There's no pixel to the left of the first pixel. Luckily, it's + * predicted to be half of the pixel above it. So again, this works + * perfectly with our loop if we make sure a starts at zero. + */ + png_debug(1, "in png_read_filter_row_avg4_sse2"); + const __m128i zero = _mm_setzero_si128(); + __m128i b; + __m128i a, d = zero; + + png_size_t rb = row_info->rowbytes; + while (rb > 0) { + b = load4(prev); + a = d; d = load4(row ); + + /* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */ + __m128i avg = _mm_avg_epu8(a,b); + /* ...but we can fix it up by subtracting off 1 if it rounded up. */ + avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b), + _mm_set1_epi8(1))); + + d = _mm_add_epi8(d, avg); + store4(row, d); + + prev += 4; + row += 4; + rb -= 4; + } +} + +/* Returns |x| for 16-bit lanes. */ +static __m128i abs_i16(__m128i x) { +#if PNG_INTEL_SSE_IMPLEMENTATION >= 2 + return _mm_abs_epi16(x); +#else + /* Read this all as, return x<0 ? -x : x. + * To negate two's complement, you flip all the bits then add 1. + */ + __m128i is_negative = _mm_cmplt_epi16(x, _mm_setzero_si128()); + + /* Flip negative lanes. */ + x = _mm_xor_si128(x, is_negative); + + /* +1 to negative lanes, else +0. */ + x = _mm_sub_epi16(x, is_negative); + return x; +#endif +} + +/* Bytewise c ? t : e. */ +static __m128i if_then_else(__m128i c, __m128i t, __m128i e) { +#if PNG_INTEL_SSE_IMPLEMENTATION >= 3 + return _mm_blendv_epi8(e,t,c); +#else + return _mm_or_si128(_mm_and_si128(c, t), _mm_andnot_si128(c, e)); +#endif +} + +void png_read_filter_row_paeth3_sse2(png_row_infop row_info, png_bytep row, + png_const_bytep prev) +{ + /* Paeth tries to predict pixel d using the pixel to the left of it, a, + * and two pixels from the previous row, b and c: + * prev: c b + * row: a d + * The Paeth function predicts d to be whichever of a, b, or c is nearest to + * p=a+b-c. + * + * The first pixel has no left context, and so uses an Up filter, p = b. + * This works naturally with our main loop's p = a+b-c if we force a and c + * to zero. + * Here we zero b and d, which become c and a respectively at the start of + * the loop. + */ + png_debug(1, "in png_read_filter_row_paeth3_sse2"); + const __m128i zero = _mm_setzero_si128(); + __m128i c, b = zero, + a, d = zero; + + png_size_t rb = row_info->rowbytes; + while (rb >= 4) { + /* It's easiest to do this math (particularly, deal with pc) with 16-bit + * intermediates. + */ + c = b; b = _mm_unpacklo_epi8(load4(prev), zero); + a = d; d = _mm_unpacklo_epi8(load4(row ), zero); + + /* (p-a) == (a+b-c - a) == (b-c) */ + __m128i pa = _mm_sub_epi16(b,c); + + /* (p-b) == (a+b-c - b) == (a-c) */ + __m128i pb = _mm_sub_epi16(a,c); + + /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */ + __m128i pc = _mm_add_epi16(pa,pb); + + pa = abs_i16(pa); /* |p-a| */ + pb = abs_i16(pb); /* |p-b| */ + pc = abs_i16(pc); /* |p-c| */ + + __m128i smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); + + /* Paeth breaks ties favoring a over b over c. */ + __m128i nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a, + if_then_else(_mm_cmpeq_epi16(smallest, pb), b, + c)); + + /* Note `_epi8`: we need addition to wrap modulo 255. */ + d = _mm_add_epi8(d, nearest); + store3(row, _mm_packus_epi16(d,d)); + + prev += 3; + row += 3; + rb -= 3; + } + if (rb > 0) { + /* It's easiest to do this math (particularly, deal with pc) with 16-bit + * intermediates. + */ + c = b; b = _mm_unpacklo_epi8(load3(prev), zero); + a = d; d = _mm_unpacklo_epi8(load3(row ), zero); + + /* (p-a) == (a+b-c - a) == (b-c) */ + __m128i pa = _mm_sub_epi16(b,c); + + /* (p-b) == (a+b-c - b) == (a-c) */ + __m128i pb = _mm_sub_epi16(a,c); + + /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */ + __m128i pc = _mm_add_epi16(pa,pb); + + pa = abs_i16(pa); /* |p-a| */ + pb = abs_i16(pb); /* |p-b| */ + pc = abs_i16(pc); /* |p-c| */ + + __m128i smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); + + /* Paeth breaks ties favoring a over b over c. */ + __m128i nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a, + if_then_else(_mm_cmpeq_epi16(smallest, pb), b, + c)); + + /* Note `_epi8`: we need addition to wrap modulo 255. */ + d = _mm_add_epi8(d, nearest); + store3(row, _mm_packus_epi16(d,d)); + + prev += 3; + row += 3; + rb -= 3; + } +} + +void png_read_filter_row_paeth4_sse2(png_row_infop row_info, png_bytep row, + png_const_bytep prev) +{ + /* Paeth tries to predict pixel d using the pixel to the left of it, a, + * and two pixels from the previous row, b and c: + * prev: c b + * row: a d + * The Paeth function predicts d to be whichever of a, b, or c is nearest to + * p=a+b-c. + * + * The first pixel has no left context, and so uses an Up filter, p = b. + * This works naturally with our main loop's p = a+b-c if we force a and c + * to zero. + * Here we zero b and d, which become c and a respectively at the start of + * the loop. + */ + png_debug(1, "in png_read_filter_row_paeth4_sse2"); + const __m128i zero = _mm_setzero_si128(); + __m128i c, b = zero, + a, d = zero; + + png_size_t rb = row_info->rowbytes; + while (rb > 0) { + /* It's easiest to do this math (particularly, deal with pc) with 16-bit + * intermediates. + */ + c = b; b = _mm_unpacklo_epi8(load4(prev), zero); + a = d; d = _mm_unpacklo_epi8(load4(row ), zero); + + /* (p-a) == (a+b-c - a) == (b-c) */ + __m128i pa = _mm_sub_epi16(b,c); + + /* (p-b) == (a+b-c - b) == (a-c) */ + __m128i pb = _mm_sub_epi16(a,c); + + /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */ + __m128i pc = _mm_add_epi16(pa,pb); + + pa = abs_i16(pa); /* |p-a| */ + pb = abs_i16(pb); /* |p-b| */ + pc = abs_i16(pc); /* |p-c| */ + + __m128i smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); + + /* Paeth breaks ties favoring a over b over c. */ + __m128i nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a, + if_then_else(_mm_cmpeq_epi16(smallest, pb), b, + c)); + + /* Note `_epi8`: we need addition to wrap modulo 255. */ + d = _mm_add_epi8(d, nearest); + store4(row, _mm_packus_epi16(d,d)); + + prev += 4; + row += 4; + rb -= 4; + } +} + +#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */ +#endif /* READ */ diff --git a/3rdparty/libpng/contrib/intel/intel_init.c b/3rdparty/libpng/contrib/intel/intel_init.c new file mode 100644 index 0000000000..328e90e9af --- /dev/null +++ b/3rdparty/libpng/contrib/intel/intel_init.c @@ -0,0 +1,54 @@ + +/* intel_init.c - SSE2 optimized filter functions + * + * Copyright (c) 2016 Google, Inc. + * Written by Mike Klein and Matt Sarett + * Derived from arm/arm_init.c, which was + * Copyright (c) 2014,2016 Glenn Randers-Pehrson + * + * Last changed in libpng 1.6.22 [May 26, 2016] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "../../pngpriv.h" + +#ifdef PNG_READ_SUPPORTED +#if PNG_INTEL_SSE_IMPLEMENTATION > 0 + +void +png_init_filter_functions_sse2(png_structp pp, unsigned int bpp) +{ + /* The techniques used to implement each of these filters in SSE operate on + * one pixel at a time. + * So they generally speed up 3bpp images about 3x, 4bpp images about 4x. + * They can scale up to 6 and 8 bpp images and down to 2 bpp images, + * but they'd not likely have any benefit for 1bpp images. + * Most of these can be implemented using only MMX and 64-bit registers, + * but they end up a bit slower than using the equally-ubiquitous SSE2. + */ + png_debug(1, "in png_init_filter_functions_sse2"); + if (bpp == 3) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_sse2; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_sse2; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth3_sse2; + } + else if (bpp == 4) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_sse2; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_sse2; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth4_sse2; + } + + /* No need optimize PNG_FILTER_VALUE_UP. The compiler should + * autovectorize. + */ +} + +#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/3rdparty/libpng/contrib/intel/intel_sse.patch b/3rdparty/libpng/contrib/intel/intel_sse.patch new file mode 100644 index 0000000000..c5579e3abd --- /dev/null +++ b/3rdparty/libpng/contrib/intel/intel_sse.patch @@ -0,0 +1,187 @@ +diff --git a/configure.ac b/configure.ac +--- a/configure.ac 2016-05-25 18:59:10.000000000 -0400 ++++ b/configure.ac 2016-05-25 19:48:10.631751170 -0400 +@@ -341,16 +341,50 @@ AC_ARG_ENABLE([arm-neon], + + AM_CONDITIONAL([PNG_ARM_NEON], + [test "$enable_arm_neon" != 'no' && + case "$host_cpu" in + arm*|aarch64*) :;; + *) test "$enable_arm_neon" != '';; + esac]) + ++# INTEL ++# ===== ++# ++# INTEL SSE (SIMD) support. ++ ++AC_ARG_ENABLE([intel-sse], ++ AS_HELP_STRING([[[--enable-intel-sse]]], ++ [Enable Intel SSE optimizations: =no/off, yes/on:] ++ [no/off: disable the optimizations;] ++ [yes/on: enable the optimizations.] ++ [If not specified: determined by the compiler.]), ++ [case "$enableval" in ++ no|off) ++ # disable the default enabling: ++ AC_DEFINE([PNG_INTEL_SSE_OPT], [0], ++ [Disable Intel SSE optimizations]) ++ # Prevent inclusion of the assembler files below: ++ enable_intel_sse=no;; ++ yes|on) ++ AC_DEFINE([PNG_INTEL_SSE_OPT], [1], ++ [Enable Intel SSE optimizations]);; ++ *) ++ AC_MSG_ERROR([--enable-intel-sse=${enable_intel_sse}: invalid value]) ++ esac]) ++ ++# Add Intel specific files to all builds where the host_cpu is Intel ('x86*') ++# or where Intel optimizations were explicitly requested (this allows a ++# fallback if a future host CPU does not match 'x86*') ++AM_CONDITIONAL([PNG_INTEL_SSE], ++ [test "$enable_intel_sse" != 'no' && ++ case "$host_cpu" in ++ i?86|x86_64) :;; ++ *) test "$enable_intel_sse" != '';; ++ esac]) + AC_MSG_NOTICE([[Extra options for compiler: $PNG_COPTS]]) + + # Config files, substituting as above + AC_CONFIG_FILES([Makefile libpng.pc:libpng.pc.in]) + AC_CONFIG_FILES([libpng-config:libpng-config.in], + [chmod +x libpng-config]) + + AC_OUTPUT +diff --git a/Makefile.am b/Makefile.am +--- a/Makefile.am 2016-05-17 18:15:12.000000000 -0400 ++++ b/Makefile.am 2016-05-25 19:48:10.631751170 -0400 +@@ -92,16 +92,20 @@ libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SO + pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\ + png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h pngusr.dfa + + if PNG_ARM_NEON + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += arm/arm_init.c\ + arm/filter_neon.S arm/filter_neon_intrinsics.c + endif + ++if PNG_INTEL_SSE ++libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += contrib/intel/intel_init.c\ ++ contrib/intel/filter_sse2_intrinsics.c ++endif + nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h + + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS = -no-undefined -export-dynamic \ + -version-number @PNGLIB_MAJOR@@PNGLIB_MINOR@:@PNGLIB_RELEASE@:0 + + if HAVE_LD_VERSION_SCRIPT + # Versioned symbols and restricted exports + if HAVE_SOLARIS_LD +diff --git a/pngpriv.h b/pngpriv.h +--- a/pngpriv.h 2016-08-01 18:13:38.770128810 -0500 ++++ b/pngpriv.h 2016-08-01 18:50:19.130179017 -0500 +@@ -177,16 +177,52 @@ + # endif /* !PNG_ARM_NEON_IMPLEMENTATION */ + + # ifndef PNG_ARM_NEON_IMPLEMENTATION + /* Use the intrinsics code by default. */ + # define PNG_ARM_NEON_IMPLEMENTATION 1 + # endif + #endif /* PNG_ARM_NEON_OPT > 0 */ + ++#ifndef PNG_INTEL_SSE_OPT ++# ifdef PNG_INTEL_SSE ++ /* Only check for SSE if the build configuration has been modified to ++ * enable SSE optimizations. This means that these optimizations will ++ * be off by default. See contrib/intel for more details. ++ */ ++# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \ ++ defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ ++ (defined(_M_IX86_FP) && _M_IX86_FP >= 2) ++# define PNG_INTEL_SSE_OPT 1 ++# endif ++# endif ++#endif ++ ++#if PNG_INTEL_SSE_OPT > 0 ++# ifndef PNG_INTEL_SSE_IMPLEMENTATION ++# if defined(__SSE4_1__) || defined(__AVX__) ++ /* We are not actually using AVX, but checking for AVX is the best ++ way we can detect SSE4.1 and SSSE3 on MSVC. ++ */ ++# define PNG_INTEL_SSE_IMPLEMENTATION 3 ++# elif defined(__SSSE3__) ++# define PNG_INTEL_SSE_IMPLEMENTATION 2 ++# elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ ++ (defined(_M_IX86_FP) && _M_IX86_FP >= 2) ++# define PNG_INTEL_SSE_IMPLEMENTATION 1 ++# else ++# define PNG_INTEL_SSE_IMPLEMENTATION 0 ++# endif ++# endif ++ ++# if PNG_INTEL_SSE_IMPLEMENTATION > 0 ++# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2 ++# endif ++#endif ++ + /* Is this a build of a DLL where compilation of the object modules requires + * different preprocessor settings to those required for a simple library? If + * so PNG_BUILD_DLL must be set. + * + * If libpng is used inside a DLL but that DLL does not export the libpng APIs + * PNG_BUILD_DLL must not be set. To avoid the code below kicking in build a + * static library of libpng then link the DLL against that. + */ +@@ -1185,16 +1221,31 @@ PNG_INTERNAL_FUNCTION(void,png_read_filt + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); + PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); + PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); + PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); + #endif ++ ++#if PNG_INTEL_SSE_IMPLEMENTATION > 0 ++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop ++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop ++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop ++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop ++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop ++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop ++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); ++#endif + + /* Choose the best filter to use and filter the row data */ + PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr, + png_row_infop row_info),PNG_EMPTY); + + #ifdef PNG_SEQUENTIAL_READ_SUPPORTED + PNG_INTERNAL_FUNCTION(void,png_read_IDAT_data,(png_structrp png_ptr, + png_bytep output, png_alloc_size_t avail_out),PNG_EMPTY); +@@ -1914,16 +1965,20 @@ PNG_INTERNAL_FUNCTION(void, PNG_FILTER_O + /* List *all* the possible optimizations here - this branch is required if + * the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in + * CFLAGS in place of CPPFLAGS *and* uses symbol prefixing. + */ + # if PNG_ARM_NEON_OPT > 0 + PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, + (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); + # endif ++# if PNG_INTEL_SSE_IMPLEMENTATION > 0 ++PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, ++ (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); ++# endif + #endif + + PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr, + png_const_charp key, png_bytep new_key), PNG_EMPTY); + + /* Maintainer: Put new private prototypes here ^ */ + + #include "pngdebug.h" diff --git a/3rdparty/libpng/opencv-libpng.patch b/3rdparty/libpng/opencv-libpng.patch index 9fac20355e..b76f87c523 100644 --- a/3rdparty/libpng/opencv-libpng.patch +++ b/3rdparty/libpng/opencv-libpng.patch @@ -1,6 +1,67 @@ +diff --git a/3rdparty/libpng/CMakeLists.txt b/3rdparty/libpng/CMakeLists.txt +index fee9c99..eaf2095 100644 +--- a/3rdparty/libpng/CMakeLists.txt ++++ b/3rdparty/libpng/CMakeLists.txt +@@ -33,6 +33,11 @@ if(ENABLE_NEON) + add_definitions(-DPNG_ARM_NEON_OPT=2) + endif() + ++if(ENABLE_SSE) ++ list(APPEND lib_srcs contrib/intel/intel_init.c contrib/intel/filter_sse2_intrinsics.c) ++ add_definitions(-DPNG_INTEL_SSE) ++endif() ++ + # ---------------------------------------------------------------------------------- + # Define the library target: + # ---------------------------------------------------------------------------------- +diff --git a/3rdparty/libpng/pngpriv.h b/3rdparty/libpng/pngpriv.h +index fe3355d..c0aa785 100644 --- a/3rdparty/libpng/pngpriv.h +++ b/3rdparty/libpng/pngpriv.h -@@ -457,7 +457,7 @@ +@@ -182,6 +182,42 @@ + # endif + #endif /* PNG_ARM_NEON_OPT > 0 */ + ++#ifndef PNG_INTEL_SSE_OPT ++# ifdef PNG_INTEL_SSE ++ /* Only check for SSE if the build configuration has been modified to ++ * enable SSE optimizations. This means that these optimizations will ++ * be off by default. See contrib/intel for more details. ++ */ ++# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \ ++ defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ ++ (defined(_M_IX86_FP) && _M_IX86_FP >= 2) ++# define PNG_INTEL_SSE_OPT 1 ++# endif ++# endif ++#endif ++ ++#if defined(PNG_INTEL_SSE_OPT) && PNG_INTEL_SSE_OPT > 0 ++# ifndef PNG_INTEL_SSE_IMPLEMENTATION ++# if defined(__SSE4_1__) || defined(__AVX__) ++ /* We are not actually using AVX, but checking for AVX is the best ++ way we can detect SSE4.1 and SSSE3 on MSVC. ++ */ ++# define PNG_INTEL_SSE_IMPLEMENTATION 3 ++# elif defined(__SSSE3__) ++# define PNG_INTEL_SSE_IMPLEMENTATION 2 ++# elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ ++ (defined(_M_IX86_FP) && _M_IX86_FP >= 2) ++# define PNG_INTEL_SSE_IMPLEMENTATION 1 ++# else ++# define PNG_INTEL_SSE_IMPLEMENTATION 0 ++# endif ++# endif ++ ++# if PNG_INTEL_SSE_IMPLEMENTATION > 0 ++# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2 ++# endif ++#endif ++ + /* Is this a build of a DLL where compilation of the object modules requires + * different preprocessor settings to those required for a simple library? If + * so PNG_BUILD_DLL must be set. +@@ -457,7 +493,7 @@ /* Memory model/platform independent fns */ #ifndef PNG_ABORT @@ -9,3 +70,36 @@ # define PNG_ABORT() ExitProcess(0) # else # define PNG_ABORT() abort() +@@ -1190,6 +1226,21 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop + PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); + #endif ++ ++#if defined(PNG_INTEL_SSE_IMPLEMENTATION) && PNG_INTEL_SSE_IMPLEMENTATION > 0 ++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop ++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop ++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop ++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop ++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop ++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop ++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); ++#endif + + /* Choose the best filter to use and filter the row data */ + PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr, +@@ -1919,6 +1970,10 @@ PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr, + PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, + (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); + # endif ++# if defined(PNG_INTEL_SSE_IMPLEMENTATION) && PNG_INTEL_SSE_IMPLEMENTATION > 0 ++PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, ++ (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); ++# endif + #endif + + PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr, diff --git a/3rdparty/libpng/png.c b/3rdparty/libpng/png.c index 6fcfad72ec..0843ebbc26 100644 --- a/3rdparty/libpng/png.c +++ b/3rdparty/libpng/png.c @@ -1,8 +1,8 @@ /* png.c - location for general purpose libpng functions * - * Last changed in libpng 1.6.19 [November 12, 2015] - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -14,7 +14,7 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_19 Your_png_h_is_not_version_1_6_19; +typedef png_libpng_version_1_6_24 Your_png_h_is_not_version_1_6_24; /* Tells libpng that we have already handled the first "num_bytes" bytes * of the PNG file signature. If the PNG data is embedded into another @@ -85,7 +85,7 @@ png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED) if (items >= (~(png_alloc_size_t)0)/size) { png_warning (png_voidcast(png_structrp, png_ptr), - "Potential overflow in png_zalloc()"); + "Potential overflow in png_zalloc()"); return NULL; } @@ -172,10 +172,10 @@ png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length) int png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver) { - /* Libpng versions 1.0.0 and later are binary compatible if the version - * string matches through the second '.'; we must recompile any - * applications that use any older library version. - */ + /* Libpng versions 1.0.0 and later are binary compatible if the version + * string matches through the second '.'; we must recompile any + * applications that use any older library version. + */ if (user_png_ver != NULL) { @@ -297,7 +297,7 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, if (png_user_version_check(&create_struct, user_png_ver) != 0) { png_structrp png_ptr = png_voidcast(png_structrp, - png_malloc_warn(&create_struct, (sizeof *png_ptr))); + png_malloc_warn(&create_struct, (sizeof *png_ptr))); if (png_ptr != NULL) { @@ -346,7 +346,7 @@ png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED) * has always been done in 'example.c'. */ info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr, - (sizeof *info_ptr))); + (sizeof *info_ptr))); if (info_ptr != NULL) memset(info_ptr, 0, (sizeof *info_ptr)); @@ -402,7 +402,7 @@ png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr) */ PNG_FUNCTION(void,PNGAPI png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), - PNG_DEPRECATED) + PNG_DEPRECATED) { png_inforp info_ptr = *ptr_ptr; @@ -417,7 +417,7 @@ png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), /* The following line is why this API should not be used: */ free(info_ptr); info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL, - (sizeof *info_ptr))); + (sizeof *info_ptr))); if (info_ptr == NULL) return; *ptr_ptr = info_ptr; @@ -430,7 +430,7 @@ png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), /* The following API is not called internally */ void PNGAPI png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr, - int freer, png_uint_32 mask) + int freer, png_uint_32 mask) { png_debug(1, "in png_data_freer"); @@ -449,7 +449,7 @@ png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr, void PNGAPI png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, - int num) + int num) { png_debug(1, "in png_free_data"); @@ -775,14 +775,15 @@ png_get_copyright(png_const_structrp png_ptr) #else # ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.6.19 - November 12, 2015" PNG_STRING_NEWLINE \ - "Copyright (c) 1998-2015 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ + "libpng version 1.6.24 - August 4, 2016" PNG_STRING_NEWLINE \ + "Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson" \ + PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE; # else - return "libpng version 1.6.19 - November 12, 2015\ - Copyright (c) 1998-2015 Glenn Randers-Pehrson\ + return "libpng version 1.6.24 - August 4, 2016\ + Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson\ Copyright (c) 1996-1997 Andreas Dilger\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; # endif @@ -1032,7 +1033,7 @@ png_zstream_error(png_structrp png_ptr, int ret) #ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */ static int png_colorspace_check_gamma(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_fixed_point gAMA, int from) + png_colorspacerp colorspace, png_fixed_point gAMA, int from) /* This is called to check a new gamma value against an existing one. The * routine returns false if the new gamma value should not be written. * @@ -1046,7 +1047,7 @@ png_colorspace_check_gamma(png_const_structrp png_ptr, png_fixed_point gtest; if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 && - (png_muldiv(>est, colorspace->gamma, PNG_FP_1, gAMA) == 0 || + (png_muldiv(>est, colorspace->gamma, PNG_FP_1, gAMA) == 0 || png_gamma_significant(gtest) != 0)) { /* Either this is an sRGB image, in which case the calculated gamma @@ -1058,7 +1059,7 @@ png_colorspace_check_gamma(png_const_structrp png_ptr, if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2) { png_chunk_report(png_ptr, "gamma value does not match sRGB", - PNG_CHUNK_ERROR); + PNG_CHUNK_ERROR); /* Do not overwrite an sRGB value */ return from == 2; } @@ -1066,7 +1067,7 @@ png_colorspace_check_gamma(png_const_structrp png_ptr, else /* sRGB tag not involved */ { png_chunk_report(png_ptr, "gamma value does not match libpng estimate", - PNG_CHUNK_WARNING); + PNG_CHUNK_WARNING); return from == 1; } } @@ -1076,7 +1077,7 @@ png_colorspace_check_gamma(png_const_structrp png_ptr, void /* PRIVATE */ png_colorspace_set_gamma(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_fixed_point gAMA) + png_colorspacerp colorspace, png_fixed_point gAMA) { /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't * occur. Since the fixed point representation is asymetrical it is @@ -1634,8 +1635,8 @@ static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */ static int png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr, - png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ, - int preferred) + png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ, + int preferred) { if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) return 0; @@ -1682,7 +1683,7 @@ png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr, int /* PRIVATE */ png_colorspace_set_chromaticities(png_const_structrp png_ptr, - png_colorspacerp colorspace, const png_xy *xy, int preferred) + png_colorspacerp colorspace, const png_xy *xy, int preferred) { /* We must check the end points to ensure they are reasonable - in the past * color management systems have crashed as a result of getting bogus @@ -1696,7 +1697,7 @@ png_colorspace_set_chromaticities(png_const_structrp png_ptr, { case 0: /* success */ return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ, - preferred); + preferred); case 1: /* We can't invert the chromaticities so we can't produce value XYZ @@ -1719,7 +1720,7 @@ png_colorspace_set_chromaticities(png_const_structrp png_ptr, int /* PRIVATE */ png_colorspace_set_endpoints(png_const_structrp png_ptr, - png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred) + png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred) { png_XYZ XYZ = *XYZ_in; png_xy xy; @@ -1728,7 +1729,7 @@ png_colorspace_set_endpoints(png_const_structrp png_ptr, { case 0: return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ, - preferred); + preferred); case 1: /* End points are invalid. */ @@ -1785,7 +1786,7 @@ is_ICC_signature(png_alloc_size_t it) static int png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_alloc_size_t value, png_const_charp reason) + png_const_charp name, png_alloc_size_t value, png_const_charp reason) { size_t pos; char message[196]; /* see below for calculation */ @@ -1810,8 +1811,8 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/ pos = png_safecat(message, (sizeof message), pos, - png_format_number(number, number+(sizeof number), - PNG_NUMBER_FORMAT_x, value)); + png_format_number(number, number+(sizeof number), + PNG_NUMBER_FORMAT_x, value)); pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/ } # endif @@ -1825,7 +1826,7 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, * application errors the PNG won't be written.) */ png_chunk_report(png_ptr, message, - (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR); + (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR); return 0; } @@ -1834,7 +1835,7 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, #ifdef PNG_sRGB_SUPPORTED int /* PRIVATE */ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, - int intent) + int intent) { /* sRGB sets known gamma, end points and (from the chunk) intent. */ /* IMPORTANT: these are not necessarily the values found in an ICC profile @@ -1871,10 +1872,10 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, */ if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST) return png_icc_profile_error(png_ptr, colorspace, "sRGB", - (unsigned)intent, "invalid sRGB rendering intent"); + (unsigned)intent, "invalid sRGB rendering intent"); if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 && - colorspace->rendering_intent != intent) + colorspace->rendering_intent != intent) return png_icc_profile_error(png_ptr, colorspace, "sRGB", (unsigned)intent, "inconsistent rendering intents"); @@ -1888,8 +1889,8 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, * warn but overwrite the value with the correct one. */ if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 && - !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy, - 100)) + !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy, + 100)) png_chunk_report(png_ptr, "cHRM chunk does not match sRGB", PNG_CHUNK_ERROR); @@ -1897,7 +1898,7 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, * returns true when the 'from' argument corresponds to sRGB (2). */ (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE, - 2/*from sRGB*/); + 2/*from sRGB*/); /* intent: bugs in GCC force 'int' to be used as the parameter type. */ colorspace->rendering_intent = (png_uint_16)intent; @@ -1932,19 +1933,19 @@ static const png_byte D50_nCIEXYZ[12] = int /* PRIVATE */ png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length) + png_const_charp name, png_uint_32 profile_length) { if (profile_length < 132) return png_icc_profile_error(png_ptr, colorspace, name, profile_length, - "too short"); + "too short"); return 1; } int /* PRIVATE */ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length, - png_const_bytep profile/* first 132 bytes only */, int color_type) + png_const_charp name, png_uint_32 profile_length, + png_const_bytep profile/* first 132 bytes only */, int color_type) { png_uint_32 temp; @@ -1956,18 +1957,18 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, temp = png_get_uint_32(profile); if (temp != profile_length) return png_icc_profile_error(png_ptr, colorspace, name, temp, - "length does not match profile"); + "length does not match profile"); temp = (png_uint_32) (*(profile+8)); if (temp > 3 && (profile_length & 3)) return png_icc_profile_error(png_ptr, colorspace, name, profile_length, - "invalid length"); + "invalid length"); temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */ if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */ profile_length < 132+12*temp) /* truncated tag table */ return png_icc_profile_error(png_ptr, colorspace, name, temp, - "tag count too large"); + "tag count too large"); /* The 'intent' must be valid or we can't store it, ICC limits the intent to * 16 bits. @@ -1975,14 +1976,14 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, temp = png_get_uint_32(profile+64); if (temp >= 0xffff) /* The ICC limit */ return png_icc_profile_error(png_ptr, colorspace, name, temp, - "invalid rendering intent"); + "invalid rendering intent"); /* This is just a warning because the profile may be valid in future * versions. */ if (temp >= PNG_sRGB_INTENT_LAST) (void)png_icc_profile_error(png_ptr, NULL, name, temp, - "intent outside defined range"); + "intent outside defined range"); /* At this point the tag table can't be checked because it hasn't necessarily * been loaded; however, various header fields can be checked. These checks @@ -1999,7 +2000,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, temp = png_get_uint_32(profile+36); /* signature 'ascp' */ if (temp != 0x61637370) return png_icc_profile_error(png_ptr, colorspace, name, temp, - "invalid signature"); + "invalid signature"); /* Currently the PCS illuminant/adopted white point (the computational * white point) are required to be D50, @@ -2010,7 +2011,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, */ if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0) (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/, - "PCS illuminant is not D50"); + "PCS illuminant is not D50"); /* The PNG spec requires this: * "If the iCCP chunk is present, the image samples conform to the colour @@ -2038,18 +2039,18 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, case 0x52474220: /* 'RGB ' */ if ((color_type & PNG_COLOR_MASK_COLOR) == 0) return png_icc_profile_error(png_ptr, colorspace, name, temp, - "RGB color space not permitted on grayscale PNG"); + "RGB color space not permitted on grayscale PNG"); break; case 0x47524159: /* 'GRAY' */ if ((color_type & PNG_COLOR_MASK_COLOR) != 0) return png_icc_profile_error(png_ptr, colorspace, name, temp, - "Gray color space not permitted on RGB PNG"); + "Gray color space not permitted on RGB PNG"); break; default: return png_icc_profile_error(png_ptr, colorspace, name, temp, - "invalid ICC profile color space"); + "invalid ICC profile color space"); } /* It is up to the application to check that the profile class matches the @@ -2074,7 +2075,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, case 0x61627374: /* 'abst' */ /* May not be embedded in an image */ return png_icc_profile_error(png_ptr, colorspace, name, temp, - "invalid embedded Abstract ICC profile"); + "invalid embedded Abstract ICC profile"); case 0x6c696e6b: /* 'link' */ /* DeviceLink profiles cannot be interpreted in a non-device specific @@ -2084,7 +2085,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, * PNG. */ return png_icc_profile_error(png_ptr, colorspace, name, temp, - "unexpected DeviceLink ICC profile class"); + "unexpected DeviceLink ICC profile class"); case 0x6e6d636c: /* 'nmcl' */ /* A NamedColor profile is also device specific, however it doesn't @@ -2092,7 +2093,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, * certainly it will fail the tests below. */ (void)png_icc_profile_error(png_ptr, NULL, name, temp, - "unexpected NamedColor ICC profile class"); + "unexpected NamedColor ICC profile class"); break; default: @@ -2102,7 +2103,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, * understood profiles. */ (void)png_icc_profile_error(png_ptr, NULL, name, temp, - "unrecognized ICC profile class"); + "unrecognized ICC profile class"); break; } @@ -2118,7 +2119,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, default: return png_icc_profile_error(png_ptr, colorspace, name, temp, - "unexpected ICC PCS encoding"); + "unexpected ICC PCS encoding"); } return 1; @@ -2126,8 +2127,8 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, int /* PRIVATE */ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length, - png_const_bytep profile /* header plus whole tag table */) + png_const_charp name, png_uint_32 profile_length, + png_const_bytep profile /* header plus whole tag table */) { png_uint_32 tag_count = png_get_uint_32(profile+128); png_uint_32 itag; @@ -2155,7 +2156,7 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, * alignment. */ (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "ICC profile tag start not a multiple of 4"); + "ICC profile tag start not a multiple of 4"); } /* This is a hard error; potentially it can cause read outside the @@ -2163,7 +2164,7 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, */ if (tag_start > profile_length || tag_length > profile_length - tag_start) return png_icc_profile_error(png_ptr, colorspace, name, tag_id, - "ICC profile tag outside profile"); + "ICC profile tag outside profile"); } return 1; /* success, maybe with warnings */ @@ -2191,22 +2192,22 @@ static const struct */ /* adler32, crc32, MD5[4], intent, date, length, file-name */ PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9, - PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0, - "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc") + PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0, + "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc") /* ICC sRGB v2 perceptual no black-compensation: */ PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21, - PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0, - "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc") + PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0, + "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc") PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae, - PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0, - "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc") + PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0, + "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc") /* ICC sRGB v4 perceptual */ PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812, - PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0, - "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc") + PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0, + "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc") /* The following profiles have no known MD5 checksum. If there is a match * on the (empty) MD5 the other fields are used to attempt a match and @@ -2214,8 +2215,8 @@ static const struct * which suggests that they were also made by Hewlett Packard. */ PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce, - PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0, - "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc") + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0, + "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc") /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not * match the D50 PCS illuminant in the header (it is in fact the D65 values, @@ -2225,17 +2226,17 @@ static const struct * chromaticAdaptationTag. */ PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552, - PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/, - "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual") + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/, + "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual") PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d, - PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/, - "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative") + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/, + "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative") }; static int png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, - png_const_bytep profile, uLong adler) + png_const_bytep profile, uLong adler) { /* The quick check is to verify just the MD5 signature and trust the * rest of the data. Because the profile has already been verified for @@ -2319,7 +2320,7 @@ png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, * which is made irrelevant by this error. */ png_chunk_report(png_ptr, "known incorrect sRGB profile", - PNG_CHUNK_ERROR); + PNG_CHUNK_ERROR); } /* Warn that this being done; this isn't even an error since @@ -2329,8 +2330,8 @@ png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, else if (png_sRGB_checks[i].have_md5 == 0) { png_chunk_report(png_ptr, - "out-of-date sRGB profile with no signature", - PNG_CHUNK_WARNING); + "out-of-date sRGB profile with no signature", + PNG_CHUNK_WARNING); } return 1+png_sRGB_checks[i].is_broken; @@ -2343,7 +2344,7 @@ png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, * Fall through to "no match". */ png_chunk_report(png_ptr, - "Not recognizing known sRGB profile that has been edited", + "Not recognizing known sRGB profile that has been edited", PNG_CHUNK_WARNING); break; # endif @@ -2353,38 +2354,36 @@ png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, return 0; /* no match */ } -#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */ void /* PRIVATE */ png_icc_set_sRGB(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_const_bytep profile, uLong adler) + png_colorspacerp colorspace, png_const_bytep profile, uLong adler) { /* Is this profile one of the known ICC sRGB profiles? If it is, just set * the sRGB information. */ -#if PNG_sRGB_PROFILE_CHECKS >= 0 if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0) -#endif (void)png_colorspace_set_sRGB(png_ptr, colorspace, (int)/*already checked*/png_get_uint_32(profile+64)); } +#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */ #endif /* sRGB */ int /* PRIVATE */ png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length, png_const_bytep profile, - int color_type) + png_const_charp name, png_uint_32 profile_length, png_const_bytep profile, + int color_type) { if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) return 0; if (png_icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && png_icc_check_header(png_ptr, colorspace, name, profile_length, profile, - color_type) != 0 && + color_type) != 0 && png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, - profile) != 0) + profile) != 0) { -# ifdef PNG_sRGB_SUPPORTED +# if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0 /* If no sRGB support, don't try storing sRGB information */ png_icc_set_sRGB(png_ptr, colorspace, profile, 0); # endif @@ -2443,7 +2442,7 @@ png_colorspace_set_rgb_coefficients(png_structrp png_ptr) /* Check for an internal error. */ if (r+g+b != 32768) png_error(png_ptr, - "internal error handling cHRM coefficients"); + "internal error handling cHRM coefficients"); else { @@ -2469,7 +2468,7 @@ png_colorspace_set_rgb_coefficients(png_structrp png_ptr) static int /* PRIVATE */ png_gt(size_t a, size_t b) { - return a > b; + return a > b; } #else # define png_gt(a,b) ((a) > (b)) @@ -2477,9 +2476,9 @@ png_gt(size_t a, size_t b) void /* PRIVATE */ png_check_IHDR(png_const_structrp png_ptr, - png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_type, int compression_type, - int filter_type) + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) { int error = 0; @@ -2642,7 +2641,7 @@ png_check_IHDR(png_const_structrp png_ptr, int /* PRIVATE */ png_check_fp_number(png_const_charp string, png_size_t size, int *statep, - png_size_tp whereami) + png_size_tp whereami) { int state = *statep; png_size_t i = *whereami; @@ -3805,25 +3804,25 @@ png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val) { if (value > 0 && value < 65535) { -# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - /* The same (unsigned int)->(double) constraints apply here as above, - * however in this case the (unsigned int) to (int) conversion can - * overflow on an ANSI-C90 compliant system so the cast needs to ensure - * that this is not possible. - */ - double r = floor(65535*pow((png_int_32)value/65535., - gamma_val*.00001)+.5); - return (png_uint_16)r; -# else - png_int_32 lg2 = png_log16bit(value); - png_fixed_point res; +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + /* The same (unsigned int)->(double) constraints apply here as above, + * however in this case the (unsigned int) to (int) conversion can + * overflow on an ANSI-C90 compliant system so the cast needs to ensure + * that this is not possible. + */ + double r = floor(65535*pow((png_int_32)value/65535., + gamma_val*.00001)+.5); + return (png_uint_16)r; +# else + png_int_32 lg2 = png_log16bit(value); + png_fixed_point res; - if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0) - return png_exp16bit(res); + if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0) + return png_exp16bit(res); - /* Overflow. */ - value = 0; -# endif + /* Overflow. */ + value = 0; +# endif } return (png_uint_16)value; @@ -3862,7 +3861,7 @@ png_gamma_correct(png_structrp png_ptr, unsigned int value, */ static void png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable, - PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) + PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) { /* Various values derived from 'shift': */ PNG_CONST unsigned int num = 1U << (8U - shift); @@ -3939,7 +3938,7 @@ png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable, */ static void png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable, - PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) + PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) { PNG_CONST unsigned int num = 1U << (8U - shift); PNG_CONST unsigned int max = (1U << (16U - shift))-1U; @@ -4007,7 +4006,7 @@ png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable, */ static void png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable, - PNG_CONST png_fixed_point gamma_val) + PNG_CONST png_fixed_point gamma_val) { unsigned int i; png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256); @@ -4087,131 +4086,133 @@ png_destroy_gamma_table(png_structrp png_ptr) void /* PRIVATE */ png_build_gamma_table(png_structrp png_ptr, int bit_depth) { - png_debug(1, "in png_build_gamma_table"); + png_debug(1, "in png_build_gamma_table"); - /* Remove any existing table; this copes with multiple calls to - * png_read_update_info. The warning is because building the gamma tables - * multiple times is a performance hit - it's harmless but the ability to call - * png_read_update_info() multiple times is new in 1.5.6 so it seems sensible - * to warn if the app introduces such a hit. - */ - if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL) - { - png_warning(png_ptr, "gamma table being rebuilt"); - png_destroy_gamma_table(png_ptr); - } + /* Remove any existing table; this copes with multiple calls to + * png_read_update_info. The warning is because building the gamma tables + * multiple times is a performance hit - it's harmless but the ability to + * call png_read_update_info() multiple times is new in 1.5.6 so it seems + * sensible to warn if the app introduces such a hit. + */ + if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL) + { + png_warning(png_ptr, "gamma table being rebuilt"); + png_destroy_gamma_table(png_ptr); + } - if (bit_depth <= 8) - { - png_build_8bit_table(png_ptr, &png_ptr->gamma_table, - png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma) : PNG_FP_1); + if (bit_depth <= 8) + { + png_build_8bit_table(png_ptr, &png_ptr->gamma_table, + png_ptr->screen_gamma > 0 ? + png_reciprocal2(png_ptr->colorspace.gamma, + png_ptr->screen_gamma) : PNG_FP_1); #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0) - { - png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, - png_reciprocal(png_ptr->colorspace.gamma)); + if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0) + { + png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, + png_reciprocal(png_ptr->colorspace.gamma)); - png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, - png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : - png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); - } + png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, + png_ptr->screen_gamma > 0 ? + png_reciprocal(png_ptr->screen_gamma) : + png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); + } #endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ - } + } #ifdef PNG_16BIT_SUPPORTED - else - { - png_byte shift, sig_bit; + else + { + png_byte shift, sig_bit; - if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0) - { - sig_bit = png_ptr->sig_bit.red; + if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0) + { + sig_bit = png_ptr->sig_bit.red; - if (png_ptr->sig_bit.green > sig_bit) - sig_bit = png_ptr->sig_bit.green; + if (png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; - if (png_ptr->sig_bit.blue > sig_bit) - sig_bit = png_ptr->sig_bit.blue; - } - else - sig_bit = png_ptr->sig_bit.gray; + if (png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + sig_bit = png_ptr->sig_bit.gray; - /* 16-bit gamma code uses this equation: - * - * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8] - * - * Where 'iv' is the input color value and 'ov' is the output value - - * pow(iv, gamma). - * - * Thus the gamma table consists of up to 256 256-entry tables. The table - * is selected by the (8-gamma_shift) most significant of the low 8 bits of - * the color value then indexed by the upper 8 bits: - * - * table[low bits][high 8 bits] - * - * So the table 'n' corresponds to all those 'iv' of: - * - * ..<(n+1 << gamma_shift)-1> - * - */ - if (sig_bit > 0 && sig_bit < 16U) - /* shift == insignificant bits */ - shift = (png_byte)((16U - sig_bit) & 0xff); + /* 16-bit gamma code uses this equation: + * + * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8] + * + * Where 'iv' is the input color value and 'ov' is the output value - + * pow(iv, gamma). + * + * Thus the gamma table consists of up to 256 256-entry tables. The table + * is selected by the (8-gamma_shift) most significant of the low 8 bits + * of the color value then indexed by the upper 8 bits: + * + * table[low bits][high 8 bits] + * + * So the table 'n' corresponds to all those 'iv' of: + * + * ..<(n+1 << gamma_shift)-1> + * + */ + if (sig_bit > 0 && sig_bit < 16U) + /* shift == insignificant bits */ + shift = (png_byte)((16U - sig_bit) & 0xff); - else - shift = 0; /* keep all 16 bits */ + else + shift = 0; /* keep all 16 bits */ - if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0) - { - /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively - * the significant bits in the *input* when the output will - * eventually be 8 bits. By default it is 11. - */ - if (shift < (16U - PNG_MAX_GAMMA_8)) - shift = (16U - PNG_MAX_GAMMA_8); - } + if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0) + { + /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively + * the significant bits in the *input* when the output will + * eventually be 8 bits. By default it is 11. + */ + if (shift < (16U - PNG_MAX_GAMMA_8)) + shift = (16U - PNG_MAX_GAMMA_8); + } - if (shift > 8U) - shift = 8U; /* Guarantees at least one table! */ + if (shift > 8U) + shift = 8U; /* Guarantees at least one table! */ - png_ptr->gamma_shift = shift; + png_ptr->gamma_shift = shift; - /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now - * PNG_COMPOSE). This effectively smashed the background calculation for - * 16-bit output because the 8-bit table assumes the result will be reduced - * to 8 bits. - */ - if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0) - png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, - png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma) : PNG_FP_1); + /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now + * PNG_COMPOSE). This effectively smashed the background calculation for + * 16-bit output because the 8-bit table assumes the result will be + * reduced to 8 bits. + */ + if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0) + png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma, + png_ptr->screen_gamma) : PNG_FP_1); - else - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, - png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma) : PNG_FP_1); + else + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, + png_ptr->screen_gamma) : PNG_FP_1); #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0) - { - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, - png_reciprocal(png_ptr->colorspace.gamma)); + if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0) + { + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, + png_reciprocal(png_ptr->colorspace.gamma)); - /* Notice that the '16 from 1' table should be full precision, however - * the lookup on this table still uses gamma_shift, so it can't be. - * TODO: fix this. - */ - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, - png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : - png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); - } + /* Notice that the '16 from 1' table should be full precision, however + * the lookup on this table still uses gamma_shift, so it can't be. + * TODO: fix this. + */ + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, + png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : + png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); + } #endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ - } + } #endif /* 16BIT */ } #endif /* READ_GAMMA */ diff --git a/3rdparty/libpng/png.h b/3rdparty/libpng/png.h index c83051b1ca..ebfb3dd02e 100644 --- a/3rdparty/libpng/png.h +++ b/3rdparty/libpng/png.h @@ -1,9 +1,9 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.19, November 12, 2015 + * libpng version 1.6.24, August 4, 2016 * - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -12,7 +12,8 @@ * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.6.19, November 12, 2015: Glenn + * libpng versions 0.97, January 1998, through 1.6.24, August 4, 2016: + * Glenn Randers-Pehrson. * See also "Contributing Authors", below. */ @@ -24,8 +25,12 @@ * * This code is released under the libpng license. * - * libpng versions 1.0.7, July 1, 2000, through 1.6.19, November 12, 2015, are - * Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are + * Some files in the "contrib" directory and some configure-generated + * files that are distributed with libpng have other copyright owners and + * are released under other open source licenses. + * + * libpng versions 1.0.7, July 1, 2000 through 1.6.24, August 4, 2016 are + * Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are * derived from libpng-1.0.6, and are distributed according to the same * disclaimer and license as libpng-1.0.6 with the following individuals * added to the list of Contributing Authors: @@ -46,6 +51,10 @@ * risk of satisfactory quality, performance, accuracy, and effort is with * the user. * + * Some files in the "contrib" directory have other copyright owners and + * are released under other open source licenses. + * + * * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from * libpng-0.96, and are distributed according to the same disclaimer and @@ -56,6 +65,9 @@ * Glenn Randers-Pehrson * Willem van Schaik * + * Some files in the "scripts" directory have different copyright owners + * but are also released under this license. + * * libpng versions 0.89, June 1996, through 0.96, May 1997, are * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, * and are distributed according to the same disclaimer and license as @@ -69,6 +81,9 @@ * Greg Roelofs * Tom Tanner * + * Some files in the "scripts" directory have other copyright owners + * but are released under this license. + * * libpng versions 0.5, May 1995, through 0.88, January 1996, are * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * @@ -108,6 +123,29 @@ * appreciated. * * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. + * + * TRADEMARK: + * + * The name "libpng" has not been registered by the Copyright owner + * as a trademark in any jurisdiction. However, because libpng has + * been distributed and maintained world-wide, continually since 1995, + * the Copyright owner claims "common-law trademark protection" in any + * jurisdiction where common-law trademark is recognized. + * + * OSI CERTIFICATION: + * + * Libpng is OSI Certified Open Source Software. OSI Certified Open Source is + * a certification mark of the Open Source Initiative. OSI has not addressed + * the additional disclaimers inserted at version 1.0.7. + * + * EXPORT CONTROL: + * + * The Copyright owner believes that the Export Control Classification + * Number (ECCN) for libpng is EAR99, which means not subject to export + * controls or International Traffic in Arms Regulations (ITAR) because + * it is open source, publicly available software, that does not contain + * any encryption software. See the EAR, paragraphs 734.3(b)(3) and + * 734.7(b). */ /* @@ -120,12 +158,6 @@ * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). */ -/* - * Libpng is OSI Certified Open Source Software. OSI Certified Open Source is - * a certification mark of the Open Source Initiative. OSI has not addressed - * the additional disclaimers inserted at version 1.0.7. - */ - /* * The contributing authors would like to thank all those who helped * with testing, bug fixes, and patience. This wouldn't have been @@ -181,11 +213,11 @@ * ... * 1.0.19 10 10019 10.so.0.19[.0] * ... - * 1.2.53 13 10253 12.so.0.53[.0] + * 1.2.56 13 10256 12.so.0.56[.0] * ... - * 1.5.23 15 10523 15.so.15.23[.0] + * 1.5.27 15 10527 15.so.15.27[.0] * ... - * 1.6.19 16 10619 16.so.16.19[.0] + * 1.6.24 16 10624 16.so.16.24[.0] * * Henceforth the source version will match the shared-library major * and minor numbers; the shared-library major version number will be @@ -213,13 +245,13 @@ * Y2K compliance in libpng: * ========================= * - * November 12, 2015 + * August 4, 2016 * * Since the PNG Development group is an ad-hoc body, we can't make * an official declaration. * * This is your unofficial assurance that libpng from version 0.71 and - * upward through 1.6.19 are Y2K compliant. It is my belief that + * upward through 1.6.24 are Y2K compliant. It is my belief that * earlier versions were also Y2K compliant. * * Libpng only has two year fields. One is a 2-byte unsigned integer @@ -281,9 +313,8 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.19" -#define PNG_HEADER_VERSION_STRING \ - " libpng version 1.6.19 - November 12, 2015\n" +#define PNG_LIBPNG_VER_STRING "1.6.24" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.24 - August 4, 2016\n" #define PNG_LIBPNG_VER_SONUM 16 #define PNG_LIBPNG_VER_DLLNUM 16 @@ -291,7 +322,7 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 6 -#define PNG_LIBPNG_VER_RELEASE 19 +#define PNG_LIBPNG_VER_RELEASE 24 /* This should match the numeric part of the final component of * PNG_LIBPNG_VER_STRING, omitting any leading zero: @@ -322,20 +353,20 @@ * version 1.0.0 was mis-numbered 100 instead of 10000). From * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release */ -#define PNG_LIBPNG_VER 10619 /* 1.6.19 */ +#define PNG_LIBPNG_VER 10624 /* 1.6.24 */ /* Library configuration: these options cannot be changed after * the library has been built. */ #ifndef PNGLCONF_H - /* If pnglibconf.h is missing, you can - * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h - */ +/* If pnglibconf.h is missing, you can + * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h + */ # include "pnglibconf.h" #endif #ifndef PNG_VERSION_INFO_ONLY - /* Machine specific configuration. */ +/* Machine specific configuration. */ # include "pngconf.h" #endif @@ -432,7 +463,7 @@ extern "C" { /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_6_19; +typedef char* png_libpng_version_1_6_24; /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. * @@ -625,17 +656,17 @@ typedef png_time * * png_timepp; */ typedef struct png_unknown_chunk_t { - png_byte name[5]; /* Textual chunk name with '\0' terminator */ - png_byte *data; /* Data, should not be modified on read! */ - png_size_t size; + png_byte name[5]; /* Textual chunk name with '\0' terminator */ + png_byte *data; /* Data, should not be modified on read! */ + png_size_t size; - /* On write 'location' must be set using the flag values listed below. - * Notice that on read it is set by libpng however the values stored have - * more bits set than are listed below. Always treat the value as a - * bitmask. On write set only one bit - setting multiple bits may cause the - * chunk to be written in multiple places. - */ - png_byte location; /* mode of operation at read time */ + /* On write 'location' must be set using the flag values listed below. + * Notice that on read it is set by libpng however the values stored have + * more bits set than are listed below. Always treat the value as a + * bitmask. On write set only one bit - setting multiple bits may cause the + * chunk to be written in multiple places. + */ + png_byte location; /* mode of operation at read time */ } png_unknown_chunk; @@ -733,24 +764,22 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; * data in the info_struct to be written into the output file. The values * of the PNG_INFO_ defines should NOT be changed. */ -#define PNG_INFO_gAMA 0x0001 -#define PNG_INFO_sBIT 0x0002 -#define PNG_INFO_cHRM 0x0004 -#define PNG_INFO_PLTE 0x0008 -#define PNG_INFO_tRNS 0x0010 -#define PNG_INFO_bKGD 0x0020 -#define PNG_INFO_hIST 0x0040 -#define PNG_INFO_pHYs 0x0080 -#define PNG_INFO_oFFs 0x0100 -#define PNG_INFO_tIME 0x0200 -#define PNG_INFO_pCAL 0x0400 -#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ -#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ -#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ -#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ -#if INT_MAX >= 0x8000 /* else this might break */ -#define PNG_INFO_IDAT 0x8000 /* ESR, 1.0.6 */ -#endif +#define PNG_INFO_gAMA 0x0001U +#define PNG_INFO_sBIT 0x0002U +#define PNG_INFO_cHRM 0x0004U +#define PNG_INFO_PLTE 0x0008U +#define PNG_INFO_tRNS 0x0010U +#define PNG_INFO_bKGD 0x0020U +#define PNG_INFO_hIST 0x0040U +#define PNG_INFO_pHYs 0x0080U +#define PNG_INFO_oFFs 0x0100U +#define PNG_INFO_tIME 0x0200U +#define PNG_INFO_pCAL 0x0400U +#define PNG_INFO_sRGB 0x0800U /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000U /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ /* This is used for the transformation routines, as some of them * change these values for the row. It also should enable using @@ -1321,7 +1350,7 @@ PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr)); #endif #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED -#define PNG_READ_16_TO_8 SUPPORTED /* Name prior to 1.5.4 */ +#define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */ /* Strip the second byte of information from a 16-bit depth file. */ PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); #endif @@ -1472,8 +1501,8 @@ PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, #define PNG_FILTER_UP 0x20 #define PNG_FILTER_AVG 0x40 #define PNG_FILTER_PAETH 0x80 -#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ - PNG_FILTER_AVG | PNG_FILTER_PAETH) +#define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP) +#define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH) /* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. * These defines should NOT be changed. @@ -1750,21 +1779,21 @@ PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, #define PNG_SET_WILL_FREE_DATA 1 #define PNG_USER_WILL_FREE_DATA 2 /* Flags for png_ptr->free_me and info_ptr->free_me */ -#define PNG_FREE_HIST 0x0008 -#define PNG_FREE_ICCP 0x0010 -#define PNG_FREE_SPLT 0x0020 -#define PNG_FREE_ROWS 0x0040 -#define PNG_FREE_PCAL 0x0080 -#define PNG_FREE_SCAL 0x0100 +#define PNG_FREE_HIST 0x0008U +#define PNG_FREE_ICCP 0x0010U +#define PNG_FREE_SPLT 0x0020U +#define PNG_FREE_ROWS 0x0040U +#define PNG_FREE_PCAL 0x0080U +#define PNG_FREE_SCAL 0x0100U #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_FREE_UNKN 0x0200 +# define PNG_FREE_UNKN 0x0200U #endif -/* PNG_FREE_LIST 0x0400 removed in 1.6.0 because it is ignored */ -#define PNG_FREE_PLTE 0x1000 -#define PNG_FREE_TRNS 0x2000 -#define PNG_FREE_TEXT 0x4000 -#define PNG_FREE_ALL 0x7fff -#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ +/* PNG_FREE_LIST 0x0400U removed in 1.6.0 because it is ignored */ +#define PNG_FREE_PLTE 0x1000U +#define PNG_FREE_TRNS 0x2000U +#define PNG_FREE_TEXT 0x4000U +#define PNG_FREE_ALL 0x7fffU +#define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ #ifdef PNG_USER_MEM_SUPPORTED PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, @@ -2270,8 +2299,10 @@ PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to * be processed by libpng. */ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, int keep, png_const_bytep chunk_list, int num_chunks)); +#endif /* HANDLE_AS_UNKNOWN */ /* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; * the result is therefore true (non-zero) if special handling is required, @@ -2279,7 +2310,7 @@ PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, */ PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, png_const_bytep chunk_name)); -#endif +#endif /* SET_UNKNOWN_CHUNKS */ #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, @@ -2500,33 +2531,37 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ -# define png_composite(composite, fg, alpha, bg) \ - { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ - * (png_uint_16)(alpha) \ - + (png_uint_16)(bg)*(png_uint_16)(255 \ - - (png_uint_16)(alpha)) + 128); \ - (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); } +# define png_composite(composite, fg, alpha, bg) \ + { \ + png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + 128); \ + (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); \ + } -# define png_composite_16(composite, fg, alpha, bg) \ - { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ - * (png_uint_32)(alpha) \ - + (png_uint_32)(bg)*(65535 \ - - (png_uint_32)(alpha)) + 32768); \ - (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); } +# define png_composite_16(composite, fg, alpha, bg) \ + { \ + png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(65535 \ + - (png_uint_32)(alpha)) + 32768); \ + (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \ + } #else /* Standard method using integer division */ -# define png_composite(composite, fg, alpha, bg) \ - (composite) = \ - (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ - 127) / 255)) +# define png_composite(composite, fg, alpha, bg) \ + (composite) = \ + (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + 127) / 255)) -# define png_composite_16(composite, fg, alpha, bg) \ - (composite) = \ - (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ - 32767) / 65535)) +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = \ + (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ + 32767) / 65535)) #endif /* READ_COMPOSITE_NODIV */ #ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED @@ -2562,38 +2597,38 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); * format for negative values, which is almost certainly true. */ # define PNG_get_uint_32(buf) \ - (((png_uint_32)(*(buf)) << 24) + \ - ((png_uint_32)(*((buf) + 1)) << 16) + \ - ((png_uint_32)(*((buf) + 2)) << 8) + \ - ((png_uint_32)(*((buf) + 3)))) + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the * function) incorrectly returned a value of type png_uint_32. */ # define PNG_get_uint_16(buf) \ - ((png_uint_16) \ - (((unsigned int)(*(buf)) << 8) + \ - ((unsigned int)(*((buf) + 1))))) + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) # define PNG_get_int_32(buf) \ - ((png_int_32)((*(buf) & 0x80) \ - ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ - : (png_int_32)png_get_uint_32(buf))) + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ + : (png_int_32)png_get_uint_32(buf))) - /* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, - * but defining a macro name prefixed with PNG_PREFIX. - */ +/* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, + * but defining a macro name prefixed with PNG_PREFIX. + */ # ifndef PNG_PREFIX -# define png_get_uint_32(buf) PNG_get_uint_32(buf) -# define png_get_uint_16(buf) PNG_get_uint_16(buf) -# define png_get_int_32(buf) PNG_get_int_32(buf) +# define png_get_uint_32(buf) PNG_get_uint_32(buf) +# define png_get_uint_16(buf) PNG_get_uint_16(buf) +# define png_get_int_32(buf) PNG_get_int_32(buf) # endif #else # ifdef PNG_PREFIX - /* No macros; revert to the (redefined) function */ -# define PNG_get_uint_32 (png_get_uint_32) -# define PNG_get_uint_16 (png_get_uint_16) -# define PNG_get_int_32 (png_get_int_32) + /* No macros; revert to the (redefined) function */ +# define PNG_get_uint_32 (png_get_uint_32) +# define PNG_get_uint_16 (png_get_uint_16) +# define PNG_get_int_32 (png_get_int_32) # endif #endif @@ -2888,12 +2923,19 @@ typedef struct * is the minimum 'row stride', the minimum count of components between each * row. For a color-mapped image this is the minimum number of bytes in a * row. + * + * WARNING: this macro overflows for some images with more than one component + * and very large image widths. libpng will refuse to process an image where + * this macro would overflow. */ #define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride)) /* Return the size, in bytes, of an image buffer given a png_image and a row * stride - the number of components to leave space for in each row. + * + * WARNING: this macro overflows a 32-bit integer for some large PNG images, + * libpng will refuse to process an image where such an overflow would occur. */ #define PNG_IMAGE_SIZE(image)\ @@ -3014,7 +3056,6 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image)); #endif /* SIMPLIFIED_READ */ #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED -#ifdef PNG_STDIO_SUPPORTED /* WRITE APIS * ---------- * For write you must initialize a png_image structure to describe the image to @@ -3031,6 +3072,7 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image)); * values do not correspond to the colors in sRGB. * colormap_entries: set to the number of entries in the color-map (0 to 256) */ +#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, const char *file, int convert_to_8bit, const void *buffer, png_int_32 row_stride, const void *colormap)); @@ -3040,8 +3082,9 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, int convert_to_8_bit, const void *buffer, png_int_32 row_stride, const void *colormap)); /* Write the image to the given (FILE*). */ +#endif /* SIMPLIFIED_WRITE_STDIO */ -/* With both write APIs if image is in one of the linear formats with 16-bit +/* With all write APIs if image is in one of the linear formats with 16-bit * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG * gamma encoded according to the sRGB specification, otherwise a 16-bit linear * encoded PNG file is written. @@ -3053,13 +3096,103 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, * * With all APIs row_stride is handled as in the read APIs - it is the spacing * from one row to the next in component sized units (1 or 2 bytes) and if - * negative indicates a bottom-up row layout in the buffer. If row_stride is zero, - * libpng will calculate it for you from the image width and number of channels. + * negative indicates a bottom-up row layout in the buffer. If row_stride is + * zero, libpng will calculate it for you from the image width and number of + * channels. * - * Note that the write API does not support interlacing, sub-8-bit pixels, indexed - * PNG (color_type 3) or most ancillary chunks. + * Note that the write API does not support interlacing, sub-8-bit pixels or + * most ancillary chunks. If you need to write text chunks (e.g. for copyright + * notices) you need to use one of the other APIs. */ -#endif /* STDIO */ + +PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, + png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit, + const void *buffer, png_int_32 row_stride, const void *colormap)); + /* Write the image to the given memory buffer. The function both writes the + * whole PNG data stream to *memory and updates *memory_bytes with the count + * of bytes written. + * + * 'memory' may be NULL. In this case *memory_bytes is not read however on + * success the number of bytes which would have been written will still be + * stored in *memory_bytes. On failure *memory_bytes will contain 0. + * + * If 'memory' is not NULL it must point to memory[*memory_bytes] of + * writeable memory. + * + * If the function returns success memory[*memory_bytes] (if 'memory' is not + * NULL) contains the written PNG data. *memory_bytes will always be less + * than or equal to the original value. + * + * If the function returns false and *memory_bytes was not changed an error + * occured during write. If *memory_bytes was changed, or is not 0 if + * 'memory' was NULL, the write would have succeeded but for the memory + * buffer being too small. *memory_bytes contains the required number of + * bytes and will be bigger that the original value. + */ + +#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\ + row_stride, colormap)\ + png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\ + row_stride, colormap) + /* Return the amount of memory in 'size' required to compress this image. + * The png_image structure 'image' must be filled in as in the above + * function and must not be changed before the actual write call, the buffer + * and all other parameters must also be identical to that in the final + * write call. The 'size' variable need not be initialized. + * + * NOTE: the macro returns true/false, if false is returned 'size' will be + * set to zero and the write failed and probably will fail if tried again. + */ + +/* You can pre-allocate the buffer by making sure it is of sufficient size + * regardless of the amount of compression achieved. The buffer size will + * always be bigger than the original image and it will never be filled. The + * following macros are provided to assist in allocating the buffer. + */ +#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height) + /* The number of uncompressed bytes in the PNG byte encoding of the image; + * uncompressing the PNG IDAT data will give this number of bytes. + * + * NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this + * macro can because of the extra bytes used in the PNG byte encoding. You + * need to avoid this macro if your image size approaches 2^30 in width or + * height. The same goes for the remainder of these macros; they all produce + * bigger numbers than the actual in-memory image size. + */ +#ifndef PNG_ZLIB_MAX_SIZE +# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U) + /* An upper bound on the number of compressed bytes given 'b' uncompressed + * bytes. This is based on deflateBounds() in zlib; different + * implementations of zlib compression may conceivably produce more data so + * if your zlib implementation is not zlib itself redefine this macro + * appropriately. + */ +#endif + +#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\ + PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image)) + /* An upper bound on the size of the data in the PNG IDAT chunks. */ + +#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\ + ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\ + (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\ + 12U+3U*(image).colormap_entries/*PLTE data*/+\ + (((image).format&PNG_FORMAT_FLAG_ALPHA)?\ + 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\ + 12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size)) + /* A helper for the following macro; if your compiler cannot handle the + * following macro use this one with the result of + * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most + * compilers should handle this just fine.) + */ + +#define PNG_IMAGE_PNG_SIZE_MAX(image)\ + PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image)) + /* An upper bound on the total length of the PNG data stream for 'image'. + * The result is of type png_alloc_size_t, on 32-bit systems this may + * overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will + * run out of buffer space but return a corrected size which should work. + */ #endif /* SIMPLIFIED_WRITE */ /******************************************************************************* * END OF SIMPLIFIED API @@ -3117,7 +3250,7 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, * one to use is one more than this.) */ #ifdef PNG_EXPORT_LAST_ORDINAL - PNG_EXPORT_LAST_ORDINAL(244); + PNG_EXPORT_LAST_ORDINAL(245); #endif #ifdef __cplusplus diff --git a/3rdparty/libpng/pngconf.h b/3rdparty/libpng/pngconf.h index f1b795b478..9da691dbb8 100644 --- a/3rdparty/libpng/pngconf.h +++ b/3rdparty/libpng/pngconf.h @@ -1,9 +1,9 @@ /* pngconf.h - machine configurable file for libpng * - * libpng version 1.6.19, July 23, 2015 + * libpng version 1.6.24, August 4, 2016 * - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -188,27 +188,27 @@ * compatible with GCC or Visual C because of different calling conventions. */ # if PNG_API_RULE == 2 - /* If this line results in an error, either because __watcall is not - * understood or because of a redefine just below you cannot use *this* - * build of the library with the compiler you are using. *This* build was - * build using Watcom and applications must also be built using Watcom! - */ + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ # define PNGCAPI __watcall # endif # if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) # define PNGCAPI __cdecl # if PNG_API_RULE == 1 - /* If this line results in an error __stdcall is not understood and - * PNG_API_RULE should not have been set to '1'. - */ + /* If this line results in an error __stdcall is not understood and + * PNG_API_RULE should not have been set to '1'. + */ # define PNGAPI __stdcall # endif # else - /* An older compiler, or one not detected (erroneously) above, - * if necessary override on the command line to get the correct - * variants for the compiler. - */ + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ # ifndef PNGCAPI # define PNGCAPI _cdecl # endif @@ -225,10 +225,10 @@ # if (defined(_MSC_VER) && _MSC_VER < 800) ||\ (defined(__BORLANDC__) && __BORLANDC__ < 0x500) - /* older Borland and MSC - * compilers used '__export' and required this to be after - * the type. - */ + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ # ifndef PNG_EXPORT_TYPE # define PNG_EXPORT_TYPE(type) type PNG_IMPEXP # endif @@ -244,9 +244,9 @@ # if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) # define PNGAPI _System # else /* !Windows/x86 && !OS/2 */ - /* Use the defaults, or define PNG*API on the command line (but - * this will have to be done for every compile!) - */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ # endif /* other system, !OS/2 */ #endif /* !Windows/x86 */ @@ -267,7 +267,7 @@ */ #ifndef PNG_IMPEXP # if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) - /* This forces use of a DLL, disallowing static linking */ + /* This forces use of a DLL, disallowing static linking */ # define PNG_IMPEXP PNG_DLL_IMPORT # endif @@ -340,7 +340,7 @@ * less efficient code. */ # if defined(__clang__) && defined(__has_attribute) - /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */ + /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */ # if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__) # define PNG_USE_RESULT __attribute__((__warn_unused_result__)) # endif diff --git a/3rdparty/libpng/pngdebug.h b/3rdparty/libpng/pngdebug.h index 6a01b106ed..15a7ed0c95 100644 --- a/3rdparty/libpng/pngdebug.h +++ b/3rdparty/libpng/pngdebug.h @@ -2,7 +2,7 @@ /* pngdebug.h - Debugging macros for libpng, also used in pngtest.c * * Last changed in libpng 1.6.8 [December 19, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * diff --git a/3rdparty/libpng/pngerror.c b/3rdparty/libpng/pngerror.c index 0781866a89..f13b76443a 100644 --- a/3rdparty/libpng/pngerror.c +++ b/3rdparty/libpng/pngerror.c @@ -1,8 +1,8 @@ /* pngerror.c - stub functions for i/o and memory allocation * - * Last changed in libpng 1.6.15 [November 20, 2014] - * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -26,7 +26,7 @@ static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr, #ifdef PNG_WARNINGS_SUPPORTED static void /* PRIVATE */ png_default_warning PNGARG((png_const_structrp png_ptr, - png_const_charp warning_message)); + png_const_charp warning_message)); #endif /* WARNINGS */ /* This function is called whenever there is a fatal error. This function @@ -37,14 +37,14 @@ png_default_warning PNGARG((png_const_structrp png_ptr, #ifdef PNG_ERROR_TEXT_SUPPORTED PNG_FUNCTION(void,PNGAPI png_error,(png_const_structrp png_ptr, png_const_charp error_message), - PNG_NORETURN) + PNG_NORETURN) { #ifdef PNG_ERROR_NUMBERS_SUPPORTED char msg[16]; if (png_ptr != NULL) { if ((png_ptr->flags & - (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0 + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0) { if (*error_message == PNG_LITERAL_SHARP) { @@ -65,18 +65,18 @@ png_error,(png_const_structrp png_ptr, png_const_charp error_message), else error_message += offset; - } - - else - { - if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0) - { - msg[0] = '0'; - msg[1] = '\0'; - error_message = msg; } - } - } + + else + { + if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0) + { + msg[0] = '0'; + msg[1] = '\0'; + error_message = msg; + } + } + } } #endif if (png_ptr != NULL && png_ptr->error_fn != NULL) @@ -110,7 +110,7 @@ png_err,(png_const_structrp png_ptr),PNG_NORETURN) */ size_t png_safecat(png_charp buffer, size_t bufsize, size_t pos, - png_const_charp string) + png_const_charp string) { if (buffer != NULL && pos < bufsize) { @@ -131,7 +131,7 @@ png_safecat(png_charp buffer, size_t bufsize, size_t pos, */ png_charp png_format_number(png_const_charp start, png_charp end, int format, - png_alloc_size_t number) + png_alloc_size_t number) { int count = 0; /* number of digits output */ int mincount = 1; /* minimum number required */ @@ -233,7 +233,7 @@ png_warning(png_const_structrp png_ptr, png_const_charp warning_message) } if (png_ptr != NULL && png_ptr->warning_fn != NULL) (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr), - warning_message + offset); + warning_message + offset); else png_default_warning(png_ptr, warning_message + offset); } @@ -245,7 +245,7 @@ png_warning(png_const_structrp png_ptr, png_const_charp warning_message) */ void png_warning_parameter(png_warning_parameters p, int number, - png_const_charp string) + png_const_charp string) { if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT) (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string); @@ -253,7 +253,7 @@ png_warning_parameter(png_warning_parameters p, int number, void png_warning_parameter_unsigned(png_warning_parameters p, int number, int format, - png_alloc_size_t value) + png_alloc_size_t value) { char buffer[PNG_NUMBER_BUFFER_SIZE]; png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value)); @@ -261,7 +261,7 @@ png_warning_parameter_unsigned(png_warning_parameters p, int number, int format, void png_warning_parameter_signed(png_warning_parameters p, int number, int format, - png_int_32 value) + png_int_32 value) { png_alloc_size_t u; png_charp str; @@ -282,7 +282,7 @@ png_warning_parameter_signed(png_warning_parameters p, int number, int format, void png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p, - png_const_charp message) + png_const_charp message) { /* The internal buffer is just 192 bytes - enough for all our messages, * overflow doesn't happen because this code checks! If someone figures @@ -391,10 +391,10 @@ png_benign_error(png_const_structrp png_ptr, png_const_charp error_message) void /* PRIVATE */ png_app_warning(png_const_structrp png_ptr, png_const_charp error_message) { - if ((png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) != 0) - png_warning(png_ptr, error_message); - else - png_error(png_ptr, error_message); + if ((png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) != 0) + png_warning(png_ptr, error_message); + else + png_error(png_ptr, error_message); # ifndef PNG_ERROR_TEXT_SUPPORTED PNG_UNUSED(error_message) @@ -404,10 +404,10 @@ png_app_warning(png_const_structrp png_ptr, png_const_charp error_message) void /* PRIVATE */ png_app_error(png_const_structrp png_ptr, png_const_charp error_message) { - if ((png_ptr->flags & PNG_FLAG_APP_ERRORS_WARN) != 0) - png_warning(png_ptr, error_message); - else - png_error(png_ptr, error_message); + if ((png_ptr->flags & PNG_FLAG_APP_ERRORS_WARN) != 0) + png_warning(png_ptr, error_message); + else + png_error(png_ptr, error_message); # ifndef PNG_ERROR_TEXT_SUPPORTED PNG_UNUSED(error_message) @@ -478,7 +478,7 @@ png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp #if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) PNG_FUNCTION(void,PNGAPI png_chunk_error,(png_const_structrp png_ptr, png_const_charp error_message), - PNG_NORETURN) + PNG_NORETURN) { char msg[18+PNG_MAX_ERROR_TEXT]; if (png_ptr == NULL) @@ -620,7 +620,7 @@ png_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn, else { png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *, - png_malloc_warn(png_ptr, jmp_buf_size)); + png_malloc_warn(png_ptr, jmp_buf_size)); if (png_ptr->jmp_buf_ptr == NULL) return NULL; /* new NULL return on OOM */ @@ -709,7 +709,7 @@ png_free_jmpbuf(png_structrp png_ptr) */ static PNG_FUNCTION(void /* PRIVATE */, png_default_error,(png_const_structrp png_ptr, png_const_charp error_message), - PNG_NORETURN) + PNG_NORETURN) { #ifdef PNG_CONSOLE_IO_SUPPORTED #ifdef PNG_ERROR_NUMBERS_SUPPORTED @@ -768,7 +768,7 @@ png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN) /* If control reaches this point, png_longjmp() must not return. The only * choice is to terminate the whole process (or maybe the thread); to do - * this the ANSI-C abort() function is used unless a different method is + * this the ANSI-C abort() function is used unless a different method is * implemented by overriding the default configuration setting for * PNG_ABORT(). */ @@ -883,7 +883,7 @@ png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode) */ PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message), - PNG_NORETURN) + PNG_NORETURN) { const png_const_structrp png_ptr = png_nonconst_ptr; png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); @@ -906,7 +906,7 @@ png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message), /* Missing longjmp buffer, the following is to help debugging: */ { size_t pos = png_safecat(image->message, (sizeof image->message), 0, - "bad longjmp: "); + "bad longjmp: "); png_safecat(image->message, (sizeof image->message), pos, error_message); } diff --git a/3rdparty/libpng/pngget.c b/3rdparty/libpng/pngget.c index 743a6a9bbc..b3c6863f40 100644 --- a/3rdparty/libpng/pngget.c +++ b/3rdparty/libpng/pngget.c @@ -1,8 +1,8 @@ /* pngget.c - retrieval of values from info struct * - * Last changed in libpng 1.6.17 [March 26, 2015] - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -456,11 +456,11 @@ png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr, return (retval); } #endif /* pHYs */ -#endif /* INCH_CONVERSIONS */ +#endif /* INCH_CONVERSIONS */ /* png_get_channels really belongs in here, too, but it's been around longer */ -#endif /* EASY_ACCESS */ +#endif /* EASY_ACCESS */ png_byte PNGAPI @@ -486,7 +486,7 @@ png_get_signature(png_const_structrp png_ptr, png_const_inforp info_ptr) #ifdef PNG_bKGD_SUPPORTED png_uint_32 PNGAPI png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr, - png_color_16p *background) + png_color_16p *background) { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0 && @@ -526,28 +526,28 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr, if (white_x != NULL) *white_x = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.whitex, "cHRM white X"); + info_ptr->colorspace.end_points_xy.whitex, "cHRM white X"); if (white_y != NULL) *white_y = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y"); + info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y"); if (red_x != NULL) *red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx, - "cHRM red X"); + "cHRM red X"); if (red_y != NULL) *red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy, - "cHRM red Y"); + "cHRM red Y"); if (green_x != NULL) *green_x = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.greenx, "cHRM green X"); + info_ptr->colorspace.end_points_xy.greenx, "cHRM green X"); if (green_y != NULL) *green_y = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y"); + info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y"); if (blue_x != NULL) *blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex, - "cHRM blue X"); + "cHRM blue X"); if (blue_y != NULL) *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey, - "cHRM blue Y"); + "cHRM blue Y"); return (PNG_INFO_cHRM); } @@ -556,42 +556,42 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr, png_uint_32 PNGAPI png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr, - double *red_X, double *red_Y, double *red_Z, double *green_X, - double *green_Y, double *green_Z, double *blue_X, double *blue_Y, - double *blue_Z) + double *red_X, double *red_Y, double *red_Z, double *green_X, + double *green_Y, double *green_Z, double *blue_X, double *blue_Y, + double *blue_Z) { if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) { png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)"); if (red_X != NULL) *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X, - "cHRM red X"); + "cHRM red X"); if (red_Y != NULL) *red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y, - "cHRM red Y"); + "cHRM red Y"); if (red_Z != NULL) *red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z, - "cHRM red Z"); + "cHRM red Z"); if (green_X != NULL) *green_X = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X"); + info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X"); if (green_Y != NULL) *green_Y = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y"); + info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y"); if (green_Z != NULL) *green_Z = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z"); + info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z"); if (blue_X != NULL) *blue_X = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X"); + info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X"); if (blue_Y != NULL) *blue_Y = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y"); + info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y"); if (blue_Z != NULL) *blue_Z = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z"); + info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z"); return (PNG_INFO_cHRM); } @@ -681,8 +681,8 @@ png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, png_debug1(1, "in %s retrieval function", "gAMA"); if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 && - file_gamma != NULL) + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 && + file_gamma != NULL) { *file_gamma = info_ptr->colorspace.gamma; return (PNG_INFO_gAMA); @@ -704,7 +704,7 @@ png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr, file_gamma != NULL) { *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma, - "png_get_gAMA"); + "png_get_gAMA"); return (PNG_INFO_gAMA); } @@ -901,7 +901,7 @@ png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, */ *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width"); *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height), - "sCAL height"); + "sCAL height"); return (PNG_INFO_sCAL); } @@ -1142,19 +1142,19 @@ png_get_compression_buffer_size(png_const_structrp png_ptr) return 0; #ifdef PNG_WRITE_SUPPORTED - if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0) + if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0) #endif { #ifdef PNG_SEQUENTIAL_READ_SUPPORTED - return png_ptr->IDAT_read_size; + return png_ptr->IDAT_read_size; #else - return PNG_IDAT_READ_SIZE; + return PNG_IDAT_READ_SIZE; #endif } #ifdef PNG_WRITE_SUPPORTED - else - return png_ptr->zbuffer_size; + else + return png_ptr->zbuffer_size; #endif } diff --git a/3rdparty/libpng/pnginfo.h b/3rdparty/libpng/pnginfo.h index c8c874dd1e..361ed8be70 100644 --- a/3rdparty/libpng/pnginfo.h +++ b/3rdparty/libpng/pnginfo.h @@ -2,7 +2,7 @@ /* pnginfo.h - header file for PNG reference library * * Last changed in libpng 1.6.1 [March 28, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -223,7 +223,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) /* Storage for unknown chunks that the library doesn't recognize. */ png_unknown_chunkp unknown_chunks; - /* The type of this field is limited by the type of + /* The type of this field is limited by the type of * png_struct::user_chunk_cache_max, else overflow can occur. */ int unknown_chunks_num; diff --git a/3rdparty/libpng/pnglibconf.h b/3rdparty/libpng/pnglibconf.h index ff5d156a6b..d91d9f4199 100644 --- a/3rdparty/libpng/pnglibconf.h +++ b/3rdparty/libpng/pnglibconf.h @@ -1,8 +1,8 @@ -/* libpng 1.6.19 STANDARD API DEFINITION */ +/* libpng 1.6.24 STANDARD API DEFINITION */ /* pnglibconf.h - library build configuration */ -/* Libpng version 1.6.19 - November 12, 2015 */ +/* Libpng version 1.6.24 - August 4, 2016 */ /* Copyright (c) 1998-2015 Glenn Randers-Pehrson */ @@ -109,6 +109,7 @@ #define PNG_SIMPLIFIED_READ_SUPPORTED #define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED #define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED #define PNG_SIMPLIFIED_WRITE_SUPPORTED #define PNG_STDIO_SUPPORTED #define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED diff --git a/3rdparty/libpng/pngmem.c b/3rdparty/libpng/pngmem.c index 45ac5579b2..6033bf2f56 100644 --- a/3rdparty/libpng/pngmem.c +++ b/3rdparty/libpng/pngmem.c @@ -1,8 +1,8 @@ /* pngmem.c - stub functions for memory allocation * - * Last changed in libpng 1.6.15 [November 20, 2014] - * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -66,7 +66,7 @@ png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) */ PNG_FUNCTION(png_voidp /* PRIVATE */, png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), - PNG_ALLOCATED) + PNG_ALLOCATED) { /* Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS * allocators have also been removed in 1.6.0, so any 16-bit system now has @@ -107,7 +107,7 @@ png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), */ static png_voidp png_malloc_array_checked(png_const_structrp png_ptr, int nelements, - size_t element_size) + size_t element_size) { png_alloc_size_t req = nelements; /* known to be > 0 */ @@ -120,7 +120,7 @@ png_malloc_array_checked(png_const_structrp png_ptr, int nelements, PNG_FUNCTION(png_voidp /* PRIVATE */, png_malloc_array,(png_const_structrp png_ptr, int nelements, - size_t element_size),PNG_ALLOCATED) + size_t element_size),PNG_ALLOCATED) { if (nelements <= 0 || element_size == 0) png_error(png_ptr, "internal error: array alloc"); @@ -130,7 +130,7 @@ png_malloc_array,(png_const_structrp png_ptr, int nelements, PNG_FUNCTION(png_voidp /* PRIVATE */, png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array, - int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED) + int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED) { /* These are internal errors: */ if (add_elements <= 0 || element_size == 0 || old_elements < 0 || @@ -143,7 +143,7 @@ png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array, if (add_elements <= INT_MAX - old_elements) { png_voidp new_array = png_malloc_array_checked(png_ptr, - old_elements+add_elements, element_size); + old_elements+add_elements, element_size); if (new_array != NULL) { @@ -154,7 +154,7 @@ png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array, memcpy(new_array, old_array, element_size*(unsigned)old_elements); memset((char*)new_array + element_size*(unsigned)old_elements, 0, - element_size*(unsigned)add_elements); + element_size*(unsigned)add_elements); return new_array; } @@ -187,7 +187,7 @@ png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) #ifdef PNG_USER_MEM_SUPPORTED PNG_FUNCTION(png_voidp,PNGAPI png_malloc_default,(png_const_structrp png_ptr, png_alloc_size_t size), - PNG_ALLOCATED PNG_DEPRECATED) + PNG_ALLOCATED PNG_DEPRECATED) { png_voidp ret; @@ -210,7 +210,7 @@ png_malloc_default,(png_const_structrp png_ptr, png_alloc_size_t size), */ PNG_FUNCTION(png_voidp,PNGAPI png_malloc_warn,(png_const_structrp png_ptr, png_alloc_size_t size), - PNG_ALLOCATED) + PNG_ALLOCATED) { if (png_ptr != NULL) { diff --git a/3rdparty/libpng/pngpread.c b/3rdparty/libpng/pngpread.c index 9f68f99023..794352f42c 100644 --- a/3rdparty/libpng/pngpread.c +++ b/3rdparty/libpng/pngpread.c @@ -1,8 +1,8 @@ /* pngpread.c - read a png file in push mode * - * Last changed in libpng 1.6.18 [July 23, 2015] - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -77,11 +77,11 @@ png_process_data_pause(png_structrp png_ptr, int save) png_uint_32 PNGAPI png_process_data_skip(png_structrp png_ptr) { - /* TODO: Deprecate and remove this API. - * Somewhere the implementation of this seems to have been lost, - * or abandoned. It was only to support some internal back-door access - * to png_struct) in libpng-1.4.x. - */ +/* TODO: Deprecate and remove this API. + * Somewhere the implementation of this seems to have been lost, + * or abandoned. It was only to support some internal back-door access + * to png_struct) in libpng-1.4.x. + */ png_app_warning(png_ptr, "png_process_data_skip is not implemented in any current version of libpng"); return 0; @@ -133,7 +133,7 @@ png_process_some_data(png_structrp png_ptr, png_inforp info_ptr) void /* PRIVATE */ png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) { - png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */ + png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */ num_to_check = 8 - num_checked; if (png_ptr->buffer_size < num_to_check) @@ -210,12 +210,14 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) (png_ptr->mode & PNG_HAVE_PLTE) == 0) png_error(png_ptr, "Missing PLTE before IDAT"); - png_ptr->mode |= PNG_HAVE_IDAT; png_ptr->process_mode = PNG_READ_IDAT_MODE; - if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0) - if (png_ptr->push_length == 0) - return; + if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) + if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0) + if (png_ptr->push_length == 0) + return; + + png_ptr->mode |= PNG_HAVE_IDAT; if ((png_ptr->mode & PNG_AFTER_IDAT) != 0) png_benign_error(png_ptr, "Too many IDATs found"); @@ -408,7 +410,7 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) { PNG_PUSH_SAVE_BUFFER_IF_FULL png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, - PNG_HANDLE_CHUNK_AS_DEFAULT); + PNG_HANDLE_CHUNK_AS_DEFAULT); } png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; @@ -499,7 +501,10 @@ png_push_save_buffer(png_structrp png_ptr) png_error(png_ptr, "Insufficient memory for save_buffer"); } - memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); + if (old_buffer) + memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); + else if (png_ptr->save_buffer_size) + png_error(png_ptr, "save_buffer error"); png_free(png_ptr, old_buffer); png_ptr->save_buffer_max = new_max; } @@ -516,7 +521,7 @@ png_push_save_buffer(png_structrp png_ptr) void /* PRIVATE */ png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer, - png_size_t buffer_length) + png_size_t buffer_length) { png_ptr->current_buffer = buffer; png_ptr->current_buffer_size = buffer_length; @@ -619,7 +624,7 @@ png_push_read_IDAT(png_structrp png_ptr) void /* PRIVATE */ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, - png_size_t buffer_length) + png_size_t buffer_length) { /* The caller checks for a non-zero buffer length. */ if (!(buffer_length > 0) || buffer == NULL) @@ -662,7 +667,7 @@ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, * change the current behavior (see comments in inflate.c * for why this doesn't happen at present with zlib 1.2.5). */ - ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH); + ret = PNG_INFLATE(png_ptr, Z_SYNC_FLUSH); /* Check for any failure before proceeding. */ if (ret != Z_OK && ret != Z_STREAM_END) @@ -777,7 +782,7 @@ png_push_process_row(png_structrp png_ptr) { if (png_ptr->pass < 6) png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, - png_ptr->transformations); + png_ptr->transformations); switch (png_ptr->pass) { @@ -1039,7 +1044,7 @@ png_push_have_row(png_structrp png_ptr, png_bytep row) { if (png_ptr->row_fn != NULL) (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, - (int)png_ptr->pass); + (int)png_ptr->pass); } #ifdef PNG_READ_INTERLACING_SUPPORTED diff --git a/3rdparty/libpng/pngpriv.h b/3rdparty/libpng/pngpriv.h index e30b0434ac..c0aa785f2b 100644 --- a/3rdparty/libpng/pngpriv.h +++ b/3rdparty/libpng/pngpriv.h @@ -1,8 +1,8 @@ /* pngpriv.h - private declarations for use inside libpng * - * Last changed in libpng 1.6.18 [July 23, 2015] - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -182,6 +182,42 @@ # endif #endif /* PNG_ARM_NEON_OPT > 0 */ +#ifndef PNG_INTEL_SSE_OPT +# ifdef PNG_INTEL_SSE + /* Only check for SSE if the build configuration has been modified to + * enable SSE optimizations. This means that these optimizations will + * be off by default. See contrib/intel for more details. + */ +# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \ + defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ + (defined(_M_IX86_FP) && _M_IX86_FP >= 2) +# define PNG_INTEL_SSE_OPT 1 +# endif +# endif +#endif + +#if defined(PNG_INTEL_SSE_OPT) && PNG_INTEL_SSE_OPT > 0 +# ifndef PNG_INTEL_SSE_IMPLEMENTATION +# if defined(__SSE4_1__) || defined(__AVX__) + /* We are not actually using AVX, but checking for AVX is the best + way we can detect SSE4.1 and SSSE3 on MSVC. + */ +# define PNG_INTEL_SSE_IMPLEMENTATION 3 +# elif defined(__SSSE3__) +# define PNG_INTEL_SSE_IMPLEMENTATION 2 +# elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ + (defined(_M_IX86_FP) && _M_IX86_FP >= 2) +# define PNG_INTEL_SSE_IMPLEMENTATION 1 +# else +# define PNG_INTEL_SSE_IMPLEMENTATION 0 +# endif +# endif + +# if PNG_INTEL_SSE_IMPLEMENTATION > 0 +# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2 +# endif +#endif + /* Is this a build of a DLL where compilation of the object modules requires * different preprocessor settings to those required for a simple library? If * so PNG_BUILD_DLL must be set. @@ -420,10 +456,10 @@ # if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) - /* We need to check that hasn't already been included earlier - * as it seems it doesn't agree with , yet we should really use - * if possible. - */ + /* We need to check that hasn't already been included earlier + * as it seems it doesn't agree with , yet we should really use + * if possible. + */ # if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) # include # endif @@ -431,9 +467,9 @@ # include # endif # if defined(_AMIGA) && defined(__SASC) && defined(_M68881) - /* Amiga SAS/C: We must include builtin FPU functions when compiling using - * MATH=68881 - */ + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ # include # endif #endif @@ -1025,7 +1061,7 @@ PNG_INTERNAL_FUNCTION(void,png_write_sBIT,(png_structrp png_ptr, #ifdef PNG_WRITE_cHRM_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_write_cHRM_fixed,(png_structrp png_ptr, const png_xy *xy), PNG_EMPTY); - /* The xy value must have been previously validated */ + /* The xy value must have been previously validated */ #endif #ifdef PNG_WRITE_sRGB_SUPPORTED @@ -1174,6 +1210,7 @@ PNG_INTERNAL_FUNCTION(void,png_do_write_interlace,(png_row_infop row_info, PNG_INTERNAL_FUNCTION(void,png_read_filter_row,(png_structrp pp, png_row_infop row_info, png_bytep row, png_const_bytep prev_row, int filter),PNG_EMPTY); +#if PNG_ARM_NEON_OPT > 0 PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_neon,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,(png_row_infop @@ -1188,6 +1225,22 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +#endif + +#if defined(PNG_INTEL_SSE_IMPLEMENTATION) && PNG_INTEL_SSE_IMPLEMENTATION > 0 +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +#endif /* Choose the best filter to use and filter the row data */ PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr, @@ -1215,6 +1268,14 @@ PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr), /* Initialize the row buffers, etc. */ PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY); +#if PNG_ZLIB_VERNUM >= 0x1240 +PNG_INTERNAL_FUNCTION(int,png_zlib_inflate,(png_structrp png_ptr, int flush), + PNG_EMPTY); +# define PNG_INFLATE(pp, flush) png_zlib_inflate(pp, flush) +#else /* Zlib < 1.2.4 */ +# define PNG_INFLATE(pp, flush) inflate(&(pp)->zstream, flush) +#endif /* Zlib < 1.2.4 */ + #ifdef PNG_READ_TRANSFORMS_SUPPORTED /* Optional call to update the users info structure */ PNG_INTERNAL_FUNCTION(void,png_read_transform_info,(png_structrp png_ptr, @@ -1405,7 +1466,7 @@ PNG_INTERNAL_FUNCTION(void,png_push_have_info,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_push_have_end,(png_structrp png_ptr, png_inforp info_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_have_row,(png_structrp png_ptr, - png_bytep row),PNG_EMPTY); + png_bytep row),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_read_end,(png_structrp png_ptr, png_inforp info_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_process_some_data,(png_structrp png_ptr, @@ -1444,13 +1505,13 @@ PNG_INTERNAL_FUNCTION(void,png_colorspace_set_gamma,(png_const_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_colorspace_sync_info,(png_const_structrp png_ptr, png_inforp info_ptr), PNG_EMPTY); - /* Synchronize the info 'valid' flags with the colorspace */ + /* Synchronize the info 'valid' flags with the colorspace */ PNG_INTERNAL_FUNCTION(void,png_colorspace_sync,(png_const_structrp png_ptr, png_inforp info_ptr), PNG_EMPTY); - /* Copy the png_struct colorspace to the info_struct and call the above to - * synchronize the flags. Checks for NULL info_ptr and does nothing. - */ + /* Copy the png_struct colorspace to the info_struct and call the above to + * synchronize the flags. Checks for NULL info_ptr and does nothing. + */ #endif /* Added at libpng version 1.4.0 */ @@ -1905,10 +1966,19 @@ PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr, * the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in * CFLAGS in place of CPPFLAGS *and* uses symbol prefixing. */ +# if PNG_ARM_NEON_OPT > 0 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); +# endif +# if defined(PNG_INTEL_SSE_IMPLEMENTATION) && PNG_INTEL_SSE_IMPLEMENTATION > 0 +PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, + (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); +# endif #endif +PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr, + png_const_charp key, png_bytep new_key), PNG_EMPTY); + /* Maintainer: Put new private prototypes here ^ */ #include "pngdebug.h" diff --git a/3rdparty/libpng/pngread.c b/3rdparty/libpng/pngread.c index 48aae84881..1000326922 100644 --- a/3rdparty/libpng/pngread.c +++ b/3rdparty/libpng/pngread.c @@ -1,8 +1,8 @@ /* pngread.c - read a PNG file * - * Last changed in libpng 1.6.17 [March 26, 2015] - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -28,10 +28,10 @@ png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr, { #ifndef PNG_USER_MEM_SUPPORTED png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, - error_fn, warn_fn, NULL, NULL, NULL); + error_fn, warn_fn, NULL, NULL, NULL); #else return png_create_read_struct_2(user_png_ver, error_ptr, error_fn, - warn_fn, NULL, NULL, NULL); + warn_fn, NULL, NULL, NULL); } /* Alternate create PNG structure for reading, and allocate any memory @@ -43,7 +43,7 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) { png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, - error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); + error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); #endif /* USER_MEM */ if (png_ptr != NULL) @@ -127,7 +127,10 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) } else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) + { + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; png_ptr->mode |= PNG_AFTER_IDAT; + } /* This should be a binary subdivision search or a hash for * matching the chunk name rather than a linear search. @@ -249,7 +252,7 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) else png_handle_unknown(png_ptr, info_ptr, length, - PNG_HANDLE_CHUNK_AS_DEFAULT); + PNG_HANDLE_CHUNK_AS_DEFAULT); } } #endif /* SEQUENTIAL_READ */ @@ -276,7 +279,7 @@ png_read_update_info(png_structrp png_ptr, png_inforp info_ptr) /* New in 1.6.0 this avoids the bug of doing the initializations twice */ else png_app_error(png_ptr, - "png_read_update_info/png_start_read_image: duplicate call"); + "png_read_update_info/png_start_read_image: duplicate call"); } } @@ -299,7 +302,7 @@ png_start_read_image(png_structrp png_ptr) /* New in 1.6.0 this avoids the bug of doing the initializations twice */ else png_app_error(png_ptr, - "png_start_read_image/png_read_update_info: duplicate call"); + "png_start_read_image/png_read_update_info: duplicate call"); } } #endif /* SEQUENTIAL_READ */ @@ -537,7 +540,7 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) { if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, - png_ptr->prev_row + 1, png_ptr->row_buf[0]); + png_ptr->prev_row + 1, png_ptr->row_buf[0]); else png_error(png_ptr, "bad adaptive filter value"); } @@ -581,7 +584,7 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) { if (png_ptr->pass < 6) png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, - png_ptr->transformations); + png_ptr->transformations); if (dsp_row != NULL) png_combine_row(png_ptr, dsp_row, 1/*display*/); @@ -716,7 +719,7 @@ png_read_image(png_structrp png_ptr, png_bytepp image) * but the caller should do it! */ png_warning(png_ptr, "Interlace handling should be turned on when " - "using png_read_image"); + "using png_read_image"); /* Make sure this is set correctly */ png_ptr->num_rows = png_ptr->height; } @@ -776,8 +779,8 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED /* Report invalid palette index; added at libng-1.5.10 */ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - png_ptr->num_palette_max > png_ptr->num_palette) - png_benign_error(png_ptr, "Read palette index exceeding num_palette"); + png_ptr->num_palette_max > png_ptr->num_palette) + png_benign_error(png_ptr, "Read palette index exceeding num_palette"); #endif do @@ -785,6 +788,9 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) png_uint_32 length = png_read_chunk_header(png_ptr); png_uint_32 chunk_name = png_ptr->chunk_name; + if (chunk_name != png_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + if (chunk_name == png_IEND) png_handle_IEND(png_ptr, info_ptr, length); @@ -799,9 +805,9 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) { if (chunk_name == png_IDAT) { - if ((length > 0) || - (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0) - png_benign_error(png_ptr, "Too many IDATs found"); + if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) + || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0) + png_benign_error(png_ptr, ".Too many IDATs found"); } png_handle_unknown(png_ptr, info_ptr, length, keep); if (chunk_name == png_PLTE) @@ -812,10 +818,14 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) else if (chunk_name == png_IDAT) { /* Zero length IDATs are legal after the last IDAT has been - * read, but not after other chunks have been read. + * read, but not after other chunks have been read. 1.6 does not + * always read all the deflate data; specifically it cannot be relied + * upon to read the Adler32 at the end. If it doesn't ignore IDAT + * chunks which are longer than zero as well: */ - if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0) - png_benign_error(png_ptr, "Too many IDATs found"); + if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) + || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0) + png_benign_error(png_ptr, "..Too many IDATs found"); png_crc_finish(png_ptr, length); } @@ -909,7 +919,7 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) else png_handle_unknown(png_ptr, info_ptr, length, - PNG_HANDLE_CHUNK_AS_DEFAULT); + PNG_HANDLE_CHUNK_AS_DEFAULT); } while ((png_ptr->mode & PNG_HAVE_IEND) == 0); } #endif /* SEQUENTIAL_READ */ @@ -1020,8 +1030,7 @@ png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn) #ifdef PNG_INFO_IMAGE_SUPPORTED void PNGAPI png_read_png(png_structrp png_ptr, png_inforp info_ptr, - int transforms, - voidp params) + int transforms, voidp params) { if (png_ptr == NULL || info_ptr == NULL) return; @@ -1297,7 +1306,7 @@ png_image_read_init(png_imagep image) if (info_ptr != NULL) { png_controlp control = png_voidcast(png_controlp, - png_malloc_warn(png_ptr, (sizeof *control))); + png_malloc_warn(png_ptr, (sizeof *control))); if (control != NULL) { @@ -1460,12 +1469,12 @@ png_image_begin_read_from_stdio(png_imagep image, FILE* file) else return png_image_error(image, - "png_image_begin_read_from_stdio: invalid argument"); + "png_image_begin_read_from_stdio: invalid argument"); } else if (image != NULL) return png_image_error(image, - "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION"); + "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION"); return 0; } @@ -1498,12 +1507,12 @@ png_image_begin_read_from_file(png_imagep image, const char *file_name) else return png_image_error(image, - "png_image_begin_read_from_file: invalid argument"); + "png_image_begin_read_from_file: invalid argument"); } else if (image != NULL) return png_image_error(image, - "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION"); + "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION"); return 0; } @@ -1540,7 +1549,7 @@ png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) } int PNGAPI png_image_begin_read_from_memory(png_imagep image, - png_const_voidp memory, png_size_t size) + png_const_voidp memory, png_size_t size) { if (image != NULL && image->version == PNG_IMAGE_VERSION) { @@ -1563,12 +1572,12 @@ int PNGAPI png_image_begin_read_from_memory(png_imagep image, else return png_image_error(image, - "png_image_begin_read_from_memory: invalid argument"); + "png_image_begin_read_from_memory: invalid argument"); } else if (image != NULL) return png_image_error(image, - "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION"); + "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION"); return 0; } @@ -1614,12 +1623,12 @@ png_image_skip_unused_chunks(png_structrp png_ptr) * IHDR, PLTE, tRNS, IDAT, and IEND chunks. */ png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER, - NULL, -1); + NULL, -1); /* But do not ignore image data handling chunks */ png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT, - chunks_to_process, (int)/*SAFE*/(sizeof chunks_to_process)/5); - } + chunks_to_process, (int)/*SAFE*/(sizeof chunks_to_process)/5); + } } # define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p) @@ -1686,7 +1695,7 @@ decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) #ifdef __GNUC__ default: png_error(display->image->opaque->png_ptr, - "unexpected encoding (internal error)"); + "unexpected encoding (internal error)"); #endif } @@ -1695,8 +1704,8 @@ decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) static png_uint_32 png_colormap_compose(png_image_read_control *display, - png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha, - png_uint_32 background, int encoding) + png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha, + png_uint_32 background, int encoding) { /* The file value is composed on the background, the background has the given * encoding and so does the result, the file is encoded with P_FILE and the @@ -1732,14 +1741,14 @@ png_colormap_compose(png_image_read_control *display, */ static void png_create_colormap_entry(png_image_read_control *display, - png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue, - png_uint_32 alpha, int encoding) + png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue, + png_uint_32 alpha, int encoding) { png_imagep image = display->image; const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ? - P_LINEAR : P_sRGB; + P_LINEAR : P_sRGB; const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && - (red != green || green != blue); + (red != green || green != blue); if (ip > 255) png_error(image->opaque->png_ptr, "color-map index out of range"); @@ -2019,7 +2028,7 @@ make_ga_colormap(png_image_read_control *display) for (g=0; g<6; ++g) png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51, - P_sRGB); + P_sRGB); } return i; @@ -2043,7 +2052,7 @@ make_rgb_colormap(png_image_read_control *display) for (b=0; b<6; ++b) png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255, - P_sRGB); + P_sRGB); } } @@ -2095,7 +2104,7 @@ png_image_read_colormap(png_voidp argument) else if (display->background == NULL /* no way to remove it */) png_error(png_ptr, - "a background color must be supplied to remove alpha/transparency"); + "background color must be supplied to remove alpha/transparency"); /* Get a copy of the background color (this avoids repeating the checks * below.) The encoding is 8-bit sRGB or 16-bit linear, depending on the @@ -2190,7 +2199,7 @@ png_image_read_colormap(png_voidp argument) */ if (i != trans) png_create_colormap_entry(display, i, val, val, val, 255, - P_FILE/*8-bit with file gamma*/); + P_FILE/*8-bit with file gamma*/); /* Else this entry is transparent. The colors don't matter if * there is an alpha channel (back_alpha == 0), but it does no @@ -2202,7 +2211,7 @@ png_image_read_colormap(png_voidp argument) */ else png_create_colormap_entry(display, i, back_r, back_g, back_b, - back_alpha, output_encoding); + back_alpha, output_encoding); } /* We need libpng to preserve the original encoding. */ @@ -2267,7 +2276,7 @@ png_image_read_colormap(png_voidp argument) * matches. */ png_create_colormap_entry(display, gray, back_g, back_g, - back_g, 65535, P_LINEAR); + back_g, 65535, P_LINEAR); } /* The background passed to libpng, however, must be the @@ -2281,8 +2290,8 @@ png_image_read_colormap(png_voidp argument) * doesn't. */ png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); output_processing = PNG_CMAP_NONE; break; @@ -2312,7 +2321,7 @@ png_image_read_colormap(png_voidp argument) * background color at full precision. */ png_create_colormap_entry(display, 254, back_r, back_g, back_b, - back_alpha, output_encoding); + back_alpha, output_encoding); } else @@ -2380,7 +2389,7 @@ png_image_read_colormap(png_voidp argument) /* And make sure the corresponding palette entry matches. */ png_create_colormap_entry(display, gray, back_g, back_g, - back_g, 65535, P_LINEAR); + back_g, 65535, P_LINEAR); } /* The background passed to libpng, however, must be the sRGB @@ -2390,8 +2399,8 @@ png_image_read_colormap(png_voidp argument) c.gray = c.red = c.green = c.blue = (png_uint_16)gray; png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); output_processing = PNG_CMAP_NONE; } @@ -2411,7 +2420,7 @@ png_image_read_colormap(png_voidp argument) { png_uint_32 gray = (i * 256 + 115) / 231; png_create_colormap_entry(display, i++, gray, gray, gray, - 255, P_sRGB); + 255, P_sRGB); } /* NOTE: this preserves the full precision of the application @@ -2420,13 +2429,13 @@ png_image_read_colormap(png_voidp argument) background_index = i; png_create_colormap_entry(display, i++, back_r, back_g, back_b, #ifdef __COVERITY__ - /* Coverity claims that output_encoding cannot be 2 (P_LINEAR) - * here. - */ 255U, + /* Coverity claims that output_encoding + * cannot be 2 (P_LINEAR) here. + */ 255U, #else - output_encoding == P_LINEAR ? 65535U : 255U, + output_encoding == P_LINEAR ? 65535U : 255U, #endif - output_encoding); + output_encoding); /* For non-opaque input composite on the sRGB background - this * requires inverting the encoding for each component. The input @@ -2464,9 +2473,9 @@ png_image_read_colormap(png_voidp argument) png_uint_32 gray = png_sRGB_table[g*51] * alpha; png_create_colormap_entry(display, i++, - PNG_sRGB_FROM_LINEAR(gray + back_rx), - PNG_sRGB_FROM_LINEAR(gray + back_gx), - PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB); + PNG_sRGB_FROM_LINEAR(gray + back_rx), + PNG_sRGB_FROM_LINEAR(gray + back_gx), + PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB); } } @@ -2492,7 +2501,7 @@ png_image_read_colormap(png_voidp argument) * png_set_tRNS_to_alpha before png_set_background_fixed. */ png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1, - -1); + -1); data_encoding = P_sRGB; /* The output will now be one or two 8-bit gray or gray+alpha @@ -2568,13 +2577,13 @@ png_image_read_colormap(png_voidp argument) gray = png_sRGB_table[gray]; /* now P_LINEAR */ gray = PNG_DIV257(png_gamma_16bit_correct(gray, - png_ptr->colorspace.gamma)); /* now P_FILE */ + png_ptr->colorspace.gamma)); /* now P_FILE */ /* And make sure the corresponding palette entry contains * exactly the required sRGB value. */ png_create_colormap_entry(display, gray, back_g, back_g, - back_g, 0/*unused*/, output_encoding); + back_g, 0/*unused*/, output_encoding); } else if (output_encoding == P_LINEAR) @@ -2599,8 +2608,8 @@ png_image_read_colormap(png_voidp argument) */ expand_tRNS = 1; png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); } output_processing = PNG_CMAP_NONE; @@ -2634,7 +2643,7 @@ png_image_read_colormap(png_voidp argument) /* Add a transparent entry. */ png_create_colormap_entry(display, cmap_entries, 255, 255, - 255, 0, P_sRGB); + 255, 0, P_sRGB); /* This is stored as the background index for the processing * algorithm. @@ -2655,7 +2664,7 @@ png_image_read_colormap(png_voidp argument) */ for (b=0; b<256; b = (b << 1) | 0x7f) png_create_colormap_entry(display, cmap_entries++, - r, g, b, 128, P_sRGB); + r, g, b, 128, P_sRGB); } } @@ -2682,7 +2691,7 @@ png_image_read_colormap(png_voidp argument) cmap_entries = make_rgb_colormap(display); png_create_colormap_entry(display, cmap_entries, back_r, - back_g, back_b, 0/*unused*/, output_encoding); + back_g, back_b, 0/*unused*/, output_encoding); if (output_encoding == P_LINEAR) { @@ -2704,9 +2713,9 @@ png_image_read_colormap(png_voidp argument) * index. */ if (memcmp((png_const_bytep)display->colormap + - sample_size * cmap_entries, - (png_const_bytep)display->colormap + - sample_size * PNG_RGB_INDEX(r,g,b), + sample_size * cmap_entries, + (png_const_bytep)display->colormap + + sample_size * PNG_RGB_INDEX(r,g,b), sample_size) != 0) { /* The background color must be added. */ @@ -2724,13 +2733,13 @@ png_image_read_colormap(png_voidp argument) */ for (b=0; b<256; b = (b << 1) | 0x7f) png_create_colormap_entry(display, cmap_entries++, - png_colormap_compose(display, r, P_sRGB, 128, - back_r, output_encoding), - png_colormap_compose(display, g, P_sRGB, 128, - back_g, output_encoding), - png_colormap_compose(display, b, P_sRGB, 128, - back_b, output_encoding), - 0/*unused*/, output_encoding); + png_colormap_compose(display, r, P_sRGB, 128, + back_r, output_encoding), + png_colormap_compose(display, g, P_sRGB, 128, + back_g, output_encoding), + png_colormap_compose(display, b, P_sRGB, 128, + back_b, output_encoding), + 0/*unused*/, output_encoding); } } @@ -2748,8 +2757,8 @@ png_image_read_colormap(png_voidp argument) c.blue = (png_uint_16)back_b; png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); output_processing = PNG_CMAP_RGB; } @@ -2801,7 +2810,7 @@ png_image_read_colormap(png_voidp argument) { if (trans[i] == 0) png_create_colormap_entry(display, i, back_r, back_g, - back_b, 0, output_encoding); + back_b, 0, output_encoding); else { @@ -2809,22 +2818,22 @@ png_image_read_colormap(png_voidp argument) * on the sRGB color in 'back'. */ png_create_colormap_entry(display, i, - png_colormap_compose(display, colormap[i].red, P_FILE, - trans[i], back_r, output_encoding), - png_colormap_compose(display, colormap[i].green, P_FILE, - trans[i], back_g, output_encoding), - png_colormap_compose(display, colormap[i].blue, P_FILE, - trans[i], back_b, output_encoding), - output_encoding == P_LINEAR ? trans[i] * 257U : - trans[i], - output_encoding); + png_colormap_compose(display, colormap[i].red, + P_FILE, trans[i], back_r, output_encoding), + png_colormap_compose(display, colormap[i].green, + P_FILE, trans[i], back_g, output_encoding), + png_colormap_compose(display, colormap[i].blue, + P_FILE, trans[i], back_b, output_encoding), + output_encoding == P_LINEAR ? trans[i] * 257U : + trans[i], + output_encoding); } } else png_create_colormap_entry(display, i, colormap[i].red, - colormap[i].green, colormap[i].blue, - i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/); + colormap[i].green, colormap[i].blue, + i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/); } /* The PNG data may have indices packed in fewer than 8 bits, it @@ -2838,7 +2847,6 @@ png_image_read_colormap(png_voidp argument) default: png_error(png_ptr, "invalid PNG color type"); /*NOT REACHED*/ - break; } /* Now deal with the output processing */ @@ -2915,7 +2923,7 @@ static int png_image_read_and_map(png_voidp argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, - argument); + argument); png_imagep image = display->image; png_structrp png_ptr = image->opaque->png_ptr; int passes; @@ -3052,7 +3060,7 @@ png_image_read_and_map(png_voidp argument) if (alpha >= 196) *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], - inrow[2]); + inrow[2]); else if (alpha < 64) *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND; @@ -3104,7 +3112,7 @@ static int png_image_read_colormapped(png_voidp argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, - argument); + argument); png_imagep image = display->image; png_controlp control = image->opaque; png_structrp png_ptr = control->png_ptr; @@ -3237,7 +3245,7 @@ static int png_image_read_composite(png_voidp argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, - argument); + argument); png_imagep image = display->image; png_structrp png_ptr = image->opaque->png_ptr; int passes; @@ -3364,7 +3372,7 @@ static int png_image_read_background(png_voidp argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, - argument); + argument); png_imagep image = display->image; png_structrp png_ptr = image->opaque->png_ptr; png_inforp info_ptr = image->opaque->info_ptr; @@ -3424,8 +3432,7 @@ png_image_read_background(png_voidp argument) for (pass = 0; pass < passes; ++pass) { - png_bytep row = png_voidcast(png_bytep, - display->first_row); + png_bytep row = png_voidcast(png_bytep, display->first_row); unsigned int startx, stepx, stepy; png_uint_32 y; @@ -3453,7 +3460,7 @@ png_image_read_background(png_voidp argument) for (; ylocal_row); + display->local_row); png_bytep outrow = first_row + y * step_row; png_const_bytep end_row = outrow + width; @@ -3498,7 +3505,7 @@ png_image_read_background(png_voidp argument) for (; ylocal_row); + display->local_row); png_bytep outrow = first_row + y * step_row; png_const_bytep end_row = outrow + width; @@ -3545,7 +3552,7 @@ png_image_read_background(png_voidp argument) */ { png_uint_16p first_row = png_voidcast(png_uint_16p, - display->first_row); + display->first_row); /* The division by two is safe because the caller passed in a * stride which was multiplied by 2 (below) to get row_bytes. */ @@ -3595,7 +3602,7 @@ png_image_read_background(png_voidp argument) /* Read the row, which is packed: */ png_read_row(png_ptr, png_voidcast(png_bytep, - display->local_row), NULL); + display->local_row), NULL); inrow = png_voidcast(png_const_uint_16p, display->local_row); /* Now do the pre-multiplication on each pixel in this row. @@ -3644,7 +3651,7 @@ static int png_image_read_direct(png_voidp argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, - argument); + argument); png_imagep image = display->image; png_structrp png_ptr = image->opaque->png_ptr; png_inforp info_ptr = image->opaque->info_ptr; @@ -3695,7 +3702,7 @@ png_image_read_direct(png_voidp argument) do_local_background = 1/*maybe*/; png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, - PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT); + PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT); } change &= ~PNG_FORMAT_FLAG_COLOR; @@ -3754,7 +3761,7 @@ png_image_read_direct(png_voidp argument) * final value. */ if (png_muldiv(>est, output_gamma, png_ptr->colorspace.gamma, - PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0) + PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0) do_local_background = 0; else if (mode == PNG_ALPHA_STANDARD) @@ -3817,8 +3824,8 @@ png_image_read_direct(png_voidp argument) * pixels. */ png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); } else /* compose on row: implemented below. */ @@ -3849,16 +3856,16 @@ png_image_read_direct(png_voidp argument) else filler = 255; -# ifdef PNG_FORMAT_AFIRST_SUPPORTED - if ((format & PNG_FORMAT_FLAG_AFIRST) != 0) - { - where = PNG_FILLER_BEFORE; - change &= ~PNG_FORMAT_FLAG_AFIRST; - } +#ifdef PNG_FORMAT_AFIRST_SUPPORTED + if ((format & PNG_FORMAT_FLAG_AFIRST) != 0) + { + where = PNG_FILLER_BEFORE; + change &= ~PNG_FORMAT_FLAG_AFIRST; + } - else -# endif - where = PNG_FILLER_AFTER; + else +#endif + where = PNG_FILLER_AFTER; png_set_add_alpha(png_ptr, filler, where); } @@ -3966,12 +3973,12 @@ png_image_read_direct(png_voidp argument) if (info_ptr->bit_depth == 16) info_format |= PNG_FORMAT_FLAG_LINEAR; -# ifdef PNG_FORMAT_BGR_SUPPORTED - if ((png_ptr->transformations & PNG_BGR) != 0) - info_format |= PNG_FORMAT_FLAG_BGR; -# endif +#ifdef PNG_FORMAT_BGR_SUPPORTED + if ((png_ptr->transformations & PNG_BGR) != 0) + info_format |= PNG_FORMAT_FLAG_BGR; +#endif -# ifdef PNG_FORMAT_AFIRST_SUPPORTED +#ifdef PNG_FORMAT_AFIRST_SUPPORTED if (do_local_background == 2) { if ((format & PNG_FORMAT_FLAG_AFIRST) != 0) @@ -4068,67 +4075,117 @@ png_image_read_direct(png_voidp argument) int PNGAPI png_image_finish_read(png_imagep image, png_const_colorp background, - void *buffer, png_int_32 row_stride, void *colormap) + void *buffer, png_int_32 row_stride, void *colormap) { if (image != NULL && image->version == PNG_IMAGE_VERSION) { - png_uint_32 check; + /* Check for row_stride overflow. This check is not performed on the + * original PNG format because it may not occur in the output PNG format + * and libpng deals with the issues of reading the original. + */ + const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); - if (row_stride == 0) - row_stride = PNG_IMAGE_ROW_STRIDE(*image); - - if (row_stride < 0) - check = -row_stride; - - else - check = row_stride; - - if (image->opaque != NULL && buffer != NULL && - check >= PNG_IMAGE_ROW_STRIDE(*image)) + /* The following checks just the 'row_stride' calculation to ensure it + * fits in a signed 32-bit value. Because channels/components can be + * either 1 or 2 bytes in size the length of a row can still overflow 32 + * bits; this is just to verify that the 'row_stride' argument can be + * represented. + */ + if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */ { - if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 || - (image->colormap_entries > 0 && colormap != NULL)) + png_uint_32 check; + const png_uint_32 png_row_stride = image->width * channels; + + if (row_stride == 0) + row_stride = (png_int_32)/*SAFE*/png_row_stride; + + if (row_stride < 0) + check = -row_stride; + + else + check = row_stride; + + /* This verifies 'check', the absolute value of the actual stride + * passed in and detects overflow in the application calculation (i.e. + * if the app did actually pass in a non-zero 'row_stride'. + */ + if (image->opaque != NULL && buffer != NULL && check >= png_row_stride) { - int result; - png_image_read_control display; - - memset(&display, 0, (sizeof display)); - display.image = image; - display.buffer = buffer; - display.row_stride = row_stride; - display.colormap = colormap; - display.background = background; - display.local_row = NULL; - - /* Choose the correct 'end' routine; for the color-map case all the - * setup has already been done. + /* Now check for overflow of the image buffer calculation; this + * limits the whole image size to 32 bits for API compatibility with + * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro. + * + * The PNG_IMAGE_BUFFER_SIZE macro is: + * + * (PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)*height*(row_stride)) + * + * And the component size is always 1 or 2, so make sure that the + * number of *bytes* that the application is saying are available + * does actually fit into a 32-bit number. + * + * NOTE: this will be changed in 1.7 because PNG_IMAGE_BUFFER_SIZE + * will be changed to use png_alloc_size_t; bigger images can be + * accomodated on 64-bit systems. */ - if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0) - result = - png_safe_execute(image, png_image_read_colormap, &display) && - png_safe_execute(image, png_image_read_colormapped, &display); + if (image->height <= + 0xFFFFFFFFU/PNG_IMAGE_PIXEL_COMPONENT_SIZE(image->format)/check) + { + if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 || + (image->colormap_entries > 0 && colormap != NULL)) + { + int result; + png_image_read_control display; + + memset(&display, 0, (sizeof display)); + display.image = image; + display.buffer = buffer; + display.row_stride = row_stride; + display.colormap = colormap; + display.background = background; + display.local_row = NULL; + + /* Choose the correct 'end' routine; for the color-map case + * all the setup has already been done. + */ + if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0) + result = + png_safe_execute(image, + png_image_read_colormap, &display) && + png_safe_execute(image, + png_image_read_colormapped, &display); + + else + result = + png_safe_execute(image, + png_image_read_direct, &display); + + png_image_free(image); + return result; + } + + else + return png_image_error(image, + "png_image_finish_read[color-map]: no color-map"); + } else - result = - png_safe_execute(image, png_image_read_direct, &display); - - png_image_free(image); - return result; + return png_image_error(image, + "png_image_finish_read: image too large"); } else return png_image_error(image, - "png_image_finish_read[color-map]: no color-map"); + "png_image_finish_read: invalid argument"); } else return png_image_error(image, - "png_image_finish_read: invalid argument"); + "png_image_finish_read: row_stride too large"); } else if (image != NULL) return png_image_error(image, - "png_image_finish_read: damaged PNG_IMAGE_VERSION"); + "png_image_finish_read: damaged PNG_IMAGE_VERSION"); return 0; } diff --git a/3rdparty/libpng/pngrio.c b/3rdparty/libpng/pngrio.c index 38f7fd49d6..7e26e855ca 100644 --- a/3rdparty/libpng/pngrio.c +++ b/3rdparty/libpng/pngrio.c @@ -1,8 +1,8 @@ /* pngrio.c - functions for data input * - * Last changed in libpng 1.6.17 [March 26, 2015] - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -85,7 +85,7 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) */ void PNGAPI png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr, - png_rw_ptr read_data_fn) + png_rw_ptr read_data_fn) { if (png_ptr == NULL) return; diff --git a/3rdparty/libpng/pngrtran.c b/3rdparty/libpng/pngrtran.c index f129ef129c..748ffb3ed4 100644 --- a/3rdparty/libpng/pngrtran.c +++ b/3rdparty/libpng/pngrtran.c @@ -1,8 +1,8 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * Last changed in libpng 1.6.19 [November 12, 2015] - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -48,7 +48,7 @@ png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action) case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ png_warning(png_ptr, - "Can't discard critical data on CRC error"); + "Can't discard critical data on CRC error"); case PNG_CRC_ERROR_QUIT: /* Error/quit */ case PNG_CRC_DEFAULT: @@ -101,7 +101,7 @@ png_rtran_ok(png_structrp png_ptr, int need_IHDR) { if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0) png_app_error(png_ptr, - "invalid after png_start_read_image or png_read_update_info"); + "invalid after png_start_read_image or png_read_update_info"); else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0) png_app_error(png_ptr, "invalid before the PNG header has been read"); @@ -159,7 +159,7 @@ png_set_background(png_structrp png_ptr, png_set_background_fixed(png_ptr, background_color, background_gamma_code, need_expand, png_fixed(png_ptr, background_gamma, "png_set_background")); } -# endif /* FLOATING_POINT */ +# endif /* FLOATING_POINT */ #endif /* READ_BACKGROUND */ /* Scale 16-bit depth files to 8-bit depth. If both of these are set then the @@ -209,7 +209,7 @@ png_set_strip_alpha(png_structrp png_ptr) #if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED) static png_fixed_point translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma, - int is_screen) + int is_screen) { /* Check for flag values. The main reason for having the old Mac value as a * flag is that it is pretty near impossible to work out what the correct @@ -273,7 +273,7 @@ convert_gamma_value(png_structrp png_ptr, double output_gamma) #ifdef PNG_READ_ALPHA_MODE_SUPPORTED void PNGFAPI png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, - png_fixed_point output_gamma) + png_fixed_point output_gamma) { int compose = 0; png_fixed_point file_gamma; @@ -289,9 +289,12 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, * is expected to be 1 or greater, but this range test allows for some * viewing correction values. The intent is to weed out users of this API * who use the inverse of the gamma value accidentally! Since some of these - * values are reasonable this may have to be changed. + * values are reasonable this may have to be changed: + * + * 1.6.x: changed from 0.07..3 to 0.01..100 (to accomodate the optimal 16-bit + * gamma of 36, and its reciprocal.) */ - if (output_gamma < 70000 || output_gamma > 300000) + if (output_gamma < 1000 || output_gamma > 10000000) png_error(png_ptr, "output gamma out of expected range"); /* The default file gamma is the inverse of the output gamma; the output @@ -374,7 +377,7 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, if ((png_ptr->transformations & PNG_COMPOSE) != 0) png_error(png_ptr, - "conflicting calls to set alpha mode and background"); + "conflicting calls to set alpha mode and background"); png_ptr->transformations |= PNG_COMPOSE; } @@ -385,7 +388,7 @@ void PNGAPI png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma) { png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr, - output_gamma)); + output_gamma)); } # endif #endif @@ -799,7 +802,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, #ifdef PNG_READ_GAMMA_SUPPORTED void PNGFAPI png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma, - png_fixed_point file_gamma) + png_fixed_point file_gamma) { png_debug(1, "in png_set_gamma_fixed"); @@ -841,7 +844,7 @@ void PNGAPI png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma) { png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma), - convert_gamma_value(png_ptr, file_gamma)); + convert_gamma_value(png_ptr, file_gamma)); } # endif /* FLOATING_POINT */ #endif /* READ_GAMMA */ @@ -987,7 +990,7 @@ png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, * that it just worked and get a memory overwrite. */ png_error(png_ptr, - "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); + "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */ } @@ -1014,7 +1017,7 @@ png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, { if (red >= 0 && green >= 0) png_app_warning(png_ptr, - "ignoring out of range rgb_to_gray coefficients"); + "ignoring out of range rgb_to_gray coefficients"); /* Use the defaults, from the cHRM chunk if set, else the historical * values which are close to the sRGB/HDTV/ITU-Rec 709 values. See @@ -1023,7 +1026,7 @@ png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, * something has already provided a default. */ if (png_ptr->rgb_to_gray_red_coeff == 0 && - png_ptr->rgb_to_gray_green_coeff == 0) + png_ptr->rgb_to_gray_green_coeff == 0) { png_ptr->rgb_to_gray_red_coeff = 6968; png_ptr->rgb_to_gray_green_coeff = 23434; @@ -1040,10 +1043,10 @@ png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, void PNGAPI png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red, - double green) + double green) { png_set_rgb_to_gray_fixed(png_ptr, error_action, - png_fixed(png_ptr, red, "rgb to gray red coefficient"), + png_fixed(png_ptr, red, "rgb to gray red coefficient"), png_fixed(png_ptr, green, "rgb to gray green coefficient")); } #endif /* FLOATING POINT */ @@ -1300,7 +1303,7 @@ png_init_read_transformations(png_structrp png_ptr) { if (png_ptr->screen_gamma != 0) /* screen set too */ gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma, - png_ptr->screen_gamma); + png_ptr->screen_gamma); else /* Assume the output matches the input; a long time default behavior @@ -1581,7 +1584,7 @@ png_init_read_transformations(png_structrp png_ptr) */ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0) png_warning(png_ptr, - "libpng does not support gamma+background+rgb_to_gray"); + "libpng does not support gamma+background+rgb_to_gray"); if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0) { @@ -1617,13 +1620,13 @@ png_init_read_transformations(png_structrp png_ptr) case PNG_BACKGROUND_GAMMA_FILE: g = png_reciprocal(png_ptr->colorspace.gamma); gs = png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma); + png_ptr->screen_gamma); break; case PNG_BACKGROUND_GAMMA_UNIQUE: g = png_reciprocal(png_ptr->background_gamma); gs = png_reciprocal2(png_ptr->background_gamma, - png_ptr->screen_gamma); + png_ptr->screen_gamma); break; default: g = PNG_FP_1; /* back_1 */ @@ -1651,11 +1654,11 @@ png_init_read_transformations(png_structrp png_ptr) if (png_gamma_significant(g) != 0) { back_1.red = png_gamma_8bit_correct(png_ptr->background.red, - g); + g); back_1.green = png_gamma_8bit_correct( - png_ptr->background.green, g); + png_ptr->background.green, g); back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue, - g); + g); } else @@ -1726,7 +1729,7 @@ png_init_read_transformations(png_structrp png_ptr) case PNG_BACKGROUND_GAMMA_FILE: g = png_reciprocal(png_ptr->colorspace.gamma); gs = png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma); + png_ptr->screen_gamma); break; case PNG_BACKGROUND_GAMMA_UNIQUE: @@ -1912,7 +1915,7 @@ png_init_read_transformations(png_structrp png_ptr) png_ptr->palette[i].blue = (png_byte)component; } } -#endif /* READ_SHIFT */ +#endif /* READ_SHIFT */ } /* Modify the info structure to reflect the transformations. The @@ -4192,7 +4195,7 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) */ static void png_do_expand_palette(png_row_infop row_info, png_bytep row, - png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) + png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) { int shift, value; png_bytep sp, dp; @@ -4499,7 +4502,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, row_info->channels = 2; row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_width); + row_width); } } else if (row_info->color_type == PNG_COLOR_TYPE_RGB && @@ -4759,7 +4762,7 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) png_do_strip_channel(row_info, png_ptr->row_buf + 1, - 0 /* at_start == false, because SWAP_ALPHA happens later */); + 0 /* at_start == false, because SWAP_ALPHA happens later */); #endif #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED diff --git a/3rdparty/libpng/pngrutil.c b/3rdparty/libpng/pngrutil.c index ee584a8c40..1c8a179443 100644 --- a/3rdparty/libpng/pngrutil.c +++ b/3rdparty/libpng/pngrutil.c @@ -1,8 +1,8 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.6.19 [November 12, 2015] - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -90,7 +90,7 @@ png_get_int_32)(png_const_bytep buf) uval = (uval ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */ if ((uval & 0x80000000) == 0) /* no overflow */ - return -(png_int_32)uval; + return -(png_int_32)uval; /* The following has to be safe; this function only gets called on PNG data * and if we get here that data is invalid. 0 is the most safe value and * if not then an attacker would surely just generate a PNG with 0 instead. @@ -377,10 +377,16 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) if (((png_ptr->options >> PNG_MAXIMUM_INFLATE_WINDOW) & 3) == PNG_OPTION_ON) + { window_bits = 15; + png_ptr->zstream_start = 0; /* fixed window size */ + } else + { window_bits = 0; + png_ptr->zstream_start = 1; + } # else # define window_bits 0 # endif @@ -429,6 +435,31 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) #endif } +#if PNG_ZLIB_VERNUM >= 0x1240 +/* Handle the start of the inflate stream if we called inflateInit2(strm,0); + * in this case some zlib versions skip validation of the CINFO field and, in + * certain circumstances, libpng may end up displaying an invalid image, in + * contrast to implementations that call zlib in the normal way (e.g. libpng + * 1.5). + */ +int /* PRIVATE */ +png_zlib_inflate(png_structrp png_ptr, int flush) +{ + if (png_ptr->zstream_start && png_ptr->zstream.avail_in > 0) + { + if ((*png_ptr->zstream.next_in >> 4) > 7) + { + png_ptr->zstream.msg = "invalid window size (libpng)"; + return Z_DATA_ERROR; + } + + png_ptr->zstream_start = 0; + } + + return inflate(&png_ptr->zstream, flush); +} +#endif /* Zlib >= 1.2.4 */ + #ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED /* png_inflate now returns zlib error codes including Z_OK and Z_STREAM_END to * allow the caller to do multiple calls if required. If the 'finish' flag is @@ -522,7 +553,7 @@ png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish, * the previous chunk of input data. Tell zlib if we have reached the * end of the output buffer. */ - ret = inflate(&png_ptr->zstream, avail_out > 0 ? Z_NO_FLUSH : + ret = PNG_INFLATE(png_ptr, avail_out > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH)); } while (ret == Z_OK); @@ -559,6 +590,7 @@ png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish, } } +#if defined(PNG_READ_zTXt_SUPPORTED) || defined (PNG_READ_iTXt_SUPPORTED) /* * Decompress trailing data in a chunk. The assumption is that read_buffer * points at an allocated area holding the contents of a chunk with a @@ -568,9 +600,9 @@ png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish, */ static int png_decompress_chunk(png_structrp png_ptr, - png_uint_32 chunklength, png_uint_32 prefix_size, - png_alloc_size_t *newlength /* must be initialized to the maximum! */, - int terminate /*add a '\0' to the end of the uncompressed data*/) + png_uint_32 chunklength, png_uint_32 prefix_size, + png_alloc_size_t *newlength /* must be initialized to the maximum! */, + int terminate /*add a '\0' to the end of the uncompressed data*/) { /* TODO: implement different limits for different types of chunk. * @@ -607,8 +639,8 @@ png_decompress_chunk(png_structrp png_ptr, png_uint_32 lzsize = chunklength - prefix_size; ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/, - /* input: */ png_ptr->read_buffer + prefix_size, &lzsize, - /* output: */ NULL, newlength); + /* input: */ png_ptr->read_buffer + prefix_size, &lzsize, + /* output: */ NULL, newlength); if (ret == Z_STREAM_END) { @@ -628,15 +660,15 @@ png_decompress_chunk(png_structrp png_ptr, */ png_alloc_size_t new_size = *newlength; png_alloc_size_t buffer_size = prefix_size + new_size + - (terminate != 0); + (terminate != 0); png_bytep text = png_voidcast(png_bytep, png_malloc_base(png_ptr, - buffer_size)); + buffer_size)); if (text != NULL) { ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/, - png_ptr->read_buffer + prefix_size, &lzsize, - text + prefix_size, newlength); + png_ptr->read_buffer + prefix_size, &lzsize, + text + prefix_size, newlength); if (ret == Z_STREAM_END) { @@ -723,6 +755,7 @@ png_decompress_chunk(png_structrp png_ptr, return Z_MEM_ERROR; } } +#endif /* READ_zTXt || READ_iTXt */ #endif /* READ_COMPRESSED_TEXT */ #ifdef PNG_READ_iCCP_SUPPORTED @@ -731,8 +764,8 @@ png_decompress_chunk(png_structrp png_ptr, */ static int png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size, - png_uint_32p chunk_bytes, png_bytep next_out, png_alloc_size_t *out_size, - int finish) + png_uint_32p chunk_bytes, png_bytep next_out, png_alloc_size_t *out_size, + int finish) { if (png_ptr->zowner == png_ptr->chunk_name) { @@ -771,8 +804,8 @@ png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size, * the available output is produced; this allows reading of truncated * streams. */ - ret = inflate(&png_ptr->zstream, - *chunk_bytes > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH)); + ret = PNG_INFLATE(png_ptr, *chunk_bytes > 0 ? + Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH)); } while (ret == Z_OK && (*out_size > 0 || png_ptr->zstream.avail_out > 0)); @@ -1261,7 +1294,7 @@ png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; (void)png_colorspace_set_chromaticities(png_ptr, &png_ptr->colorspace, &xy, - 1/*prefer cHRM values*/); + 1/*prefer cHRM values*/); png_colorspace_sync(png_ptr, info_ptr); } #endif @@ -1401,8 +1434,8 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_ptr->zstream.next_in = (Bytef*)keyword + (keyword_length+2); png_ptr->zstream.avail_in = read_length; (void)png_inflate_read(png_ptr, local_buffer, - (sizeof local_buffer), &length, profile_header, &size, - 0/*finish: don't, because the output is too small*/); + (sizeof local_buffer), &length, profile_header, &size, + 0/*finish: don't, because the output is too small*/); if (size == 0) { @@ -1412,14 +1445,14 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_get_uint_32(profile_header); if (png_icc_check_length(png_ptr, &png_ptr->colorspace, - keyword, profile_length) != 0) + keyword, profile_length) != 0) { /* The length is apparently ok, so we can check the 132 * byte header. */ if (png_icc_check_header(png_ptr, &png_ptr->colorspace, - keyword, profile_length, profile_header, - png_ptr->color_type) != 0) + keyword, profile_length, profile_header, + png_ptr->color_type) != 0) { /* Now read the tag table; a variable size buffer is * needed at this point, allocate one for the whole @@ -1427,20 +1460,20 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) * that none of these stuff will overflow. */ const png_uint_32 tag_count = png_get_uint_32( - profile_header+128); + profile_header+128); png_bytep profile = png_read_buffer(png_ptr, - profile_length, 2/*silent*/); + profile_length, 2/*silent*/); if (profile != NULL) { memcpy(profile, profile_header, - (sizeof profile_header)); + (sizeof profile_header)); size = 12 * tag_count; (void)png_inflate_read(png_ptr, local_buffer, - (sizeof local_buffer), &length, - profile + (sizeof profile_header), &size, 0); + (sizeof local_buffer), &length, + profile + (sizeof profile_header), &size, 0); /* Still expect a buffer error because we expect * there to be some tag data! @@ -1448,22 +1481,22 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (size == 0) { if (png_icc_check_tag_table(png_ptr, - &png_ptr->colorspace, keyword, profile_length, - profile) != 0) + &png_ptr->colorspace, keyword, profile_length, + profile) != 0) { /* The profile has been validated for basic * security issues, so read the whole thing in. */ size = profile_length - (sizeof profile_header) - - 12 * tag_count; + - 12 * tag_count; (void)png_inflate_read(png_ptr, local_buffer, - (sizeof local_buffer), &length, - profile + (sizeof profile_header) + - 12 * tag_count, &size, 1/*finish*/); + (sizeof local_buffer), &length, + profile + (sizeof profile_header) + + 12 * tag_count, &size, 1/*finish*/); if (length > 0 && !(png_ptr->flags & - PNG_FLAG_BENIGN_ERRORS_WARN)) + PNG_FLAG_BENIGN_ERRORS_WARN)) errmsg = "extra compressed data"; /* But otherwise allow extra data: */ @@ -1475,34 +1508,34 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) * keep going. */ png_chunk_warning(png_ptr, - "extra compressed data"); + "extra compressed data"); } png_crc_finish(png_ptr, length); finished = 1; -# ifdef PNG_sRGB_SUPPORTED +# if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0 /* Check for a match against sRGB */ png_icc_set_sRGB(png_ptr, - &png_ptr->colorspace, profile, - png_ptr->zstream.adler); -# endif + &png_ptr->colorspace, profile, + png_ptr->zstream.adler); +# endif /* Steal the profile for info_ptr. */ if (info_ptr != NULL) { png_free_data(png_ptr, info_ptr, - PNG_FREE_ICCP, 0); + PNG_FREE_ICCP, 0); info_ptr->iccp_name = png_voidcast(char*, - png_malloc_base(png_ptr, - keyword_length+1)); + png_malloc_base(png_ptr, + keyword_length+1)); if (info_ptr->iccp_name != NULL) { memcpy(info_ptr->iccp_name, keyword, - keyword_length+1); + keyword_length+1); info_ptr->iccp_proflen = - profile_length; + profile_length; info_ptr->iccp_profile = profile; png_ptr->read_buffer = NULL; /*steal*/ info_ptr->free_me |= PNG_FREE_ICCP; @@ -1670,7 +1703,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) ++entry_start; /* A sample depth should follow the separator, and we should be on it */ - if (entry_start > buffer + length - 2) + if (length < 2U || entry_start > buffer + (length - 2U)) { png_warning(png_ptr, "malformed sPLT chunk"); return; @@ -2174,7 +2207,7 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) /* We need to have at least 12 bytes after the purpose string * in order to get the parameter information. */ - if (endptr <= buf + 12) + if (endptr - buf <= 12) { png_chunk_benign_error(png_ptr, "invalid"); return; @@ -2239,7 +2272,7 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) } png_set_pCAL(png_ptr, info_ptr, (png_charp)buffer, X0, X1, type, nparams, - (png_charp)units, params); + (png_charp)units, params); png_free(png_ptr, params); } @@ -2282,7 +2315,7 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) } png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)", - length + 1); + length + 1); buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/); @@ -2334,7 +2367,7 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else /* This is the (only) success case. */ png_set_sCAL_s(png_ptr, info_ptr, buffer[0], - (png_charp)buffer+1, (png_charp)buffer+heighti); + (png_charp)buffer+1, (png_charp)buffer+heighti); } } #endif @@ -2434,8 +2467,8 @@ png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (buffer == NULL) { - png_chunk_benign_error(png_ptr, "out of memory"); - return; + png_chunk_benign_error(png_ptr, "out of memory"); + return; } png_crc_read(png_ptr, buffer, length); @@ -2542,7 +2575,7 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) * and text chunks. */ if (png_decompress_chunk(png_ptr, length, keyword_length+2, - &uncompressed_length, 1/*terminate*/) == Z_STREAM_END) + &uncompressed_length, 1/*terminate*/) == Z_STREAM_END) { png_text text; @@ -2682,7 +2715,7 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) * iCCP and text chunks. */ if (png_decompress_chunk(png_ptr, length, prefix_length, - &uncompressed_length, 1/*terminate*/) == Z_STREAM_END) + &uncompressed_length, 1/*terminate*/) == Z_STREAM_END) buffer = png_ptr->read_buffer; else @@ -2762,7 +2795,7 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) { /* Do a 'warn' here - it is handled below. */ png_ptr->unknown_chunk.data = png_voidcast(png_bytep, - png_malloc_warn(png_ptr, length)); + png_malloc_warn(png_ptr, length)); } } @@ -2787,7 +2820,7 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) /* Handle an unknown, or known but disabled, chunk */ void /* PRIVATE */ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, - png_uint_32 length, int keep) + png_uint_32 length, int keep) { int handled = 0; /* the chunk was handled */ @@ -2825,7 +2858,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, { /* Callback to user unknown chunk handler */ int ret = (*(png_ptr->read_user_chunk_fn))(png_ptr, - &png_ptr->unknown_chunk); + &png_ptr->unknown_chunk); /* ret is: * negative: An error occurred; png_chunk_error will be called. @@ -2859,9 +2892,9 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, { png_chunk_warning(png_ptr, "Saving unknown chunk:"); png_app_warning(png_ptr, - "forcing save of an unhandled chunk;" - " please call png_set_keep_unknown_chunks"); - /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */ + "forcing save of an unhandled chunk;" + " please call png_set_keep_unknown_chunks"); + /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */ } # endif keep = PNG_HANDLE_CHUNK_IF_SAFE; @@ -2954,7 +2987,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, * out; store the chunk. */ png_set_unknown_chunks(png_ptr, info_ptr, - &png_ptr->unknown_chunk, 1); + &png_ptr->unknown_chunk, 1); handled = 1; # ifdef PNG_USER_LIMITS_SUPPORTED break; @@ -3387,8 +3420,8 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) /* Everything is aligned for png_uint_16 copies, but try for * png_uint_32 first. */ - if (png_isaligned(dp, png_uint_32) != 0 && - png_isaligned(sp, png_uint_32) != 0 && + if (png_isaligned(dp, png_uint_32) && + png_isaligned(sp, png_uint_32) && bytes_to_copy % (sizeof (png_uint_32)) == 0 && bytes_to_jump % (sizeof (png_uint_32)) == 0) { @@ -3508,7 +3541,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) #ifdef PNG_READ_INTERLACING_SUPPORTED void /* PRIVATE */ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, - png_uint_32 transformations /* Because these may affect the byte layout */) + png_uint_32 transformations /* Because these may affect the byte layout */) { /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Offset to next interlace block */ @@ -3752,7 +3785,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, static void png_read_filter_row_sub(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) + png_const_bytep prev_row) { png_size_t i; png_size_t istop = row_info->rowbytes; @@ -3770,7 +3803,7 @@ png_read_filter_row_sub(png_row_infop row_info, png_bytep row, static void png_read_filter_row_up(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) + png_const_bytep prev_row) { png_size_t i; png_size_t istop = row_info->rowbytes; @@ -3786,7 +3819,7 @@ png_read_filter_row_up(png_row_infop row_info, png_bytep row, static void png_read_filter_row_avg(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) + png_const_bytep prev_row) { png_size_t i; png_bytep rp = row; @@ -3813,7 +3846,7 @@ png_read_filter_row_avg(png_row_infop row_info, png_bytep row, static void png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) + png_const_bytep prev_row) { png_bytep rp_end = row + row_info->rowbytes; int a, c; @@ -3861,7 +3894,7 @@ png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, static void png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) + png_const_bytep prev_row) { int bpp = (row_info->pixel_depth + 7) >> 3; png_bytep rp_end = row + bpp; @@ -3946,7 +3979,7 @@ png_init_filter_functions(png_structrp pp) void /* PRIVATE */ png_read_filter_row(png_structrp pp, png_row_infop row_info, png_bytep row, - png_const_bytep prev_row, int filter) + png_const_bytep prev_row, int filter) { /* OPTIMIZATION: DO NOT MODIFY THIS FUNCTION, instead #define * PNG_FILTER_OPTIMIZATIONS to a function that overrides the generic @@ -3964,7 +3997,7 @@ png_read_filter_row(png_structrp pp, png_row_infop row_info, png_bytep row, #ifdef PNG_SEQUENTIAL_READ_SUPPORTED void /* PRIVATE */ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, - png_alloc_size_t avail_out) + png_alloc_size_t avail_out) { /* Loop reading IDATs and decompressing the result into output[avail_out] */ png_ptr->zstream.next_out = output; @@ -4039,7 +4072,7 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, * * TODO: deal more elegantly with truncated IDAT lists. */ - ret = inflate(&png_ptr->zstream, Z_NO_FLUSH); + ret = PNG_INFLATE(png_ptr, Z_NO_FLUSH); /* Take the unconsumed output back. */ if (output != NULL) @@ -4416,42 +4449,42 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) if (row_bytes + 48 > png_ptr->old_big_row_buf_size) { - png_free(png_ptr, png_ptr->big_row_buf); - png_free(png_ptr, png_ptr->big_prev_row); + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->big_prev_row); - if (png_ptr->interlaced != 0) - png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, - row_bytes + 48); + if (png_ptr->interlaced != 0) + png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, + row_bytes + 48); - else - png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48); + else + png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48); - png_ptr->big_prev_row = (png_bytep)png_malloc(png_ptr, row_bytes + 48); + png_ptr->big_prev_row = (png_bytep)png_malloc(png_ptr, row_bytes + 48); #ifdef PNG_ALIGNED_MEMORY_SUPPORTED - /* Use 16-byte aligned memory for row_buf with at least 16 bytes - * of padding before and after row_buf; treat prev_row similarly. - * NOTE: the alignment is to the start of the pixels, one beyond the start - * of the buffer, because of the filter byte. Prior to libpng 1.5.6 this - * was incorrect; the filter byte was aligned, which had the exact - * opposite effect of that intended. - */ - { - png_bytep temp = png_ptr->big_row_buf + 32; - int extra = (int)((temp - (png_bytep)0) & 0x0f); - png_ptr->row_buf = temp - extra - 1/*filter byte*/; + /* Use 16-byte aligned memory for row_buf with at least 16 bytes + * of padding before and after row_buf; treat prev_row similarly. + * NOTE: the alignment is to the start of the pixels, one beyond the start + * of the buffer, because of the filter byte. Prior to libpng 1.5.6 this + * was incorrect; the filter byte was aligned, which had the exact + * opposite effect of that intended. + */ + { + png_bytep temp = png_ptr->big_row_buf + 32; + int extra = (int)((temp - (png_bytep)0) & 0x0f); + png_ptr->row_buf = temp - extra - 1/*filter byte*/; - temp = png_ptr->big_prev_row + 32; - extra = (int)((temp - (png_bytep)0) & 0x0f); - png_ptr->prev_row = temp - extra - 1/*filter byte*/; - } + temp = png_ptr->big_prev_row + 32; + extra = (int)((temp - (png_bytep)0) & 0x0f); + png_ptr->prev_row = temp - extra - 1/*filter byte*/; + } #else - /* Use 31 bytes of padding before and 17 bytes after row_buf. */ - png_ptr->row_buf = png_ptr->big_row_buf + 31; - png_ptr->prev_row = png_ptr->big_prev_row + 31; + /* Use 31 bytes of padding before and 17 bytes after row_buf. */ + png_ptr->row_buf = png_ptr->big_row_buf + 31; + png_ptr->prev_row = png_ptr->big_prev_row + 31; #endif - png_ptr->old_big_row_buf_size = row_bytes + 48; + png_ptr->old_big_row_buf_size = row_bytes + 48; } #ifdef PNG_MAX_MALLOC_64K diff --git a/3rdparty/libpng/pngset.c b/3rdparty/libpng/pngset.c index 05a2134dbb..cccd9cdc7e 100644 --- a/3rdparty/libpng/pngset.c +++ b/3rdparty/libpng/pngset.c @@ -1,8 +1,8 @@ /* pngset.c - storage of image information into info struct * - * Last changed in libpng 1.6.19 [November 12, 2015] - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -104,14 +104,14 @@ png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr, double green_x, double green_y, double blue_x, double blue_y) { png_set_cHRM_fixed(png_ptr, info_ptr, - png_fixed(png_ptr, white_x, "cHRM White X"), - png_fixed(png_ptr, white_y, "cHRM White Y"), - png_fixed(png_ptr, red_x, "cHRM Red X"), - png_fixed(png_ptr, red_y, "cHRM Red Y"), - png_fixed(png_ptr, green_x, "cHRM Green X"), - png_fixed(png_ptr, green_y, "cHRM Green Y"), - png_fixed(png_ptr, blue_x, "cHRM Blue X"), - png_fixed(png_ptr, blue_y, "cHRM Blue Y")); + png_fixed(png_ptr, white_x, "cHRM White X"), + png_fixed(png_ptr, white_y, "cHRM White Y"), + png_fixed(png_ptr, red_x, "cHRM Red X"), + png_fixed(png_ptr, red_y, "cHRM Red Y"), + png_fixed(png_ptr, green_x, "cHRM Green X"), + png_fixed(png_ptr, green_y, "cHRM Green Y"), + png_fixed(png_ptr, blue_x, "cHRM Blue X"), + png_fixed(png_ptr, blue_y, "cHRM Blue Y")); } void PNGAPI @@ -120,15 +120,15 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, double blue_X, double blue_Y, double blue_Z) { png_set_cHRM_XYZ_fixed(png_ptr, info_ptr, - png_fixed(png_ptr, red_X, "cHRM Red X"), - png_fixed(png_ptr, red_Y, "cHRM Red Y"), - png_fixed(png_ptr, red_Z, "cHRM Red Z"), - png_fixed(png_ptr, green_X, "cHRM Green X"), - png_fixed(png_ptr, green_Y, "cHRM Green Y"), - png_fixed(png_ptr, green_Z, "cHRM Green Z"), - png_fixed(png_ptr, blue_X, "cHRM Blue X"), - png_fixed(png_ptr, blue_Y, "cHRM Blue Y"), - png_fixed(png_ptr, blue_Z, "cHRM Blue Z")); + png_fixed(png_ptr, red_X, "cHRM Red X"), + png_fixed(png_ptr, red_Y, "cHRM Red Y"), + png_fixed(png_ptr, red_Z, "cHRM Red Z"), + png_fixed(png_ptr, green_X, "cHRM Green X"), + png_fixed(png_ptr, green_Y, "cHRM Green Y"), + png_fixed(png_ptr, green_Z, "cHRM Green Z"), + png_fixed(png_ptr, blue_X, "cHRM Blue X"), + png_fixed(png_ptr, blue_Y, "cHRM Blue Y"), + png_fixed(png_ptr, blue_Z, "cHRM Blue Z")); } # endif /* FLOATING_POINT */ @@ -316,10 +316,10 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, length = strlen(units) + 1; png_debug1(3, "allocating units for info (%lu bytes)", - (unsigned long)length); + (unsigned long)length); info_ptr->pcal_units = png_voidcast(png_charp, - png_malloc_warn(png_ptr, length)); + png_malloc_warn(png_ptr, length)); if (info_ptr->pcal_units == NULL) { @@ -398,7 +398,7 @@ png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw); info_ptr->scal_s_width = png_voidcast(png_charp, - png_malloc_warn(png_ptr, lengthw)); + png_malloc_warn(png_ptr, lengthw)); if (info_ptr->scal_s_width == NULL) { @@ -414,7 +414,7 @@ png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh); info_ptr->scal_s_height = png_voidcast(png_charp, - png_malloc_warn(png_ptr, lengthh)); + png_malloc_warn(png_ptr, lengthh)); if (info_ptr->scal_s_height == NULL) { @@ -453,9 +453,9 @@ png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit, char sheight[PNG_sCAL_MAX_DIGITS+1]; png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width, - PNG_sCAL_PRECISION); + PNG_sCAL_PRECISION); png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height, - PNG_sCAL_PRECISION); + PNG_sCAL_PRECISION); png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); } @@ -520,8 +520,8 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, if (png_ptr == NULL || info_ptr == NULL) return; - max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? - (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH; + max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? + (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH; if (num_palette < 0 || num_palette > (int) max_palette_length) { @@ -648,7 +648,7 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, */ { int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name, - proflen, profile, info_ptr->color_type); + proflen, profile, info_ptr->color_type); png_colorspace_sync_info(png_ptr, info_ptr); @@ -673,7 +673,7 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, memcpy(new_iccp_name, name, length); new_iccp_profile = png_voidcast(png_bytep, - png_malloc_warn(png_ptr, proflen)); + png_malloc_warn(png_ptr, proflen)); if (new_iccp_profile == NULL) { @@ -748,14 +748,14 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, * the overflow checks. */ new_text = png_voidcast(png_textp,png_realloc_array(png_ptr, - info_ptr->text, old_num_text, max_text-old_num_text, - sizeof *new_text)); + info_ptr->text, old_num_text, max_text-old_num_text, + sizeof *new_text)); } if (new_text == NULL) { png_chunk_report(png_ptr, "too many text chunks", - PNG_CHUNK_WRITE_ERROR); + PNG_CHUNK_WRITE_ERROR); return 1; } @@ -783,7 +783,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST) { png_chunk_report(png_ptr, "text compression mode is out of range", - PNG_CHUNK_WRITE_ERROR); + PNG_CHUNK_WRITE_ERROR); continue; } @@ -815,7 +815,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, # else /* iTXt */ { png_chunk_report(png_ptr, "iTXt chunk not supported", - PNG_CHUNK_WRITE_ERROR); + PNG_CHUNK_WRITE_ERROR); continue; } # endif @@ -844,7 +844,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, if (textp->key == NULL) { png_chunk_report(png_ptr, "text chunk: out of memory", - PNG_CHUNK_WRITE_ERROR); + PNG_CHUNK_WRITE_ERROR); return 1; } @@ -952,12 +952,14 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); - /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ - png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep, - png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); - if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) + { + /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ + info_ptr->trans_alpha = png_voidcast(png_bytep, + png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); + } + png_ptr->trans_alpha = info_ptr->trans_alpha; } if (trans_color != NULL) @@ -974,7 +976,7 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, trans_color->green > sample_max || trans_color->blue > sample_max))) png_warning(png_ptr, - "tRNS chunk has out-of-range samples for bit_depth"); + "tRNS chunk has out-of-range samples for bit_depth"); } #endif @@ -1016,8 +1018,8 @@ png_set_sPLT(png_const_structrp png_ptr, * overflows. Notice that the parameters are (int) and (size_t) */ np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr, - info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries, - sizeof *np)); + info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries, + sizeof *np)); if (np == NULL) { @@ -1078,7 +1080,7 @@ png_set_sPLT(png_const_structrp png_ptr, * checked it when doing the allocation. */ memcpy(np->entries, entries->entries, - entries->nentries * sizeof (png_sPLT_entry)); + entries->nentries * sizeof (png_sPLT_entry)); /* Note that 'continue' skips the advance of the out pointer and out * count, so an invalid entry is not added. @@ -1108,10 +1110,10 @@ check_location(png_const_structrp png_ptr, int location) { /* Write struct, so unknown chunks come from the app */ png_app_warning(png_ptr, - "png_set_unknown_chunks now expects a valid location"); + "png_set_unknown_chunks now expects a valid location"); /* Use the old behavior */ location = (png_byte)(png_ptr->mode & - (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)); + (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)); } /* This need not be an internal error - if the app calls @@ -1134,7 +1136,7 @@ check_location(png_const_structrp png_ptr, int location) void PNGAPI png_set_unknown_chunks(png_const_structrp png_ptr, - png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns) + png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns) { png_unknown_chunkp np; @@ -1173,13 +1175,13 @@ png_set_unknown_chunks(png_const_structrp png_ptr, * appropriate to read or write. */ np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr, - info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns, - sizeof *np)); + info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns, + sizeof *np)); if (np == NULL) { png_chunk_report(png_ptr, "too many unknown chunks", - PNG_CHUNK_WRITE_ERROR); + PNG_CHUNK_WRITE_ERROR); return; } @@ -1208,12 +1210,12 @@ png_set_unknown_chunks(png_const_structrp png_ptr, else { np->data = png_voidcast(png_bytep, - png_malloc_base(png_ptr, unknowns->size)); + png_malloc_base(png_ptr, unknowns->size)); if (np->data == NULL) { png_chunk_report(png_ptr, "unknown chunk: out of memory", - PNG_CHUNK_WRITE_ERROR); + PNG_CHUNK_WRITE_ERROR); /* But just skip storing the unknown chunk */ continue; } @@ -1420,7 +1422,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep, for (i=0; i PNG_UINT_31_MAX) - png_error(png_ptr, "invalid compression buffer size"); + if (size == 0 || size > PNG_UINT_31_MAX) + png_error(png_ptr, "invalid compression buffer size"); # ifdef PNG_SEQUENTIAL_READ_SUPPORTED - if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0) - { - png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */ - return; - } + if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0) + { + png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */ + return; + } # endif # ifdef PNG_WRITE_SUPPORTED - if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0) + if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0) + { + if (png_ptr->zowner != 0) { - if (png_ptr->zowner != 0) - { - png_warning(png_ptr, - "Compression buffer size cannot be changed because it is in use"); + png_warning(png_ptr, + "Compression buffer size cannot be changed because it is in use"); - return; - } + return; + } #ifndef __COVERITY__ - /* Some compilers complain that this is always false. However, it - * can be true when integer overflow happens. - */ - if (size > ZLIB_IO_MAX) - { - png_warning(png_ptr, - "Compression buffer size limited to system maximum"); - size = ZLIB_IO_MAX; /* must fit */ - } + /* Some compilers complain that this is always false. However, it + * can be true when integer overflow happens. + */ + if (size > ZLIB_IO_MAX) + { + png_warning(png_ptr, + "Compression buffer size limited to system maximum"); + size = ZLIB_IO_MAX; /* must fit */ + } #endif - if (size < 6) - { - /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH - * if this is permitted. - */ - png_warning(png_ptr, - "Compression buffer size cannot be reduced below 6"); + if (size < 6) + { + /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH + * if this is permitted. + */ + png_warning(png_ptr, + "Compression buffer size cannot be reduced below 6"); - return; - } - - if (png_ptr->zbuffer_size != size) - { - png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); - png_ptr->zbuffer_size = (uInt)size; - } + return; } + + if (png_ptr->zbuffer_size != size) + { + png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); + png_ptr->zbuffer_size = (uInt)size; + } + } # endif } @@ -1573,7 +1575,7 @@ png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max, { /* Images with dimensions larger than these limits will be * rejected by png_set_IHDR(). To accept any PNG datastream - * regardless of dimensions, set both limits to 0x7ffffff. + * regardless of dimensions, set both limits to 0x7fffffff. */ if (png_ptr == NULL) return; @@ -1644,4 +1646,92 @@ png_set_check_for_invalid_index(png_structrp png_ptr, int allowed) png_ptr->num_palette_max = -1; } #endif + +#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) || \ + defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) +/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, + * and if invalid, correct the keyword rather than discarding the entire + * chunk. The PNG 1.0 specification requires keywords 1-79 characters in + * length, forbids leading or trailing whitespace, multiple internal spaces, + * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. + * + * The 'new_key' buffer must be 80 characters in size (for the keyword plus a + * trailing '\0'). If this routine returns 0 then there was no keyword, or a + * valid one could not be generated, and the caller must png_error. + */ +png_uint_32 /* PRIVATE */ +png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) +{ +#ifdef PNG_WARNINGS_SUPPORTED + png_const_charp orig_key = key; +#endif + png_uint_32 key_len = 0; + int bad_character = 0; + int space = 1; + + png_debug(1, "in png_check_keyword"); + + if (key == NULL) + { + *new_key = 0; + return 0; + } + + while (*key && key_len < 79) + { + png_byte ch = (png_byte)*key++; + + if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/)) + *new_key++ = ch, ++key_len, space = 0; + + else if (space == 0) + { + /* A space or an invalid character when one wasn't seen immediately + * before; output just a space. + */ + *new_key++ = 32, ++key_len, space = 1; + + /* If the character was not a space then it is invalid. */ + if (ch != 32) + bad_character = ch; + } + + else if (bad_character == 0) + bad_character = ch; /* just skip it, record the first error */ + } + + if (key_len > 0 && space != 0) /* trailing space */ + { + --key_len, --new_key; + if (bad_character == 0) + bad_character = 32; + } + + /* Terminate the keyword */ + *new_key = 0; + + if (key_len == 0) + return 0; + +#ifdef PNG_WARNINGS_SUPPORTED + /* Try to only output one warning per keyword: */ + if (*key != 0) /* keyword too long */ + png_warning(png_ptr, "keyword truncated"); + + else if (bad_character != 0) + { + PNG_WARNING_PARAMETERS(p) + + png_warning_parameter(p, 1, orig_key); + png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character); + + png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'"); + } +#else /* !WARNINGS */ + PNG_UNUSED(png_ptr) +#endif /* !WARNINGS */ + + return key_len; +} +#endif /* TEXT || pCAL || iCCP || sPLT */ #endif /* READ || WRITE */ diff --git a/3rdparty/libpng/pngstruct.h b/3rdparty/libpng/pngstruct.h index c8c0e46e8b..2b0eb49025 100644 --- a/3rdparty/libpng/pngstruct.h +++ b/3rdparty/libpng/pngstruct.h @@ -1,8 +1,8 @@ /* pngstruct.h - header file for PNG reference library * - * Last changed in libpng 1.6.18 [July 23, 2015] - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -249,7 +249,7 @@ struct png_struct_def png_byte filter; /* file filter type (always 0) */ png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ png_byte pass; /* current interlace pass (0 - 6) */ - png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ in png.h ) */ png_byte color_type; /* color type of file */ png_byte bit_depth; /* bit depth of file */ png_byte usr_bit_depth; /* bit depth of users row: write only */ @@ -263,6 +263,9 @@ struct png_struct_def /* pixel depth used for the row buffers */ png_byte transformed_pixel_depth; /* pixel depth after read/write transforms */ +#if PNG_ZLIB_VERNUM >= 0x1240 + png_byte zstream_start; /* at start of an input zlib stream */ +#endif /* Zlib >= 1.2.4 */ #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) png_uint_16 filler; /* filler bytes for pixel expansion */ #endif diff --git a/3rdparty/libpng/pngtrans.c b/3rdparty/libpng/pngtrans.c index 0c0d92d8fd..e5cbd79b9d 100644 --- a/3rdparty/libpng/pngtrans.c +++ b/3rdparty/libpng/pngtrans.c @@ -1,8 +1,8 @@ /* pngtrans.c - transforms the data in a row (used by both readers and writers) * - * Last changed in libpng 1.6.18 [July 23, 2015] - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -172,13 +172,14 @@ png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc) * size! */ png_app_error(png_ptr, - "png_set_filler is invalid for low bit depth gray output"); + "png_set_filler is invalid for" + " low bit depth gray output"); return; } default: png_app_error(png_ptr, - "png_set_filler: inappropriate color type"); + "png_set_filler: inappropriate color type"); return; } # else @@ -797,7 +798,7 @@ png_set_user_transform_info(png_structrp png_ptr, png_voidp (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0) { png_app_error(png_ptr, - "info change after png_start_read_image or png_read_update_info"); + "info change after png_start_read_image or png_read_update_info"); return; } #endif diff --git a/3rdparty/libpng/pngwio.c b/3rdparty/libpng/pngwio.c index db76e6b8d7..37c7c3a7f0 100644 --- a/3rdparty/libpng/pngwio.c +++ b/3rdparty/libpng/pngwio.c @@ -1,8 +1,8 @@ /* pngwio.c - functions for data output * - * Last changed in libpng 1.6.15 [November 20, 2014] - * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -35,7 +35,7 @@ png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length) /* NOTE: write_data_fn must not change the buffer! */ if (png_ptr->write_data_fn != NULL ) (*(png_ptr->write_data_fn))(png_ptr, png_constcast(png_bytep,data), - length); + length); else png_error(png_ptr, "Call to NULL write function"); diff --git a/3rdparty/libpng/pngwrite.c b/3rdparty/libpng/pngwrite.c index 0d4ee9f7ae..aaa2b017df 100644 --- a/3rdparty/libpng/pngwrite.c +++ b/3rdparty/libpng/pngwrite.c @@ -1,8 +1,8 @@ /* pngwrite.c - general routines to write a PNG file * - * Last changed in libpng 1.6.19 [November 12, 2015] - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -12,9 +12,9 @@ */ #include "pngpriv.h" -#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) +#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED # include -#endif +#endif /* SIMPLIFIED_WRITE_STDIO */ #ifdef PNG_WRITE_SUPPORTED @@ -22,7 +22,7 @@ /* Write out all the unknown chunks for the current given location */ static void write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr, - unsigned int where) + unsigned int where) { if (info_ptr->unknown_chunks_num != 0) { @@ -148,11 +148,11 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) # ifdef PNG_WRITE_sRGB_SUPPORTED if ((info_ptr->valid & PNG_INFO_sRGB) != 0) png_app_warning(png_ptr, - "profile matches sRGB but writing iCCP instead"); + "profile matches sRGB but writing iCCP instead"); # endif png_write_iCCP(png_ptr, info_ptr->iccp_name, - info_ptr->iccp_profile); + info_ptr->iccp_profile); } # ifdef PNG_WRITE_sRGB_SUPPORTED else @@ -383,7 +383,7 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr) for (i = 0; i < info_ptr->num_text; i++) { png_debug2(2, "Writing trailer text chunk %d, type %d", i, - info_ptr->text[i].compression); + info_ptr->text[i].compression); /* An internationalized chunk? */ if (info_ptr->text[i].compression > 0) { @@ -693,7 +693,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row) return; png_debug2(1, "in png_write_row (row %u, pass %d)", - png_ptr->row_number, png_ptr->pass); + png_ptr->row_number, png_ptr->pass); /* Initialize transformations and other stuff if first time */ if (png_ptr->row_number == 0 && png_ptr->pass == 0) @@ -1069,7 +1069,7 @@ png_set_filter(png_structrp png_ptr, int method, int filters) * is not available so the filter can't be used. Just warn here. */ png_app_warning(png_ptr, - "png_set_filter: UP/AVG/PAETH cannot be added after start"); + "png_set_filter: UP/AVG/PAETH cannot be added after start"); filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); } @@ -1095,13 +1095,13 @@ png_set_filter(png_structrp png_ptr, int method, int filters) if (png_ptr->try_row == NULL) png_ptr->try_row = png_voidcast(png_bytep, - png_malloc(png_ptr, buf_size)); + png_malloc(png_ptr, buf_size)); if (num_filters > 1) { if (png_ptr->tst_row == NULL) png_ptr->tst_row = png_voidcast(png_bytep, - png_malloc(png_ptr, buf_size)); + png_malloc(png_ptr, buf_size)); } } png_ptr->do_filter = (png_byte)filters; @@ -1452,7 +1452,6 @@ png_write_png(png_structrp png_ptr, png_inforp info_ptr, #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED -# ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */ /* Initialize the write structure - general purpose utility. */ static int png_image_write_init(png_imagep image) @@ -1504,6 +1503,10 @@ typedef struct png_const_voidp first_row; ptrdiff_t row_bytes; png_voidp local_row; + /* Byte count for memory writing */ + png_bytep memory; + png_alloc_size_t memory_bytes; /* not used for STDIO */ + png_alloc_size_t output_bytes; /* running total */ } png_image_write_control; /* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to @@ -1625,7 +1628,7 @@ png_write_image_16bit(png_voidp argument) static png_byte png_unpremultiply(png_uint_32 component, png_uint_32 alpha, - png_uint_32 reciprocal/*from the above macro*/) + png_uint_32 reciprocal/*from the above macro*/) { /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0 * is represented as some other value there is more likely to be a @@ -1845,16 +1848,16 @@ png_image_set_PLTE(png_image_write_control *display) if (channels >= 3) /* RGB */ { palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)], - alpha, reciprocal); + alpha, reciprocal); palette[i].green = png_unpremultiply(entry[afirst + 1], alpha, - reciprocal); + reciprocal); palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha, - reciprocal); + reciprocal); } else /* gray */ palette[i].blue = palette[i].red = palette[i].green = - png_unpremultiply(entry[afirst], alpha, reciprocal); + png_unpremultiply(entry[afirst], alpha, reciprocal); } } @@ -1901,11 +1904,11 @@ png_image_set_PLTE(png_image_write_control *display) # endif png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette, - entries); + entries); if (num_trans > 0) png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS, - num_trans, NULL); + num_trans, NULL); image->colormap_entries = entries; } @@ -1914,7 +1917,7 @@ static int png_image_write_main(png_voidp argument) { png_image_write_control *display = png_voidcast(png_image_write_control*, - argument); + argument); png_imagep image = display->image; png_structrp png_ptr = image->opaque->png_ptr; png_inforp info_ptr = image->opaque->info_ptr; @@ -1931,9 +1934,43 @@ png_image_write_main(png_voidp argument) png_set_benign_errors(png_ptr, 0/*error*/); # endif - /* Default the 'row_stride' parameter if required. */ - if (display->row_stride == 0) - display->row_stride = PNG_IMAGE_ROW_STRIDE(*image); + /* Default the 'row_stride' parameter if required, also check the row stride + * and total image size to ensure that they are within the system limits. + */ + { + const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); + + if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */ + { + png_uint_32 check; + const png_uint_32 png_row_stride = image->width * channels; + + if (display->row_stride == 0) + display->row_stride = (png_int_32)/*SAFE*/png_row_stride; + + if (display->row_stride < 0) + check = -display->row_stride; + + else + check = display->row_stride; + + if (check >= png_row_stride) + { + /* Now check for overflow of the image buffer calculation; this + * limits the whole image size to 32 bits for API compatibility with + * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro. + */ + if (image->height > 0xFFFFFFFF/png_row_stride) + png_error(image->opaque->png_ptr, "memory image too large"); + } + + else + png_error(image->opaque->png_ptr, "supplied row stride too small"); + } + + else + png_error(image->opaque->png_ptr, "image row stride too large"); + } /* Set the required transforms then write the rows in the correct order. */ if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0) @@ -1943,24 +1980,24 @@ png_image_write_main(png_voidp argument) png_uint_32 entries = image->colormap_entries; png_set_IHDR(png_ptr, info_ptr, image->width, image->height, - entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)), - PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)), + PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_image_set_PLTE(display); } else png_error(image->opaque->png_ptr, - "no color-map for color-mapped image"); + "no color-map for color-mapped image"); } else png_set_IHDR(png_ptr, info_ptr, image->width, image->height, - write_16bit ? 16 : 8, - ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) + - ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0), - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + write_16bit ? 16 : 8, + ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) + + ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0), + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* Counter-intuitively the data transformations must be called *after* * png_write_info, not before as in the read code, but the 'set' functions @@ -1975,11 +2012,11 @@ png_image_write_main(png_voidp argument) if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0) png_set_cHRM_fixed(png_ptr, info_ptr, - /* color x y */ - /* white */ 31270, 32900, - /* red */ 64000, 33000, - /* green */ 30000, 60000, - /* blue */ 15000, 6000 + /* color x y */ + /* white */ 31270, 32900, + /* red */ 64000, 33000, + /* green */ 30000, 60000, + /* blue */ 15000, 6000 ); } @@ -2073,7 +2110,7 @@ png_image_write_main(png_voidp argument) (colormap == 0 && display->convert_to_8bit != 0)) { png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, - png_get_rowbytes(png_ptr, info_ptr))); + png_get_rowbytes(png_ptr, info_ptr))); int result; display->local_row = row; @@ -2110,14 +2147,130 @@ png_image_write_main(png_voidp argument) return 1; } + +static void (PNGCBAPI +image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, + png_size_t size) +{ + png_image_write_control *display = png_voidcast(png_image_write_control*, + png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/); + const png_alloc_size_t ob = display->output_bytes; + + /* Check for overflow; this should never happen: */ + if (size <= ((png_alloc_size_t)-1) - ob) + { + /* I don't think libpng ever does this, but just in case: */ + if (size > 0) + { + if (display->memory_bytes >= ob+size) /* writing */ + memcpy(display->memory+ob, data, size); + + /* Always update the size: */ + display->output_bytes = ob+size; + } + } + + else + png_error(png_ptr, "png_image_write_to_memory: PNG too big"); +} + +static void (PNGCBAPI +image_memory_flush)(png_structp png_ptr) +{ + PNG_UNUSED(png_ptr) +} + +static int +png_image_write_memory(png_voidp argument) +{ + png_image_write_control *display = png_voidcast(png_image_write_control*, + argument); + + /* The rest of the memory-specific init and write_main in an error protected + * environment. This case needs to use callbacks for the write operations + * since libpng has no built in support for writing to memory. + */ + png_set_write_fn(display->image->opaque->png_ptr, display/*io_ptr*/, + image_memory_write, image_memory_flush); + + return png_image_write_main(display); +} + +int PNGAPI +png_image_write_to_memory(png_imagep image, void *memory, + png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit, + const void *buffer, png_int_32 row_stride, const void *colormap) +{ + /* Write the image to the given buffer, or count the bytes if it is NULL */ + if (image != NULL && image->version == PNG_IMAGE_VERSION) + { + if (memory_bytes != NULL && buffer != NULL) + { + /* This is to give the caller an easier error detection in the NULL + * case and guard against uninitialized variable problems: + */ + if (memory == NULL) + *memory_bytes = 0; + + if (png_image_write_init(image) != 0) + { + png_image_write_control display; + int result; + + memset(&display, 0, (sizeof display)); + display.image = image; + display.buffer = buffer; + display.row_stride = row_stride; + display.colormap = colormap; + display.convert_to_8bit = convert_to_8bit; + display.memory = png_voidcast(png_bytep, memory); + display.memory_bytes = *memory_bytes; + display.output_bytes = 0; + + result = png_safe_execute(image, png_image_write_memory, &display); + png_image_free(image); + + /* write_memory returns true even if we ran out of buffer. */ + if (result) + { + /* On out-of-buffer this function returns '0' but still updates + * memory_bytes: + */ + if (memory != NULL && display.output_bytes > *memory_bytes) + result = 0; + + *memory_bytes = display.output_bytes; + } + + return result; + } + + else + return 0; + } + + else + return png_image_error(image, + "png_image_write_to_memory: invalid argument"); + } + + else if (image != NULL) + return png_image_error(image, + "png_image_write_to_memory: incorrect PNG_IMAGE_VERSION"); + + else + return 0; +} + +#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED int PNGAPI png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, - const void *buffer, png_int_32 row_stride, const void *colormap) + const void *buffer, png_int_32 row_stride, const void *colormap) { /* Write the image to the given (FILE*). */ if (image != NULL && image->version == PNG_IMAGE_VERSION) { - if (file != NULL) + if (file != NULL && buffer != NULL) { if (png_image_write_init(image) != 0) { @@ -2148,12 +2301,12 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, else return png_image_error(image, - "png_image_write_to_stdio: invalid argument"); + "png_image_write_to_stdio: invalid argument"); } else if (image != NULL) return png_image_error(image, - "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION"); + "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION"); else return 0; @@ -2161,20 +2314,20 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, int PNGAPI png_image_write_to_file(png_imagep image, const char *file_name, - int convert_to_8bit, const void *buffer, png_int_32 row_stride, - const void *colormap) + int convert_to_8bit, const void *buffer, png_int_32 row_stride, + const void *colormap) { /* Write the image to the named file. */ if (image != NULL && image->version == PNG_IMAGE_VERSION) { - if (file_name != NULL) + if (file_name != NULL && buffer != NULL) { FILE *fp = fopen(file_name, "wb"); if (fp != NULL) { if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer, - row_stride, colormap) != 0) + row_stride, colormap) != 0) { int error; /* from fflush/fclose */ @@ -2215,16 +2368,16 @@ png_image_write_to_file(png_imagep image, const char *file_name, else return png_image_error(image, - "png_image_write_to_file: invalid argument"); + "png_image_write_to_file: invalid argument"); } else if (image != NULL) return png_image_error(image, - "png_image_write_to_file: incorrect PNG_IMAGE_VERSION"); + "png_image_write_to_file: incorrect PNG_IMAGE_VERSION"); else return 0; } -# endif /* STDIO */ +#endif /* SIMPLIFIED_WRITE_STDIO */ #endif /* SIMPLIFIED_WRITE */ #endif /* WRITE */ diff --git a/3rdparty/libpng/pngwtran.c b/3rdparty/libpng/pngwtran.c index 5dc949157d..423fb2d5bb 100644 --- a/3rdparty/libpng/pngwtran.c +++ b/3rdparty/libpng/pngwtran.c @@ -1,8 +1,8 @@ /* pngwtran.c - transforms the data in a row for PNG writers * - * Last changed in libpng 1.6.18 [July 23, 2015] - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -525,7 +525,7 @@ png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info) #ifdef PNG_WRITE_FILLER_SUPPORTED if ((png_ptr->transformations & PNG_FILLER) != 0) png_do_strip_channel(row_info, png_ptr->row_buf + 1, - !(png_ptr->flags & PNG_FLAG_FILLER_AFTER)); + !(png_ptr->flags & PNG_FLAG_FILLER_AFTER)); #endif #ifdef PNG_WRITE_PACKSWAP_SUPPORTED @@ -549,7 +549,7 @@ png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info) #ifdef PNG_WRITE_SHIFT_SUPPORTED if ((png_ptr->transformations & PNG_SHIFT) != 0) png_do_shift(row_info, png_ptr->row_buf + 1, - &(png_ptr->shift)); + &(png_ptr->shift)); #endif #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED diff --git a/3rdparty/libpng/pngwutil.c b/3rdparty/libpng/pngwutil.c index adc4729c24..3f1ed0cc8f 100644 --- a/3rdparty/libpng/pngwutil.c +++ b/3rdparty/libpng/pngwutil.c @@ -1,8 +1,8 @@ /* pngwutil.c - utilities to write a PNG file * - * Last changed in libpng 1.6.19 [November 12, 2015] - * Copyright (c) 1998-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.24 [August 4, 2016] + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -23,10 +23,10 @@ void PNGAPI png_save_uint_32(png_bytep buf, png_uint_32 i) { - buf[0] = (png_byte)(i >> 24); - buf[1] = (png_byte)(i >> 16); - buf[2] = (png_byte)(i >> 8); - buf[3] = (png_byte)(i ); + buf[0] = (png_byte)((i >> 24) & 0xffU); + buf[1] = (png_byte)((i >> 16) & 0xffU); + buf[2] = (png_byte)((i >> 8) & 0xffU); + buf[3] = (png_byte)( i & 0xffU); } /* Place a 16-bit number into a buffer in PNG byte order. @@ -36,8 +36,8 @@ png_save_uint_32(png_bytep buf, png_uint_32 i) void PNGAPI png_save_uint_16(png_bytep buf, unsigned int i) { - buf[0] = (png_byte)(i >> 8); - buf[1] = (png_byte)(i ); + buf[0] = (png_byte)((i >> 8) & 0xffU); + buf[1] = (png_byte)( i & 0xffU); } #endif @@ -59,7 +59,7 @@ png_write_sig(png_structrp png_ptr) /* Write the rest of the 8 byte signature */ png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], - (png_size_t)(8 - png_ptr->sig_bytes)); + (png_size_t)(8 - png_ptr->sig_bytes)); if (png_ptr->sig_bytes < 3) png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; @@ -174,7 +174,7 @@ png_write_chunk_end(png_structrp png_ptr) */ static void png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, - png_const_bytep data, png_size_t length) + png_const_bytep data, png_size_t length) { if (png_ptr == NULL) return; @@ -191,10 +191,10 @@ png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, /* This is the API that calls the internal function above. */ void PNGAPI png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string, - png_const_bytep data, png_size_t length) + png_const_bytep data, png_size_t length) { png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, - length); + length); } /* This is used below to find the size of an image to pass to png_deflate_claim, @@ -291,7 +291,7 @@ optimize_cmf(png_bytep data, png_alloc_size_t data_size) /* Initialize the compressor for the appropriate type of compression. */ static int png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, - png_alloc_size_t data_size) + png_alloc_size_t data_size) { if (png_ptr->zowner != 0) { @@ -416,7 +416,7 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, else { ret = deflateInit2(&png_ptr->zstream, level, method, windowBits, - memLevel, strategy); + memLevel, strategy); if (ret == Z_OK) png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; @@ -477,7 +477,7 @@ typedef struct static void png_text_compress_init(compression_state *comp, png_const_bytep input, - png_alloc_size_t input_len) + png_alloc_size_t input_len) { comp->input = input; comp->input_len = input_len; @@ -487,7 +487,7 @@ png_text_compress_init(compression_state *comp, png_const_bytep input, /* Compress the data in the compression state input */ static int png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, - compression_state *comp, png_uint_32 prefix_len) + compression_state *comp, png_uint_32 prefix_len) { int ret; @@ -579,7 +579,7 @@ png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, /* Compress the data */ ret = deflate(&png_ptr->zstream, - input_len > 0 ? Z_NO_FLUSH : Z_FINISH); + input_len > 0 ? Z_NO_FLUSH : Z_FINISH); /* Claw back input data that was not consumed (because avail_in is * reset above every time round the loop). @@ -665,90 +665,6 @@ png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp) } #endif /* WRITE_COMPRESSED_TEXT */ -#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ - defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) -/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, - * and if invalid, correct the keyword rather than discarding the entire - * chunk. The PNG 1.0 specification requires keywords 1-79 characters in - * length, forbids leading or trailing whitespace, multiple internal spaces, - * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. - * - * The 'new_key' buffer must be 80 characters in size (for the keyword plus a - * trailing '\0'). If this routine returns 0 then there was no keyword, or a - * valid one could not be generated, and the caller must png_error. - */ -static png_uint_32 -png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) -{ - png_const_charp orig_key = key; - png_uint_32 key_len = 0; - int bad_character = 0; - int space = 1; - - png_debug(1, "in png_check_keyword"); - - if (key == NULL) - { - *new_key = 0; - return 0; - } - - while (*key && key_len < 79) - { - png_byte ch = (png_byte)*key++; - - if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/)) - *new_key++ = ch, ++key_len, space = 0; - - else if (space == 0) - { - /* A space or an invalid character when one wasn't seen immediately - * before; output just a space. - */ - *new_key++ = 32, ++key_len, space = 1; - - /* If the character was not a space then it is invalid. */ - if (ch != 32) - bad_character = ch; - } - - else if (bad_character == 0) - bad_character = ch; /* just skip it, record the first error */ - } - - if (key_len > 0 && space != 0) /* trailing space */ - { - --key_len, --new_key; - if (bad_character == 0) - bad_character = 32; - } - - /* Terminate the keyword */ - *new_key = 0; - - if (key_len == 0) - return 0; - -#ifdef PNG_WARNINGS_SUPPORTED - /* Try to only output one warning per keyword: */ - if (*key != 0) /* keyword too long */ - png_warning(png_ptr, "keyword truncated"); - - else if (bad_character != 0) - { - PNG_WARNING_PARAMETERS(p) - - png_warning_parameter(p, 1, orig_key); - png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character); - - png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'"); - } -#endif /* WARNINGS */ - - return key_len; -} -#endif /* WRITE_TEXT || WRITE_pCAL || WRITE_iCCP || WRITE_sPLT */ - /* Write the IHDR chunk, and update the png_struct with the necessary * information. Note that the rest of this code depends upon this * information being correct. @@ -1009,7 +925,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, */ void /* PRIVATE */ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, - png_alloc_size_t input_len, int flush) + png_alloc_size_t input_len, int flush) { if (png_ptr->zowner != png_IDAT) { @@ -1021,7 +937,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, if (png_ptr->zbuffer_list == NULL) { png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp, - png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); + png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); png_ptr->zbuffer_list->next = NULL; } @@ -1442,7 +1358,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, /* Write the chunk out as it is */ png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, - (png_size_t)num_trans); + (png_size_t)num_trans); } else if (color_type == PNG_COLOR_TYPE_GRAY) @@ -1473,7 +1389,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, #endif { png_app_warning(png_ptr, - "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); return; } @@ -1525,7 +1441,8 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) #endif { png_warning(png_ptr, - "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + "Ignoring attempt to write 16-bit bKGD chunk " + "when bit_depth is 8"); return; } @@ -1655,7 +1572,7 @@ png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, /* Compute the compressed data; do it now for the length */ png_text_compress_init(&comp, (png_const_bytep)text, - text == NULL ? 0 : strlen(text)); + text == NULL ? 0 : strlen(text)); if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK) png_error(png_ptr, png_ptr->zstream.msg); @@ -2025,7 +1942,7 @@ png_write_start_row(png_structrp png_ptr) */ if ((filters & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0) png_ptr->prev_row = png_voidcast(png_bytep, - png_calloc(png_ptr, buf_size)); + png_calloc(png_ptr, buf_size)); #endif /* WRITE_FILTER */ #ifdef PNG_WRITE_INTERLACING_SUPPORTED @@ -2328,7 +2245,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) */ static void /* PRIVATE */ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, - png_size_t row_bytes); + png_size_t row_bytes); #ifdef PNG_WRITE_FILTER_SUPPORTED static png_size_t /* PRIVATE */ @@ -2346,14 +2263,22 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, i++, rp++, dp++) { v = *dp = *rp; +#ifdef PNG_USE_ABS + sum += 128 - abs(v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif } for (lp = png_ptr->row_buf + 1; i < row_bytes; i++, rp++, lp++, dp++) { v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); +#ifdef PNG_USE_ABS + sum += 128 - abs(v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif if (sum > lmins) /* We are already worse, don't continue. */ break; @@ -2362,6 +2287,28 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, return (sum); } +static void /* PRIVATE */ +png_setup_sub_row_only(png_structrp png_ptr, const png_uint_32 bpp, + const png_size_t row_bytes) +{ + png_bytep rp, dp, lp; + png_size_t i; + + png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; + + for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp; + i++, rp++, dp++) + { + *dp = *rp; + } + + for (lp = png_ptr->row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + } +} + static png_size_t /* PRIVATE */ png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, const png_size_t lmins) @@ -2378,7 +2325,11 @@ png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, i++, rp++, pp++, dp++) { v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); +#ifdef PNG_USE_ABS + sum += 128 - abs(v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif if (sum > lmins) /* We are already worse, don't continue. */ break; @@ -2386,10 +2337,25 @@ png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, return (sum); } +static void /* PRIVATE */ +png_setup_up_row_only(png_structrp png_ptr, const png_size_t row_bytes) +{ + png_bytep rp, dp, pp; + png_size_t i; + + png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; + + for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, + pp = png_ptr->prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + } +} static png_size_t /* PRIVATE */ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes, const png_size_t lmins) + const png_size_t row_bytes, const png_size_t lmins) { png_bytep rp, dp, pp, lp; png_uint_32 i; @@ -2399,11 +2365,15 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, - pp = png_ptr->prev_row + 1; i < bpp; i++) + pp = png_ptr->prev_row + 1; i < bpp; i++) { v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); +#ifdef PNG_USE_ABS + sum += 128 - abs(v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif } for (lp = png_ptr->row_buf + 1; i < row_bytes; i++) @@ -2411,7 +2381,11 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, v = *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); +#ifdef PNG_USE_ABS + sum += 128 - abs(v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif if (sum > lmins) /* We are already worse, don't continue. */ break; @@ -2419,6 +2393,27 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, return (sum); } +static void /* PRIVATE */ +png_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp, + const png_size_t row_bytes) +{ + png_bytep rp, dp, pp, lp; + png_uint_32 i; + + png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; + + for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, + pp = png_ptr->prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + } + + for (lp = png_ptr->row_buf + 1; i < row_bytes; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + } +} static png_size_t /* PRIVATE */ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, @@ -2436,7 +2431,11 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, { v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); +#ifdef PNG_USE_ABS + sum += 128 - abs(v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif } for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes; @@ -2465,7 +2464,11 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); +#ifdef PNG_USE_ABS + sum += 128 - abs(v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif if (sum > lmins) /* We are already worse, don't continue. */ break; @@ -2473,6 +2476,48 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, return (sum); } +static void /* PRIVATE */ +png_setup_paeth_row_only(png_structrp png_ptr, const png_uint_32 bpp, + const png_size_t row_bytes) +{ + png_bytep rp, dp, pp, cp, lp; + png_size_t i; + + png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; + + for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, + pp = png_ptr->prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + } + + for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes; + i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + } +} #endif /* WRITE_FILTER */ void /* PRIVATE */ @@ -2481,7 +2526,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) #ifndef PNG_WRITE_FILTER_SUPPORTED png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1); #else - png_byte filter_to_do = png_ptr->do_filter; + unsigned int filter_to_do = png_ptr->do_filter; png_bytep row_buf; png_bytep best_row; png_uint_32 bpp; @@ -2527,32 +2572,33 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) */ best_row = png_ptr->row_buf; - - if ((filter_to_do & PNG_FILTER_NONE) != 0 && filter_to_do != PNG_FILTER_NONE) + if (PNG_SIZE_MAX/128 <= row_bytes) { + /* Overflow can occur in the calculation, just select the lowest set + * filter. + */ + filter_to_do &= 0U-filter_to_do; + } + else if ((filter_to_do & PNG_FILTER_NONE) != 0 && + filter_to_do != PNG_FILTER_NONE) + { + /* Overflow not possible and multiple filters in the list, including the + * 'none' filter. + */ png_bytep rp; png_size_t sum = 0; png_size_t i; int v; - if (PNG_SIZE_MAX/128 <= row_bytes) - { - for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) - { - /* Check for overflow */ - if (sum > PNG_SIZE_MAX/128 - 256) - break; - - v = *rp; - sum += (v < 128) ? v : 256 - v; - } - } - else /* Overflow is not possible */ { for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) { v = *rp; +#ifdef PNG_USE_ABS + sum += 128 - abs(v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif } } @@ -2563,7 +2609,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) if (filter_to_do == PNG_FILTER_SUB) /* It's the only filter so no testing is needed */ { - (void) png_setup_sub_row(png_ptr, bpp, row_bytes, mins); + png_setup_sub_row_only(png_ptr, bpp, row_bytes); best_row = png_ptr->try_row; } @@ -2572,7 +2618,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) png_size_t sum; png_size_t lmins = mins; - sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); + sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); if (sum < mins) { @@ -2589,7 +2635,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) /* Up filter */ if (filter_to_do == PNG_FILTER_UP) { - (void) png_setup_up_row(png_ptr, row_bytes, mins); + png_setup_up_row_only(png_ptr, row_bytes); best_row = png_ptr->try_row; } @@ -2598,7 +2644,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) png_size_t sum; png_size_t lmins = mins; - sum = png_setup_up_row(png_ptr, row_bytes, lmins); + sum = png_setup_up_row(png_ptr, row_bytes, lmins); if (sum < mins) { @@ -2615,7 +2661,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) /* Avg filter */ if (filter_to_do == PNG_FILTER_AVG) { - (void) png_setup_avg_row(png_ptr, bpp, row_bytes, mins); + png_setup_avg_row_only(png_ptr, bpp, row_bytes); best_row = png_ptr->try_row; } @@ -2639,9 +2685,9 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) } /* Paeth filter */ - if ((filter_to_do == PNG_FILTER_PAETH) != 0) + if (filter_to_do == PNG_FILTER_PAETH) { - (void) png_setup_paeth_row(png_ptr, bpp, row_bytes, mins); + png_setup_paeth_row_only(png_ptr, bpp, row_bytes); best_row = png_ptr->try_row; } @@ -2673,7 +2719,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) /* Do the actual writing of a previously filtered row. */ static void png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, - png_size_t full_row_length/*includes filter byte*/) + png_size_t full_row_length/*includes filter byte*/) { png_debug(1, "in png_write_filtered_row"); From 063ac74369199c1cfcaefe266d963ea1c21db75d Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 25 Aug 2016 14:57:12 +0300 Subject: [PATCH 092/178] fix modules deps --- modules/highgui/CMakeLists.txt | 2 +- modules/highgui/include/opencv2/highgui.hpp | 4 ++++ modules/highgui/include/opencv2/highgui/highgui_c.h | 4 ++++ modules/highgui/src/precomp.hpp | 8 +++++--- modules/highgui/test/test_precomp.hpp | 12 ------------ 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/modules/highgui/CMakeLists.txt b/modules/highgui/CMakeLists.txt index eee6a934ac..eb5617751e 100644 --- a/modules/highgui/CMakeLists.txt +++ b/modules/highgui/CMakeLists.txt @@ -1,5 +1,5 @@ set(the_description "High-level GUI and Media I/O") -ocv_add_module(highgui opencv_imgproc opencv_imgcodecs opencv_videoio WRAP python) +ocv_add_module(highgui opencv_imgproc OPTIONAL opencv_imgcodecs opencv_videoio WRAP python) # ---------------------------------------------------------------------------- # CMake file for highgui. See root CMakeLists.txt diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index b5c22a19ee..d29afbe75b 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -44,8 +44,12 @@ #define __OPENCV_HIGHGUI_HPP__ #include "opencv2/core.hpp" +#ifdef HAVE_OPENCV_IMGCODECS #include "opencv2/imgcodecs.hpp" +#endif +#ifdef HAVE_OPENCV_VIDEOIO #include "opencv2/videoio.hpp" +#endif /** @defgroup highgui High-level GUI diff --git a/modules/highgui/include/opencv2/highgui/highgui_c.h b/modules/highgui/include/opencv2/highgui/highgui_c.h index 47fdb84a4e..8ddb819a7a 100644 --- a/modules/highgui/include/opencv2/highgui/highgui_c.h +++ b/modules/highgui/include/opencv2/highgui/highgui_c.h @@ -44,8 +44,12 @@ #include "opencv2/core/core_c.h" #include "opencv2/imgproc/imgproc_c.h" +#ifdef HAVE_OPENCV_IMGCODECS #include "opencv2/imgcodecs/imgcodecs_c.h" +#endif +#ifdef HAVE_OPENCV_VIDEOIO #include "opencv2/videoio/videoio_c.h" +#endif #ifdef __cplusplus extern "C" { diff --git a/modules/highgui/src/precomp.hpp b/modules/highgui/src/precomp.hpp index 796af39768..59bf7aa7be 100644 --- a/modules/highgui/src/precomp.hpp +++ b/modules/highgui/src/precomp.hpp @@ -47,12 +47,14 @@ #include "opencv2/core/utility.hpp" #include "opencv2/core/private.hpp" -#include "opencv2/imgcodecs.hpp" - #include "opencv2/imgproc/imgproc_c.h" -#include "opencv2/imgcodecs/imgcodecs_c.h" #include "opencv2/highgui/highgui_c.h" +#ifdef HAVE_OPENCV_IMGCODECS +#include "opencv2/imgcodecs.hpp" +#include "opencv2/imgcodecs/imgcodecs_c.h" +#endif + #include #include #include diff --git a/modules/highgui/test/test_precomp.hpp b/modules/highgui/test/test_precomp.hpp index e4d7797158..40945acbfe 100644 --- a/modules/highgui/test/test_precomp.hpp +++ b/modules/highgui/test/test_precomp.hpp @@ -6,16 +6,4 @@ # endif #endif -#ifndef __OPENCV_TEST_PRECOMP_HPP__ -#define __OPENCV_TEST_PRECOMP_HPP__ - -#include #include "opencv2/ts.hpp" -//#include "opencv2/imgproc.hpp" -//#include "opencv2/imgcodecs.hpp" -//#include "opencv2/highgui.hpp" -//#include "opencv2/imgproc/imgproc_c.h" - -//#include "opencv2/core/private.hpp" - -#endif From ae3dfa80db593ee8d192659cd095b4f90b3ec469 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Thu, 25 Aug 2016 16:08:35 +0300 Subject: [PATCH 093/178] OpenVX HAL --- 3rdparty/openvx/CMakeLists.txt | 17 +++ 3rdparty/openvx/include/openvx_hal.hpp | 196 +++++++++++++++++++++++++ 3rdparty/openvx/src/openvx_hal.cpp | 8 + CMakeLists.txt | 15 ++ cmake/FindOpenVX.cmake | 20 +++ 5 files changed, 256 insertions(+) create mode 100644 3rdparty/openvx/CMakeLists.txt create mode 100644 3rdparty/openvx/include/openvx_hal.hpp create mode 100644 3rdparty/openvx/src/openvx_hal.cpp create mode 100644 cmake/FindOpenVX.cmake diff --git a/3rdparty/openvx/CMakeLists.txt b/3rdparty/openvx/CMakeLists.txt new file mode 100644 index 0000000000..ae9285eaf7 --- /dev/null +++ b/3rdparty/openvx/CMakeLists.txt @@ -0,0 +1,17 @@ +add_library(openvx_hal STATIC src/openvx_hal.cpp) +target_include_directories(openvx_hal PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/modules/core/include + ${OPENVX_INCLUDE_DIR}) +target_link_libraries(openvx_hal LINK_PUBLIC ${OPENVX_LIBRARIES}) +set_target_properties(openvx_hal PROPERTIES POSITION_INDEPENDENT_CODE TRUE) +set_target_properties(openvx_hal PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH}) +if(NOT BUILD_SHARED_LIBS) + ocv_install_target(openvx_hal EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) +endif() + +set(OPENVX_HAL_FOUND TRUE PARENT_SCOPE) +set(OPENVX_HAL_VERSION 0.0.1 PARENT_SCOPE) +set(OPENVX_HAL_LIBRARIES "openvx_hal" PARENT_SCOPE) +set(OPENVX_HAL_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/openvx_hal.hpp" PARENT_SCOPE) +set(OPENVX_HAL_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include" "${OPENVX_INCLUDE_DIR}" PARENT_SCOPE) diff --git a/3rdparty/openvx/include/openvx_hal.hpp b/3rdparty/openvx/include/openvx_hal.hpp new file mode 100644 index 0000000000..893547dfdf --- /dev/null +++ b/3rdparty/openvx/include/openvx_hal.hpp @@ -0,0 +1,196 @@ +#ifndef OPENCV_OPENVX_HAL_HPP_INCLUDED +#define OPENCV_OPENVX_HAL_HPP_INCLUDED + +#include "opencv2/core/hal/interface.h" + +#include "VX/vx.h" +#include "VX/vxu.h" + +#include + +//================================================================================================== +// utility +// ... + +#if 0 +#include +#define PRINT(...) printf(__VA_ARGS__) +#else +#define PRINT(...) +#endif + +#if __cplusplus >= 201103L +#include +struct Tick +{ + typedef std::chrono::time_point point_t; + point_t start; + point_t point; + Tick() + { + start = std::chrono::steady_clock::now(); + point = std::chrono::steady_clock::now(); + } + inline int one() + { + point_t old = point; + point = std::chrono::steady_clock::now(); + return std::chrono::duration_cast(point - old).count(); + } + inline int total() + { + return std::chrono::duration_cast(std::chrono::steady_clock::now() - start).count(); + } +}; +#endif + +//================================================================================================== +// One more OpenVX C++ binding :-) +// ... + +template +struct VX_Traits +{ + enum { + Type = 0 + }; +}; + +template <> +struct VX_Traits +{ + enum { + Type = VX_DF_IMAGE_U8 + }; +}; + +template <> +struct VX_Traits +{ + enum { + Type = VX_DF_IMAGE_U16 + }; +}; + +template <> +struct VX_Traits +{ + enum { + Type = VX_DF_IMAGE_S16 + }; +}; + + +struct vxContext; +struct vxImage; +struct vxErr; + + +struct vxErr +{ + vx_status status; + std::string msg; + vxErr(vx_status status_, const std::string & msg_) : status(status_), msg(msg_) {} + void check() + { + if (status != VX_SUCCESS) + throw *this; + } + void print() + { + PRINT("OpenVX HAL impl error: %d (%s)\n", status, msg.c_str()); + } + static void check(vx_context ctx) + { + vxErr(vxGetStatus((vx_reference)ctx), "context check").check(); + } + static void check(vx_image img) + { + vxErr(vxGetStatus((vx_reference)img), "image check").check(); + } + static void check(vx_status s) + { + vxErr(s, "status check").check(); + } +}; + + +struct vxContext +{ + vx_context ctx; + static vxContext * getContext(); +private: + vxContext() + { + ctx = vxCreateContext(); + vxErr::check(ctx); + } + ~vxContext() + { + vxReleaseContext(&ctx); + } +}; + + +struct vxImage +{ + vx_image img; + + template + vxImage(vxContext &ctx, const T *data, size_t step, int w, int h) + { + if (h == 1) + step = w * sizeof(T); + vx_imagepatch_addressing_t addr; + addr.dim_x = w; + addr.dim_y = h; + addr.stride_x = sizeof(T); + addr.stride_y = step; + addr.scale_x = VX_SCALE_UNITY; + addr.scale_y = VX_SCALE_UNITY; + addr.step_x = 1; + addr.step_y = 1; + void *ptrs[] = { (void*)data }; + img = vxCreateImageFromHandle(ctx.ctx, VX_Traits::Type, &addr, ptrs, VX_MEMORY_TYPE_HOST); + vxErr::check(img); + } + ~vxImage() + { + vxSwapImageHandle(img, NULL, NULL, 1); + vxReleaseImage(&img); + } +}; + +//================================================================================================== +// real code starts here +// ... + +template +inline int ovx_hal_add(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h) +{ + try + { + vxContext * ctx = vxContext::getContext(); + vxImage ia(*ctx, a, astep, w, h); + vxImage ib(*ctx, b, bstep, w, h); + vxImage ic(*ctx, c, cstep, w, h); + vxErr::check(vxuAdd(ctx->ctx, ia.img, ib.img, VX_CONVERT_POLICY_SATURATE, ic.img)); + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +//================================================================================================== +// functions redefinition +// ... + +#undef cv_hal_add8u +#define cv_hal_add8u ovx_hal_add +#undef cv_hal_add16s +#define cv_hal_add16s ovx_hal_add + +#endif diff --git a/3rdparty/openvx/src/openvx_hal.cpp b/3rdparty/openvx/src/openvx_hal.cpp new file mode 100644 index 0000000000..e95bbb2b58 --- /dev/null +++ b/3rdparty/openvx/src/openvx_hal.cpp @@ -0,0 +1,8 @@ +#include "openvx_hal.hpp" + +vxContext * vxContext::getContext() +{ + // not thread safe + static vxContext instance; + return &instance; +} diff --git a/CMakeLists.txt b/CMakeLists.txt index c9568546f7..9daf330033 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -190,6 +190,7 @@ OCV_OPTION(WITH_JPEG "Include JPEG support" ON) OCV_OPTION(WITH_WEBP "Include WebP support" ON IF (NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_OPENEXR "Include ILM support via OpenEXR" ON IF (NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_OPENGL "Include OpenGL support" OFF IF (NOT ANDROID AND NOT WINRT) ) +OCV_OPTION(WITH_OPENVX "Include OpenVX support" OFF) OCV_OPTION(WITH_OPENNI "Include OpenNI support" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_OPENNI2 "Include OpenNI2 support" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_PNG "Include PNG support" ON) @@ -615,6 +616,9 @@ endif() include(cmake/OpenCVDetectVTK.cmake) +if(WITH_OPENVX) + include(cmake/FindOpenVX.cmake) +endif() # ---------------------------------------------------------------------------- # OpenCV HAL @@ -640,6 +644,12 @@ if(NOT DEFINED OpenCV_HAL) set(OpenCV_HAL "OpenCV_HAL") endif() +if(HAVE_OPENVX) + if(NOT ";${OpenCV_HAL};" MATCHES ";openvx;") + set(OpenCV_HAL "openvx;${OpenCV_HAL}") + endif() +endif() + if(WITH_CAROTENE) ocv_debug_message(STATUS "Enable carotene acceleration") if(NOT ";${OpenCV_HAL};" MATCHES ";carotene;") @@ -652,6 +662,10 @@ foreach(hal ${OpenCV_HAL}) add_subdirectory(3rdparty/carotene/hal) ocv_hal_register(CAROTENE_HAL_LIBRARIES CAROTENE_HAL_HEADERS CAROTENE_HAL_INCLUDE_DIRS) list(APPEND OpenCV_USED_HAL "carotene (ver ${CAROTENE_HAL_VERSION})") + elseif(hal STREQUAL "openvx") + add_subdirectory(3rdparty/openvx) + ocv_hal_register(OPENVX_HAL_LIBRARIES OPENVX_HAL_HEADERS OPENVX_HAL_INCLUDE_DIRS) + list(APPEND OpenCV_USED_HAL "openvx (ver ${OPENVX_HAL_VERSION})") else() ocv_debug_message(STATUS "OpenCV HAL: ${hal} ...") ocv_clear_vars(OpenCV_HAL_LIBRARIES OpenCV_HAL_HEADERS OpenCV_HAL_INCLUDE_DIRS) @@ -1219,6 +1233,7 @@ endif(DEFINED WITH_LAPACK) status(" Use Eigen:" HAVE_EIGEN THEN "YES (ver ${EIGEN_WORLD_VERSION}.${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION})" ELSE NO) status(" Use Cuda:" HAVE_CUDA THEN "YES (ver ${CUDA_VERSION_STRING})" ELSE NO) status(" Use OpenCL:" HAVE_OPENCL THEN YES ELSE NO) +status(" Use OpenVX:" HAVE_OPENVX THEN "YES (${OPENVX_LIBS})" ELSE "NO") status(" Use custom HAL:" OpenCV_USED_HAL THEN "YES (${OpenCV_USED_HAL})" ELSE "NO") if(HAVE_CUDA) diff --git a/cmake/FindOpenVX.cmake b/cmake/FindOpenVX.cmake new file mode 100644 index 0000000000..dc1f7617bd --- /dev/null +++ b/cmake/FindOpenVX.cmake @@ -0,0 +1,20 @@ +ocv_clear_vars(HAVE_OPENVX OPENVX_LIBS) + +set(OPENVX_ROOT "" CACHE PATH "OpenVX install directory") + +if(OPENVX_ROOT) + find_path(OPENVX_INCLUDE_DIR "VX/vx.h" PATHS "${OPENVX_ROOT}/include" DOC "OpenVX include path") + find_library(OPENVX_openvx_LIB "openvx" PATHS "${OPENVX_ROOT}/lib") + find_library(OPENVX_vxu_LIB "vxu" PATHS "${OPENVX_ROOT}/lib") + set(OPENVX_LIBRARIES "${OPENVX_openvx_LIB}" "${OPENVX_vxu_LIB}" CACHE STRING "OpenVX libraries") + if (OPENVX_INCLUDE_DIR AND OPENVX_LIBRARIES) + set(HAVE_OPENVX TRUE) + endif() +endif() + +if(NOT HAVE_OPENVX) + unset(OPENVX_LIBRARIES CACHE) + unset(OPENVX_INCLUDE_DIR CACHE) + unset(HAVE_OPENVX) + message(STATUS "OpenVX: OFF") +endif() From 5383a625a787307013e14ac9452a3b95bc116725 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 25 Aug 2016 16:21:52 +0300 Subject: [PATCH 094/178] fix Win build, change default WINNT macro to WinXP Returning to Win2k value is possible via this CMake option: cmake -DOPENCV_EXTRA_FLAGS="/D_WIN32_WINNT=0x0500" ... --- modules/core/src/parallel.cpp | 2 +- modules/highgui/src/precomp.hpp | 8 -------- modules/imgcodecs/src/precomp.hpp | 8 -------- modules/videoio/src/cap_ffmpeg.cpp | 24 ++++++++++-------------- modules/videoio/src/precomp.hpp | 2 +- 5 files changed, 12 insertions(+), 32 deletions(-) diff --git a/modules/core/src/parallel.cpp b/modules/core/src/parallel.cpp index d4968652a3..e4ee8f50ab 100644 --- a/modules/core/src/parallel.cpp +++ b/modules/core/src/parallel.cpp @@ -521,7 +521,7 @@ int cv::getNumberOfCPUs(void) { #if defined WIN32 || defined _WIN32 SYSTEM_INFO sysinfo; -#if defined(_M_ARM) || defined(_M_X64) || defined(WINRT) +#if (defined(_M_ARM) || defined(_M_X64) || defined(WINRT)) && _WIN32_WINNT >= 0x501 GetNativeSystemInfo( &sysinfo ); #else GetSystemInfo( &sysinfo ); diff --git a/modules/highgui/src/precomp.hpp b/modules/highgui/src/precomp.hpp index 796af39768..31969403b1 100644 --- a/modules/highgui/src/precomp.hpp +++ b/modules/highgui/src/precomp.hpp @@ -61,14 +61,6 @@ #include #if defined WIN32 || defined WINCE - #if !defined _WIN32_WINNT - #ifdef HAVE_MSMF - #define _WIN32_WINNT 0x0600 // Windows Vista - #else - #define _WIN32_WINNT 0x0500 // Windows 2000 - #endif - #endif - #include #undef small #undef min diff --git a/modules/imgcodecs/src/precomp.hpp b/modules/imgcodecs/src/precomp.hpp index 101f01577c..6a16ca865a 100644 --- a/modules/imgcodecs/src/precomp.hpp +++ b/modules/imgcodecs/src/precomp.hpp @@ -59,14 +59,6 @@ #include #if defined WIN32 || defined WINCE - #if !defined _WIN32_WINNT - #ifdef HAVE_MSMF - #define _WIN32_WINNT 0x0600 // Windows Vista - #else - #define _WIN32_WINNT 0x0500 // Windows 2000 - #endif - #endif - #include #undef small #undef min diff --git a/modules/videoio/src/cap_ffmpeg.cpp b/modules/videoio/src/cap_ffmpeg.cpp index 772996e505..26e2ead0cd 100644 --- a/modules/videoio/src/cap_ffmpeg.cpp +++ b/modules/videoio/src/cap_ffmpeg.cpp @@ -65,9 +65,11 @@ static cv::Mutex _icvInitFFMPEG_mutex; static const HMODULE cv_GetCurrentModule() { HMODULE h = 0; +#if _WIN32_WINNT >= 0x0501 ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, reinterpret_cast(cv_GetCurrentModule), &h); +#endif return h; } #endif @@ -98,22 +100,16 @@ private: icvInitFFMPEG() { #if defined WIN32 || defined _WIN32 + const wchar_t* module_name_ = L"opencv_ffmpeg" + CVAUX_STRW(CV_MAJOR_VERSION) CVAUX_STRW(CV_MINOR_VERSION) CVAUX_STRW(CV_SUBMINOR_VERSION) + #if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__) + L"_64" + #endif + L".dll"; # ifdef WINRT - const wchar_t* module_name = L"opencv_ffmpeg" - CVAUX_STRW(CV_MAJOR_VERSION) CVAUX_STRW(CV_MINOR_VERSION) CVAUX_STRW(CV_SUBMINOR_VERSION) - #if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__) - L"_64" - #endif - L".dll"; - - icvFFOpenCV = LoadPackagedLibrary( module_name, 0 ); + icvFFOpenCV = LoadPackagedLibrary( module_name_, 0 ); # else - const std::wstring module_name = L"opencv_ffmpeg" - CVAUX_STRW(CV_MAJOR_VERSION) CVAUX_STRW(CV_MINOR_VERSION) CVAUX_STRW(CV_SUBMINOR_VERSION) - #if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__) - L"_64" - #endif - L".dll"; + const std::wstring module_name(module_name_); const wchar_t* ffmpeg_env_path = _wgetenv(L"OPENCV_FFMPEG_DLL_DIR"); std::wstring module_path = diff --git a/modules/videoio/src/precomp.hpp b/modules/videoio/src/precomp.hpp index 45ce1a1f60..517dc9186b 100644 --- a/modules/videoio/src/precomp.hpp +++ b/modules/videoio/src/precomp.hpp @@ -66,7 +66,7 @@ #ifdef HAVE_MSMF #define _WIN32_WINNT 0x0600 // Windows Vista #else - #define _WIN32_WINNT 0x0500 // Windows 2000 + #define _WIN32_WINNT 0x0501 // Windows XP #endif #endif From f1db065c10eb6be75fdb08ae50264b1481eb49f5 Mon Sep 17 00:00:00 2001 From: Valeriy Van Date: Thu, 25 Aug 2016 21:40:16 +0300 Subject: [PATCH 095/178] Unifies Obj-C property attributes changing retain to strong strong and retain are synonymous but using strong along with obsolete synonym retain in one file is negligent --- modules/videoio/include/opencv2/videoio/cap_ios.h | 12 ++++++------ modules/videoio/src/cap_ios_abstract_camera.mm | 2 +- modules/videoio/src/cap_ios_photo_camera.mm | 2 +- modules/videoio/src/cap_ios_video_camera.mm | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/videoio/include/opencv2/videoio/cap_ios.h b/modules/videoio/include/opencv2/videoio/cap_ios.h index 1a9875b257..9075fe1c80 100644 --- a/modules/videoio/include/opencv2/videoio/cap_ios.h +++ b/modules/videoio/include/opencv2/videoio/cap_ios.h @@ -64,8 +64,8 @@ int imageHeight; } -@property (nonatomic, retain) AVCaptureSession* captureSession; -@property (nonatomic, retain) AVCaptureConnection* videoCaptureConnection; +@property (nonatomic, strong) AVCaptureSession* captureSession; +@property (nonatomic, strong) AVCaptureConnection* videoCaptureConnection; @property (nonatomic, readonly) BOOL running; @property (nonatomic, readonly) BOOL captureSessionLoaded; @@ -80,7 +80,7 @@ @property (nonatomic, assign) int imageWidth; @property (nonatomic, assign) int imageHeight; -@property (nonatomic, retain) UIView* parentView; +@property (nonatomic, strong) UIView* parentView; - (void)start; - (void)stop; @@ -138,9 +138,9 @@ @property (nonatomic, assign) BOOL recordVideo; @property (nonatomic, assign) BOOL rotateVideo; -@property (nonatomic, retain) AVAssetWriterInput* recordAssetWriterInput; -@property (nonatomic, retain) AVAssetWriterInputPixelBufferAdaptor* recordPixelBufferAdaptor; -@property (nonatomic, retain) AVAssetWriter* recordAssetWriter; +@property (nonatomic, strong) AVAssetWriterInput* recordAssetWriterInput; +@property (nonatomic, strong) AVAssetWriterInputPixelBufferAdaptor* recordPixelBufferAdaptor; +@property (nonatomic, strong) AVAssetWriter* recordAssetWriter; - (void)adjustLayoutToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation; - (void)layoutPreviewLayer; diff --git a/modules/videoio/src/cap_ios_abstract_camera.mm b/modules/videoio/src/cap_ios_abstract_camera.mm index e580f24250..5c870a7604 100644 --- a/modules/videoio/src/cap_ios_abstract_camera.mm +++ b/modules/videoio/src/cap_ios_abstract_camera.mm @@ -37,7 +37,7 @@ @interface CvAbstractCamera () -@property (nonatomic, retain) AVCaptureVideoPreviewLayer* captureVideoPreviewLayer; +@property (nonatomic, strong) AVCaptureVideoPreviewLayer* captureVideoPreviewLayer; - (void)deviceOrientationDidChange:(NSNotification*)notification; - (void)startCaptureSession; diff --git a/modules/videoio/src/cap_ios_photo_camera.mm b/modules/videoio/src/cap_ios_photo_camera.mm index c6c93a8cf0..8cf19226b6 100644 --- a/modules/videoio/src/cap_ios_photo_camera.mm +++ b/modules/videoio/src/cap_ios_photo_camera.mm @@ -37,7 +37,7 @@ @interface CvPhotoCamera () -@property (nonatomic, retain) AVCaptureStillImageOutput* stillImageOutput; +@property (nonatomic, strong) AVCaptureStillImageOutput* stillImageOutput; @end diff --git a/modules/videoio/src/cap_ios_video_camera.mm b/modules/videoio/src/cap_ios_video_camera.mm index ee074afdef..c1a0b4d774 100644 --- a/modules/videoio/src/cap_ios_video_camera.mm +++ b/modules/videoio/src/cap_ios_video_camera.mm @@ -49,8 +49,8 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} - (void)createVideoFileOutput; -@property (nonatomic, retain) CALayer *customPreviewLayer; -@property (nonatomic, retain) AVCaptureVideoDataOutput *videoDataOutput; +@property (nonatomic, strong) CALayer *customPreviewLayer; +@property (nonatomic, strong) AVCaptureVideoDataOutput *videoDataOutput; @end From db6d94a7b07f57ed8a359263753c056bd2081827 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 26 Aug 2016 13:33:47 +0300 Subject: [PATCH 096/178] cmake: minimize MSVS projects layout Also put "object" targets to off by default (they doesn't work well) --- cmake/OpenCVModule.cmake | 4 ++++ cmake/OpenCVUtils.cmake | 2 +- modules/core/CMakeLists.txt | 6 ++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 197aead0d2..742a287ec9 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -779,6 +779,8 @@ macro(_ocv_create_module) endforeach() endif() + source_group("Include" FILES "${OPENCV_CONFIG_FILE_INCLUDE_DIR}/cvconfig.h" "${OPENCV_CONFIG_FILE_INCLUDE_DIR}/opencv2/opencv_modules.hpp") + source_group("Src" FILES "${${the_module}_pch}") ocv_add_library(${the_module} ${OPENCV_MODULE_TYPE} ${OPENCV_MODULE_${the_module}_HEADERS} ${OPENCV_MODULE_${the_module}_SOURCES} "${OPENCV_CONFIG_FILE_INCLUDE_DIR}/cvconfig.h" "${OPENCV_CONFIG_FILE_INCLUDE_DIR}/opencv2/opencv_modules.hpp" ${${the_module}_pch} ${sub_objs}) @@ -1015,6 +1017,7 @@ function(ocv_add_perf_tests) get_native_precompiled_header(${the_target} perf_precomp.hpp) endif() + source_group("Src" FILES "${${the_target}_pch}") ocv_add_executable(${the_target} ${OPENCV_PERF_${the_module}_SOURCES} ${${the_target}_pch}) ocv_target_include_modules(${the_target} ${perf_deps} "${perf_path}") ocv_target_link_libraries(${the_target} ${perf_deps} ${OPENCV_MODULE_${the_module}_DEPS} ${OPENCV_LINKER_LIBS}) @@ -1091,6 +1094,7 @@ function(ocv_add_accuracy_tests) get_native_precompiled_header(${the_target} test_precomp.hpp) endif() + source_group("Src" FILES "${${the_target}_pch}") ocv_add_executable(${the_target} ${OPENCV_TEST_${the_module}_SOURCES} ${${the_target}_pch}) ocv_target_include_modules(${the_target} ${test_deps} "${test_path}") ocv_target_link_libraries(${the_target} ${test_deps} ${OPENCV_MODULE_${the_module}_DEPS} ${OPENCV_LINKER_LIBS}) diff --git a/cmake/OpenCVUtils.cmake b/cmake/OpenCVUtils.cmake index b1a099e695..8d7c98b3e5 100644 --- a/cmake/OpenCVUtils.cmake +++ b/cmake/OpenCVUtils.cmake @@ -815,7 +815,7 @@ function(ocv_add_library target) add_library(${target} ${ARGN} ${cuda_objs}) # Add OBJECT library (added in cmake 2.8.8) to use in compound modules - if (NOT CMAKE_VERSION VERSION_LESS "2.8.8" + if (NOT CMAKE_VERSION VERSION_LESS "2.8.8" AND OPENCV_ENABLE_OBJECT_TARGETS AND NOT OPENCV_MODULE_${target}_CHILDREN AND NOT OPENCV_MODULE_${target}_CLASS STREQUAL "BINDINGS" AND NOT ${target} STREQUAL "opencv_ts" diff --git a/modules/core/CMakeLists.txt b/modules/core/CMakeLists.txt index 36c4eea5d4..0485a08ad3 100644 --- a/modules/core/CMakeLists.txt +++ b/modules/core/CMakeLists.txt @@ -22,8 +22,10 @@ endif() file(GLOB lib_cuda_hdrs "include/opencv2/${name}/cuda/*.hpp" "include/opencv2/${name}/cuda/*.h") file(GLOB lib_cuda_hdrs_detail "include/opencv2/${name}/cuda/detail/*.hpp" "include/opencv2/${name}/cuda/detail/*.h") -source_group("Cuda Headers" FILES ${lib_cuda_hdrs}) -source_group("Cuda Headers\\Detail" FILES ${lib_cuda_hdrs_detail}) +source_group("Include\\Cuda Headers" FILES ${lib_cuda_hdrs}) +source_group("Include\\Cuda Headers\\Detail" FILES ${lib_cuda_hdrs_detail}) + +source_group("Src" FILES "${OPENCV_MODULE_opencv_core_BINARY_DIR}/version_string.inc") ocv_glob_module_sources(SOURCES "${OPENCV_MODULE_opencv_core_BINARY_DIR}/version_string.inc" HEADERS ${lib_cuda_hdrs} ${lib_cuda_hdrs_detail}) From 5ddd25313fa77f033325035f16adba0068a6f018 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Fri, 26 Aug 2016 16:01:00 +0400 Subject: [PATCH 097/178] Add Grana's connected components algorithm for 8-way connectivity. (#6823) * Add Grana's connected components algorithm for 8-way connectivity. That algorithm is faster than Wu's one (currently implemented in opencv). For more details see https://github.com/prittt/YACCLAB. * New functions signature and distance transform compatibility * Add tests to imgproc/test/test_connectedcomponents.cpp * Change of test_connectedcomponents.cpp for c++98 support --- modules/imgproc/include/opencv2/imgproc.hpp | 51 +- modules/imgproc/src/connectedcomponents.cpp | 1401 ++++++++++++++++- modules/imgproc/src/distransform.cpp | 2 +- .../imgproc/test/test_connectedcomponents.cpp | 85 +- 4 files changed, 1486 insertions(+), 53 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index f4698036b6..71c4f48d12 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -413,6 +413,13 @@ enum ConnectedComponentsTypes { CC_STAT_MAX = 5 }; +//! connected components algorithm +enum ConnectedComponentsAlgorithmsTypes { + CCL_WU = 0, //!< SAUF algorithm for 8-way connectivity, SAUF algorithm for 4-way connectivity + CCL_DEFAULT = -1, //!< BBDT algortihm for 8-way connectivity, SAUF algorithm for 4-way connectivity + CCL_GRANA = 1 //!< BBDT algorithm for 8-way connectivity, SAUF algorithm for 4-way connectivity +}; + //! mode of the contour retrieval algorithm enum RetrievalModes { /** retrieves only the extreme outer contours. It sets `hierarchy[i][2]=hierarchy[i][3]=-1` for @@ -3648,16 +3655,56 @@ CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ, image with 4 or 8 way connectivity - returns N, the total number of labels [0, N-1] where 0 represents the background label. ltype specifies the output label image type, an important consideration based on the total number of labels or alternatively the total number of pixels in -the source image. +the source image. ccltype specifies the connected components labeling algorithm to use, currently +Grana's (BBDT) and Wu's (SAUF) algorithms are supported, see the cv::ConnectedComponentsAlgorithmsTypes +for details. Note that SAUF algorithm forces a row major ordering of labels while BBDT does not. @param image the 8-bit single-channel image to be labeled @param labels destination labeled image @param connectivity 8 or 4 for 8-way or 4-way connectivity respectively @param ltype output image label type. Currently CV_32S and CV_16U are supported. - */ +@param ccltype connected components algorithm type (see the cv::ConnectedComponentsAlgorithmsTypes). +*/ +CV_EXPORTS_AS(connectedComponentsWithAlgorithm) int connectedComponents(InputArray image, OutputArray labels, + int connectivity, int ltype, int ccltype); + + +/** @overload + +@param image the 8-bit single-channel image to be labeled +@param labels destination labeled image +@param connectivity 8 or 4 for 8-way or 4-way connectivity respectively +@param ltype output image label type. Currently CV_32S and CV_16U are supported. +*/ CV_EXPORTS_W int connectedComponents(InputArray image, OutputArray labels, int connectivity = 8, int ltype = CV_32S); + +/** @brief computes the connected components labeled image of boolean image and also produces a statistics output for each label + +image with 4 or 8 way connectivity - returns N, the total number of labels [0, N-1] where 0 +represents the background label. ltype specifies the output label image type, an important +consideration based on the total number of labels or alternatively the total number of pixels in +the source image. ccltype specifies the connected components labeling algorithm to use, currently +Grana's (BBDT) and Wu's (SAUF) algorithms are supported, see the cv::ConnectedComponentsAlgorithmsTypes +for details. Note that SAUF algorithm forces a row major ordering of labels while BBDT does not. + + +@param image the 8-bit single-channel image to be labeled +@param labels destination labeled image +@param stats statistics output for each label, including the background label, see below for +available statistics. Statistics are accessed via stats(label, COLUMN) where COLUMN is one of +cv::ConnectedComponentsTypes. The data type is CV_32S. +@param centroids centroid output for each label, including the background label. Centroids are +accessed via centroids(label, 0) for x and centroids(label, 1) for y. The data type CV_64F. +@param connectivity 8 or 4 for 8-way or 4-way connectivity respectively +@param ltype output image label type. Currently CV_32S and CV_16U are supported. +@param ccltype connected components algorithm type (see the cv::ConnectedComponentsAlgorithmsTypes). +*/ +CV_EXPORTS_AS(connectedComponentsWithStatsWithAlgorithm) int connectedComponentsWithStats(InputArray image, OutputArray labels, + OutputArray stats, OutputArray centroids, + int connectivity, int ltype, int ccltype); + /** @overload @param image the 8-bit single-channel image to be labeled @param labels destination labeled image diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp index 523eb14c09..bf53704144 100644 --- a/modules/imgproc/src/connectedcomponents.cpp +++ b/modules/imgproc/src/connectedcomponents.cpp @@ -38,6 +38,10 @@ // the use of this software, even if advised of the possibility of such damage. // // 2011 Jason Newton +// 2016 Costantino Grama +// 2016 Federico Bolelli +// 2016 Lorenzo Baraldi +// 2016 Roberto Vezzani //M*/ // #include "precomp.hpp" @@ -188,7 +192,7 @@ namespace cv{ //reference for 8-way: {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}};//a, b, c, d neighborhoods const int G8[4][2] = {{1, -1}, {1, 0}, {1, 1}, {0, -1}};//a, b, c, d neighborhoods template - struct LabelingImpl{ + struct LabelingWu{ LabelT operator()(const cv::Mat &I, cv::Mat &L, int connectivity, StatsOp &sop){ CV_Assert(L.rows == I.rows); CV_Assert(L.cols == I.cols); @@ -329,33 +333,1366 @@ namespace cv{ fastFree(P); return nLabels; - }//End function LabelingImpl operator() + }//End function LabelingWu operator() + };//End struct LabelingWu - };//End struct LabelingImpl + // Based on “Optimized Block-based Connected Components Labeling with Decision Trees”, Costantino Grana et al + // Only for 8-connectivity + template + struct LabelingGrana{ + LabelT operator()(const cv::Mat &img, cv::Mat &imgLabels, int connectivity, StatsOp &sop){ + CV_Assert(img.rows == imgLabels.rows); + CV_Assert(img.cols == imgLabels.cols); + CV_Assert(connectivity == 8 || connectivity == 4); + + const int h = img.rows; + const int w = img.cols; + + //A quick and dirty upper bound for the maximimum number of labels. + const size_t Plength = img.rows*img.cols / 4; + LabelT *P = (LabelT *)fastMalloc(sizeof(LabelT)* Plength); + P[0] = 0; + LabelT lunique = 1; + + // First scan + for (int r = 0; r(r); + const PixelT* const img_row_prev = (PixelT *)(((char *)img_row) - img.step.p[0]); + const PixelT* const img_row_prev_prev = (PixelT *)(((char *)img_row_prev) - img.step.p[0]); + const PixelT* const img_row_fol = (PixelT *)(((char *)img_row) + img.step.p[0]); + LabelT* const imgLabels_row = imgLabels.ptr(r); + LabelT* const imgLabels_row_prev_prev = (LabelT *)(((char *)imgLabels_row) - imgLabels.step.p[0] - imgLabels.step.p[0]); + for (int c = 0; c < w; c += 2) { + + // We work with 2x2 blocks + // +-+-+-+ + // |P|Q|R| + // +-+-+-+ + // |S|X| + // +-+-+ + + // The pixels are named as follows + // +---+---+---+ + // |a b|c d|e f| + // |g h|i j|k l| + // +---+---+---+ + // |m n|o p| + // |q r|s t| + // +---+---+ + + // Pixels a, f, l, q are not needed, since we need to understand the + // the connectivity between these blocks and those pixels only metter + // when considering the outer connectivities + + // A bunch of defines used to check if the pixels are foreground, + // without going outside the image limits. + #define condition_b c-1>=0 && r-2>=0 && img_row_prev_prev[c-1]>0 + #define condition_c r-2>=0 && img_row_prev_prev[c]>0 + #define condition_d c+1=0 && img_row_prev_prev[c+1]>0 + #define condition_e c+2=0 && img_row_prev_prev[c+2]>0 + + #define condition_g c-2>=0 && r-1>=0 && img_row_prev[c-2]>0 + #define condition_h c-1>=0 && r-1>=0 && img_row_prev[c-1]>0 + #define condition_i r-1>=0 && img_row_prev[c]>0 + #define condition_j c+1=0 && img_row_prev[c+1]>0 + #define condition_k c+2=0 && img_row_prev[c+2]>0 + + #define condition_m c-2>=0 && img_row[c-2]>0 + #define condition_n c-1>=0 && img_row[c-1]>0 + #define condition_o img_row[c]>0 + #define condition_p c+10 + + #define condition_r c-1>=0 && r+10 + #define condition_s r+10 + #define condition_t c+10 + + // This is a decision tree which allows to choose which action to + // perform, checking as few conditions as possible. + // Actions: the blocks label are provisionally stored in the top left + // pixel of the block in the labels image + + if (condition_o) { + if (condition_n) { + if (condition_j) { + if (condition_i) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_c) { + if (condition_h) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_g) { + if (condition_b) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + } + else { + if (condition_p) { + if (condition_k) { + if (condition_d) { + if (condition_i) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_c) { + if (condition_h) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_g) { + if (condition_b) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + } + else { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + } + } + else { + if (condition_r) { + if (condition_j) { + if (condition_m) { + if (condition_h) { + if (condition_i) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_c) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + } + else { + if (condition_g) { + if (condition_b) { + if (condition_i) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_c) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + } + else { + if (condition_i) { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + else { + if (condition_h) { + if (condition_c) { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + else { + //Action_14: Merge labels of block P, Q and S + imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row_prev_prev[c]), imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + } + } + else { + if (condition_p) { + if (condition_k) { + if (condition_m) { + if (condition_h) { + if (condition_d) { + if (condition_i) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_c) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + else { + if (condition_d) { + if (condition_g) { + if (condition_b) { + if (condition_i) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_c) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + else { + if (condition_i) { + if (condition_g) { + if (condition_b) { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + else { + //Action_16: labels of block Q, R and S + imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_16: labels of block Q, R and S + imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + } + } + else { + if (condition_i) { + if (condition_d) { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + else { + //Action_16: labels of block Q, R and S + imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]); + continue; + } + } + else { + if (condition_h) { + if (condition_d) { + if (condition_c) { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + else { + //Action_15: Merge labels of block P, R and S + imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_15: Merge labels of block P, R and S + imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + } + } + else { + if (condition_h) { + if (condition_m) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + // ACTION_9 Merge labels of block P and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row[c - 2]); + continue; + } + } + else { + if (condition_i) { + if (condition_m) { + if (condition_g) { + if (condition_b) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + } + } + } + else { + if (condition_h) { + if (condition_m) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + // ACTION_9 Merge labels of block P and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row[c - 2]); + continue; + } + } + else { + if (condition_i) { + if (condition_m) { + if (condition_g) { + if (condition_b) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + } + } + } + } + else { + if (condition_j) { + if (condition_i) { + //Action_4: Assign label of block Q + imgLabels_row[c] = imgLabels_row_prev_prev[c]; + continue; + } + else { + if (condition_h) { + if (condition_c) { + //Action_4: Assign label of block Q + imgLabels_row[c] = imgLabels_row_prev_prev[c]; + continue; + } + else { + //Action_7: Merge labels of block P and Q + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row_prev_prev[c]); + continue; + } + } + else { + //Action_4: Assign label of block Q + imgLabels_row[c] = imgLabels_row_prev_prev[c]; + continue; + } + } + } + else { + if (condition_p) { + if (condition_k) { + if (condition_i) { + if (condition_d) { + //Action_5: Assign label of block R + imgLabels_row[c] = imgLabels_row_prev_prev[c + 2]; + continue; + } + else { + // ACTION_10 Merge labels of block Q and R + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]); + continue; + } + } + else { + if (condition_h) { + if (condition_d) { + if (condition_c) { + //Action_5: Assign label of block R + imgLabels_row[c] = imgLabels_row_prev_prev[c + 2]; + continue; + } + else { + //Action_8: Merge labels of block P and R + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row_prev_prev[c + 2]); + continue; + } + } + else { + //Action_8: Merge labels of block P and R + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row_prev_prev[c + 2]); + continue; + } + } + else { + //Action_5: Assign label of block R + imgLabels_row[c] = imgLabels_row_prev_prev[c + 2]; + continue; + } + } + } + else { + if (condition_i) { + //Action_4: Assign label of block Q + imgLabels_row[c] = imgLabels_row_prev_prev[c]; + continue; + } + else { + if (condition_h) { + //Action_3: Assign label of block P + imgLabels_row[c] = imgLabels_row_prev_prev[c - 2]; + continue; + } + else { + //Action_2: New label (the block has foreground pixels and is not connected to anything else) + imgLabels_row[c] = lunique; + P[lunique] = lunique; + lunique = lunique + 1; + continue; + } + } + } + } + else { + if (condition_i) { + //Action_4: Assign label of block Q + imgLabels_row[c] = imgLabels_row_prev_prev[c]; + continue; + } + else { + if (condition_h) { + //Action_3: Assign label of block P + imgLabels_row[c] = imgLabels_row_prev_prev[c - 2]; + continue; + } + else { + //Action_2: New label (the block has foreground pixels and is not connected to anything else) + imgLabels_row[c] = lunique; + P[lunique] = lunique; + lunique = lunique + 1; + continue; + } + } + } + } + } + } + } + else { + if (condition_s) { + if (condition_p) { + if (condition_n) { + if (condition_j) { + if (condition_i) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_c) { + if (condition_h) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_g) { + if (condition_b) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + } + else { + if (condition_k) { + if (condition_d) { + if (condition_i) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_c) { + if (condition_h) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_g) { + if (condition_b) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + } + } + else { + if (condition_r) { + if (condition_j) { + if (condition_m) { + if (condition_h) { + if (condition_i) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_c) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + } + else { + if (condition_g) { + if (condition_b) { + if (condition_i) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_c) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + else { + if (condition_k) { + if (condition_d) { + if (condition_m) { + if (condition_h) { + if (condition_i) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_c) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + } + else { + if (condition_g) { + if (condition_b) { + if (condition_i) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_c) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + else { + if (condition_i) { + if (condition_m) { + if (condition_h) { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + else { + if (condition_g) { + if (condition_b) { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + else { + //Action_16: labels of block Q, R and S + imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_16: labels of block Q, R and S + imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_16: labels of block Q, R and S + imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_12: Merge labels of block R and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]); + continue; + } + } + } + else { + if (condition_i) { + if (condition_m) { + if (condition_h) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_g) { + if (condition_b) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + } + else { + //Action_11: Merge labels of block Q and S + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]); + continue; + } + } + else { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + } + } + } + else { + if (condition_j) { + //Action_4: Assign label of block Q + imgLabels_row[c] = imgLabels_row_prev_prev[c]; + continue; + } + else { + if (condition_k) { + if (condition_i) { + if (condition_d) { + //Action_5: Assign label of block R + imgLabels_row[c] = imgLabels_row_prev_prev[c + 2]; + continue; + } + else { + // ACTION_10 Merge labels of block Q and R + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]); + continue; + } + } + else { + //Action_5: Assign label of block R + imgLabels_row[c] = imgLabels_row_prev_prev[c + 2]; + continue; + } + } + else { + if (condition_i) { + //Action_4: Assign label of block Q + imgLabels_row[c] = imgLabels_row_prev_prev[c]; + continue; + } + else { + //Action_2: New label (the block has foreground pixels and is not connected to anything else) + imgLabels_row[c] = lunique; + P[lunique] = lunique; + lunique = lunique + 1; + continue; + } + } + } + } + } + } + else { + if (condition_r) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + if (condition_n) { + //Action_6: Assign label of block S + imgLabels_row[c] = imgLabels_row[c - 2]; + continue; + } + else { + //Action_2: New label (the block has foreground pixels and is not connected to anything else) + imgLabels_row[c] = lunique; + P[lunique] = lunique; + lunique = lunique + 1; + continue; + } + } + } + } + else { + if (condition_p) { + if (condition_j) { + //Action_4: Assign label of block Q + imgLabels_row[c] = imgLabels_row_prev_prev[c]; + continue; + } + else { + if (condition_k) { + if (condition_i) { + if (condition_d) { + //Action_5: Assign label of block R + imgLabels_row[c] = imgLabels_row_prev_prev[c + 2]; + continue; + } + else { + // ACTION_10 Merge labels of block Q and R + imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]); + continue; + } + } + else { + //Action_5: Assign label of block R + imgLabels_row[c] = imgLabels_row_prev_prev[c + 2]; + continue; + } + } + else { + if (condition_i) { + //Action_4: Assign label of block Q + imgLabels_row[c] = imgLabels_row_prev_prev[c]; + continue; + } + else { + //Action_2: New label (the block has foreground pixels and is not connected to anything else) + imgLabels_row[c] = lunique; + P[lunique] = lunique; + lunique = lunique + 1; + continue; + } + } + } + } + else { + if (condition_t) { + //Action_2: New label (the block has foreground pixels and is not connected to anything else) + imgLabels_row[c] = lunique; + P[lunique] = lunique; + lunique = lunique + 1; + continue; + } + else { + // Action_1: No action (the block has no foreground pixels) + imgLabels_row[c] = 0; + continue; + } + } + } + } + } + } + + // Second scan + analysis + LabelT nLabels = flattenL(P, lunique); + sop.init(nLabels); + + if (imgLabels.rows & 1){ + if (imgLabels.cols & 1){ + //Case 1: both rows and cols odd + for (int r = 0; r(r); + const PixelT* const img_row_fol = (PixelT *)(((char *)img_row) + img.step.p[0]); + LabelT* const imgLabels_row = imgLabels.ptr(r); + LabelT* const imgLabels_row_fol = (LabelT *)(((char *)imgLabels_row) + imgLabels.step.p[0]); + + for (int c = 0; c0) { + iLabel = P[iLabel]; + if (img_row[c] > 0){ + imgLabels_row[c] = iLabel; + sop(r, c, iLabel); + } + else{ + imgLabels_row[c] = 0; + sop(r, c, 0); + } + if (c + 1 0){ + imgLabels_row[c + 1] = iLabel; + sop(r, c + 1, iLabel); + } + else{ + imgLabels_row[c + 1] = 0; + sop(r, c + 1, 0); + } + if (r + 1 0){ + imgLabels_row_fol[c] = iLabel; + sop(r + 1, c, iLabel); + } else{ + imgLabels_row_fol[c] = 0; + sop(r + 1, c, 0); + } + if (img_row_fol[c + 1]>0){ + imgLabels_row_fol[c + 1] = iLabel; + sop(r + 1, c + 1, iLabel); + } else{ + imgLabels_row_fol[c + 1] = 0; + sop(r + 1, c + 1, 0); + } + } + } + else if (r + 10){ + imgLabels_row_fol[c] = iLabel; + sop(r + 1, c, iLabel); + }else{ + imgLabels_row_fol[c] = 0; + sop(r + 1, c, 0); + } + } + } + else { + imgLabels_row[c] = 0; + sop(r, c, 0); + if (c + 1(r); + const PixelT* const img_row_fol = (PixelT *)(((char *)img_row) + img.step.p[0]); + LabelT* const imgLabels_row = imgLabels.ptr(r); + LabelT* const imgLabels_row_fol = (LabelT *)(((char *)imgLabels_row) + imgLabels.step.p[0]); + + for (int c = 0; c0) { + iLabel = P[iLabel]; + if (img_row[c]>0){ + imgLabels_row[c] = iLabel; + sop(r, c, iLabel); + } else{ + imgLabels_row[c] = 0; + sop(r, c, 0); + } + if (img_row[c + 1]>0){ + imgLabels_row[c + 1] = iLabel; + sop(r, c + 1, iLabel); + }else{ + imgLabels_row[c + 1] = 0; + sop(r, c + 1, 0); + } + if (r + 10){ + imgLabels_row_fol[c] = iLabel; + sop(r + 1, c, iLabel); + }else{ + imgLabels_row_fol[c] = 0; + sop(r + 1, c, 0); + } + if (img_row_fol[c + 1]>0){ + imgLabels_row_fol[c + 1] = iLabel; + sop(r + 1, c + 1, iLabel); + }else{ + imgLabels_row_fol[c + 1] = 0; + sop(r + 1, c + 1, 0); + } + } + } + else { + imgLabels_row[c] = 0; + imgLabels_row[c + 1] = 0; + sop(r, c, 0); + sop(r, c + 1, 0); + if (r + 1(r); + const PixelT* const img_row_fol = (PixelT *)(((char *)img_row) + img.step.p[0]); + LabelT* const imgLabels_row = imgLabels.ptr(r); + LabelT* const imgLabels_row_fol = (LabelT *)(((char *)imgLabels_row) + imgLabels.step.p[0]); + + for (int c = 0; c0) { + iLabel = P[iLabel]; + if (img_row[c]>0){ + imgLabels_row[c] = iLabel; + sop(r, c, iLabel); + }else{ + imgLabels_row[c] = 0; + sop(r, c, 0); + } + if (img_row_fol[c]>0){ + imgLabels_row_fol[c] = iLabel; + sop(r + 1, c, iLabel); + }else{ + imgLabels_row_fol[c] = 0; + sop(r + 1, c, 0); + } + if (c + 10){ + imgLabels_row[c + 1] = iLabel; + sop(r, c + 1, iLabel); + }else{ + imgLabels_row[c + 1] = 0; + sop(r, c + 1, 0); + } + if (img_row_fol[c + 1]>0){ + imgLabels_row_fol[c + 1] = iLabel; + sop(r + 1, c + 1, iLabel); + }else{ + imgLabels_row_fol[c + 1] = 0; + sop(r + 1, c + 1, 0); + } + } + } + else{ + imgLabels_row[c] = 0; + imgLabels_row_fol[c] = 0; + sop(r, c, 0); + sop(r + 1, c, 0); + if (c + 1(r); + const PixelT* const img_row_fol = (PixelT *)(((char *)img_row) + img.step.p[0]); + LabelT* const imgLabels_row = imgLabels.ptr(r); + LabelT* const imgLabels_row_fol = (LabelT *)(((char *)imgLabels_row) + imgLabels.step.p[0]); + + for (int c = 0; c0) { + iLabel = P[iLabel]; + if (img_row[c] > 0){ + imgLabels_row[c] = iLabel; + sop(r, c, iLabel); + }else{ + imgLabels_row[c] = 0; + sop(r, c, 0); + } + if (img_row[c + 1] > 0){ + imgLabels_row[c + 1] = iLabel; + sop(r, c + 1, iLabel); + }else{ + imgLabels_row[c + 1] = 0; + sop(r, c + 1, 0); + } + if (img_row_fol[c] > 0){ + imgLabels_row_fol[c] = iLabel; + sop(r + 1, c, iLabel); + }else{ + imgLabels_row_fol[c] = 0; + sop(r + 1, c, 0); + } + if (img_row_fol[c + 1] > 0){ + imgLabels_row_fol[c + 1] = iLabel; + sop(r + 1, c + 1, iLabel); + }else{ + imgLabels_row_fol[c + 1] = 0; + sop(r + 1, c + 1, 0); + } + } + else { + imgLabels_row[c] = 0; + imgLabels_row[c + 1] = 0; + imgLabels_row_fol[c] = 0; + imgLabels_row_fol[c + 1] = 0; + sop(r, c, 0); + sop(r, c + 1, 0); + sop(r + 1, c, 0); + sop(r + 1, c + 1, 0); + } + } + } + }//END case 4 + } + + sop.finish(); + fastFree(P); + + return nLabels; + + } //End function LabelingGrana operator() + }; //End struct LabelingGrana }//end namespace connectedcomponents //L's type must have an appropriate depth for the number of pixels in I template static -int connectedComponents_sub1(const cv::Mat &I, cv::Mat &L, int connectivity, StatsOp &sop){ +int connectedComponents_sub1(const cv::Mat &I, cv::Mat &L, int connectivity, int ccltype, StatsOp &sop){ CV_Assert(L.channels() == 1 && I.channels() == 1); CV_Assert(connectivity == 8 || connectivity == 4); + CV_Assert(ccltype == CCL_GRANA || ccltype == CCL_WU || ccltype == CCL_DEFAULT); int lDepth = L.depth(); int iDepth = I.depth(); - using connectedcomponents::LabelingImpl; - //warn if L's depth is not sufficient? CV_Assert(iDepth == CV_8U || iDepth == CV_8S); - if(lDepth == CV_8U){ - return (int) LabelingImpl()(I, L, connectivity, sop); - }else if(lDepth == CV_16U){ - return (int) LabelingImpl()(I, L, connectivity, sop); - }else if(lDepth == CV_32S){ - //note that signed types don't really make sense here and not being able to use unsigned matters for scientific projects - //OpenCV: how should we proceed? .at typechecks in debug mode - return (int) LabelingImpl()(I, L, connectivity, sop); + if (ccltype == CCL_WU || connectivity == 4){ + // Wu algorithm is used + using connectedcomponents::LabelingWu; + //warn if L's depth is not sufficient? + if (lDepth == CV_8U){ + return (int)LabelingWu()(I, L, connectivity, sop); + } + else if (lDepth == CV_16U){ + return (int)LabelingWu()(I, L, connectivity, sop); + } + else if (lDepth == CV_32S){ + //note that signed types don't really make sense here and not being able to use unsigned matters for scientific projects + //OpenCV: how should we proceed? .at typechecks in debug mode + return (int)LabelingWu()(I, L, connectivity, sop); + } + }else if ((ccltype == CCL_GRANA || ccltype == CCL_DEFAULT) && connectivity == 8){ + // Grana algorithm is used + using connectedcomponents::LabelingGrana; + //warn if L's depth is not sufficient? + if (lDepth == CV_8U){ + return (int)LabelingGrana()(I, L, connectivity, sop); + } + else if (lDepth == CV_16U){ + return (int)LabelingGrana()(I, L, connectivity, sop); + } + else if (lDepth == CV_32S){ + //note that signed types don't really make sense here and not being able to use unsigned matters for scientific projects + //OpenCV: how should we proceed? .at typechecks in debug mode + return (int)LabelingGrana()(I, L, connectivity, sop); + } } CV_Error(CV_StsUnsupportedFormat, "unsupported label/image type"); @@ -364,33 +1701,49 @@ int connectedComponents_sub1(const cv::Mat &I, cv::Mat &L, int connectivity, Sta } +// Simple wrapper to ensure binary and source compatibility (ABI) int cv::connectedComponents(InputArray _img, OutputArray _labels, int connectivity, int ltype){ + return cv::connectedComponents(_img, _labels, connectivity, ltype, CCL_DEFAULT); +} + +int cv::connectedComponents(InputArray _img, OutputArray _labels, int connectivity, int ltype, int ccltype){ const cv::Mat img = _img.getMat(); _labels.create(img.size(), CV_MAT_DEPTH(ltype)); cv::Mat labels = _labels.getMat(); connectedcomponents::NoOp sop; - if(ltype == CV_16U){ - return connectedComponents_sub1(img, labels, connectivity, sop); - }else if(ltype == CV_32S){ - return connectedComponents_sub1(img, labels, connectivity, sop); - }else{ + if (ltype == CV_16U){ + return connectedComponents_sub1(img, labels, connectivity, ccltype, sop); + } + else if (ltype == CV_32S){ + return connectedComponents_sub1(img, labels, connectivity, ccltype, sop); + } + else{ CV_Error(CV_StsUnsupportedFormat, "the type of labels must be 16u or 32s"); return 0; } } +// Simple wrapper to ensure binary and source compatibility (ABI) int cv::connectedComponentsWithStats(InputArray _img, OutputArray _labels, OutputArray statsv, OutputArray centroids, int connectivity, int ltype) +{ + return cv::connectedComponentsWithStats(_img, _labels, statsv, centroids, connectivity, ltype, CCL_DEFAULT); +} + +int cv::connectedComponentsWithStats(InputArray _img, OutputArray _labels, OutputArray statsv, + OutputArray centroids, int connectivity, int ltype, int ccltype) { const cv::Mat img = _img.getMat(); _labels.create(img.size(), CV_MAT_DEPTH(ltype)); cv::Mat labels = _labels.getMat(); connectedcomponents::CCStatsOp sop(statsv, centroids); - if(ltype == CV_16U){ - return connectedComponents_sub1(img, labels, connectivity, sop); - }else if(ltype == CV_32S){ - return connectedComponents_sub1(img, labels, connectivity, sop); - }else{ + if (ltype == CV_16U){ + return connectedComponents_sub1(img, labels, connectivity, ccltype, sop); + } + else if (ltype == CV_32S){ + return connectedComponents_sub1(img, labels, connectivity, ccltype, sop); + } + else{ CV_Error(CV_StsUnsupportedFormat, "the type of labels must be 16u or 32s"); return 0; } diff --git a/modules/imgproc/src/distransform.cpp b/modules/imgproc/src/distransform.cpp index 070a649e63..36914d89d8 100644 --- a/modules/imgproc/src/distransform.cpp +++ b/modules/imgproc/src/distransform.cpp @@ -827,7 +827,7 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe if( labelType == CV_DIST_LABEL_CCOMP ) { Mat zpix = src == 0; - connectedComponents(zpix, labels, 8, CV_32S); + connectedComponents(zpix, labels, 8, CV_32S, CCL_WU); } else { diff --git a/modules/imgproc/test/test_connectedcomponents.cpp b/modules/imgproc/test/test_connectedcomponents.cpp index dd4d8339a0..d1c7b6a5fe 100644 --- a/modules/imgproc/test/test_connectedcomponents.cpp +++ b/modules/imgproc/test/test_connectedcomponents.cpp @@ -42,6 +42,7 @@ #include "test_precomp.hpp" #include +#include using namespace cv; using namespace std; @@ -58,49 +59,81 @@ protected: CV_ConnectedComponentsTest::CV_ConnectedComponentsTest() {} CV_ConnectedComponentsTest::~CV_ConnectedComponentsTest() {} +// This function force a row major order for the labels +void normalizeLabels(Mat1i& imgLabels, int iNumLabels) { + vector vecNewLabels(iNumLabels + 1, 0); + int iMaxNewLabel = 0; + + for (int r = 0; r0) { + if (vecNewLabels[iCurLabel] == 0) { + vecNewLabels[iCurLabel] = ++iMaxNewLabel; + } + imgLabels(r, c) = vecNewLabels[iCurLabel]; + } + } + } +} + + void CV_ConnectedComponentsTest::run( int /* start_from */) { + + int ccltype[] = { cv::CCL_WU, cv::CCL_DEFAULT, cv::CCL_GRANA }; + string exp_path = string(ts->get_data_path()) + "connectedcomponents/ccomp_exp.png"; Mat exp = imread(exp_path, 0); Mat orig = imread(string(ts->get_data_path()) + "connectedcomponents/concentric_circles.png", 0); if (orig.empty()) { - ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA ); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); return; } Mat bw = orig > 128; - Mat labelImage; - int nLabels = connectedComponents(bw, labelImage, 8, CV_32S); - for(int r = 0; r < labelImage.rows; ++r){ - for(int c = 0; c < labelImage.cols; ++c){ - int l = labelImage.at(r, c); - bool pass = l >= 0 && l <= nLabels; - if(!pass){ - ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); - return; + for (uint cclt = 0; cclt < sizeof(ccltype)/sizeof(int); ++cclt) + { + + Mat1i labelImage; + int nLabels = connectedComponents(bw, labelImage, 8, CV_32S, ccltype[cclt]); + + normalizeLabels(labelImage, nLabels); + + // Validate test results + for (int r = 0; r < labelImage.rows; ++r){ + for (int c = 0; c < labelImage.cols; ++c){ + int l = labelImage.at(r, c); + bool pass = l >= 0 && l <= nLabels; + if (!pass){ + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } } } + + if (exp.empty() || orig.size() != exp.size()) + { + imwrite(exp_path, labelImage); + exp = labelImage; + } + + if (0 != cvtest::norm(labelImage > 0, exp > 0, NORM_INF)) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); + return; + } + if (nLabels != cvtest::norm(labelImage, NORM_INF) + 1) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); + return; + } + } - if( exp.empty() || orig.size() != exp.size() ) - { - imwrite(exp_path, labelImage); - exp = labelImage; - } - - if (0 != cvtest::norm(labelImage > 0, exp > 0, NORM_INF)) - { - ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH ); - return; - } - if (nLabels != cvtest::norm(labelImage, NORM_INF)+1) - { - ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH ); - return; - } ts->set_failed_test_info(cvtest::TS::OK); } From 40b870704edf3c89288a5cc7d81507e1103684c9 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Fri, 26 Aug 2016 16:25:46 +0400 Subject: [PATCH 098/178] add 2 extra methods to ml::TrainData (#7169) * expose 2 extra methods from ml::TrainData: getNames() and getVarSymbolFlags(). The first one returns text labels from CSV (if the data has been loaded from CSV); the second one returns a matrix of boolean values; its n-th element is 1 iff the corresponding column in the CSV uses symbolic names, not numbers. * check that the dynamic_cast succeeds --- modules/ml/include/opencv2/ml.hpp | 4 ++++ modules/ml/src/data.cpp | 40 ++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/modules/ml/include/opencv2/ml.hpp b/modules/ml/include/opencv2/ml.hpp index d016810874..ea9c89e4e6 100644 --- a/modules/ml/include/opencv2/ml.hpp +++ b/modules/ml/include/opencv2/ml.hpp @@ -190,6 +190,7 @@ public: CV_WRAP virtual Mat getTestSampleWeights() const = 0; CV_WRAP virtual Mat getVarIdx() const = 0; CV_WRAP virtual Mat getVarType() const = 0; + CV_WRAP Mat getVarSymbolFlags() const; CV_WRAP virtual int getResponseType() const = 0; CV_WRAP virtual Mat getTrainSampleIdx() const = 0; CV_WRAP virtual Mat getTestSampleIdx() const = 0; @@ -227,6 +228,9 @@ public: /** @brief Returns matrix of test samples */ CV_WRAP Mat getTestSamples() const; + /** @brief Returns vector of symbolic names captured in loadFromCSV() */ + CV_WRAP void getNames(std::vector& names) const; + CV_WRAP static Mat getSubVector(const Mat& vec, const Mat& idx); /** @brief Reads the dataset from a .csv file and returns the ready-to-use training data. diff --git a/modules/ml/src/data.cpp b/modules/ml/src/data.cpp index 465163c927..5e1b6d2340 100644 --- a/modules/ml/src/data.cpp +++ b/modules/ml/src/data.cpp @@ -220,6 +220,7 @@ public: samples.release(); missing.release(); varType.release(); + varSymbolFlags.release(); responses.release(); sampleIdx.release(); trainSampleIdx.release(); @@ -522,6 +523,7 @@ public: std::vector allresponses; std::vector rowvals; std::vector vtypes, rowtypes; + std::vector vsymbolflags; bool haveMissed = false; char* buf = &_buf[0]; @@ -583,6 +585,9 @@ public: } else vtypes = rowtypes; + vsymbolflags.resize(nvars); + for( i = 0; i < nvars; i++ ) + vsymbolflags[i] = (uchar)(rowtypes[i] == VAR_CATEGORICAL); ridx0 = ridx0 >= 0 ? ridx0 : ridx0 == -1 ? nvars - 1 : -1; ridx1 = ridx1 >= 0 ? ridx1 : ridx0 >= 0 ? ridx0+1 : -1; @@ -598,6 +603,11 @@ public: { CV_Assert( (!varTypesSet && vtypes[i] == rowtypes[i]) || (varTypesSet && (vtypes[i] == rowtypes[i] || rowtypes[i] == VAR_ORDERED)) ); + uchar sflag = (uchar)(rowtypes[i] == VAR_CATEGORICAL); + if( vsymbolflags[i] == VAR_MISSED ) + vsymbolflags[i] = sflag; + else + CV_Assert(vsymbolflags[i] == sflag || rowtypes[i] == VAR_MISSED); } if( ridx0 >= 0 ) @@ -657,7 +667,10 @@ public: } bool ok = !samples.empty(); if(ok) + { std::swap(tempNameMap, nameMap); + Mat(vsymbolflags).copyTo(varSymbolFlags); + } return ok; } @@ -976,13 +989,38 @@ public: FILE* file; int layout; - Mat samples, missing, varType, varIdx, responses, missingSubst; + Mat samples, missing, varType, varIdx, varSymbolFlags, responses, missingSubst; Mat sampleIdx, trainSampleIdx, testSampleIdx; Mat sampleWeights, catMap, catOfs; Mat normCatResponses, classLabels, classCounters; MapType nameMap; }; +void TrainData::getNames(std::vector& names) const +{ + const TrainDataImpl* impl = dynamic_cast(this); + CV_Assert(impl != 0); + size_t n = impl->nameMap.size(); + TrainDataImpl::MapType::const_iterator it = impl->nameMap.begin(), + it_end = impl->nameMap.end(); + names.resize(n+1); + names[0] = "?"; + for( ; it != it_end; ++it ) + { + String s = it->first; + int label = it->second; + CV_Assert( label > 0 && label <= (int)n ); + names[label] = s; + } +} + +Mat TrainData::getVarSymbolFlags() const +{ + const TrainDataImpl* impl = dynamic_cast(this); + CV_Assert(impl != 0); + return impl->varSymbolFlags; +} + Ptr TrainData::loadFromCSV(const String& filename, int headerLines, int responseStartIdx, From a88bf4e5aa5452992cf2922aa91728d111139bdb Mon Sep 17 00:00:00 2001 From: mrquorr Date: Fri, 12 Aug 2016 00:14:01 -0500 Subject: [PATCH 099/178] test added, only if HAVE_GDCM is on --- modules/imgcodecs/test/test_grfmt.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/imgcodecs/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp index f305ca137a..d4f1d74a34 100644 --- a/modules/imgcodecs/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -92,6 +92,12 @@ TEST(Imgcodecs_imread, regression) { #ifdef HAVE_JASPER "Rome.jp2", +#endif +#ifdef HAVE_GDCM + "int16-mono1.dcm", + "uint8-mono2.dcm", + "uint16-mono2.dcm", + "uint8-rgb.dcm", #endif "color_palette_alpha.png", "multipage.tif", @@ -111,9 +117,10 @@ TEST(Imgcodecs_imread, regression) ASSERT_TRUE(imread_compare(path, IMREAD_COLOR)); ASSERT_TRUE(imread_compare(path, IMREAD_ANYDEPTH)); ASSERT_TRUE(imread_compare(path, IMREAD_ANYCOLOR)); - if (path.substr(path.length() - 3) != "hdr") + const string ext = path.substr( path.length() - 3 ); + if ( ext != "hdr" && ext != "dcm" ) { - // GDAL does not support hdr + // GDAL does not support hdr nor dcm ASSERT_TRUE(imread_compare(path, IMREAD_LOAD_GDAL)); } } From ec5ae4af1d5b13833ce9e28fb7ed4f1814557e43 Mon Sep 17 00:00:00 2001 From: Asal Mirzaieva Date: Fri, 19 Aug 2016 13:48:56 +0300 Subject: [PATCH 100/178] add explanation to the Bounding Box and Circles tutorial - also some minor changes to the respective sample cpp file --- .../bounding_rects_circles.markdown | 43 +++++++++++++++ .../generalContours_demo1.cpp | 54 ++++++++++++++----- 2 files changed, 83 insertions(+), 14 deletions(-) diff --git a/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.markdown b/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.markdown index fef66fb665..56d886d89f 100644 --- a/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.markdown +++ b/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.markdown @@ -22,6 +22,49 @@ This tutorial code's is shown lines below. You can also download it from Explanation ----------- +The main function is rather simple, as follows from the comments we do the following: +-# Open the image, convert it into grayscale and blur it to get rid of the noise. + @snippet samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp setup +-# Create a window with header "Source" and display the source file in it. + @snippet samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp createWindow +-# Create a trackbar on the source_window and assign a callback function to it + In general callback functions are used to react to some kind of signal, in our + case it's trackbar's state change. + @snippet samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp taskbar +-# Explicit one-time call of `thresh_callback` is necessary to display + the "Contours" window simultaniously with the "Source" window. + @snippet samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp callback00 +-# Wait for user to close the windows. + @snippet samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp waitForIt + + +The callback function `thresh_callback` does all the interesting job. + + +-# Writes to `threshold_output` the threshold of the grayscale picture (you can check out about thresholding @ref tutorial_threshold "here"). + @snippet samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp threshold +-# Finds contours and saves them to the vectors `contour` and `hierarchy`. + @snippet samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp findContours +-# For every found contour we now apply approximation to polygons + with accuracy +-3 and stating that the curve must me closed. + + After that we find a bounding rect for every polygon and save it to `boundRect`. + + At last we find a minimum enclosing circle for every polygon and + save it to `center` and `radius` vectors. + @snippet samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp allthework + +We found everything we need, all we have to do is to draw. + +-# Create new Mat of unsigned 8-bit chars, filled with zeros. + It will contain all the drawings we are going to make (rects and circles). + @snippet samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp zeroMat +-# For every contour: pick a random color, draw the contour, the bounding rectangle and + the minimal enclosing circle with it, + @snippet samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp forContour +-# Display the results: create a new window "Contours" and show everything we added to drawings on it. + @snippet samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp showDrawings + Result ------ diff --git a/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp b/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp index 29d75515cf..1e5585aa5f 100644 --- a/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp +++ b/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp @@ -25,22 +25,34 @@ void thresh_callback(int, void* ); */ int main( int, char** argv ) { - /// Load source image and convert it to gray + //![setup] + /// Load source image src = imread( argv[1], IMREAD_COLOR ); /// Convert image to gray and blur it cvtColor( src, src_gray, COLOR_BGR2GRAY ); blur( src_gray, src_gray, Size(3,3) ); + //![setup] + //![createWindow] /// Create Window const char* source_window = "Source"; namedWindow( source_window, WINDOW_AUTOSIZE ); imshow( source_window, src ); + //![createWindow] + //![taskbar] createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback ); - thresh_callback( 0, 0 ); + //![taskbar] + //![callback00] + thresh_callback( 0, 0 ); + //![callback00] + + //![waitForIt] waitKey(0); + //![waitForIt] + return(0); } @@ -53,10 +65,15 @@ void thresh_callback(int, void* ) vector > contours; vector hierarchy; + //![threshold] /// Detect edges using Threshold threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY ); + //![threshold] + + //![findContours] /// Find contours findContours( threshold_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) ); + //![findContours] /// Approximate contours to polygons + get bounding rects and circles vector > contours_poly( contours.size() ); @@ -64,24 +81,33 @@ void thresh_callback(int, void* ) vectorcenter( contours.size() ); vectorradius( contours.size() ); + //![allthework] for( size_t i = 0; i < contours.size(); i++ ) - { approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true ); - boundRect[i] = boundingRect( Mat(contours_poly[i]) ); - minEnclosingCircle( contours_poly[i], center[i], radius[i] ); - } - + { + approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true ); + boundRect[i] = boundingRect( Mat(contours_poly[i]) ); + minEnclosingCircle( contours_poly[i], center[i], radius[i] ); + } + //![allthework] + //![zeroMat] /// Draw polygonal contour + bonding rects + circles Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 ); - for( size_t i = 0; i< contours.size(); i++ ) - { - Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) ); - drawContours( drawing, contours_poly, (int)i, color, 1, 8, vector(), 0, Point() ); - rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 ); - circle( drawing, center[i], (int)radius[i], color, 2, 8, 0 ); - } + //![zeroMat] + //![forContour] + for( size_t i = 0; i< contours.size(); i++ ) + { + Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) ); + drawContours( drawing, contours_poly, (int)i, color, 1, 8, vector(), 0, Point() ); + rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 ); + circle( drawing, center[i], (int)radius[i], color, 2, 8, 0 ); + } + //![forContour] + + //![showDrawings] /// Show in a window namedWindow( "Contours", WINDOW_AUTOSIZE ); imshow( "Contours", drawing ); + //![showDrawings] } From 69c7eea69463b4e4aa5f4426480791ef14193753 Mon Sep 17 00:00:00 2001 From: Valeriy Van Date: Sat, 27 Aug 2016 01:10:17 +0300 Subject: [PATCH 101/178] Cleans up ios stuff declaration removing not needed ivars backing properties --- .../videoio/include/opencv2/videoio/cap_ios.h | 26 ------------------- modules/videoio/src/cap_ios_video_camera.mm | 4 +-- 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/modules/videoio/include/opencv2/videoio/cap_ios.h b/modules/videoio/include/opencv2/videoio/cap_ios.h index 9075fe1c80..4df9c51755 100644 --- a/modules/videoio/include/opencv2/videoio/cap_ios.h +++ b/modules/videoio/include/opencv2/videoio/cap_ios.h @@ -41,27 +41,9 @@ @interface CvAbstractCamera : NSObject { - AVCaptureSession* captureSession; - AVCaptureConnection* videoCaptureConnection; - AVCaptureVideoPreviewLayer *captureVideoPreviewLayer; - UIDeviceOrientation currentDeviceOrientation; BOOL cameraAvailable; - BOOL captureSessionLoaded; - BOOL running; - BOOL useAVCaptureVideoPreviewLayer; - - AVCaptureDevicePosition defaultAVCaptureDevicePosition; - AVCaptureVideoOrientation defaultAVCaptureVideoOrientation; - NSString *const defaultAVCaptureSessionPreset; - - int defaultFPS; - - UIView* parentView; - - int imageWidth; - int imageHeight; } @property (nonatomic, strong) AVCaptureSession* captureSession; @@ -121,14 +103,6 @@ dispatch_queue_t videoDataOutputQueue; CALayer *customPreviewLayer; - BOOL grayscaleMode; - - BOOL recordVideo; - BOOL rotateVideo; - AVAssetWriterInput* recordAssetWriterInput; - AVAssetWriterInputPixelBufferAdaptor* recordPixelBufferAdaptor; - AVAssetWriter* recordAssetWriter; - CMTime lastSampleTime; } diff --git a/modules/videoio/src/cap_ios_video_camera.mm b/modules/videoio/src/cap_ios_video_camera.mm index c1a0b4d774..a8cb7a6926 100644 --- a/modules/videoio/src/cap_ios_video_camera.mm +++ b/modules/videoio/src/cap_ios_video_camera.mm @@ -183,7 +183,7 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} break; // leave the layer in its last known orientation } - switch (defaultAVCaptureVideoOrientation) { + switch (self.defaultAVCaptureVideoOrientation) { case AVCaptureVideoOrientationLandscapeRight: rotation_angle += 180; break; @@ -249,7 +249,7 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} break; // leave the layer in its last known orientation } - switch (defaultAVCaptureVideoOrientation) { + switch (self.defaultAVCaptureVideoOrientation) { case AVCaptureVideoOrientationLandscapeRight: rotation_angle += 180; break; From 9678d48e1aacfb57d4efcdad30401ba5b6b24185 Mon Sep 17 00:00:00 2001 From: Matthew Self Date: Wed, 17 Aug 2016 00:17:45 -0700 Subject: [PATCH 102/178] 2-channel interleaved load/store for universal intrinsics (float only) * Added 2-channel ops to match existing 3-channel and 4-channel ops * v_load_deinterleave() and v_store_interleave() * Implements float32x4 only on SSE (but all types on NEON and CPP) * Includes tests * Will be used to vectorize 2D functions, such as estimateAffine2D() --- .../include/opencv2/core/hal/intrin_cpp.hpp | 55 ++++++++++++++++--- .../include/opencv2/core/hal/intrin_neon.hpp | 13 +++++ .../include/opencv2/core/hal/intrin_sse.hpp | 24 ++++++++ modules/core/test/test_intrin.cpp | 27 +++++++++ 4 files changed, 111 insertions(+), 8 deletions(-) diff --git a/modules/core/include/opencv2/core/hal/intrin_cpp.hpp b/modules/core/include/opencv2/core/hal/intrin_cpp.hpp index 04b1d928b2..97ea5ea0b6 100644 --- a/modules/core/include/opencv2/core/hal/intrin_cpp.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_cpp.hpp @@ -103,7 +103,7 @@ block and to save contents of the register to memory block. These operations allow to reorder or recombine elements in one or multiple vectors. -- Interleave, deinterleave (3 and 4 channels): @ref v_load_deinterleave, @ref v_store_interleave +- Interleave, deinterleave (2, 3 and 4 channels): @ref v_load_deinterleave, @ref v_store_interleave - Expand: @ref v_load_expand, @ref v_load_expand_q, @ref v_expand - Pack: @ref v_pack, @ref v_pack_u, @ref v_rshr_pack, @ref v_rshr_pack_u, @ref v_pack_store, @ref v_pack_u_store, @ref v_rshr_pack_store, @ref v_rshr_pack_u_store @@ -1075,12 +1075,31 @@ v_load_expand_q(const _Tp* ptr) return c; } -/** @brief Load and deinterleave (4 channels) +/** @brief Load and deinterleave (2 channels) -Load data from memory deinterleave and store to 4 registers. +Load data from memory deinterleave and store to 2 registers. Scheme: @code -{A1 B1 C1 D1 A2 B2 C2 D2 ...} ==> {A1 A2 ...}, {B1 B2 ...}, {C1 C2 ...}, {D1 D2 ...} +{A1 B1 A2 B2 ...} ==> {A1 A2 ...}, {B1 B2 ...} +@endcode +For all types except 64-bit. */ +template inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a, + v_reg<_Tp, n>& b) +{ + int i, i2; + for( i = i2 = 0; i < n; i++, i2 += 2 ) + { + a.s[i] = ptr[i2]; + b.s[i] = ptr[i2+1]; + } +} + +/** @brief Load and deinterleave (3 channels) + +Load data from memory deinterleave and store to 3 registers. +Scheme: +@code +{A1 B1 C1 A2 B2 C2 ...} ==> {A1 A2 ...}, {B1 B2 ...}, {C1 C2 ...} @endcode For all types except 64-bit. */ template inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a, @@ -1095,12 +1114,12 @@ template inline void v_load_deinterleave(const _Tp* ptr, v_ } } -/** @brief Load and deinterleave (3 channels) +/** @brief Load and deinterleave (4 channels) -Load data from memory deinterleave and store to 3 registers. +Load data from memory deinterleave and store to 4 registers. Scheme: @code -{A1 B1 C1 A2 B2 C2 ...} ==> {A1 A2 ...}, {B1 B2 ...}, {C1 C2 ...} +{A1 B1 C1 D1 A2 B2 C2 D2 ...} ==> {A1 A2 ...}, {B1 B2 ...}, {C1 C2 ...}, {D1 D2 ...} @endcode For all types except 64-bit. */ template @@ -1118,12 +1137,32 @@ inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a, } } +/** @brief Interleave and store (2 channels) + +Interleave and store data from 2 registers to memory. +Scheme: +@code +{A1 A2 ...}, {B1 B2 ...} ==> {A1 B1 A2 B2 ...} +@endcode +For all types except 64-bit. */ +template +inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a, + const v_reg<_Tp, n>& b) +{ + int i, i2; + for( i = i2 = 0; i < n; i++, i2 += 2 ) + { + ptr[i2] = a.s[i]; + ptr[i2+1] = b.s[i]; + } +} + /** @brief Interleave and store (3 channels) Interleave and store data from 3 registers to memory. Scheme: @code -{A1 A2 ...}, {B1 B2 ...}, {C1 C2 ...}, {D1 D2 ...} ==> {A1 B1 C1 D1 A2 B2 C2 D2 ...} +{A1 A2 ...}, {B1 B2 ...}, {C1 C2 ...} ==> {A1 B1 C1 A2 B2 C2 ...} @endcode For all types except 64-bit. */ template diff --git a/modules/core/include/opencv2/core/hal/intrin_neon.hpp b/modules/core/include/opencv2/core/hal/intrin_neon.hpp index f3e47ca8ba..dbfd6bda2b 100644 --- a/modules/core/include/opencv2/core/hal/intrin_neon.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_neon.hpp @@ -809,6 +809,12 @@ OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(int32x4, s32) OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(float32x4, f32) #define OPENCV_HAL_IMPL_NEON_INTERLEAVED(_Tpvec, _Tp, suffix) \ +inline void v_load_deinterleave(const _Tp* ptr, v_##_Tpvec& a, v_##_Tpvec& b) \ +{ \ + _Tpvec##x2_t v = vld2q_##suffix(ptr); \ + a.val = v.val[0]; \ + b.val = v.val[1]; \ +} \ inline void v_load_deinterleave(const _Tp* ptr, v_##_Tpvec& a, v_##_Tpvec& b, v_##_Tpvec& c) \ { \ _Tpvec##x3_t v = vld3q_##suffix(ptr); \ @@ -825,6 +831,13 @@ inline void v_load_deinterleave(const _Tp* ptr, v_##_Tpvec& a, v_##_Tpvec& b, \ c.val = v.val[2]; \ d.val = v.val[3]; \ } \ +inline void v_store_interleave( _Tp* ptr, const v_##_Tpvec& a, const v_##_Tpvec& b) \ +{ \ + _Tpvec##x2_t v; \ + v.val[0] = a.val; \ + v.val[1] = b.val; \ + vst2q_##suffix(ptr, v); \ +} \ inline void v_store_interleave( _Tp* ptr, const v_##_Tpvec& a, const v_##_Tpvec& b, const v_##_Tpvec& c) \ { \ _Tpvec##x3_t v; \ diff --git a/modules/core/include/opencv2/core/hal/intrin_sse.hpp b/modules/core/include/opencv2/core/hal/intrin_sse.hpp index 1840e0305d..1a9f58e263 100644 --- a/modules/core/include/opencv2/core/hal/intrin_sse.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_sse.hpp @@ -1374,6 +1374,18 @@ inline void v_load_deinterleave(const unsigned* ptr, v_uint32x4& a, v_uint32x4& v_transpose4x4(u0, u1, u2, u3, a, b, c, d); } +// 2-channel, float only +inline void v_load_deinterleave(const float* ptr, v_float32x4& a, v_float32x4& b) +{ + const int mask_lo = _MM_SHUFFLE(2, 0, 2, 0), mask_hi = _MM_SHUFFLE(3, 1, 3, 1); + + __m128 u0 = _mm_loadu_ps(ptr); // a0 b0 a1 b1 + __m128 u1 = _mm_loadu_ps((ptr + 4)); // a2 b2 a3 b3 + + a.val = _mm_shuffle_ps(u0, u1, mask_lo); // a0 a1 a2 a3 + b.val = _mm_shuffle_ps(u0, u1, mask_hi); // b0 b1 ab b3 +} + inline void v_store_interleave( uchar* ptr, const v_uint8x16& a, const v_uint8x16& b, const v_uint8x16& c ) { @@ -1529,6 +1541,18 @@ inline void v_store_interleave(unsigned* ptr, const v_uint32x4& a, const v_uint3 v_store(ptr + 12, t3); } +// 2-channel, float only +inline void v_store_interleave(float* ptr, const v_float32x4& a, const v_float32x4& b) +{ + // a0 a1 a2 a3 ... + // b0 b1 b2 b3 ... + __m128 u0 = _mm_unpacklo_ps(a.val, b.val); // a0 b0 a1 b1 + __m128 u1 = _mm_unpackhi_ps(a.val, b.val); // a2 b2 a3 b3 + + _mm_storeu_ps(ptr, u0); + _mm_storeu_ps((ptr + 4), u1); +} + #define OPENCV_HAL_IMPL_SSE_LOADSTORE_INTERLEAVE(_Tpvec, _Tp, suffix, _Tpuvec, _Tpu, usuffix) \ inline void v_load_deinterleave( const _Tp* ptr, _Tpvec& a0, \ _Tpvec& b0, _Tpvec& c0 ) \ diff --git a/modules/core/test/test_intrin.cpp b/modules/core/test/test_intrin.cpp index ca9d3dc7b7..6b6817c690 100644 --- a/modules/core/test/test_intrin.cpp +++ b/modules/core/test/test_intrin.cpp @@ -132,6 +132,32 @@ template struct TheTest return *this; } + // float32x4 only + TheTest & test_interleave_2channel() + { + Data data1, data2; + data2 += 20; + + R a = data1, b = data2; + + LaneType buf2[R::nlanes * 2]; + + v_store_interleave(buf2, a, b); + + Data z(0); + a = b = z; + + v_load_deinterleave(buf2, a, b); + + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(data1, Data(a)); + EXPECT_EQ(data2, Data(b)); + } + + return *this; + } + // v_expand and v_load_expand TheTest & test_expand() { @@ -846,6 +872,7 @@ TEST(hal_intrin, float32x4) { TheTest() .test_loadstore() .test_interleave() + .test_interleave_2channel() .test_addsub() .test_mul() .test_div() From 7de2e1e7957075ebbd504b2c9aea256e61b2d547 Mon Sep 17 00:00:00 2001 From: Matthew Self Date: Fri, 26 Aug 2016 20:39:38 -0700 Subject: [PATCH 103/178] Improve perfomance of median calculation in LMedS algorithm * Use `nth_element()` to find the median instead of `sort()` in `LMeDSPointSetRegistrator::run()` * Improves performance of this part of LMedS from `n log(n)` to `n` by avoiding doing a full sort. * Makes LMedS 2x faster for 100 points, 4x faster for 5,000 points in `EstimateAffine2D()`. * LMedS is now never more than 2x slower than RANSAC and is faster in some cases. --- modules/calib3d/src/ptsetreg.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/calib3d/src/ptsetreg.cpp b/modules/calib3d/src/ptsetreg.cpp index 830fa8ae1a..5e652d4fd5 100644 --- a/modules/calib3d/src/ptsetreg.cpp +++ b/modules/calib3d/src/ptsetreg.cpp @@ -344,10 +344,8 @@ public: else errf = err; CV_Assert( errf.isContinuous() && errf.type() == CV_32F && (int)errf.total() == count ); - std::sort(errf.ptr(), errf.ptr() + count); - - double median = count % 2 != 0 ? - errf.at(count/2) : (errf.at(count/2-1) + errf.at(count/2))*0.5; + std::nth_element(errf.ptr(), errf.ptr() + count/2, errf.ptr() + count); + double median = errf.at(count/2); if( median < minMedian ) { From 31e790da33765a4ba86ae79726f9a3cb56b1ff9e Mon Sep 17 00:00:00 2001 From: Valeriy Van Date: Sun, 28 Aug 2016 12:29:58 +0300 Subject: [PATCH 104/178] Fixes spelling in NSLog --- modules/videoio/src/cap_ios_abstract_camera.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/videoio/src/cap_ios_abstract_camera.mm b/modules/videoio/src/cap_ios_abstract_camera.mm index 5c870a7604..702b1f2107 100644 --- a/modules/videoio/src/cap_ios_abstract_camera.mm +++ b/modules/videoio/src/cap_ios_abstract_camera.mm @@ -333,7 +333,7 @@ device.focusMode = AVCaptureFocusModeContinuousAutoFocus; [device unlockForConfiguration]; } else { - NSLog(@"unable to lock device for autofocos configuration %@", [error localizedDescription]); + NSLog(@"unable to lock device for autofocus configuration %@", [error localizedDescription]); } } [self.captureSession addInput:input]; From 517be4bfa96277a89fea4b2fbf8b46c457833639 Mon Sep 17 00:00:00 2001 From: Valeriy Van Date: Sun, 28 Aug 2016 12:34:50 +0300 Subject: [PATCH 105/178] Changes [error localizedDescription] for [error description] in NSLog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no sense to log error messages in user’s locale. Imagine you’re trying to guess what's going on decrypting logs in hebrew, arabic, slavic. localizedDescription is for end user messages, not for logs. --- modules/videoio/src/cap_ios_abstract_camera.mm | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/videoio/src/cap_ios_abstract_camera.mm b/modules/videoio/src/cap_ios_abstract_camera.mm index 702b1f2107..425032c6e0 100644 --- a/modules/videoio/src/cap_ios_abstract_camera.mm +++ b/modules/videoio/src/cap_ios_abstract_camera.mm @@ -323,7 +323,7 @@ NSError* error = nil; AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error]; if (!input) { - NSLog(@"error creating input %@", [error localizedDescription]); + NSLog(@"error creating input %@", [error description]); } // support for autofocus @@ -333,7 +333,7 @@ device.focusMode = AVCaptureFocusModeContinuousAutoFocus; [device unlockForConfiguration]; } else { - NSLog(@"unable to lock device for autofocus configuration %@", [error localizedDescription]); + NSLog(@"unable to lock device for autofocus configuration %@", [error description]); } } [self.captureSession addInput:input]; @@ -436,7 +436,7 @@ device.focusMode = AVCaptureFocusModeLocked; [device unlockForConfiguration]; } else { - NSLog(@"unable to lock device for locked focus configuration %@", [error localizedDescription]); + NSLog(@"unable to lock device for locked focus configuration %@", [error description]); } } } @@ -450,7 +450,7 @@ device.focusMode = AVCaptureFocusModeContinuousAutoFocus; [device unlockForConfiguration]; } else { - NSLog(@"unable to lock device for autofocus configuration %@", [error localizedDescription]); + NSLog(@"unable to lock device for autofocus configuration %@", [error description]); } } } @@ -464,7 +464,7 @@ device.exposureMode = AVCaptureExposureModeLocked; [device unlockForConfiguration]; } else { - NSLog(@"unable to lock device for locked exposure configuration %@", [error localizedDescription]); + NSLog(@"unable to lock device for locked exposure configuration %@", [error description]); } } } @@ -478,7 +478,7 @@ device.exposureMode = AVCaptureExposureModeContinuousAutoExposure; [device unlockForConfiguration]; } else { - NSLog(@"unable to lock device for autoexposure configuration %@", [error localizedDescription]); + NSLog(@"unable to lock device for autoexposure configuration %@", [error description]); } } } @@ -492,7 +492,7 @@ device.whiteBalanceMode = AVCaptureWhiteBalanceModeLocked; [device unlockForConfiguration]; } else { - NSLog(@"unable to lock device for locked white balance configuration %@", [error localizedDescription]); + NSLog(@"unable to lock device for locked white balance configuration %@", [error description]); } } } @@ -506,7 +506,7 @@ device.whiteBalanceMode = AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance; [device unlockForConfiguration]; } else { - NSLog(@"unable to lock device for auto white balance configuration %@", [error localizedDescription]); + NSLog(@"unable to lock device for auto white balance configuration %@", [error description]); } } } From 5a71bde79aecccb4eb4f7bb77f377d9f14f53f9c Mon Sep 17 00:00:00 2001 From: Valeriy Van Date: Sun, 28 Aug 2016 12:48:08 +0300 Subject: [PATCH 106/178] Changes existential NSStringFromSelector(_cmd) for straightforward __FUCNTION__ --- modules/videoio/src/cap_ios_abstract_camera.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/videoio/src/cap_ios_abstract_camera.mm b/modules/videoio/src/cap_ios_abstract_camera.mm index 425032c6e0..79e0c3d7a9 100644 --- a/modules/videoio/src/cap_ios_abstract_camera.mm +++ b/modules/videoio/src/cap_ios_abstract_camera.mm @@ -379,13 +379,13 @@ - (void)createCaptureOutput; { [NSException raise:NSInternalInconsistencyException - format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]; + format:@"You must override %s in a subclass", __FUNCTION__]; } - (void)createCustomVideoPreview; { [NSException raise:NSInternalInconsistencyException - format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]; + format:@"You must override %s in a subclass", __FUNCTION__]; } - (void)updateOrientation; From 6825375694be46933aed68dfe7e196fed26d9772 Mon Sep 17 00:00:00 2001 From: anirudt Date: Mon, 29 Aug 2016 20:22:08 +0530 Subject: [PATCH 107/178] docs: adds note for python in docs related to moments --- modules/imgproc/include/opencv2/imgproc.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 71c4f48d12..ad71d8b8ee 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -3570,6 +3570,8 @@ results are returned in the structure cv::Moments. @param array Raster image (single-channel, 8-bit or floating-point 2D array) or an array ( \f$1 \times N\f$ or \f$N \times 1\f$ ) of 2D points (Point or Point2f ). +Note: For Python users, note that the numpy type for the input array should be either np.int32 or +np.float32, or in general of type CV_32S or CV_32F. @param binaryImage If it is true, all non-zero image pixels are treated as 1's. The parameter is used for images only. @returns moments. From acb62692e4477c8999fb44cbad838cd307dfe577 Mon Sep 17 00:00:00 2001 From: Valeriy Van Date: Mon, 29 Aug 2016 21:55:59 +0300 Subject: [PATCH 108/178] Cleans up declarations in window_cocoa.mm removing unnecessary iVars declarations and changing retain property attribute to strong --- modules/highgui/src/window_cocoa.mm | 30 +++++++---------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/modules/highgui/src/window_cocoa.mm b/modules/highgui/src/window_cocoa.mm index a653cd355c..a1befc3352 100644 --- a/modules/highgui/src/window_cocoa.mm +++ b/modules/highgui/src/window_cocoa.mm @@ -82,42 +82,26 @@ static NSAutoreleasePool *pool = nil; static NSMutableDictionary *windows = nil; static bool wasInitialized = false; -@interface CVView : NSView { - NSImage *image; -} -@property(retain) NSImage *image; +@interface CVView : NSView +@property(strong) NSImage *image; - (void)setImageData:(CvArr *)arr; @end -@interface CVSlider : NSView { - NSSlider *slider; - NSTextField *name; - int *value; - void *userData; - CvTrackbarCallback callback; - CvTrackbarCallback2 callback2; -} -@property(retain) NSSlider *slider; -@property(retain) NSTextField *name; +@interface CVSlider : NSView +@property(strong) NSSlider *slider; +@property(strong) NSTextField *name; @property(assign) int *value; @property(assign) void *userData; @property(assign) CvTrackbarCallback callback; @property(assign) CvTrackbarCallback2 callback2; @end -@interface CVWindow : NSWindow { - NSMutableDictionary *sliders; - CvMouseCallback mouseCallback; - void *mouseParam; - BOOL autosize; - BOOL firstContent; - int status; -} +@interface CVWindow : NSWindow @property(assign) CvMouseCallback mouseCallback; @property(assign) void *mouseParam; @property(assign) BOOL autosize; @property(assign) BOOL firstContent; -@property(retain) NSMutableDictionary *sliders; +@property(strong) NSMutableDictionary *sliders; @property(readwrite) int status; - (CVView *)contentView; - (void)cvSendMouseEvent:(NSEvent *)event type:(int)type flags:(int)flags; From 7fef96be1ef16f3420b8fe2909e2896129a18ecb Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Tue, 30 Aug 2016 17:21:02 +0900 Subject: [PATCH 109/178] add 64F intrinsic in HAL NEON * use universal intrinsic for accumulate series using float/double * accumulate, accumulateSquare, accumulateProduct and accumulateWeighted * add v_cvt_f64_high in both SSE/NEON * add test for conversion v_cvt_f64_high in test_intrin.cpp * improve some existing universal intrinsic by using new instructions in Aarch64 * add workaround for Android build in intrin_neon.hpp --- .../include/opencv2/core/hal/intrin_neon.hpp | 282 +++++++- .../include/opencv2/core/hal/intrin_sse.hpp | 10 + modules/core/test/test_intrin.cpp | 6 + modules/imgproc/src/accum.cpp | 636 +++++++++--------- 4 files changed, 614 insertions(+), 320 deletions(-) diff --git a/modules/core/include/opencv2/core/hal/intrin_neon.hpp b/modules/core/include/opencv2/core/hal/intrin_neon.hpp index f3e47ca8ba..f989b3a8ad 100644 --- a/modules/core/include/opencv2/core/hal/intrin_neon.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_neon.hpp @@ -53,6 +53,28 @@ namespace cv //! @cond IGNORED #define CV_SIMD128 1 +#if defined(__aarch64__) +#define CV_SIMD128_64F 1 +#else +#define CV_SIMD128_64F 0 +#endif + +#if CV_SIMD128_64F +#define OPENCV_HAL_IMPL_NEON_REINTERPRET(_Tpv, suffix) \ +template static inline \ +_Tpv vreinterpretq_##suffix##_f64(T a) { return (_Tpv) a; } \ +template static inline \ +float64x2_t vreinterpretq_f64_##suffix(T a) { return (float64x2_t) a; } +OPENCV_HAL_IMPL_NEON_REINTERPRET(uint8x16_t, u8) +OPENCV_HAL_IMPL_NEON_REINTERPRET(int8x16_t, s8) +OPENCV_HAL_IMPL_NEON_REINTERPRET(uint16x8_t, u16) +OPENCV_HAL_IMPL_NEON_REINTERPRET(int16x8_t, s16) +OPENCV_HAL_IMPL_NEON_REINTERPRET(uint32x4_t, u32) +OPENCV_HAL_IMPL_NEON_REINTERPRET(int32x4_t, s32) +OPENCV_HAL_IMPL_NEON_REINTERPRET(uint64x2_t, u64) +OPENCV_HAL_IMPL_NEON_REINTERPRET(int64x2_t, s64) +OPENCV_HAL_IMPL_NEON_REINTERPRET(float32x4_t, f32) +#endif struct v_uint8x16 { @@ -232,6 +254,27 @@ struct v_int64x2 int64x2_t val; }; +#if CV_SIMD128_64F +struct v_float64x2 +{ + typedef double lane_type; + enum { nlanes = 2 }; + + v_float64x2() {} + explicit v_float64x2(float64x2_t v) : val(v) {} + v_float64x2(double v0, double v1) + { + double v[] = {v0, v1}; + val = vld1q_f64(v); + } + double get0() const + { + return vgetq_lane_f64(val, 0); + } + float64x2_t val; +}; +#endif + #define OPENCV_HAL_IMPL_NEON_INIT(_Tpv, _Tp, suffix) \ inline v_##_Tpv v_setzero_##suffix() { return v_##_Tpv(vdupq_n_##suffix((_Tp)0)); } \ inline v_##_Tpv v_setall_##suffix(_Tp v) { return v_##_Tpv(vdupq_n_##suffix(v)); } \ @@ -255,6 +298,21 @@ OPENCV_HAL_IMPL_NEON_INIT(int32x4, int, s32) OPENCV_HAL_IMPL_NEON_INIT(uint64x2, uint64, u64) OPENCV_HAL_IMPL_NEON_INIT(int64x2, int64, s64) OPENCV_HAL_IMPL_NEON_INIT(float32x4, float, f32) +#if CV_SIMD128_64F +#define OPENCV_HAL_IMPL_NEON_INIT_64(_Tpv, suffix) \ +inline v_float64x2 v_reinterpret_as_f64(const v_##_Tpv& v) { return v_float64x2(vreinterpretq_f64_##suffix(v.val)); } +OPENCV_HAL_IMPL_NEON_INIT(float64x2, double, f64) +OPENCV_HAL_IMPL_NEON_INIT_64(uint8x16, u8) +OPENCV_HAL_IMPL_NEON_INIT_64(int8x16, s8) +OPENCV_HAL_IMPL_NEON_INIT_64(uint16x8, u16) +OPENCV_HAL_IMPL_NEON_INIT_64(int16x8, s16) +OPENCV_HAL_IMPL_NEON_INIT_64(uint32x4, u32) +OPENCV_HAL_IMPL_NEON_INIT_64(int32x4, s32) +OPENCV_HAL_IMPL_NEON_INIT_64(uint64x2, u64) +OPENCV_HAL_IMPL_NEON_INIT_64(int64x2, s64) +OPENCV_HAL_IMPL_NEON_INIT_64(float32x4, f32) +OPENCV_HAL_IMPL_NEON_INIT_64(float64x2, f64) +#endif #define OPENCV_HAL_IMPL_NEON_PACK(_Tpvec, _Tp, hreg, suffix, _Tpwvec, wsuffix, pack, op) \ inline _Tpvec v_##pack(const _Tpwvec& a, const _Tpwvec& b) \ @@ -337,7 +395,13 @@ OPENCV_HAL_IMPL_NEON_BIN_OP(+, v_int64x2, vaddq_s64) OPENCV_HAL_IMPL_NEON_BIN_OP(-, v_int64x2, vsubq_s64) OPENCV_HAL_IMPL_NEON_BIN_OP(+, v_uint64x2, vaddq_u64) OPENCV_HAL_IMPL_NEON_BIN_OP(-, v_uint64x2, vsubq_u64) - +#if CV_SIMD128_64F +OPENCV_HAL_IMPL_NEON_BIN_OP(/, v_float32x4, vdivq_f32) +OPENCV_HAL_IMPL_NEON_BIN_OP(+, v_float64x2, vaddq_f64) +OPENCV_HAL_IMPL_NEON_BIN_OP(-, v_float64x2, vsubq_f64) +OPENCV_HAL_IMPL_NEON_BIN_OP(*, v_float64x2, vmulq_f64) +OPENCV_HAL_IMPL_NEON_BIN_OP(/, v_float64x2, vdivq_f64) +#else inline v_float32x4 operator / (const v_float32x4& a, const v_float32x4& b) { float32x4_t reciprocal = vrecpeq_f32(b.val); @@ -353,6 +417,7 @@ inline v_float32x4& operator /= (v_float32x4& a, const v_float32x4& b) a.val = vmulq_f32(a.val, reciprocal); return a; } +#endif inline void v_mul_expand(const v_int16x8& a, const v_int16x8& b, v_int32x4& c, v_int32x4& d) @@ -421,6 +486,18 @@ inline v_float32x4 operator ~ (const v_float32x4& a) return v_float32x4(vreinterpretq_f32_s32(vmvnq_s32(vreinterpretq_s32_f32(a.val)))); } +#if CV_SIMD128_64F +inline v_float32x4 v_sqrt(const v_float32x4& x) +{ + return v_float32x4(vsqrtq_f32(x.val)); +} + +inline v_float32x4 v_invsqrt(const v_float32x4& x) +{ + v_float32x4 one = v_setall_f32(1.0f); + return one / v_sqrt(x); +} +#else inline v_float32x4 v_sqrt(const v_float32x4& x) { float32x4_t x1 = vmaxq_f32(x.val, vdupq_n_f32(FLT_MIN)); @@ -437,10 +514,47 @@ inline v_float32x4 v_invsqrt(const v_float32x4& x) e = vmulq_f32(vrsqrtsq_f32(vmulq_f32(x.val, e), e), e); return v_float32x4(e); } +#endif inline v_float32x4 v_abs(v_float32x4 x) { return v_float32x4(vabsq_f32(x.val)); } +#if CV_SIMD128_64F +#define OPENCV_HAL_IMPL_NEON_DBL_BIT_OP(bin_op, intrin) \ +inline v_float64x2 operator bin_op (const v_float64x2& a, const v_float64x2& b) \ +{ \ + return v_float64x2(vreinterpretq_f64_s64(intrin(vreinterpretq_s64_f64(a.val), vreinterpretq_s64_f64(b.val)))); \ +} \ +inline v_float64x2& operator bin_op##= (v_float64x2& a, const v_float64x2& b) \ +{ \ + a.val = vreinterpretq_f64_s64(intrin(vreinterpretq_s64_f64(a.val), vreinterpretq_s64_f64(b.val))); \ + return a; \ +} + +OPENCV_HAL_IMPL_NEON_DBL_BIT_OP(&, vandq_s64) +OPENCV_HAL_IMPL_NEON_DBL_BIT_OP(|, vorrq_s64) +OPENCV_HAL_IMPL_NEON_DBL_BIT_OP(^, veorq_s64) + +inline v_float64x2 operator ~ (const v_float64x2& a) +{ + return v_float64x2(vreinterpretq_f64_s32(vmvnq_s32(vreinterpretq_s32_f64(a.val)))); +} + +inline v_float64x2 v_sqrt(const v_float64x2& x) +{ + return v_float64x2(vsqrtq_f64(x.val)); +} + +inline v_float64x2 v_invsqrt(const v_float64x2& x) +{ + v_float64x2 one = v_setall_f64(1.0f); + return one / v_sqrt(x); +} + +inline v_float64x2 v_abs(v_float64x2 x) +{ return v_float64x2(vabsq_f64(x.val)); } +#endif + // TODO: exp, log, sin, cos #define OPENCV_HAL_IMPL_NEON_BIN_FUNC(_Tpvec, func, intrin) \ @@ -463,8 +577,23 @@ OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_int32x4, v_min, vminq_s32) OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_int32x4, v_max, vmaxq_s32) OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_float32x4, v_min, vminq_f32) OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_float32x4, v_max, vmaxq_f32) +#if CV_SIMD128_64F +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_float64x2, v_min, vminq_f64) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_float64x2, v_max, vmaxq_f64) +#endif - +#if CV_SIMD128_64F +inline int64x2_t vmvnq_s64(int64x2_t a) +{ + int64x2_t vx = vreinterpretq_s64_u32(vdupq_n_u32(0xFFFFFFFF)); + return veorq_s64(a, vx); +} +inline uint64x2_t vmvnq_u64(uint64x2_t a) +{ + uint64x2_t vx = vreinterpretq_u64_u32(vdupq_n_u32(0xFFFFFFFF)); + return veorq_u64(a, vx); +} +#endif #define OPENCV_HAL_IMPL_NEON_INT_CMP_OP(_Tpvec, cast, suffix, not_suffix) \ inline _Tpvec operator == (const _Tpvec& a, const _Tpvec& b) \ { return _Tpvec(cast(vceqq_##suffix(a.val, b.val))); } \ @@ -486,6 +615,11 @@ OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int16x8, vreinterpretq_s16_u16, s16, u16) OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_uint32x4, OPENCV_HAL_NOP, u32, u32) OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int32x4, vreinterpretq_s32_u32, s32, u32) OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_float32x4, vreinterpretq_f32_u32, f32, u32) +#if CV_SIMD128_64F +OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_uint64x2, OPENCV_HAL_NOP, u64, u64) +OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int64x2, vreinterpretq_s64_u64, s64, u64) +OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_float64x2, vreinterpretq_f64_u64, f64, u64) +#endif OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint8x16, v_add_wrap, vaddq_u8) OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_int8x16, v_add_wrap, vaddq_s8) @@ -501,6 +635,9 @@ OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint8x16, v_absdiff, vabdq_u8) OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint16x8, v_absdiff, vabdq_u16) OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint32x4, v_absdiff, vabdq_u32) OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_float32x4, v_absdiff, vabdq_f32) +#if CV_SIMD128_64F +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_float64x2, v_absdiff, vabdq_f64) +#endif #define OPENCV_HAL_IMPL_NEON_BIN_FUNC2(_Tpvec, _Tpvec2, cast, func, intrin) \ inline _Tpvec2 func(const _Tpvec& a, const _Tpvec& b) \ @@ -528,6 +665,24 @@ inline v_float32x4 v_muladd(const v_float32x4& a, const v_float32x4& b, const v_ return v_float32x4(vmlaq_f32(c.val, a.val, b.val)); } +#if CV_SIMD128_64F +inline v_float64x2 v_magnitude(const v_float64x2& a, const v_float64x2& b) +{ + v_float64x2 x(vaddq_f64(vmulq_f64(a.val, a.val), vmulq_f64(b.val, b.val))); + return v_sqrt(x); +} + +inline v_float64x2 v_sqr_magnitude(const v_float64x2& a, const v_float64x2& b) +{ + return v_float64x2(vaddq_f64(vmulq_f64(a.val, a.val), vmulq_f64(b.val, b.val))); +} + +inline v_float64x2 v_muladd(const v_float64x2& a, const v_float64x2& b, const v_float64x2& c) +{ + return v_float64x2(vaddq_f64(c.val, vmulq_f64(a.val, b.val))); +} +#endif + // trade efficiency for convenience #define OPENCV_HAL_IMPL_NEON_SHIFT_OP(_Tpvec, suffix, _Tps, ssuffix) \ inline _Tpvec operator << (const _Tpvec& a, int n) \ @@ -575,6 +730,9 @@ OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_int32x4, int, s32) OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_uint64x2, uint64, u64) OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_int64x2, int64, s64) OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_float32x4, float, f32) +#if CV_SIMD128_64F +OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_float64x2, double, f64) +#endif #define OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(_Tpvec, scalartype, func, scalar_func) \ inline scalartype v_reduce_##func(const _Tpvec& a) \ @@ -627,6 +785,16 @@ inline int v_signmask(const v_int32x4& a) { return v_signmask(v_reinterpret_as_u32(a)); } inline int v_signmask(const v_float32x4& a) { return v_signmask(v_reinterpret_as_u32(a)); } +#if CV_SIMD128_64F +inline int v_signmask(const v_uint64x2& a) +{ + int64x1_t m0 = vdup_n_s64(0); + uint64x2_t v0 = vshlq_u64(vshrq_n_u64(a.val, 63), vcombine_s64(m0, m0)); + return (int)vgetq_lane_u64(v0, 0) + ((int)vgetq_lane_u64(v0, 1) << 1); +} +inline int v_signmask(const v_float64x2& a) +{ return v_signmask(v_reinterpret_as_u64(a)); } +#endif #define OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(_Tpvec, suffix, shift) \ inline bool v_check_all(const v_##_Tpvec& a) \ @@ -645,6 +813,9 @@ inline bool v_check_any(const v_##_Tpvec& a) \ OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint8x16, u8, 7) OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint16x8, u16, 15) OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint32x4, u32, 31) +#if CV_SIMD128_64F +OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint64x2, u64, 63) +#endif inline bool v_check_all(const v_int8x16& a) { return v_check_all(v_reinterpret_as_u8(a)); } @@ -664,6 +835,17 @@ inline bool v_check_any(const v_int32x4& a) inline bool v_check_any(const v_float32x4& a) { return v_check_any(v_reinterpret_as_u32(a)); } +#if CV_SIMD128_64F +inline bool v_check_all(const v_int64x2& a) +{ return v_check_all(v_reinterpret_as_u64(a)); } +inline bool v_check_all(const v_float64x2& a) +{ return v_check_all(v_reinterpret_as_u64(a)); } +inline bool v_check_any(const v_int64x2& a) +{ return v_check_any(v_reinterpret_as_u64(a)); } +inline bool v_check_any(const v_float64x2& a) +{ return v_check_any(v_reinterpret_as_u64(a)); } +#endif + #define OPENCV_HAL_IMPL_NEON_SELECT(_Tpvec, suffix, usuffix) \ inline _Tpvec v_select(const _Tpvec& mask, const _Tpvec& a, const _Tpvec& b) \ { \ @@ -677,6 +859,9 @@ OPENCV_HAL_IMPL_NEON_SELECT(v_int16x8, s16, u16) OPENCV_HAL_IMPL_NEON_SELECT(v_uint32x4, u32, u32) OPENCV_HAL_IMPL_NEON_SELECT(v_int32x4, s32, u32) OPENCV_HAL_IMPL_NEON_SELECT(v_float32x4, f32, u32) +#if CV_SIMD128_64F +OPENCV_HAL_IMPL_NEON_SELECT(v_float64x2, f64, u64) +#endif #define OPENCV_HAL_IMPL_NEON_EXPAND(_Tpvec, _Tpwvec, _Tp, suffix) \ inline void v_expand(const _Tpvec& a, _Tpwvec& b0, _Tpwvec& b1) \ @@ -710,6 +895,27 @@ inline v_int32x4 v_load_expand_q(const schar* ptr) return v_int32x4(vmovl_s16(v1)); } +#if defined(__aarch64__) +#define OPENCV_HAL_IMPL_NEON_UNPACKS(_Tpvec, suffix) \ +inline void v_zip(const v_##_Tpvec& a0, const v_##_Tpvec& a1, v_##_Tpvec& b0, v_##_Tpvec& b1) \ +{ \ + b0.val = vzip1q_##suffix(a0.val, a1.val); \ + b1.val = vzip2q_##suffix(a0.val, a1.val); \ +} \ +inline v_##_Tpvec v_combine_low(const v_##_Tpvec& a, const v_##_Tpvec& b) \ +{ \ + return v_##_Tpvec(vcombine_##suffix(vget_low_##suffix(a.val), vget_low_##suffix(b.val))); \ +} \ +inline v_##_Tpvec v_combine_high(const v_##_Tpvec& a, const v_##_Tpvec& b) \ +{ \ + return v_##_Tpvec(vcombine_##suffix(vget_high_##suffix(a.val), vget_high_##suffix(b.val))); \ +} \ +inline void v_recombine(const v_##_Tpvec& a, const v_##_Tpvec& b, v_##_Tpvec& c, v_##_Tpvec& d) \ +{ \ + c.val = vcombine_##suffix(vget_low_##suffix(a.val), vget_low_##suffix(b.val)); \ + d.val = vcombine_##suffix(vget_high_##suffix(a.val), vget_high_##suffix(b.val)); \ +} +#else #define OPENCV_HAL_IMPL_NEON_UNPACKS(_Tpvec, suffix) \ inline void v_zip(const v_##_Tpvec& a0, const v_##_Tpvec& a1, v_##_Tpvec& b0, v_##_Tpvec& b1) \ { \ @@ -730,6 +936,7 @@ inline void v_recombine(const v_##_Tpvec& a, const v_##_Tpvec& b, v_##_Tpvec& c, c.val = vcombine_##suffix(vget_low_##suffix(a.val), vget_low_##suffix(b.val)); \ d.val = vcombine_##suffix(vget_high_##suffix(a.val), vget_high_##suffix(b.val)); \ } +#endif OPENCV_HAL_IMPL_NEON_UNPACKS(uint8x16, u8) OPENCV_HAL_IMPL_NEON_UNPACKS(int8x16, s8) @@ -738,6 +945,9 @@ OPENCV_HAL_IMPL_NEON_UNPACKS(int16x8, s16) OPENCV_HAL_IMPL_NEON_UNPACKS(uint32x4, u32) OPENCV_HAL_IMPL_NEON_UNPACKS(int32x4, s32) OPENCV_HAL_IMPL_NEON_UNPACKS(float32x4, f32) +#if CV_SIMD128_64F +OPENCV_HAL_IMPL_NEON_UNPACKS(float64x2, f64) +#endif #define OPENCV_HAL_IMPL_NEON_EXTRACT(_Tpvec, suffix) \ template \ @@ -755,6 +965,9 @@ OPENCV_HAL_IMPL_NEON_EXTRACT(int32x4, s32) OPENCV_HAL_IMPL_NEON_EXTRACT(uint64x2, u64) OPENCV_HAL_IMPL_NEON_EXTRACT(int64x2, s64) OPENCV_HAL_IMPL_NEON_EXTRACT(float32x4, f32) +#if CV_SIMD128_64F +OPENCV_HAL_IMPL_NEON_EXTRACT(float64x2, f64) +#endif inline v_int32x4 v_round(const v_float32x4& a) { @@ -782,6 +995,38 @@ inline v_int32x4 v_ceil(const v_float32x4& a) inline v_int32x4 v_trunc(const v_float32x4& a) { return v_int32x4(vcvtq_s32_f32(a.val)); } +#if CV_SIMD128_64F +inline v_int32x4 v_round(const v_float64x2& a) +{ + static const int32x2_t zero = vdup_n_s32(0); + return v_int32x4(vcombine_s32(vmovn_s64(vcvtaq_s64_f64(a.val)), zero)); +} + +inline v_int32x4 v_floor(const v_float64x2& a) +{ + static const int32x2_t zero = vdup_n_s32(0); + int64x2_t a1 = vcvtq_s64_f64(a.val); + uint64x2_t mask = vcgtq_f64(vcvtq_f64_s64(a1), a.val); + a1 = vaddq_s64(a1, vreinterpretq_s64_u64(mask)); + return v_int32x4(vcombine_s32(vmovn_s64(a1), zero)); +} + +inline v_int32x4 v_ceil(const v_float64x2& a) +{ + static const int32x2_t zero = vdup_n_s32(0); + int64x2_t a1 = vcvtq_s64_f64(a.val); + uint64x2_t mask = vcgtq_f64(a.val, vcvtq_f64_s64(a1)); + a1 = vsubq_s64(a1, vreinterpretq_s64_u64(mask)); + return v_int32x4(vcombine_s32(vmovn_s64(a1), zero)); +} + +inline v_int32x4 v_trunc(const v_float64x2& a) +{ + static const int32x2_t zero = vdup_n_s32(0); + return v_int32x4(vcombine_s32(vmovn_s64(vcvtaq_s64_f64(a.val)), zero)); +} +#endif + #define OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(_Tpvec, suffix) \ inline void v_transpose4x4(const v_##_Tpvec& a0, const v_##_Tpvec& a1, \ const v_##_Tpvec& a2, const v_##_Tpvec& a3, \ @@ -851,12 +1096,45 @@ OPENCV_HAL_IMPL_NEON_INTERLEAVED(int16x8, short, s16) OPENCV_HAL_IMPL_NEON_INTERLEAVED(uint32x4, unsigned, u32) OPENCV_HAL_IMPL_NEON_INTERLEAVED(int32x4, int, s32) OPENCV_HAL_IMPL_NEON_INTERLEAVED(float32x4, float, f32) +#if CV_SIMD128_64F +OPENCV_HAL_IMPL_NEON_INTERLEAVED(float64x2, double, f64) +#endif inline v_float32x4 v_cvt_f32(const v_int32x4& a) { return v_float32x4(vcvtq_f32_s32(a.val)); } +#if CV_SIMD128_64F +inline v_float32x4 v_cvt_f32(const v_float64x2& a) +{ + float32x2_t zero = vdup_n_f32(0.0f); + return v_float32x4(vcombine_f32(vcvt_f32_f64(a.val), zero)); +} + +inline v_float64x2 v_cvt_f64(const v_int32x4& a) +{ + return v_float64x2(vcvt_f64_f32(vcvt_f32_s32(vget_low_s32(a.val)))); +} + +inline v_float64x2 v_cvt_f64_high(const v_int32x4& a) +{ + return v_float64x2(vcvt_f64_f32(vcvt_f32_s32(vget_high_s32(a.val)))); +} + +inline v_float64x2 v_cvt_f64(const v_float32x4& a) +{ + return v_float64x2(vcvt_f64_f32(vget_low_f32(a.val))); +} + +inline v_float64x2 v_cvt_f64_high(const v_float32x4& a) +{ + return v_float64x2(vcvt_f64_f32(vget_high_f32(a.val))); +} +#endif + + + //! @endcond } diff --git a/modules/core/include/opencv2/core/hal/intrin_sse.hpp b/modules/core/include/opencv2/core/hal/intrin_sse.hpp index 1840e0305d..8b49bbb465 100644 --- a/modules/core/include/opencv2/core/hal/intrin_sse.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_sse.hpp @@ -1587,11 +1587,21 @@ inline v_float64x2 v_cvt_f64(const v_int32x4& a) return v_float64x2(_mm_cvtepi32_pd(a.val)); } +inline v_float64x2 v_cvt_f64_high(const v_int32x4& a) +{ + return v_float64x2(_mm_cvtepi32_pd(_mm_srli_si128(a.val,8))); +} + inline v_float64x2 v_cvt_f64(const v_float32x4& a) { return v_float64x2(_mm_cvtps_pd(a.val)); } +inline v_float64x2 v_cvt_f64_high(const v_float32x4& a) +{ + return v_float64x2(_mm_cvtps_pd(_mm_castsi128_ps(_mm_srli_si128(_mm_castps_si128(a.val),8)))); +} + //! @endcond } diff --git a/modules/core/test/test_intrin.cpp b/modules/core/test/test_intrin.cpp index ca9d3dc7b7..c1f2a31c05 100644 --- a/modules/core/test/test_intrin.cpp +++ b/modules/core/test/test_intrin.cpp @@ -626,12 +626,18 @@ template struct TheTest dataA *= 1.1; R a = dataA; Rt b = v_cvt_f64(a); + Rt c = v_cvt_f64_high(a); Data resB = b; + Data resC = c; int n = std::min(Rt::nlanes, R::nlanes); for (int i = 0; i < n; ++i) { EXPECT_EQ((typename Rt::lane_type)dataA[i], resB[i]); } + for (int i = 0; i < n; ++i) + { + EXPECT_EQ((typename Rt::lane_type)dataA[i+n], resC[i]); + } #endif return *this; } diff --git a/modules/imgproc/src/accum.cpp b/modules/imgproc/src/accum.cpp index 8626187fd8..eaf85a2654 100644 --- a/modules/imgproc/src/accum.cpp +++ b/modules/imgproc/src/accum.cpp @@ -395,7 +395,7 @@ struct AccW_SIMD return x; } }; -#elif CV_SSE2 +#elif CV_SIMD128 template <> struct Acc_SIMD { @@ -408,8 +408,8 @@ struct Acc_SIMD len *= cn; for ( ; x <= len - 8; x += 8) { - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_loadu_ps(src + x))); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_loadu_ps(src + x + 4))); + v_store(dst + x, v_load(dst + x) + v_load(src + x)); + v_store(dst + x + 4, v_load(dst + x + 4) + v_load(src + x + 4)); } } @@ -417,6 +417,7 @@ struct Acc_SIMD } }; +#if CV_SIMD128_64F template <> struct Acc_SIMD { @@ -429,17 +430,12 @@ struct Acc_SIMD len *= cn; for ( ; x <= len - 4; x += 4) { - __m128 v_src = _mm_loadu_ps(src + x); - __m128d v_src0 = _mm_cvtps_pd(v_src); - __m128d v_src1 = _mm_cvtps_pd(_mm_shuffle_ps(v_src, v_src, _MM_SHUFFLE(1, 0, 3, 2))); + v_float32x4 v_src = v_load(src + x); + v_float64x2 v_src0 = v_cvt_f64(v_src); + v_float64x2 v_src1 = v_cvt_f64_high(v_src); - __m128d v_dst0 = _mm_loadu_pd(dst + x); - __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); - - v_dst0 = _mm_add_pd(v_dst0, v_src0); - v_dst1 = _mm_add_pd(v_dst1, v_src1); - _mm_storeu_pd(dst + x, v_dst0); - _mm_storeu_pd(dst + x + 2, v_dst1); + v_store(dst + x, v_load(dst + x) + v_src0); + v_store(dst + x + 2, v_load(dst + x + 2) + v_src1); } } return x; @@ -458,21 +454,17 @@ struct Acc_SIMD len *= cn; for ( ; x <= len - 4; x += 4) { - __m128d v_src0 = _mm_loadu_pd(src + x); - __m128d v_src1 = _mm_loadu_pd(src + x + 2); + v_float64x2 v_src0 = v_load(src + x); + v_float64x2 v_src1 = v_load(src + x + 2); - __m128d v_dst0 = _mm_loadu_pd(dst + x); - __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); - - v_dst0 = _mm_add_pd(v_dst0, v_src0); - v_dst1 = _mm_add_pd(v_dst1, v_src1); - _mm_storeu_pd(dst + x, v_dst0); - _mm_storeu_pd(dst + x + 2, v_dst1); + v_store(dst + x, v_load(dst + x) + v_src0); + v_store(dst + x + 2, v_load(dst + x + 2) + v_src1); } } return x; } }; +#endif //CV_SIMD128_64F template <> struct AccSqr_SIMD @@ -486,12 +478,13 @@ struct AccSqr_SIMD len *= cn; for ( ; x <= len - 8; x += 8) { - __m128 v_src0 = _mm_loadu_ps(src + x); - __m128 v_src1 = _mm_loadu_ps(src + x + 4); - v_src0 = _mm_mul_ps(v_src0, v_src0); - v_src1 = _mm_mul_ps(v_src1, v_src1); - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), v_src0)); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), v_src1)); + v_float32x4 v_src0 = v_load(src + x); + v_float32x4 v_src1 = v_load(src + x + 4); + v_src0 = v_src0 * v_src0; + v_src1 = v_src1 * v_src1; + + v_store(dst + x, v_load(dst + x) + v_src0); + v_store(dst + x + 4, v_load(dst + x + 4) + v_src1); } } @@ -499,6 +492,7 @@ struct AccSqr_SIMD } }; +#if CV_SIMD128_64F template <> struct AccSqr_SIMD { @@ -511,19 +505,14 @@ struct AccSqr_SIMD len *= cn; for ( ; x <= len - 4; x += 4) { - __m128 v_src = _mm_loadu_ps(src + x); - __m128d v_src0 = _mm_cvtps_pd(v_src); - __m128d v_src1 = _mm_cvtps_pd(_mm_shuffle_ps(v_src, v_src, _MM_SHUFFLE(1, 0, 3, 2))); - v_src0 = _mm_mul_pd(v_src0, v_src0); - v_src1 = _mm_mul_pd(v_src1, v_src1); + v_float32x4 v_src = v_load(src + x); + v_float64x2 v_src0 = v_cvt_f64(v_src); + v_float64x2 v_src1 = v_cvt_f64_high(v_src); + v_src0 = v_src0 * v_src0; + v_src1 = v_src1 * v_src1; - __m128d v_dst0 = _mm_loadu_pd(dst + x); - __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); - v_dst0 = _mm_add_pd(v_dst0, v_src0); - v_dst1 = _mm_add_pd(v_dst1, v_src1); - - _mm_storeu_pd(dst + x, v_dst0); - _mm_storeu_pd(dst + x + 2, v_dst1); + v_store(dst + x, v_load(dst + x) + v_src0); + v_store(dst + x + 2, v_load(dst + x + 2) + v_src1); } } return x; @@ -542,23 +531,19 @@ struct AccSqr_SIMD len *= cn; for ( ; x <= len - 4; x += 4) { - __m128d v_src0 = _mm_loadu_pd(src + x); - __m128d v_src1 = _mm_loadu_pd(src + x + 2); - v_src0 = _mm_mul_pd(v_src0, v_src0); - v_src1 = _mm_mul_pd(v_src1, v_src1); + v_float64x2 v_src0 = v_load(src + x); + v_float64x2 v_src1 = v_load(src + x + 2); + v_src0 = v_src0 * v_src0; + v_src1 = v_src1 * v_src1; - __m128d v_dst0 = _mm_loadu_pd(dst + x); - __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); - - v_dst0 = _mm_add_pd(v_dst0, v_src0); - v_dst1 = _mm_add_pd(v_dst1, v_src1); - _mm_storeu_pd(dst + x, v_dst0); - _mm_storeu_pd(dst + x + 2, v_dst1); + v_store(dst + x, v_load(dst + x) + v_src0); + v_store(dst + x + 2, v_load(dst + x + 2) + v_src1); } } return x; } }; +#endif //CV_SIMD128_64F template <> struct AccProd_SIMD @@ -572,8 +557,8 @@ struct AccProd_SIMD len *= cn; for ( ; x <= len - 8; x += 8) { - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_mul_ps(_mm_loadu_ps(src1 + x), _mm_loadu_ps(src2 + x)))); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_mul_ps(_mm_loadu_ps(src1 + x + 4), _mm_loadu_ps(src2 + x + 4)))); + v_store(dst + x, v_load(dst + x) + v_load(src1 + x) * v_load(src2 + x)); + v_store(dst + x + 4, v_load(dst + x + 4) + v_load(src1 + x + 4) * v_load(src2 + x + 4)); } } @@ -581,6 +566,7 @@ struct AccProd_SIMD } }; +#if CV_SIMD128_64F template <> struct AccProd_SIMD { @@ -593,22 +579,16 @@ struct AccProd_SIMD len *= cn; for ( ; x <= len - 4; x += 4) { - __m128 v_1src = _mm_loadu_ps(src1 + x); - __m128 v_2src = _mm_loadu_ps(src2 + x); + v_float32x4 v_1src = v_load(src1 + x); + v_float32x4 v_2src = v_load(src2 + x); - __m128d v_1src0 = _mm_cvtps_pd(v_1src); - __m128d v_1src1 = _mm_cvtps_pd(_mm_shuffle_ps(v_1src, v_1src, _MM_SHUFFLE(0, 0, 3, 2))); - __m128d v_2src0 = _mm_cvtps_pd(v_2src); - __m128d v_2src1 = _mm_cvtps_pd(_mm_shuffle_ps(v_2src, v_2src, _MM_SHUFFLE(0, 0, 3, 2))); + v_float64x2 v_1src0 = v_cvt_f64(v_1src); + v_float64x2 v_1src1 = v_cvt_f64_high(v_1src); + v_float64x2 v_2src0 = v_cvt_f64(v_2src); + v_float64x2 v_2src1 = v_cvt_f64_high(v_2src); - __m128d v_dst0 = _mm_loadu_pd(dst + x); - __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); - - v_dst0 = _mm_add_pd(v_dst0, _mm_mul_pd(v_1src0, v_2src0)); - v_dst1 = _mm_add_pd(v_dst1, _mm_mul_pd(v_1src1, v_2src1)); - - _mm_storeu_pd(dst + x, v_dst0); - _mm_storeu_pd(dst + x + 2, v_dst1); + v_store(dst + x, v_load(dst + x) + (v_1src0 * v_2src0)); + v_store(dst + x + 2, v_load(dst + x + 2) + (v_1src1 * v_2src1)); } } return x; @@ -627,25 +607,19 @@ struct AccProd_SIMD len *= cn; for ( ; x <= len - 4; x += 4) { - __m128d v_src00 = _mm_loadu_pd(src1 + x); - __m128d v_src01 = _mm_loadu_pd(src1 + x + 2); - __m128d v_src10 = _mm_loadu_pd(src2 + x); - __m128d v_src11 = _mm_loadu_pd(src2 + x + 2); - __m128d v_src0 = _mm_mul_pd(v_src00, v_src10); - __m128d v_src1 = _mm_mul_pd(v_src01, v_src11); + v_float64x2 v_src00 = v_load(src1 + x); + v_float64x2 v_src01 = v_load(src1 + x + 2); + v_float64x2 v_src10 = v_load(src2 + x); + v_float64x2 v_src11 = v_load(src2 + x + 2); - __m128d v_dst0 = _mm_loadu_pd(dst + x); - __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); - - v_dst0 = _mm_add_pd(v_dst0, v_src0); - v_dst1 = _mm_add_pd(v_dst1, v_src1); - _mm_storeu_pd(dst + x, v_dst0); - _mm_storeu_pd(dst + x + 2, v_dst1); + v_store(dst + x, v_load(dst + x) + (v_src00 * v_src10)); + v_store(dst + x + 2, v_load(dst + x + 2) + (v_src01 * v_src11)); } } return x; } }; +#endif //CV_SIMD128_64F template <> struct AccW_SIMD @@ -653,16 +627,16 @@ struct AccW_SIMD int operator() (const float * src, float * dst, const uchar * mask, int len, int cn, float alpha) const { int x = 0; - __m128 v_alpha = _mm_set1_ps(alpha); - __m128 v_beta = _mm_set1_ps(1.0f - alpha); + v_float32x4 v_alpha = v_setall_f32(alpha); + v_float32x4 v_beta = v_setall_f32(1.0f - alpha); if (!mask) { len *= cn; for ( ; x <= len - 8; x += 8) { - _mm_storeu_ps(dst + x, _mm_add_ps(_mm_mul_ps(_mm_loadu_ps(dst + x), v_beta), _mm_mul_ps(_mm_loadu_ps(src + x), v_alpha))); - _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_mul_ps(_mm_loadu_ps(dst + x + 4), v_beta), _mm_mul_ps(_mm_loadu_ps(src + x + 4), v_alpha))); + v_store(dst + x, ((v_load(dst + x) * v_beta) + (v_load(src + x) * v_alpha))); + v_store(dst + x + 4, ((v_load(dst + x + 4) * v_beta) + (v_load(src + x + 4) * v_alpha))); } } @@ -670,31 +644,32 @@ struct AccW_SIMD } }; +#if CV_SIMD128_64F template <> struct AccW_SIMD { int operator() (const float * src, double * dst, const uchar * mask, int len, int cn, double alpha) const { int x = 0; - __m128d v_alpha = _mm_set1_pd(alpha); - __m128d v_beta = _mm_set1_pd(1.0f - alpha); + v_float64x2 v_alpha = v_setall_f64(alpha); + v_float64x2 v_beta = v_setall_f64(1.0f - alpha); if (!mask) { len *= cn; for ( ; x <= len - 8; x += 8) { - __m128 v_src0 = _mm_loadu_ps(src + x); - __m128 v_src1 = _mm_loadu_ps(src + x + 4); - __m128d v_src00 = _mm_cvtps_pd(v_src0); - __m128d v_src01 = _mm_cvtps_pd(_mm_shuffle_ps(v_src0, v_src0, _MM_SHUFFLE(0, 0, 3, 2))); - __m128d v_src10 = _mm_cvtps_pd(v_src1); - __m128d v_src11 = _mm_cvtps_pd(_mm_shuffle_ps(v_src1, v_src1, _MM_SHUFFLE(0, 0, 3, 2))); + v_float32x4 v_src0 = v_load(src + x); + v_float32x4 v_src1 = v_load(src + x + 4); + v_float64x2 v_src00 = v_cvt_f64(v_src0); + v_float64x2 v_src01 = v_cvt_f64_high(v_src0); + v_float64x2 v_src10 = v_cvt_f64(v_src1); + v_float64x2 v_src11 = v_cvt_f64_high(v_src1); - _mm_storeu_pd(dst + x, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(dst + x), v_beta), _mm_mul_pd(v_src00, v_alpha))); - _mm_storeu_pd(dst + x + 2, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(dst + x + 2), v_beta), _mm_mul_pd(v_src01, v_alpha))); - _mm_storeu_pd(dst + x + 4, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(dst + x + 4), v_beta), _mm_mul_pd(v_src10, v_alpha))); - _mm_storeu_pd(dst + x + 6, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(dst + x + 6), v_beta), _mm_mul_pd(v_src11, v_alpha))); + v_store(dst + x, ((v_load(dst + x) * v_beta) + (v_src00 * v_alpha))); + v_store(dst + x + 2, ((v_load(dst + x + 2) * v_beta) + (v_src01 * v_alpha))); + v_store(dst + x + 4, ((v_load(dst + x + 4) * v_beta) + (v_src10 * v_alpha))); + v_store(dst + x + 6, ((v_load(dst + x + 6) * v_beta) + (v_src11 * v_alpha))); } } @@ -708,26 +683,27 @@ struct AccW_SIMD int operator() (const double * src, double * dst, const uchar * mask, int len, int cn, double alpha) const { int x = 0; - __m128d v_alpha = _mm_set1_pd(alpha); - __m128d v_beta = _mm_set1_pd(1.0f - alpha); + v_float64x2 v_alpha = v_setall_f64(alpha); + v_float64x2 v_beta = v_setall_f64(1.0f - alpha); if (!mask) { len *= cn; for ( ; x <= len - 4; x += 4) { - __m128d v_src0 = _mm_loadu_pd(src + x); - __m128d v_src1 = _mm_loadu_pd(src + x + 2); + v_float64x2 v_src0 = v_load(src + x); + v_float64x2 v_src1 = v_load(src + x + 2); - _mm_storeu_pd(dst + x, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(dst + x), v_beta), _mm_mul_pd(v_src0, v_alpha))); - _mm_storeu_pd(dst + x + 2, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(dst + x + 2), v_beta), _mm_mul_pd(v_src1, v_alpha))); + v_store(dst + x, ((v_load(dst + x) * v_beta) + (v_src0 * v_alpha))); + v_store(dst + x + 2, ((v_load(dst + x + 2) * v_beta) + (v_src1 * v_alpha))); } } return x; } }; -#endif +#endif //CV_SIMD128_64F +#endif //CV_SIMD128 #if CV_SIMD128 template <> @@ -742,7 +718,7 @@ struct Acc_SIMD len *= cn; for ( ; x <= len - 16; x += 16) { - v_uint8x16 v_src = v_load((const uchar*)(src + x)); + v_uint8x16 v_src = v_load(src + x); v_uint16x8 v_src0, v_src1; v_expand(v_src, v_src0, v_src1); @@ -762,9 +738,9 @@ struct Acc_SIMD for ( ; x <= len - 16; x += 16) { - v_uint8x16 v_mask = v_load((const uchar*)(mask + x)); + v_uint8x16 v_mask = v_load(mask + x); v_mask = ~(v_0 == v_mask); - v_uint8x16 v_src = v_load((const uchar*)(src + x)); + v_uint8x16 v_src = v_load(src + x); v_src = v_src & v_mask; v_uint16x8 v_src0, v_src1; v_expand(v_src, v_src0, v_src1); @@ -795,7 +771,7 @@ struct Acc_SIMD len *= cn; for ( ; x <= len - 8; x += 8) { - v_uint16x8 v_src = v_load((const ushort*)(src + x)); + v_uint16x8 v_src = v_load(src + x); v_uint32x4 v_src0, v_src1; v_expand(v_src, v_src0, v_src1); @@ -808,7 +784,7 @@ struct Acc_SIMD } }; -#if CV_SSE2 +#if CV_SIMD128_64F template <> struct Acc_SIMD { @@ -818,52 +794,52 @@ struct Acc_SIMD if (!mask) { - __m128i v_0 = _mm_setzero_si128(); len *= cn; for ( ; x <= len - 16; x += 16) { - __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); - __m128i v_int0 = _mm_unpacklo_epi8(v_src, v_0); - __m128i v_int1 = _mm_unpackhi_epi8(v_src, v_0); - __m128i v_int00 = _mm_unpacklo_epi16(v_int0, v_0); - __m128i v_int01 = _mm_unpackhi_epi16(v_int0, v_0); - __m128i v_int10 = _mm_unpacklo_epi16(v_int1, v_0); - __m128i v_int11 = _mm_unpackhi_epi16(v_int1, v_0); - __m128d v_src0 = _mm_cvtepi32_pd(v_int00); - __m128d v_src1 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int00, _MM_SHUFFLE(0, 0, 3, 2))); - __m128d v_src2 = _mm_cvtepi32_pd(v_int01); - __m128d v_src3 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int01, _MM_SHUFFLE(0, 0, 3, 2))); - __m128d v_src4 = _mm_cvtepi32_pd(v_int10); - __m128d v_src5 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int10, _MM_SHUFFLE(0, 0, 3, 2))); - __m128d v_src6 = _mm_cvtepi32_pd(v_int11); - __m128d v_src7 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int11, _MM_SHUFFLE(0, 0, 3, 2))); + v_uint8x16 v_src = v_load(src + x); + v_uint16x8 v_int0, v_int1; + v_expand(v_src, v_int0, v_int1); - __m128d v_dst0 = _mm_loadu_pd(dst + x); - __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); - __m128d v_dst2 = _mm_loadu_pd(dst + x + 4); - __m128d v_dst3 = _mm_loadu_pd(dst + x + 6); - __m128d v_dst4 = _mm_loadu_pd(dst + x + 8); - __m128d v_dst5 = _mm_loadu_pd(dst + x + 10); - __m128d v_dst6 = _mm_loadu_pd(dst + x + 12); - __m128d v_dst7 = _mm_loadu_pd(dst + x + 14); + v_uint32x4 v_int00, v_int01, v_int10, v_int11; + v_expand(v_int0, v_int00, v_int01); + v_expand(v_int1, v_int10, v_int11); - v_dst0 = _mm_add_pd(v_dst0, v_src0); - v_dst1 = _mm_add_pd(v_dst1, v_src1); - v_dst2 = _mm_add_pd(v_dst2, v_src2); - v_dst3 = _mm_add_pd(v_dst3, v_src3); - v_dst4 = _mm_add_pd(v_dst4, v_src4); - v_dst5 = _mm_add_pd(v_dst5, v_src5); - v_dst6 = _mm_add_pd(v_dst6, v_src6); - v_dst7 = _mm_add_pd(v_dst7, v_src7); + v_float64x2 v_src0 = v_cvt_f64(v_reinterpret_as_s32(v_int00)); + v_float64x2 v_src1 = v_cvt_f64_high(v_reinterpret_as_s32(v_int00)); + v_float64x2 v_src2 = v_cvt_f64(v_reinterpret_as_s32(v_int01)); + v_float64x2 v_src3 = v_cvt_f64_high(v_reinterpret_as_s32(v_int01)); + v_float64x2 v_src4 = v_cvt_f64(v_reinterpret_as_s32(v_int10)); + v_float64x2 v_src5 = v_cvt_f64_high(v_reinterpret_as_s32(v_int10)); + v_float64x2 v_src6 = v_cvt_f64(v_reinterpret_as_s32(v_int11)); + v_float64x2 v_src7 = v_cvt_f64_high(v_reinterpret_as_s32(v_int11)); - _mm_storeu_pd(dst + x, v_dst0); - _mm_storeu_pd(dst + x + 2, v_dst1); - _mm_storeu_pd(dst + x + 4, v_dst2); - _mm_storeu_pd(dst + x + 6, v_dst3); - _mm_storeu_pd(dst + x + 8, v_dst4); - _mm_storeu_pd(dst + x + 10, v_dst5); - _mm_storeu_pd(dst + x + 12, v_dst6); - _mm_storeu_pd(dst + x + 14, v_dst7); + v_float64x2 v_dst0 = v_load(dst + x); + v_float64x2 v_dst1 = v_load(dst + x + 2); + v_float64x2 v_dst2 = v_load(dst + x + 4); + v_float64x2 v_dst3 = v_load(dst + x + 6); + v_float64x2 v_dst4 = v_load(dst + x + 8); + v_float64x2 v_dst5 = v_load(dst + x + 10); + v_float64x2 v_dst6 = v_load(dst + x + 12); + v_float64x2 v_dst7 = v_load(dst + x + 14); + + v_dst0 = v_dst0 + v_src0; + v_dst1 = v_dst1 + v_src1; + v_dst2 = v_dst2 + v_src2; + v_dst3 = v_dst3 + v_src3; + v_dst4 = v_dst4 + v_src4; + v_dst5 = v_dst5 + v_src5; + v_dst6 = v_dst6 + v_src6; + v_dst7 = v_dst7 + v_src7; + + v_store(dst + x, v_dst0); + v_store(dst + x + 2, v_dst1); + v_store(dst + x + 4, v_dst2); + v_store(dst + x + 6, v_dst3); + v_store(dst + x + 8, v_dst4); + v_store(dst + x + 10, v_dst5); + v_store(dst + x + 12, v_dst6); + v_store(dst + x + 14, v_dst7); } } return x; @@ -879,32 +855,32 @@ struct Acc_SIMD if (!mask) { - __m128i v_0 = _mm_setzero_si128(); len *= cn; for ( ; x <= len - 8; x += 8) { - __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); - __m128i v_int0 = _mm_unpacklo_epi16(v_src, v_0); - __m128i v_int1 = _mm_unpackhi_epi16(v_src, v_0); - __m128d v_src0 = _mm_cvtepi32_pd(v_int0); - __m128d v_src1 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int0, _MM_SHUFFLE(0, 0, 3, 2))); - __m128d v_src2 = _mm_cvtepi32_pd(v_int1); - __m128d v_src3 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int1, _MM_SHUFFLE(0, 0, 3, 2))); + v_uint16x8 v_src = v_load(src + x); + v_uint32x4 v_int0, v_int1; + v_expand(v_src, v_int0, v_int1); - __m128d v_dst0 = _mm_loadu_pd(dst + x); - __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); - __m128d v_dst2 = _mm_loadu_pd(dst + x + 4); - __m128d v_dst3 = _mm_loadu_pd(dst + x + 6); + v_float64x2 v_src0 = v_cvt_f64(v_reinterpret_as_s32(v_int0)); + v_float64x2 v_src1 = v_cvt_f64_high(v_reinterpret_as_s32(v_int0)); + v_float64x2 v_src2 = v_cvt_f64(v_reinterpret_as_s32(v_int1)); + v_float64x2 v_src3 = v_cvt_f64_high(v_reinterpret_as_s32(v_int1)); - v_dst0 = _mm_add_pd(v_dst0, v_src0); - v_dst1 = _mm_add_pd(v_dst1, v_src1); - v_dst2 = _mm_add_pd(v_dst2, v_src2); - v_dst3 = _mm_add_pd(v_dst3, v_src3); + v_float64x2 v_dst0 = v_load(dst + x); + v_float64x2 v_dst1 = v_load(dst + x + 2); + v_float64x2 v_dst2 = v_load(dst + x + 4); + v_float64x2 v_dst3 = v_load(dst + x + 6); - _mm_storeu_pd(dst + x, v_dst0); - _mm_storeu_pd(dst + x + 2, v_dst1); - _mm_storeu_pd(dst + x + 4, v_dst2); - _mm_storeu_pd(dst + x + 6, v_dst3); + v_dst0 = v_dst0 + v_src0; + v_dst1 = v_dst1 + v_src1; + v_dst2 = v_dst2 + v_src2; + v_dst3 = v_dst3 + v_src3; + + v_store(dst + x, v_dst0); + v_store(dst + x + 2, v_dst1); + v_store(dst + x + 4, v_dst2); + v_store(dst + x + 6, v_dst3); } } return x; @@ -924,7 +900,7 @@ struct AccSqr_SIMD len *= cn; for ( ; x <= len - 16; x += 16) { - v_uint8x16 v_src = v_load((const uchar*)(src + x)); + v_uint8x16 v_src = v_load(src + x); v_uint16x8 v_src0, v_src1; v_expand(v_src, v_src0, v_src1); v_src0 = v_src0 * v_src0; @@ -945,9 +921,9 @@ struct AccSqr_SIMD v_uint8x16 v_0 = v_setall_u8(0); for ( ; x <= len - 16; x += 16) { - v_uint8x16 v_mask = v_load((const uchar*)(mask + x)); + v_uint8x16 v_mask = v_load(mask + x); v_mask = ~(v_0 == v_mask); - v_uint8x16 v_src = v_load((const uchar*)(src + x)); + v_uint8x16 v_src = v_load(src + x); v_src = v_src & v_mask; v_uint16x8 v_src0, v_src1; v_expand(v_src, v_src0, v_src1); @@ -981,7 +957,7 @@ struct AccSqr_SIMD len *= cn; for ( ; x <= len - 8; x += 8) { - v_uint16x8 v_src = v_load((const ushort*)(src + x)); + v_uint16x8 v_src = v_load(src + x); v_uint32x4 v_src0, v_src1; v_expand(v_src, v_src0, v_src1); @@ -1000,7 +976,7 @@ struct AccSqr_SIMD } }; -#if CV_SSE2 +#if CV_SIMD128_64F template <> struct AccSqr_SIMD { @@ -1010,37 +986,39 @@ struct AccSqr_SIMD if (!mask) { - __m128i v_0 = _mm_setzero_si128(); len *= cn; for ( ; x <= len - 8; x += 8) { - __m128i v_src = _mm_loadl_epi64((const __m128i*)(src + x)); - __m128i v_int = _mm_unpacklo_epi8(v_src, v_0); - __m128i v_int0 = _mm_unpacklo_epi16(v_int, v_0); - __m128i v_int1 = _mm_unpackhi_epi16(v_int, v_0); - __m128d v_src0 = _mm_cvtepi32_pd(v_int0); - __m128d v_src1 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int0, _MM_SHUFFLE(0, 0, 3, 2))); - __m128d v_src2 = _mm_cvtepi32_pd(v_int1); - __m128d v_src3 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int1, _MM_SHUFFLE(0, 0, 3, 2))); - v_src0 = _mm_mul_pd(v_src0, v_src0); - v_src1 = _mm_mul_pd(v_src1, v_src1); - v_src2 = _mm_mul_pd(v_src2, v_src2); - v_src3 = _mm_mul_pd(v_src3, v_src3); + v_uint8x16 v_src = v_load(src + x); + v_uint16x8 v_int, dummy; + v_expand(v_src, v_int, dummy); - __m128d v_dst0 = _mm_loadu_pd(dst + x); - __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); - __m128d v_dst2 = _mm_loadu_pd(dst + x + 4); - __m128d v_dst3 = _mm_loadu_pd(dst + x + 6); + v_uint32x4 v_int0, v_int1; + v_expand(v_int, v_int0, v_int1); - v_dst0 = _mm_add_pd(v_dst0, v_src0); - v_dst1 = _mm_add_pd(v_dst1, v_src1); - v_dst2 = _mm_add_pd(v_dst2, v_src2); - v_dst3 = _mm_add_pd(v_dst3, v_src3); + v_float64x2 v_src0 = v_cvt_f64(v_reinterpret_as_s32(v_int0)); + v_float64x2 v_src1 = v_cvt_f64_high(v_reinterpret_as_s32(v_int0)); + v_float64x2 v_src2 = v_cvt_f64(v_reinterpret_as_s32(v_int1)); + v_float64x2 v_src3 = v_cvt_f64_high(v_reinterpret_as_s32(v_int1)); + v_src0 = v_src0 * v_src0; + v_src1 = v_src1 * v_src1; + v_src2 = v_src2 * v_src2; + v_src3 = v_src3 * v_src3; - _mm_storeu_pd(dst + x, v_dst0); - _mm_storeu_pd(dst + x + 2, v_dst1); - _mm_storeu_pd(dst + x + 4, v_dst2); - _mm_storeu_pd(dst + x + 6, v_dst3); + v_float64x2 v_dst0 = v_load(dst + x); + v_float64x2 v_dst1 = v_load(dst + x + 2); + v_float64x2 v_dst2 = v_load(dst + x + 4); + v_float64x2 v_dst3 = v_load(dst + x + 6); + + v_dst0 += v_src0; + v_dst1 += v_src1; + v_dst2 += v_src2; + v_dst3 += v_src3; + + v_store(dst + x, v_dst0); + v_store(dst + x + 2, v_dst1); + v_store(dst + x + 4, v_dst2); + v_store(dst + x + 6, v_dst3); } } return x; @@ -1056,36 +1034,39 @@ struct AccSqr_SIMD if (!mask) { - __m128i v_0 = _mm_setzero_si128(); len *= cn; for ( ; x <= len - 8; x += 8) { - __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); - __m128i v_int0 = _mm_unpacklo_epi16(v_src, v_0); - __m128i v_int1 = _mm_unpackhi_epi16(v_src, v_0); - __m128d v_src0 = _mm_cvtepi32_pd(v_int0); - __m128d v_src1 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int0, _MM_SHUFFLE(0, 0, 3, 2))); - __m128d v_src2 = _mm_cvtepi32_pd(v_int1); - __m128d v_src3 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int1, _MM_SHUFFLE(0, 0, 3, 2))); - v_src0 = _mm_mul_pd(v_src0, v_src0); - v_src1 = _mm_mul_pd(v_src1, v_src1); - v_src2 = _mm_mul_pd(v_src2, v_src2); - v_src3 = _mm_mul_pd(v_src3, v_src3); + v_uint16x8 v_src = v_load(src + x); + v_uint32x4 v_int_0, v_int_1; + v_expand(v_src, v_int_0, v_int_1); - __m128d v_dst0 = _mm_loadu_pd(dst + x); - __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); - __m128d v_dst2 = _mm_loadu_pd(dst + x + 4); - __m128d v_dst3 = _mm_loadu_pd(dst + x + 6); + v_int32x4 v_int0 = v_reinterpret_as_s32(v_int_0); + v_int32x4 v_int1 = v_reinterpret_as_s32(v_int_1); - v_dst0 = _mm_add_pd(v_dst0, v_src0); - v_dst1 = _mm_add_pd(v_dst1, v_src1); - v_dst2 = _mm_add_pd(v_dst2, v_src2); - v_dst3 = _mm_add_pd(v_dst3, v_src3); + v_float64x2 v_src0 = v_cvt_f64(v_int0); + v_float64x2 v_src1 = v_cvt_f64_high(v_int0); + v_float64x2 v_src2 = v_cvt_f64(v_int1); + v_float64x2 v_src3 = v_cvt_f64_high(v_int1); + v_src0 = v_src0 * v_src0; + v_src1 = v_src1 * v_src1; + v_src2 = v_src2 * v_src2; + v_src3 = v_src3 * v_src3; - _mm_storeu_pd(dst + x, v_dst0); - _mm_storeu_pd(dst + x + 2, v_dst1); - _mm_storeu_pd(dst + x + 4, v_dst2); - _mm_storeu_pd(dst + x + 6, v_dst3); + v_float64x2 v_dst0 = v_load(dst + x); + v_float64x2 v_dst1 = v_load(dst + x + 2); + v_float64x2 v_dst2 = v_load(dst + x + 4); + v_float64x2 v_dst3 = v_load(dst + x + 6); + + v_dst0 += v_src0; + v_dst1 += v_src1; + v_dst2 += v_src2; + v_dst3 += v_src3; + + v_store(dst + x, v_dst0); + v_store(dst + x + 2, v_dst1); + v_store(dst + x + 4, v_dst2); + v_store(dst + x + 6, v_dst3); } } return x; @@ -1227,7 +1208,7 @@ struct AccProd_SIMD } }; -#if CV_SSE2 +#if CV_SIMD128_64F template <> struct AccProd_SIMD { @@ -1237,38 +1218,44 @@ struct AccProd_SIMD if (!mask) { - __m128i v_0 = _mm_setzero_si128(); len *= cn; for ( ; x <= len - 8; x += 8) { - __m128i v_1src = _mm_loadl_epi64((const __m128i*)(src1 + x)); - __m128i v_2src = _mm_loadl_epi64((const __m128i*)(src2 + x)); + v_uint8x16 v_1src = v_load(src1 + x); + v_uint8x16 v_2src = v_load(src2 + x); - __m128i v_1int = _mm_unpacklo_epi8(v_1src, v_0); - __m128i v_2int = _mm_unpacklo_epi8(v_2src, v_0); - __m128i v_1int0 = _mm_unpacklo_epi16(v_1int, v_0); - __m128i v_1int1 = _mm_unpackhi_epi16(v_1int, v_0); - __m128i v_2int0 = _mm_unpacklo_epi16(v_2int, v_0); - __m128i v_2int1 = _mm_unpackhi_epi16(v_2int, v_0); - __m128d v_src0 = _mm_mul_pd(_mm_cvtepi32_pd(v_1int0),_mm_cvtepi32_pd(v_2int0)); - __m128d v_src1 = _mm_mul_pd(_mm_cvtepi32_pd(_mm_shuffle_epi32(v_1int0, _MM_SHUFFLE(0, 0, 3, 2))),_mm_cvtepi32_pd(_mm_shuffle_epi32(v_2int0, _MM_SHUFFLE(0, 0, 3, 2)))); - __m128d v_src2 = _mm_mul_pd(_mm_cvtepi32_pd(v_1int1),_mm_cvtepi32_pd(v_2int1)); - __m128d v_src3 = _mm_mul_pd(_mm_cvtepi32_pd(_mm_shuffle_epi32(v_1int1, _MM_SHUFFLE(0, 0, 3, 2))),_mm_cvtepi32_pd(_mm_shuffle_epi32(v_2int1, _MM_SHUFFLE(0, 0, 3, 2)))); + v_uint16x8 v_1int, v_2int, dummy; + v_expand(v_1src, v_1int, dummy); + v_expand(v_2src, v_2int, dummy); - __m128d v_dst0 = _mm_loadu_pd(dst + x); - __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); - __m128d v_dst2 = _mm_loadu_pd(dst + x + 4); - __m128d v_dst3 = _mm_loadu_pd(dst + x + 6); + v_uint32x4 v_1int_0, v_1int_1, v_2int_0, v_2int_1; + v_expand(v_1int, v_1int_0, v_1int_1); + v_expand(v_2int, v_2int_0, v_2int_1); - v_dst0 = _mm_add_pd(v_dst0, v_src0); - v_dst1 = _mm_add_pd(v_dst1, v_src1); - v_dst2 = _mm_add_pd(v_dst2, v_src2); - v_dst3 = _mm_add_pd(v_dst3, v_src3); + v_int32x4 v_1int0 = v_reinterpret_as_s32(v_1int_0); + v_int32x4 v_1int1 = v_reinterpret_as_s32(v_1int_1); + v_int32x4 v_2int0 = v_reinterpret_as_s32(v_2int_0); + v_int32x4 v_2int1 = v_reinterpret_as_s32(v_2int_1); - _mm_storeu_pd(dst + x, v_dst0); - _mm_storeu_pd(dst + x + 2, v_dst1); - _mm_storeu_pd(dst + x + 4, v_dst2); - _mm_storeu_pd(dst + x + 6, v_dst3); + v_float64x2 v_src0 = v_cvt_f64(v_1int0) * v_cvt_f64(v_2int0); + v_float64x2 v_src1 = v_cvt_f64_high(v_1int0) * v_cvt_f64_high(v_2int0); + v_float64x2 v_src2 = v_cvt_f64(v_1int1) * v_cvt_f64(v_2int1); + v_float64x2 v_src3 = v_cvt_f64_high(v_1int1) * v_cvt_f64_high(v_2int1); + + v_float64x2 v_dst0 = v_load(dst + x); + v_float64x2 v_dst1 = v_load(dst + x + 2); + v_float64x2 v_dst2 = v_load(dst + x + 4); + v_float64x2 v_dst3 = v_load(dst + x + 6); + + v_dst0 += v_src0; + v_dst1 += v_src1; + v_dst2 += v_src2; + v_dst3 += v_src3; + + v_store(dst + x, v_dst0); + v_store(dst + x + 2, v_dst1); + v_store(dst + x + 4, v_dst2); + v_store(dst + x + 6, v_dst3); } } return x; @@ -1284,35 +1271,40 @@ struct AccProd_SIMD if (!mask) { - __m128i v_0 = _mm_setzero_si128(); len *= cn; for ( ; x <= len - 8; x += 8) { - __m128i v_1src = _mm_loadu_si128((const __m128i*)(src1 + x)); - __m128i v_2src = _mm_loadu_si128((const __m128i*)(src2 + x)); - __m128i v_1int0 = _mm_unpacklo_epi16(v_1src, v_0); - __m128i v_1int1 = _mm_unpackhi_epi16(v_1src, v_0); - __m128i v_2int0 = _mm_unpacklo_epi16(v_2src, v_0); - __m128i v_2int1 = _mm_unpackhi_epi16(v_2src, v_0); - __m128d v_src0 = _mm_mul_pd(_mm_cvtepi32_pd(v_1int0),_mm_cvtepi32_pd(v_2int0)); - __m128d v_src1 = _mm_mul_pd(_mm_cvtepi32_pd(_mm_shuffle_epi32(v_1int0, _MM_SHUFFLE(0, 0, 3, 2))),_mm_cvtepi32_pd(_mm_shuffle_epi32(v_2int0, _MM_SHUFFLE(0, 0, 3, 2)))); - __m128d v_src2 = _mm_mul_pd(_mm_cvtepi32_pd(v_1int1),_mm_cvtepi32_pd(v_2int1)); - __m128d v_src3 = _mm_mul_pd(_mm_cvtepi32_pd(_mm_shuffle_epi32(v_1int1, _MM_SHUFFLE(0, 0, 3, 2))),_mm_cvtepi32_pd(_mm_shuffle_epi32(v_2int1, _MM_SHUFFLE(0, 0, 3, 2)))); + v_uint16x8 v_1src = v_load(src1 + x); + v_uint16x8 v_2src = v_load(src2 + x); - __m128d v_dst0 = _mm_loadu_pd(dst + x); - __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); - __m128d v_dst2 = _mm_loadu_pd(dst + x + 4); - __m128d v_dst3 = _mm_loadu_pd(dst + x + 6); + v_uint32x4 v_1int_0, v_1int_1, v_2int_0, v_2int_1; + v_expand(v_1src, v_1int_0, v_1int_1); + v_expand(v_2src, v_2int_0, v_2int_1); - v_dst0 = _mm_add_pd(v_dst0, v_src0); - v_dst1 = _mm_add_pd(v_dst1, v_src1); - v_dst2 = _mm_add_pd(v_dst2, v_src2); - v_dst3 = _mm_add_pd(v_dst3, v_src3); + v_int32x4 v_1int0 = v_reinterpret_as_s32(v_1int_0); + v_int32x4 v_1int1 = v_reinterpret_as_s32(v_1int_1); + v_int32x4 v_2int0 = v_reinterpret_as_s32(v_2int_0); + v_int32x4 v_2int1 = v_reinterpret_as_s32(v_2int_1); - _mm_storeu_pd(dst + x, v_dst0); - _mm_storeu_pd(dst + x + 2, v_dst1); - _mm_storeu_pd(dst + x + 4, v_dst2); - _mm_storeu_pd(dst + x + 6, v_dst3); + v_float64x2 v_src0 = v_cvt_f64(v_1int0) * v_cvt_f64(v_2int0); + v_float64x2 v_src1 = v_cvt_f64_high(v_1int0) * v_cvt_f64_high(v_2int0); + v_float64x2 v_src2 = v_cvt_f64(v_1int1) * v_cvt_f64(v_2int1); + v_float64x2 v_src3 = v_cvt_f64_high(v_1int1) * v_cvt_f64_high(v_2int1); + + v_float64x2 v_dst0 = v_load(dst + x); + v_float64x2 v_dst1 = v_load(dst + x + 2); + v_float64x2 v_dst2 = v_load(dst + x + 4); + v_float64x2 v_dst3 = v_load(dst + x + 6); + + v_dst0 = v_dst0 + v_src0; + v_dst1 = v_dst1 + v_src1; + v_dst2 = v_dst2 + v_src2; + v_dst3 = v_dst3 + v_src3; + + v_store(dst + x, v_dst0); + v_store(dst + x + 2, v_dst1); + v_store(dst + x + 4, v_dst2); + v_store(dst + x + 6, v_dst3); } } return x; @@ -1399,45 +1391,50 @@ struct AccW_SIMD } }; -#if CV_SSE2 +#if CV_SIMD128_64F template <> struct AccW_SIMD { int operator() (const uchar * src, double * dst, const uchar * mask, int len, int cn, double alpha) const { int x = 0; - __m128d v_alpha = _mm_set1_pd(alpha); - __m128d v_beta = _mm_set1_pd(1.0f - alpha); - __m128i v_0 = _mm_setzero_si128(); + v_float64x2 v_alpha = v_setall_f64(alpha); + v_float64x2 v_beta = v_setall_f64(1.0f - alpha); if (!mask) { len *= cn; for ( ; x <= len - 8; x += 8) { - __m128i v_src = _mm_loadl_epi64((const __m128i*)(src + x)); - __m128i v_int = _mm_unpacklo_epi8(v_src, v_0); - __m128i v_int0 = _mm_unpacklo_epi16(v_int, v_0); - __m128i v_int1 = _mm_unpackhi_epi16(v_int, v_0); - __m128d v_src0 = _mm_cvtepi32_pd(v_int0); - __m128d v_src1 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int0, _MM_SHUFFLE(0, 0, 3, 2))); - __m128d v_src2 = _mm_cvtepi32_pd(v_int1); - __m128d v_src3 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int1, _MM_SHUFFLE(0, 0, 3, 2))); + v_uint8x16 v_src = v_load(src + x); + v_uint16x8 v_int, dummy; + v_expand(v_src, v_int, dummy); - __m128d v_dst0 = _mm_loadu_pd(dst + x); - __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); - __m128d v_dst2 = _mm_loadu_pd(dst + x + 4); - __m128d v_dst3 = _mm_loadu_pd(dst + x + 6); + v_uint32x4 v_int_0, v_int_1; + v_expand(v_int, v_int_0, v_int_1); - v_dst0 = _mm_add_pd(_mm_mul_pd(v_dst0, v_beta), _mm_mul_pd(v_src0, v_alpha)); - v_dst1 = _mm_add_pd(_mm_mul_pd(v_dst1, v_beta), _mm_mul_pd(v_src1, v_alpha)); - v_dst2 = _mm_add_pd(_mm_mul_pd(v_dst2, v_beta), _mm_mul_pd(v_src2, v_alpha)); - v_dst3 = _mm_add_pd(_mm_mul_pd(v_dst3, v_beta), _mm_mul_pd(v_src3, v_alpha)); + v_int32x4 v_int0 = v_reinterpret_as_s32(v_int_0); + v_int32x4 v_int1 = v_reinterpret_as_s32(v_int_1); - _mm_storeu_pd(dst + x, v_dst0); - _mm_storeu_pd(dst + x + 2, v_dst1); - _mm_storeu_pd(dst + x + 4, v_dst2); - _mm_storeu_pd(dst + x + 6, v_dst3); + v_float64x2 v_src0 = v_cvt_f64(v_int0); + v_float64x2 v_src1 = v_cvt_f64_high(v_int0); + v_float64x2 v_src2 = v_cvt_f64(v_int1); + v_float64x2 v_src3 = v_cvt_f64_high(v_int1); + + v_float64x2 v_dst0 = v_load(dst + x); + v_float64x2 v_dst1 = v_load(dst + x + 2); + v_float64x2 v_dst2 = v_load(dst + x + 4); + v_float64x2 v_dst3 = v_load(dst + x + 6); + + v_dst0 = (v_dst0 * v_beta) + (v_src0 * v_alpha); + v_dst1 = (v_dst1 * v_beta) + (v_src1 * v_alpha); + v_dst2 = (v_dst2 * v_beta) + (v_src2 * v_alpha); + v_dst3 = (v_dst3 * v_beta) + (v_src3 * v_alpha); + + v_store(dst + x, v_dst0); + v_store(dst + x + 2, v_dst1); + v_store(dst + x + 4, v_dst2); + v_store(dst + x + 6, v_dst3); } } @@ -1451,44 +1448,47 @@ struct AccW_SIMD int operator() (const ushort * src, double * dst, const uchar * mask, int len, int cn, double alpha) const { int x = 0; - __m128d v_alpha = _mm_set1_pd(alpha); - __m128d v_beta = _mm_set1_pd(1.0f - alpha); - __m128i v_0 = _mm_setzero_si128(); + v_float64x2 v_alpha = v_setall_f64(alpha); + v_float64x2 v_beta = v_setall_f64(1.0f - alpha); if (!mask) { len *= cn; for ( ; x <= len - 8; x += 8) { - __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); - __m128i v_int0 = _mm_unpacklo_epi16(v_src, v_0); - __m128i v_int1 = _mm_unpackhi_epi16(v_src, v_0); - __m128d v_src00 = _mm_cvtepi32_pd(v_int0); - __m128d v_src01 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int0, _MM_SHUFFLE(0, 0, 3, 2))); - __m128d v_src10 = _mm_cvtepi32_pd(v_int1); - __m128d v_src11 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int1, _MM_SHUFFLE(0, 0, 3, 2))); + v_uint16x8 v_src = v_load(src + x); + v_uint32x4 v_int_0, v_int_1; + v_expand(v_src, v_int_0, v_int_1); - __m128d v_dst00 = _mm_loadu_pd(dst + x); - __m128d v_dst01 = _mm_loadu_pd(dst + x + 2); - __m128d v_dst10 = _mm_loadu_pd(dst + x + 4); - __m128d v_dst11 = _mm_loadu_pd(dst + x + 6); + v_int32x4 v_int0 = v_reinterpret_as_s32(v_int_0); + v_int32x4 v_int1 = v_reinterpret_as_s32(v_int_1); - v_dst00 = _mm_add_pd(_mm_mul_pd(v_dst00, v_beta), _mm_mul_pd(v_src00, v_alpha)); - v_dst01 = _mm_add_pd(_mm_mul_pd(v_dst01, v_beta), _mm_mul_pd(v_src01, v_alpha)); - v_dst10 = _mm_add_pd(_mm_mul_pd(v_dst10, v_beta), _mm_mul_pd(v_src10, v_alpha)); - v_dst11 = _mm_add_pd(_mm_mul_pd(v_dst11, v_beta), _mm_mul_pd(v_src11, v_alpha)); + v_float64x2 v_src00 = v_cvt_f64(v_int0); + v_float64x2 v_src01 = v_cvt_f64_high(v_int0); + v_float64x2 v_src10 = v_cvt_f64(v_int1); + v_float64x2 v_src11 = v_cvt_f64_high(v_int1); - _mm_storeu_pd(dst + x, v_dst00); - _mm_storeu_pd(dst + x + 2, v_dst01); - _mm_storeu_pd(dst + x + 4, v_dst10); - _mm_storeu_pd(dst + x + 6, v_dst11); + v_float64x2 v_dst00 = v_load(dst + x); + v_float64x2 v_dst01 = v_load(dst + x + 2); + v_float64x2 v_dst10 = v_load(dst + x + 4); + v_float64x2 v_dst11 = v_load(dst + x + 6); + + v_dst00 = (v_dst00 * v_beta) + (v_src00 * v_alpha); + v_dst01 = (v_dst01 * v_beta) + (v_src01 * v_alpha); + v_dst10 = (v_dst10 * v_beta) + (v_src10 * v_alpha); + v_dst11 = (v_dst11 * v_beta) + (v_src11 * v_alpha); + + v_store(dst + x, v_dst00); + v_store(dst + x + 2, v_dst01); + v_store(dst + x + 4, v_dst10); + v_store(dst + x + 6, v_dst11); } } return x; } }; -#endif //CV_SSE2 +#endif //CV_SIMD128_64F #endif //CV_SIMD128 template void From 464d289fa9894f93839c78a47b7f3c1efc971e18 Mon Sep 17 00:00:00 2001 From: Valeriy Van Date: Tue, 30 Aug 2016 23:22:49 +0300 Subject: [PATCH 110/178] Gets rid of magic constant --- modules/imgcodecs/src/ios_conversions.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgcodecs/src/ios_conversions.mm b/modules/imgcodecs/src/ios_conversions.mm index 17fb18e229..eed867a790 100644 --- a/modules/imgcodecs/src/ios_conversions.mm +++ b/modules/imgcodecs/src/ios_conversions.mm @@ -100,7 +100,7 @@ void UIImageToMat(const UIImage* image, CGFloat cols = image.size.width, rows = image.size.height; CGContextRef contextRef; CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast; - if (CGColorSpaceGetModel(colorSpace) == 0) + if (CGColorSpaceGetModel(colorSpace) == kCGColorSpaceModelMonochrome) { m.create(rows, cols, CV_8UC1); // 8 bits per component, 1 channel bitmapInfo = kCGImageAlphaNone; From d2e23008ab3aac136376d223d9870c2435a3a638 Mon Sep 17 00:00:00 2001 From: sourin Date: Wed, 31 Aug 2016 11:29:15 +0530 Subject: [PATCH 111/178] Fixed traincascade read issue --- apps/traincascade/imagestorage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/traincascade/imagestorage.cpp b/apps/traincascade/imagestorage.cpp index 4055350c2e..420d997ee6 100644 --- a/apps/traincascade/imagestorage.cpp +++ b/apps/traincascade/imagestorage.cpp @@ -36,6 +36,7 @@ bool CvCascadeImageReader::NegReader::create( const string _filename, Size _winS while( !file.eof() ) { std::getline(file, str); + str.erase(str.find_last_not_of(" \n\r\t")+1); if (str.empty()) break; if (str.at(0) == '#' ) continue; /* comment */ imgFilenames.push_back(str); From a986db56c6af5d32393fde23cc4e1b09c9a4f29c Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 1 Sep 2016 15:17:32 +0300 Subject: [PATCH 112/178] cmake: update matlab path --- cmake/OpenCVFindMatlab.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/OpenCVFindMatlab.cmake b/cmake/OpenCVFindMatlab.cmake index 65ad965c3d..ffe8857fec 100644 --- a/cmake/OpenCVFindMatlab.cmake +++ b/cmake/OpenCVFindMatlab.cmake @@ -62,7 +62,7 @@ function(locate_matlab_root) # possible root locations, in order of likelihood set(SEARCH_DIRS_ /Applications /usr/local /opt/local /usr /opt) foreach (DIR_ ${SEARCH_DIRS_}) - file(GLOB MATLAB_ROOT_DIR_ ${DIR_}/MATLAB/R*) + file(GLOB MATLAB_ROOT_DIR_ ${DIR_}/MATLAB/R* ${DIR_}/MATLAB_R*) if (MATLAB_ROOT_DIR_) # sort in order from highest to lowest # normally it's in the format MATLAB_R[20XX][A/B] From dc704d77ac51e1b727031f7dc1e9c0b3d7075741 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 31 Aug 2016 23:12:52 +0300 Subject: [PATCH 113/178] Fixed several GCC 5.x warnings --- 3rdparty/libtiff/CMakeLists.txt | 2 +- cmake/OpenCVCompilerOptions.cmake | 1 + modules/core/include/opencv2/core/utility.hpp | 2 +- modules/core/perf/perf_umat.cpp | 3 - modules/core/test/test_ds.cpp | 2 +- .../features2d/include/opencv2/features2d.hpp | 2 +- modules/flann/include/opencv2/flann.hpp | 262 ++++++++---------- 7 files changed, 121 insertions(+), 153 deletions(-) diff --git a/3rdparty/libtiff/CMakeLists.txt b/3rdparty/libtiff/CMakeLists.txt index 13971f16ab..7a5b34c611 100644 --- a/3rdparty/libtiff/CMakeLists.txt +++ b/3rdparty/libtiff/CMakeLists.txt @@ -95,7 +95,7 @@ ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4267 /wd4305 /wd4306) # vs2008 Win64 ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4703) # vs2012 ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4456 /wd4457 /wd4312) # vs2015 -ocv_warnings_disable(CMAKE_C_FLAGS /wd4267 /wd4244 /wd4018) +ocv_warnings_disable(CMAKE_C_FLAGS /wd4267 /wd4244 /wd4018 /wd4311 /wd4312) if(UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR CV_ICC)) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake index 350eb8c48c..cce57a9364 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -97,6 +97,7 @@ if(CMAKE_COMPILER_IS_GNUCXX) add_extra_compiler_option(-Wno-narrowing) add_extra_compiler_option(-Wno-delete-non-virtual-dtor) add_extra_compiler_option(-Wno-unnamed-type-template-args) + add_extra_compiler_option(-Wno-comment) endif() add_extra_compiler_option(-fdiagnostics-show-option) diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index ba1f5c3c74..3bf6975643 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -1126,7 +1126,7 @@ CV_EXPORTS InstrNode* getTrace(); CV_EXPORTS void resetTrace(); CV_EXPORTS void setFlags(int modeFlags); CV_EXPORTS int getFlags(); -}; +} } //namespace cv diff --git a/modules/core/perf/perf_umat.cpp b/modules/core/perf/perf_umat.cpp index ddeaa7abc7..2f45b792cb 100644 --- a/modules/core/perf/perf_umat.cpp +++ b/modules/core/perf/perf_umat.cpp @@ -13,7 +13,6 @@ using namespace ::testing; using std::tr1::tuple; using std::tr1::get; -namespace { struct OpenCLState { @@ -64,5 +63,3 @@ OCL_PERF_TEST_P(UMatTest, CustomPtr, Combine(Values(sz1080p, sz2160p), Bool(), : SANITY_CHECK_NOTHING(); } - -} // namespace cvtest diff --git a/modules/core/test/test_ds.cpp b/modules/core/test/test_ds.cpp index def3fe20eb..b97b9d8d2d 100644 --- a/modules/core/test/test_ds.cpp +++ b/modules/core/test/test_ds.cpp @@ -56,7 +56,7 @@ static void cvTsSimpleSeqShiftAndCopy( CvTsSimpleSeq* seq, int from_idx, int to_ (seq->count - from_idx)*elem_size ); } seq->count += to_idx - from_idx; - if( elem && to_idx > from_idx ) + if( elem ) memcpy( seq->array + from_idx*elem_size, elem, (to_idx - from_idx)*elem_size ); } diff --git a/modules/features2d/include/opencv2/features2d.hpp b/modules/features2d/include/opencv2/features2d.hpp index 4d362923ce..264090b07c 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -1022,7 +1022,7 @@ protected: /** @brief Flann-based descriptor matcher. -This matcher trains flann::Index_ on a train descriptor collection and calls its nearest search +This matcher trains cv::flann::Index on a train descriptor collection and calls its nearest search methods to find the best matches. So, this matcher may be faster when matching a large train collection than the brute force matcher. FlannBasedMatcher does not support masking permissible matches of descriptor sets because flann::Index does not support this. : diff --git a/modules/flann/include/opencv2/flann.hpp b/modules/flann/include/opencv2/flann.hpp index 4f92d57e3e..b647766cce 100644 --- a/modules/flann/include/opencv2/flann.hpp +++ b/modules/flann/include/opencv2/flann.hpp @@ -338,164 +338,134 @@ int GenericIndex::radiusSearch(const Mat& query, Mat& indices, Mat& di * @deprecated Use GenericIndex class instead */ template -class -#ifndef _MSC_VER - FLANN_DEPRECATED -#endif - Index_ { +class Index_ +{ public: - typedef typename L2::ElementType ElementType; - typedef typename L2::ResultType DistanceType; + typedef typename L2::ElementType ElementType; + typedef typename L2::ResultType DistanceType; - Index_(const Mat& features, const ::cvflann::IndexParams& params); - - ~Index_(); - - void knnSearch(const std::vector& query, std::vector& indices, std::vector& dists, int knn, const ::cvflann::SearchParams& params); - void knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& params); - - int radiusSearch(const std::vector& query, std::vector& indices, std::vector& dists, DistanceType radius, const ::cvflann::SearchParams& params); - int radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& params); - - void save(String filename) - { - if (nnIndex_L1) nnIndex_L1->save(filename); - if (nnIndex_L2) nnIndex_L2->save(filename); - } - - int veclen() const + FLANN_DEPRECATED Index_(const Mat& dataset, const ::cvflann::IndexParams& params) { - if (nnIndex_L1) return nnIndex_L1->veclen(); - if (nnIndex_L2) return nnIndex_L2->veclen(); - } + printf("[WARNING] The cv::flann::Index_ class is deperecated, use cv::flann::GenericIndex instead\n"); - int size() const + CV_Assert(dataset.type() == CvType::type()); + CV_Assert(dataset.isContinuous()); + ::cvflann::Matrix m_dataset((ElementType*)dataset.ptr(0), dataset.rows, dataset.cols); + + if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L2 ) { + nnIndex_L1 = NULL; + nnIndex_L2 = new ::cvflann::Index< L2 >(m_dataset, params); + } + else if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L1 ) { + nnIndex_L1 = new ::cvflann::Index< L1 >(m_dataset, params); + nnIndex_L2 = NULL; + } + else { + printf("[ERROR] cv::flann::Index_ only provides backwards compatibility for the L1 and L2 distances. " + "For other distance types you must use cv::flann::GenericIndex\n"); + CV_Assert(0); + } + if (nnIndex_L1) nnIndex_L1->buildIndex(); + if (nnIndex_L2) nnIndex_L2->buildIndex(); + } + FLANN_DEPRECATED ~Index_() { - if (nnIndex_L1) return nnIndex_L1->size(); - if (nnIndex_L2) return nnIndex_L2->size(); - } + if (nnIndex_L1) delete nnIndex_L1; + if (nnIndex_L2) delete nnIndex_L2; + } - ::cvflann::IndexParams getParameters() - { - if (nnIndex_L1) return nnIndex_L1->getParameters(); - if (nnIndex_L2) return nnIndex_L2->getParameters(); + FLANN_DEPRECATED void knnSearch(const std::vector& query, std::vector& indices, std::vector& dists, int knn, const ::cvflann::SearchParams& searchParams) + { + ::cvflann::Matrix m_query((ElementType*)&query[0], 1, query.size()); + ::cvflann::Matrix m_indices(&indices[0], 1, indices.size()); + ::cvflann::Matrix m_dists(&dists[0], 1, dists.size()); - } + if (nnIndex_L1) nnIndex_L1->knnSearch(m_query,m_indices,m_dists,knn,searchParams); + if (nnIndex_L2) nnIndex_L2->knnSearch(m_query,m_indices,m_dists,knn,searchParams); + } + FLANN_DEPRECATED void knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& searchParams) + { + CV_Assert(queries.type() == CvType::type()); + CV_Assert(queries.isContinuous()); + ::cvflann::Matrix m_queries((ElementType*)queries.ptr(0), queries.rows, queries.cols); - FLANN_DEPRECATED const ::cvflann::IndexParams* getIndexParameters() - { - if (nnIndex_L1) return nnIndex_L1->getIndexParameters(); - if (nnIndex_L2) return nnIndex_L2->getIndexParameters(); - } + CV_Assert(indices.type() == CV_32S); + CV_Assert(indices.isContinuous()); + ::cvflann::Matrix m_indices((int*)indices.ptr(0), indices.rows, indices.cols); + + CV_Assert(dists.type() == CvType::type()); + CV_Assert(dists.isContinuous()); + ::cvflann::Matrix m_dists((DistanceType*)dists.ptr(0), dists.rows, dists.cols); + + if (nnIndex_L1) nnIndex_L1->knnSearch(m_queries,m_indices,m_dists,knn, searchParams); + if (nnIndex_L2) nnIndex_L2->knnSearch(m_queries,m_indices,m_dists,knn, searchParams); + } + + FLANN_DEPRECATED int radiusSearch(const std::vector& query, std::vector& indices, std::vector& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams) + { + ::cvflann::Matrix m_query((ElementType*)&query[0], 1, query.size()); + ::cvflann::Matrix m_indices(&indices[0], 1, indices.size()); + ::cvflann::Matrix m_dists(&dists[0], 1, dists.size()); + + if (nnIndex_L1) return nnIndex_L1->radiusSearch(m_query,m_indices,m_dists,radius,searchParams); + if (nnIndex_L2) return nnIndex_L2->radiusSearch(m_query,m_indices,m_dists,radius,searchParams); + } + + FLANN_DEPRECATED int radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams) + { + CV_Assert(query.type() == CvType::type()); + CV_Assert(query.isContinuous()); + ::cvflann::Matrix m_query((ElementType*)query.ptr(0), query.rows, query.cols); + + CV_Assert(indices.type() == CV_32S); + CV_Assert(indices.isContinuous()); + ::cvflann::Matrix m_indices((int*)indices.ptr(0), indices.rows, indices.cols); + + CV_Assert(dists.type() == CvType::type()); + CV_Assert(dists.isContinuous()); + ::cvflann::Matrix m_dists((DistanceType*)dists.ptr(0), dists.rows, dists.cols); + + if (nnIndex_L1) return nnIndex_L1->radiusSearch(m_query,m_indices,m_dists,radius,searchParams); + if (nnIndex_L2) return nnIndex_L2->radiusSearch(m_query,m_indices,m_dists,radius,searchParams); + } + + FLANN_DEPRECATED void save(String filename) + { + if (nnIndex_L1) nnIndex_L1->save(filename); + if (nnIndex_L2) nnIndex_L2->save(filename); + } + + FLANN_DEPRECATED int veclen() const + { + if (nnIndex_L1) return nnIndex_L1->veclen(); + if (nnIndex_L2) return nnIndex_L2->veclen(); + } + + FLANN_DEPRECATED int size() const + { + if (nnIndex_L1) return nnIndex_L1->size(); + if (nnIndex_L2) return nnIndex_L2->size(); + } + + FLANN_DEPRECATED ::cvflann::IndexParams getParameters() + { + if (nnIndex_L1) return nnIndex_L1->getParameters(); + if (nnIndex_L2) return nnIndex_L2->getParameters(); + + } + + FLANN_DEPRECATED const ::cvflann::IndexParams* getIndexParameters() + { + if (nnIndex_L1) return nnIndex_L1->getIndexParameters(); + if (nnIndex_L2) return nnIndex_L2->getIndexParameters(); + } private: - // providing backwards compatibility for L2 and L1 distances (most common) - ::cvflann::Index< L2 >* nnIndex_L2; - ::cvflann::Index< L1 >* nnIndex_L1; + // providing backwards compatibility for L2 and L1 distances (most common) + ::cvflann::Index< L2 >* nnIndex_L2; + ::cvflann::Index< L1 >* nnIndex_L1; }; -#ifdef _MSC_VER -template -class FLANN_DEPRECATED Index_; -#endif - -//! @cond IGNORED - -template -Index_::Index_(const Mat& dataset, const ::cvflann::IndexParams& params) -{ - printf("[WARNING] The cv::flann::Index_ class is deperecated, use cv::flann::GenericIndex instead\n"); - - CV_Assert(dataset.type() == CvType::type()); - CV_Assert(dataset.isContinuous()); - ::cvflann::Matrix m_dataset((ElementType*)dataset.ptr(0), dataset.rows, dataset.cols); - - if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L2 ) { - nnIndex_L1 = NULL; - nnIndex_L2 = new ::cvflann::Index< L2 >(m_dataset, params); - } - else if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L1 ) { - nnIndex_L1 = new ::cvflann::Index< L1 >(m_dataset, params); - nnIndex_L2 = NULL; - } - else { - printf("[ERROR] cv::flann::Index_ only provides backwards compatibility for the L1 and L2 distances. " - "For other distance types you must use cv::flann::GenericIndex\n"); - CV_Assert(0); - } - if (nnIndex_L1) nnIndex_L1->buildIndex(); - if (nnIndex_L2) nnIndex_L2->buildIndex(); -} - -template -Index_::~Index_() -{ - if (nnIndex_L1) delete nnIndex_L1; - if (nnIndex_L2) delete nnIndex_L2; -} - -template -void Index_::knnSearch(const std::vector& query, std::vector& indices, std::vector& dists, int knn, const ::cvflann::SearchParams& searchParams) -{ - ::cvflann::Matrix m_query((ElementType*)&query[0], 1, query.size()); - ::cvflann::Matrix m_indices(&indices[0], 1, indices.size()); - ::cvflann::Matrix m_dists(&dists[0], 1, dists.size()); - - if (nnIndex_L1) nnIndex_L1->knnSearch(m_query,m_indices,m_dists,knn,searchParams); - if (nnIndex_L2) nnIndex_L2->knnSearch(m_query,m_indices,m_dists,knn,searchParams); -} - - -template -void Index_::knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& searchParams) -{ - CV_Assert(queries.type() == CvType::type()); - CV_Assert(queries.isContinuous()); - ::cvflann::Matrix m_queries((ElementType*)queries.ptr(0), queries.rows, queries.cols); - - CV_Assert(indices.type() == CV_32S); - CV_Assert(indices.isContinuous()); - ::cvflann::Matrix m_indices((int*)indices.ptr(0), indices.rows, indices.cols); - - CV_Assert(dists.type() == CvType::type()); - CV_Assert(dists.isContinuous()); - ::cvflann::Matrix m_dists((DistanceType*)dists.ptr(0), dists.rows, dists.cols); - - if (nnIndex_L1) nnIndex_L1->knnSearch(m_queries,m_indices,m_dists,knn, searchParams); - if (nnIndex_L2) nnIndex_L2->knnSearch(m_queries,m_indices,m_dists,knn, searchParams); -} - -template -int Index_::radiusSearch(const std::vector& query, std::vector& indices, std::vector& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams) -{ - ::cvflann::Matrix m_query((ElementType*)&query[0], 1, query.size()); - ::cvflann::Matrix m_indices(&indices[0], 1, indices.size()); - ::cvflann::Matrix m_dists(&dists[0], 1, dists.size()); - - if (nnIndex_L1) return nnIndex_L1->radiusSearch(m_query,m_indices,m_dists,radius,searchParams); - if (nnIndex_L2) return nnIndex_L2->radiusSearch(m_query,m_indices,m_dists,radius,searchParams); -} - -template -int Index_::radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams) -{ - CV_Assert(query.type() == CvType::type()); - CV_Assert(query.isContinuous()); - ::cvflann::Matrix m_query((ElementType*)query.ptr(0), query.rows, query.cols); - - CV_Assert(indices.type() == CV_32S); - CV_Assert(indices.isContinuous()); - ::cvflann::Matrix m_indices((int*)indices.ptr(0), indices.rows, indices.cols); - - CV_Assert(dists.type() == CvType::type()); - CV_Assert(dists.isContinuous()); - ::cvflann::Matrix m_dists((DistanceType*)dists.ptr(0), dists.rows, dists.cols); - - if (nnIndex_L1) return nnIndex_L1->radiusSearch(m_query,m_indices,m_dists,radius,searchParams); - if (nnIndex_L2) return nnIndex_L2->radiusSearch(m_query,m_indices,m_dists,radius,searchParams); -} - -//! @endcond /** @brief Clusters features using hierarchical k-means algorithm. From 33359639878b7cfb553387c75dc43896d2aaa0fb Mon Sep 17 00:00:00 2001 From: Stephane Thiell Date: Thu, 1 Sep 2016 12:07:32 -0700 Subject: [PATCH 114/178] cmake: add support for Nvidia GPU Tesla K80 --- cmake/OpenCVDetectCUDA.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/OpenCVDetectCUDA.cmake b/cmake/OpenCVDetectCUDA.cmake index de17cee30c..70b11eb532 100644 --- a/cmake/OpenCVDetectCUDA.cmake +++ b/cmake/OpenCVDetectCUDA.cmake @@ -65,7 +65,7 @@ if(CUDA_FOUND) if(CUDA_GENERATION STREQUAL "Fermi") set(__cuda_arch_bin "2.0") elseif(CUDA_GENERATION STREQUAL "Kepler") - set(__cuda_arch_bin "3.0 3.5") + set(__cuda_arch_bin "3.0 3.5 3.7") elseif(CUDA_GENERATION STREQUAL "Maxwell") set(__cuda_arch_bin "5.0") elseif(CUDA_GENERATION STREQUAL "Pascal") @@ -92,9 +92,9 @@ if(CUDA_FOUND) set(__cuda_arch_ptx "") else() if(${CUDA_VERSION} VERSION_LESS "8.0") - set(__cuda_arch_bin "2.0 3.0 3.5 5.0") + set(__cuda_arch_bin "2.0 3.0 3.5 3.7 5.0") else() - set(__cuda_arch_bin "2.0 3.0 3.5 5.0 6.0") + set(__cuda_arch_bin "2.0 3.0 3.5 3.7 5.0 6.0") endif() set(__cuda_arch_ptx "") endif() From e06a9e900912769ba2a7df98f71725553ae38896 Mon Sep 17 00:00:00 2001 From: Matthew Cook Date: Fri, 26 Aug 2016 15:18:35 +1200 Subject: [PATCH 115/178] Fix android libc++ build --- 3rdparty/carotene/src/common.hpp | 1 + platforms/android/android.toolchain.cmake | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/3rdparty/carotene/src/common.hpp b/3rdparty/carotene/src/common.hpp index e46231a58a..823ddf1ccf 100644 --- a/3rdparty/carotene/src/common.hpp +++ b/3rdparty/carotene/src/common.hpp @@ -41,6 +41,7 @@ #define CAROTENE_SRC_COMMON_HPP #include +#include #include #if defined WITH_NEON && (defined __ARM_NEON__ || defined __ARM_NEON) diff --git a/platforms/android/android.toolchain.cmake b/platforms/android/android.toolchain.cmake index e0b4bf8d65..1d69b7504a 100644 --- a/platforms/android/android.toolchain.cmake +++ b/platforms/android/android.toolchain.cmake @@ -1048,8 +1048,7 @@ if( BUILD_WITH_ANDROID_NDK ) set( ANDROID_RTTI ON ) set( __libstl "${ANDROID_NDK}/sources/cxx-stl/llvm-libc++" ) set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libc++_static.a" ) - set( __libgnustl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) - set( ANDROID_STL_INCLUDE_DIRS "${__libgnustl}/include" "${__libgnustl}/libs/${ANDROID_NDK_ABI_NAME}/include" "${__libgnustl}/include/backward" ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/android/support/include" "${ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libcxx/include" "${ANDROID_NDK}/sources/cxx-stl/llvm-libc++abi/libcxxabi/include" ) else() message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" ) endif() From f773f45d906cd55ee8917f3bf6d3a38cd6efc27d Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Fri, 2 Sep 2016 14:36:34 +0300 Subject: [PATCH 116/178] Updated HAL interface for separable filters to address that both kernels are vectors. --- 3rdparty/carotene/hal/tegra_hal.hpp | 18 ++++----- .../include/opencv2/imgproc/hal/hal.hpp | 6 +-- modules/imgproc/src/filter.cpp | 38 ++++++++++--------- modules/imgproc/src/hal_replacement.hpp | 10 ++--- 4 files changed, 35 insertions(+), 37 deletions(-) diff --git a/3rdparty/carotene/hal/tegra_hal.hpp b/3rdparty/carotene/hal/tegra_hal.hpp index 401f521a64..37e7472282 100644 --- a/3rdparty/carotene/hal/tegra_hal.hpp +++ b/3rdparty/carotene/hal/tegra_hal.hpp @@ -1178,12 +1178,12 @@ struct SepFilterCtx CAROTENE_NS::BORDER_MODE border; }; inline int TEGRA_SEPFILTERINIT(cvhalFilter2D **context, int src_type, int dst_type, int kernel_type, - uchar *kernelx_data, size_t , int kernelx_width, int kernelx_height, - uchar *kernely_data, size_t kernely_step, int kernely_width, int kernely_height, + uchar *kernelx_data, int kernelx_length, + uchar *kernely_data, int kernely_length, int anchor_x, int anchor_y, double delta, int borderType) { if(!context || !kernelx_data || !kernely_data || src_type != CV_8UC1 || dst_type != CV_16SC1 || - !(kernelx_width == 3 && kernelx_height == 1) || !(kernely_width == 1 && kernely_height == 3) || + kernelx_length != 3 || kernely_length != 3 || delta != 0 || anchor_x != 1 || anchor_y != 1) return CV_HAL_ERROR_NOT_IMPLEMENTED; @@ -1225,24 +1225,24 @@ inline int TEGRA_SEPFILTERINIT(cvhalFilter2D **context, int src_type, int dst_ty ctx->kernelx_data[1]=kernelx_data[1]; ctx->kernelx_data[2]=kernelx_data[2]; ctx->kernely_data[0]=kernely_data[0]; - ctx->kernely_data[1]=kernely_data[kernely_step]; - ctx->kernely_data[2]=kernely_data[2*kernely_step]; + ctx->kernely_data[1]=kernely_data[1]; + ctx->kernely_data[2]=kernely_data[2]; break; case CV_8SC1: ctx->kernelx_data[0]=((char*)kernelx_data)[0]; ctx->kernelx_data[1]=((char*)kernelx_data)[1]; ctx->kernelx_data[2]=((char*)kernelx_data)[2]; ctx->kernely_data[0]=((char*)kernely_data)[0]; - ctx->kernely_data[1]=((char*)(kernely_data+kernely_step))[0]; - ctx->kernely_data[2]=((char*)(kernely_data+2*kernely_step))[0]; + ctx->kernely_data[1]=((char*)kernely_data)[1]; + ctx->kernely_data[2]=((char*)kernely_data)[2]; break; case CV_16UC1: ctx->kernelx_data[0]=((int16_t*)kernelx_data)[0]; ctx->kernelx_data[1]=((int16_t*)kernelx_data)[1]; ctx->kernelx_data[2]=((int16_t*)kernelx_data)[2]; ctx->kernely_data[0]=((int16_t*)kernely_data)[0]; - ctx->kernely_data[1]=((int16_t*)(kernely_data+kernely_step))[0]; - ctx->kernely_data[2]=((int16_t*)(kernely_data+2*kernely_step))[0]; + ctx->kernely_data[1]=((int16_t*)kernely_data)[1]; + ctx->kernely_data[2]=((int16_t*)kernely_data)[2]; default: delete ctx; return CV_HAL_ERROR_NOT_IMPLEMENTED; diff --git a/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp b/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp index 0943a2dfa2..23ed10c88d 100644 --- a/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp +++ b/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp @@ -30,10 +30,8 @@ struct CV_EXPORTS Filter2D struct CV_EXPORTS SepFilter2D { static Ptr create(int stype, int dtype, int ktype, - uchar * kernelx_data, size_t kernelx_step, - int kernelx_width, int kernelx_height, - uchar * kernely_data, size_t kernely_step, - int kernely_width, int kernely_height, + uchar * kernelx_data, int kernelx_len, + uchar * kernely_data, int kernely_len, int anchor_x, int anchor_y, double delta, int borderType); virtual void apply(uchar * src_data, size_t src_step, diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 3bd5cd0f1e..68a168f617 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -4823,13 +4823,13 @@ struct ReplacementSepFilter : public hal::SepFilter2D bool isInitialized; ReplacementSepFilter() : ctx(0), isInitialized(false) {} bool init(int stype, int dtype, int ktype, - uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, - uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, + uchar * kernelx_data, int kernelx_len, + uchar * kernely_data, int kernely_len, int anchor_x, int anchor_y, double delta, int borderType) { int res = cv_hal_sepFilterInit(&ctx, stype, dtype, ktype, - kernelx_data, kernelx_step, kernelx_width, kernelx_height, - kernely_data, kernely_step, kernely_width, kernely_height, + kernelx_data, kernelx_len, + kernely_data, kernely_len, anchor_x, anchor_y, delta, borderType); isInitialized = (res == CV_HAL_ERROR_OK); return isInitialized; @@ -4862,14 +4862,14 @@ struct OcvSepFilter : public hal::SepFilter2D int src_type; int dst_type; bool init(int stype, int dtype, int ktype, - uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, - uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, + uchar * kernelx_data, int kernelx_len, + uchar * kernely_data, int kernely_len, int anchor_x, int anchor_y, double delta, int borderType) { src_type = stype; dst_type = dtype; - Mat kernelX(Size(kernelx_width, kernelx_height), ktype, kernelx_data, kernelx_step); - Mat kernelY(Size(kernely_width, kernely_height), ktype, kernely_data, kernely_step); + Mat kernelX(Size(kernelx_len, 1), ktype, kernelx_data); + Mat kernelY(Size(kernely_len, 1), ktype, kernely_data); f = createSeparableLinearFilter( stype, dtype, kernelX, kernelY, Point(anchor_x, anchor_y), @@ -4958,15 +4958,15 @@ Ptr Filter2D::create(uchar* kernel_data, size_t kernel_step, int //--------------------------------------------------------------- Ptr SepFilter2D::create(int stype, int dtype, int ktype, - uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, - uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, + uchar * kernelx_data, int kernelx_len, + uchar * kernely_data, int kernely_len, int anchor_x, int anchor_y, double delta, int borderType) { { ReplacementSepFilter * impl = new ReplacementSepFilter(); if (impl->init(stype, dtype, ktype, - kernelx_data, kernelx_step, kernelx_width, kernelx_height, - kernely_data, kernely_step, kernely_width, kernely_height, + kernelx_data, kernelx_len, + kernely_data, kernely_len, anchor_x, anchor_y, delta, borderType)) { return Ptr(impl); @@ -4976,8 +4976,8 @@ Ptr SepFilter2D::create(int stype, int dtype, int ktype, { OcvSepFilter * impl = new OcvSepFilter(); impl->init(stype, dtype, ktype, - kernelx_data, kernelx_step, kernelx_width, kernelx_height, - kernely_data, kernely_step, kernely_width, kernely_height, + kernelx_data, kernelx_len, + kernely_data, kernely_len, anchor_x, anchor_y, delta, borderType); return Ptr(impl); } @@ -5041,11 +5041,15 @@ void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, if( (borderType & BORDER_ISOLATED) == 0 ) src.locateROI( wsz, ofs ); - CV_Assert(kernelX.type() == kernelY.type()); + CV_Assert( kernelX.type() == kernelY.type() && + (kernelX.cols == 1 || kernelX.rows == 1) && + (kernelY.cols == 1 || kernelY.rows == 1) ); + Mat contKernelX = kernelX.isContinuous() ? kernelX : kernelX.clone(); + Mat contKernelY = kernelY.isContinuous() ? kernelY : kernelY.clone(); Ptr c = hal::SepFilter2D::create(src.type(), dst.type(), kernelX.type(), - kernelX.data, kernelX.step, kernelX.cols, kernelX.rows, - kernelY.data, kernelY.step, kernelY.cols, kernelY.rows, + contKernelX.data, kernelX.cols + kernelX.rows - 1, + contKernelY.data, kernelY.cols + kernelY.rows - 1, anchor.x, anchor.y, delta, borderType & ~BORDER_ISOLATED); c->apply(src.data, src.step, dst.data, dst.step, dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y); } diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index ecc11fb0b4..fdf3ab72e8 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -140,20 +140,16 @@ inline int hal_ni_filterFree(cvhalFilter2D *context) { return CV_HAL_ERROR_NOT_I @param dst_type destination image type @param kernel_type kernels type @param kernelx_data pointer to x-kernel data - @param kernelx_step x-kernel step - @param kernelx_width x-kernel width - @param kernelx_height x-kernel height + @param kernelx_length x-kernel vector length @param kernely_data pointer to y-kernel data - @param kernely_step y-kernel step - @param kernely_width y-kernel width - @param kernely_height y-kernel height + @param kernely_length y-kernel vector length @param anchor_x relative X position of center point within the kernel @param anchor_y relative Y position of center point within the kernel @param delta added to pixel values @param borderType border processing mode (CV_HAL_BORDER_REFLECT, ...) @sa cv::sepFilter2D, cv::hal::SepFilter2D */ -inline int hal_ni_sepFilterInit(cvhalFilter2D **context, int src_type, int dst_type, int kernel_type, uchar *kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, uchar *kernely_data, size_t kernely_step, int kernely_width, int kernely_height, int anchor_x, int anchor_y, double delta, int borderType) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_sepFilterInit(cvhalFilter2D **context, int src_type, int dst_type, int kernel_type, uchar *kernelx_data, int kernelx_length, uchar *kernely_data, int kernely_length, int anchor_x, int anchor_y, double delta, int borderType) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } /** @brief hal_sepFilter @param context pointer to user-defined context From 62cabb58a99d880a541fea31227189a242d805c3 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Fri, 2 Sep 2016 12:20:32 +0200 Subject: [PATCH 117/178] doxygen: undistortPoints - replace matlab code by latex forumlae --- modules/imgproc/include/opencv2/imgproc.hpp | 33 +++++++++++---------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 71c4f48d12..961f450201 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -2953,20 +2953,23 @@ The function is similar to cv::undistort and cv::initUndistortRectifyMap but it sparse set of points instead of a raster image. Also the function performs a reverse transformation to projectPoints. In case of a 3D object, it does not reconstruct its 3D coordinates, but for a planar object, it does, up to a translation vector, if the proper R is specified. -@code - // (u,v) is the input point, (u', v') is the output point - // camera_matrix=[fx 0 cx; 0 fy cy; 0 0 1] - // P=[fx' 0 cx' tx; 0 fy' cy' ty; 0 0 1 tz] - x" = (u - cx)/fx - y" = (v - cy)/fy - (x',y') = undistort(x",y",dist_coeffs) - [X,Y,W]T = R*[x' y' 1]T - x = X/W, y = Y/W - // only performed if P=[fx' 0 cx' [tx]; 0 fy' cy' [ty]; 0 0 1 [tz]] is specified - u' = x*fx' + cx' - v' = y*fy' + cy', -@endcode -where cv::undistort is an approximate iterative algorithm that estimates the normalized original + +For each observed point coordinate \f$(u, v)\f$ the function computes: +\f[ +\begin{array}{l} +x^{"} \leftarrow (u - c_x)/f_x \\ +y^{"} \leftarrow (v - c_y)/f_y \\ +(x',y') = undistort(x^{"},y^{"}, \texttt{distCoeffs}) \\ +{[X\,Y\,W]} ^T \leftarrow R*[x' \, y' \, 1]^T \\ +x \leftarrow X/W \\ +y \leftarrow Y/W \\ +\text{only performed if P is specified:} \\ +u' \leftarrow x {f'}_x + {c'}_x \\ +v' \leftarrow y {f'}_y + {c'}_y +\end{array} +\f] + +where *undistort* is an approximate iterative algorithm that estimates the normalized original point coordinates out of the normalized distorted point coordinates ("normalized" means that the coordinates do not depend on the camera matrix). @@ -2981,7 +2984,7 @@ transformation. If matrix P is identity or omitted, dst will contain normalized of 4, 5, 8, 12 or 14 elements. If the vector is NULL/empty, the zero distortion coefficients are assumed. @param R Rectification transformation in the object space (3x3 matrix). R1 or R2 computed by cv::stereoRectify can be passed here. If the matrix is empty, the identity transformation is used. -@param P New camera matrix (3x3) or new projection matrix (3x4). P1 or P2 computed by +@param P New camera matrix (3x3) or new projection matrix (3x4) \f$\begin{bmatrix} {f'}_x & 0 & {c'}_x & t_x \\ 0 & {f'}_y & {c'}_y & t_y \\ 0 & 0 & 1 & t_z \end{bmatrix}\f$. P1 or P2 computed by cv::stereoRectify can be passed here. If the matrix is empty, the identity new camera matrix is used. */ CV_EXPORTS_W void undistortPoints( InputArray src, OutputArray dst, From cfcf8abbb6589cf5e9926f73f78ce8c16d8eba30 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Fri, 2 Sep 2016 12:21:08 +0200 Subject: [PATCH 118/178] doxygen: imgproc - underscores should not be escaped in texttt --- modules/imgproc/include/opencv2/imgproc.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 961f450201..58553de732 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -2296,13 +2296,13 @@ The function converts a pair of maps for remap from one representation to anothe options ( (map1.type(), map2.type()) \f$\rightarrow\f$ (dstmap1.type(), dstmap2.type()) ) are supported: -- \f$\texttt{(CV\_32FC1, CV\_32FC1)} \rightarrow \texttt{(CV\_16SC2, CV\_16UC1)}\f$. This is the +- \f$\texttt{(CV_32FC1, CV_32FC1)} \rightarrow \texttt{(CV_16SC2, CV_16UC1)}\f$. This is the most frequently used conversion operation, in which the original floating-point maps (see remap ) are converted to a more compact and much faster fixed-point representation. The first output array contains the rounded coordinates and the second array (created only when nninterpolation=false ) contains indices in the interpolation tables. -- \f$\texttt{(CV\_32FC2)} \rightarrow \texttt{(CV\_16SC2, CV\_16UC1)}\f$. The same as above but +- \f$\texttt{(CV_32FC2)} \rightarrow \texttt{(CV_16SC2, CV_16UC1)}\f$. The same as above but the original maps are stored in one 2-channel matrix. - Reverse conversion. Obviously, the reconstructed floating-point maps will not be exactly the same @@ -2352,7 +2352,7 @@ CV_EXPORTS Mat getPerspectiveTransform( const Point2f src[], const Point2f dst[] The function calculates the \f$2 \times 3\f$ matrix of an affine transform so that: -\f[\begin{bmatrix} x'_i \\ y'_i \end{bmatrix} = \texttt{map\_matrix} \cdot \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix}\f] +\f[\begin{bmatrix} x'_i \\ y'_i \end{bmatrix} = \texttt{map_matrix} \cdot \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix}\f] where @@ -2382,7 +2382,7 @@ CV_EXPORTS_W void invertAffineTransform( InputArray M, OutputArray iM ); The function calculates the \f$3 \times 3\f$ matrix of a perspective transform so that: -\f[\begin{bmatrix} t_i x'_i \\ t_i y'_i \\ t_i \end{bmatrix} = \texttt{map\_matrix} \cdot \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix}\f] +\f[\begin{bmatrix} t_i x'_i \\ t_i y'_i \\ t_i \end{bmatrix} = \texttt{map_matrix} \cdot \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix}\f] where From aaa335b617123309a89a38d74c1c71d97e8ee22c Mon Sep 17 00:00:00 2001 From: catree Date: Sun, 4 Sep 2016 04:17:15 +0200 Subject: [PATCH 119/178] Add the possibility to use a video stream with the peopledetect.cpp sample. Fixed video input argument. --- samples/cpp/peopledetect.cpp | 118 ++++++++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 28 deletions(-) diff --git a/samples/cpp/peopledetect.cpp b/samples/cpp/peopledetect.cpp index e14d07c1b1..aca05fd0ca 100644 --- a/samples/cpp/peopledetect.cpp +++ b/samples/cpp/peopledetect.cpp @@ -1,27 +1,23 @@ +#include +#include #include #include #include -#include +#include +#include +#include using namespace cv; using namespace std; -static void help() -{ - cout << "\nThis program demonstrates the use of the HoG descriptor using\n" - " HOGDescriptor::hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());\n" - "Usage:\n" - "./peopledetect --i= | --d=\n\n" - "During execution:\n\tHit q or ESC key to quit.\n" - "\tUsing OpenCV version " << CV_VERSION << "\n" << endl; -} - const char* keys = { - "{help h||}" - "{image i| ../data/basketball2.png|input image name}" - "{directory d||images directory}" + "{ help h | | print help message }" + "{ image i | | specify input image}" + "{ camera c | | enable camera capturing }" + "{ video v | ../data/768x576.avi | use video as input }" + "{ directory d | | images directory}" }; static void detectAndDraw(const HOGDescriptor &hog, Mat &img) @@ -69,7 +65,12 @@ int main(int argc, char** argv) if (parser.has("help")) { - help(); + cout << "\nThis program demonstrates the use of the HoG descriptor using\n" + " HOGDescriptor::hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());\n"; + parser.printMessage(); + cout << "During execution:\n\tHit q or ESC key to quit.\n" + "\tUsing OpenCV version " << CV_VERSION << "\n" + "Note: camera device number must be different from -1.\n" << endl; return 0; } @@ -78,6 +79,8 @@ int main(int argc, char** argv) namedWindow("people detector", 1); string pattern_glob = ""; + string video_filename = "../data/768x576.avi"; + int camera_id = -1; if (parser.has("directory")) { pattern_glob = parser.get("directory"); @@ -86,26 +89,85 @@ int main(int argc, char** argv) { pattern_glob = parser.get("image"); } - - if (!pattern_glob.empty()) + else if (parser.has("camera")) { + camera_id = parser.get("camera"); + } + else if (parser.has("video")) + { + video_filename = parser.get("video"); + } + + if (!pattern_glob.empty() || camera_id != -1 || !video_filename.empty()) + { + //Read from input image files vector filenames; - String folder(pattern_glob); - glob(folder, filenames); + //Read from video file + VideoCapture vc; + Mat frame; - for (vector::const_iterator it = filenames.begin(); it != filenames.end(); ++it) + if (!pattern_glob.empty()) { - cout << "\nRead: " << *it << endl; - // Read current image - Mat current_image = imread(*it); + String folder(pattern_glob); + glob(folder, filenames); + } + else if (camera_id != -1) + { + vc.open(camera_id); + if (!vc.isOpened()) + { + stringstream msg; + msg << "can't open camera: " << camera_id; + throw runtime_error(msg.str()); + } + } + else + { + vc.open(video_filename.c_str()); + if (!vc.isOpened()) + throw runtime_error(string("can't open video file: " + video_filename)); + } - if (current_image.empty()) - continue; + vector::const_iterator it_image = filenames.begin(); - detectAndDraw(hog, current_image); + for (;;) + { + if (!pattern_glob.empty()) + { + bool read_image_ok = false; + for (; it_image != filenames.end(); ++it_image) + { + cout << "\nRead: " << *it_image << endl; + // Read current image + frame = imread(*it_image); - imshow("people detector", current_image); - int c = waitKey(0) & 255; + if (!frame.empty()) + { + ++it_image; + read_image_ok = true; + break; + } + } + + //No more valid images + if (!read_image_ok) + { + //Release the image in order to exit the while loop + frame.release(); + } + } + else + { + vc >> frame; + } + + if (frame.empty()) + break; + + detectAndDraw(hog, frame); + + imshow("people detector", frame); + int c = waitKey( vc.isOpened() ? 30 : 0 ) & 255; if ( c == 'q' || c == 'Q' || c == 27) break; } From 903789f7afc7fd88e28c9bc62cdbbe00e911b972 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Fri, 2 Sep 2016 21:57:46 +0900 Subject: [PATCH 120/178] use universal intrinsic for FP16 * use v_float16x4 (universal intrinsic) instead of raw SSE/NEON implementation * define v_load_f16/v_store_f16 since v_load can't be distinguished when short pointer passed * brush up implementation on old compiler (guard correctly) * add test for v_load_f16 and round trip conversion of v_float16x4 * fix conversion error --- .../include/opencv2/core/hal/intrin_neon.hpp | 51 ++++++++++++++++++ .../include/opencv2/core/hal/intrin_sse.hpp | 39 ++++++++++++++ modules/core/src/convert.cpp | 42 +++------------ modules/core/test/test_intrin.cpp | 53 +++++++++++++++++++ 4 files changed, 149 insertions(+), 36 deletions(-) diff --git a/modules/core/include/opencv2/core/hal/intrin_neon.hpp b/modules/core/include/opencv2/core/hal/intrin_neon.hpp index e5a42aa723..dd5e2e91db 100644 --- a/modules/core/include/opencv2/core/hal/intrin_neon.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_neon.hpp @@ -275,6 +275,39 @@ struct v_float64x2 }; #endif +#if defined (HAVE_FP16) +// Workaround for old comiplers +template static inline int16x4_t vreinterpret_s16_f16(T a) +{ return (int16x4_t)a; } +template static inline float16x4_t vreinterpret_f16_s16(T a) +{ return (float16x4_t)a; } +template static inline float16x4_t vld1_f16(const T* ptr) +{ return vreinterpret_f16_s16(vld1_s16((const short*)ptr)); } +template static inline void vst1_f16(T* ptr, float16x4_t a) +{ vst1_s16((short*)ptr, vreinterpret_s16_f16(a)); } +static inline short vget_lane_f16(float16x4_t a, int b) +{ return vget_lane_s16(vreinterpret_s16_f16(a), b); } + +struct v_float16x4 +{ + typedef short lane_type; + enum { nlanes = 4 }; + + v_float16x4() {} + explicit v_float16x4(float16x4_t v) : val(v) {} + v_float16x4(short v0, short v1, short v2, short v3) + { + short v[] = {v0, v1, v2, v3}; + val = vld1_f16(v); + } + short get0() const + { + return vget_lane_f16(val, 0); + } + float16x4_t val; +}; +#endif + #define OPENCV_HAL_IMPL_NEON_INIT(_Tpv, _Tp, suffix) \ inline v_##_Tpv v_setzero_##suffix() { return v_##_Tpv(vdupq_n_##suffix((_Tp)0)); } \ inline v_##_Tpv v_setall_##suffix(_Tp v) { return v_##_Tpv(vdupq_n_##suffix(v)); } \ @@ -734,6 +767,14 @@ OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_float32x4, float, f32) OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_float64x2, double, f64) #endif +#if defined (HAVE_FP16) +// Workaround for old comiplers +inline v_float16x4 v_load_f16(const short* ptr) +{ return v_float16x4(vld1_f16(ptr)); } +inline void v_store_f16(short* ptr, v_float16x4& a) +{ vst1_f16(ptr, a.val); } +#endif + #define OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(_Tpvec, scalartype, func, scalar_func) \ inline scalartype v_reduce_##func(const _Tpvec& a) \ { \ @@ -1146,7 +1187,17 @@ inline v_float64x2 v_cvt_f64_high(const v_float32x4& a) } #endif +#if defined (HAVE_FP16) +inline v_float32x4 v_cvt_f32(const v_float16x4& a) +{ + return v_float32x4(vcvt_f32_f16(a.val)); +} +inline v_float16x4 v_cvt_f16(const v_float32x4& a) +{ + return v_float16x4(vcvt_f16_f32(a.val)); +} +#endif //! @endcond diff --git a/modules/core/include/opencv2/core/hal/intrin_sse.hpp b/modules/core/include/opencv2/core/hal/intrin_sse.hpp index 2efd6154cb..3e2ebae68c 100644 --- a/modules/core/include/opencv2/core/hal/intrin_sse.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_sse.hpp @@ -252,6 +252,26 @@ struct v_float64x2 __m128d val; }; +#if defined(HAVE_FP16) +struct v_float16x4 +{ + typedef short lane_type; + enum { nlanes = 4 }; + + v_float16x4() {} + explicit v_float16x4(__m128i v) : val(v) {} + v_float16x4(short v0, short v1, short v2, short v3) + { + val = _mm_setr_epi16(v0, v1, v2, v3, 0, 0, 0, 0); + } + short get0() const + { + return (short)_mm_cvtsi128_si32(val); + } + __m128i val; +}; +#endif + #define OPENCV_HAL_IMPL_SSE_INITVEC(_Tpvec, _Tp, suffix, zsuffix, ssuffix, _Tps, cast) \ inline _Tpvec v_setzero_##suffix() { return _Tpvec(_mm_setzero_##zsuffix()); } \ inline _Tpvec v_setall_##suffix(_Tp v) { return _Tpvec(_mm_set1_##ssuffix((_Tps)v)); } \ @@ -1021,6 +1041,13 @@ inline void v_store_high(_Tp* ptr, const _Tpvec& a) \ OPENCV_HAL_IMPL_SSE_LOADSTORE_FLT_OP(v_float32x4, float, ps) OPENCV_HAL_IMPL_SSE_LOADSTORE_FLT_OP(v_float64x2, double, pd) +#if defined(HAVE_FP16) +inline v_float16x4 v_load_f16(const short* ptr) +{ return v_float16x4(_mm_loadl_epi64((const __m128i*)ptr)); } +inline void v_store_f16(short* ptr, v_float16x4& a) +{ _mm_storel_epi64((__m128i*)ptr, a.val); } +#endif + #define OPENCV_HAL_IMPL_SSE_REDUCE_OP_4(_Tpvec, scalartype, func, scalar_func) \ inline scalartype v_reduce_##func(const _Tpvec& a) \ { \ @@ -1626,6 +1653,18 @@ inline v_float64x2 v_cvt_f64_high(const v_float32x4& a) return v_float64x2(_mm_cvtps_pd(_mm_castsi128_ps(_mm_srli_si128(_mm_castps_si128(a.val),8)))); } +#if defined(HAVE_FP16) +inline v_float32x4 v_cvt_f32(const v_float16x4& a) +{ + return v_float32x4(_mm_cvtph_ps(a.val)); +} + +inline v_float16x4 v_cvt_f16(const v_float32x4& a) +{ + return v_float16x4(_mm_cvtps_ph(a.val, 0)); +} +#endif + //! @endcond } diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 0305785437..c405919f17 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -4537,16 +4537,6 @@ static short convertFp16SW(float fp32) } #endif -#if CV_FP16 && (defined __GNUC__) && (defined __arm__ || defined __aarch64__) - #if 5 <= __GNUC__ - static inline float16x4_t load_f16(const short* p) { return vld1_f16((const float16_t*)p); } - static inline void store_f16(short* p, float16x4_t v) { vst1_f16((float16_t*)p, v); } - #else - static inline float16x4_t load_f16(const short* p) { return (float16x4_t)vld1_s16(p); } - static inline void store_f16(short* p, float16x4_t v) { vst1_s16(p, (int16x4_t)v); } - #endif -#endif - // template for FP16 HW conversion function template static void cvtScaleHalf_( const T* src, size_t sstep, DT* dst, size_t dstep, Size size); @@ -4570,21 +4560,11 @@ cvtScaleHalf_( const float* src, size_t sstep, short* dst, size_t #if CV_FP16 for ( ; x <= size.width - 4; x += 4) { -#if defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86) || defined(i386) - __m128 v_src = _mm_loadu_ps(src + x); + v_float32x4 v_src = v_load(src + x); - __m128i v_dst = _mm_cvtps_ph(v_src, 0); + v_float16x4 v_dst = v_cvt_f16(v_src); - _mm_storel_epi64((__m128i *)(dst + x), v_dst); -#elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) - float32x4_t v_src = vld1q_f32(src + x); - - float16x4_t v_dst = vcvt_f16_f32(v_src); - - store_f16(dst + x, v_dst); -#else -#error "Configuration error" -#endif + v_store_f16(dst + x, v_dst); } #endif } @@ -4626,21 +4606,11 @@ cvtScaleHalf_( const short* src, size_t sstep, float* dst, size_t #if CV_FP16 for ( ; x <= size.width - 4; x += 4) { -#if defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86) || defined(i386) - __m128i v_src = _mm_loadl_epi64((__m128i*)(src+x)); + v_float16x4 v_src = v_load_f16(src + x); - __m128 v_dst = _mm_cvtph_ps(v_src); + v_float32x4 v_dst = v_cvt_f32(v_src); - _mm_storeu_ps(dst + x, v_dst); -#elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) - float16x4_t v_src = load_f16(src+x); - - float32x4_t v_dst = vcvt_f32_f16(v_src); - - vst1q_f32(dst + x, v_dst); -#else -#error "Configuration error" -#endif + v_store(dst + x, v_dst); } #endif } diff --git a/modules/core/test/test_intrin.cpp b/modules/core/test/test_intrin.cpp index e9c8cc4628..d9704ef432 100644 --- a/modules/core/test/test_intrin.cpp +++ b/modules/core/test/test_intrin.cpp @@ -1,3 +1,4 @@ +#include "test_precomp.hpp" #include "test_intrin_utils.hpp" #include @@ -710,6 +711,49 @@ template struct TheTest return *this; } +#if CV_FP16 + TheTest & test_loadstore_fp16() + { + AlignedData data; + AlignedData out; + + // check if addresses are aligned and unaligned respectively + EXPECT_EQ((size_t)0, (size_t)&data.a.d % 16); + EXPECT_NE((size_t)0, (size_t)&data.u.d % 16); + EXPECT_EQ((size_t)0, (size_t)&out.a.d % 16); + EXPECT_NE((size_t)0, (size_t)&out.u.d % 16); + + // check some initialization methods + R r1 = data.u; + R r2 = v_load_f16(data.a.d); + R r3(r2); + EXPECT_EQ(data.u[0], r1.get0()); + EXPECT_EQ(data.a[0], r2.get0()); + EXPECT_EQ(data.a[0], r3.get0()); + + // check some store methods + out.a.clear(); + v_store_f16(out.a.d, r1); + EXPECT_EQ(data.a, out.a); + + return *this; + } + + TheTest & test_float_cvt_fp16() + { + AlignedData data; + + // check conversion + v_float32x4 r1 = v_load(data.a.d); + v_float16x4 r2 = v_cvt_f16(r1); + v_float32x4 r3 = v_cvt_f32(r2); + EXPECT_EQ(0x3c00, r2.get0()); + EXPECT_EQ(r3.get0(), r1.get0()); + + return *this; + } +#endif + }; @@ -915,6 +959,15 @@ TEST(hal_intrin, float64x2) { } #endif +#if CV_FP16 +TEST(hal_intrin, float16x4) { + TheTest() + .test_loadstore_fp16() + .test_float_cvt_fp16() + ; +} +#endif + }; }; From 765dd309818cafbc38af2a3d3e003bb64b42bb1c Mon Sep 17 00:00:00 2001 From: Sergey Alexandrov Date: Mon, 5 Sep 2016 09:27:35 +0200 Subject: [PATCH 121/178] Add support for GpuMat in InputArray::isContinuous() --- modules/core/src/matrix.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index f98155cd3c..a370ec46df 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -1998,6 +1998,9 @@ bool _InputArray::isContinuous(int i) const return vv[i].isContinuous(); } + if( k == CUDA_GPU_MAT ) + return i < 0 ? ((const cuda::GpuMat*)obj)->isContinuous() : true; + CV_Error(CV_StsNotImplemented, "Unknown/unsupported array type"); return false; } From 9e61a28b2e79e8fc65bcc5609206b70ce7a98e1d Mon Sep 17 00:00:00 2001 From: mschoeneck Date: Mon, 5 Sep 2016 12:51:36 +0200 Subject: [PATCH 122/178] Improve canny (#7227) * Improve Canny by using _mm_movemask_epi8 to find next pixel magnitude greater than lower threshold. Added parallelized finalPass to Canny with variable gradients. Little changes in finalPass. * Some things fixed --- modules/imgproc/src/canny.cpp | 234 +++++++++++++++++++++++++++------- 1 file changed, 190 insertions(+), 44 deletions(-) diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 6ef5dee9e8..784b5ffe24 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -525,9 +525,88 @@ public: #define CANNY_SHIFT 15 const int TG22 = (int)(0.4142135623730950488016887242097*(1 << CANNY_SHIFT) + 0.5); - int prev_flag = 0; - bool canny_push = false; - for (int j = 0; j < src.cols; j++) + int prev_flag = 0, j = 0; +#if CV_SSE2 + if (checkHardwareSupport(CPU_SSE2)) + { + __m128i v_low = _mm_set1_epi32(low), v_one = _mm_set1_epi8(1); + + for (; j <= src.cols - 16; j += 16) + { + __m128i v_m1 = _mm_loadu_si128((const __m128i*)(_mag + j)); + __m128i v_m2 = _mm_loadu_si128((const __m128i*)(_mag + j + 4)); + __m128i v_m3 = _mm_loadu_si128((const __m128i*)(_mag + j + 8)); + __m128i v_m4 = _mm_loadu_si128((const __m128i*)(_mag + j + 12)); + + _mm_storeu_si128((__m128i*)(_map + j), v_one); + + __m128i v_cmp1 = _mm_cmpgt_epi32(v_m1, v_low); + __m128i v_cmp2 = _mm_cmpgt_epi32(v_m2, v_low); + __m128i v_cmp3 = _mm_cmpgt_epi32(v_m3, v_low); + __m128i v_cmp4 = _mm_cmpgt_epi32(v_m4, v_low); + + v_cmp1 = _mm_packs_epi32(v_cmp1, v_cmp2); + v_cmp2 = _mm_packs_epi32(v_cmp3, v_cmp4); + + v_cmp1 = _mm_packs_epi16(v_cmp1, v_cmp2); + unsigned int mask = _mm_movemask_epi8(v_cmp1); + + if (mask) + { + int m, k = j; + + for (; mask; ++k, mask >>= 1) + { + if (mask & 0x00000001) + { + m = _mag[k]; + int xs = _x[k]; + int ys = _y[k]; + int x = std::abs(xs); + int y = std::abs(ys) << CANNY_SHIFT; + + int tg22x = x * TG22; + + if (y < tg22x) + { + if (m > _mag[k - 1] && m >= _mag[k + 1]) goto _canny_push_sse; + } + else + { + int tg67x = tg22x + (x << (CANNY_SHIFT + 1)); + if (y > tg67x) + { + if (m > _mag[k + magstep2] && m >= _mag[k + magstep1]) goto _canny_push_sse; + } else + { + int s = (xs ^ ys) < 0 ? -1 : 1; + if (m > _mag[k + magstep2 - s] && m > _mag[k + magstep1 + s]) goto _canny_push_sse; + } + } + } + + prev_flag = 0; + continue; + +_canny_push_sse: + // _map[k-mapstep] is short-circuited at the start because previous thread is + // responsible for initializing it. + if (m > high && !prev_flag && (i <= boundaries.start + 1 || _map[k - mapstep] != 2)) + { + CANNY_PUSH(_map + k); + prev_flag = 1; + } else + _map[k] = 0; + + } + + if (prev_flag && ((k < j+16) || (k < src.cols && _mag[k] <= high))) + prev_flag = 0; + } + } + } +#endif + for (; j < src.cols; j++) { int m = _mag[j]; @@ -542,42 +621,37 @@ public: if (y < tg22x) { - if (m > _mag[j-1] && m >= _mag[j+1]) canny_push = true; + if (m > _mag[j-1] && m >= _mag[j+1]) goto _canny_push; } else { int tg67x = tg22x + (x << (CANNY_SHIFT+1)); if (y > tg67x) { - if (m > _mag[j+magstep2] && m >= _mag[j+magstep1]) canny_push = true; + if (m > _mag[j+magstep2] && m >= _mag[j+magstep1]) goto _canny_push; } else { int s = (xs ^ ys) < 0 ? -1 : 1; - if (m > _mag[j+magstep2-s] && m > _mag[j+magstep1+s]) canny_push = true; + if (m > _mag[j+magstep2-s] && m > _mag[j+magstep1+s]) goto _canny_push; } } } - if (!canny_push) + + prev_flag = 0; + _map[j] = uchar(1); + continue; + +_canny_push: + // _map[j-mapstep] is short-circuited at the start because previous thread is + // responsible for initializing it. + if (!prev_flag && m > high && (i <= boundaries.start+1 || _map[j-mapstep] != 2) ) { - prev_flag = 0; - _map[j] = uchar(1); - continue; + CANNY_PUSH(_map + j); + prev_flag = 1; } else - { - // _map[j-mapstep] is short-circuited at the start because previous thread is - // responsible for initializing it. - if (!prev_flag && m > high && (i <= boundaries.start+1 || _map[j-mapstep] != 2) ) - { - CANNY_PUSH(_map + j); - prev_flag = 1; - } - else - _map[j] = 0; - - canny_push = false; - } + _map[j] = 0; } // scroll the ring buffer @@ -640,8 +714,8 @@ class finalPass : public ParallelLoopBody { public: - finalPass(const Mat & _src, Mat &_dst, uchar *_map, ptrdiff_t _mapstep) : - src(_src), dst(_dst), map(_map), mapstep(_mapstep) {} + finalPass(uchar *_map, Mat &_dst, ptrdiff_t _mapstep) : + map(_map), dst(_dst), mapstep(_mapstep) {} ~finalPass() {} @@ -664,7 +738,7 @@ public: if(haveSSE2) { const __m128i v_zero = _mm_setzero_si128(); - for(; j <= src.cols - 32; j += 32) { + for(; j <= dst.cols - 32; j += 32) { __m128i v_pmap1 = _mm_loadu_si128((const __m128i*)(pmap + j)); __m128i v_pmap2 = _mm_loadu_si128((const __m128i*)(pmap + j + 16)); @@ -688,7 +762,7 @@ public: _mm_storeu_si128((__m128i*)(pdst + j + 16), v_pmap2); } - for(; j <= src.cols - 16; j += 16) { + for(; j <= dst.cols - 16; j += 16) { __m128i v_pmap = _mm_loadu_si128((const __m128i*)(pmap + j)); __m128i v_pmaplo = _mm_unpacklo_epi8(v_pmap, v_zero); @@ -704,15 +778,14 @@ public: } } #endif - for (; j < src.cols; j++) + for (; j < dst.cols; j++) pdst[j] = (uchar)-(pmap[j] >> 1); } } private: - const Mat &src; - Mat &dst; uchar *map; + Mat &dst; ptrdiff_t mapstep; }; @@ -817,7 +890,7 @@ int high = cvFloor(high_thresh); if (!m[mapstep+1]) CANNY_PUSH_SERIAL(m + mapstep + 1); } - parallel_for_(Range(0, src.rows), finalPass(src, dst, map, mapstep), src.total()/(double)(1<<16)); + parallel_for_(Range(0, dst.rows), finalPass(map, dst, mapstep), dst.total()/(double)(1<<16)); } void Canny( InputArray _dx, InputArray _dy, OutputArray _dst, @@ -1032,12 +1105,92 @@ static void CannyImpl(Mat& dx, Mat& dy, Mat& dst, stack_top = stack_bottom + sz; } - int prev_flag = 0; - for (int j = 0; j < cols; j++) - { - #define CANNY_SHIFT 15 - const int TG22 = (int)(0.4142135623730950488016887242097*(1<>= 1) + { + if (mask & 0x00000001) + { + m = _mag[k]; + int xs = _x[k]; + int ys = _y[k]; + int x = std::abs(xs); + int y = std::abs(ys) << CANNY_SHIFT; + + int tg22x = x * TG22; + + if (y < tg22x) + { + if (m > _mag[k - 1] && m >= _mag[k + 1]) goto ocv_canny_push_sse; + } + else + { + int tg67x = tg22x + (x << (CANNY_SHIFT + 1)); + if (y > tg67x) + { + if (m > _mag[k + magstep2] && m >= _mag[k + magstep1]) goto ocv_canny_push_sse; + } else + { + int s = (xs ^ ys) < 0 ? -1 : 1; + if (m > _mag[k + magstep2 - s] && m > _mag[k + magstep1 + s]) goto ocv_canny_push_sse; + } + } + } + + prev_flag = 0; + continue; + +ocv_canny_push_sse: + // _map[k-mapstep] is short-circuited at the start because previous thread is + // responsible for initializing it. + if (!prev_flag && m > high && _map[k-mapstep] != 2) + { + CANNY_PUSH(_map + k); + prev_flag = 1; + } else + _map[k] = 0; + + } + + if (prev_flag && ((k < j+16) || (k < cols && _mag[k] <= high))) + prev_flag = 0; + } + } + } +#endif + for (; j < cols; j++) + { int m = _mag[j]; if (m > low) @@ -1112,14 +1265,7 @@ __ocv_canny_push: if (!m[mapstep+1]) CANNY_PUSH(m + mapstep + 1); } - // the final pass, form the final image - const uchar* pmap = map + mapstep + 1; - uchar* pdst = dst.ptr(); - for (int i = 0; i < rows; i++, pmap += mapstep, pdst += dst.step) - { - for (int j = 0; j < cols; j++) - pdst[j] = (uchar)-(pmap[j] >> 1); - } + parallel_for_(Range(0, dst.rows), finalPass(map, dst, mapstep), dst.total()/(double)(1<<16)); } } // namespace cv From dfe4519c074da92ac7151f90fe875a9c38176ddc Mon Sep 17 00:00:00 2001 From: Vladislav Sovrasov Date: Tue, 23 Aug 2016 16:35:03 +0300 Subject: [PATCH 123/178] Add QR decomposition to HAL --- doc/opencv.bib | 5 + modules/calib3d/include/opencv2/calib3d.hpp | 1 + modules/calib3d/src/calibration.cpp | 3 + modules/core/include/opencv2/core/hal/hal.hpp | 2 + modules/core/src/hal_internal.cpp | 116 +++++++++++++++++ modules/core/src/hal_internal.hpp | 7 + modules/core/src/hal_replacement.hpp | 23 ++++ modules/core/src/lapack.cpp | 26 +++- modules/core/src/matrix_decomp.cpp | 123 ++++++++++++++++++ modules/core/test/test_math.cpp | 47 ++++++- 10 files changed, 348 insertions(+), 5 deletions(-) diff --git a/doc/opencv.bib b/doc/opencv.bib index dea93f8b1f..29a2ae4512 100644 --- a/doc/opencv.bib +++ b/doc/opencv.bib @@ -457,6 +457,11 @@ title = {ROF and TV-L1 denoising with Primal-Dual algorithm}, url = {http://znah.net/rof-and-tv-l1-denoising-with-primal-dual-algorithm.html} } +@MISC{VandLec, + author = {Vandenberghe, Lieven}, + title = {QR Factorization}, + url = {http://www.seas.ucla.edu/~vandenbe/133A/lectures/qr.pdf} +} @ARTICLE{MHT2011, author = {Getreuer, Pascal}, title = {Malvar-He-Cutler Linear Image Demosaicking}, diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index 654cc4d3bc..fcca409e55 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -263,6 +263,7 @@ enum { CALIB_USE_INTRINSIC_GUESS = 0x00001, CALIB_FIX_S1_S2_S3_S4 = 0x10000, CALIB_TILTED_MODEL = 0x40000, CALIB_FIX_TAUX_TAUY = 0x80000, + CALIB_USE_QR = 0x100000, //!< use QR instead of SVD decomposition for solving. Faster but potentially less precise // only for stereo CALIB_FIX_INTRINSIC = 0x00100, CALIB_SAME_FOCAL_LENGTH = 0x00200, diff --git a/modules/calib3d/src/calibration.cpp b/modules/calib3d/src/calibration.cpp index fae4f601d7..0abbee65e0 100644 --- a/modules/calib3d/src/calibration.cpp +++ b/modules/calib3d/src/calibration.cpp @@ -1485,6 +1485,9 @@ static double cvCalibrateCamera2Internal( const CvMat* objectPoints, if(flags & CALIB_USE_LU) { solver.solveMethod = DECOMP_LU; } + else if(flags & CALIB_USE_QR) { + solver.solveMethod = DECOMP_QR; + } { double* param = solver.param->data.db; diff --git a/modules/core/include/opencv2/core/hal/hal.hpp b/modules/core/include/opencv2/core/hal/hal.hpp index f254b58582..63d766585b 100644 --- a/modules/core/include/opencv2/core/hal/hal.hpp +++ b/modules/core/include/opencv2/core/hal/hal.hpp @@ -66,6 +66,8 @@ CV_EXPORTS bool Cholesky32f(float* A, size_t astep, int m, float* b, size_t bste CV_EXPORTS bool Cholesky64f(double* A, size_t astep, int m, double* b, size_t bstep, int n); CV_EXPORTS void SVD32f(float* At, size_t astep, float* W, float* U, size_t ustep, float* Vt, size_t vstep, int m, int n, int flags); CV_EXPORTS void SVD64f(double* At, size_t astep, double* W, double* U, size_t ustep, double* Vt, size_t vstep, int m, int n, int flags); +CV_EXPORTS int QR32f(float* A, size_t astep, int m, int n, int k, float* b, size_t bstep, float* hFactors); +CV_EXPORTS int QR64f(double* A, size_t astep, int m, int n, int k, double* b, size_t bstep, double* hFactors); CV_EXPORTS void gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step, float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, diff --git a/modules/core/src/hal_internal.cpp b/modules/core/src/hal_internal.cpp index 5b83522eed..0c6b7c01f8 100644 --- a/modules/core/src/hal_internal.cpp +++ b/modules/core/src/hal_internal.cpp @@ -61,10 +61,12 @@ #include #include #include +#include #define HAL_GEMM_SMALL_COMPLEX_MATRIX_THRESH 100 #define HAL_GEMM_SMALL_MATRIX_THRESH 100 #define HAL_SVD_SMALL_MATRIX_THRESH 25 +#define HAL_QR_SMALL_MATRIX_THRESH 30 #define HAL_LU_SMALL_MATRIX_THRESH 100 #define HAL_CHOLESKY_SMALL_MATRIX_THRESH 100 @@ -259,6 +261,106 @@ lapack_SVD(fptype* a, size_t a_step, fptype *w, fptype* u, size_t u_step, fptype return CV_HAL_ERROR_OK; } +template static inline int +lapack_QR(fptype* a, size_t a_step, int m, int n, int k, fptype* b, size_t b_step, fptype* dst, int* info) +{ + int lda = a_step / sizeof(fptype); + char mode[] = { 'N', '\0' }; + if(m < n) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + std::vector tmpAMemHolder; + fptype* tmpA; + int ldtmpA; + if (m == n) + { + transpose_square_inplace(a, lda, m); + tmpA = a; + ldtmpA = lda; + } + else + { + tmpAMemHolder.resize(m*n); + tmpA = &tmpAMemHolder.front(); + ldtmpA = m; + transpose(a, lda, tmpA, m, m, n); + } + + int lwork = -1; + fptype work1 = 0.; + + if (b) + { + if (k == 1 && b_step == sizeof(fptype)) + { + if (typeid(fptype) == typeid(float)) + sgels_(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)b, &m, (float*)&work1, &lwork, info); + else if (typeid(fptype) == typeid(double)) + dgels_(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)b, &m, (double*)&work1, &lwork, info); + + lwork = (int)round(work1); //optimal buffer size + std::vector workBufMemHolder(lwork + 1); + fptype* buffer = &workBufMemHolder.front(); + + if (typeid(fptype) == typeid(float)) + sgels_(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)b, &m, (float*)buffer, &lwork, info); + else if (typeid(fptype) == typeid(double)) + dgels_(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)b, &m, (double*)buffer, &lwork, info); + } + else + { + std::vector tmpBMemHolder(m*k); + fptype* tmpB = &tmpBMemHolder.front(); + int ldb = b_step / sizeof(fptype); + transpose(b, ldb, tmpB, m, m, k); + + if (typeid(fptype) == typeid(float)) + sgels_(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)tmpB, &m, (float*)&work1, &lwork, info); + else if (typeid(fptype) == typeid(double)) + dgels_(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)tmpB, &m, (double*)&work1, &lwork, info); + + lwork = (int)round(work1); //optimal buffer size + std::vector workBufMemHolder(lwork + 1); + fptype* buffer = &workBufMemHolder.front(); + + if (typeid(fptype) == typeid(float)) + sgels_(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)tmpB, &m, (float*)buffer, &lwork, info); + else if (typeid(fptype) == typeid(double)) + dgels_(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)tmpB, &m, (double*)buffer, &lwork, info); + + transpose(tmpB, m, b, ldb, k, m); + } + } + else + { + if (typeid(fptype) == typeid(float)) + sgeqrf_(&m, &n, (float*)tmpA, &ldtmpA, (float*)dst, (float*)&work1, &lwork, info); + else if (typeid(fptype) == typeid(double)) + dgeqrf_(&m, &n, (double*)tmpA, &ldtmpA, (double*)dst, (double*)&work1, &lwork, info); + + lwork = (int)round(work1); //optimal buffer size + std::vector workBufMemHolder(lwork + 1); + fptype* buffer = &workBufMemHolder.front(); + + if (typeid(fptype) == typeid(float)) + sgeqrf_(&m, &n, (float*)tmpA, &ldtmpA, (float*)dst, (float*)buffer, &lwork, info); + else if (typeid(fptype) == typeid(double)) + dgeqrf_(&m, &n, (double*)tmpA, &ldtmpA, (double*)dst, (double*)buffer, &lwork, info); + } + + if (m == n) + transpose_square_inplace(a, lda, m); + else + transpose(tmpA, m, a, lda, n, m); + + if (*info != 0) + *info = 0; + else + *info = 1; + + return CV_HAL_ERROR_OK; +} + template static inline int lapack_gemm(const fptype *src1, size_t src1_step, const fptype *src2, size_t src2_step, fptype alpha, const fptype *src3, size_t src3_step, fptype beta, fptype *dst, size_t dst_step, int a_m, int a_n, int d_n, int flags) @@ -459,6 +561,20 @@ int lapack_SVD64f(double* a, size_t a_step, double *w, double* u, size_t u_step, return lapack_SVD(a, a_step, w, u, u_step, vt, v_step, m, n, flags, &info); } +int lapack_QR32f(float* src1, size_t src1_step, int m, int n, int k, float* src2, size_t src2_step, float* dst, int* info) +{ + if (m < HAL_QR_SMALL_MATRIX_THRESH) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + return lapack_QR(src1, src1_step, m, n, k, src2, src2_step, dst, info); +} + +int lapack_QR64f(double* src1, size_t src1_step, int m, int n, int k, double* src2, size_t src2_step, double* dst, int* info) +{ + if (m < HAL_QR_SMALL_MATRIX_THRESH) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + return lapack_QR(src1, src1_step, m, n, k, src2, src2_step, dst, info); +} + int lapack_gemm32f(const float *src1, size_t src1_step, const float *src2, size_t src2_step, float alpha, const float *src3, size_t src3_step, float beta, float *dst, size_t dst_step, int m, int n, int k, int flags) { diff --git a/modules/core/src/hal_internal.hpp b/modules/core/src/hal_internal.hpp index 26bc142e04..129a710145 100644 --- a/modules/core/src/hal_internal.hpp +++ b/modules/core/src/hal_internal.hpp @@ -55,6 +55,8 @@ int lapack_Cholesky32f(float* a, size_t a_step, int m, float* b, size_t b_step, int lapack_Cholesky64f(double* a, size_t a_step, int m, double* b, size_t b_step, int n, bool* info); int lapack_SVD32f(float* a, size_t a_step, float* w, float* u, size_t u_step, float* vt, size_t v_step, int m, int n, int flags); int lapack_SVD64f(double* a, size_t a_step, double* w, double* u, size_t u_step, double* vt, size_t v_step, int m, int n, int flags); +int lapack_QR32f(float* src1, size_t src1_step, int m, int n, int k, float* src2, size_t src2_step, float* dst, int* info); +int lapack_QR64f(double* src1, size_t src1_step, int m, int n, int k, double* src2, size_t src2_step, double* dst, int* info); int lapack_gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step, float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, int m, int n, int k, int flags); @@ -83,6 +85,11 @@ int lapack_gemm64fc(const double* src1, size_t src1_step, const double* src2, si #undef cv_hal_SVD64f #define cv_hal_SVD64f lapack_SVD64f +#undef cv_hal_QR32f +#define cv_hal_QR32f lapack_QR32f +#undef cv_hal_QR64f +#define cv_hal_QR64f lapack_QR64f + #undef cv_hal_gemm32f #define cv_hal_gemm32f lapack_gemm32f #undef cv_hal_gemm64f diff --git a/modules/core/src/hal_replacement.hpp b/modules/core/src/hal_replacement.hpp index 2121261f6d..9a1177e9c2 100644 --- a/modules/core/src/hal_replacement.hpp +++ b/modules/core/src/hal_replacement.hpp @@ -634,6 +634,27 @@ inline int hal_ni_SVD32f(float* src, size_t src_step, float* w, float* u, size_t inline int hal_ni_SVD64f(double* src, size_t src_step, double* w, double* u, size_t u_step, double* vt, size_t vt_step, int m, int n, int flags) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } //! @} +/** +Performs QR decomposition of \f$M\times N\f$(\f$M>N\f$) matrix \f$A = Q*R\f$ and solves matrix equation \f$A*X=B\f$. +@param src1 pointer to input matrix \f$A\f$ stored in row major order. After finish of work src1 contains upper triangular \f$N\times N\f$ matrix \f$R\f$. +Lower triangle of src1 will be filled with vectors of elementary reflectors. See @cite VandLec and Lapack's DGEQRF documentation for details. +@param src1_step number of bytes between two consequent rows of matrix \f$A\f$. +@param m number fo rows in matrix \f$A\f$. +@param n number of columns in matrix \f$A\f$. +@param k number of right-hand vectors in \f$M\times K\f$ matrix \f$B\f$. +@param src2 pointer to \f$M\times K\f$ matrix \f$B\f$ which is the right-hand side of system \f$A*X=B\f$. \f$B\f$ stored in row major order. +If src2 is null pointer only QR decomposition will be performed. Otherwise system will be solved and src1 will be used as temporary buffer, so +after finish of work src2 contains solution \f$X\f$ of system \f$A*X=B\f$. +@param src2_step number of bytes between two consequent rows of matrix \f$B\f$. +@param dst pointer to continiuos \f$N\times 1\f$ array for scalar factors of elementary reflectors. See @cite VandLec for details. +@param info indicates success of decomposition. If *info is zero decomposition failed. +*/ +//! @addtogroup core_hal_interface_decomp_qr QR matrix decomposition +//! @{ +inline int hal_ni_QR32f(float* src1, size_t src1_step, int m, int n, int k, float* src2, size_t src2_step, float* dst, int* info) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_QR64f(double* src1, size_t src1_step, int m, int n, int k, double* src2, size_t src2_step, double* dst, int* info) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +//! @} + //! @cond IGNORED @@ -643,6 +664,8 @@ inline int hal_ni_SVD64f(double* src, size_t src_step, double* w, double* u, siz #define cv_hal_Cholesky64f hal_ni_Cholesky64f #define cv_hal_SVD32f hal_ni_SVD32f #define cv_hal_SVD64f hal_ni_SVD64f +#define cv_hal_QR32f hal_ni_QR32f +#define cv_hal_QR64f hal_ni_QR64f //! @endcond diff --git a/modules/core/src/lapack.cpp b/modules/core/src/lapack.cpp index eed86b4d55..a602eecd80 100644 --- a/modules/core/src/lapack.cpp +++ b/modules/core/src/lapack.cpp @@ -1238,9 +1238,6 @@ bool cv::solve( InputArray _src, InputArray _src2arg, OutputArray _dst, int meth return result; } - if( method == DECOMP_QR ) - method = DECOMP_SVD; - int m = src.rows, m_ = m, n = src.cols, nb = _src2.cols; size_t esz = CV_ELEM_SIZE(type), bufsize = 0; size_t vstep = alignSize(n*esz, 16); @@ -1268,7 +1265,6 @@ bool cv::solve( InputArray _src, InputArray _src2arg, OutputArray _dst, int meth if( is_normal ) bufsize += n*nb*esz; - if( method == DECOMP_SVD || method == DECOMP_EIG ) bufsize += n*5*esz + n*vstep + nb*sizeof(double) + 32; @@ -1321,6 +1317,28 @@ bool cv::solve( InputArray _src, InputArray _src2arg, OutputArray _dst, int meth else result = hal::Cholesky64f(a.ptr(), a.step, n, dst.ptr(), dst.step, nb); } + else if( method == DECOMP_QR ) + { + Mat rhsMat; + if( is_normal || m == n ) + { + src2.copyTo(dst); + rhsMat = dst; + } + else + { + rhsMat = Mat(m, nb, type); + src2.copyTo(rhsMat); + } + + if( type == CV_32F ) + result = hal::QR32f(a.ptr(), a.step, a.rows, a.cols, rhsMat.cols, rhsMat.ptr(), rhsMat.step, NULL) != 0; + else + result = hal::QR64f(a.ptr(), a.step, a.rows, a.cols, rhsMat.cols, rhsMat.ptr(), rhsMat.step, NULL) != 0; + + if (rhsMat.rows != dst.rows) + rhsMat.rowRange(0, dst.rows).copyTo(dst); + } else { ptr = alignPtr(ptr, 16); diff --git a/modules/core/src/matrix_decomp.cpp b/modules/core/src/matrix_decomp.cpp index 58829b56f8..66c584a103 100644 --- a/modules/core/src/matrix_decomp.cpp +++ b/modules/core/src/matrix_decomp.cpp @@ -225,6 +225,129 @@ bool Cholesky64f(double* A, size_t astep, int m, double* b, size_t bstep, int n) return CholImpl(A, astep, m, b, bstep, n); } +template inline static int +sign(_Tp x) +{ + if (x >= (_Tp)0) + return 1; + else + return -1; +} + +template static inline int +QRImpl(_Tp* A, size_t astep, int m, int n, int k, _Tp* b, size_t bstep, _Tp* hFactors, _Tp eps) +{ + astep /= sizeof(_Tp); + bstep /= sizeof(_Tp); + + cv::AutoBuffer<_Tp> buffer; + size_t buf_size = m ? m + n : hFactors != NULL; + buffer.allocate(buf_size); + _Tp* vl = buffer; + if (hFactors == NULL) + hFactors = vl + m; + + for (int l = 0; l < n; l++) + { + //generate vl + int vlSize = m - l; + _Tp vlNorm = (_Tp)0; + for (int i = 0; i < vlSize; i++) + { + vl[i] = A[(l + i)*astep + l]; + vlNorm += vl[i] * vl[i]; + } + _Tp tmpV = vl[0]; + vl[0] = vl[0] + sign(vl[0])*std::sqrt(vlNorm); + vlNorm = std::sqrt(vlNorm + vl[0] * vl[0] - tmpV*tmpV); + for (int i = 0; i < vlSize; i++) + { + vl[i] /= vlNorm; + } + //multiply A_l*vl + for (int j = l; j < n; j++) + { + _Tp v_lA = (_Tp)0; + for (int i = l; i < m; i++) + { + v_lA += vl[i - l] * A[i*astep + j]; + } + + for (int i = l; i < m; i++) + { + A[i*astep + j] -= 2 * vl[i - l] * v_lA; + } + } + + //save vl and factors + hFactors[l] = vl[0] * vl[0]; + for (int i = 1; i < vlSize; i++) + { + A[(l + i)*astep + l] = vl[i] / vl[0]; + } + } + + if (b) + { + //generate new rhs + for (int l = 0; l < n; l++) + { + //unpack vl + vl[0] = (_Tp)1; + for (int j = 1; j < m - l; j++) + { + vl[j] = A[(j + l)*astep + l]; + } + + //h_l*x + for (int j = 0; j < k; j++) + { + _Tp v_lB = (_Tp)0; + for (int i = l; i < m; i++) + v_lB += vl[i - l] * b[i*bstep + j]; + + for (int i = l; i < m; i++) + b[i*bstep + j] -= 2 * vl[i - l] * v_lB * hFactors[l]; + } + } + //do back substitution + for (int i = n - 1; i >= 0; i--) + { + for (int j = n - 1; j > i; j--) + { + for (int p = 0; p < k; p++) + b[i*bstep + p] -= b[j*bstep + p] * A[i*astep + j]; + } + if (std::abs(A[i*astep + i]) < eps) + return 0; + for (int p = 0; p < k; p++) + b[i*bstep + p] /= A[i*astep + i]; + } + } + + return 1; +} + +int QR32f(float* A, size_t astep, int m, int n, int k, float* b, size_t bstep, float* hFactors) +{ + CV_INSTRUMENT_REGION() + + int output; + CALL_HAL_RET(QR32f, cv_hal_QR32f, output, A, astep, m, n, k, b, bstep, hFactors); + output = QRImpl(A, astep, m, n, k, b, bstep, hFactors, FLT_EPSILON * 10); + return output; +} + +int QR64f(double* A, size_t astep, int m, int n, int k, double* b, size_t bstep, double* hFactors) +{ + CV_INSTRUMENT_REGION() + + int output; + CALL_HAL_RET(QR64f, cv_hal_QR64f, output, A, astep, m, n, k, b, bstep, hFactors) + output = QRImpl(A, astep, m, n, k, b, bstep, hFactors, DBL_EPSILON * 100); + return output; +} + //============================================================================= // for compatibility with 3.0 diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index 32888ff734..3870d31cd5 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -2994,6 +2994,51 @@ TEST(Core_Cholesky, accuracy64f) for (int i = 0; i < A.rows; i++) for (int j = i + 1; j < A.cols; j++) A.at(i, j) = 0.0; - EXPECT_TRUE(norm(refA - A*A.t()) < 10e-5); + EXPECT_LE(norm(refA, A*A.t(), CV_RELATIVE_L2), FLT_EPSILON); } + +TEST(Core_QR_Solver, accuracy64f) +{ + int m = 20, n = 18; + Mat A(m, m, CV_64F); + Mat B(m, n, CV_64F); + Mat mean(1, 1, CV_64F); + *mean.ptr() = 10.0; + Mat dev(1, 1, CV_64F); + *dev.ptr() = 10.0; + RNG rng(10); + rng.fill(A, RNG::NORMAL, mean, dev); + rng.fill(B, RNG::NORMAL, mean, dev); + A = A*A.t(); + Mat solutionQR; + + //solve system with square matrix + solve(A, B, solutionQR, DECOMP_QR); + EXPECT_LE(norm(A*solutionQR, B, CV_RELATIVE_L2), FLT_EPSILON); + + A = Mat(m, n, CV_64F); + B = Mat(m, n, CV_64F); + rng.fill(A, RNG::NORMAL, mean, dev); + rng.fill(B, RNG::NORMAL, mean, dev); + + //solve normal system + solve(A, B, solutionQR, DECOMP_QR | DECOMP_NORMAL); + EXPECT_LE(norm(A.t()*(A*solutionQR), A.t()*B, CV_RELATIVE_L2), FLT_EPSILON); + + //solve overdeterminated system as a least squares problem + Mat solutionSVD; + solve(A, B, solutionQR, DECOMP_QR); + solve(A, B, solutionSVD, DECOMP_SVD); + EXPECT_LE(norm(solutionQR, solutionSVD, CV_RELATIVE_L2), FLT_EPSILON); + + //solve system with singular matrix + A = Mat(10, 10, CV_64F); + B = Mat(10, 1, CV_64F); + rng.fill(A, RNG::NORMAL, mean, dev); + rng.fill(B, RNG::NORMAL, mean, dev); + for (int i = 0; i < A.cols; i++) + A.at(0, i) = A.at(1, i); + ASSERT_FALSE(solve(A, B, solutionQR, DECOMP_QR)); +} + /* End of file. */ From 6172803012c679ec345c2e91207874d72ec62a89 Mon Sep 17 00:00:00 2001 From: Dimitrios Katsaros Date: Thu, 14 Jul 2016 15:27:36 +0200 Subject: [PATCH 124/178] imgcodecs: Implementation of PAM encoder/decoder This patch implements the PAM image format as defined at: http://netpbm.sourceforge.net/doc/pam.html The PAM format provides a generic means for storing 2 dimensional information. This is useful for opencv since there are cases where data gets translated into non standardized formats, which makes it difficult to store and load this information. --- .../imgcodecs/include/opencv2/imgcodecs.hpp | 13 +- .../include/opencv2/imgcodecs/imgcodecs_c.h | 11 +- modules/imgcodecs/src/grfmt_pam.cpp | 719 ++++++++++++++++++ modules/imgcodecs/src/grfmt_pam.hpp | 99 +++ modules/imgcodecs/src/grfmts.hpp | 1 + modules/imgcodecs/src/loadsave.cpp | 2 + 6 files changed, 843 insertions(+), 2 deletions(-) create mode 100644 modules/imgcodecs/src/grfmt_pam.cpp create mode 100644 modules/imgcodecs/src/grfmt_pam.hpp diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index ce827a7e0f..d797737733 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -88,7 +88,8 @@ enum ImwriteFlags { IMWRITE_PNG_STRATEGY = 17, //!< One of cv::ImwritePNGFlags, default is IMWRITE_PNG_STRATEGY_DEFAULT. IMWRITE_PNG_BILEVEL = 18, //!< Binary level PNG, 0 or 1, default is 0. IMWRITE_PXM_BINARY = 32, //!< For PPM, PGM, or PBM, it can be a binary format flag, 0 or 1. Default value is 1. - IMWRITE_WEBP_QUALITY = 64 //!< For WEBP, it can be a quality from 1 to 100 (the higher is the better). By default (without any parameter) and for quality above 100 the lossless compression is used. + IMWRITE_WEBP_QUALITY = 64, //!< For WEBP, it can be a quality from 1 to 100 (the higher is the better). By default (without any parameter) and for quality above 100 the lossless compression is used. + IMWRITE_PAM_TUPLETYPE = 128,//!< For PAM, sets the TUPLETYPE field to the corresponding string value that is defined for the format }; //! Imwrite PNG specific flags used to tune the compression algorithm. @@ -107,6 +108,16 @@ enum ImwritePNGFlags { IMWRITE_PNG_STRATEGY_FIXED = 4 //!< Using this value prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. }; +//! Imwrite PAM specific tupletype flags used to define the 'TUPETYPE' field of a PAM file. +enum ImwritePAMFlags { + IMWRITE_PAM_FORMAT_NULL = 0, + IMWRITE_PAM_FORMAT_BLACKANDWHITE = 1, + IMWRITE_PAM_FORMAT_GRAYSCALE = 2, + IMWRITE_PAM_FORMAT_GRAYSCALE_ALPHA = 3, + IMWRITE_PAM_FORMAT_RGB = 4, + IMWRITE_PAM_FORMAT_RGB_ALPHA = 5, + }; + /** @brief Loads an image from a file. @anchor imread diff --git a/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h b/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h index ad793cc94a..27ab35d8f1 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h +++ b/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h @@ -92,9 +92,18 @@ enum CV_IMWRITE_PNG_STRATEGY_RLE =3, CV_IMWRITE_PNG_STRATEGY_FIXED =4, CV_IMWRITE_PXM_BINARY =32, - CV_IMWRITE_WEBP_QUALITY =64 + CV_IMWRITE_WEBP_QUALITY =64, + CV_IMWRITE_PAM_TUPLETYPE = 128, + CV_IMWRITE_PAM_FORMAT_NULL = 0, + CV_IMWRITE_PAM_FORMAT_BLACKANDWHITE = 1, + CV_IMWRITE_PAM_FORMAT_GRAYSCALE = 2, + CV_IMWRITE_PAM_FORMAT_GRAYSCALE_ALPHA = 3, + CV_IMWRITE_PAM_FORMAT_RGB = 4, + CV_IMWRITE_PAM_FORMAT_RGB_ALPHA = 5, }; + + /* save image to file */ CVAPI(int) cvSaveImage( const char* filename, const CvArr* image, const int* params CV_DEFAULT(0) ); diff --git a/modules/imgcodecs/src/grfmt_pam.cpp b/modules/imgcodecs/src/grfmt_pam.cpp new file mode 100644 index 0000000000..ac7198a66f --- /dev/null +++ b/modules/imgcodecs/src/grfmt_pam.cpp @@ -0,0 +1,719 @@ +/*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 +// (3-clause BSD License) +// +// Copyright (C) 2000-2016, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved. +// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// Copyright (C) 2015-2016, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015-2016, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// 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. +// +//M*/ + + +#include + +#include "precomp.hpp" +#include "utils.hpp" +#include "grfmt_pam.hpp" + +/* the PAM related fields */ +#define MAX_PAM_HEADER_IDENITFIER_LENGTH 8 +#define MAX_PAM_HEADER_VALUE_LENGTH 255 + +/* PAM header fileds */ +typedef enum { + PAM_HEADER_NONE, + PAM_HEADER_COMMENT, + PAM_HEADER_ENDHDR, + PAM_HEADER_HEIGHT, + PAM_HEADER_WIDTH, + PAM_HEADER_DEPTH, + PAM_HEADER_MAXVAL, + PAM_HEADER_TUPLTYPE, +} PamHeaderFieldType; + +struct pam_header_field { + PamHeaderFieldType type; + char identifier[MAX_PAM_HEADER_IDENITFIER_LENGTH+1]; +}; + +const static struct pam_header_field fields[] = { + {PAM_HEADER_ENDHDR, "ENDHDR"}, + {PAM_HEADER_HEIGHT, "HEIGHT"}, + {PAM_HEADER_WIDTH, "WIDTH"}, + {PAM_HEADER_DEPTH, "DEPTH"}, + {PAM_HEADER_MAXVAL, "MAXVAL"}, + {PAM_HEADER_TUPLTYPE, "TUPLTYPE"}, +}; +#define PAM_FIELDS_NO (sizeof (fields) / sizeof ((fields)[0])) + +typedef bool (*cvtFunc) (void *src, void *target, int width, int target_channels, + int target_depth); + +struct channel_layout { + uint rchan, gchan, bchan, graychan; +}; + +struct pam_format { + uint fmt; + char name[MAX_PAM_HEADER_VALUE_LENGTH+1]; + cvtFunc cvt_func; + /* the channel layout that should be used when + * imread_ creates a 3 channel or 1 channel image + * used when no conversion function is available + */ + struct channel_layout layout; +}; + +static bool rgb_convert (void *src, void *target, int width, int target_channels, + int target_depth); + +const static struct pam_format formats[] = { + {CV_IMWRITE_PAM_FORMAT_NULL, "", NULL, {0, 0, 0, 0} }, + {CV_IMWRITE_PAM_FORMAT_BLACKANDWHITE, "BLACKANDWHITE", NULL, {0, 0, 0, 0} }, + {CV_IMWRITE_PAM_FORMAT_GRAYSCALE, "GRAYSCALE", NULL, {0, 0, 0, 0} }, + {CV_IMWRITE_PAM_FORMAT_GRAYSCALE_ALPHA, "GRAYSCALE_ALPHA", NULL, {0, 0, 0, 0} }, + {CV_IMWRITE_PAM_FORMAT_RGB, "RGB", rgb_convert, {0, 1, 2, 0} }, + {CV_IMWRITE_PAM_FORMAT_RGB_ALPHA, "RGB_ALPHA", NULL, {0, 1, 2, 0} }, +}; +#define PAM_FORMATS_NO (sizeof (fields) / sizeof ((fields)[0])) + +/* + * conversion functions + */ + +static bool +rgb_convert (void *src, void *target, int width, int target_channels, int target_depth) +{ + bool ret = false; + if (target_channels == 3) { + switch (target_depth) { + case CV_8U: + icvCvt_RGB2BGR_8u_C3R( (uchar*) src, 0, (uchar*) target, 0, + cvSize(width,1) ); + ret = true; + break; + case CV_16U: + icvCvt_RGB2BGR_16u_C3R( (ushort *)src, 0, (ushort *)target, 0, + cvSize(width,1) ); + ret = true; + break; + default: + break; + } + } else if (target_channels == 1) { + switch (target_depth) { + case CV_8U: + icvCvt_BGR2Gray_8u_C3C1R( (uchar*) src, 0, (uchar*) target, 0, + cvSize(width,1), 2 ); + ret = true; + break; + case CV_16U: + icvCvt_BGRA2Gray_16u_CnC1R( (ushort *)src, 0, (ushort *)target, 0, + cvSize(width,1), 3, 2 ); + ret = true; + break; + default: + break; + } + } + return ret; +} + +/* + * copy functions used as a fall back for undefined formats + * or simpler conversion options + */ + +static void +basic_conversion (void *src, const struct channel_layout *layout, int src_sampe_size, + int src_width, void *target, int target_channels, int target_depth) +{ + switch (target_depth) { + case CV_8U: + { + uchar *d = (uchar *)target, *s = (uchar *)src, + *end = ((uchar *)src) + src_width; + switch (target_channels) { + case 1: + for( ; s < end; d += 3, s += src_sampe_size ) + d[0] = d[1] = d[2] = s[layout->graychan]; + break; + case 3: + for( ; s < end; d += 3, s += src_sampe_size ) { + d[0] = s[layout->bchan]; + d[1] = s[layout->gchan]; + d[2] = s[layout->rchan]; + } + break; + default: + assert (0); + } + break; + } + case CV_16U: + { + ushort *d = (ushort *)target, *s = (ushort *)src, + *end = ((ushort *)src) + src_width; + switch (target_channels) { + case 1: + for( ; s < end; d += 3, s += src_sampe_size ) + d[0] = d[1] = d[2] = s[layout->graychan]; + break; + case 3: + for( ; s < end; d += 3, s += src_sampe_size ) { + d[0] = s[layout->bchan]; + d[1] = s[layout->gchan]; + d[2] = s[layout->rchan]; + } + break; + default: + assert (0); + } + break; + } + default: + assert (0); + } +} + + +static bool ReadPAMHeaderLine (cv::RLByteStream& strm, + PamHeaderFieldType &fieldtype, + char value[MAX_PAM_HEADER_VALUE_LENGTH+1]) +{ + int code, pos; + bool ident_found = false; + uint i; + char ident[MAX_PAM_HEADER_IDENITFIER_LENGTH+1] = { 0 }; + + do { + code = strm.getByte(); + } while ( isspace(code) ); + + if (code == '#') { + /* we are in a comment, eat characters until linebreak */ + do + { + code = strm.getByte(); + } while( code != '\n' && code != '\r' ); + fieldtype = PAM_HEADER_COMMENT; + return true; + } else if (code == '\n' || code == '\r' ) { + fieldtype = PAM_HEADER_NONE; + return true; + } + + /* nul-ify buffers before writing to them */ + memset (ident, '\0', sizeof(char) * MAX_PAM_HEADER_IDENITFIER_LENGTH); + for (i=0; i= 0 && isspace(value[pos])) + value[pos--] = '\0'; + + return true; +} + +static bool ParseNumber (char *str, int *retval) +{ + char *endptr; + long lval = strtol (str, &endptr, 0); + + if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) + || (errno != 0 && lval == 0)) { + return false; + } + if (endptr == str) { + return false; + } + + *retval = (int) lval; + + return true; +} + +namespace cv +{ + +PAMDecoder::PAMDecoder() +{ + m_offset = -1; + m_buf_supported = true; + bit_mode = false; + selected_fmt = CV_IMWRITE_PAM_FORMAT_NULL; +} + + +PAMDecoder::~PAMDecoder() +{ + m_strm.close(); +} + +size_t PAMDecoder::signatureLength() const +{ + return 3; +} + +bool PAMDecoder::checkSignature( const String& signature ) const +{ + return signature.size() >= 3 && signature[0] == 'P' && + signature[1] == '7' && + isspace(signature[2]); +} + +ImageDecoder PAMDecoder::newDecoder() const +{ + return makePtr(); +} + +struct parsed_fields +{ + bool endhdr, height, width, depth, maxval; +}; + +#define HEADER_READ_CORRECT(pf) (pf.endhdr && pf.height && pf.width \ + && pf.depth && pf.maxval) + + +bool PAMDecoder::readHeader() +{ + PamHeaderFieldType fieldtype = PAM_HEADER_NONE; + char value[MAX_PAM_HEADER_VALUE_LENGTH+1]; + int byte; + struct parsed_fields flds; + if( !m_buf.empty() ) + { + if( !m_strm.open(m_buf) ) + return false; + } + else if( !m_strm.open( m_filename )) + return false; + try + { + byte = m_strm.getByte(); + if( byte != 'P' ) + throw RBS_BAD_HEADER; + + byte = m_strm.getByte(); + if (byte != '7') + throw RBS_BAD_HEADER; + + byte = m_strm.getByte(); + if (byte != '\n' && byte != '\r') + throw RBS_BAD_HEADER; + + uint i; + memset (&flds, 0x00, sizeof (struct parsed_fields)); + do { + if (!ReadPAMHeaderLine(m_strm, fieldtype, value)) + throw RBS_BAD_HEADER; + switch (fieldtype) { + case PAM_HEADER_NONE: + case PAM_HEADER_COMMENT: + continue; + case PAM_HEADER_ENDHDR: + flds.endhdr = true; + break; + case PAM_HEADER_HEIGHT: + if (flds.height) + throw RBS_BAD_HEADER; + if (!ParseNumber (value, &m_height)) + throw RBS_BAD_HEADER; + flds.height = true; + break; + case PAM_HEADER_WIDTH: + if (flds.width) + throw RBS_BAD_HEADER; + if (!ParseNumber (value, &m_width)) + throw RBS_BAD_HEADER; + flds.width = true; + break; + case PAM_HEADER_DEPTH: + if (flds.depth) + throw RBS_BAD_HEADER; + if (!ParseNumber (value, &m_channels)) + throw RBS_BAD_HEADER; + flds.depth = true; + break; + case PAM_HEADER_MAXVAL: + if (flds.maxval) + throw RBS_BAD_HEADER; + if (!ParseNumber (value, &m_maxval)) + throw RBS_BAD_HEADER; + if ( m_maxval > 65535 ) + throw RBS_BAD_HEADER; + if ( m_maxval > 255 ) { + m_sampledepth = CV_16U; + } + else + m_sampledepth = CV_8U; + if (m_maxval == 1) + bit_mode = true; + flds.maxval = true; + break; + case PAM_HEADER_TUPLTYPE: + for (i=0; i _src(src_elems_per_row * 2); + uchar* src = _src; + AutoBuffer _gray_palette; + uchar* gray_palette = _gray_palette; + + if( m_offset < 0 || !m_strm.isOpened()) + return false; + + if (selected_fmt != CV_IMWRITE_PAM_FORMAT_NULL) + fmt = &formats[selected_fmt]; + else { + /* default layout handling */ + if (m_channels >= 3) { + layout.bchan = 0; + layout.gchan = 1; + layout.rchan = 2; + } else + layout.bchan = layout.gchan = layout.rchan = 0; + layout.graychan = 0; + } + + try + { + m_strm.setPos( m_offset ); + + /* the case where data fits the opencv matrix */ + if (m_sampledepth == img.depth() && target_channels == m_channels && !bit_mode) { + /* special case for 16bit images with wrong endianess */ + if (m_sampledepth == CV_16U && !isBigEndian()) + { + for (y = 0; y < m_height; y++, data += imp_stride ) + { + m_strm.getBytes( src, src_stride ); + for( x = 0; x < src_elems_per_row; x++ ) + { + uchar v = src[x * 2]; + data[x * 2] = src[x * 2 + 1]; + data[x * 2 + 1] = v; + } + } + } + else { + m_strm.getBytes( data, src_stride * m_height ); + } + + } + else { + /* black and white mode */ + if (bit_mode) { + if( target_channels == 1 ) + { + _gray_palette.allocate(2); + gray_palette = _gray_palette; + gray_palette[0] = 0; + gray_palette[1] = 255; + for( y = 0; y < m_height; y++, data += imp_stride ) + { + m_strm.getBytes( src, src_stride ); + FillGrayRow1( data, src, m_width, gray_palette ); + } + } else if ( target_channels == 3 ) + { + FillGrayPalette( palette, 1 , false ); + for( y = 0; y < m_height; y++, data += imp_stride ) + { + m_strm.getBytes( src, src_stride ); + FillColorRow1( data, src, m_width, palette ); + } + } + } else { + for (y = 0; y < m_height; y++, data += imp_stride ) + { + m_strm.getBytes( src, src_stride ); + + /* endianess correction */ + if( m_sampledepth == CV_16U && !isBigEndian() ) + { + for( x = 0; x < src_elems_per_row; x++ ) + { + uchar v = src[x * 2]; + src[x * 2] = src[x * 2 + 1]; + src[x * 2 + 1] = v; + } + } + + /* scale down */ + if( img.depth() == CV_8U && m_sampledepth == CV_16U ) + { + for( x = 0; x < src_elems_per_row; x++ ) + { + int v = ((ushort *)src)[x]; + src[x] = (uchar)(v >> 8); + } + } + + /* if we are only scaling up/down then we can then copy the data */ + if (target_channels == m_channels) { + memcpy (data, src, imp_stride); + } + /* perform correct conversion based on format */ + else if (fmt) { + funcout = false; + if (fmt->cvt_func) + funcout = fmt->cvt_func (src, data, m_width, target_channels, + img.depth()); + /* fall back to default if there is no conversion function or it + * can't handle the specified characteristics + */ + if (!funcout) + basic_conversion (src, &fmt->layout, m_channels, + m_width, data, target_channels, img.depth()); + + /* default to selecting the first available channels */ + } else { + basic_conversion (src, &layout, m_channels, + m_width, data, target_channels, img.depth()); + } + } + } + } + + res = true; + } catch(...) + { + } + + return res; +} + + +////////////////////////////////////////////////////////////////////////////////////////// + +PAMEncoder::PAMEncoder() +{ + m_description = "Portable arbitrary format (*.pam)"; + m_buf_supported = true; +} + + +PAMEncoder::~PAMEncoder() +{ +} + + +ImageEncoder PAMEncoder::newEncoder() const +{ + return makePtr(); +} + + +bool PAMEncoder::isFormatSupported( int depth ) const +{ + return depth == CV_8U || depth == CV_16U; +} + + +bool PAMEncoder::write( const Mat& img, const std::vector& params ) +{ + + WLByteStream strm; + + int width = img.cols, height = img.rows; + int stride = width*(int)img.elemSize(); + const uchar* data = img.ptr(); + const struct pam_format *fmt = NULL; + int x, y, tmp, bufsize = 256; + + /* parse save file type */ + for( size_t i = 0; i < params.size(); i += 2 ) + if( params[i] == CV_IMWRITE_PAM_TUPLETYPE ) { + if ( params[i+1] > CV_IMWRITE_PAM_FORMAT_NULL && + params[i+1] < (int) PAM_FORMATS_NO) + fmt = &formats[params[i+1]]; + } + + if( m_buf ) + { + if( !strm.open(*m_buf) ) + return false; + m_buf->reserve( alignSize(256 + stride*height, 256)); + } + else if( !strm.open(m_filename) ) + return false; + + tmp = width * (int)img.elemSize(); + + if (bufsize < tmp) + bufsize = tmp; + + AutoBuffer _buffer(bufsize); + char* buffer = _buffer; + + /* write header */ + tmp = 0; + tmp += sprintf( buffer, "P7\n"); + tmp += sprintf( buffer + tmp, "WIDTH %d\n", width); + tmp += sprintf( buffer + tmp, "HEIGHT %d\n", height); + tmp += sprintf( buffer + tmp, "DEPTH %d\n", img.channels()); + tmp += sprintf( buffer + tmp, "MAXVAL %d\n", (1 << img.elemSize1()*8) - 1); + if (fmt) + tmp += sprintf( buffer + tmp, "TUPLTYPE %s\n", fmt->name ); + tmp += sprintf( buffer + tmp, "ENDHDR\n" ); + + strm.putBytes( buffer, (int)strlen(buffer) ); + /* write data */ + if (img.depth() == CV_8U) + strm.putBytes( data, stride*height ); + else if (img.depth() == CV_16U) { + /* fix endianess */ + if (!isBigEndian()) { + for( y = 0; y < height; y++ ) { + memcpy( buffer, img.ptr(y), stride ); + for( x = 0; x < stride; x += 2 ) + { + uchar v = buffer[x]; + buffer[x] = buffer[x + 1]; + buffer[x + 1] = v; + } + strm.putBytes( buffer, stride ); + } + } else + strm.putBytes( data, stride*height ); + } else + assert (0); + + strm.close(); + return true; +} + +} diff --git a/modules/imgcodecs/src/grfmt_pam.hpp b/modules/imgcodecs/src/grfmt_pam.hpp new file mode 100644 index 0000000000..8b3b1f10c9 --- /dev/null +++ b/modules/imgcodecs/src/grfmt_pam.hpp @@ -0,0 +1,99 @@ +/*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 +// (3-clause BSD License) +// +// Copyright (C) 2000-2016, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved. +// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// Copyright (C) 2015-2016, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015-2016, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// 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. +// +// +//M*/ + +//Based on "imgcodecs/src/grfmt_pxm.hpp" +//Written by Dimitrios Katsaros + +#ifndef _OPENCV_PAM_HPP_ +#define _OPENCV_PAM_HPP_ + +#include "grfmt_base.hpp" +#include "bitstrm.hpp" + +namespace cv +{ + +class PAMDecoder : public BaseImageDecoder +{ +public: + + PAMDecoder(); + virtual ~PAMDecoder(); + + bool readData( Mat& img ); + bool readHeader(); + + size_t signatureLength() const; + bool checkSignature( const String& signature ) const; + ImageDecoder newDecoder() const; + +protected: + + RLByteStream m_strm; + int m_maxval, m_channels, m_sampledepth, m_offset, + selected_fmt; + bool bit_mode; +}; + + +class PAMEncoder : public BaseImageEncoder +{ +public: + PAMEncoder(); + virtual ~PAMEncoder(); + + bool isFormatSupported( int depth ) const; + bool write( const Mat& img, const std::vector& params ); + + ImageEncoder newEncoder() const; +}; + +} + +#endif /* _OPENCV_PAM_HPP_ */ \ No newline at end of file diff --git a/modules/imgcodecs/src/grfmts.hpp b/modules/imgcodecs/src/grfmts.hpp index 7db1ac94a2..10bd88264e 100644 --- a/modules/imgcodecs/src/grfmts.hpp +++ b/modules/imgcodecs/src/grfmts.hpp @@ -55,5 +55,6 @@ #include "grfmt_hdr.hpp" #include "grfmt_gdal.hpp" #include "grfmt_gdcm.hpp" +#include "grfmt_pam.hpp" #endif/*_GRFMTS_H_*/ diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index 1c0b794b8e..36e6349d75 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -109,6 +109,8 @@ struct ImageCodecInitializer /// Attach the GDAL Decoder decoders.push_back( makePtr() ); #endif/*HAVE_GDAL*/ + decoders.push_back( makePtr() ); + encoders.push_back( makePtr() ); } std::vector decoders; From 4e513a3346fb647f49fdbf9849328fcc8c691a54 Mon Sep 17 00:00:00 2001 From: Dimitrios Katsaros Date: Sun, 14 Aug 2016 22:17:55 +0200 Subject: [PATCH 125/178] Imgcodecs: Fixed a bug with checkSignature in GdalDecoder In cases where the signaure string contains a terminating character, the std::string member function size returns a smaller value than the allocated string. In these cases, if you then try to use substr, you will get an out_of_range exception. This patch remedies the problem. --- modules/imgcodecs/src/grfmt_gdal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgcodecs/src/grfmt_gdal.cpp b/modules/imgcodecs/src/grfmt_gdal.cpp index 1094b91b38..8865ae4948 100644 --- a/modules/imgcodecs/src/grfmt_gdal.cpp +++ b/modules/imgcodecs/src/grfmt_gdal.cpp @@ -559,7 +559,7 @@ bool GdalDecoder::checkSignature( const String& signature )const{ // look for NITF - std::string str = signature.c_str(); + std::string str(signature); if( str.substr(0,4).find("NITF") != std::string::npos ){ return true; } From 41431e11f50d70d879275f4dd4bb024fb4d89482 Mon Sep 17 00:00:00 2001 From: Dimitrios Katsaros Date: Wed, 20 Jul 2016 15:13:39 +0200 Subject: [PATCH 126/178] Imgcodecs: Implemented simple tests for PAM format --- modules/imgcodecs/test/test_grfmt.cpp | 28 ++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/modules/imgcodecs/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp index f305ca137a..4328372703 100644 --- a/modules/imgcodecs/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -44,6 +44,7 @@ #include #include +#include using namespace cv; using namespace std; @@ -308,6 +309,7 @@ string ext_from_int(int ext) #ifdef HAVE_TIFF if (ext == 3) return ".tiff"; #endif + if (ext == 4) return ".pam"; return ""; } @@ -323,7 +325,7 @@ public: for (int k = 1; k <= 5; ++k) { - for (int ext = 0; ext < 4; ++ext) // 0 - png, 1 - bmp, 2 - pgm, 3 - tiff + for (int ext = 0; ext < 5; ++ext) // 0 - png, 1 - bmp, 2 - pgm, 3 - tiff { if(ext_from_int(ext).empty()) continue; @@ -1017,3 +1019,27 @@ TEST(Imgcodecs_Hdr, regression) ASSERT_FALSE(max > DBL_EPSILON); } } + +TEST(Imgcodecs_Pam, readwrite) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "readwrite/"; + string filepath = folder + "lena.pam"; + + cv::Mat img = cv::imread(filepath); + ASSERT_FALSE(img.empty()); + + std::vector params; + params.push_back(IMWRITE_PAM_TUPLETYPE); + params.push_back(IMWRITE_PAM_FORMAT_RGB); + + string writefile = cv::tempfile(".pam"); + EXPECT_NO_THROW(cv::imwrite(writefile, img, params)); + cv::Mat reread = cv::imread(writefile); + + string writefile_no_param = cv::tempfile(".pam"); + EXPECT_NO_THROW(cv::imwrite(writefile_no_param, img)); + cv::Mat reread_no_param = cv::imread(writefile_no_param); + + EXPECT_EQ(0, cvtest::norm(reread, reread_no_param, NORM_INF)); + EXPECT_EQ(0, cvtest::norm(img, reread, NORM_INF)); +} From 27ae1578ac3bfcf4a3aece04bec802d41a0d918b Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Wed, 7 Sep 2016 15:48:37 +0200 Subject: [PATCH 127/178] BackgroundSubtractorMOG2Impl: only use OpenCL if input image is UMat --- modules/video/src/bgfg_gaussmix2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index f4d2cc237e..9efc713c20 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -846,7 +846,7 @@ void BackgroundSubtractorMOG2Impl::apply(InputArray _image, OutputArray _fgmask, #ifdef HAVE_OPENCL if (opencl_ON) { - CV_OCL_RUN(opencl_ON, ocl_apply(_image, _fgmask, learningRate)) + CV_OCL_RUN(_image.isUMat(), ocl_apply(_image, _fgmask, learningRate)) opencl_ON = false; initialize(_image.size(), _image.type()); From c562f0ad387c7af58f6da35d7c21b87646d05481 Mon Sep 17 00:00:00 2001 From: Valeriy Van Date: Wed, 7 Sep 2016 00:39:27 +0300 Subject: [PATCH 128/178] Minor fix in MatAllocator::download Minor fix in MatAllocator::upload Minor fix in MatAllocator::copy Minor fix in setSize function Minor fix in Mat::Mat Minor fix in cvMatNDToMat function Minor fix in _InputArray::getMatVector Minor fix in _InputArray::getUMatVector Minor fix in cv::hconcat Minor fix in cv::vconcat Minor fix in cv::setIdentity Minor fix in cv::trace Minor fix in transposeI_ template function Minor fix in reduceC_ template function Minor fix in sort_ template function Minor fix in sortIdx_ template function Minor fix in cvRange function Minor fix in MatConstIterator::seek Minor fix in SparseMat::create Minor fix in SparseMat::copyTo Minor fix in SparseMat::convertTo Minor fix in SparseMat::convertTo Minor fix in SparseMat::ptr Minor fix in SparseMat::resizeHashTab Fixes indentation --- modules/core/src/matrix.cpp | 211 +++++++++++++++++------------------- 1 file changed, 100 insertions(+), 111 deletions(-) diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index a370ec46df..46137ddda3 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -77,9 +77,9 @@ void MatAllocator::download(UMatData* u, void* dstptr, { CV_Assert( sz[i] <= (size_t)INT_MAX ); if( sz[i] == 0 ) - return; + return; if( srcofs ) - srcptr += srcofs[i]*(i <= dims-2 ? srcstep[i] : 1); + srcptr += srcofs[i]*(i <= dims-2 ? srcstep[i] : 1); isz[i] = (int)sz[i]; } @@ -89,9 +89,9 @@ void MatAllocator::download(UMatData* u, void* dstptr, const Mat* arrays[] = { &src, &dst }; uchar* ptrs[2]; NAryMatIterator it(arrays, ptrs, 2); - size_t j, planesz = it.size; + size_t planesz = it.size; - for( j = 0; j < it.nplanes; j++, ++it ) + for( size_t j = 0; j < it.nplanes; j++, ++it ) memcpy(ptrs[1], ptrs[0], planesz); } @@ -108,9 +108,9 @@ void MatAllocator::upload(UMatData* u, const void* srcptr, int dims, const size_ { CV_Assert( sz[i] <= (size_t)INT_MAX ); if( sz[i] == 0 ) - return; + return; if( dstofs ) - dstptr += dstofs[i]*(i <= dims-2 ? dststep[i] : 1); + dstptr += dstofs[i]*(i <= dims-2 ? dststep[i] : 1); isz[i] = (int)sz[i]; } @@ -120,9 +120,9 @@ void MatAllocator::upload(UMatData* u, const void* srcptr, int dims, const size_ const Mat* arrays[] = { &src, &dst }; uchar* ptrs[2]; NAryMatIterator it(arrays, ptrs, 2); - size_t j, planesz = it.size; + size_t planesz = it.size; - for( j = 0; j < it.nplanes; j++, ++it ) + for( size_t j = 0; j < it.nplanes; j++, ++it ) memcpy(ptrs[1], ptrs[0], planesz); } @@ -155,9 +155,9 @@ void MatAllocator::copy(UMatData* usrc, UMatData* udst, int dims, const size_t s const Mat* arrays[] = { &src, &dst }; uchar* ptrs[2]; NAryMatIterator it(arrays, ptrs, 2); - size_t j, planesz = it.size; + size_t planesz = it.size; - for( j = 0; j < it.nplanes; j++, ++it ) + for( size_t j = 0; j < it.nplanes; j++, ++it ) memcpy(ptrs[1], ptrs[0], planesz); } @@ -301,8 +301,7 @@ static inline void setSize( Mat& m, int _dims, const int* _sz, return; size_t esz = CV_ELEM_SIZE(m.flags), esz1 = CV_ELEM_SIZE1(m.flags), total = esz; - int i; - for( i = _dims-1; i >= 0; i-- ) + for( int i = _dims-1; i >= 0; i-- ) { int s = _sz[i]; CV_Assert( s >= 0 ); @@ -546,16 +545,16 @@ Mat::Mat(const Mat& m, const Range* ranges) : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows) { - int i, d = m.dims; + int d = m.dims; CV_Assert(ranges); - for( i = 0; i < d; i++ ) + for( int i = 0; i < d; i++ ) { Range r = ranges[i]; CV_Assert( r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]) ); } *this = m; - for( i = 0; i < d; i++ ) + for( int i = 0; i < d; i++ ) { Range r = ranges[i]; if( r != Range::all() && r != Range(0, size.p[i])) @@ -580,8 +579,8 @@ static Mat cvMatNDToMat(const CvMatND* m, bool copyData) int _sizes[CV_MAX_DIM]; size_t _steps[CV_MAX_DIM]; - int i, d = m->dims; - for( i = 0; i < d; i++ ) + int d = m->dims; + for( int i = 0; i < d; i++ ) { _sizes[i] = m->dim[i].size; _steps[i] = m->dim[i].step; @@ -1290,10 +1289,10 @@ void _InputArray::getMatVector(std::vector& mv) const if( k == MAT ) { const Mat& m = *(const Mat*)obj; - int i, n = (int)m.size[0]; + int n = (int)m.size[0]; mv.resize(n); - for( i = 0; i < n; i++ ) + for( int i = 0; i < n; i++ ) mv[i] = m.dims == 2 ? Mat(1, m.cols, m.type(), (void*)m.ptr(i)) : Mat(m.dims-1, &m.size[1], m.type(), (void*)m.ptr(i), &m.step[1]); return; @@ -1302,20 +1301,20 @@ void _InputArray::getMatVector(std::vector& mv) const if( k == EXPR ) { Mat m = *(const MatExpr*)obj; - int i, n = m.size[0]; + int n = m.size[0]; mv.resize(n); - for( i = 0; i < n; i++ ) + for( int i = 0; i < n; i++ ) mv[i] = m.row(i); return; } if( k == MATX ) { - size_t i, n = sz.height, esz = CV_ELEM_SIZE(flags); + size_t n = sz.height, esz = CV_ELEM_SIZE(flags); mv.resize(n); - for( i = 0; i < n; i++ ) + for( size_t i = 0; i < n; i++ ) mv[i] = Mat(1, sz.width, CV_MAT_TYPE(flags), (uchar*)obj + esz*sz.width*i); return; } @@ -1324,11 +1323,11 @@ void _InputArray::getMatVector(std::vector& mv) const { const std::vector& v = *(const std::vector*)obj; - size_t i, n = v.size(), esz = CV_ELEM_SIZE(flags); + size_t n = v.size(), esz = CV_ELEM_SIZE(flags); int t = CV_MAT_DEPTH(flags), cn = CV_MAT_CN(flags); mv.resize(n); - for( i = 0; i < n; i++ ) + for( size_t i = 0; i < n; i++ ) mv[i] = Mat(1, cn, t, (void*)(&v[0] + esz*i)); return; } @@ -1342,11 +1341,11 @@ void _InputArray::getMatVector(std::vector& mv) const if( k == STD_VECTOR_VECTOR ) { const std::vector >& vv = *(const std::vector >*)obj; - int i, n = (int)vv.size(); + int n = (int)vv.size(); int t = CV_MAT_TYPE(flags); mv.resize(n); - for( i = 0; i < n; i++ ) + for( int i = 0; i < n; i++ ) { const std::vector& v = vv[i]; mv[i] = Mat(size(i), t, (void*)&v[0]); @@ -1357,10 +1356,10 @@ void _InputArray::getMatVector(std::vector& mv) const if( k == STD_VECTOR_MAT ) { const std::vector& v = *(const std::vector*)obj; - size_t i, n = v.size(); + size_t n = v.size(); mv.resize(n); - for( i = 0; i < n; i++ ) + for( size_t i = 0; i < n; i++ ) mv[i] = v[i]; return; } @@ -1368,10 +1367,10 @@ void _InputArray::getMatVector(std::vector& mv) const if( k == STD_VECTOR_UMAT ) { const std::vector& v = *(const std::vector*)obj; - size_t i, n = v.size(); + size_t n = v.size(); mv.resize(n); - for( i = 0; i < n; i++ ) + for( size_t i = 0; i < n; i++ ) mv[i] = v[i].getMat(accessFlags); return; } @@ -1393,10 +1392,10 @@ void _InputArray::getUMatVector(std::vector& umv) const if( k == STD_VECTOR_MAT ) { const std::vector& v = *(const std::vector*)obj; - size_t i, n = v.size(); + size_t n = v.size(); umv.resize(n); - for( i = 0; i < n; i++ ) + for( size_t i = 0; i < n; i++ ) umv[i] = v[i].getUMat(accessFlags); return; } @@ -1404,10 +1403,10 @@ void _InputArray::getUMatVector(std::vector& umv) const if( k == STD_VECTOR_UMAT ) { const std::vector& v = *(const std::vector*)obj; - size_t i, n = v.size(); + size_t n = v.size(); umv.resize(n); - for( i = 0; i < n; i++ ) + for( size_t i = 0; i < n; i++ ) umv[i] = v[i]; return; } @@ -2818,8 +2817,7 @@ void cv::hconcat(const Mat* src, size_t nsrc, OutputArray _dst) } int totalCols = 0, cols = 0; - size_t i; - for( i = 0; i < nsrc; i++ ) + for( size_t i = 0; i < nsrc; i++ ) { CV_Assert( src[i].dims <= 2 && src[i].rows == src[0].rows && @@ -2828,7 +2826,7 @@ void cv::hconcat(const Mat* src, size_t nsrc, OutputArray _dst) } _dst.create( src[0].rows, totalCols, src[0].type()); Mat dst = _dst.getMat(); - for( i = 0; i < nsrc; i++ ) + for( size_t i = 0; i < nsrc; i++ ) { Mat dpart = dst(Rect(cols, 0, src[i].cols, src[i].rows)); src[i].copyTo(dpart); @@ -2864,8 +2862,7 @@ void cv::vconcat(const Mat* src, size_t nsrc, OutputArray _dst) } int totalRows = 0, rows = 0; - size_t i; - for( i = 0; i < nsrc; i++ ) + for( size_t i = 0; i < nsrc; i++ ) { CV_Assert(src[i].dims <= 2 && src[i].cols == src[0].cols && @@ -2874,7 +2871,7 @@ void cv::vconcat(const Mat* src, size_t nsrc, OutputArray _dst) } _dst.create( totalRows, src[0].cols, src[0].type()); Mat dst = _dst.getMat(); - for( i = 0; i < nsrc; i++ ) + for( size_t i = 0; i < nsrc; i++ ) { Mat dpart(dst, Rect(0, rows, src[i].cols, src[i].rows)); src[i].copyTo(dpart); @@ -2951,7 +2948,7 @@ void cv::setIdentity( InputOutputArray _m, const Scalar& s ) ocl_setIdentity(_m, s)) Mat m = _m.getMat(); - int i, j, rows = m.rows, cols = m.cols, type = m.type(); + int rows = m.rows, cols = m.cols, type = m.type(); if( type == CV_32FC1 ) { @@ -2959,9 +2956,9 @@ void cv::setIdentity( InputOutputArray _m, const Scalar& s ) float val = (float)s[0]; size_t step = m.step/sizeof(data[0]); - for( i = 0; i < rows; i++, data += step ) + for( int i = 0; i < rows; i++, data += step ) { - for( j = 0; j < cols; j++ ) + for( int j = 0; j < cols; j++ ) data[j] = 0; if( i < cols ) data[i] = val; @@ -2973,9 +2970,9 @@ void cv::setIdentity( InputOutputArray _m, const Scalar& s ) double val = s[0]; size_t step = m.step/sizeof(data[0]); - for( i = 0; i < rows; i++, data += step ) + for( int i = 0; i < rows; i++, data += step ) { - for( j = 0; j < cols; j++ ) + for( int j = 0; j < cols; j++ ) data[j] = j == i ? val : 0; } } @@ -2994,7 +2991,7 @@ cv::Scalar cv::trace( InputArray _m ) Mat m = _m.getMat(); CV_Assert( m.dims <= 2 ); - int i, type = m.type(); + int type = m.type(); int nm = std::min(m.rows, m.cols); if( type == CV_32FC1 ) @@ -3002,7 +2999,7 @@ cv::Scalar cv::trace( InputArray _m ) const float* ptr = m.ptr(); size_t step = m.step/sizeof(ptr[0]) + 1; double _s = 0; - for( i = 0; i < nm; i++ ) + for( int i = 0; i < nm; i++ ) _s += ptr[i*step]; return _s; } @@ -3012,7 +3009,7 @@ cv::Scalar cv::trace( InputArray _m ) const double* ptr = m.ptr(); size_t step = m.step/sizeof(ptr[0]) + 1; double _s = 0; - for( i = 0; i < nm; i++ ) + for( int i = 0; i < nm; i++ ) _s += ptr[i*step]; return _s; } @@ -3084,12 +3081,11 @@ transpose_( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ) template static void transposeI_( uchar* data, size_t step, int n ) { - int i, j; - for( i = 0; i < n; i++ ) + for( int i = 0; i < n; i++ ) { T* row = (T*)(data + step*i); uchar* data1 = data + i*sizeof(T); - for( j = i+1; j < n; j++ ) + for( int j = i+1; j < n; j++ ) std::swap( row[j], *(T*)(data1 + step*j) ); } } @@ -3417,7 +3413,7 @@ reduceC_( const Mat& srcmat, Mat& dstmat ) { typedef typename Op::rtype WT; Size size = srcmat.size(); - int i, k, cn = srcmat.channels(); + int cn = srcmat.channels(); size.width *= cn; Op op; @@ -3426,13 +3422,14 @@ reduceC_( const Mat& srcmat, Mat& dstmat ) const T* src = srcmat.ptr(y); ST* dst = dstmat.ptr(y); if( size.width == cn ) - for( k = 0; k < cn; k++ ) + for( int k = 0; k < cn; k++ ) dst[k] = src[k]; else { - for( k = 0; k < cn; k++ ) + for( int k = 0; k < cn; k++ ) { WT a0 = src[k], a1 = src[k+cn]; + int i; for( i = 2*cn; i <= size.width - 4*cn; i += 4*cn ) { a0 = op(a0, (WT)src[i+k]); @@ -3446,7 +3443,7 @@ reduceC_( const Mat& srcmat, Mat& dstmat ) a0 = op(a0, (WT)src[i+k]); } a0 = op(a0, a1); - dst[k] = (ST)a0; + dst[k] = (ST)a0; } } } @@ -3934,7 +3931,7 @@ template static void sort_( const Mat& src, Mat& dst, int flags ) { AutoBuffer buf; T* bptr; - int i, j, n, len; + int n, len; bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW; bool inplace = src.data == dst.data; bool sortDescending = (flags & CV_SORT_DESCENDING) != 0; @@ -3959,7 +3956,7 @@ template static void sort_( const Mat& src, Mat& dst, int flags ) } #endif - for( i = 0; i < n; i++ ) + for( int i = 0; i < n; i++ ) { T* ptr = bptr; if( sortRows ) @@ -3974,7 +3971,7 @@ template static void sort_( const Mat& src, Mat& dst, int flags ) } else { - for( j = 0; j < len; j++ ) + for( int j = 0; j < len; j++ ) ptr[j] = src.ptr(j)[i]; } @@ -3996,7 +3993,7 @@ template static void sort_( const Mat& src, Mat& dst, int flags ) #ifdef USE_IPP_SORT setIppErrorStatus(); #endif - for( j = 0; j < len/2; j++ ) + for( int j = 0; j < len/2; j++ ) std::swap(ptr[j], ptr[len-1-j]); } #ifdef USE_IPP_SORT @@ -4015,7 +4012,7 @@ template static void sort_( const Mat& src, Mat& dst, int flags ) #endif if( !sortRows ) - for( j = 0; j < len; j++ ) + for( int j = 0; j < len; j++ ) dst.ptr(j)[i] = ptr[j]; } } @@ -4056,14 +4053,12 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) { AutoBuffer buf; AutoBuffer ibuf; - T* bptr; - int* _iptr; - int i, j, n, len; bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW; bool sortDescending = (flags & CV_SORT_DESCENDING) != 0; CV_Assert( src.data != dst.data ); + int n, len; if( sortRows ) n = src.rows, len = src.cols; else @@ -4072,8 +4067,8 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) buf.allocate(len); ibuf.allocate(len); } - bptr = (T*)buf; - _iptr = (int*)ibuf; + T* bptr = (T*)buf; + int* _iptr = (int*)ibuf; #if defined USE_IPP_SORT && IPP_DISABLE_BLOCK int depth = src.depth(); @@ -4086,7 +4081,7 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) } #endif - for( i = 0; i < n; i++ ) + for( int i = 0; i < n; i++ ) { T* ptr = bptr; int* iptr = _iptr; @@ -4098,10 +4093,10 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) } else { - for( j = 0; j < len; j++ ) + for( int j = 0; j < len; j++ ) ptr[j] = src.ptr(j)[i]; } - for( j = 0; j < len; j++ ) + for( int j = 0; j < len; j++ ) iptr[j] = j; #if defined USE_IPP_SORT && IPP_DISABLE_BLOCK @@ -4121,7 +4116,7 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) #if defined USE_IPP_SORT && IPP_DISABLE_BLOCK setIppErrorStatus(); #endif - for( j = 0; j < len/2; j++ ) + for( int j = 0; j < len/2; j++ ) std::swap(iptr[j], iptr[len-1-j]); } #if defined USE_IPP_SORT && IPP_DISABLE_BLOCK @@ -4140,7 +4135,7 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) #endif if( !sortRows ) - for( j = 0; j < len; j++ ) + for( int j = 0; j < len; j++ ) dst.ptr(j)[i] = iptr[j]; } } @@ -4251,22 +4246,17 @@ cvReduce( const CvArr* srcarr, CvArr* dstarr, int dim, int op ) CV_IMPL CvArr* cvRange( CvArr* arr, double start, double end ) { - int ok = 0; - CvMat stub, *mat = (CvMat*)arr; - double delta; - int type, step; + int step; double val = start; - int i, j; - int rows, cols; if( !CV_IS_MAT(mat) ) mat = cvGetMat( mat, &stub); - rows = mat->rows; - cols = mat->cols; - type = CV_MAT_TYPE(mat->type); - delta = (end-start)/(rows*cols); + int rows = mat->rows; + int cols = mat->cols; + int type = CV_MAT_TYPE(mat->type); + double delta = (end-start)/(rows*cols); if( CV_IS_MAT_CONT(mat->type) ) { @@ -4285,29 +4275,28 @@ cvRange( CvArr* arr, double start, double end ) if( fabs(val - ival) < DBL_EPSILON && fabs(delta - idelta) < DBL_EPSILON ) { - for( i = 0; i < rows; i++, idata += step ) - for( j = 0; j < cols; j++, ival += idelta ) + for( int i = 0; i < rows; i++, idata += step ) + for( int j = 0; j < cols; j++, ival += idelta ) idata[j] = ival; } else { - for( i = 0; i < rows; i++, idata += step ) - for( j = 0; j < cols; j++, val += delta ) + for( int i = 0; i < rows; i++, idata += step ) + for( int j = 0; j < cols; j++, val += delta ) idata[j] = cvRound(val); } } else if( type == CV_32FC1 ) { float* fdata = mat->data.fl; - for( i = 0; i < rows; i++, fdata += step ) - for( j = 0; j < cols; j++, val += delta ) + for( int i = 0; i < rows; i++, fdata += step ) + for( int j = 0; j < cols; j++, val += delta ) fdata[j] = (float)val; } else CV_Error( CV_StsUnsupportedFormat, "The function only supports 32sC1 and 32fC1 datatypes" ); - ok = 1; - return ok ? arr : 0; + return arr; } @@ -4708,7 +4697,7 @@ void MatConstIterator::seek(ptrdiff_t ofs, bool relative) void MatConstIterator::seek(const int* _idx, bool relative) { - int i, d = m->dims; + int d = m->dims; ptrdiff_t ofs = 0; if( !_idx ) ; @@ -4716,7 +4705,7 @@ void MatConstIterator::seek(const int* _idx, bool relative) ofs = _idx[0]*m->size[1] + _idx[1]; else { - for( i = 0; i < d; i++ ) + for( int i = 0; i < d; i++ ) ofs = ofs*m->size[i] + _idx[i]; } seek(ofs, relative); @@ -4926,13 +4915,13 @@ SparseMat::SparseMat(const Mat& m) void SparseMat::create(int d, const int* _sizes, int _type) { - int i; CV_Assert( _sizes && 0 < d && d <= CV_MAX_DIM ); - for( i = 0; i < d; i++ ) + for( int i = 0; i < d; i++ ) CV_Assert( _sizes[i] > 0 ); _type = CV_MAT_TYPE(_type); if( hdr && _type == type() && hdr->dims == d && hdr->refcount == 1 ) { + int i; for( i = 0; i < d; i++ ) if( _sizes[i] != hdr->size[i] ) break; @@ -4945,7 +4934,7 @@ void SparseMat::create(int d, const int* _sizes, int _type) int _sizes_backup[CV_MAX_DIM]; // #5991 if (_sizes == hdr->size) { - for(i = 0; i < d; i++ ) + for(int i = 0; i < d; i++ ) _sizes_backup[i] = _sizes[i]; _sizes = _sizes_backup; } @@ -4965,9 +4954,9 @@ void SparseMat::copyTo( SparseMat& m ) const } m.create( hdr->dims, hdr->size, type() ); SparseMatConstIterator from = begin(); - size_t i, N = nzcount(), esz = elemSize(); + size_t N = nzcount(), esz = elemSize(); - for( i = 0; i < N; i++, ++from ) + for( size_t i = 0; i < N; i++, ++from ) { const Node* n = from.node(); uchar* to = m.newNode(n->idx, n->hashval); @@ -4983,9 +4972,9 @@ void SparseMat::copyTo( Mat& m ) const m = Scalar(0); SparseMatConstIterator from = begin(); - size_t i, N = nzcount(), esz = elemSize(); + size_t N = nzcount(), esz = elemSize(); - for( i = 0; i < N; i++, ++from ) + for( size_t i = 0; i < N; i++, ++from ) { const Node* n = from.node(); copyElem( from.ptr, (ndims > 1 ? m.ptr(n->idx) : m.ptr(n->idx[0])), esz); @@ -5012,12 +5001,12 @@ void SparseMat::convertTo( SparseMat& m, int rtype, double alpha ) const m.create( hdr->dims, hdr->size, rtype ); SparseMatConstIterator from = begin(); - size_t i, N = nzcount(); + size_t N = nzcount(); if( alpha == 1 ) { ConvertData cvtfunc = getConvertElem(type(), rtype); - for( i = 0; i < N; i++, ++from ) + for( size_t i = 0; i < N; i++, ++from ) { const Node* n = from.node(); uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval); @@ -5027,7 +5016,7 @@ void SparseMat::convertTo( SparseMat& m, int rtype, double alpha ) const else { ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype); - for( i = 0; i < N; i++, ++from ) + for( size_t i = 0; i < N; i++, ++from ) { const Node* n = from.node(); uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval); @@ -5049,12 +5038,12 @@ void SparseMat::convertTo( Mat& m, int rtype, double alpha, double beta ) const m = Scalar(beta); SparseMatConstIterator from = begin(); - size_t i, N = nzcount(); + size_t N = nzcount(); if( alpha == 1 && beta == 0 ) { ConvertData cvtfunc = getConvertElem(type(), rtype); - for( i = 0; i < N; i++, ++from ) + for( size_t i = 0; i < N; i++, ++from ) { const Node* n = from.node(); uchar* to = m.ptr(n->idx); @@ -5064,7 +5053,7 @@ void SparseMat::convertTo( Mat& m, int rtype, double alpha, double beta ) const else { ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype); - for( i = 0; i < N; i++, ++from ) + for( size_t i = 0; i < N; i++, ++from ) { const Node* n = from.node(); uchar* to = m.ptr(n->idx); @@ -5098,7 +5087,7 @@ uchar* SparseMat::ptr(int i0, bool createMissing, size_t* hashval) int idx[] = { i0 }; return newNode( idx, h ); } - return 0; + return NULL; } uchar* SparseMat::ptr(int i0, int i1, bool createMissing, size_t* hashval) @@ -5120,7 +5109,7 @@ uchar* SparseMat::ptr(int i0, int i1, bool createMissing, size_t* hashval) int idx[] = { i0, i1 }; return newNode( idx, h ); } - return 0; + return NULL; } uchar* SparseMat::ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval) @@ -5143,7 +5132,7 @@ uchar* SparseMat::ptr(int i0, int i1, int i2, bool createMissing, size_t* hashva int idx[] = { i0, i1, i2 }; return newNode( idx, h ); } - return 0; + return NULL; } uchar* SparseMat::ptr(const int* idx, bool createMissing, size_t* hashval) @@ -5167,7 +5156,7 @@ uchar* SparseMat::ptr(const int* idx, bool createMissing, size_t* hashval) nidx = elem->next; } - return createMissing ? newNode(idx, h) : 0; + return createMissing ? newNode(idx, h) : NULL; } void SparseMat::erase(int i0, int i1, size_t* hashval) @@ -5241,13 +5230,13 @@ void SparseMat::resizeHashTab(size_t newsize) if((newsize & (newsize-1)) != 0) newsize = (size_t)1 << cvCeil(std::log((double)newsize)/CV_LOG2); - size_t i, hsize = hdr->hashtab.size(); + size_t hsize = hdr->hashtab.size(); std::vector _newh(newsize); size_t* newh = &_newh[0]; - for( i = 0; i < newsize; i++ ) + for( size_t i = 0; i < newsize; i++ ) newh[i] = 0; uchar* pool = &hdr->pool[0]; - for( i = 0; i < hsize; i++ ) + for( size_t i = 0; i < hsize; i++ ) { size_t nidx = hdr->hashtab[i]; while( nidx ) From fd1370b92b8d629f8459add34c1e63d22677c182 Mon Sep 17 00:00:00 2001 From: Finfa811 Date: Thu, 8 Sep 2016 10:49:48 +0200 Subject: [PATCH 129/178] Reverted BORDER_CONSTAT in stitcher.cpp Resolves #7251 --- modules/stitching/src/stitcher.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/stitching/src/stitcher.cpp b/modules/stitching/src/stitcher.cpp index 3760c75a63..19d3924337 100644 --- a/modules/stitching/src/stitcher.cpp +++ b/modules/stitching/src/stitcher.cpp @@ -192,7 +192,7 @@ Stitcher::Status Stitcher::composePanorama(InputArrayOfArrays images, OutputArra K(1,1) *= (float)seam_work_aspect_; K(1,2) *= (float)seam_work_aspect_; - corners[i] = w->warp(seam_est_imgs_[i], K, cameras_[i].R, INTER_LINEAR, BORDER_CONSTANT, images_warped[i]); + corners[i] = w->warp(seam_est_imgs_[i], K, cameras_[i].R, INTER_LINEAR, BORDER_REFLECT, images_warped[i]); sizes[i] = images_warped[i].size(); w->warp(masks[i], K, cameras_[i].R, INTER_NEAREST, BORDER_CONSTANT, masks_warped[i]); @@ -298,7 +298,7 @@ Stitcher::Status Stitcher::composePanorama(InputArrayOfArrays images, OutputArra int64 pt = getTickCount(); #endif // Warp the current image - w->warp(img, K, cameras_[img_idx].R, INTER_LINEAR, BORDER_CONSTANT, img_warped); + w->warp(img, K, cameras_[img_idx].R, INTER_LINEAR, BORDER_REFLECT, img_warped); LOGLN(" warp the current image: " << ((getTickCount() - pt) / getTickFrequency()) << " sec"); #if ENABLE_LOG pt = getTickCount(); From d5603caa0b3011e05e31b216b010a9165ec0ac29 Mon Sep 17 00:00:00 2001 From: Vladislav Sovrasov Date: Thu, 18 Aug 2016 12:37:04 +0300 Subject: [PATCH 130/178] Delete direct lapack calls, minor fixes in UI --- apps/interactive-calibration/CMakeLists.txt | 9 - apps/interactive-calibration/calibCommon.hpp | 2 +- .../cvCalibrationFork.cpp | 824 ------------------ .../cvCalibrationFork.hpp | 56 -- apps/interactive-calibration/linalg.cpp | 491 ----------- apps/interactive-calibration/linalg.hpp | 13 - apps/interactive-calibration/main.cpp | 26 +- 7 files changed, 16 insertions(+), 1405 deletions(-) delete mode 100644 apps/interactive-calibration/cvCalibrationFork.cpp delete mode 100644 apps/interactive-calibration/cvCalibrationFork.hpp delete mode 100644 apps/interactive-calibration/linalg.cpp delete mode 100644 apps/interactive-calibration/linalg.hpp diff --git a/apps/interactive-calibration/CMakeLists.txt b/apps/interactive-calibration/CMakeLists.txt index 8174c40734..74a1e169e9 100644 --- a/apps/interactive-calibration/CMakeLists.txt +++ b/apps/interactive-calibration/CMakeLists.txt @@ -5,15 +5,6 @@ if(NOT OCV_DEPENDENCIES_FOUND) return() endif() -find_package(LAPACK) -if(LAPACK_FOUND) - find_file(LAPACK_HEADER "lapacke.h") - if(LAPACK_HEADER) - add_definitions(-DUSE_LAPACK) - link_libraries(${LAPACK_LIBRARIES}) - endif() -endif() - project(interactive-calibration) set(the_target opencv_interactive-calibration) diff --git a/apps/interactive-calibration/calibCommon.hpp b/apps/interactive-calibration/calibCommon.hpp index 4580a302c4..31c74b440a 100644 --- a/apps/interactive-calibration/calibCommon.hpp +++ b/apps/interactive-calibration/calibCommon.hpp @@ -23,7 +23,7 @@ namespace calib static const std::string consoleHelp = "Hot keys:\nesc - exit application\n" "s - save current data to .xml file\n" "r - delete last frame\n" - "u - enable/disable applying undistortion" + "u - enable/disable applying undistortion\n" "d - delete all frames\n" "v - switch visualization"; diff --git a/apps/interactive-calibration/cvCalibrationFork.cpp b/apps/interactive-calibration/cvCalibrationFork.cpp deleted file mode 100644 index c603dbeb87..0000000000 --- a/apps/interactive-calibration/cvCalibrationFork.cpp +++ /dev/null @@ -1,824 +0,0 @@ -#include -#include "linalg.hpp" -#include "cvCalibrationFork.hpp" - -using namespace cv; - -static void subMatrix(const cv::Mat& src, cv::Mat& dst, const std::vector& cols, - const std::vector& rows); -static const char* cvDistCoeffErr = "Distortion coefficients must be 1x4, 4x1, 1x5, 5x1, 1x8, 8x1, 1x12, 12x1, 1x14 or 14x1 floating-point vector"; - -static void cvEvaluateJtJ2(CvMat* _JtJ, - const CvMat* camera_matrix, - const CvMat* distortion_coeffs, - const CvMat* object_points, - const CvMat* param, - const CvMat* npoints, - int flags, int NINTRINSIC, double aspectRatio) -{ - int i, pos, ni, total = 0, npstep = 0, maxPoints = 0; - - npstep = npoints->rows == 1 ? 1 : npoints->step/CV_ELEM_SIZE(npoints->type); - int nimages = npoints->rows*npoints->cols; - for( i = 0; i < nimages; i++ ) - { - ni = npoints->data.i[i*npstep]; - if( ni < 4 ) - { - CV_Error_( CV_StsOutOfRange, ("The number of points in the view #%d is < 4", i)); - } - maxPoints = MAX( maxPoints, ni ); - total += ni; - } - - Mat _Ji( maxPoints*2, NINTRINSIC, CV_64FC1, Scalar(0)); - Mat _Je( maxPoints*2, 6, CV_64FC1 ); - Mat _err( maxPoints*2, 1, CV_64FC1 ); - Mat _m( 1, total, CV_64FC2 ); - const Mat matM = cvarrToMat(object_points); - - cvZero(_JtJ); - for(i = 0, pos = 0; i < nimages; i++, pos += ni ) - { - CvMat _ri, _ti; - ni = npoints->data.i[i*npstep]; - - cvGetRows( param, &_ri, NINTRINSIC + i*6, NINTRINSIC + i*6 + 3 ); - cvGetRows( param, &_ti, NINTRINSIC + i*6 + 3, NINTRINSIC + i*6 + 6 ); - - CvMat _Mi(matM.colRange(pos, pos + ni)); - CvMat _mi(_m.colRange(pos, pos + ni)); - - _Je.resize(ni*2); _Ji.resize(ni*2); _err.resize(ni*2); - CvMat _dpdr(_Je.colRange(0, 3)); - CvMat _dpdt(_Je.colRange(3, 6)); - CvMat _dpdf(_Ji.colRange(0, 2)); - CvMat _dpdc(_Ji.colRange(2, 4)); - CvMat _dpdk(_Ji.colRange(4, NINTRINSIC)); - CvMat _mp(_err.reshape(2, 1)); - - cvProjectPoints2( &_Mi, &_ri, &_ti, camera_matrix, distortion_coeffs, &_mp, &_dpdr, &_dpdt, - (flags & CALIB_FIX_FOCAL_LENGTH) ? 0 : &_dpdf, - (flags & CALIB_FIX_PRINCIPAL_POINT) ? 0 : &_dpdc, &_dpdk, - (flags & CALIB_FIX_ASPECT_RATIO) ? aspectRatio : 0); - cvSub( &_mp, &_mi, &_mp ); - Mat JtJ(cvarrToMat(_JtJ)); - // see HZ: (A6.14) for details on the structure of the Jacobian - JtJ(Rect(0, 0, NINTRINSIC, NINTRINSIC)) += _Ji.t() * _Ji; - JtJ(Rect(NINTRINSIC + i * 6, NINTRINSIC + i * 6, 6, 6)) = _Je.t() * _Je; - JtJ(Rect(NINTRINSIC + i * 6, 0, 6, NINTRINSIC)) = _Ji.t() * _Je; - } -} - -double cvfork::cvCalibrateCamera2( const CvMat* objectPoints, - const CvMat* imagePoints, const CvMat* npoints, - CvSize imageSize, CvMat* cameraMatrix, CvMat* distCoeffs, - CvMat* rvecs, CvMat* tvecs, CvMat* stdDevs, CvMat* perViewErrors, int flags, CvTermCriteria termCrit ) -{ - { - const int NINTRINSIC = CV_CALIB_NINTRINSIC; - double reprojErr = 0; - - Matx33d A; - double k[14] = {0}; - CvMat matA = cvMat(3, 3, CV_64F, A.val), _k; - int i, nimages, maxPoints = 0, ni = 0, pos, total = 0, nparams, npstep, cn; - double aspectRatio = 0.; - - // 0. check the parameters & allocate buffers - if( !CV_IS_MAT(objectPoints) || !CV_IS_MAT(imagePoints) || - !CV_IS_MAT(npoints) || !CV_IS_MAT(cameraMatrix) || !CV_IS_MAT(distCoeffs) ) - CV_Error( CV_StsBadArg, "One of required vector arguments is not a valid matrix" ); - - if( imageSize.width <= 0 || imageSize.height <= 0 ) - CV_Error( CV_StsOutOfRange, "image width and height must be positive" ); - - if( CV_MAT_TYPE(npoints->type) != CV_32SC1 || - (npoints->rows != 1 && npoints->cols != 1) ) - CV_Error( CV_StsUnsupportedFormat, - "the array of point counters must be 1-dimensional integer vector" ); - if(flags & CV_CALIB_TILTED_MODEL) - { - //when the tilted sensor model is used the distortion coefficients matrix must have 14 parameters - if (distCoeffs->cols*distCoeffs->rows != 14) - CV_Error( CV_StsBadArg, "The tilted sensor model must have 14 parameters in the distortion matrix" ); - } - else - { - //when the thin prism model is used the distortion coefficients matrix must have 12 parameters - if(flags & CV_CALIB_THIN_PRISM_MODEL) - if (distCoeffs->cols*distCoeffs->rows != 12) - CV_Error( CV_StsBadArg, "Thin prism model must have 12 parameters in the distortion matrix" ); - } - - nimages = npoints->rows*npoints->cols; - npstep = npoints->rows == 1 ? 1 : npoints->step/CV_ELEM_SIZE(npoints->type); - - if( rvecs ) - { - cn = CV_MAT_CN(rvecs->type); - if( !CV_IS_MAT(rvecs) || - (CV_MAT_DEPTH(rvecs->type) != CV_32F && CV_MAT_DEPTH(rvecs->type) != CV_64F) || - ((rvecs->rows != nimages || (rvecs->cols*cn != 3 && rvecs->cols*cn != 9)) && - (rvecs->rows != 1 || rvecs->cols != nimages || cn != 3)) ) - CV_Error( CV_StsBadArg, "the output array of rotation vectors must be 3-channel " - "1xn or nx1 array or 1-channel nx3 or nx9 array, where n is the number of views" ); - } - - if( tvecs ) - { - cn = CV_MAT_CN(tvecs->type); - if( !CV_IS_MAT(tvecs) || - (CV_MAT_DEPTH(tvecs->type) != CV_32F && CV_MAT_DEPTH(tvecs->type) != CV_64F) || - ((tvecs->rows != nimages || tvecs->cols*cn != 3) && - (tvecs->rows != 1 || tvecs->cols != nimages || cn != 3)) ) - CV_Error( CV_StsBadArg, "the output array of translation vectors must be 3-channel " - "1xn or nx1 array or 1-channel nx3 array, where n is the number of views" ); - } - - if( stdDevs ) - { - cn = CV_MAT_CN(stdDevs->type); - if( !CV_IS_MAT(stdDevs) || - (CV_MAT_DEPTH(stdDevs->type) != CV_32F && CV_MAT_DEPTH(stdDevs->type) != CV_64F) || - ((stdDevs->rows != (nimages*6 + NINTRINSIC) || stdDevs->cols*cn != 1) && - (stdDevs->rows != 1 || stdDevs->cols != (nimages*6 + NINTRINSIC) || cn != 1)) ) - CV_Error( CV_StsBadArg, "the output array of standard deviations vectors must be 1-channel " - "1x(n*6 + NINTRINSIC) or (n*6 + NINTRINSIC)x1 array, where n is the number of views" ); - } - - if( (CV_MAT_TYPE(cameraMatrix->type) != CV_32FC1 && - CV_MAT_TYPE(cameraMatrix->type) != CV_64FC1) || - cameraMatrix->rows != 3 || cameraMatrix->cols != 3 ) - CV_Error( CV_StsBadArg, - "Intrinsic parameters must be 3x3 floating-point matrix" ); - - if( (CV_MAT_TYPE(distCoeffs->type) != CV_32FC1 && - CV_MAT_TYPE(distCoeffs->type) != CV_64FC1) || - (distCoeffs->cols != 1 && distCoeffs->rows != 1) || - (distCoeffs->cols*distCoeffs->rows != 4 && - distCoeffs->cols*distCoeffs->rows != 5 && - distCoeffs->cols*distCoeffs->rows != 8 && - distCoeffs->cols*distCoeffs->rows != 12 && - distCoeffs->cols*distCoeffs->rows != 14) ) - CV_Error( CV_StsBadArg, cvDistCoeffErr ); - - for( i = 0; i < nimages; i++ ) - { - ni = npoints->data.i[i*npstep]; - if( ni < 4 ) - { - CV_Error_( CV_StsOutOfRange, ("The number of points in the view #%d is < 4", i)); - } - maxPoints = MAX( maxPoints, ni ); - total += ni; - } - - Mat matM( 1, total, CV_64FC3 ); - Mat _m( 1, total, CV_64FC2 ); - - if(CV_MAT_CN(objectPoints->type) == 3) { - cvarrToMat(objectPoints).convertTo(matM, CV_64F); - } else { - convertPointsHomogeneous(cvarrToMat(objectPoints), matM); - } - - if(CV_MAT_CN(imagePoints->type) == 2) { - cvarrToMat(imagePoints).convertTo(_m, CV_64F); - } else { - convertPointsHomogeneous(cvarrToMat(imagePoints), _m); - } - - nparams = NINTRINSIC + nimages*6; - Mat _Ji( maxPoints*2, NINTRINSIC, CV_64FC1, Scalar(0)); - Mat _Je( maxPoints*2, 6, CV_64FC1 ); - Mat _err( maxPoints*2, 1, CV_64FC1 ); - - _k = cvMat( distCoeffs->rows, distCoeffs->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(distCoeffs->type)), k); - if( distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) < 8 ) - { - if( distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) < 5 ) - flags |= CALIB_FIX_K3; - flags |= CALIB_FIX_K4 | CALIB_FIX_K5 | CALIB_FIX_K6; - } - const double minValidAspectRatio = 0.01; - const double maxValidAspectRatio = 100.0; - - // 1. initialize intrinsic parameters & LM solver - if( flags & CALIB_USE_INTRINSIC_GUESS ) - { - cvConvert( cameraMatrix, &matA ); - if( A(0, 0) <= 0 || A(1, 1) <= 0 ) - CV_Error( CV_StsOutOfRange, "Focal length (fx and fy) must be positive" ); - if( A(0, 2) < 0 || A(0, 2) >= imageSize.width || - A(1, 2) < 0 || A(1, 2) >= imageSize.height ) - CV_Error( CV_StsOutOfRange, "Principal point must be within the image" ); - if( fabs(A(0, 1)) > 1e-5 ) - CV_Error( CV_StsOutOfRange, "Non-zero skew is not supported by the function" ); - if( fabs(A(1, 0)) > 1e-5 || fabs(A(2, 0)) > 1e-5 || - fabs(A(2, 1)) > 1e-5 || fabs(A(2,2)-1) > 1e-5 ) - CV_Error( CV_StsOutOfRange, - "The intrinsic matrix must have [fx 0 cx; 0 fy cy; 0 0 1] shape" ); - A(0, 1) = A(1, 0) = A(2, 0) = A(2, 1) = 0.; - A(2, 2) = 1.; - - if( flags & CALIB_FIX_ASPECT_RATIO ) - { - aspectRatio = A(0, 0)/A(1, 1); - - if( aspectRatio < minValidAspectRatio || aspectRatio > maxValidAspectRatio ) - CV_Error( CV_StsOutOfRange, - "The specified aspect ratio (= cameraMatrix[0][0] / cameraMatrix[1][1]) is incorrect" ); - } - cvConvert( distCoeffs, &_k ); - } - else - { - Scalar mean, sdv; - meanStdDev(matM, mean, sdv); - if( fabs(mean[2]) > 1e-5 || fabs(sdv[2]) > 1e-5 ) - CV_Error( CV_StsBadArg, - "For non-planar calibration rigs the initial intrinsic matrix must be specified" ); - for( i = 0; i < total; i++ ) - matM.at(i).z = 0.; - - if( flags & CALIB_FIX_ASPECT_RATIO ) - { - aspectRatio = cvmGet(cameraMatrix,0,0); - aspectRatio /= cvmGet(cameraMatrix,1,1); - if( aspectRatio < minValidAspectRatio || aspectRatio > maxValidAspectRatio ) - CV_Error( CV_StsOutOfRange, - "The specified aspect ratio (= cameraMatrix[0][0] / cameraMatrix[1][1]) is incorrect" ); - } - CvMat _matM(matM), m(_m); - cvInitIntrinsicParams2D( &_matM, &m, npoints, imageSize, &matA, aspectRatio ); - } - - //CvLevMarq solver( nparams, 0, termCrit ); - cvfork::CvLevMarqFork solver( nparams, 0, termCrit ); - Mat allErrors(1, total, CV_64FC2); - - if(flags & CALIB_USE_LU) { - solver.solveMethod = DECOMP_LU; - } - else if(flags & CALIB_USE_QR) - solver.solveMethod = DECOMP_QR; - - { - double* param = solver.param->data.db; - uchar* mask = solver.mask->data.ptr; - - param[0] = A(0, 0); param[1] = A(1, 1); param[2] = A(0, 2); param[3] = A(1, 2); - std::copy(k, k + 14, param + 4); - - if( flags & CV_CALIB_FIX_FOCAL_LENGTH ) - mask[0] = mask[1] = 0; - if( flags & CV_CALIB_FIX_PRINCIPAL_POINT ) - mask[2] = mask[3] = 0; - if( flags & CV_CALIB_ZERO_TANGENT_DIST ) - { - param[6] = param[7] = 0; - mask[6] = mask[7] = 0; - } - if( !(flags & CALIB_RATIONAL_MODEL) ) - flags |= CALIB_FIX_K4 + CALIB_FIX_K5 + CALIB_FIX_K6; - if( !(flags & CV_CALIB_THIN_PRISM_MODEL)) - flags |= CALIB_FIX_S1_S2_S3_S4; - if( !(flags & CV_CALIB_TILTED_MODEL)) - flags |= CALIB_FIX_TAUX_TAUY; - - mask[ 4] = !(flags & CALIB_FIX_K1); - mask[ 5] = !(flags & CALIB_FIX_K2); - mask[ 8] = !(flags & CALIB_FIX_K3); - mask[ 9] = !(flags & CALIB_FIX_K4); - mask[10] = !(flags & CALIB_FIX_K5); - mask[11] = !(flags & CALIB_FIX_K6); - - if(flags & CALIB_FIX_S1_S2_S3_S4) - { - mask[12] = 0; - mask[13] = 0; - mask[14] = 0; - mask[15] = 0; - } - if(flags & CALIB_FIX_TAUX_TAUY) - { - mask[16] = 0; - mask[17] = 0; - } - } - - // 2. initialize extrinsic parameters - for( i = 0, pos = 0; i < nimages; i++, pos += ni ) - { - CvMat _ri, _ti; - ni = npoints->data.i[i*npstep]; - - cvGetRows( solver.param, &_ri, NINTRINSIC + i*6, NINTRINSIC + i*6 + 3 ); - cvGetRows( solver.param, &_ti, NINTRINSIC + i*6 + 3, NINTRINSIC + i*6 + 6 ); - - CvMat _Mi(matM.colRange(pos, pos + ni)); - CvMat _mi(_m.colRange(pos, pos + ni)); - - cvFindExtrinsicCameraParams2( &_Mi, &_mi, &matA, &_k, &_ri, &_ti ); - } - - // 3. run the optimization - for(;;) - { - const CvMat* _param = 0; - CvMat *_JtJ = 0, *_JtErr = 0; - double* _errNorm = 0; - bool proceed = solver.updateAlt( _param, _JtJ, _JtErr, _errNorm ); - double *param = solver.param->data.db, *pparam = solver.prevParam->data.db; - - if( flags & CALIB_FIX_ASPECT_RATIO ) - { - param[0] = param[1]*aspectRatio; - pparam[0] = pparam[1]*aspectRatio; - } - - A(0, 0) = param[0]; A(1, 1) = param[1]; A(0, 2) = param[2]; A(1, 2) = param[3]; - std::copy(param + 4, param + 4 + 14, k); - - if( !proceed ) { - //do errors estimation - if(stdDevs) { - Ptr JtJ(cvCreateMat(nparams, nparams, CV_64F)); - CvMat cvMatM(matM); - cvEvaluateJtJ2(JtJ, &matA, &_k, &cvMatM, solver.param, npoints, flags, NINTRINSIC, aspectRatio); - - Mat mask = cvarrToMat(solver.mask); - int nparams_nz = countNonZero(mask); - Mat JtJinv, JtJN; - JtJN.create(nparams_nz, nparams_nz, CV_64F); - subMatrix(cvarrToMat(JtJ), JtJN, mask, mask); - completeSymm(JtJN, false); - #ifndef USE_LAPACK - cv::invert(JtJN, JtJinv, DECOMP_SVD); - #else - cvfork::invert(JtJN, JtJinv, DECOMP_SVD); - #endif - double sigma2 = norm(allErrors, NORM_L2SQR) / (total - nparams_nz); - Mat stdDevsM = cvarrToMat(stdDevs); - int j = 0; - for (int s = 0; s < nparams; s++) - if(mask.data[s]) { - stdDevsM.at(s) = std::sqrt(JtJinv.at(j,j)*sigma2); - j++; - } - else - stdDevsM.at(s) = 0; - } - break; - } - - reprojErr = 0; - - for( i = 0, pos = 0; i < nimages; i++, pos += ni ) - { - CvMat _ri, _ti; - ni = npoints->data.i[i*npstep]; - - cvGetRows( solver.param, &_ri, NINTRINSIC + i*6, NINTRINSIC + i*6 + 3 ); - cvGetRows( solver.param, &_ti, NINTRINSIC + i*6 + 3, NINTRINSIC + i*6 + 6 ); - - CvMat _Mi(matM.colRange(pos, pos + ni)); - CvMat _mi(_m.colRange(pos, pos + ni)); - CvMat _me(allErrors.colRange(pos, pos + ni)); - - _Je.resize(ni*2); _Ji.resize(ni*2); _err.resize(ni*2); - CvMat _dpdr(_Je.colRange(0, 3)); - CvMat _dpdt(_Je.colRange(3, 6)); - CvMat _dpdf(_Ji.colRange(0, 2)); - CvMat _dpdc(_Ji.colRange(2, 4)); - CvMat _dpdk(_Ji.colRange(4, NINTRINSIC)); - CvMat _mp(_err.reshape(2, 1)); - - if( solver.state == CvLevMarq::CALC_J ) - { - cvProjectPoints2( &_Mi, &_ri, &_ti, &matA, &_k, &_mp, &_dpdr, &_dpdt, - (flags & CALIB_FIX_FOCAL_LENGTH) ? 0 : &_dpdf, - (flags & CALIB_FIX_PRINCIPAL_POINT) ? 0 : &_dpdc, &_dpdk, - (flags & CALIB_FIX_ASPECT_RATIO) ? aspectRatio : 0); - } - else - cvProjectPoints2( &_Mi, &_ri, &_ti, &matA, &_k, &_mp ); - - cvSub( &_mp, &_mi, &_mp ); - - if( solver.state == CvLevMarq::CALC_J ) - { - Mat JtJ(cvarrToMat(_JtJ)), JtErr(cvarrToMat(_JtErr)); - - // see HZ: (A6.14) for details on the structure of the Jacobian - JtJ(Rect(0, 0, NINTRINSIC, NINTRINSIC)) += _Ji.t() * _Ji; - JtJ(Rect(NINTRINSIC + i * 6, NINTRINSIC + i * 6, 6, 6)) = _Je.t() * _Je; - JtJ(Rect(NINTRINSIC + i * 6, 0, 6, NINTRINSIC)) = _Ji.t() * _Je; - - JtErr.rowRange(0, NINTRINSIC) += _Ji.t() * _err; - JtErr.rowRange(NINTRINSIC + i * 6, NINTRINSIC + (i + 1) * 6) = _Je.t() * _err; - - } - if (stdDevs || perViewErrors) - cvCopy(&_mp, &_me); - reprojErr += norm(_err, NORM_L2SQR); - } - - if( _errNorm ) - *_errNorm = reprojErr; - } - - // 4. store the results - cvConvert( &matA, cameraMatrix ); - cvConvert( &_k, distCoeffs ); - - for( i = 0, pos = 0; i < nimages; i++) - { - CvMat src, dst; - if( perViewErrors ) - { - ni = npoints->data.i[i*npstep]; - perViewErrors->data.db[i] = std::sqrt(cv::norm(allErrors.colRange(pos, pos + ni), NORM_L2SQR) / ni); - pos+=ni; - } - - if( rvecs ) - { - src = cvMat( 3, 1, CV_64F, solver.param->data.db + NINTRINSIC + i*6 ); - if( rvecs->rows == nimages && rvecs->cols*CV_MAT_CN(rvecs->type) == 9 ) - { - dst = cvMat( 3, 3, CV_MAT_DEPTH(rvecs->type), - rvecs->data.ptr + rvecs->step*i ); - cvRodrigues2( &src, &matA ); - cvConvert( &matA, &dst ); - } - else - { - dst = cvMat( 3, 1, CV_MAT_DEPTH(rvecs->type), rvecs->rows == 1 ? - rvecs->data.ptr + i*CV_ELEM_SIZE(rvecs->type) : - rvecs->data.ptr + rvecs->step*i ); - cvConvert( &src, &dst ); - } - } - if( tvecs ) - { - src = cvMat( 3, 1, CV_64F, solver.param->data.db + NINTRINSIC + i*6 + 3 ); - dst = cvMat( 3, 1, CV_MAT_DEPTH(tvecs->type), tvecs->rows == 1 ? - tvecs->data.ptr + i*CV_ELEM_SIZE(tvecs->type) : - tvecs->data.ptr + tvecs->step*i ); - cvConvert( &src, &dst ); - } - } - - return std::sqrt(reprojErr/total); - } -} - - -static Mat prepareCameraMatrix(Mat& cameraMatrix0, int rtype) -{ - Mat cameraMatrix = Mat::eye(3, 3, rtype); - if( cameraMatrix0.size() == cameraMatrix.size() ) - cameraMatrix0.convertTo(cameraMatrix, rtype); - return cameraMatrix; -} - -static Mat prepareDistCoeffs(Mat& distCoeffs0, int rtype) -{ - Mat distCoeffs = Mat::zeros(distCoeffs0.cols == 1 ? Size(1, 14) : Size(14, 1), rtype); - if( distCoeffs0.size() == Size(1, 4) || - distCoeffs0.size() == Size(1, 5) || - distCoeffs0.size() == Size(1, 8) || - distCoeffs0.size() == Size(1, 12) || - distCoeffs0.size() == Size(1, 14) || - distCoeffs0.size() == Size(4, 1) || - distCoeffs0.size() == Size(5, 1) || - distCoeffs0.size() == Size(8, 1) || - distCoeffs0.size() == Size(12, 1) || - distCoeffs0.size() == Size(14, 1) ) - { - Mat dstCoeffs(distCoeffs, Rect(0, 0, distCoeffs0.cols, distCoeffs0.rows)); - distCoeffs0.convertTo(dstCoeffs, rtype); - } - return distCoeffs; -} - -static void collectCalibrationData( InputArrayOfArrays objectPoints, - InputArrayOfArrays imagePoints1, - InputArrayOfArrays imagePoints2, - Mat& objPtMat, Mat& imgPtMat1, Mat* imgPtMat2, - Mat& npoints ) -{ - int nimages = (int)objectPoints.total(); - int i, j = 0, ni = 0, total = 0; - CV_Assert(nimages > 0 && nimages == (int)imagePoints1.total() && - (!imgPtMat2 || nimages == (int)imagePoints2.total())); - - for( i = 0; i < nimages; i++ ) - { - ni = objectPoints.getMat(i).checkVector(3, CV_32F); - if( ni <= 0 ) - CV_Error(CV_StsUnsupportedFormat, "objectPoints should contain vector of vectors of points of type Point3f"); - int ni1 = imagePoints1.getMat(i).checkVector(2, CV_32F); - if( ni1 <= 0 ) - CV_Error(CV_StsUnsupportedFormat, "imagePoints1 should contain vector of vectors of points of type Point2f"); - CV_Assert( ni == ni1 ); - - total += ni; - } - - npoints.create(1, (int)nimages, CV_32S); - objPtMat.create(1, (int)total, CV_32FC3); - imgPtMat1.create(1, (int)total, CV_32FC2); - Point2f* imgPtData2 = 0; - - if( imgPtMat2 ) - { - imgPtMat2->create(1, (int)total, CV_32FC2); - imgPtData2 = imgPtMat2->ptr(); - } - - Point3f* objPtData = objPtMat.ptr(); - Point2f* imgPtData1 = imgPtMat1.ptr(); - - for( i = 0; i < nimages; i++, j += ni ) - { - Mat objpt = objectPoints.getMat(i); - Mat imgpt1 = imagePoints1.getMat(i); - ni = objpt.checkVector(3, CV_32F); - npoints.at(i) = ni; - memcpy( objPtData + j, objpt.ptr(), ni*sizeof(objPtData[0]) ); - memcpy( imgPtData1 + j, imgpt1.ptr(), ni*sizeof(imgPtData1[0]) ); - - if( imgPtData2 ) - { - Mat imgpt2 = imagePoints2.getMat(i); - int ni2 = imgpt2.checkVector(2, CV_32F); - CV_Assert( ni == ni2 ); - memcpy( imgPtData2 + j, imgpt2.ptr(), ni*sizeof(imgPtData2[0]) ); - } - } -} - -double cvfork::calibrateCamera(InputArrayOfArrays _objectPoints, - InputArrayOfArrays _imagePoints, - Size imageSize, InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs, - OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, OutputArray _stdDeviations, OutputArray _perViewErrors, int flags, TermCriteria criteria ) -{ - int rtype = CV_64F; - Mat cameraMatrix = _cameraMatrix.getMat(); - cameraMatrix = prepareCameraMatrix(cameraMatrix, rtype); - Mat distCoeffs = _distCoeffs.getMat(); - distCoeffs = prepareDistCoeffs(distCoeffs, rtype); - if( !(flags & CALIB_RATIONAL_MODEL) && - (!(flags & CALIB_THIN_PRISM_MODEL)) && - (!(flags & CALIB_TILTED_MODEL))) - distCoeffs = distCoeffs.rows == 1 ? distCoeffs.colRange(0, 5) : distCoeffs.rowRange(0, 5); - - int nimages = int(_objectPoints.total()); - CV_Assert( nimages > 0 ); - Mat objPt, imgPt, npoints, rvecM, tvecM, stdDeviationsM, errorsM; - - bool rvecs_needed = _rvecs.needed(), tvecs_needed = _tvecs.needed(), - stddev_needed = _stdDeviations.needed(), errors_needed = _perViewErrors.needed(); - - bool rvecs_mat_vec = _rvecs.isMatVector(); - bool tvecs_mat_vec = _tvecs.isMatVector(); - - if( rvecs_needed ) { - _rvecs.create(nimages, 1, CV_64FC3); - - if(rvecs_mat_vec) - rvecM.create(nimages, 3, CV_64F); - else - rvecM = _rvecs.getMat(); - } - - if( tvecs_needed ) { - _tvecs.create(nimages, 1, CV_64FC3); - - if(tvecs_mat_vec) - tvecM.create(nimages, 3, CV_64F); - else - tvecM = _tvecs.getMat(); - } - - if( stddev_needed ) { - _stdDeviations.create(nimages*6 + CV_CALIB_NINTRINSIC, 1, CV_64F); - stdDeviationsM = _stdDeviations.getMat(); - } - - if( errors_needed) { - _perViewErrors.create(nimages, 1, CV_64F); - errorsM = _perViewErrors.getMat(); - } - - collectCalibrationData( _objectPoints, _imagePoints, noArray(), - objPt, imgPt, 0, npoints ); - CvMat c_objPt = objPt, c_imgPt = imgPt, c_npoints = npoints; - CvMat c_cameraMatrix = cameraMatrix, c_distCoeffs = distCoeffs; - CvMat c_rvecM = rvecM, c_tvecM = tvecM, c_stdDev = stdDeviationsM, c_errors = errorsM; - - double reprojErr = cvfork::cvCalibrateCamera2(&c_objPt, &c_imgPt, &c_npoints, imageSize, - &c_cameraMatrix, &c_distCoeffs, - rvecs_needed ? &c_rvecM : NULL, - tvecs_needed ? &c_tvecM : NULL, - stddev_needed ? &c_stdDev : NULL, - errors_needed ? &c_errors : NULL, flags, criteria ); - - // overly complicated and inefficient rvec/ tvec handling to support vector - for(int i = 0; i < nimages; i++ ) - { - if( rvecs_needed && rvecs_mat_vec) - { - _rvecs.create(3, 1, CV_64F, i, true); - Mat rv = _rvecs.getMat(i); - memcpy(rv.ptr(), rvecM.ptr(i), 3*sizeof(double)); - } - if( tvecs_needed && tvecs_mat_vec) - { - _tvecs.create(3, 1, CV_64F, i, true); - Mat tv = _tvecs.getMat(i); - memcpy(tv.ptr(), tvecM.ptr(i), 3*sizeof(double)); - } - } - - cameraMatrix.copyTo(_cameraMatrix); - distCoeffs.copyTo(_distCoeffs); - - return reprojErr; -} - -double cvfork::calibrateCameraCharuco(InputArrayOfArrays _charucoCorners, InputArrayOfArrays _charucoIds, - Ptr &_board, Size imageSize, - InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs, - OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, OutputArray _stdDeviations, OutputArray _perViewErrors, - int flags, TermCriteria criteria) { - - CV_Assert(_charucoIds.total() > 0 && (_charucoIds.total() == _charucoCorners.total())); - - // Join object points of charuco corners in a single vector for calibrateCamera() function - std::vector< std::vector< Point3f > > allObjPoints; - allObjPoints.resize(_charucoIds.total()); - for(unsigned int i = 0; i < _charucoIds.total(); i++) { - unsigned int nCorners = (unsigned int)_charucoIds.getMat(i).total(); - CV_Assert(nCorners > 0 && nCorners == _charucoCorners.getMat(i).total()); //actually nCorners must be > 3 for calibration - allObjPoints[i].reserve(nCorners); - - for(unsigned int j = 0; j < nCorners; j++) { - int pointId = _charucoIds.getMat(i).ptr< int >(0)[j]; - CV_Assert(pointId >= 0 && pointId < (int)_board->chessboardCorners.size()); - allObjPoints[i].push_back(_board->chessboardCorners[pointId]); - } - } - - return cvfork::calibrateCamera(allObjPoints, _charucoCorners, imageSize, _cameraMatrix, _distCoeffs, - _rvecs, _tvecs, _stdDeviations, _perViewErrors, flags, criteria); -} - - -static void subMatrix(const cv::Mat& src, cv::Mat& dst, const std::vector& cols, - const std::vector& rows) { - int nonzeros_cols = cv::countNonZero(cols); - cv::Mat tmp(src.rows, nonzeros_cols, CV_64FC1); - - for (int i = 0, j = 0; i < (int)cols.size(); i++) - { - if (cols[i]) - { - src.col(i).copyTo(tmp.col(j++)); - } - } - - int nonzeros_rows = cv::countNonZero(rows); - dst.create(nonzeros_rows, nonzeros_cols, CV_64FC1); - for (int i = 0, j = 0; i < (int)rows.size(); i++) - { - if (rows[i]) - { - tmp.row(i).copyTo(dst.row(j++)); - } - } -} - -void cvfork::CvLevMarqFork::step() -{ - using namespace cv; - const double LOG10 = log(10.); - double lambda = exp(lambdaLg10*LOG10); - int nparams = param->rows; - - Mat _JtJ = cvarrToMat(JtJ); - Mat _mask = cvarrToMat(mask); - - int nparams_nz = countNonZero(_mask); - if(!JtJN || JtJN->rows != nparams_nz) { - // prevent re-allocation in every step - JtJN.reset(cvCreateMat( nparams_nz, nparams_nz, CV_64F )); - JtJV.reset(cvCreateMat( nparams_nz, 1, CV_64F )); - JtJW.reset(cvCreateMat( nparams_nz, 1, CV_64F )); - } - - Mat _JtJN = cvarrToMat(JtJN); - Mat _JtErr = cvarrToMat(JtJV); - Mat_ nonzero_param = cvarrToMat(JtJW); - - subMatrix(cvarrToMat(JtErr), _JtErr, std::vector(1, 1), _mask); - subMatrix(_JtJ, _JtJN, _mask, _mask); - - if( !err ) - completeSymm( _JtJN, completeSymmFlag ); -#if 1 - _JtJN.diag() *= 1. + lambda; -#else - _JtJN.diag() += lambda; -#endif -#ifndef USE_LAPACK - cv::solve(_JtJN, _JtErr, nonzero_param, solveMethod); -#else - cvfork::solve(_JtJN, _JtErr, nonzero_param, solveMethod); -#endif - - int j = 0; - for( int i = 0; i < nparams; i++ ) - param->data.db[i] = prevParam->data.db[i] - (mask->data.ptr[i] ? nonzero_param(j++) : 0); -} - -cvfork::CvLevMarqFork::CvLevMarqFork(int nparams, int nerrs, CvTermCriteria criteria0, bool _completeSymmFlag) -{ - init(nparams, nerrs, criteria0, _completeSymmFlag); -} - -cvfork::CvLevMarqFork::~CvLevMarqFork() -{ - clear(); -} - -bool cvfork::CvLevMarqFork::updateAlt( const CvMat*& _param, CvMat*& _JtJ, CvMat*& _JtErr, double*& _errNorm ) -{ - CV_Assert( !err ); - if( state == DONE ) - { - _param = param; - return false; - } - - if( state == STARTED ) - { - _param = param; - cvZero( JtJ ); - cvZero( JtErr ); - errNorm = 0; - _JtJ = JtJ; - _JtErr = JtErr; - _errNorm = &errNorm; - state = CALC_J; - return true; - } - - if( state == CALC_J ) - { - cvCopy( param, prevParam ); - step(); - _param = param; - prevErrNorm = errNorm; - errNorm = 0; - _errNorm = &errNorm; - state = CHECK_ERR; - return true; - } - - assert( state == CHECK_ERR ); - if( errNorm > prevErrNorm ) - { - if( ++lambdaLg10 <= 16 ) - { - step(); - _param = param; - errNorm = 0; - _errNorm = &errNorm; - state = CHECK_ERR; - return true; - } - } - - lambdaLg10 = MAX(lambdaLg10-1, -16); - if( ++iters >= criteria.max_iter || - cvNorm(param, prevParam, CV_RELATIVE_L2) < criteria.epsilon ) - { - //printf("iters %i\n", iters); - _param = param; - state = DONE; - return false; - } - - prevErrNorm = errNorm; - cvZero( JtJ ); - cvZero( JtErr ); - _param = param; - _JtJ = JtJ; - _JtErr = JtErr; - state = CALC_J; - return true; -} diff --git a/apps/interactive-calibration/cvCalibrationFork.hpp b/apps/interactive-calibration/cvCalibrationFork.hpp deleted file mode 100644 index 075f251ef5..0000000000 --- a/apps/interactive-calibration/cvCalibrationFork.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef CV_CALIBRATION_FORK_HPP -#define CV_CALIBRATION_FORK_HPP - -#include -#include -#include -#include - -namespace cvfork -{ -using namespace cv; - -#define CV_CALIB_NINTRINSIC 18 -#define CALIB_USE_QR (1 << 18) - -double calibrateCamera(InputArrayOfArrays objectPoints, - InputArrayOfArrays imagePoints, Size imageSize, - InputOutputArray cameraMatrix, InputOutputArray distCoeffs, - OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, OutputArray stdDeviations, - OutputArray perViewErrors, int flags = 0, TermCriteria criteria = TermCriteria( - TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); - -double cvCalibrateCamera2( const CvMat* object_points, - const CvMat* image_points, - const CvMat* point_counts, - CvSize image_size, - CvMat* camera_matrix, - CvMat* distortion_coeffs, - CvMat* rotation_vectors CV_DEFAULT(NULL), - CvMat* translation_vectors CV_DEFAULT(NULL), - CvMat* stdDeviations_vector CV_DEFAULT(NULL), - CvMat* perViewErrors_vector CV_DEFAULT(NULL), - int flags CV_DEFAULT(0), - CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria( - CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,DBL_EPSILON)) ); - -double calibrateCameraCharuco(InputArrayOfArrays _charucoCorners, InputArrayOfArrays _charucoIds, - Ptr &_board, Size imageSize, - InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs, - OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, OutputArray _stdDeviations, OutputArray _perViewErrors, - int flags = 0, TermCriteria criteria = TermCriteria( - TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); - -class CvLevMarqFork : public CvLevMarq -{ -public: - CvLevMarqFork( int nparams, int nerrs, CvTermCriteria criteria= - cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON), - bool completeSymmFlag=false ); - bool updateAlt( const CvMat*& _param, CvMat*& _JtJ, CvMat*& _JtErr, double*& _errNorm ); - void step(); - ~CvLevMarqFork(); -}; -} - -#endif diff --git a/apps/interactive-calibration/linalg.cpp b/apps/interactive-calibration/linalg.cpp deleted file mode 100644 index e75b4d2d93..0000000000 --- a/apps/interactive-calibration/linalg.cpp +++ /dev/null @@ -1,491 +0,0 @@ -#include "linalg.hpp" - -#ifdef USE_LAPACK - -typedef int integer; -#include - -#include -using namespace cv; - -bool cvfork::solve(InputArray _src, const InputArray _src2arg, OutputArray _dst, int method ) - { - bool result = true; - Mat src = _src.getMat(), _src2 = _src2arg.getMat(); - int type = src.type(); - bool is_normal = (method & DECOMP_NORMAL) != 0; - - CV_Assert( type == _src2.type() && (type == CV_32F || type == CV_64F) ); - - method &= ~DECOMP_NORMAL; - CV_Assert( (method != DECOMP_LU && method != DECOMP_CHOLESKY) || - is_normal || src.rows == src.cols ); - - double rcond=-1, s1=0, work1=0, *work=0, *s=0; - float frcond=-1, fs1=0, fwork1=0, *fwork=0, *fs=0; - integer m = src.rows, m_ = m, n = src.cols, mn = std::max(m,n), - nm = std::min(m, n), nb = _src2.cols, lwork=-1, liwork=0, iwork1=0, - lda = m, ldx = mn, info=0, rank=0, *iwork=0; - int elem_size = CV_ELEM_SIZE(type); - bool copy_rhs=false; - int buf_size=0; - AutoBuffer buffer; - uchar* ptr; - char N[] = {'N', '\0'}, L[] = {'L', '\0'}; - - Mat src2 = _src2; - _dst.create( src.cols, src2.cols, src.type() ); - Mat dst = _dst.getMat(); - - if( m <= n ) - is_normal = false; - else if( is_normal ) - m_ = n; - - buf_size += (is_normal ? n*n : m*n)*elem_size; - - if( m_ != n || nb > 1 || !dst.isContinuous() ) - { - copy_rhs = true; - if( is_normal ) - buf_size += n*nb*elem_size; - else - buf_size += mn*nb*elem_size; - } - - if( method == DECOMP_SVD || method == DECOMP_EIG ) - { - integer nlvl = cvRound(std::log(std::max(std::min(m_,n)/25., 1.))/CV_LOG2) + 1; - liwork = std::min(m_,n)*(3*std::max(nlvl,(integer)0) + 11); - - if( type == CV_32F ) - sgelsd_(&m_, &n, &nb, (float*)src.data, &lda, (float*)dst.data, &ldx, - &fs1, &frcond, &rank, &fwork1, &lwork, &iwork1, &info); - else - dgelsd_(&m_, &n, &nb, (double*)src.data, &lda, (double*)dst.data, &ldx, - &s1, &rcond, &rank, &work1, &lwork, &iwork1, &info ); - buf_size += nm*elem_size + (liwork + 1)*sizeof(integer); - } - else if( method == DECOMP_QR ) - { - if( type == CV_32F ) - sgels_(N, &m_, &n, &nb, (float*)src.data, &lda, - (float*)dst.data, &ldx, &fwork1, &lwork, &info ); - else - dgels_(N, &m_, &n, &nb, (double*)src.data, &lda, - (double*)dst.data, &ldx, &work1, &lwork, &info ); - } - else if( method == DECOMP_LU ) - { - buf_size += (n+1)*sizeof(integer); - } - else if( method == DECOMP_CHOLESKY ) - ; - else - CV_Error( Error::StsBadArg, "Unknown method" ); - assert(info == 0); - - lwork = cvRound(type == CV_32F ? (double)fwork1 : work1); - buf_size += lwork*elem_size; - buffer.allocate(buf_size); - ptr = (uchar*)buffer; - - Mat at(n, m_, type, ptr); - ptr += n*m_*elem_size; - - if( method == DECOMP_CHOLESKY || method == DECOMP_EIG ) - src.copyTo(at); - else if( !is_normal ) - transpose(src, at); - else - mulTransposed(src, at, true); - - Mat xt; - if( !is_normal ) - { - if( copy_rhs ) - { - Mat temp(nb, mn, type, ptr); - ptr += nb*mn*elem_size; - Mat bt = temp.colRange(0, m); - xt = temp.colRange(0, n); - transpose(src2, bt); - } - else - { - src2.copyTo(dst); - xt = Mat(1, n, type, dst.data); - } - } - else - { - if( copy_rhs ) - { - xt = Mat(nb, n, type, ptr); - ptr += nb*n*elem_size; - } - else - xt = Mat(1, n, type, dst.data); - // (a'*b)' = b'*a - gemm( src2, src, 1, Mat(), 0, xt, GEMM_1_T ); - } - - lda = (int)(at.step ? at.step/elem_size : at.cols); - ldx = (int)(xt.step ? xt.step/elem_size : (!is_normal && copy_rhs ? mn : n)); - - if( method == DECOMP_SVD || method == DECOMP_EIG ) - { - if( type == CV_32F ) - { - fs = (float*)ptr; - ptr += nm*elem_size; - fwork = (float*)ptr; - ptr += lwork*elem_size; - iwork = (integer*)alignPtr(ptr, sizeof(integer)); - - sgelsd_(&m_, &n, &nb, (float*)at.data, &lda, (float*)xt.data, &ldx, - fs, &frcond, &rank, fwork, &lwork, iwork, &info); - } - else - { - s = (double*)ptr; - ptr += nm*elem_size; - work = (double*)ptr; - ptr += lwork*elem_size; - iwork = (integer*)alignPtr(ptr, sizeof(integer)); - - dgelsd_(&m_, &n, &nb, (double*)at.data, &lda, (double*)xt.data, &ldx, - s, &rcond, &rank, work, &lwork, iwork, &info); - } - } - else if( method == DECOMP_QR ) - { - if( type == CV_32F ) - { - fwork = (float*)ptr; - sgels_(N, &m_, &n, &nb, (float*)at.data, &lda, - (float*)xt.data, &ldx, fwork, &lwork, &info); - } - else - { - work = (double*)ptr; - dgels_(N, &m_, &n, &nb, (double*)at.data, &lda, - (double*)xt.data, &ldx, work, &lwork, &info); - } - } - else if( method == DECOMP_CHOLESKY || (method == DECOMP_LU && is_normal) ) - { - if( type == CV_32F ) - { - spotrf_(L, &n, (float*)at.data, &lda, &info); - if(info==0) - spotrs_(L, &n, &nb, (float*)at.data, &lda, (float*)xt.data, &ldx, &info); - } - else - { - dpotrf_(L, &n, (double*)at.data, &lda, &info); - if(info==0) - dpotrs_(L, &n, &nb, (double*)at.data, &lda, (double*)xt.data, &ldx, &info); - } - } - else if( method == DECOMP_LU ) - { - iwork = (integer*)alignPtr(ptr, sizeof(integer)); - if( type == CV_32F ) - sgesv_(&n, &nb, (float*)at.data, &lda, iwork, (float*)xt.data, &ldx, &info ); - else - dgesv_(&n, &nb, (double*)at.data, &lda, iwork, (double*)xt.data, &ldx, &info ); - } - else - assert(0); - result = info == 0; - - if( !result ) - dst = Scalar(0); - else if( xt.data != dst.data ) - transpose( xt, dst ); - - return result; - } - -static void _SVDcompute( const InputArray _aarr, OutputArray _w, - OutputArray _u, OutputArray _vt, int flags = 0) -{ - Mat a = _aarr.getMat(), u, vt; - integer m = a.rows, n = a.cols, mn = std::max(m, n), nm = std::min(m, n); - int type = a.type(), elem_size = (int)a.elemSize(); - bool compute_uv = _u.needed() || _vt.needed(); - - if( flags & SVD::NO_UV ) - { - _u.release(); - _vt.release(); - compute_uv = false; - } - - if( compute_uv ) - { - _u.create( (int)m, (int)((flags & SVD::FULL_UV) ? m : nm), type ); - _vt.create( (int)((flags & SVD::FULL_UV) ? n : nm), n, type ); - u = _u.getMat(); - vt = _vt.getMat(); - } - - _w.create(nm, 1, type, -1, true); - - Mat _a = a, w = _w.getMat(); - CV_Assert( w.isContinuous() ); - int work_ofs=0, iwork_ofs=0, buf_size = 0; - bool temp_a = false; - double u1=0, v1=0, work1=0; - float uf1=0, vf1=0, workf1=0; - integer lda, ldu, ldv, lwork=-1, iwork1=0, info=0; - char mode[] = {compute_uv ? 'S' : 'N', '\0'}; - - if( m != n && compute_uv && (flags & SVD::FULL_UV) ) - mode[0] = 'A'; - - if( !(flags & SVD::MODIFY_A) ) - { - if( mode[0] == 'N' || mode[0] == 'A' ) - temp_a = true; - else if( compute_uv && (a.size() == vt.size() || a.size() == u.size()) && mode[0] == 'S' ) - mode[0] = 'O'; - } - - lda = a.cols; - ldv = ldu = mn; - - if( type == CV_32F ) - { - sgesdd_(mode, &n, &m, (float*)a.data, &lda, (float*)w.data, - &vf1, &ldv, &uf1, &ldu, &workf1, &lwork, &iwork1, &info ); - lwork = cvRound(workf1); - } - else - { - dgesdd_(mode, &n, &m, (double*)a.data, &lda, (double*)w.data, - &v1, &ldv, &u1, &ldu, &work1, &lwork, &iwork1, &info ); - lwork = cvRound(work1); - } - - assert(info == 0); - if( temp_a ) - { - buf_size += n*m*elem_size; - } - work_ofs = buf_size; - buf_size += lwork*elem_size; - buf_size = alignSize(buf_size, sizeof(integer)); - iwork_ofs = buf_size; - buf_size += 8*nm*sizeof(integer); - - AutoBuffer buf(buf_size); - uchar* buffer = (uchar*)buf; - - if( temp_a ) - { - _a = Mat(a.rows, a.cols, type, buffer ); - a.copyTo(_a); - } - - if( !(flags & SVD::MODIFY_A) && !temp_a ) - { - if( compute_uv && a.size() == vt.size() ) - { - a.copyTo(vt); - _a = vt; - } - else if( compute_uv && a.size() == u.size() ) - { - a.copyTo(u); - _a = u; - } - } - - if( compute_uv ) - { - ldv = (int)(vt.step ? vt.step/elem_size : vt.cols); - ldu = (int)(u.step ? u.step/elem_size : u.cols); - } - - lda = (int)(_a.step ? _a.step/elem_size : _a.cols); - if( type == CV_32F ) - { - sgesdd_(mode, &n, &m, _a.ptr(), &lda, w.ptr(), - vt.data ? vt.ptr() : (float*)&v1, &ldv, - u.data ? u.ptr() : (float*)&u1, &ldu, - (float*)(buffer + work_ofs), &lwork, - (integer*)(buffer + iwork_ofs), &info ); - } - else - { - dgesdd_(mode, &n, &m, _a.ptr(), &lda, w.ptr(), - vt.data ? vt.ptr() : &v1, &ldv, - u.data ? u.ptr() : &u1, &ldu, - (double*)(buffer + work_ofs), &lwork, - (integer*)(buffer + iwork_ofs), &info ); - } - CV_Assert(info >= 0); - if(info != 0) - { - if( u.data ) - u = Scalar(0.); - if( vt.data ) - vt = Scalar(0.); - w = Scalar(0.); - } -} -////////////////////////////////////////////////////////// -template static void -MatrAXPY( int m, int n, const T1* x, int dx, - const T2* a, int inca, T3* y, int dy ) -{ - int i, j; - for( i = 0; i < m; i++, x += dx, y += dy ) - { - T2 s = a[i*inca]; - for( j = 0; j <= n - 4; j += 4 ) - { - T3 t0 = (T3)(y[j] + s*x[j]); - T3 t1 = (T3)(y[j+1] + s*x[j+1]); - y[j] = t0; - y[j+1] = t1; - t0 = (T3)(y[j+2] + s*x[j+2]); - t1 = (T3)(y[j+3] + s*x[j+3]); - y[j+2] = t0; - y[j+3] = t1; - } - - for( ; j < n; j++ ) - y[j] = (T3)(y[j] + s*x[j]); - } -} -template static void -SVBkSb( int m, int n, const T* w, int incw, - const T* u, int ldu, int uT, - const T* v, int ldv, int vT, - const T* b, int ldb, int nb, - T* x, int ldx, double* buffer, T eps ) -{ - double threshold = 0; - int udelta0 = uT ? ldu : 1, udelta1 = uT ? 1 : ldu; - int vdelta0 = vT ? ldv : 1, vdelta1 = vT ? 1 : ldv; - int i, j, nm = std::min(m, n); - - if( !b ) - nb = m; - - for( i = 0; i < n; i++ ) - for( j = 0; j < nb; j++ ) - x[i*ldx + j] = 0; - - for( i = 0; i < nm; i++ ) - threshold += w[i*incw]; - threshold *= eps; - - // v * inv(w) * uT * b - for( i = 0; i < nm; i++, u += udelta0, v += vdelta0 ) - { - double wi = w[i*incw]; - if( wi <= threshold ) - continue; - wi = 1/wi; - - if( nb == 1 ) - { - double s = 0; - if( b ) - for( j = 0; j < m; j++ ) - s += u[j*udelta1]*b[j*ldb]; - else - s = u[0]; - s *= wi; - - for( j = 0; j < n; j++ ) - x[j*ldx] = (T)(x[j*ldx] + s*v[j*vdelta1]); - } - else - { - if( b ) - { - for( j = 0; j < nb; j++ ) - buffer[j] = 0; - MatrAXPY( m, nb, b, ldb, u, udelta1, buffer, 0 ); - for( j = 0; j < nb; j++ ) - buffer[j] *= wi; - } - else - { - for( j = 0; j < nb; j++ ) - buffer[j] = u[j*udelta1]*wi; - } - MatrAXPY( n, nb, buffer, 0, v, vdelta1, x, ldx ); - } - } -} - -static void _backSubst( const InputArray _w, const InputArray _u, const InputArray _vt, - const InputArray _rhs, OutputArray _dst ) -{ - Mat w = _w.getMat(), u = _u.getMat(), vt = _vt.getMat(), rhs = _rhs.getMat(); - int type = w.type(), esz = (int)w.elemSize(); - int m = u.rows, n = vt.cols, nb = rhs.data ? rhs.cols : m; - AutoBuffer buffer(nb); - CV_Assert( u.data && vt.data && w.data ); - - CV_Assert( rhs.data == 0 || (rhs.type() == type && rhs.rows == m) ); - - _dst.create( n, nb, type ); - Mat dst = _dst.getMat(); - if( type == CV_32F ) - SVBkSb(m, n, (float*)w.data, 1, (float*)u.data, (int)(u.step/esz), false, - (float*)vt.data, (int)(vt.step/esz), true, (float*)rhs.data, (int)(rhs.step/esz), - nb, (float*)dst.data, (int)(dst.step/esz), buffer, 10*FLT_EPSILON ); - else if( type == CV_64F ) - SVBkSb(m, n, (double*)w.data, 1, (double*)u.data, (int)(u.step/esz), false, - (double*)vt.data, (int)(vt.step/esz), true, (double*)rhs.data, (int)(rhs.step/esz), - nb, (double*)dst.data, (int)(dst.step/esz), buffer, 2*DBL_EPSILON ); - else - CV_Error( Error::StsUnsupportedFormat, "" ); -} -/////////////////////////////////////////// - -#define Sf( y, x ) ((float*)(srcdata + y*srcstep))[x] -#define Sd( y, x ) ((double*)(srcdata + y*srcstep))[x] -#define Df( y, x ) ((float*)(dstdata + y*dststep))[x] -#define Dd( y, x ) ((double*)(dstdata + y*dststep))[x] - -double cvfork::invert( InputArray _src, OutputArray _dst, int method ) -{ - Mat src = _src.getMat(); - int type = src.type(); - - CV_Assert(type == CV_32F || type == CV_64F); - - size_t esz = CV_ELEM_SIZE(type); - int m = src.rows, n = src.cols; - - if( method == DECOMP_SVD ) - { - int nm = std::min(m, n); - - AutoBuffer _buf((m*nm + nm + nm*n)*esz + sizeof(double)); - uchar* buf = alignPtr((uchar*)_buf, (int)esz); - Mat u(m, nm, type, buf); - Mat w(nm, 1, type, u.ptr() + m*nm*esz); - Mat vt(nm, n, type, w.ptr() + nm*esz); - - _SVDcompute(src, w, u, vt); - _backSubst(w, u, vt, Mat(), _dst); - - return type == CV_32F ? - (w.ptr()[0] >= FLT_EPSILON ? - w.ptr()[n-1]/w.ptr()[0] : 0) : - (w.ptr()[0] >= DBL_EPSILON ? - w.ptr()[n-1]/w.ptr()[0] : 0); - } - return 0; -} - -#endif //USE_LAPACK diff --git a/apps/interactive-calibration/linalg.hpp b/apps/interactive-calibration/linalg.hpp deleted file mode 100644 index 4a4d2b053b..0000000000 --- a/apps/interactive-calibration/linalg.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef LINALG_HPP -#define LINALG_HPP - -#include - -namespace cvfork { - -double invert( cv::InputArray _src, cv::OutputArray _dst, int method ); -bool solve(cv::InputArray _src, cv::InputArray _src2arg, cv::OutputArray _dst, int method ); - -} - -#endif diff --git a/apps/interactive-calibration/main.cpp b/apps/interactive-calibration/main.cpp index f41bcbc371..051b24cf2c 100644 --- a/apps/interactive-calibration/main.cpp +++ b/apps/interactive-calibration/main.cpp @@ -12,7 +12,6 @@ #include "calibCommon.hpp" #include "calibPipeline.hpp" #include "frameProcessor.hpp" -#include "cvCalibrationFork.hpp" #include "calibController.hpp" #include "parametersController.hpp" #include "rotationConverters.hpp" @@ -106,7 +105,7 @@ int main(int argc, char** argv) if(!parser.has("v")) globalData->imageSize = capParams.cameraResolution; int calibrationFlags = 0; - if(intParams.fastSolving) calibrationFlags |= CALIB_USE_QR; + if(intParams.fastSolving) calibrationFlags |= cv::CALIB_USE_QR; cv::Ptr controller(new calibController(globalData, calibrationFlags, parser.get("ft"), capParams.minFramesNum)); cv::Ptr dataController(new calibDataController(globalData, capParams.maxFramesNum, @@ -131,11 +130,16 @@ int main(int argc, char** argv) cv::namedWindow(mainWindowName); cv::moveWindow(mainWindowName, 10, 10); #ifdef HAVE_QT - cv::createButton("Delete last frame", deleteButton, &dataController, cv::QT_PUSH_BUTTON); - cv::createButton("Delete all frames", deleteAllButton, &dataController, cv::QT_PUSH_BUTTON); - cv::createButton("Undistort", undistortButton, &showProcessor, cv::QT_CHECKBOX, false); - cv::createButton("Save current parameters", saveCurrentParamsButton, &dataController, cv::QT_PUSH_BUTTON); - cv::createButton("Switch visualisation mode", switchVisualizationModeButton, &showProcessor, cv::QT_PUSH_BUTTON); + cv::createButton("Delete last frame", deleteButton, &dataController, + cv::QT_PUSH_BUTTON | cv::QT_NEW_BUTTONBAR); + cv::createButton("Delete all frames", deleteAllButton, &dataController, + cv::QT_PUSH_BUTTON | cv::QT_NEW_BUTTONBAR); + cv::createButton("Undistort", undistortButton, &showProcessor, + cv::QT_CHECKBOX | cv::QT_NEW_BUTTONBAR, false); + cv::createButton("Save current parameters", saveCurrentParamsButton, &dataController, + cv::QT_PUSH_BUTTON | cv::QT_NEW_BUTTONBAR); + cv::createButton("Switch visualisation mode", switchVisualizationModeButton, &showProcessor, + cv::QT_PUSH_BUTTON | cv::QT_NEW_BUTTONBAR); #endif //HAVE_QT try { bool pipelineFinished = false; @@ -156,10 +160,10 @@ int main(int argc, char** argv) if(capParams.board != chAruco) { globalData->totalAvgErr = - cvfork::calibrateCamera(globalData->objectPoints, globalData->imagePoints, + cv::calibrateCamera(globalData->objectPoints, globalData->imagePoints, globalData->imageSize, globalData->cameraMatrix, globalData->distCoeffs, cv::noArray(), cv::noArray(), - globalData->stdDeviations, globalData->perViewErrors, + globalData->stdDeviations, cv::noArray(), globalData->perViewErrors, calibrationFlags, solverTermCrit); } else { @@ -169,10 +173,10 @@ int main(int argc, char** argv) cv::aruco::CharucoBoard::create(capParams.boardSize.width, capParams.boardSize.height, capParams.charucoSquareLenght, capParams.charucoMarkerSize, dictionary); globalData->totalAvgErr = - cvfork::calibrateCameraCharuco(globalData->allCharucoCorners, globalData->allCharucoIds, + cv::aruco::calibrateCameraCharuco(globalData->allCharucoCorners, globalData->allCharucoIds, charucoboard, globalData->imageSize, globalData->cameraMatrix, globalData->distCoeffs, - cv::noArray(), cv::noArray(), globalData->stdDeviations, + cv::noArray(), cv::noArray(), globalData->stdDeviations, cv::noArray(), globalData->perViewErrors, calibrationFlags, solverTermCrit); } dataController->updateUndistortMap(); From 6d54abbd0fc64b23ea0b97f3c906cba219b52dc8 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 1 Sep 2016 15:31:08 +0300 Subject: [PATCH 131/178] ffmpeg: fix get_fps() --- modules/videoio/src/cap_ffmpeg_impl.hpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index a0b9d402f6..9bc23bd965 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -1135,7 +1135,14 @@ int CvCapture_FFMPEG::get_bitrate() const double CvCapture_FFMPEG::get_fps() const { +#if 0 && LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(55, 1, 100) && LIBAVFORMAT_VERSION_MICRO >= 100 + double fps = r2d(av_guess_frame_rate(ic, ic->streams[video_stream], NULL)); +#else +#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54, 1, 0) + double fps = r2d(ic->streams[video_stream]->avg_frame_rate); +#else double fps = r2d(ic->streams[video_stream]->r_frame_rate); +#endif #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0) if (fps < eps_zero) @@ -1148,7 +1155,7 @@ double CvCapture_FFMPEG::get_fps() const { fps = 1.0 / r2d(ic->streams[video_stream]->codec->time_base); } - +#endif return fps; } From 03767340bb6de127b291e3b90978b5121d1982bc Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 8 Sep 2016 14:42:01 +0300 Subject: [PATCH 132/178] ffmpeg: fill avg_frame_rate --- modules/videoio/src/cap_ffmpeg_impl.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index 9bc23bd965..e7ece78a01 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -1582,6 +1582,10 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, } #endif +#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(52, 42, 0) + st->avg_frame_rate = (AVRational){frame_rate, frame_rate_base}; +#endif + return st; } From 10d18a315c99ece9fee02666afdebe42da0943a9 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 25 Aug 2016 17:26:46 +0300 Subject: [PATCH 133/178] instrumentation: minor refactoring, wrap OpenCL - calculate ticksTotal instead of ticksMean - local / global width is based on ticksTotal value - added instrumentation for OpenCL program compilation - added instrumentation for OpenCL kernel execution --- cmake/OpenCVGenABI.cmake | 2 +- modules/core/include/opencv2/core/private.hpp | 14 ++++-- modules/core/include/opencv2/core/utility.hpp | 49 ++++++++++++------- modules/core/src/ocl.cpp | 10 ++++ modules/core/src/system.cpp | 46 ++++++++--------- modules/ts/src/ts_perf.cpp | 19 ++++--- 6 files changed, 86 insertions(+), 54 deletions(-) diff --git a/cmake/OpenCVGenABI.cmake b/cmake/OpenCVGenABI.cmake index 35cc10d8ed..86aa78b17b 100644 --- a/cmake/OpenCVGenABI.cmake +++ b/cmake/OpenCVGenABI.cmake @@ -43,7 +43,7 @@ string(REPLACE ";" "\n " OPENCV_ABI_SKIP_HEADERS "${OPENCV_ABI_SKIP_HEADERS}" string(REPLACE ";" "\n " OPENCV_ABI_SKIP_LIBRARIES "${OPENCV_ABI_SKIP_LIBRARIES}") # Options -set(OPENCV_ABI_GCC_OPTIONS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}") +set(OPENCV_ABI_GCC_OPTIONS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE} -DOPENCV_ABI_CHECK=1") string(REGEX REPLACE "([^ ]) +([^ ])" "\\1\\n \\2" OPENCV_ABI_GCC_OPTIONS "${OPENCV_ABI_GCC_OPTIONS}") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/opencv_abi.xml.in" "${path1}") diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index c839327823..44e1a44bc1 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -476,7 +476,7 @@ public: class CV_EXPORTS IntrumentationRegion { public: - IntrumentationRegion(const char* funName, const char* fileName, int lineNum, int instrType = TYPE_GENERAL, int implType = IMPL_PLAIN); + IntrumentationRegion(const char* funName, const char* fileName, int lineNum, TYPE instrType = TYPE_GENERAL, IMPL implType = IMPL_PLAIN); ~IntrumentationRegion(); private: @@ -492,7 +492,7 @@ CV_EXPORTS InstrNode* getCurrentNode(); ///// General instrumentation // Instrument region -#define CV_INSTRUMENT_REGION_META(TYPE, IMPL, ...) ::cv::instr::IntrumentationRegion __instr_region__(__FUNCTION__, __FILE__, __LINE__, TYPE, IMPL); +#define CV_INSTRUMENT_REGION_META(NAME, TYPE, IMPL) ::cv::instr::IntrumentationRegion __instr_region__(NAME, __FILE__, __LINE__, TYPE, IMPL); // Instrument functions with non-void return type #define CV_INSTRUMENT_FUN_RT_META(TYPE, IMPL, ERROR_COND, FUN, ...) ([&]()\ {\ @@ -535,13 +535,13 @@ CV_EXPORTS InstrNode* getCurrentNode(); ///// General instrumentation // General OpenCV region instrumentation macro -#define CV_INSTRUMENT_REGION() CV_INSTRUMENT_REGION_META(cv::instr::TYPE_GENERAL, cv::instr::IMPL_PLAIN) +#define CV_INSTRUMENT_REGION() CV_INSTRUMENT_REGION_META(__FUNCTION__, cv::instr::TYPE_GENERAL, cv::instr::IMPL_PLAIN) // Parallel OpenCV region instrumentation macro #define CV_INSTRUMENT_REGION_MT() CV_INSTRUMENT_REGION_MT_META(cv::instr::TYPE_GENERAL, cv::instr::IMPL_PLAIN) ///// IPP instrumentation // Wrapper region instrumentation macro -#define CV_INSTRUMENT_REGION_IPP() CV_INSTRUMENT_REGION_META(::cv::instr::TYPE_WRAPPER, ::cv::instr::IMPL_IPP) +#define CV_INSTRUMENT_REGION_IPP() CV_INSTRUMENT_REGION_META(__FUNCTION__, ::cv::instr::TYPE_WRAPPER, ::cv::instr::IMPL_IPP) // Function instrumentation macro #define CV_INSTRUMENT_FUN_IPP(FUN, ...) CV_INSTRUMENT_FUN_RT_META(::cv::instr::TYPE_FUN, ::cv::instr::IMPL_IPP, status < 0, FUN, __VA_ARGS__) // Diagnostic markers @@ -549,12 +549,15 @@ CV_EXPORTS InstrNode* getCurrentNode(); ///// OpenCL instrumentation // Wrapper region instrumentation macro -#define CV_INSTRUMENT_REGION_OPENCL() CV_INSTRUMENT_REGION_META(::cv::instr::TYPE_WRAPPER, ::cv::instr::IMPL_OPENCL) +#define CV_INSTRUMENT_REGION_OPENCL() CV_INSTRUMENT_REGION_META(__FUNCTION__, ::cv::instr::TYPE_WRAPPER, ::cv::instr::IMPL_OPENCL) +#define CV_INSTRUMENT_REGION_OPENCL_(NAME) CV_INSTRUMENT_REGION_META(NAME, ::cv::instr::TYPE_WRAPPER, ::cv::instr::IMPL_OPENCL) // Function instrumentation macro #define CV_INSTRUMENT_FUN_OPENCL_KERNEL(FUN, ...) CV_INSTRUMENT_FUN_RT_META(::cv::instr::TYPE_FUN, ::cv::instr::IMPL_OPENCL, status == 0, FUN, __VA_ARGS__) // Diagnostic markers #define CV_INSTRUMENT_MARK_OPENCL(NAME) CV_INSTRUMENT_MARK_META(::cv::instr::IMPL_OPENCL, NAME) #else +#define CV_INSTRUMENT_REGION_META(...) + #define CV_INSTRUMENT_REGION() #define CV_INSTRUMENT_REGION_MT() @@ -563,6 +566,7 @@ CV_EXPORTS InstrNode* getCurrentNode(); #define CV_INSTRUMENT_MARK_IPP(NAME) #define CV_INSTRUMENT_REGION_OPENCL() +#define CV_INSTRUMENT_REGION_OPENCL_(...) #define CV_INSTRUMENT_FUN_OPENCL_KERNEL(FUN, ...) ((FUN)(__VA_ARGS__)) #define CV_INSTRUMENT_MARK_OPENCL(NAME) #endif diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index 3bf6975643..e465faee5f 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -1076,7 +1076,10 @@ public: // Instrumentation external interface namespace instr { -enum + +#if !defined OPENCV_ABI_CHECK + +enum TYPE { TYPE_GENERAL = 0, // OpenCV API function, e.g. exported function TYPE_MARKER, // Information marker @@ -1084,48 +1087,60 @@ enum TYPE_FUN, // Simple function call }; -enum +enum IMPL { IMPL_PLAIN = 0, IMPL_IPP, IMPL_OPENCL, }; -enum -{ - FLAGS_MAPPING = 0x01, -}; - class CV_EXPORTS NodeData { public: - NodeData(const char* funName = 0, const char* fileName = NULL, int lineNum = 0, int instrType = TYPE_GENERAL, int implType = IMPL_PLAIN); + NodeData(const char* funName = 0, const char* fileName = NULL, int lineNum = 0, cv::instr::TYPE instrType = TYPE_GENERAL, cv::instr::IMPL implType = IMPL_PLAIN); NodeData(NodeData &ref); ~NodeData(); NodeData& operator=(const NodeData&); cv::String m_funName; - int m_instrType; - int m_implType; - cv::String m_fileName; + cv::instr::TYPE m_instrType; + cv::instr::IMPL m_implType; + const char* m_fileName; int m_lineNum; - bool m_funError; volatile int m_counter; - bool m_stopPoint; - uint64 m_ticksMean; + volatile uint64 m_ticksTotal; + // No synchronization + double getTotalMs() const { return (double)m_ticksTotal * 1000. / cv::getTickFrequency(); } + // No synchronization + double getMeanMs() const { return (double)m_ticksTotal * 1000. / (m_counter * cv::getTickFrequency()); } + + bool m_funError; + bool m_stopPoint; }; bool operator==(const NodeData& lhs, const NodeData& rhs); typedef Node InstrNode; +CV_EXPORTS InstrNode* getTrace(); + +#endif // !defined OPENCV_ABI_CHECK + + CV_EXPORTS bool useInstrumentation(); CV_EXPORTS void setUseInstrumentation(bool flag); -CV_EXPORTS InstrNode* getTrace(); CV_EXPORTS void resetTrace(); -CV_EXPORTS void setFlags(int modeFlags); -CV_EXPORTS int getFlags(); + +enum FLAGS +{ + FLAGS_NONE = 0, + FLAGS_MAPPING = 1 << 0, +}; + +CV_EXPORTS void setFlags(FLAGS modeFlags); +static inline void setFlags(int modeFlags) { setFlags((FLAGS)modeFlags); } +CV_EXPORTS FLAGS getFlags(); } } //namespace cv diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 6780d85e57..924b360851 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -45,6 +45,7 @@ #include #include #include // std::cerr +#include #define CV_OPENCL_ALWAYS_SHOW_BUILD_LOG 0 #define CV_OPENCL_SHOW_RUN_ERRORS 0 @@ -3169,6 +3170,9 @@ struct Kernel::Impl { cl_program ph = (cl_program)prog.ptr(); cl_int retval = 0; +#ifdef ENABLE_INSTRUMENTATION + name = kname; +#endif handle = ph != 0 ? clCreateKernel(ph, kname, &retval) : 0; CV_OclDbgAssert(retval == CL_SUCCESS); @@ -3221,6 +3225,9 @@ struct Kernel::Impl IMPLEMENT_REFCOUNTABLE(); +#ifdef ENABLE_INSTRUMENTATION + cv::String name; +#endif cl_kernel handle; cl_event e; enum { MAX_ARRS = 16 }; @@ -3441,6 +3448,8 @@ int Kernel::set(int i, const KernelArg& arg) bool Kernel::run(int dims, size_t _globalsize[], size_t _localsize[], bool sync, const Queue& q) { + CV_INSTRUMENT_REGION_META(p->name.c_str(), instr::TYPE_FUN, instr::IMPL_OPENCL); + if(!p || !p->handle || p->e != 0) return false; @@ -3552,6 +3561,7 @@ struct Program::Impl Impl(const ProgramSource& _src, const String& _buildflags, String& errmsg) { + CV_INSTRUMENT_REGION_OPENCL_(cv::format("Compile: %" PRIx64 " options: %s", _src.hash(), _buildflags.c_str()).c_str()); refcount = 1; const Context& ctx = Context::getDefault(); src = _src; diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index ffca514f8e..bd44fe3339 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -1337,7 +1337,7 @@ void resetTrace() #endif } -void setFlags(int modeFlags) +void setFlags(FLAGS modeFlags) { #ifdef ENABLE_INSTRUMENTATION getInstrumentStruct().enableMapping = (modeFlags & FLAGS_MAPPING); @@ -1345,33 +1345,34 @@ void setFlags(int modeFlags) CV_UNUSED(modeFlags); #endif } -int getFlags() +FLAGS getFlags() { #ifdef ENABLE_INSTRUMENTATION int flags = 0; if(getInstrumentStruct().enableMapping) flags |= FLAGS_MAPPING; - return flags; + return (FLAGS)flags; #else - return 0; + return (FLAGS)0; #endif } -NodeData::NodeData(const char* funName, const char* fileName, int lineNum, int instrType, int implType) +NodeData::NodeData(const char* funName, const char* fileName, int lineNum, cv::instr::TYPE instrType, cv::instr::IMPL implType) { m_instrType = TYPE_GENERAL; m_implType = IMPL_PLAIN; - m_funError = false; - m_counter = 0; - m_stopPoint = false; - m_ticksMean = 0; - m_funName = funName; m_instrType = instrType; m_implType = implType; m_fileName = fileName; m_lineNum = lineNum; + + m_counter = 0; + m_ticksTotal = 0; + + m_funError = false; + m_stopPoint = false; } NodeData::NodeData(NodeData &ref) { @@ -1382,13 +1383,12 @@ NodeData& NodeData::operator=(const NodeData &right) this->m_funName = right.m_funName; this->m_instrType = right.m_instrType; this->m_implType = right.m_implType; - this->m_funError = right.m_funError; - this->m_counter = right.m_counter; - this->m_stopPoint = right.m_stopPoint; - this->m_ticksMean = right.m_ticksMean; this->m_fileName = right.m_fileName; this->m_lineNum = right.m_lineNum; - + this->m_counter = right.m_counter; + this->m_ticksTotal = right.m_ticksTotal; + this->m_funError = right.m_funError; + this->m_stopPoint = right.m_stopPoint; return *this; } NodeData::~NodeData() @@ -1418,7 +1418,7 @@ InstrNode* getCurrentNode() return getInstrumentTLSStruct().pCurrentNode; } -IntrumentationRegion::IntrumentationRegion(const char* funName, const char* fileName, int lineNum, int instrType, int implType) +IntrumentationRegion::IntrumentationRegion(const char* funName, const char* fileName, int lineNum, TYPE instrType, IMPL implType) { m_disabled = false; m_regionTicks = 0; @@ -1482,18 +1482,18 @@ IntrumentationRegion::~IntrumentationRegion() } else { - if(pTLS->pCurrentNode->m_payload.m_implType == cv::instr::IMPL_OPENCL && - pTLS->pCurrentNode->m_payload.m_instrType == cv::instr::TYPE_FUN) - cv::ocl::finish(); + if (pTLS->pCurrentNode->m_payload.m_implType == cv::instr::IMPL_OPENCL && + (pTLS->pCurrentNode->m_payload.m_instrType == cv::instr::TYPE_FUN || + pTLS->pCurrentNode->m_payload.m_instrType == cv::instr::TYPE_WRAPPER)) + { + cv::ocl::finish(); // TODO Support "async" OpenCL instrumentation + } uint64 ticks = (getTickCount() - m_regionTicks); { cv::AutoLock guard(pStruct->mutexCount); // Concurrent ticks accumulation pTLS->pCurrentNode->m_payload.m_counter++; - if(pTLS->pCurrentNode->m_payload.m_counter <= 1) - pTLS->pCurrentNode->m_payload.m_ticksMean = ticks; - else - pTLS->pCurrentNode->m_payload.m_ticksMean = (pTLS->pCurrentNode->m_payload.m_ticksMean*(pTLS->pCurrentNode->m_payload.m_counter-1) + ticks)/pTLS->pCurrentNode->m_payload.m_counter; + pTLS->pCurrentNode->m_payload.m_ticksTotal += ticks; } pTLS->pCurrentNode = pTLS->pCurrentNode->m_pParent; diff --git a/modules/ts/src/ts_perf.cpp b/modules/ts/src/ts_perf.cpp index 50e23548fe..8866272667 100644 --- a/modules/ts/src/ts_perf.cpp +++ b/modules/ts/src/ts_perf.cpp @@ -767,7 +767,7 @@ static void printShift(cv::instr::InstrNode *pNode, cv::instr::InstrNode* pRoot) static double calcLocalWeight(cv::instr::InstrNode *pNode) { if(pNode->m_pParent && pNode->m_pParent->m_pParent) - return ((double)pNode->m_payload.m_ticksMean*100/pNode->m_pParent->m_payload.m_ticksMean); + return ((double)pNode->m_payload.m_ticksTotal*100/pNode->m_pParent->m_payload.m_ticksTotal); else return 100; } @@ -779,7 +779,7 @@ static double calcGlobalWeight(cv::instr::InstrNode *pNode) while(globNode->m_pParent && globNode->m_pParent->m_pParent) globNode = globNode->m_pParent; - return ((double)pNode->m_payload.m_ticksMean*100/(double)globNode->m_payload.m_ticksMean); + return ((double)pNode->m_payload.m_ticksTotal*100/(double)globNode->m_payload.m_ticksTotal); } static void printNodeRec(cv::instr::InstrNode *pNode, cv::instr::InstrNode *pRoot) @@ -811,7 +811,7 @@ static void printNodeRec(cv::instr::InstrNode *pNode, cv::instr::InstrNode *pRoo if(pNode->m_pParent) { printf(" - C:%d", pNode->m_payload.m_counter); - printf(" T:%.4fms", (double)pNode->m_payload.m_ticksMean/cv::getTickFrequency()*1000); + printf(" T:%.4fms", pNode->m_payload.getMeanMs()); if(pNode->m_pParent->m_pParent) printf(" L:%.0f%% G:%.0f%%", calcLocalWeight(pNode), calcGlobalWeight(pNode)); } @@ -886,12 +886,15 @@ static cv::String nodeToString(cv::instr::InstrNode *pNode) return string; } -static uint64 getNodeTimeRec(cv::instr::InstrNode *pNode, int type, int impl) +static uint64 getNodeTimeRec(cv::instr::InstrNode *pNode, cv::instr::TYPE type, cv::instr::IMPL impl) { uint64 ticks = 0; - if(pNode->m_pParent && pNode->m_payload.m_instrType == type && pNode->m_payload.m_implType == impl) - ticks = pNode->m_payload.m_ticksMean; + if (pNode->m_pParent && (type < 0 || pNode->m_payload.m_instrType == type) && pNode->m_payload.m_implType == impl) + { + ticks = pNode->m_payload.m_ticksTotal; + return ticks; + } for(size_t i = 0; i < pNode->m_childs.size(); i++) ticks += getNodeTimeRec(pNode->m_childs[i], type, impl); @@ -899,7 +902,7 @@ static uint64 getNodeTimeRec(cv::instr::InstrNode *pNode, int type, int impl) return ticks; } -static uint64 getImplTime(int impl) +static uint64 getImplTime(cv::instr::IMPL impl) { uint64 ticks = 0; cv::instr::InstrNode *pRoot = cv::instr::getTrace(); @@ -915,7 +918,7 @@ static uint64 getTotalTime() cv::instr::InstrNode *pRoot = cv::instr::getTrace(); for(size_t i = 0; i < pRoot->m_childs.size(); i++) - ticks += pRoot->m_childs[i]->m_payload.m_ticksMean; + ticks += pRoot->m_childs[i]->m_payload.m_ticksTotal; return ticks; } From d855608e6ec2cc42656b9245c3420725d7afa993 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 26 Aug 2016 15:08:50 +0300 Subject: [PATCH 134/178] instrumentation: fix build on Linux - enable C++11 - fix macro --- cmake/OpenCVCompilerOptions.cmake | 5 +++++ modules/core/include/opencv2/core/private.hpp | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake index cce57a9364..15e4db1125 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -233,6 +233,11 @@ if(CMAKE_COMPILER_IS_GNUCXX) set(OPENCV_EXTRA_CXX_FLAGS "${OPENCV_EXTRA_CXX_FLAGS} --coverage") endif() + if(ENABLE_INSTRUMENTATION) + set(OPENCV_EXTRA_CXX_FLAGS "${OPENCV_EXTRA_CXX_FLAGS} --std=c++11") + set(WITH_VTK OFF) # There are issues with VTK 6.0 + endif() + set(OPENCV_EXTRA_FLAGS_RELEASE "${OPENCV_EXTRA_FLAGS_RELEASE} -DNDEBUG") set(OPENCV_EXTRA_FLAGS_DEBUG "${OPENCV_EXTRA_FLAGS_DEBUG} -O0 -DDEBUG -D_DEBUG") endif() diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index 44e1a44bc1..1a876b03f2 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -502,12 +502,12 @@ CV_EXPORTS InstrNode* getCurrentNode(); auto status = ((FUN)(__VA_ARGS__));\ if(ERROR_COND){\ ::cv::instr::getCurrentNode()->m_payload.m_funError = true;\ - CV_INSTRUMENT_MARK_META(IMPL, ##FUN - BadExit);\ + CV_INSTRUMENT_MARK_META(IMPL, #FUN " - BadExit");\ }\ return status;\ }catch(...){\ ::cv::instr::getCurrentNode()->m_payload.m_funError = true;\ - CV_INSTRUMENT_MARK_META(IMPL, ##FUN - BadExit);\ + CV_INSTRUMENT_MARK_META(IMPL, #FUN " - BadExit");\ throw;\ }\ }else{\ @@ -523,7 +523,7 @@ CV_EXPORTS InstrNode* getCurrentNode(); (FUN)(__VA_ARGS__);\ }catch(...){\ ::cv::instr::getCurrentNode()->m_payload.m_funError = true;\ - CV_INSTRUMENT_MARK_META(IMPL, ##FUN - BadExit);\ + CV_INSTRUMENT_MARK_META(IMPL, #FUN "- BadExit");\ throw;\ }\ }else{\ @@ -531,7 +531,7 @@ CV_EXPORTS InstrNode* getCurrentNode(); }\ }()) // Instrumentation information marker -#define CV_INSTRUMENT_MARK_META(IMPL, NAME, ...) {::cv::instr::IntrumentationRegion __instr_mark__(#NAME, __FILE__, __LINE__, ::cv::instr::TYPE_MARKER, IMPL);} +#define CV_INSTRUMENT_MARK_META(IMPL, NAME, ...) {::cv::instr::IntrumentationRegion __instr_mark__(NAME, __FILE__, __LINE__, ::cv::instr::TYPE_MARKER, IMPL);} ///// General instrumentation // General OpenCV region instrumentation macro From c7f5bc3624b73bbfc5d90e3146842617feef8637 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 8 Sep 2016 16:19:05 +0300 Subject: [PATCH 135/178] viz: use ../precomp.hpp in modules/viz/src/vtk/* files --- modules/viz/src/vtk/vtkCloudMatSink.cpp | 2 +- modules/viz/src/vtk/vtkCloudMatSource.cpp | 2 +- modules/viz/src/vtk/vtkImageMatSource.cpp | 2 +- modules/viz/src/vtk/vtkImageMatSource.h | 2 +- modules/viz/src/vtk/vtkOBJWriter.cpp | 2 +- modules/viz/src/vtk/vtkTrajectorySource.cpp | 2 +- modules/viz/src/vtk/vtkVizInteractorStyle.cpp | 2 +- modules/viz/src/vtk/vtkXYZReader.cpp | 2 +- modules/viz/src/vtk/vtkXYZWriter.cpp | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/viz/src/vtk/vtkCloudMatSink.cpp b/modules/viz/src/vtk/vtkCloudMatSink.cpp index 8bd1011323..aa3d34ca4f 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSink.cpp @@ -42,7 +42,7 @@ // //M*/ -#include "precomp.hpp" +#include "../precomp.hpp" namespace cv { namespace viz { diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index 1d8ab7894c..3e3ef16722 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -42,7 +42,7 @@ // //M*/ -#include "precomp.hpp" +#include "../precomp.hpp" namespace cv { namespace viz { diff --git a/modules/viz/src/vtk/vtkImageMatSource.cpp b/modules/viz/src/vtk/vtkImageMatSource.cpp index 6586175236..d9de698df9 100644 --- a/modules/viz/src/vtk/vtkImageMatSource.cpp +++ b/modules/viz/src/vtk/vtkImageMatSource.cpp @@ -42,7 +42,7 @@ // //M*/ -#include "precomp.hpp" +#include "../precomp.hpp" namespace cv { namespace viz { diff --git a/modules/viz/src/vtk/vtkImageMatSource.h b/modules/viz/src/vtk/vtkImageMatSource.h index db0c093ed8..a7a41e082f 100644 --- a/modules/viz/src/vtk/vtkImageMatSource.h +++ b/modules/viz/src/vtk/vtkImageMatSource.h @@ -42,7 +42,7 @@ // //M*/ -#include "precomp.hpp" +#include "../precomp.hpp" #ifndef __vtkImageMatSource_h #define __vtkImageMatSource_h diff --git a/modules/viz/src/vtk/vtkOBJWriter.cpp b/modules/viz/src/vtk/vtkOBJWriter.cpp index 7480b11ac2..296b6eb065 100644 --- a/modules/viz/src/vtk/vtkOBJWriter.cpp +++ b/modules/viz/src/vtk/vtkOBJWriter.cpp @@ -42,7 +42,7 @@ // //M*/ -#include "precomp.hpp" +#include "../precomp.hpp" namespace cv { namespace viz { diff --git a/modules/viz/src/vtk/vtkTrajectorySource.cpp b/modules/viz/src/vtk/vtkTrajectorySource.cpp index 2036e09af3..d0e180a9c1 100644 --- a/modules/viz/src/vtk/vtkTrajectorySource.cpp +++ b/modules/viz/src/vtk/vtkTrajectorySource.cpp @@ -42,7 +42,7 @@ // //M*/ -#include "precomp.hpp" +#include "../precomp.hpp" namespace cv { namespace viz { diff --git a/modules/viz/src/vtk/vtkVizInteractorStyle.cpp b/modules/viz/src/vtk/vtkVizInteractorStyle.cpp index 9b5eca2b0e..e2d338066e 100644 --- a/modules/viz/src/vtk/vtkVizInteractorStyle.cpp +++ b/modules/viz/src/vtk/vtkVizInteractorStyle.cpp @@ -43,7 +43,7 @@ // //M*/ -#include "precomp.hpp" +#include "../precomp.hpp" namespace cv { namespace viz { diff --git a/modules/viz/src/vtk/vtkXYZReader.cpp b/modules/viz/src/vtk/vtkXYZReader.cpp index 283a592489..57726eae9b 100644 --- a/modules/viz/src/vtk/vtkXYZReader.cpp +++ b/modules/viz/src/vtk/vtkXYZReader.cpp @@ -42,7 +42,7 @@ // //M*/ -#include "precomp.hpp" +#include "../precomp.hpp" namespace cv { namespace viz { diff --git a/modules/viz/src/vtk/vtkXYZWriter.cpp b/modules/viz/src/vtk/vtkXYZWriter.cpp index 5a3d7d5c83..cf95e3c6a0 100644 --- a/modules/viz/src/vtk/vtkXYZWriter.cpp +++ b/modules/viz/src/vtk/vtkXYZWriter.cpp @@ -42,7 +42,7 @@ // //M*/ -#include "precomp.hpp" +#include "../precomp.hpp" namespace cv { namespace viz { From 4170c97984f684c14da20cd32d07a278518dd25f Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Tue, 16 Aug 2016 16:57:27 +0300 Subject: [PATCH 136/178] Several HAL API functions are implemented as immediate mode OpenVX calls --- 3rdparty/openvx/include/openvx_hal.hpp | 62 +++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 5 deletions(-) diff --git a/3rdparty/openvx/include/openvx_hal.hpp b/3rdparty/openvx/include/openvx_hal.hpp index 893547dfdf..33de4bf834 100644 --- a/3rdparty/openvx/include/openvx_hal.hpp +++ b/3rdparty/openvx/include/openvx_hal.hpp @@ -156,7 +156,7 @@ struct vxImage } ~vxImage() { - vxSwapImageHandle(img, NULL, NULL, 1); + vxErr::check(vxSwapImageHandle(img, NULL, NULL, 1)); vxReleaseImage(&img); } }; @@ -165,16 +165,45 @@ struct vxImage // real code starts here // ... -template -inline int ovx_hal_add(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h) +#define OVX_BINARY_OP(hal_func, ovx_call, ...) \ +template \ +inline int ovx_hal_##hal_func(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h, __VA_ARGS__) \ +{ \ + try \ + { \ + vxContext * ctx = vxContext::getContext(); \ + vxImage ia(*ctx, a, astep, w, h); \ + vxImage ib(*ctx, b, bstep, w, h); \ + vxImage ic(*ctx, c, cstep, w, h); \ + ovx_call \ + } \ + catch (vxErr & e) \ + { \ + e.print(); \ + return CV_HAL_ERROR_UNKNOWN; \ + } \ + return CV_HAL_ERROR_OK; \ +} + +OVX_BINARY_OP(add, {vxErr::check(vxuAdd(ctx->ctx, ia.img, ib.img, VX_CONVERT_POLICY_SATURATE, ic.img));}) +OVX_BINARY_OP(sub, {vxErr::check(vxuSubtract(ctx->ctx, ia.img, ib.img, VX_CONVERT_POLICY_SATURATE, ic.img));}) + +OVX_BINARY_OP(absdiff, {vxErr::check(vxuAbsDiff(ctx->ctx, ia.img, ib.img, ic.img));}) + +OVX_BINARY_OP(and, {vxErr::check(vxuAnd(ctx->ctx, ia.img, ib.img, ic.img));}) +OVX_BINARY_OP(or, {vxErr::check(vxuOr(ctx->ctx, ia.img, ib.img, ic.img));}) +OVX_BINARY_OP(xor, {vxErr::check(vxuXor(ctx->ctx, ia.img, ib.img, ic.img));}) + +OVX_BINARY_OP(mul, {vxErr::check(vxuMultiply(ctx->ctx, ia.img, ib.img, (float)scale, VX_CONVERT_POLICY_SATURATE, VX_ROUND_POLICY_TO_ZERO, ic.img));}, double scale) + +inline int ovx_hal_not(const uchar *a, size_t astep, uchar *c, size_t cstep, int w, int h) { try { vxContext * ctx = vxContext::getContext(); vxImage ia(*ctx, a, astep, w, h); - vxImage ib(*ctx, b, bstep, w, h); vxImage ic(*ctx, c, cstep, w, h); - vxErr::check(vxuAdd(ctx->ctx, ia.img, ib.img, VX_CONVERT_POLICY_SATURATE, ic.img)); + vxErr::check(vxuNot(ctx->ctx, ia.img, ic.img)); } catch (vxErr & e) { @@ -192,5 +221,28 @@ inline int ovx_hal_add(const T *a, size_t astep, const T *b, size_t bstep, T *c, #define cv_hal_add8u ovx_hal_add #undef cv_hal_add16s #define cv_hal_add16s ovx_hal_add +#undef cv_hal_sub8u +#define cv_hal_sub8u ovx_hal_sub +#undef cv_hal_sub16s +#define cv_hal_sub16s ovx_hal_sub + +#undef cv_hal_absdiff8u +#define cv_hal_absdiff8u ovx_hal_absdiff +#undef cv_hal_absdiff16s +#define cv_hal_absdiff16s ovx_hal_absdiff + +#undef cv_hal_and8u +#define cv_hal_and8u ovx_hal_and +#undef cv_hal_or8u +#define cv_hal_or8u ovx_hal_or +#undef cv_hal_xor8u +#define cv_hal_xor8u ovx_hal_xor +#undef cv_hal_not8u +#define cv_hal_not8u ovx_hal_not + +#undef cv_hal_mul8u +#define cv_hal_mul8u ovx_hal_mul +#undef cv_hal_mul16s +#define cv_hal_mul16s ovx_hal_mul #endif From c9229f754325a89de3553ad2190ffcc0879d8ace Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Wed, 31 Aug 2016 17:10:45 +0300 Subject: [PATCH 137/178] Resize, Warp and Filter HAL API functions are implemented as immediate mode OpenVX calls --- 3rdparty/openvx/include/openvx_hal.hpp | 306 ++++++++++++++++++++++++- 1 file changed, 301 insertions(+), 5 deletions(-) diff --git a/3rdparty/openvx/include/openvx_hal.hpp b/3rdparty/openvx/include/openvx_hal.hpp index 33de4bf834..6dbec79af0 100644 --- a/3rdparty/openvx/include/openvx_hal.hpp +++ b/3rdparty/openvx/include/openvx_hal.hpp @@ -7,6 +7,7 @@ #include "VX/vxu.h" #include +#include //================================================================================================== // utility @@ -52,7 +53,8 @@ template struct VX_Traits { enum { - Type = 0 + ImgType = 0, + DataType = 0 }; }; @@ -60,7 +62,8 @@ template <> struct VX_Traits { enum { - Type = VX_DF_IMAGE_U8 + ImgType = VX_DF_IMAGE_U8, + DataType = VX_TYPE_UINT8 }; }; @@ -68,7 +71,8 @@ template <> struct VX_Traits { enum { - Type = VX_DF_IMAGE_U16 + ImgType = VX_DF_IMAGE_U16, + DataType = VX_TYPE_UINT16 }; }; @@ -76,7 +80,17 @@ template <> struct VX_Traits { enum { - Type = VX_DF_IMAGE_S16 + ImgType = VX_DF_IMAGE_S16, + DataType = VX_TYPE_INT16 + }; +}; + +template <> +struct VX_Traits +{ + enum { + ImgType = 0, + DataType = VX_TYPE_FLOAT32 }; }; @@ -108,6 +122,14 @@ struct vxErr { vxErr(vxGetStatus((vx_reference)img), "image check").check(); } + static void check(vx_matrix mtx) + { + vxErr(vxGetStatus((vx_reference)mtx), "matrix check").check(); + } + static void check(vx_convolution cnv) + { + vxErr(vxGetStatus((vx_reference)cnv), "convolution check").check(); + } static void check(vx_status s) { vxErr(s, "status check").check(); @@ -151,7 +173,7 @@ struct vxImage addr.step_x = 1; addr.step_y = 1; void *ptrs[] = { (void*)data }; - img = vxCreateImageFromHandle(ctx.ctx, VX_Traits::Type, &addr, ptrs, VX_MEMORY_TYPE_HOST); + img = vxCreateImageFromHandle(ctx.ctx, VX_Traits::ImgType, &addr, ptrs, VX_MEMORY_TYPE_HOST); vxErr::check(img); } ~vxImage() @@ -161,6 +183,39 @@ struct vxImage } }; +struct vxMatrix +{ + vx_matrix mtx; + + template + vxMatrix(vxContext &ctx, const T *data, int w, int h) + { + mtx = vxCreateMatrix(ctx.ctx, VX_Traits::DataType, w, h); + vxErr::check(mtx); + vxErr::check(vxCopyMatrix(mtx, data, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); + } + ~vxMatrix() + { + vxReleaseMatrix(&mtx); + } +}; + +struct vxConvolution +{ + vx_convolution cnv; + + vxConvolution(vxContext &ctx, const short *data, int w, int h) + { + cnv = vxCreateConvolution(ctx.ctx, w, h); + vxErr::check(cnv); + vxErr::check(vxCopyConvolutionCoefficients(cnv, (void*)data, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); + } + ~vxConvolution() + { + vxReleaseConvolution(&cnv); + } +}; + //================================================================================================== // real code starts here // ... @@ -213,6 +268,229 @@ inline int ovx_hal_not(const uchar *a, size_t astep, uchar *c, size_t cstep, int return CV_HAL_ERROR_OK; } +#if defined OPENCV_IMGPROC_HAL_INTERFACE_H +#define CV_HAL_INTER_NEAREST 0 +#define CV_HAL_INTER_LINEAR 1 +#define CV_HAL_INTER_CUBIC 2 +#define CV_HAL_INTER_AREA 3 +#define CV_HAL_INTER_LANCZOS4 4 +#define MORPH_ERODE 0 +#define MORPH_DILATE 1 + +inline int ovx_hal_resize(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, double inv_scale_x, double inv_scale_y, int interpolation) +{ + try + { + vxContext * ctx = vxContext::getContext(); + vxImage ia(*ctx, a, astep, aw, ah); + vxImage ib(*ctx, b, bstep, bw, bh); + + if(!((atype == CV_8UC1 || atype == CV_8SC1) && + inv_scale_x > 0 && inv_scale_y > 0 && + (bw - 0.5) / inv_scale_x - 0.5 < aw && (bh - 0.5) / inv_scale_y - 0.5 < ah && + (bw + 0.5) / inv_scale_x + 0.5 >= aw && (bh + 0.5) / inv_scale_y + 0.5 >= ah && + std::abs(bw / inv_scale_x - aw) < 0.1 && std::abs(bh / inv_scale_y - ah) < 0.1 )) + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad scale").check(); + + int mode; + if (interpolation == CV_HAL_INTER_LINEAR) + mode = VX_INTERPOLATION_BILINEAR; + else if (interpolation == CV_HAL_INTER_AREA) + mode = VX_INTERPOLATION_AREA; + else if (interpolation == CV_HAL_INTER_NEAREST) + mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; + else + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad interpolation mode").check(); + + vxErr::check( vxuScaleImage(ctx->ctx, ia.img, ib.img, mode)); + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +inline int ovx_hal_warpAffine(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, const double M[6], int interpolation, int, const double*) +{ + try + { + vxContext * ctx = vxContext::getContext(); + vxImage ia(*ctx, a, astep, aw, ah); + vxImage ib(*ctx, b, bstep, bw, bh); + + if (!(atype == CV_8UC1 || atype == CV_8SC1)) + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad input type").check(); + + // It make sense to check border mode as well, but it's impossible to set border mode for immediate OpenVX calls + // So the only supported modes should be UNDEFINED(there is no such for HAL) and probably ISOLATED + + int mode; + if (interpolation == CV_HAL_INTER_LINEAR) + mode = VX_INTERPOLATION_BILINEAR; + else if (interpolation == CV_HAL_INTER_AREA) + mode = VX_INTERPOLATION_AREA; + else if (interpolation == CV_HAL_INTER_NEAREST) + mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; + else + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad interpolation mode").check(); + + vxMatrix mtx(*ctx, std::vector(M, M + 6).data(), 2, 3); + vxErr::check(vxuWarpAffine(ctx->ctx, ia.img, mtx.mtx, mode, ib.img)); + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +inline int ovx_hal_warpPerspectve(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, const double M[9], int interpolation, int, const double*) +{ + try + { + vxContext * ctx = vxContext::getContext(); + vxImage ia(*ctx, a, astep, aw, ah); + vxImage ib(*ctx, b, bstep, bw, bh); + + if (!(atype == CV_8UC1 || atype == CV_8SC1)) + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad input type").check(); + + // It make sense to check border mode as well, but it's impossible to set border mode for immediate OpenVX calls + // So the only supported modes should be UNDEFINED(there is no such for HAL) and probably ISOLATED + + int mode; + if (interpolation == CV_HAL_INTER_LINEAR) + mode = VX_INTERPOLATION_BILINEAR; + else if (interpolation == CV_HAL_INTER_AREA) + mode = VX_INTERPOLATION_AREA; + else if (interpolation == CV_HAL_INTER_NEAREST) + mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; + else + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad interpolation mode").check(); + + vxMatrix mtx(*ctx, std::vector(M, M + 9).data(), 3, 3); + vxErr::check(vxuWarpAffine(ctx->ctx, ia.img, mtx.mtx, mode, ib.img)); + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +struct cvhalFilter2D; + +struct FilterCtx +{ + vxConvolution cnv; + int dst_type; + FilterCtx(vxContext &ctx, const short *data, int w, int h, int _dst_type) : + cnv(ctx, data, w, h), dst_type(_dst_type) {} +}; + +inline int ovx_hal_filterInit(cvhalFilter2D **filter_context, uchar *kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, + int max_width, int max_height, int src_type, int dst_type, int borderType, double delta, int anchor_x, int anchor_y, bool allowSubmatrix, bool allowInplace) +{ + if (!filter_context || !kernel_data || allowSubmatrix || allowInplace || delta != 0 || + src_type != CV_8UC1 || (dst_type != CV_8UC1 && dst_type != CV_16SC1) || + kernel_width % 2 == 0 || kernel_height % 2 == 0 || anchor_x != kernel_width / 2 || anchor_y != kernel_height / 2) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + // It make sense to check border mode as well, but it's impossible to set border mode for immediate OpenVX calls + // So the only supported modes should be UNDEFINED(there is no such for HAL) and probably ISOLATED + + vxContext * ctx = vxContext::getContext(); + + std::vector data; + data.reserve(kernel_width*kernel_height); + switch (kernel_type) + { + case CV_8UC1: + for (int j = 0; j < kernel_height; ++j) + { + uchar * row = (uchar*)(kernel_data + kernel_step*j); + for (int i = 0; i < kernel_width; ++i) + data.push_back(row[i]); + } + break; + case CV_8SC1: + for (int j = 0; j < kernel_height; ++j) + { + schar * row = (schar*)(kernel_data + kernel_step*j); + for (int i = 0; i < kernel_width; ++i) + data.push_back(row[i]); + } + break; + case CV_16SC1: + for (int j = 0; j < kernel_height; ++j) + { + short * row = (short*)(kernel_data + kernel_step*j); + for (int i = 0; i < kernel_width; ++i) + data.push_back(row[i]); + } + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + FilterCtx* cnv = new FilterCtx(*ctx, data.data(), kernel_width, kernel_height, dst_type); + if (!cnv) + return CV_HAL_ERROR_UNKNOWN; + + *filter_context = (cvhalFilter2D*)(cnv); + return CV_HAL_ERROR_OK; +} + +inline int ovx_hal_filterFree(cvhalFilter2D *filter_context) +{ + if (filter_context) + { + delete (FilterCtx*)filter_context; + return CV_HAL_ERROR_OK; + } + else + { + return CV_HAL_ERROR_UNKNOWN; + } +} + +inline int ovx_hal_filter(cvhalFilter2D *filter_context, uchar *a, size_t astep, uchar *b, size_t bstep, int w, int h, int full_w, int full_h, int offset_x, int offset_y) +{ + try + { + FilterCtx* cnv = (FilterCtx*)filter_context; + if(cnv) + vxErr::check(cnv->cnv.cnv); + else + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad HAL context").check(); + + vxContext * ctx = vxContext::getContext(); + vxImage ia(*ctx, a, astep, w, h); + + if (cnv->dst_type == CV_16SC1) + { + vxImage ib(*ctx, (short*)b, bstep, w, h); + vxErr::check(vxuConvolve(ctx->ctx, ia.img, cnv->cnv.cnv, ib.img)); + } + else + { + vxImage ib(*ctx, b, bstep, w, h); + vxErr::check(vxuConvolve(ctx->ctx, ia.img, cnv->cnv.cnv, ib.img)); + } + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +#endif + //================================================================================================== // functions redefinition // ... @@ -245,4 +523,22 @@ inline int ovx_hal_not(const uchar *a, size_t astep, uchar *c, size_t cstep, int #undef cv_hal_mul16s #define cv_hal_mul16s ovx_hal_mul +#if defined OPENCV_IMGPROC_HAL_INTERFACE_H + +#undef cv_hal_resize +#define cv_hal_resize ovx_hal_resize +#undef cv_hal_warpAffine +#define cv_hal_warpAffine ovx_hal_warpAffine +#undef cv_hal_warpPerspective +#define cv_hal_warpPerspective ovx_hal_warpPerspectve + +#undef cv_hal_filterInit +#define cv_hal_filterInit ovx_hal_filterInit +#undef cv_hal_filter +#define cv_hal_filter ovx_hal_filter +#undef cv_hal_filterFree +#define cv_hal_filterFree ovx_hal_filterFree + +#endif + #endif From 5ec47299e23b86c8944ce3d25dc7f5d302bcaac3 Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Thu, 1 Sep 2016 16:11:44 +0300 Subject: [PATCH 138/178] Fixed warpings, added border mode support to warps and filter. Added morphology HAL API functions implemented as immediate mode OpenVX calls. --- 3rdparty/openvx/include/openvx_hal.hpp | 257 ++++++++++++++++++++++-- modules/imgproc/src/hal_replacement.hpp | 2 +- 2 files changed, 241 insertions(+), 18 deletions(-) diff --git a/3rdparty/openvx/include/openvx_hal.hpp b/3rdparty/openvx/include/openvx_hal.hpp index 6dbec79af0..a9f5ddfde5 100644 --- a/3rdparty/openvx/include/openvx_hal.hpp +++ b/3rdparty/openvx/include/openvx_hal.hpp @@ -8,6 +8,7 @@ #include #include +#include //================================================================================================== // utility @@ -312,7 +313,7 @@ inline int ovx_hal_resize(int atype, const uchar *a, size_t astep, int aw, int a return CV_HAL_ERROR_OK; } -inline int ovx_hal_warpAffine(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, const double M[6], int interpolation, int, const double*) +inline int ovx_hal_warpAffine(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, const double M[6], int interpolation, int borderType, const double borderValue[4]) { try { @@ -323,8 +324,19 @@ inline int ovx_hal_warpAffine(int atype, const uchar *a, size_t astep, int aw, i if (!(atype == CV_8UC1 || atype == CV_8SC1)) vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad input type").check(); - // It make sense to check border mode as well, but it's impossible to set border mode for immediate OpenVX calls - // So the only supported modes should be UNDEFINED(there is no such for HAL) and probably ISOLATED + vx_border_t border; + switch (borderType) + { + case CV_HAL_BORDER_CONSTANT: + border.mode = VX_BORDER_CONSTANT; + border.constant_value.U8 = borderValue[0]; + break; + case CV_HAL_BORDER_REPLICATE: + border.mode = VX_BORDER_REPLICATE; + break; + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } int mode; if (interpolation == CV_HAL_INTER_LINEAR) @@ -336,8 +348,20 @@ inline int ovx_hal_warpAffine(int atype, const uchar *a, size_t astep, int aw, i else vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad interpolation mode").check(); - vxMatrix mtx(*ctx, std::vector(M, M + 6).data(), 2, 3); + std::vector data; + data.reserve(6); + for (int j = 0; j < 3; ++j) + for (int i = 0; i < 2; ++i) + data.push_back(M[i*3+j]); + + vxMatrix mtx(*ctx, data.data(), 2, 3); + //ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments + //since OpenVX standart says nothing about thread-safety for now + vx_border_t prevBorder; + vxErr::check(vxQueryContext(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); + vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &border, sizeof(border))); vxErr::check(vxuWarpAffine(ctx->ctx, ia.img, mtx.mtx, mode, ib.img)); + vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); } catch (vxErr & e) { @@ -347,7 +371,7 @@ inline int ovx_hal_warpAffine(int atype, const uchar *a, size_t astep, int aw, i return CV_HAL_ERROR_OK; } -inline int ovx_hal_warpPerspectve(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, const double M[9], int interpolation, int, const double*) +inline int ovx_hal_warpPerspectve(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, const double M[9], int interpolation, int borderType, const double borderValue[4]) { try { @@ -358,8 +382,19 @@ inline int ovx_hal_warpPerspectve(int atype, const uchar *a, size_t astep, int a if (!(atype == CV_8UC1 || atype == CV_8SC1)) vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad input type").check(); - // It make sense to check border mode as well, but it's impossible to set border mode for immediate OpenVX calls - // So the only supported modes should be UNDEFINED(there is no such for HAL) and probably ISOLATED + vx_border_t border; + switch (borderType) + { + case CV_HAL_BORDER_CONSTANT: + border.mode = VX_BORDER_CONSTANT; + border.constant_value.U8 = borderValue[0]; + break; + case CV_HAL_BORDER_REPLICATE: + border.mode = VX_BORDER_REPLICATE; + break; + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } int mode; if (interpolation == CV_HAL_INTER_LINEAR) @@ -371,8 +406,20 @@ inline int ovx_hal_warpPerspectve(int atype, const uchar *a, size_t astep, int a else vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad interpolation mode").check(); - vxMatrix mtx(*ctx, std::vector(M, M + 9).data(), 3, 3); - vxErr::check(vxuWarpAffine(ctx->ctx, ia.img, mtx.mtx, mode, ib.img)); + std::vector data; + data.reserve(9); + for (int j = 0; j < 3; ++j) + for (int i = 0; i < 3; ++i) + data.push_back(M[i * 3 + j]); + + vxMatrix mtx(*ctx, data.data(), 3, 3); + //ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments + //since OpenVX standart says nothing about thread-safety for now + vx_border_t prevBorder; + vxErr::check(vxQueryContext(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); + vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &border, sizeof(border))); + vxErr::check(vxuWarpPerspective(ctx->ctx, ia.img, mtx.mtx, mode, ib.img)); + vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); } catch (vxErr & e) { @@ -387,9 +434,10 @@ struct cvhalFilter2D; struct FilterCtx { vxConvolution cnv; + vx_border_t border; int dst_type; - FilterCtx(vxContext &ctx, const short *data, int w, int h, int _dst_type) : - cnv(ctx, data, w, h), dst_type(_dst_type) {} + FilterCtx(vxContext &ctx, const short *data, int w, int h, int _dst_type, vx_border_t & _border) : + cnv(ctx, data, w, h), dst_type(_dst_type), border(_border) {} }; inline int ovx_hal_filterInit(cvhalFilter2D **filter_context, uchar *kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, @@ -400,8 +448,19 @@ inline int ovx_hal_filterInit(cvhalFilter2D **filter_context, uchar *kernel_data kernel_width % 2 == 0 || kernel_height % 2 == 0 || anchor_x != kernel_width / 2 || anchor_y != kernel_height / 2) return CV_HAL_ERROR_NOT_IMPLEMENTED; - // It make sense to check border mode as well, but it's impossible to set border mode for immediate OpenVX calls - // So the only supported modes should be UNDEFINED(there is no such for HAL) and probably ISOLATED + vx_border_t border; + switch (borderType) + { + case CV_HAL_BORDER_CONSTANT: + border.mode = VX_BORDER_CONSTANT; + border.constant_value.U8 = 0; + break; + case CV_HAL_BORDER_REPLICATE: + border.mode = VX_BORDER_REPLICATE; + break; + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } vxContext * ctx = vxContext::getContext(); @@ -436,7 +495,7 @@ inline int ovx_hal_filterInit(cvhalFilter2D **filter_context, uchar *kernel_data return CV_HAL_ERROR_NOT_IMPLEMENTED; } - FilterCtx* cnv = new FilterCtx(*ctx, data.data(), kernel_width, kernel_height, dst_type); + FilterCtx* cnv = new FilterCtx(*ctx, data.data(), kernel_width, kernel_height, dst_type, border); if (!cnv) return CV_HAL_ERROR_UNKNOWN; @@ -462,14 +521,17 @@ inline int ovx_hal_filter(cvhalFilter2D *filter_context, uchar *a, size_t astep, try { FilterCtx* cnv = (FilterCtx*)filter_context; - if(cnv) - vxErr::check(cnv->cnv.cnv); - else + if(!cnv) vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad HAL context").check(); vxContext * ctx = vxContext::getContext(); vxImage ia(*ctx, a, astep, w, h); + //ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments + //since OpenVX standart says nothing about thread-safety for now + vx_border_t prevBorder; + vxErr::check(vxQueryContext(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); + vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &(cnv->border), sizeof(cnv->border))); if (cnv->dst_type == CV_16SC1) { vxImage ib(*ctx, (short*)b, bstep, w, h); @@ -480,6 +542,160 @@ inline int ovx_hal_filter(cvhalFilter2D *filter_context, uchar *a, size_t astep, vxImage ib(*ctx, b, bstep, w, h); vxErr::check(vxuConvolve(ctx->ctx, ia.img, cnv->cnv.cnv, ib.img)); } + vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +struct MorphCtx +{ + vxMatrix mask; + int operation; + vx_border_t border; + MorphCtx(vxContext &ctx, const uchar *data, int w, int h, int _operation, vx_border_t & _border) : + mask(ctx, data, w, h), operation(_operation), border(_border) {} +}; + +inline int ovx_hal_morphInit(cvhalFilter2D **filter_context, int operation, int src_type, int dst_type, int max_width, int max_height, + int kernel_type, uchar *kernel_data, size_t kernel_step, int kernel_width, int kernel_height, int anchor_x, int anchor_y, + int borderType, const double borderValue[4], int iterations, bool allowSubmatrix, bool allowInplace) +{ + if (!filter_context || !kernel_data || allowSubmatrix || allowInplace || iterations != 1 || + src_type != CV_8UC1 || dst_type != CV_8UC1 || + kernel_width % 2 == 0 || kernel_height % 2 == 0 || anchor_x != kernel_width / 2 || anchor_y != kernel_height / 2) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + vx_border_t border; + switch (borderType) + { + case CV_HAL_BORDER_CONSTANT: + border.mode = VX_BORDER_CONSTANT; + if (borderValue[0] == DBL_MAX && borderValue[1] == DBL_MAX && borderValue[2] == DBL_MAX && borderValue[3] == DBL_MAX) + { + if (operation == MORPH_ERODE) + border.constant_value.U8 = UCHAR_MAX; + else + border.constant_value.U8 = 0; + } + else + { + border.constant_value.U8 = cv::saturate_cast(borderValue[0]); + } + break; + case CV_HAL_BORDER_REPLICATE: + border.mode = VX_BORDER_REPLICATE; + break; + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + vxContext * ctx = vxContext::getContext(); + + std::vector kernel_mat; + kernel_mat.resize(kernel_width * kernel_height); + switch (CV_MAT_DEPTH(kernel_type)) + { + case CV_8U: + case CV_8S: + for (int j = 0; j < kernel_height; ++j) + { + uchar * kernel_row = kernel_data + j * kernel_step; + for (int i = 0; i < kernel_height; ++i) + kernel_mat.push_back(kernel_row[i] ? 255 : 0); + } + break; + case CV_16U: + case CV_16S: + for (int j = 0; j < kernel_height; ++j) + { + short * kernel_row = (short*)(kernel_data + j * kernel_step); + for (int i = 0; i < kernel_height; ++i) + kernel_mat.push_back(kernel_row[i] ? 255 : 0); + } + break; + case CV_32S: + for (int j = 0; j < kernel_height; ++j) + { + int * kernel_row = (int*)(kernel_data + j * kernel_step); + for (int i = 0; i < kernel_height; ++i) + kernel_mat.push_back(kernel_row[i] ? 255 : 0); + } + break; + case CV_32F: + for (int j = 0; j < kernel_height; ++j) + { + float * kernel_row = (float*)(kernel_data + j * kernel_step); + for (int i = 0; i < kernel_height; ++i) + kernel_mat.push_back(kernel_row[i] ? 255 : 0); + } + break; + case CV_64F: + for (int j = 0; j < kernel_height; ++j) + { + double * kernel_row = (double*)(kernel_data + j * kernel_step); + for (int i = 0; i < kernel_height; ++i) + kernel_mat.push_back(kernel_row[i] ? 255 : 0); + } + break; + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + MorphCtx* mat; + switch (operation) + { + case MORPH_ERODE: + mat = new MorphCtx(*ctx, kernel_mat.data(), kernel_width, kernel_height, VX_NONLINEAR_FILTER_MIN, border); + case MORPH_DILATE: + mat = new MorphCtx(*ctx, kernel_mat.data(), kernel_width, kernel_height, VX_NONLINEAR_FILTER_MAX, border); + break; + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + if (!mat) + return CV_HAL_ERROR_UNKNOWN; + + *filter_context = (cvhalFilter2D*)(mat); + return CV_HAL_ERROR_OK; +} + +inline int ovx_hal_morphFree(cvhalFilter2D *filter_context) +{ + if (filter_context) + { + delete (MorphCtx*)filter_context; + return CV_HAL_ERROR_OK; + } + else + { + return CV_HAL_ERROR_UNKNOWN; + } +} + +inline int ovx_hal_morph(cvhalFilter2D *filter_context, uchar *a, size_t astep, uchar *b, size_t bstep, int w, int h, int src_full_width, int src_full_height, int src_roi_x, int src_roi_y, int dst_full_width, int dst_full_height, int dst_roi_x, int dst_roi_y) +{ + try + { + MorphCtx* mat = (MorphCtx*)filter_context; + if (!mat) + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad HAL context").check(); + + vxContext * ctx = vxContext::getContext(); + vxImage ia(*ctx, a, astep, w, h); + vxImage ib(*ctx, b, bstep, w, h); + + //ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments + //since OpenVX standart says nothing about thread-safety for now + vx_border_t prevBorder; + vxErr::check(vxQueryContext(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); + vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &(mat->border), sizeof(mat->border))); + vxErr::check(vxuNonLinearFilter(ctx->ctx, mat->operation, ia.img, mat->mask.mtx, ib.img)); + vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); } catch (vxErr & e) { @@ -539,6 +755,13 @@ inline int ovx_hal_filter(cvhalFilter2D *filter_context, uchar *a, size_t astep, #undef cv_hal_filterFree #define cv_hal_filterFree ovx_hal_filterFree +#undef cv_hal_morphInit +#define cv_hal_morphInit ovx_hal_morphInit +#undef cv_hal_morph +#define cv_hal_morph ovx_hal_morph +#undef cv_hal_morphFree +#define cv_hal_morphFree ovx_hal_morphFree + #endif #endif diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index fdf3ab72e8..3196cd88eb 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -263,7 +263,7 @@ inline int hal_ni_resize(int src_type, const uchar *src_data, size_t src_step, i @param dst_step destination image step @param dst_width destination image width @param dst_height destination image height - @param M 3x2 matrix with transform coefficients + @param M 2x3 matrix with transform coefficients @param interpolation interpolation mode (CV_HAL_INTER_NEAREST, ...) @param borderType border processing mode (CV_HAL_BORDER_REFLECT, ...) @param borderValue values to use for CV_HAL_BORDER_CONSTANT mode From fb3140ceefc403216a387de9917578b8c1e3157a Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Thu, 8 Sep 2016 14:22:11 +0300 Subject: [PATCH 139/178] Fixed compilation. Changed value returned by functions called with unsuported parameters. --- 3rdparty/openvx/include/openvx_hal.hpp | 75 ++++++++++++++++---------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/3rdparty/openvx/include/openvx_hal.hpp b/3rdparty/openvx/include/openvx_hal.hpp index a9f5ddfde5..af1771a88a 100644 --- a/3rdparty/openvx/include/openvx_hal.hpp +++ b/3rdparty/openvx/include/openvx_hal.hpp @@ -8,6 +8,8 @@ #include #include + +#include #include //================================================================================================== @@ -168,7 +170,7 @@ struct vxImage addr.dim_x = w; addr.dim_y = h; addr.stride_x = sizeof(T); - addr.stride_y = step; + addr.stride_y = (vx_int32)step; addr.scale_x = VX_SCALE_UNITY; addr.scale_y = VX_SCALE_UNITY; addr.step_x = 1; @@ -193,7 +195,7 @@ struct vxMatrix { mtx = vxCreateMatrix(ctx.ctx, VX_Traits::DataType, w, h); vxErr::check(mtx); - vxErr::check(vxCopyMatrix(mtx, data, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); + vxErr::check(vxCopyMatrix(mtx, const_cast(data), VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST)); } ~vxMatrix() { @@ -209,7 +211,7 @@ struct vxConvolution { cnv = vxCreateConvolution(ctx.ctx, w, h); vxErr::check(cnv); - vxErr::check(vxCopyConvolutionCoefficients(cnv, (void*)data, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); + vxErr::check(vxCopyConvolutionCoefficients(cnv, const_cast(data), VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST)); } ~vxConvolution() { @@ -221,24 +223,24 @@ struct vxConvolution // real code starts here // ... -#define OVX_BINARY_OP(hal_func, ovx_call, ...) \ -template \ -inline int ovx_hal_##hal_func(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h, __VA_ARGS__) \ -{ \ - try \ - { \ - vxContext * ctx = vxContext::getContext(); \ - vxImage ia(*ctx, a, astep, w, h); \ - vxImage ib(*ctx, b, bstep, w, h); \ - vxImage ic(*ctx, c, cstep, w, h); \ - ovx_call \ - } \ - catch (vxErr & e) \ - { \ - e.print(); \ - return CV_HAL_ERROR_UNKNOWN; \ - } \ - return CV_HAL_ERROR_OK; \ +#define OVX_BINARY_OP(hal_func, ovx_call) \ +template \ +inline int ovx_hal_##hal_func(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h) \ +{ \ + try \ + { \ + vxContext * ctx = vxContext::getContext(); \ + vxImage ia(*ctx, a, astep, w, h); \ + vxImage ib(*ctx, b, bstep, w, h); \ + vxImage ic(*ctx, c, cstep, w, h); \ + ovx_call \ + } \ + catch (vxErr & e) \ + { \ + e.print(); \ + return CV_HAL_ERROR_UNKNOWN; \ + } \ + return CV_HAL_ERROR_OK; \ } OVX_BINARY_OP(add, {vxErr::check(vxuAdd(ctx->ctx, ia.img, ib.img, VX_CONVERT_POLICY_SATURATE, ic.img));}) @@ -250,7 +252,24 @@ OVX_BINARY_OP(and, {vxErr::check(vxuAnd(ctx->ctx, ia.img, ib.img, ic.img));}) OVX_BINARY_OP(or, {vxErr::check(vxuOr(ctx->ctx, ia.img, ib.img, ic.img));}) OVX_BINARY_OP(xor, {vxErr::check(vxuXor(ctx->ctx, ia.img, ib.img, ic.img));}) -OVX_BINARY_OP(mul, {vxErr::check(vxuMultiply(ctx->ctx, ia.img, ib.img, (float)scale, VX_CONVERT_POLICY_SATURATE, VX_ROUND_POLICY_TO_ZERO, ic.img));}, double scale) +template +inline int ovx_hal_mul(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h, double scale) +{ + try + { + vxContext * ctx = vxContext::getContext(); + vxImage ia(*ctx, a, astep, w, h); + vxImage ib(*ctx, b, bstep, w, h); + vxImage ic(*ctx, c, cstep, w, h); + vxErr::check(vxuMultiply(ctx->ctx, ia.img, ib.img, (float)scale, VX_CONVERT_POLICY_SATURATE, VX_ROUND_POLICY_TO_ZERO, ic.img)); + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} inline int ovx_hal_not(const uchar *a, size_t astep, uchar *c, size_t cstep, int w, int h) { @@ -291,7 +310,7 @@ inline int ovx_hal_resize(int atype, const uchar *a, size_t astep, int aw, int a (bw - 0.5) / inv_scale_x - 0.5 < aw && (bh - 0.5) / inv_scale_y - 0.5 < ah && (bw + 0.5) / inv_scale_x + 0.5 >= aw && (bh + 0.5) / inv_scale_y + 0.5 >= ah && std::abs(bw / inv_scale_x - aw) < 0.1 && std::abs(bh / inv_scale_y - ah) < 0.1 )) - vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad scale").check(); + return CV_HAL_ERROR_NOT_IMPLEMENTED; int mode; if (interpolation == CV_HAL_INTER_LINEAR) @@ -301,7 +320,7 @@ inline int ovx_hal_resize(int atype, const uchar *a, size_t astep, int aw, int a else if (interpolation == CV_HAL_INTER_NEAREST) mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; else - vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad interpolation mode").check(); + return CV_HAL_ERROR_NOT_IMPLEMENTED; vxErr::check( vxuScaleImage(ctx->ctx, ia.img, ib.img, mode)); } @@ -322,7 +341,7 @@ inline int ovx_hal_warpAffine(int atype, const uchar *a, size_t astep, int aw, i vxImage ib(*ctx, b, bstep, bw, bh); if (!(atype == CV_8UC1 || atype == CV_8SC1)) - vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad input type").check(); + return CV_HAL_ERROR_NOT_IMPLEMENTED; vx_border_t border; switch (borderType) @@ -346,7 +365,7 @@ inline int ovx_hal_warpAffine(int atype, const uchar *a, size_t astep, int aw, i else if (interpolation == CV_HAL_INTER_NEAREST) mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; else - vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad interpolation mode").check(); + return CV_HAL_ERROR_NOT_IMPLEMENTED; std::vector data; data.reserve(6); @@ -380,7 +399,7 @@ inline int ovx_hal_warpPerspectve(int atype, const uchar *a, size_t astep, int a vxImage ib(*ctx, b, bstep, bw, bh); if (!(atype == CV_8UC1 || atype == CV_8SC1)) - vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad input type").check(); + return CV_HAL_ERROR_NOT_IMPLEMENTED; vx_border_t border; switch (borderType) @@ -404,7 +423,7 @@ inline int ovx_hal_warpPerspectve(int atype, const uchar *a, size_t astep, int a else if (interpolation == CV_HAL_INTER_NEAREST) mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; else - vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad interpolation mode").check(); + return CV_HAL_ERROR_NOT_IMPLEMENTED; std::vector data; data.reserve(9); From d402bac69dce841a067730c4382d2550650873cc Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 8 Sep 2016 19:41:11 +0300 Subject: [PATCH 140/178] cmake: fix libpng build on MSVS2012 --- 3rdparty/libpng/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/3rdparty/libpng/CMakeLists.txt b/3rdparty/libpng/CMakeLists.txt index eaf2095b8a..99e4663033 100644 --- a/3rdparty/libpng/CMakeLists.txt +++ b/3rdparty/libpng/CMakeLists.txt @@ -33,7 +33,8 @@ if(ENABLE_NEON) add_definitions(-DPNG_ARM_NEON_OPT=2) endif() -if(ENABLE_SSE) +if(ENABLE_SSE + AND (NOT MSVC OR (MSVC_VERSION GREATER 1799))) # MSVS2013+ (issue #7232) list(APPEND lib_srcs contrib/intel/intel_init.c contrib/intel/filter_sse2_intrinsics.c) add_definitions(-DPNG_INTEL_SSE) endif() From 14fd22e664ba381d500e2044db013057f6ebe875 Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Thu, 8 Sep 2016 19:47:03 +0300 Subject: [PATCH 141/178] Added morphology and channel merge HAL API functions implemented as immediate mode OpenVX calls. --- 3rdparty/openvx/include/openvx_hal.hpp | 188 +++++++++++++++++++++++-- 1 file changed, 180 insertions(+), 8 deletions(-) diff --git a/3rdparty/openvx/include/openvx_hal.hpp b/3rdparty/openvx/include/openvx_hal.hpp index af1771a88a..3a16fa231d 100644 --- a/3rdparty/openvx/include/openvx_hal.hpp +++ b/3rdparty/openvx/include/openvx_hal.hpp @@ -179,6 +179,92 @@ struct vxImage img = vxCreateImageFromHandle(ctx.ctx, VX_Traits::ImgType, &addr, ptrs, VX_MEMORY_TYPE_HOST); vxErr::check(img); } + vxImage(vxContext &ctx, int imgType, const uchar *data, size_t step, int w, int h) + { + if (h == 1) + step = w; + vx_imagepatch_addressing_t addr[4]; + void *ptrs[4]; + switch (imgType) + { + case VX_DF_IMAGE_U8: + case VX_DF_IMAGE_U16: + case VX_DF_IMAGE_S16: + case VX_DF_IMAGE_U32: + case VX_DF_IMAGE_S32: + case VX_DF_IMAGE_RGB: + case VX_DF_IMAGE_RGBX: + case VX_DF_IMAGE_UYVY: + case VX_DF_IMAGE_YUYV: + addr[0].dim_x = w; + addr[0].dim_y = h; + addr[0].stride_x = imgType == VX_DF_IMAGE_U8 ? 1 : + imgType == VX_DF_IMAGE_RGB ? 3 : + (imgType == VX_DF_IMAGE_U16 || imgType == VX_DF_IMAGE_S16) ? 2 : 4; + addr[0].stride_y = (vx_int32)step; + addr[0].scale_x = VX_SCALE_UNITY; + addr[0].scale_y = VX_SCALE_UNITY; + addr[0].step_x = (imgType == VX_DF_IMAGE_UYVY || imgType == VX_DF_IMAGE_YUYV) ? 2 : 1; + addr[0].step_y = 1; + ptrs[0] = (void*)data; + break; + case VX_DF_IMAGE_NV12: + case VX_DF_IMAGE_NV21: + addr[0].dim_x = w; + addr[0].dim_y = h; + addr[0].stride_x = 1; + addr[0].stride_y = (vx_int32)step; + addr[0].scale_x = VX_SCALE_UNITY; + addr[0].scale_y = VX_SCALE_UNITY; + addr[0].step_x = 1; + addr[0].step_y = 1; + ptrs[0] = (void*)data; + addr[1].dim_x = (w + 1) / 2; + addr[1].dim_y = (h + 1) / 2; + addr[1].stride_x = 2; + addr[1].stride_y = (vx_int32)step; + addr[1].scale_x = VX_SCALE_UNITY; + addr[1].scale_y = VX_SCALE_UNITY; + addr[1].step_x = 2; + addr[1].step_y = 2; + ptrs[1] = (void*)(data + h * step); + break; + case VX_DF_IMAGE_IYUV: + case VX_DF_IMAGE_YUV4: + addr[0].dim_x = w; + addr[0].dim_y = h; + addr[0].stride_x = 1; + addr[0].stride_y = (vx_int32)step; + addr[0].scale_x = VX_SCALE_UNITY; + addr[0].scale_y = VX_SCALE_UNITY; + addr[0].step_x = 1; + addr[0].step_y = 1; + ptrs[0] = (void*)data; + addr[1].dim_x = imgType == VX_DF_IMAGE_YUV4 ? w : (w + 1) / 2; + addr[1].dim_y = imgType == VX_DF_IMAGE_YUV4 ? h : (h + 1) / 2; + addr[1].stride_x = 1; + addr[1].stride_y = (vx_int32)step; + addr[1].scale_x = VX_SCALE_UNITY; + addr[1].scale_y = VX_SCALE_UNITY; + addr[1].step_x = imgType == VX_DF_IMAGE_YUV4 ? 1 : 2; + addr[1].step_y = imgType == VX_DF_IMAGE_YUV4 ? 1 : 2; + ptrs[1] = (void*)(data + h * step); + addr[2].dim_x = addr[1].dim_x; + addr[2].dim_y = addr[1].dim_y; + addr[2].stride_x = 1; + addr[2].stride_y = (vx_int32)step; + addr[2].scale_x = VX_SCALE_UNITY; + addr[2].scale_y = VX_SCALE_UNITY; + addr[2].step_x = addr[1].step_x; + addr[2].step_y = addr[1].step_y; + ptrs[2] = (void*)(data + (h + addr[1].dim_y) * step); + break; + default: + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad image format").check(); + } + img = vxCreateImageFromHandle(ctx.ctx, imgType, addr, ptrs, VX_MEMORY_TYPE_HOST); + vxErr::check(img); + } ~vxImage() { vxErr::check(vxSwapImageHandle(img, NULL, NULL, 1)); @@ -288,6 +374,30 @@ inline int ovx_hal_not(const uchar *a, size_t astep, uchar *c, size_t cstep, int return CV_HAL_ERROR_OK; } +inline int ovx_hal_merge8u(const uchar **src_data, uchar *dst_data, int len, int cn) +{ + if (cn != 3 && cn != 4) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + try + { + vxContext * ctx = vxContext::getContext(); + vxImage ia(*ctx, src_data[0], len, len, 1); + vxImage ib(*ctx, src_data[1], len, len, 1); + vxImage ic(*ctx, src_data[2], len, len, 1); + vxImage id(*ctx, cn == 4 ? VX_DF_IMAGE_RGBX : VX_DF_IMAGE_RGB, dst_data, len, len, 1); + vxErr::check(vxuChannelCombine(ctx->ctx, ia.img, ib.img, ic.img, + cn == 4 ? vxImage(*ctx, src_data[3], len, len, 1).img : NULL, + id.img)); + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + + #if defined OPENCV_IMGPROC_HAL_INTERFACE_H #define CV_HAL_INTER_NEAREST 0 #define CV_HAL_INTER_LINEAR 1 @@ -348,7 +458,7 @@ inline int ovx_hal_warpAffine(int atype, const uchar *a, size_t astep, int aw, i { case CV_HAL_BORDER_CONSTANT: border.mode = VX_BORDER_CONSTANT; - border.constant_value.U8 = borderValue[0]; + border.constant_value.U8 = (vx_uint8)(borderValue[0]); break; case CV_HAL_BORDER_REPLICATE: border.mode = VX_BORDER_REPLICATE; @@ -371,7 +481,7 @@ inline int ovx_hal_warpAffine(int atype, const uchar *a, size_t astep, int aw, i data.reserve(6); for (int j = 0; j < 3; ++j) for (int i = 0; i < 2; ++i) - data.push_back(M[i*3+j]); + data.push_back((float)(M[i*3+j])); vxMatrix mtx(*ctx, data.data(), 2, 3); //ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments @@ -406,7 +516,7 @@ inline int ovx_hal_warpPerspectve(int atype, const uchar *a, size_t astep, int a { case CV_HAL_BORDER_CONSTANT: border.mode = VX_BORDER_CONSTANT; - border.constant_value.U8 = borderValue[0]; + border.constant_value.U8 = (vx_uint8)(borderValue[0]); break; case CV_HAL_BORDER_REPLICATE: border.mode = VX_BORDER_REPLICATE; @@ -429,7 +539,7 @@ inline int ovx_hal_warpPerspectve(int atype, const uchar *a, size_t astep, int a data.reserve(9); for (int j = 0; j < 3; ++j) for (int i = 0; i < 3; ++i) - data.push_back(M[i * 3 + j]); + data.push_back((float)(M[i * 3 + j])); vxMatrix mtx(*ctx, data.data(), 3, 3); //ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments @@ -460,7 +570,7 @@ struct FilterCtx }; inline int ovx_hal_filterInit(cvhalFilter2D **filter_context, uchar *kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, - int max_width, int max_height, int src_type, int dst_type, int borderType, double delta, int anchor_x, int anchor_y, bool allowSubmatrix, bool allowInplace) + int , int , int src_type, int dst_type, int borderType, double delta, int anchor_x, int anchor_y, bool allowSubmatrix, bool allowInplace) { if (!filter_context || !kernel_data || allowSubmatrix || allowInplace || delta != 0 || src_type != CV_8UC1 || (dst_type != CV_8UC1 && dst_type != CV_16SC1) || @@ -535,7 +645,7 @@ inline int ovx_hal_filterFree(cvhalFilter2D *filter_context) } } -inline int ovx_hal_filter(cvhalFilter2D *filter_context, uchar *a, size_t astep, uchar *b, size_t bstep, int w, int h, int full_w, int full_h, int offset_x, int offset_y) +inline int ovx_hal_filter(cvhalFilter2D *filter_context, uchar *a, size_t astep, uchar *b, size_t bstep, int w, int h, int , int , int , int ) { try { @@ -571,6 +681,58 @@ inline int ovx_hal_filter(cvhalFilter2D *filter_context, uchar *a, size_t astep, return CV_HAL_ERROR_OK; } +inline int ovx_hal_sepFilterInit(cvhalFilter2D **filter_context, int src_type, int dst_type, + int kernel_type, uchar *kernelx_data, int kernelx_length, uchar *kernely_data, int kernely_length, + int anchor_x, int anchor_y, double delta, int borderType) +{ + if (!filter_context || !kernelx_data || !kernely_data || delta != 0 || + src_type != CV_8UC1 || (dst_type != CV_8UC1 && dst_type != CV_16SC1) || + kernelx_length % 2 == 0 || kernely_length % 2 == 0 || anchor_x != kernelx_length / 2 || anchor_y != kernely_length / 2) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + vx_border_t border; + switch (borderType) + { + case CV_HAL_BORDER_CONSTANT: + border.mode = VX_BORDER_CONSTANT; + border.constant_value.U8 = 0; + break; + case CV_HAL_BORDER_REPLICATE: + border.mode = VX_BORDER_REPLICATE; + break; + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + vxContext * ctx = vxContext::getContext(); + + //At the moment OpenVX doesn't support separable filters natively so combine kernels to generic convolution + std::vector data; + data.reserve(kernelx_length*kernely_length); + switch (kernel_type) + { + case CV_8UC1: + for (int j = 0; j < kernely_length; ++j) + for (int i = 0; i < kernelx_length; ++i) + data.push_back((short)(kernely_data[j]) * kernelx_data[i]); + break; + case CV_8SC1: + for (int j = 0; j < kernely_length; ++j) + for (int i = 0; i < kernelx_length; ++i) + data.push_back((short)(((schar*)kernely_data)[j]) * ((schar*)kernelx_data)[i]); + break; + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + FilterCtx* cnv = new FilterCtx(*ctx, data.data(), kernelx_length, kernely_length, dst_type, border); + if (!cnv) + return CV_HAL_ERROR_UNKNOWN; + + *filter_context = (cvhalFilter2D*)(cnv); + return CV_HAL_ERROR_OK; +} + struct MorphCtx { vxMatrix mask; @@ -580,7 +742,7 @@ struct MorphCtx mask(ctx, data, w, h), operation(_operation), border(_border) {} }; -inline int ovx_hal_morphInit(cvhalFilter2D **filter_context, int operation, int src_type, int dst_type, int max_width, int max_height, +inline int ovx_hal_morphInit(cvhalFilter2D **filter_context, int operation, int src_type, int dst_type, int , int , int kernel_type, uchar *kernel_data, size_t kernel_step, int kernel_width, int kernel_height, int anchor_x, int anchor_y, int borderType, const double borderValue[4], int iterations, bool allowSubmatrix, bool allowInplace) { @@ -696,7 +858,7 @@ inline int ovx_hal_morphFree(cvhalFilter2D *filter_context) } } -inline int ovx_hal_morph(cvhalFilter2D *filter_context, uchar *a, size_t astep, uchar *b, size_t bstep, int w, int h, int src_full_width, int src_full_height, int src_roi_x, int src_roi_y, int dst_full_width, int dst_full_height, int dst_roi_x, int dst_roi_y) +inline int ovx_hal_morph(cvhalFilter2D *filter_context, uchar *a, size_t astep, uchar *b, size_t bstep, int w, int h, int , int , int , int , int , int , int , int ) { try { @@ -758,6 +920,9 @@ inline int ovx_hal_morph(cvhalFilter2D *filter_context, uchar *a, size_t astep, #undef cv_hal_mul16s #define cv_hal_mul16s ovx_hal_mul +#undef cv_hal_merge8u +#define cv_hal_merge8u ovx_hal_merge8u + #if defined OPENCV_IMGPROC_HAL_INTERFACE_H #undef cv_hal_resize @@ -774,6 +939,13 @@ inline int ovx_hal_morph(cvhalFilter2D *filter_context, uchar *a, size_t astep, #undef cv_hal_filterFree #define cv_hal_filterFree ovx_hal_filterFree +#undef cv_hal_sepFilterInit +#define cv_hal_sepFilterInit ovx_hal_sepFilterInit +#undef cv_hal_sepFilter +#define cv_hal_sepFilter ovx_hal_filter +#undef cv_hal_sepFilterFree +#define cv_hal_sepFilterFree ovx_hal_filterFree + #undef cv_hal_morphInit #define cv_hal_morphInit ovx_hal_morphInit #undef cv_hal_morph From 186f6977bcf64e1fc936a7022dd4d03bc9837d8f Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 8 Sep 2016 19:53:39 +0300 Subject: [PATCH 142/178] ffmpeg: update Windows binaries (ffmpeg 3.1.3) --- 3rdparty/ffmpeg/ffmpeg.cmake | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/3rdparty/ffmpeg/ffmpeg.cmake b/3rdparty/ffmpeg/ffmpeg.cmake index 193b5d8905..d89b0a573a 100644 --- a/3rdparty/ffmpeg/ffmpeg.cmake +++ b/3rdparty/ffmpeg/ffmpeg.cmake @@ -1,8 +1,8 @@ -# Binary branch name: ffmpeg/master_20160715 -# Binaries were created for OpenCV: 0e6aa189cb9a9642b0ae7983d301693516faad5d -set(FFMPEG_BINARIES_COMMIT "7eef9080d3271c7547d303fa839a62e1124ff1e6") -set(FFMPEG_FILE_HASH_BIN32 "3bb2a8388af90adf6c762210e696400d") -set(FFMPEG_FILE_HASH_BIN64 "ebcfc963f0a94f7e83d58d60eaf23849") +# Binary branch name: ffmpeg/master_20160908 +# Binaries were created for OpenCV: 11a65475d8d460a01c8818c5a2d0544ec49d7d68 +set(FFMPEG_BINARIES_COMMIT "03835134465888981e066434dc95009e8328d4ea") +set(FFMPEG_FILE_HASH_BIN32 "32ba7790b0ac7a6dc66be91603637a7d") +set(FFMPEG_FILE_HASH_BIN64 "068ecaa459a5571e7909cff90999a420") set(FFMPEG_FILE_HASH_CMAKE "f99941d10c1e87bf16b9055e8fc91ab2") set(FFMPEG_DOWNLOAD_URL ${OPENCV_FFMPEG_URL};$ENV{OPENCV_FFMPEG_URL};https://raw.githubusercontent.com/opencv/opencv_3rdparty/${FFMPEG_BINARIES_COMMIT}/ffmpeg/) From 311a232a09314aca57ad07fd2c42ca74a2d1aa11 Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Thu, 8 Sep 2016 20:40:51 +0300 Subject: [PATCH 143/178] Added color conversion HAL API functions implemented as immediate mode OpenVX calls. --- 3rdparty/openvx/include/openvx_hal.hpp | 111 +++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/3rdparty/openvx/include/openvx_hal.hpp b/3rdparty/openvx/include/openvx_hal.hpp index 3a16fa231d..a6547e12bb 100644 --- a/3rdparty/openvx/include/openvx_hal.hpp +++ b/3rdparty/openvx/include/openvx_hal.hpp @@ -886,6 +886,106 @@ inline int ovx_hal_morph(cvhalFilter2D *filter_context, uchar *a, size_t astep, return CV_HAL_ERROR_OK; } +inline int ovx_hal_cvtBGRtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int depth, int acn, int bcn, bool swapBlue) +{ + if (depth != CV_8U || swapBlue || acn == bcn || (acn != 3 && acn != 4) || (bcn != 3 && bcn != 4)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + try + { + vxContext * ctx = vxContext::getContext(); + vxImage ia(*ctx, acn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, a, astep, w, h); + vxImage ib(*ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, b, bstep, w, h); + vxErr::check(vxuColorConvert(ctx->ctx, ia.img, ib.img)); + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +inline int ovx_hal_cvtTwoPlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx) +{ + if (!swapBlue || (bcn != 3 && bcn != 4)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + try + { + vxContext * ctx = vxContext::getContext(); + vxImage ia(*ctx, uIdx ? VX_DF_IMAGE_NV21 : VX_DF_IMAGE_NV12, a, astep, w, h); + vxImage ib(*ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, b, bstep, w, h); + vxErr::check(vxuColorConvert(ctx->ctx, ia.img, ib.img)); + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +inline int ovx_hal_cvtThreePlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx) +{ + if (!swapBlue || (bcn != 3 && bcn != 4) || uIdx) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + try + { + vxContext * ctx = vxContext::getContext(); + vxImage ia(*ctx, VX_DF_IMAGE_IYUV, a, astep, w, h); + vxImage ib(*ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, b, bstep, w, h); + vxErr::check(vxuColorConvert(ctx->ctx, ia.img, ib.img)); + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +inline int ovx_hal_cvtBGRtoThreePlaneYUV(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int acn, bool swapBlue, int uIdx) +{ + if (!swapBlue || (acn != 3 && acn != 4) || uIdx) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + try + { + vxContext * ctx = vxContext::getContext(); + vxImage ia(*ctx, acn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, a, astep, w, h); + vxImage ib(*ctx, VX_DF_IMAGE_IYUV, b, bstep, w, h); + vxErr::check(vxuColorConvert(ctx->ctx, ia.img, ib.img)); + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +inline int ovx_hal_cvtOnePlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx, int ycn) +{ + if (!swapBlue || (bcn != 3 && bcn != 4) || uIdx) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + try + { + vxContext * ctx = vxContext::getContext(); + vxImage ia(*ctx, ycn ? VX_DF_IMAGE_UYVY : VX_DF_IMAGE_YUYV, a, astep, w, h); + vxImage ib(*ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, b, bstep, w, h); + vxErr::check(vxuColorConvert(ctx->ctx, ia.img, ib.img)); + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + #endif //================================================================================================== @@ -953,6 +1053,17 @@ inline int ovx_hal_morph(cvhalFilter2D *filter_context, uchar *a, size_t astep, #undef cv_hal_morphFree #define cv_hal_morphFree ovx_hal_morphFree +#undef cv_hal_cvtBGRtoBGR +#define cv_hal_cvtBGRtoBGR ovx_hal_cvtBGRtoBGR +#undef cv_hal_cvtTwoPlaneYUVtoBGR +#define cv_hal_cvtTwoPlaneYUVtoBGR ovx_hal_cvtTwoPlaneYUVtoBGR +#undef cv_hal_cvtThreePlaneYUVtoBGR +#define cv_hal_cvtThreePlaneYUVtoBGR ovx_hal_cvtThreePlaneYUVtoBGR +#undef cv_hal_cvtBGRtoThreePlaneYUV +#define cv_hal_cvtBGRtoThreePlaneYUV ovx_hal_cvtBGRtoThreePlaneYUV +#undef cv_hal_cvtOnePlaneYUVtoBGR +#define cv_hal_cvtOnePlaneYUVtoBGR ovx_hal_cvtOnePlaneYUVtoBGR + #endif #endif From 06e0fb25e92ec7abbdae75e3e502a785a11367e1 Mon Sep 17 00:00:00 2001 From: anirudt Date: Fri, 9 Sep 2016 13:23:43 +0530 Subject: [PATCH 144/178] docs: adds doxygen @note for python in docs related to contour moments --- modules/imgproc/include/opencv2/imgproc.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index ad71d8b8ee..15bed25b9b 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -3570,12 +3570,15 @@ results are returned in the structure cv::Moments. @param array Raster image (single-channel, 8-bit or floating-point 2D array) or an array ( \f$1 \times N\f$ or \f$N \times 1\f$ ) of 2D points (Point or Point2f ). -Note: For Python users, note that the numpy type for the input array should be either np.int32 or -np.float32, or in general of type CV_32S or CV_32F. @param binaryImage If it is true, all non-zero image pixels are treated as 1's. The parameter is used for images only. @returns moments. +@note Only applicable to contour moments calculations: For Python users, note that the numpy +type for the input array should be either np.int32 or np.float32, or in general of type CV_32S or CV_32F. +Thus, np.float will not work in this case, as it is the same as np.float64 and does not satisfy the +Point2f type check. + @sa contourArea, arcLength */ CV_EXPORTS_W Moments moments( InputArray array, bool binaryImage = false ); From f85e33f4af15638cdff6ffb50e7669370cdd7f5b Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 9 Sep 2016 15:38:00 +0300 Subject: [PATCH 145/178] videoio: refactor AVFoundation code integration --- CMakeLists.txt | 15 +++-- cmake/OpenCVFindLibsVideo.cmake | 30 ++++------ cmake/templates/cvconfig.h.in | 3 - modules/videoio/CMakeLists.txt | 13 +++-- modules/videoio/include/opencv2/videoio.hpp | 57 +++++++++---------- .../include/opencv2/videoio/videoio_c.h | 1 - modules/videoio/src/cap.cpp | 16 ------ modules/videoio/src/cap_avfoundation_mac.mm | 28 ++++----- modules/videoio/src/precomp.hpp | 4 -- 9 files changed, 69 insertions(+), 98 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9681a28810..96cb85bcdf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -169,8 +169,7 @@ OCV_OPTION(OPENCV_ENABLE_NONFREE "Enable non-free algorithms" OFF) # Optional 3rd party components # =================================================== OCV_OPTION(WITH_1394 "Include IEEE1394 support" ON IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) -OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O (iOS)" ON IF IOS) -OCV_OPTION(WITH_AVFOUNDATION_MAC "Use AVFoundation for Video I/O (Mac)" ON IF (NOT IOS AND APPLE) ) +OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O (iOS/Mac)" ON IF APPLE) OCV_OPTION(WITH_CARBON "Use Carbon for UI instead of Cocoa" OFF IF APPLE ) OCV_OPTION(WITH_CAROTENE "Use NVidia carotene acceleration library for ARM platform" ON IF (ARM OR AARCH64) AND NOT IOS AND NOT (CMAKE_VERSION VERSION_LESS "2.8.11")) OCV_OPTION(WITH_VTK "Include VTK library support (and build opencv_viz module eiher)" ON IF (NOT ANDROID AND NOT IOS AND NOT WINRT AND NOT CMAKE_CROSSCOMPILING) ) @@ -199,7 +198,8 @@ OCV_OPTION(WITH_PVAPI "Include Prosilica GigE support" OFF OCV_OPTION(WITH_GIGEAPI "Include Smartek GigE support" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_QT "Build with Qt Backend support" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_WIN32UI "Build with Win32 UI Backend support" ON IF WIN32 AND NOT WINRT) -OCV_OPTION(WITH_QUICKTIME "Use QuickTime for Video I/O insted of QTKit" OFF IF APPLE ) +OCV_OPTION(WITH_QUICKTIME "Use QuickTime for Video I/O" OFF IF APPLE ) +OCV_OPTION(WITH_QTKIT "Use QTKit Video I/O backend" OFF IF APPLE ) OCV_OPTION(WITH_TBB "Include Intel TBB support" OFF IF (NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_OPENMP "Include OpenMP support" OFF) OCV_OPTION(WITH_CSTRIPES "Include C= support" OFF IF (WIN32 AND NOT WINRT) ) @@ -1110,10 +1110,13 @@ if(DEFINED WITH_GIGEAPI) endif(DEFINED WITH_GIGEAPI) if(DEFINED APPLE) + status(" AVFoundation:" HAVE_AVFOUNDATION THEN YES ELSE NO) + if(WITH_QUICKTIME OR HAVE_QUICKTIME) status(" QuickTime:" HAVE_QUICKTIME THEN YES ELSE NO) - status(" QTKit:" HAVE_QTKIT THEN YES ELSE NO) - status(" AVFoundation:" WITH_AVFOUNDATION THEN YES ELSE NO) - status(" AVFoundationMac:" WITH_AVFOUNDATION_MAC THEN YES ELSE NO) + endif() + if(WITH_QTKIT OR HAVE_QTKIT) + status(" QTKit:" HAVE_QTKIT THEN "YES (deprecated)" ELSE NO) + endif() endif(DEFINED APPLE) if(DEFINED WITH_UNICAP) diff --git a/cmake/OpenCVFindLibsVideo.cmake b/cmake/OpenCVFindLibsVideo.cmake index c23ee06d87..0c4072cb3b 100644 --- a/cmake/OpenCVFindLibsVideo.cmake +++ b/cmake/OpenCVFindLibsVideo.cmake @@ -302,26 +302,18 @@ if(WIN32) endif() endif(WIN32) -# --- Apple AV Foundation (iOS) --- -if(WITH_AVFOUNDATION) - set(HAVE_AVFOUNDATION YES) -endif() - -# --- Apple AV Foundation (Mac) --- -if(WITH_AVFOUNDATION_MAC) - set(HAVE_AVFOUNDATION_MAC YES) -endif() - -# --- QuickTime, Apple AV Foundation (Mac) --- -if (NOT IOS) - if(WITH_QUICKTIME) - set(HAVE_QUICKTIME YES) - elseif(WITH_QTKIT) - set(HAVE_QTKIT YES) - elseif(APPLE AND CMAKE_COMPILER_IS_CLANGCXX) - set(HAVE_AVFOUNDATION_MAC YES) +if(APPLE) + if(WITH_AVFOUNDATION) + set(HAVE_AVFOUNDATION YES) endif() -endif() + if(NOT IOS) + if(WITH_QUICKTIME) + set(HAVE_QUICKTIME YES) + elseif(WITH_QTKIT) + set(HAVE_QTKIT YES) + endif() + endif() +endif(APPLE) # --- Intel Perceptual Computing SDK --- if(WITH_INTELPERC) diff --git a/cmake/templates/cvconfig.h.in b/cmake/templates/cvconfig.h.in index 50b4185e2c..56d415b400 100644 --- a/cmake/templates/cvconfig.h.in +++ b/cmake/templates/cvconfig.h.in @@ -16,9 +16,6 @@ /* AVFoundation video libraries */ #cmakedefine HAVE_AVFOUNDATION -/* AVFoundation (Mac) video libraries */ -#cmakedefine HAVE_AVFOUNDATION_MAC - /* V4L capturing support */ #cmakedefine HAVE_CAMV4L diff --git a/modules/videoio/CMakeLists.txt b/modules/videoio/CMakeLists.txt index d75c2d80bb..413b3cdea0 100644 --- a/modules/videoio/CMakeLists.txt +++ b/modules/videoio/CMakeLists.txt @@ -168,12 +168,13 @@ if(HAVE_GIGE_API) endif(HAVE_GIGE_API) if(HAVE_AVFOUNDATION) - list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_avfoundation.mm) - list(APPEND VIDEOIO_LIBRARIES "-framework AVFoundation" "-framework QuartzCore") -endif() -if(HAVE_AVFOUNDATION_MAC) - list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_avfoundation_mac.mm) - list(APPEND VIDEOIO_LIBRARIES "-framework Cocoa" "-framework Accelerate" "-framework AVFoundation" "-framework CoreGraphics" "-framework CoreImage" "-framework CoreMedia" "-framework CoreVideo" "-framework QuartzCore") + if(IOS) + list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_avfoundation.mm) + list(APPEND VIDEOIO_LIBRARIES "-framework AVFoundation" "-framework QuartzCore") + else() + list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_avfoundation_mac.mm) + list(APPEND VIDEOIO_LIBRARIES "-framework Cocoa" "-framework Accelerate" "-framework AVFoundation" "-framework CoreGraphics" "-framework CoreImage" "-framework CoreMedia" "-framework CoreVideo" "-framework QuartzCore") + endif() endif() if(HAVE_QUICKTIME) diff --git a/modules/videoio/include/opencv2/videoio.hpp b/modules/videoio/include/opencv2/videoio.hpp index c41d4246d2..b769163cf3 100644 --- a/modules/videoio/include/opencv2/videoio.hpp +++ b/modules/videoio/include/opencv2/videoio.hpp @@ -82,35 +82,34 @@ To enable/disable APIs, you have to: 2. rebuild OpenCV itself */ enum VideoCaptureAPIs { - CAP_ANY = 0, //!< Auto detect - CAP_VFW = 200, //!< Video For Windows (platform native) - CAP_V4L = 200, //!< V4L/V4L2 capturing support via libv4l - CAP_V4L2 = CAP_V4L, //!< Same as CAP_V4L - CAP_FIREWIRE = 300, //!< IEEE 1394 drivers - CAP_FIREWARE = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE - CAP_IEEE1394 = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE - CAP_DC1394 = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE - CAP_CMU1394 = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE - CAP_QT = 500, //!< QuickTime - CAP_UNICAP = 600, //!< Unicap drivers - CAP_DSHOW = 700, //!< DirectShow (via videoInput) - CAP_PVAPI = 800, //!< PvAPI, Prosilica GigE SDK - CAP_OPENNI = 900, //!< OpenNI (for Kinect) - CAP_OPENNI_ASUS = 910, //!< OpenNI (for Asus Xtion) - CAP_ANDROID = 1000, //!< Android - not used - CAP_XIAPI = 1100, //!< XIMEA Camera API - CAP_AVFOUNDATION = 1200, //!< AVFoundation framework for iOS - CAP_AVFOUNDATION_MAC = 1210, //!< AVFoundation framework for macOS - CAP_GIGANETIX = 1300, //!< Smartek Giganetix GigEVisionSDK - CAP_MSMF = 1400, //!< Microsoft Media Foundation (via videoInput) - CAP_WINRT = 1410, //!< Microsoft Windows Runtime using Media Foundation - CAP_INTELPERC = 1500, //!< Intel Perceptual Computing SDK - CAP_OPENNI2 = 1600, //!< OpenNI2 (for Kinect) - CAP_OPENNI2_ASUS = 1610, //!< OpenNI2 (for Asus Xtion and Occipital Structure sensors) - CAP_GPHOTO2 = 1700, //!< gPhoto2 connection - CAP_GSTREAMER = 1800, //!< GStreamer - CAP_FFMPEG = 1900, //!< FFMPEG - CAP_IMAGES = 2000 //!< OpenCV Image Sequence (e.g. img_%02d.jpg) + CAP_ANY = 0, //!< Auto detect + CAP_VFW = 200, //!< Video For Windows (platform native) + CAP_V4L = 200, //!< V4L/V4L2 capturing support via libv4l + CAP_V4L2 = CAP_V4L, //!< Same as CAP_V4L + CAP_FIREWIRE = 300, //!< IEEE 1394 drivers + CAP_FIREWARE = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE + CAP_IEEE1394 = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE + CAP_DC1394 = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE + CAP_CMU1394 = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE + CAP_QT = 500, //!< QuickTime + CAP_UNICAP = 600, //!< Unicap drivers + CAP_DSHOW = 700, //!< DirectShow (via videoInput) + CAP_PVAPI = 800, //!< PvAPI, Prosilica GigE SDK + CAP_OPENNI = 900, //!< OpenNI (for Kinect) + CAP_OPENNI_ASUS = 910, //!< OpenNI (for Asus Xtion) + CAP_ANDROID = 1000, //!< Android - not used + CAP_XIAPI = 1100, //!< XIMEA Camera API + CAP_AVFOUNDATION = 1200, //!< AVFoundation framework for iOS (OS X Lion will have the same API) + CAP_GIGANETIX = 1300, //!< Smartek Giganetix GigEVisionSDK + CAP_MSMF = 1400, //!< Microsoft Media Foundation (via videoInput) + CAP_WINRT = 1410, //!< Microsoft Windows Runtime using Media Foundation + CAP_INTELPERC = 1500, //!< Intel Perceptual Computing SDK + CAP_OPENNI2 = 1600, //!< OpenNI2 (for Kinect) + CAP_OPENNI2_ASUS = 1610, //!< OpenNI2 (for Asus Xtion and Occipital Structure sensors) + CAP_GPHOTO2 = 1700, //!< gPhoto2 connection + CAP_GSTREAMER = 1800, //!< GStreamer + CAP_FFMPEG = 1900, //!< FFMPEG + CAP_IMAGES = 2000 //!< OpenCV Image Sequence (e.g. img_%02d.jpg) }; //! generic properties (based on DC1394 properties) diff --git a/modules/videoio/include/opencv2/videoio/videoio_c.h b/modules/videoio/include/opencv2/videoio/videoio_c.h index 1351c4e73a..e502c7be83 100644 --- a/modules/videoio/include/opencv2/videoio/videoio_c.h +++ b/modules/videoio/include/opencv2/videoio/videoio_c.h @@ -108,7 +108,6 @@ enum CV_CAP_XIAPI =1100, // XIMEA Camera API CV_CAP_AVFOUNDATION = 1200, // AVFoundation framework for iOS (OS X Lion will have the same API) - CV_CAP_AVFOUNDATION_MAC = 1210, // AVFoundation framework for Mac CV_CAP_GIGANETIX = 1300, // Smartek Giganetix GigEVisionSDK diff --git a/modules/videoio/src/cap.cpp b/modules/videoio/src/cap.cpp index 8e12b62da0..55c20bef52 100644 --- a/modules/videoio/src/cap.cpp +++ b/modules/videoio/src/cap.cpp @@ -266,12 +266,6 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index) if (pref) break; #endif -#ifdef HAVE_AVFOUNDATION_MAC - case CV_CAP_AVFOUNDATION_MAC: - TRY_OPEN(capture, cvCreateCameraCapture_AVFoundation_Mac(index)) - if (pref) break; -#endif - #ifdef HAVE_GIGE_API case CV_CAP_GIGANETIX: TRY_OPEN(capture, cvCreateCameraCapture_Giganetix(index)) @@ -340,12 +334,6 @@ CV_IMPL CvCapture * cvCreateFileCaptureWithPreference (const char * filename, in if (apiPreference) break; #endif -#ifdef HAVE_AVFOUNDATION_MAC - case CV_CAP_AVFOUNDATION_MAC: - TRY_OPEN(result, cvCreateFileCapture_AVFoundation_Mac(filename)) - if (apiPreference) break; -#endif - #ifdef HAVE_OPENNI case CV_CAP_OPENNI: TRY_OPEN(result, cvCreateFileCapture_OpenNI (filename)) @@ -403,10 +391,6 @@ CV_IMPL CvVideoWriter* cvCreateVideoWriter( const char* filename, int fourcc, TRY_OPEN(result, cvCreateVideoWriter_AVFoundation(filename, fourcc, fps, frameSize, is_color)) #endif -#ifdef HAVE_AVFOUNDATION_MAC - TRY_OPEN(result, cvCreateVideoWriter_AVFoundation_Mac(filename, fourcc, fps, frameSize, is_color)) -#endif - #if defined(HAVE_QUICKTIME) || defined(HAVE_QTKIT) TRY_OPEN(result, cvCreateVideoWriter_QT(filename, fourcc, fps, frameSize, is_color)) #endif diff --git a/modules/videoio/src/cap_avfoundation_mac.mm b/modules/videoio/src/cap_avfoundation_mac.mm index 4228bc3735..8c30506400 100644 --- a/modules/videoio/src/cap_avfoundation_mac.mm +++ b/modules/videoio/src/cap_avfoundation_mac.mm @@ -171,18 +171,18 @@ private: /***************************************************************************** * - * CvVideoWriter_AVFoundation_Mac Declaration. + * CvVideoWriter_AVFoundation Declaration. * - * CvVideoWriter_AVFoundation_Mac is the instantiation of a video output class. + * CvVideoWriter_AVFoundation is the instantiation of a video output class. * *****************************************************************************/ -class CvVideoWriter_AVFoundation_Mac : public CvVideoWriter { +class CvVideoWriter_AVFoundation : public CvVideoWriter { public: - CvVideoWriter_AVFoundation_Mac(const char* filename, int fourcc, + CvVideoWriter_AVFoundation(const char* filename, int fourcc, double fps, CvSize frame_size, int is_color=1); - ~CvVideoWriter_AVFoundation_Mac(); + ~CvVideoWriter_AVFoundation(); bool writeFrame(const IplImage* image); private: IplImage* argbimage; @@ -203,7 +203,7 @@ class CvVideoWriter_AVFoundation_Mac : public CvVideoWriter { /****************** Implementation of interface functions ********************/ -CvCapture* cvCreateFileCapture_AVFoundation_Mac(const char* filename) { +CvCapture* cvCreateFileCapture_AVFoundation(const char* filename) { CvCaptureFile *retval = new CvCaptureFile(filename); if(retval->didStart()) @@ -212,17 +212,17 @@ CvCapture* cvCreateFileCapture_AVFoundation_Mac(const char* filename) { return NULL; } -CvCapture* cvCreateCameraCapture_AVFoundation_Mac(int index ) { +CvCapture* cvCreateCameraCapture_AVFoundation(int index ) { CvCapture* retval = new CvCaptureCAM(index); if (!((CvCaptureCAM *)retval)->didStart()) cvReleaseCapture(&retval); return retval; } -CvVideoWriter* cvCreateVideoWriter_AVFoundation_Mac(const char* filename, int fourcc, +CvVideoWriter* cvCreateVideoWriter_AVFoundation(const char* filename, int fourcc, double fps, CvSize frame_size, int is_color) { - return new CvVideoWriter_AVFoundation_Mac(filename, fourcc, fps, frame_size,is_color); + return new CvVideoWriter_AVFoundation(filename, fourcc, fps, frame_size,is_color); } /********************** Implementation of Classes ****************************/ @@ -1087,14 +1087,14 @@ bool CvCaptureFile::setProperty(int property_id, double value) { /***************************************************************************** * - * CvVideoWriter_AVFoundation_Mac Implementation. + * CvVideoWriter_AVFoundation Implementation. * - * CvVideoWriter_AVFoundation_Mac is the instantiation of a video output class. + * CvVideoWriter_AVFoundation is the instantiation of a video output class. * *****************************************************************************/ -CvVideoWriter_AVFoundation_Mac::CvVideoWriter_AVFoundation_Mac(const char* filename, int fourcc, +CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const char* filename, int fourcc, double fps, CvSize frame_size, int is_color) { @@ -1222,7 +1222,7 @@ CvVideoWriter_AVFoundation_Mac::CvVideoWriter_AVFoundation_Mac(const char* filen } -CvVideoWriter_AVFoundation_Mac::~CvVideoWriter_AVFoundation_Mac() { +CvVideoWriter_AVFoundation::~CvVideoWriter_AVFoundation() { NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; [mMovieWriterInput markAsFinished]; @@ -1243,7 +1243,7 @@ static void releaseCallback( void *releaseRefCon, const void * ) { CFRelease((CFDataRef)releaseRefCon); } -bool CvVideoWriter_AVFoundation_Mac::writeFrame(const IplImage* iplimage) { +bool CvVideoWriter_AVFoundation::writeFrame(const IplImage* iplimage) { NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; // writer status check diff --git a/modules/videoio/src/precomp.hpp b/modules/videoio/src/precomp.hpp index 50853d0bb9..45ce1a1f60 100644 --- a/modules/videoio/src/precomp.hpp +++ b/modules/videoio/src/precomp.hpp @@ -127,7 +127,6 @@ CvCapture* cvCreateFileCapture_OpenNI( const char* filename ); CvCapture* cvCreateCameraCapture_Android( int index ); CvCapture* cvCreateCameraCapture_XIMEA( int index ); CvCapture* cvCreateCameraCapture_AVFoundation(int index); -CvCapture* cvCreateCameraCapture_AVFoundation_Mac(int index); CvCapture* cvCreateFileCapture_Images(const char* filename); CvVideoWriter* cvCreateVideoWriter_Images(const char* filename); @@ -156,9 +155,6 @@ CvVideoWriter* cvCreateVideoWriter_QT ( const char* filename, int fourcc, CvCapture* cvCreateFileCapture_AVFoundation (const char * filename); CvVideoWriter* cvCreateVideoWriter_AVFoundation( const char* filename, int fourcc, double fps, CvSize frameSize, int is_color ); -CvCapture* cvCreateFileCapture_AVFoundation_Mac(const char * filename); -CvVideoWriter* cvCreateVideoWriter_AVFoundation_Mac( const char* filename, int fourcc, - double fps, CvSize frameSize, int is_color ); CvCapture * cvCreateCameraCapture_Unicap (const int index); From be65701908370a55d73e2f86c7aacd8b4abc00f9 Mon Sep 17 00:00:00 2001 From: "PkLab.net" Date: Wed, 24 Aug 2016 19:57:17 +0200 Subject: [PATCH 146/178] Large update of videoio doc and samples following mshabunin comments --- modules/core/doc/intro.markdown | 2 +- modules/videoio/doc/pics/videoio_overview.svg | 877 ++++++++++++++++++ modules/videoio/doc/videoio_overview.markdown | 94 ++ modules/videoio/include/opencv2/videoio.hpp | 406 ++++---- .../include/opencv2/videoio/videoio_c.h | 94 +- samples/cpp/videocapture_basic.cpp | 52 ++ ...ter_video.cpp => videocapture_starter.cpp} | 9 +- samples/cpp/videowriter_basic.cpp | 65 ++ 8 files changed, 1396 insertions(+), 203 deletions(-) create mode 100644 modules/videoio/doc/pics/videoio_overview.svg create mode 100644 modules/videoio/doc/videoio_overview.markdown create mode 100644 samples/cpp/videocapture_basic.cpp rename samples/cpp/{starter_video.cpp => videocapture_starter.cpp} (95%) create mode 100644 samples/cpp/videowriter_basic.cpp diff --git a/modules/core/doc/intro.markdown b/modules/core/doc/intro.markdown index 964fb06331..41d80781b6 100644 --- a/modules/core/doc/intro.markdown +++ b/modules/core/doc/intro.markdown @@ -22,7 +22,7 @@ libraries. The following modules are available: - **objdetect** - detection of objects and instances of the predefined classes (for example, faces, eyes, mugs, people, cars, and so on). - **highgui** - an easy-to-use interface to simple UI capabilities. -- **videoio** - an easy-to-use interface to video capturing and video codecs. +- @ref videoio - an easy-to-use interface to video capturing and video codecs. - **gpu** - GPU-accelerated algorithms from different OpenCV modules. - ... some other helper modules, such as FLANN and Google test wrappers, Python bindings, and others. diff --git a/modules/videoio/doc/pics/videoio_overview.svg b/modules/videoio/doc/pics/videoio_overview.svg new file mode 100644 index 0000000000..f6b376e49c --- /dev/null +++ b/modules/videoio/doc/pics/videoio_overview.svg @@ -0,0 +1,877 @@ + + + + + + + + OpenCV video I/O Structure + + + + + image/svg+xml + + OpenCV video I/O Structure + + + + PkLab.net + + + English + + + OpenCV + Video I/O + + + + + + + + + + + + + + + + + + MEDIA DEVICES + + SYSTEM + + + + + + + USER APPLICATION + + OpenCV Video I/O + + OpenCV Video I/O API Backends + + DShow + + MSMF + + FFMPEG + + V4L + + VFW + + AVF/IOS + + etc... + + OPENNI + + Manufacturer Driver + + C / C++ / JAVA API + + cv::Mat frombuffer + + ManufacturerLibrary + + BackendsLibraries + + O.S.Libraries + + + set / getproperties + grab / writeframe + + Camera + + Video File + + Network Stream + + create / opendevice + + CODECS(fourcc) + + + + VideoCapture + + VideoWriter + Camera + File or URL stream+ fourcc codec + + diff --git a/modules/videoio/doc/videoio_overview.markdown b/modules/videoio/doc/videoio_overview.markdown new file mode 100644 index 0000000000..b96d06089f --- /dev/null +++ b/modules/videoio/doc/videoio_overview.markdown @@ -0,0 +1,94 @@ +Video I/O with OpenCV Overview {#videoio_overview} +=================================== + +### See also: + - @ref videoio "Video I/O Code Reference" + - Tutorials: @ref tutorial_table_of_content_videoio + +General Information +=================== + +The OpenCV @ref videoio module is a set of classes and functions to read and write video or images sequence. + +Basically, the module provides the cv::VideoCapture and cv::VideoWriter classes as 2-layer interface to many video +I/O APIs used as backend. + +![Video I/O with OpenCV](pics/videoio_overview.svg) + +Some backends such as (DSHOW) Direct Show, Video For Windows (VFW), Microsoft Media Foundation (MSMF), +Video 4 Linux (V4L), etc... are interfaces to the video I/O library provided by the operating system. + +Some others backends like OpenNI2 for Kinect, Intel Perceptual Computing SDK, GStreamer, +XIMEA Camera API, etc... are interfaces to proprietary drivers or to external library. + +See the list of supported backends here: cv::VideoCaptureAPIs + +@warning Some backends are experimental use them at your own risk +@note Each backend supports devices properties (cv::VideoCaptureProperties) in a different way or might not support any property at all. + + +Select the backend at runtime +----------------------------- + +OpenCV automatically selects and uses first available backend (`apiPreference=cv::CAP_ANY`). + +As advanced usage you can select the backend to use at runtime. Currently this option is +available only with %VideoCapture. + +For example to grab from default camera using Direct Show as backend + +```cpp +//declare a capture object +cv::VideoCapture cap(0 + cv::CAP_DSHOW); + +//or specify the apiPreference with open +cap.open(0 + cv::CAP_DSHOW); +``` + +If you want to grab from a file using the Direct Show as backend: + +```cpp +//declare a capture object +cv::VideoCapture cap(filename, cv::CAP_DSHOW); + +//or specify the apiPreference with open +cap.open(filename, cv::CAP_DSHOW); +``` + +@sa cv::VideoCapture::open() , cv::VideoCapture::VideoCapture() + +#### Enable backends + +Backends are available only if they have been built with your OpenCV binaries. + +Check in `opencv2/cvconfig.h` to know which APIs are currently available +(e.g. `HAVE_MSMF, HAVE_VFW, HAVE_LIBV4L`, etc...). + +To enable/disable APIs, you have to: + 1. re-configure OpenCV using appropriates CMake switches + (e.g. `-DWITH_MSMF=ON -DWITH_VFW=ON ... `) or checking related switch in cmake-gui + 2. rebuild OpenCV itself + +#### Use 3rd party drivers or cameras + +Many industrial cameras or some video I/O devices don't provide standard driver interfaces +for the operating system. Thus you can't use VideoCapture or VideoWriter with these devices. + +To get access to their devices, manufactures provide their own C++ API and library that you have to +include and link with your OpenCV application. + +Is common case that this libraries read/write images from/to a memory buffer. If it so, it is +possible to make a `Mat` header for memory buffer (user-allocated data) and process it +in-place using OpenCV functions. See cv::Mat::Mat() for more details. + +The FFmpeg library +------------------ + +OpenCV can use the FFmpeg library (http://ffmpeg.org/) as backend to record, convert and stream audio and video. +FFMpeg is a complete, cross-reference solution. If you enable FFmpeg while configuring OpenCV than +CMake will download and install the binaries in `OPENCV_SOURCE_CODE/3rdparty/ffmpeg/`. To use +FFMpeg at runtime, you must deploy the FFMepg binaries with your application. + +@note FFmpeg is licensed under the GNU Lesser General Public License (LGPL) version 2.1 or later. +See `OPENCV_SOURCE_CODE/3rdparty/ffmpeg/readme.txt` and http://ffmpeg.org/legal.html for details and +licensing information diff --git a/modules/videoio/include/opencv2/videoio.hpp b/modules/videoio/include/opencv2/videoio.hpp index b769163cf3..122f8495d0 100644 --- a/modules/videoio/include/opencv2/videoio.hpp +++ b/modules/videoio/include/opencv2/videoio.hpp @@ -46,13 +46,19 @@ #include "opencv2/core.hpp" /** - @defgroup videoio Media I/O + @defgroup videoio Video I/O + + @brief Read and write video or images sequence with OpenCV + + ### See also: + - @ref videoio_overview + - Tutorials: @ref tutorial_table_of_content_videoio @{ @defgroup videoio_flags_base Flags for video I/O @defgroup videoio_flags_others Additional flags for video I/O API backends - @defgroup videoio_c C API - @defgroup videoio_ios iOS glue - @defgroup videoio_winrt WinRT glue + @defgroup videoio_c C API for video I/O + @defgroup videoio_ios iOS glue for video I/O + @defgroup videoio_winrt WinRT glue for video I/O @} */ @@ -69,20 +75,18 @@ namespace cv //! @addtogroup videoio_flags_base //! @{ -/** @brief Capture API backends. + + +/** @brief %VideoCapture API backends identifier. Select preferred API for a capture object. -To be used in the constructor VideoCapture::VideoCapture or VideoCapture::open +To be used in the VideoCapture::VideoCapture() constructor or VideoCapture::open() -@note Backends are available only if they have been built with your OpenCV binaries.
-Check in cvconfig.h to know which APIs are currently available (e.g. HAVE_MSMF, HAVE_VFW, HAVE_LIBV4L). -To enable/disable APIs, you have to: - 1. re-configure OpenCV using the appropriates CMake switches - (e.g. -DWITH_MSMF=ON -DWITH_VFW=ON ... ) or checking related switch in cmake-gui - 2. rebuild OpenCV itself +@note Backends are available only if they have been built with your OpenCV binaries. +See @ref videoio_overview for more information. */ enum VideoCaptureAPIs { - CAP_ANY = 0, //!< Auto detect + CAP_ANY = 0, //!< Auto detect == 0 CAP_VFW = 200, //!< Video For Windows (platform native) CAP_V4L = 200, //!< V4L/V4L2 capturing support via libv4l CAP_V4L2 = CAP_V4L, //!< Same as CAP_V4L @@ -108,11 +112,13 @@ enum VideoCaptureAPIs { CAP_OPENNI2_ASUS = 1610, //!< OpenNI2 (for Asus Xtion and Occipital Structure sensors) CAP_GPHOTO2 = 1700, //!< gPhoto2 connection CAP_GSTREAMER = 1800, //!< GStreamer - CAP_FFMPEG = 1900, //!< FFMPEG + CAP_FFMPEG = 1900, //!< Open and record video file or stream using the FFMPEG library CAP_IMAGES = 2000 //!< OpenCV Image Sequence (e.g. img_%02d.jpg) }; -//! generic properties (based on DC1394 properties) +/** @brief %VideoCapture generic properties identifier. + @sa videoio_flags_others, VideoCapture::get(), VideoCapture::set() +*/ enum VideoCaptureProperties { CAP_PROP_POS_MSEC =0, //!< Current position of the video file in milliseconds. CAP_PROP_POS_FRAMES =1, //!< 0-based index of the frame to be decoded/captured next. @@ -150,13 +156,15 @@ enum VideoCaptureProperties { CAP_PROP_TILT =34, CAP_PROP_ROLL =35, CAP_PROP_IRIS =36, - CAP_PROP_SETTINGS =37, + CAP_PROP_SETTINGS =37, //! Pop up video/camera filter dialog (note: only supported by DSHOW backend currently. Property value is ignored) CAP_PROP_BUFFERSIZE =38, CAP_PROP_AUTOFOCUS =39 }; -//! @brief Generic camera output modes. -//! @note Currently, these are supported through the libv4l interface only. + +/** @brief Generic camera output modes identifier. +@note Currently, these are supported through the libv4l backend only. +*/ enum VideoCaptureModes { CAP_MODE_BGR = 0, //!< BGR24 (default) CAP_MODE_RGB = 1, //!< RGB24 @@ -164,7 +172,8 @@ enum VideoCaptureModes { CAP_MODE_YUYV = 3 //!< YUYV }; -/** @brief Generic properties identifier for VideoWriter +/** @brief %VideoWriter generic properties identifier. + @sa VideoWriter::get(), VideoWriter::set() */ enum VideoWriterProperties { VIDEOWRITER_PROP_QUALITY = 1, //!< Current quality (0..100%) of the encoded videostream. Can be adjusted dynamically in some codecs. @@ -177,9 +186,12 @@ enum VideoWriterProperties { //! @addtogroup videoio_flags_others //! @{ -/** @brief DC1394 only +/** @name IEEE 1394 drivers + @{ +*/ -modes of the controlling registers (can be: auto, manual, auto single push, absolute Latter allowed with any other mode) +/** @brief Modes of the IEEE 1394 controlling registers +(can be: auto, manual, auto single push, absolute Latter allowed with any other mode) every feature can have only one mode turned on at a time */ enum { CAP_PROP_DC1394_OFF = -4, //!< turn the feature off (not controlled manually nor automatically). @@ -189,6 +201,11 @@ enum { CAP_PROP_DC1394_OFF = -4, //!< turn the feature off (not c CAP_PROP_DC1394_MAX = 31 }; +//! @} IEEE 1394 drivers + +/** @name OpenNI (for Kinect) + @{ +*/ //! OpenNI map generators enum { CAP_OPENNI_DEPTH_GENERATOR = 1 << 31, @@ -197,7 +214,7 @@ enum { CAP_OPENNI_DEPTH_GENERATOR = 1 << 31, CAP_OPENNI_GENERATORS_MASK = CAP_OPENNI_DEPTH_GENERATOR + CAP_OPENNI_IMAGE_GENERATOR + CAP_OPENNI_IR_GENERATOR }; -//! Properties of cameras available through OpenNI interfaces +//! Properties of cameras available through OpenNI backend enum { CAP_PROP_OPENNI_OUTPUT_MODE = 100, CAP_PROP_OPENNI_FRAME_MAX_DEPTH = 101, //!< In mm CAP_PROP_OPENNI_BASELINE = 102, //!< In mm @@ -247,11 +264,20 @@ enum { CAP_OPENNI_VGA_30HZ = 0, CAP_OPENNI_QVGA_60HZ = 4 }; +//! @} OpenNI + +/** @name GStreamer + @{ +*/ -//! GStreamer enum { CAP_PROP_GSTREAMER_QUEUE_LENGTH = 200 //!< Default is 1 }; +//! @} GStreamer + +/** @name PvAPI, Prosilica GigE SDK + @{ +*/ //! PVAPI enum { CAP_PROP_PVAPI_MULTICASTIP = 300, //!< IP for enable multicast master mode. 0 for disable multicast. @@ -289,7 +315,13 @@ enum { CAP_PVAPI_PIXELFORMAT_MONO8 = 1, //!< Mono8 CAP_PVAPI_PIXELFORMAT_BGRA32 = 8, //!< Bgra32 }; -//! Properties of cameras available through XIMEA SDK interface +//! @} PvAPI + +/** @name XIMEA Camera API + @{ +*/ + +//! Properties of cameras available through XIMEA SDK backend enum { CAP_PROP_XI_DOWNSAMPLING = 400, //!< Change image resolution by binning or skipping. CAP_PROP_XI_DATA_FORMAT = 401, //!< Output data format. CAP_PROP_XI_OFFSET_X = 402, //!< Horizontal offset from the origin to the area of interest (in pixels). @@ -392,8 +424,8 @@ enum { CAP_PROP_XI_DOWNSAMPLING = 400, //!< Chan CAP_PROP_XI_LENS_FOCAL_LENGTH = 516, //!< Lens focal distance in mm. CAP_PROP_XI_LENS_FEATURE_SELECTOR = 517, //!< Selects the current feature which is accessible by XI_PRM_LENS_FEATURE. CAP_PROP_XI_LENS_FEATURE = 518, //!< Allows access to lens feature value currently selected by XI_PRM_LENS_FEATURE_SELECTOR. - CAP_PROP_XI_DEVICE_MODEL_ID = 521, //!< Return device model id. - CAP_PROP_XI_DEVICE_SN = 522, //!< Return device serial number. + CAP_PROP_XI_DEVICE_MODEL_ID = 521, //!< Returns device model id. + CAP_PROP_XI_DEVICE_SN = 522, //!< Returns device serial number. CAP_PROP_XI_IMAGE_DATA_FORMAT_RGB32_ALPHA = 529, //!< The alpha channel of RGB32 output image format. CAP_PROP_XI_IMAGE_PAYLOAD_SIZE = 530, //!< Buffer size in bytes sufficient for output image returned by xiGetImage. CAP_PROP_XI_TRANSPORT_PIXEL_FORMAT = 531, //!< Current format of pixels on transport layer. @@ -404,7 +436,7 @@ enum { CAP_PROP_XI_DOWNSAMPLING = 400, //!< Chan CAP_PROP_XI_COUNTER_SELECTOR = 536, //!< Select counter. CAP_PROP_XI_COUNTER_VALUE = 537, //!< Counter status. CAP_PROP_XI_ACQ_TIMING_MODE = 538, //!< Type of sensor frames timing. - CAP_PROP_XI_AVAILABLE_BANDWIDTH = 539, //!< Calculate and return available interface bandwidth(int Megabits). + CAP_PROP_XI_AVAILABLE_BANDWIDTH = 539, //!< Calculate and returns available interface bandwidth(int Megabits). CAP_PROP_XI_BUFFER_POLICY = 540, //!< Data move policy. CAP_PROP_XI_LUT_EN = 541, //!< Activates LUT. CAP_PROP_XI_LUT_INDEX = 542, //!< Control the index (offset) of the coefficient to access in the LUT. @@ -442,8 +474,14 @@ enum { CAP_PROP_XI_DOWNSAMPLING = 400, //!< Chan CAP_PROP_XI_SENSOR_FEATURE_VALUE = 586, //!< Allows access to sensor feature value currently selected by XI_PRM_SENSOR_FEATURE_SELECTOR. }; +//! @} XIMEA -//! Properties of cameras available through AVFOUNDATION interface +/** @name AVFoundation framework for iOS + OS X Lion will have the same API + @{ +*/ + +//! Properties of cameras available through AVFOUNDATION backend enum { CAP_PROP_IOS_DEVICE_FOCUS = 9001, CAP_PROP_IOS_DEVICE_EXPOSURE = 9002, CAP_PROP_IOS_DEVICE_FLASH = 9003, @@ -451,8 +489,11 @@ enum { CAP_PROP_IOS_DEVICE_FOCUS = 9001, CAP_PROP_IOS_DEVICE_TORCH = 9005 }; +/** @name Smartek Giganetix GigEVisionSDK + @{ +*/ -//! Properties of cameras available through Smartek Giganetix Ethernet Vision interface +//! Properties of cameras available through Smartek Giganetix Ethernet Vision backend /* --- Vladimir Litvinenko (litvinenko.vladimir@gmail.com) --- */ enum { CAP_PROP_GIGA_FRAME_OFFSET_X = 10001, CAP_PROP_GIGA_FRAME_OFFSET_Y = 10002, @@ -462,6 +503,11 @@ enum { CAP_PROP_GIGA_FRAME_OFFSET_X = 10001, CAP_PROP_GIGA_FRAME_SENS_HEIGH = 10006 }; +//! @} Smartek + +/** @name Intel Perceptual Computing SDK + @{ +*/ enum { CAP_PROP_INTELPERC_PROFILE_COUNT = 11001, CAP_PROP_INTELPERC_PROFILE_IDX = 11002, CAP_PROP_INTELPERC_DEPTH_LOW_CONFIDENCE_VALUE = 11003, @@ -471,7 +517,7 @@ enum { CAP_PROP_INTELPERC_PROFILE_COUNT = 11001, CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_VERT = 11007 }; -//! Intel PerC streams +//! Intel Perceptual Streams enum { CAP_INTELPERC_DEPTH_GENERATOR = 1 << 29, CAP_INTELPERC_IMAGE_GENERATOR = 1 << 28, CAP_INTELPERC_GENERATORS_MASK = CAP_INTELPERC_DEPTH_GENERATOR + CAP_INTELPERC_IMAGE_GENERATOR @@ -483,9 +529,15 @@ enum { CAP_INTELPERC_DEPTH_MAP = 0, //!< Each pixel is a 16-bit int CAP_INTELPERC_IMAGE = 3 }; +//! @} Intel Perceptual + +/** @name gPhoto2 connection + @{ +*/ + /** @brief gPhoto2 properties -if propertyId is less than 0 then work on widget with that __additive inversed__ camera setting ID +If `propertyId` is less than 0 then work on widget with that __additive inversed__ camera setting ID Get IDs by using CAP_PROP_GPHOTO2_WIDGET_ENUMERATE. @see CvCaptureCAM_GPHOTO2 for more info */ @@ -501,114 +553,112 @@ enum { CAP_PROP_GPHOTO2_PREVIEW = 17001, //!< Capture only preview fro CAP_PROP_VIEWFINDER = 17010 //!< Enter liveview mode. }; -//enum { +//! @} gPhoto2 //! @} videoio_flags_others + class IVideoCapture; -/** @brief Class for video capturing from video files, image sequences or cameras. The class provides C++ API -for capturing video from cameras or for reading video files and image sequences. Here is how the -class can be used: : -@code - #include "opencv2/opencv.hpp" +/** @brief Class for video capturing from video files, image sequences or cameras. - using namespace cv; +The class provides C++ API for capturing video from cameras or for reading video files and image sequences. - int main(int, char**) - { - VideoCapture cap(0); // open the default camera - if(!cap.isOpened()) // check if we succeeded - return -1; - - Mat edges; - namedWindow("edges",1); - for(;;) - { - Mat frame; - cap >> frame; // get a new frame from camera - cvtColor(frame, edges, COLOR_BGR2GRAY); - GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5); - Canny(edges, edges, 0, 30, 3); - imshow("edges", edges); - if(waitKey(30) >= 0) break; - } - // the camera will be deinitialized automatically in VideoCapture destructor - return 0; - } -@endcode -@note In C API the black-box structure CvCapture is used instead of VideoCapture. +Here is how the class can be used: +@include samples/cpp/videocapture_basic.cpp +@note In @ref videoio_c "C API" the black-box structure `CvCapture` is used instead of %VideoCapture. @note -- A basic sample on using the VideoCapture interface can be found at - opencv_source_code/samples/cpp/starter_video.cpp -- Another basic video processing sample can be found at - opencv_source_code/samples/cpp/video_dmtx.cpp -- (Python) A basic sample on using the VideoCapture interface can be found at - opencv_source_code/samples/python/video.py -- (Python) Another basic video processing sample can be found at - opencv_source_code/samples/python/video_dmtx.py +- (C++) A basic sample on using the %VideoCapture interface can be found at + `OPENCV_SOURCE_CODE/samples/cpp/videocapture_starter.cpp` +- (Python) A basic sample on using the %VideoCapture interface can be found at + `OPENCV_SOURCE_CODE/samples/python/video.py` - (Python) A multi threaded video processing sample can be found at - opencv_source_code/samples/python/video_threaded.py + `OPENCV_SOURCE_CODE/samples/python/video_threaded.py` +- (Python) %VideoCapture sample showcasing some features of the Video4Linux2 backend + `OPENCV_SOURCE_CODE/samples/python/video_v4l2.py` */ class CV_EXPORTS_W VideoCapture { public: - /** @brief - @note In C API, when you finished working with video, release CvCapture structure with + /** @brief Default constructor + @note In @ref videoio_c "C API", when you finished working with video, release CvCapture structure with cvReleaseCapture(), or use Ptr\ that calls cvReleaseCapture() automatically in the destructor. */ CV_WRAP VideoCapture(); /** @overload - @param filename name of the opened video file (eg. video.avi) or image sequence (eg. - img_%02d.jpg, which will read samples like img_00.jpg, img_01.jpg, img_02.jpg, ...) + @brief Open video file or a capturing device or a IP video stream for video capturing + + Same as VideoCapture(const String& filename, int apiPreference) but using default Capture API backends */ CV_WRAP VideoCapture(const String& filename); /** @overload - @param filename name of the opened video file (eg. video.avi) or image sequence (eg. - img_%02d.jpg, which will read samples like img_00.jpg, img_01.jpg, img_02.jpg, ...) + @brief Open video file or a capturing device or a IP video stream for video capturing with API Preference - @param apiPreference preferred Capture API to use. Can be used to enforce a specific reader - implementation if multiple are available: e.g. cv::CAP_FFMPEG or cv::CAP_IMAGES + @param filename it can be: + - name of video file (eg. `video.avi`) + - or image sequence (eg. `img_%02d.jpg`, which will read samples like `img_00.jpg, img_01.jpg, img_02.jpg, ...`) + - or URL of video stream (eg. `protocol://host:port/script_name?script_params|auth`). + Note that each video stream or IP camera feed has its own URL scheme. Please refer to the + documentation of source stream to know the right URL. + @param apiPreference preferred Capture API backends to use. Can be used to enforce a specific reader + implementation if multiple are available: e.g. cv::CAP_FFMPEG or cv::CAP_IMAGES or cv::CAP_DSHOW. + @sa The list of supported API backends cv::VideoCaptureAPIs */ CV_WRAP VideoCapture(const String& filename, int apiPreference); /** @overload - @param index = camera_id + domain_offset (CAP_*). id of the video capturing device to open. If there is a single - camera connected, just pass 0. Advanced Usage: to open Camera 1 using the MS Media Foundation API: index = 1 + cv::CAP_MSMF + @brief Open a camera for video capturing + + @param index camera_id + domain_offset (CAP_*) id of the video capturing device to open. To open default camera using default backend just pass 0. + Use a `domain_offset` to enforce a specific reader implementation if multiple are available like cv::CAP_FFMPEG or cv::CAP_IMAGES or cv::CAP_DSHOW. + e.g. to open Camera 1 using the MS Media Foundation API use `index = 1 + cv::CAP_MSMF` + + @sa The list of supported API backends cv::VideoCaptureAPIs */ CV_WRAP VideoCapture(int index); + /** @brief Default destructor + + The method first calls VideoCapture::release to close the already opened file or camera. + */ virtual ~VideoCapture(); - /** @brief Open video file or a capturing device for video capturing + /** @brief Open video file or a capturing device or a IP video stream for video capturing - @param filename name of the opened video file (eg. video.avi) or image sequence (eg. - img_%02d.jpg, which will read samples like img_00.jpg, img_01.jpg, img_02.jpg, ...) + @overload - The methods first call VideoCapture::release to close the already opened file or camera. + Parameters are same as the constructor VideoCapture(const String& filename) + @return `true` if the file has been successfully opened + + The method first calls VideoCapture::release to close the already opened file or camera. */ CV_WRAP virtual bool open(const String& filename); - /** @overload - @param index = camera_id + domain_offset (CAP_*). id of the video capturing device to open. If there is a single - camera connected, just pass 0. Advanced Usage: to open Camera 1 using the MS Media Foundation API: index = 1 + cv::CAP_MSMF + /** @brief Open a camera for video capturing + + @overload + + Parameters are same as the constructor VideoCapture(int index) + @return `true` if the camera has been successfully opened. + + The method first calls VideoCapture::release to close the already opened file or camera. */ CV_WRAP virtual bool open(int index); /** @brief Returns true if video capturing has been initialized already. - If the previous call to VideoCapture constructor or VideoCapture::open succeeded, the method returns + If the previous call to VideoCapture constructor or VideoCapture::open() succeeded, the method returns true. */ CV_WRAP virtual bool isOpened() const; /** @brief Closes video file or capturing device. - The methods are automatically called by subsequent VideoCapture::open and by VideoCapture + The method is automatically called by subsequent VideoCapture::open and by VideoCapture destructor. The C function also deallocates memory and clears \*capture pointer. @@ -617,7 +667,9 @@ public: /** @brief Grabs the next frame from video file or capturing device. - The methods/functions grab the next frame from video file or camera and return true (non-zero) in + @return `true` (non-zero) in the case of success. + + The method/function grabs the next frame from video file or camera and returns true (non-zero) in the case of success. The primary use of the function is in multi-camera environments, especially when the cameras do not @@ -627,34 +679,52 @@ public: from different cameras will be closer in time. Also, when a connected camera is multi-head (for example, a stereo camera or a Kinect device), the - correct way of retrieving data from it is to call VideoCapture::grab first and then call - VideoCapture::retrieve one or more times with different values of the channel parameter. See - + correct way of retrieving data from it is to call VideoCapture::grab() first and then call + VideoCapture::retrieve() one or more times with different values of the channel parameter. + + @ref tutorial_kinect_openni */ CV_WRAP virtual bool grab(); /** @brief Decodes and returns the grabbed video frame. - The methods/functions decode and return the just grabbed frame. If no frames has been grabbed - (camera has been disconnected, or there are no more frames in video file), the methods return false - and the functions return NULL pointer. + @param [out] image the video frame is returned here. If no frames has been grabbed the image will be empty. + @param flag it could be a frame index or a driver specific flag + @return `false` if no frames has been grabbed - @note OpenCV 1.x functions cvRetrieveFrame and cv.RetrieveFrame return image stored inside the video + The method decodes and returns the just grabbed frame. If no frames has been grabbed + (camera has been disconnected, or there are no more frames in video file), the method returns false + and the function returns an empty image (with %cv::Mat, test it with Mat::empty()). + + @sa read() + + @note In @ref videoio_c "C API", functions cvRetrieveFrame() and cv.RetrieveFrame() return image stored inside the video capturing structure. It is not allowed to modify or release the image! You can copy the frame using :ocvcvCloneImage and then do whatever you want with the copy. */ CV_WRAP virtual bool retrieve(OutputArray image, int flag = 0); + + /** @brief Stream operator to read the next video frame. + @sa read() + */ virtual VideoCapture& operator >> (CV_OUT Mat& image); + + /** @overload + @sa read() + */ virtual VideoCapture& operator >> (CV_OUT UMat& image); /** @brief Grabs, decodes and returns the next video frame. - The methods/functions combine VideoCapture::grab and VideoCapture::retrieve in one call. This is the - most convenient method for reading video files or capturing data from decode and return the just - grabbed frame. If no frames has been grabbed (camera has been disconnected, or there are no more - frames in video file), the methods return false and the functions return NULL pointer. + @param [out] image the video frame is returned here. If no frames has been grabbed the image will be empty. + @return `false` if no frames has been grabbed - @note OpenCV 1.x functions cvRetrieveFrame and cv.RetrieveFrame return image stored inside the video + The method/function combines VideoCapture::grab() and VideoCapture::retrieve() in one call. This is the + most convenient method for reading video files or capturing data from decode and returns the just + grabbed frame. If no frames has been grabbed (camera has been disconnected, or there are no more + frames in video file), the method returns false and the function returns empty image (with %cv::Mat, test it with Mat::empty()). + + @note In @ref videoio_c "C API", functions cvRetrieveFrame() and cv.RetrieveFrame() return image stored inside the video capturing structure. It is not allowed to modify or release the image! You can copy the frame using :ocvcvCloneImage and then do whatever you want with the copy. */ @@ -662,70 +732,43 @@ public: /** @brief Sets a property in the VideoCapture. - @param propId Property identifier. It can be one of the following: - - cv::CAP_PROP_POS_MSEC @copydoc cv::CAP_PROP_POS_MSEC - - cv::CAP_PROP_POS_FRAMES @copydoc CAP_PROP_POS_FRAMES - - cv::CAP_PROP_POS_AVI_RATIO @copydoc cv::CAP_PROP_POS_AVI_RATIO - - cv::CAP_PROP_FRAME_WIDTH @copydoc cv::CAP_PROP_FRAME_WIDTH - - cv::CAP_PROP_FRAME_HEIGHT @copydoc cv::CAP_PROP_FRAME_HEIGHT - - cv::CAP_PROP_FPS @copydoc cv::CAP_PROP_FPS - - cv::CAP_PROP_FOURCC @copydoc cv::CAP_PROP_FOURCC - - cv::CAP_PROP_FRAME_COUNT @copydoc cv::CAP_PROP_FRAME_COUNT - - cv::CAP_PROP_FORMAT @copydoc cv::CAP_PROP_FORMAT - - cv::CAP_PROP_MODE @copydoc cv::CAP_PROP_MODE - - cv::CAP_PROP_BRIGHTNESS @copydoc cv::CAP_PROP_BRIGHTNESS - - cv::CAP_PROP_CONTRAST @copydoc cv::CAP_PROP_CONTRAST - - cv::CAP_PROP_SATURATION @copydoc cv::CAP_PROP_SATURATION - - cv::CAP_PROP_HUE @copydoc cv::CAP_PROP_HUE - - cv::CAP_PROP_GAIN @copydoc cv::CAP_PROP_GAIN - - cv::CAP_PROP_EXPOSURE @copydoc cv::CAP_PROP_EXPOSURE - - cv::CAP_PROP_CONVERT_RGB @copydoc cv::CAP_PROP_CONVERT_RGB - - cv::CAP_PROP_WHITE_BALANCE_BLUE_U @copydoc cv::CAP_PROP_WHITE_BALANCE_BLUE_U - - cv::CAP_PROP_WHITE_BALANCE_RED_V @copydoc cv::CAP_PROP_WHITE_BALANCE_RED_V - - cv::CAP_PROP_RECTIFICATION @copydoc cv::CAP_PROP_RECTIFICATION + @param propId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...) + or one from @ref videoio_flags_others @param value Value of the property. + @return `true` if the property is supported by backend used by the VideoCapture instance. + @note Even if it returns `true` this doesn't ensure that the property + value has been accepted by the capture device. See note in VideoCapture::get() */ CV_WRAP virtual bool set(int propId, double value); /** @brief Returns the specified VideoCapture property - @param propId Property identifier. It can be one of the following: - - cv::CAP_PROP_POS_MSEC @copydoc cv::CAP_PROP_POS_MSEC - - cv::CAP_PROP_POS_FRAMES @copydoc CAP_PROP_POS_FRAMES - - cv::CAP_PROP_POS_AVI_RATIO @copydoc cv::CAP_PROP_POS_AVI_RATIO - - cv::CAP_PROP_FRAME_WIDTH @copydoc cv::CAP_PROP_FRAME_WIDTH - - cv::CAP_PROP_FRAME_HEIGHT @copydoc cv::CAP_PROP_FRAME_HEIGHT - - cv::CAP_PROP_FPS @copydoc cv::CAP_PROP_FPS - - cv::CAP_PROP_FOURCC @copydoc cv::CAP_PROP_FOURCC - - cv::CAP_PROP_FRAME_COUNT @copydoc cv::CAP_PROP_FRAME_COUNT - - cv::CAP_PROP_FORMAT @copydoc cv::CAP_PROP_FORMAT - - cv::CAP_PROP_MODE @copydoc cv::CAP_PROP_MODE - - cv::CAP_PROP_BRIGHTNESS @copydoc cv::CAP_PROP_BRIGHTNESS - - cv::CAP_PROP_CONTRAST @copydoc cv::CAP_PROP_CONTRAST - - cv::CAP_PROP_SATURATION @copydoc cv::CAP_PROP_SATURATION - - cv::CAP_PROP_HUE @copydoc cv::CAP_PROP_HUE - - cv::CAP_PROP_GAIN @copydoc cv::CAP_PROP_GAIN - - cv::CAP_PROP_EXPOSURE @copydoc cv::CAP_PROP_EXPOSURE - - cv::CAP_PROP_CONVERT_RGB @copydoc cv::CAP_PROP_CONVERT_RGB - - cv::CAP_PROP_WHITE_BALANCE_BLUE_U @copydoc cv::CAP_PROP_WHITE_BALANCE_BLUE_U - - cv::CAP_PROP_WHITE_BALANCE_RED_V @copydoc cv::CAP_PROP_WHITE_BALANCE_RED_V - - cv::CAP_PROP_RECTIFICATION @copydoc cv::CAP_PROP_RECTIFICATION + @param propId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...) + or one from @ref videoio_flags_others + @return Value for the specified property. Value 0 is returned when querying a property that is + not supported by the backend used by the VideoCapture instance. - @note When querying a property that is not supported by the backend used by the VideoCapture - class, value 0 is returned. - */ + @note Reading / writing properties involves many layers. Some unexpected result might happens + along this chain. + @code {.txt} + `VideoCapture -> API Backend -> Operating System -> Device Driver -> Device Hardware` + @endcode + The returned value might be different from what really used by the device or it could be encoded + using device dependant rules (eg. steps or percentage). Effective behaviour depends from device + driver and API Backend + + */ CV_WRAP virtual double get(int propId) const; - /** @overload + /** @brief Open video file or a capturing device or a IP video stream for video capturing with API Preference - @param filename name of the opened video file (eg. video.avi) or image sequence (eg. - img_%02d.jpg, which will read samples like img_00.jpg, img_01.jpg, img_02.jpg, ...) + @overload - @param apiPreference preferred Capture API to use. Can be used to enforce a specific reader - implementation if multiple are available: e.g. cv::CAP_FFMPEG or cv::CAP_IMAGES + Parameters are same as the constructor VideoCapture(const String& filename, int apiPreference) + @return `true` if the file has been successfully opened - The methods first call VideoCapture::release to close the already opened file or camera. - */ + The method first calls VideoCapture::release to close the already opened file or camera. + */ CV_WRAP virtual bool open(const String& filename, int apiPreference); protected: @@ -736,14 +779,21 @@ protected: class IVideoWriter; /** @brief Video writer class. + +The class provides C++ API for writing video files or image sequences. + +Here is how the class can be used: +@include samples/cpp/videowriter_basic.cpp */ class CV_EXPORTS_W VideoWriter { public: - /** @brief VideoWriter constructors + /** @brief Default constructors - The constructors/functions initialize video writers. On Linux FFMPEG is used to write videos; on - Windows FFMPEG or VFW is used; on MacOSX QTKit is used. + The constructors/functions initialize video writers. + - On Linux FFMPEG is used to write videos; + - On Windows FFMPEG or VFW is used; + - On MacOSX QTKit is used. */ CV_WRAP VideoWriter(); @@ -759,16 +809,31 @@ public: @param frameSize Size of the video frames. @param isColor If it is not zero, the encoder will expect and encode color frames, otherwise it will work with grayscale frames (the flag is currently supported on Windows only). + + @b Tips: + - With some backends `fourcc=-1` pops up the codec selection dialog from the system. + - To save image sequence use a proper filename (eg. `img_%02d.jpg`) and `fourcc=0` + OR `fps=0`. Use uncompressed image format (eg. `img_%02d.BMP`) to save raw frames. + - Most codecs are lossy. If you want lossless video file you need to use a lossless codecs + (eg. FFMPEG FFV1, Huffman HFYU, Lagarith LAGS, etc...) + - If FFMPEG is enabled, using `codec=0; fps=0;` you can create an uncompressed (raw) video file. */ CV_WRAP VideoWriter(const String& filename, int fourcc, double fps, Size frameSize, bool isColor = true); + /** @brief Default destructor + + The method first calls VideoWriter::release to close the already opened file. + */ virtual ~VideoWriter(); /** @brief Initializes or reinitializes video writer. The method opens video writer. Parameters are the same as in the constructor VideoWriter::VideoWriter. + @return `true` if video writer has been successfully initialized + + The method first calls VideoWriter::release to close the already opened file. */ CV_WRAP virtual bool open(const String& filename, int fourcc, double fps, Size frameSize, bool isColor = true); @@ -779,44 +844,49 @@ public: /** @brief Closes the video writer. - The methods are automatically called by subsequent VideoWriter::open and by the VideoWriter + The method is automatically called by subsequent VideoWriter::open and by the VideoWriter destructor. */ CV_WRAP virtual void release(); + + /** @brief Stream operator to write the next video frame. + @sa write + */ virtual VideoWriter& operator << (const Mat& image); /** @brief Writes the next video frame @param image The written frame - The functions/methods write the specified image to video file. It must have the same size as has + The function/method writes the specified image to video file. It must have the same size as has been specified when opening the video writer. */ CV_WRAP virtual void write(const Mat& image); /** @brief Sets a property in the VideoWriter. - @param propId Property identifier. It can be one of the following: - - cv::VIDEOWRITER_PROP_QUALITY @copydoc cv::VIDEOWRITER_PROP_QUALITY - - cv::VIDEOWRITER_PROP_NSTRIPES @copydoc cv::VIDEOWRITER_PROP_NSTRIPES + @param propId Property identifier from cv::VideoWriterProperties (eg. cv::VIDEOWRITER_PROP_QUALITY) + or one of @ref videoio_flags_others + @param value Value of the property. + @return `true` if the property is supported by the backend used by the VideoWriter instance. */ CV_WRAP virtual bool set(int propId, double value); /** @brief Returns the specified VideoWriter property - @param propId Property identifier. It can be one of the following: - - cv::VIDEOWRITER_PROP_QUALITY @copydoc cv::VIDEOWRITER_PROP_QUALITY - - cv::VIDEOWRITER_PROP_FRAMEBYTES @copydoc VIDEOWRITER_PROP_FRAMEBYTES - - cv::VIDEOWRITER_PROP_NSTRIPES @copydoc cv::VIDEOWRITER_PROP_NSTRIPES + @param propId Property identifier from cv::VideoWriterProperties (eg. cv::VIDEOWRITER_PROP_QUALITY) + or one of @ref videoio_flags_others - @note When querying a property that is not supported by the backend used by the VideoWriter - class, value 0 is returned. + @return Value for the specified property. Value 0 is returned when querying a property that is + not supported by the backend used by the VideoWriter instance. */ CV_WRAP virtual double get(int propId) const; /** @brief Concatenates 4 chars to a fourcc code + @return a fourcc code + This static method constructs the fourcc code of the codec to be used in the constructor VideoWriter::VideoWriter or VideoWriter::open. */ diff --git a/modules/videoio/include/opencv2/videoio/videoio_c.h b/modules/videoio/include/opencv2/videoio/videoio_c.h index e502c7be83..63aef7ddb2 100644 --- a/modules/videoio/include/opencv2/videoio/videoio_c.h +++ b/modules/videoio/include/opencv2/videoio/videoio_c.h @@ -57,13 +57,18 @@ extern "C" { * Working with Video Files and Cameras * \****************************************************************************************/ -/* "black box" capture structure */ +/** @brief "black box" capture structure + +In C++ use cv::VideoCapture +*/ typedef struct CvCapture CvCapture; -/* start capturing frames from video file */ +/** @brief start capturing frames from video file +*/ CVAPI(CvCapture*) cvCreateFileCapture( const char* filename ); -/* start capturing frames from video file. allows specifying a preferred API to use */ +/** @brief start capturing frames from video file. allows specifying a preferred API to use +*/ CVAPI(CvCapture*) cvCreateFileCaptureWithPreference( const char* filename , int apiPreference); enum @@ -120,24 +125,32 @@ enum CV_CAP_IMAGES = 2000 // OpenCV Image Sequence (e.g. img_%02d.jpg) }; -/* start capturing frames from camera: index = camera_index + domain_offset (CV_CAP_*) */ +/** @brief start capturing frames from camera: index = camera_index + domain_offset (CV_CAP_*) +*/ CVAPI(CvCapture*) cvCreateCameraCapture( int index ); -/* grab a frame, return 1 on success, 0 on fail. - this function is thought to be fast */ +/** @brief grab a frame, return 1 on success, 0 on fail. + + this function is thought to be fast +*/ CVAPI(int) cvGrabFrame( CvCapture* capture ); -/* get the frame grabbed with cvGrabFrame(..) +/** @brief get the frame grabbed with cvGrabFrame(..) + This function may apply some frame processing like frame decompression, flipping etc. - !!!DO NOT RELEASE or MODIFY the retrieved frame!!! */ + @warning !!!DO NOT RELEASE or MODIFY the retrieved frame!!! +*/ CVAPI(IplImage*) cvRetrieveFrame( CvCapture* capture, int streamIdx CV_DEFAULT(0) ); -/* Just a combination of cvGrabFrame and cvRetrieveFrame - !!!DO NOT RELEASE or MODIFY the retrieved frame!!! */ +/** @brief Just a combination of cvGrabFrame and cvRetrieveFrame + + @warning !!!DO NOT RELEASE or MODIFY the retrieved frame!!! +*/ CVAPI(IplImage*) cvQueryFrame( CvCapture* capture ); -/* stop capturing/reading and free resources */ +/** @brief stop capturing/reading and free resources +*/ CVAPI(void) cvReleaseCapture( CvCapture** capture ); enum @@ -498,48 +511,71 @@ enum CV_CAP_PROP_VIEWFINDER = 17010 // Enter liveview mode. }; -/* retrieve or set capture properties */ +/** @brief retrieve capture properties +*/ CVAPI(double) cvGetCaptureProperty( CvCapture* capture, int property_id ); +/** @brief set capture properties +*/ CVAPI(int) cvSetCaptureProperty( CvCapture* capture, int property_id, double value ); -// Return the type of the capturer (eg, CV_CAP_V4W, CV_CAP_UNICAP), which is unknown if created with CV_CAP_ANY +/** @brief Return the type of the capturer (eg, ::CV_CAP_VFW, ::CV_CAP_UNICAP) + +It is unknown if created with ::CV_CAP_ANY +*/ CVAPI(int) cvGetCaptureDomain( CvCapture* capture); -/* "black box" video file writer structure */ +/** @brief "black box" video file writer structure + +In C++ use cv::VideoWriter +*/ typedef struct CvVideoWriter CvVideoWriter; +//! Macro to construct the fourcc code of the codec. Same as CV_FOURCC() #define CV_FOURCC_MACRO(c1, c2, c3, c4) (((c1) & 255) + (((c2) & 255) << 8) + (((c3) & 255) << 16) + (((c4) & 255) << 24)) +/** @brief Constructs the fourcc code of the codec function + +Simply call it with 4 chars fourcc code like `CV_FOURCC('I', 'Y', 'U', 'V')` + +List of codes can be obtained at [Video Codecs by FOURCC](http://www.fourcc.org/codecs.php) page. +FFMPEG backend with MP4 container natively uses other values as fourcc code: +see [ObjectType](http://www.mp4ra.org/codecs.html). +*/ CV_INLINE int CV_FOURCC(char c1, char c2, char c3, char c4) { return CV_FOURCC_MACRO(c1, c2, c3, c4); } -#define CV_FOURCC_PROMPT -1 /* Open Codec Selection Dialog (Windows only) */ -#define CV_FOURCC_DEFAULT CV_FOURCC('I', 'Y', 'U', 'V') /* Use default codec for specified filename (Linux only) */ +//! (Windows only) Open Codec Selection Dialog +#define CV_FOURCC_PROMPT -1 +//! (Linux only) Use default codec for specified filename +#define CV_FOURCC_DEFAULT CV_FOURCC('I', 'Y', 'U', 'V') -/* initialize video file writer */ +/** @brief initialize video file writer +*/ CVAPI(CvVideoWriter*) cvCreateVideoWriter( const char* filename, int fourcc, double fps, CvSize frame_size, int is_color CV_DEFAULT(1)); -/* write frame to video file */ +/** @brief write frame to video file +*/ CVAPI(int) cvWriteFrame( CvVideoWriter* writer, const IplImage* image ); -/* close video file writer */ +/** @brief close video file writer +*/ CVAPI(void) cvReleaseVideoWriter( CvVideoWriter** writer ); -/****************************************************************************************\ -* Obsolete functions/synonyms * -\****************************************************************************************/ +// *************************************************************************************** +//! @name Obsolete functions/synonyms +//! @{ +#define cvCaptureFromCAM cvCreateCameraCapture //!< @deprecated use cvCreateCameraCapture() instead +#define cvCaptureFromFile cvCreateFileCapture //!< @deprecated use cvCreateFileCapture() instead +#define cvCaptureFromAVI cvCaptureFromFile //!< @deprecated use cvCreateFileCapture() instead +#define cvCreateAVIWriter cvCreateVideoWriter //!< @deprecated use cvCreateVideoWriter() instead +#define cvWriteToAVI cvWriteFrame //!< @deprecated use cvWriteFrame() instead +//! @} Obsolete... -#define cvCaptureFromFile cvCreateFileCapture -#define cvCaptureFromCAM cvCreateCameraCapture -#define cvCaptureFromAVI cvCaptureFromFile -#define cvCreateAVIWriter cvCreateVideoWriter -#define cvWriteToAVI cvWriteFrame - -/** @} videoio_c */ +//! @} videoio_c #ifdef __cplusplus } diff --git a/samples/cpp/videocapture_basic.cpp b/samples/cpp/videocapture_basic.cpp new file mode 100644 index 0000000000..ae77b05448 --- /dev/null +++ b/samples/cpp/videocapture_basic.cpp @@ -0,0 +1,52 @@ +/** + @file videocapture_basic.cpp + @brief A very basic sample for using VideoCapture and VideoWriter + @author PkLab.net + @date Aug 24, 2016 +*/ + +#include +#include +#include + +using namespace cv; +using namespace std; + +int main(int, char**) +{ + Mat frame; + //--- INITIALIZE VIDEOCAPTURE + VideoCapture cap; + // open the default camera using default API + cap.open(0); + // OR advance usage: select any API backend + int deviceID = 0; // 0 = open default camera + int apiID = cv::CAP_ANY; // 0 = autodetect default API + // open selected camera using selected API + cap.open(deviceID + apiID); + // check if we succeeded + if (!cap.isOpened()) { + cerr << "ERROR! Unable to open camera\n"; + return -1; + } + + //--- GRAB AND WRITE LOOP + cout << "Start grabbing" << endl + << "Press any key to terminate" << endl; + for (;;) + { + // wait for a new frame from camera and store it into 'frame' + cap.read(frame); + // check if we succeeded + if (frame.empty()) { + cerr << "ERROR! blank frame grabbed\n"; + break; + } + // show live and wait for a key with timeout long enough to show images + imshow("Live", frame); + if (waitKey(5) >= 0) + break; + } + // the camera will be deinitialized automatically in VideoCapture destructor + return 0; +} \ No newline at end of file diff --git a/samples/cpp/starter_video.cpp b/samples/cpp/videocapture_starter.cpp similarity index 95% rename from samples/cpp/starter_video.cpp rename to samples/cpp/videocapture_starter.cpp index 2839b03d7e..58f1145ed5 100644 --- a/samples/cpp/starter_video.cpp +++ b/samples/cpp/videocapture_starter.cpp @@ -1,14 +1,13 @@ -/* -* starter_video.cpp +/** +* @file videocapture_starter.cpp +* @brief A starter sample for using OpenCV VideoCapture with capture devices, video files or image sequences +* easy as CV_PI right? * * Created on: Nov 23, 2010 * Author: Ethan Rublee * * Modified on: April 17, 2013 * Author: Kevin Hughes -* -* A starter sample for using OpenCV VideoCapture with capture devices, video files or image sequences -* easy as CV_PI right? */ #include diff --git a/samples/cpp/videowriter_basic.cpp b/samples/cpp/videowriter_basic.cpp new file mode 100644 index 0000000000..9ab4efcc90 --- /dev/null +++ b/samples/cpp/videowriter_basic.cpp @@ -0,0 +1,65 @@ +/** + @file videowriter_basic.cpp + @brief A very basic sample for using VideoWriter and VideoCapture + @author PkLab.net + @date Aug 24, 2016 +*/ + +#include +#include +#include + +using namespace cv; +using namespace std; + +int main(int, char**) +{ + Mat src; + // use default camera as video source + VideoCapture cap(0); + // check if we succeeded + if (!cap.isOpened()) { + cerr << "ERROR! Unable to open camera\n"; + return -1; + } + // get one frame from camera to know frame size and type + cap >> src; + // check if we succeeded + if (src.empty()) { + cerr << "ERROR! blank frame grabbed\n"; + return -1; + } + bool isColor = (src.type() == CV_8UC3); + + //--- INITIALIZE VIDEOWRITER + VideoWriter writer; + int codec = CV_FOURCC('M', 'J', 'P', 'G'); // select desired codec (must be available at runtime) + double fps = 25.0; // framerate of the created video stream + string filename = "./live.avi"; // name of the output video file + writer.open(filename, codec, fps, src.size(), isColor); + // check if we succeeded + if (!writer.isOpened()) { + cerr << "Could not open the output video file for write\n"; + return -1; + } + + //--- GRAB AND WRITE LOOP + cout << "Writing videofile: " << filename << endl + << "Press any key to terminate" << endl; + for (;;) + { + // check if we succeeded + if (!cap.read(src)) { + cerr << "ERROR! blank frame grabbed\n"; + break; + } + // encode the frame into the videofile stream + writer.write(src); + // show live and wait for a key with timeout long enough to show images + imshow("Live", src); + if (waitKey(5) >= 0) + break; + } + // the videofile will be closed and released automatically in VideoWriter destructor + return 0; +} \ No newline at end of file From a9ab869800119360c0c34780ce1ab9d281b99753 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Fri, 9 Sep 2016 23:31:02 +0400 Subject: [PATCH 147/178] seriously improved performance of blur function, especially 3x3 and 5x5 cases (#7262) * seriously improved performance of blur function, especially 3x3 and 5x5 cases * trying to fix warnings and test failures * replaced #if 0 with #if IPP_DISABLE_BLOCK --- modules/imgproc/perf/perf_blur.cpp | 2 - modules/imgproc/src/smooth.cpp | 260 ++++++++++++++++++++++++++--- 2 files changed, 241 insertions(+), 21 deletions(-) diff --git a/modules/imgproc/perf/perf_blur.cpp b/modules/imgproc/perf/perf_blur.cpp index 58a0c7cbab..2a284dc5b9 100644 --- a/modules/imgproc/perf/perf_blur.cpp +++ b/modules/imgproc/perf/perf_blur.cpp @@ -100,9 +100,7 @@ PERF_TEST_P(Size_MatType_BorderType, blur16x16, BorderType btype = get<2>(GetParam()); double eps = 1e-3; -#if CV_NEON eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : eps; -#endif Mat src(size, type); Mat dst(size, type); diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 8639f0d243..7772fc763a 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -86,18 +86,93 @@ struct RowSum : int i = 0, k, ksz_cn = ksize*cn; width = (width - 1)*cn; - for( k = 0; k < cn; k++, S++, D++ ) + if( ksize == 3 ) { - ST s = 0; - for( i = 0; i < ksz_cn; i += cn ) - s += S[i]; - D[0] = s; - for( i = 0; i < width; i += cn ) + for( i = 0; i < width + cn; i++ ) { - s += S[i + ksz_cn] - S[i]; - D[i+cn] = s; + D[i] = (ST)(S[i] + S[i+cn] + S[i+cn*2]); } } + else if( ksize == 5 ) + { + for( i = 0; i < width + cn; i++ ) + { + D[i] = (ST)(S[i] + S[i+cn] + S[i+cn*2] + S[i + cn*3] + S[i + cn*4]); + } + } + else if( cn == 1 ) + { + ST s = 0; + for( i = 0; i < ksz_cn; i++ ) + s += S[i]; + D[0] = s; + for( i = 0; i < width; i++ ) + { + s += S[i + ksz_cn] - S[i]; + D[i+1] = s; + } + } + else if( cn == 3 ) + { + ST s0 = 0, s1 = 0, s2 = 0; + for( i = 0; i < ksz_cn; i += 3 ) + { + s0 += S[i]; + s1 += S[i+1]; + s2 += S[i+2]; + } + D[0] = s0; + D[1] = s1; + D[2] = s2; + for( i = 0; i < width; i += 3 ) + { + s0 += S[i + ksz_cn] - S[i]; + s1 += S[i + ksz_cn + 1] - S[i + 1]; + s2 += S[i + ksz_cn + 2] - S[i + 2]; + D[i+3] = s0; + D[i+4] = s1; + D[i+5] = s2; + } + } + else if( cn == 4 ) + { + ST s0 = 0, s1 = 0, s2 = 0, s3 = 0; + for( i = 0; i < ksz_cn; i += 4 ) + { + s0 += S[i]; + s1 += S[i+1]; + s2 += S[i+2]; + s3 += S[i+3]; + } + D[0] = s0; + D[1] = s1; + D[2] = s2; + D[3] = s3; + for( i = 0; i < width; i += 4 ) + { + s0 += S[i + ksz_cn] - S[i]; + s1 += S[i + ksz_cn + 1] - S[i + 1]; + s2 += S[i + ksz_cn + 2] - S[i + 2]; + s3 += S[i + ksz_cn + 3] - S[i + 3]; + D[i+4] = s0; + D[i+5] = s1; + D[i+6] = s2; + D[i+7] = s3; + } + } + else + for( k = 0; k < cn; k++, S++, D++ ) + { + ST s = 0; + for( i = 0; i < ksz_cn; i += cn ) + s += S[i]; + D[0] = s; + for( i = 0; i < width; i += cn ) + { + s += S[i + ksz_cn] - S[i]; + D[i+cn] = s; + } + } } }; @@ -138,13 +213,8 @@ struct ColumnSum : for( ; sumCount < ksize - 1; sumCount++, src++ ) { const ST* Sp = (const ST*)src[0]; - for( i = 0; i <= width - 2; i += 2 ) - { - ST s0 = SUM[i] + Sp[i], s1 = SUM[i+1] + Sp[i+1]; - SUM[i] = s0; SUM[i+1] = s1; - } - for( ; i < width; i++ ) + for( i = 0; i < width; i++ ) SUM[i] += Sp[i]; } } @@ -391,6 +461,151 @@ struct ColumnSum : std::vector sum; }; + +template<> +struct ColumnSum : +public BaseColumnFilter +{ + ColumnSum( int _ksize, int _anchor, double _scale ) : + BaseColumnFilter() + { + ksize = _ksize; + anchor = _anchor; + scale = _scale; + sumCount = 0; + divDelta = 0; + divScale = 1; + if( scale != 1 ) + { + int d = cvRound(1./scale); + double scalef = (1 << 16)/d; + divScale = cvFloor(scalef); + scalef -= divScale; + divDelta = d/2; + if( scalef < 0.5 ) + divDelta++; + else + divScale++; + } + } + + virtual void reset() { sumCount = 0; } + + virtual void operator()(const uchar** src, uchar* dst, int dststep, int count, int width) + { + int i, ds = divScale, dd = divDelta; + ushort* SUM; + bool haveScale = scale != 1; + +#if CV_SSE2 + bool haveSSE2 = checkHardwareSupport(CV_CPU_SSE2); +#elif CV_NEON + bool haveNEON = checkHardwareSupport(CV_CPU_NEON); +#endif + + if( width != (int)sum.size() ) + { + sum.resize(width); + sumCount = 0; + } + + SUM = &sum[0]; + if( sumCount == 0 ) + { + memset((void*)SUM, 0, width*sizeof(SUM[0])); + for( ; sumCount < ksize - 1; sumCount++, src++ ) + { + const ushort* Sp = (const ushort*)src[0]; + i = 0; +#if CV_SSE2 + if(haveSSE2) + { + for( ; i <= width-8; i+=8 ) + { + __m128i _sum = _mm_loadu_si128((const __m128i*)(SUM+i)); + __m128i _sp = _mm_loadu_si128((const __m128i*)(Sp+i)); + _mm_storeu_si128((__m128i*)(SUM+i),_mm_add_epi16(_sum, _sp)); + } + } +#elif CV_NEON + if(haveNEON) + { + for( ; i <= width - 8; i+=8 ) + vst1q_u16(SUM + i, vaddq_u16(vld1q_u16(SUM + i), vld1q_u16(Sp + i))); + } +#endif + for( ; i < width; i++ ) + SUM[i] += Sp[i]; + } + } + else + { + CV_Assert( sumCount == ksize-1 ); + src += ksize-1; + } + + for( ; count--; src++ ) + { + const ushort* Sp = (const ushort*)src[0]; + const ushort* Sm = (const ushort*)src[1-ksize]; + uchar* D = (uchar*)dst; + if( haveScale ) + { + i = 0; + #if CV_SSE2 + if(haveSSE2) + { + __m128i ds8 = _mm_set1_epi16((short)ds); + __m128i dd8 = _mm_set1_epi16((short)dd); + + for( ; i <= width-16; i+=16 ) + { + __m128i _sm0 = _mm_loadu_si128((const __m128i*)(Sm+i)); + __m128i _sm1 = _mm_loadu_si128((const __m128i*)(Sm+i+8)); + + __m128i _s0 = _mm_add_epi16(_mm_loadu_si128((const __m128i*)(SUM+i)), + _mm_loadu_si128((const __m128i*)(Sp+i))); + __m128i _s1 = _mm_add_epi16(_mm_loadu_si128((const __m128i*)(SUM+i+8)), + _mm_loadu_si128((const __m128i*)(Sp+i+8))); + __m128i _s2 = _mm_mulhi_epu16(_mm_adds_epu16(_s0, dd8), ds8); + __m128i _s3 = _mm_mulhi_epu16(_mm_adds_epu16(_s1, dd8), ds8); + _s0 = _mm_sub_epi16(_s0, _sm0); + _s1 = _mm_sub_epi16(_s1, _sm1); + _mm_storeu_si128((__m128i*)(D+i), _mm_packus_epi16(_s2, _s3)); + _mm_storeu_si128((__m128i*)(SUM+i), _s0); + _mm_storeu_si128((__m128i*)(SUM+i+8), _s1); + } + } + #endif + for( ; i < width; i++ ) + { + int s0 = SUM[i] + Sp[i]; + D[i] = (uchar)((s0 + dd)*ds >> 16); + SUM[i] = (ushort)(s0 - Sm[i]); + } + } + else + { + i = 0; + for( ; i < width; i++ ) + { + int s0 = SUM[i] + Sp[i]; + D[i] = saturate_cast(s0); + SUM[i] = (ushort)(s0 - Sm[i]); + } + } + dst += dststep; + } + } + + double scale; + int sumCount; + int divDelta; + int divScale; + std::vector sum; +}; + + template<> struct ColumnSum : public BaseColumnFilter @@ -1276,6 +1491,8 @@ cv::Ptr cv::getRowSumFilter(int srcType, int sumType, int ksi if( sdepth == CV_8U && ddepth == CV_32S ) return makePtr >(ksize, anchor); + if( sdepth == CV_8U && ddepth == CV_16U ) + return makePtr >(ksize, anchor); if( sdepth == CV_8U && ddepth == CV_64F ) return makePtr >(ksize, anchor); if( sdepth == CV_16U && ddepth == CV_32S ) @@ -1312,6 +1529,8 @@ cv::Ptr cv::getColumnSumFilter(int sumType, int dstType, i if( ddepth == CV_8U && sdepth == CV_32S ) return makePtr >(ksize, anchor, scale); + if( ddepth == CV_8U && sdepth == CV_16U ) + return makePtr >(ksize, anchor, scale); if( ddepth == CV_8U && sdepth == CV_64F ) return makePtr >(ksize, anchor, scale); if( ddepth == CV_16U && sdepth == CV_32S ) @@ -1346,7 +1565,10 @@ cv::Ptr cv::createBoxFilter( int srcType, int dstType, Size ks { int sdepth = CV_MAT_DEPTH(srcType); int cn = CV_MAT_CN(srcType), sumType = CV_64F; - if( sdepth <= CV_32S && (!normalize || + if( sdepth == CV_8U && CV_MAT_DEPTH(dstType) == CV_8U && + ksize.width*ksize.height <= 256 ) + sumType = CV_16U; + else if( sdepth <= CV_32S && (!normalize || ksize.width*ksize.height <= (sdepth == CV_8U ? (1<<23) : sdepth == CV_16U ? (1 << 15) : (1 << 16))) ) sumType = CV_32S; @@ -1360,7 +1582,8 @@ cv::Ptr cv::createBoxFilter( int srcType, int dstType, Size ks srcType, dstType, sumType, borderType ); } -#if defined(HAVE_IPP) +// TODO: IPP performance regression +#if defined(HAVE_IPP) && IPP_DISABLE_BLOCK namespace cv { static bool ipp_boxfilter( InputArray _src, OutputArray _dst, int ddepth, @@ -1483,9 +1706,8 @@ void cv::boxFilter( InputArray _src, OutputArray _dst, int ddepth, return; #endif -#ifdef HAVE_IPP +#if defined HAVE_IPP && IPP_DISABLE_BLOCK int ippBorderType = borderType & ~BORDER_ISOLATED; -#endif Point ocvAnchor, ippAnchor; ocvAnchor.x = anchor.x < 0 ? ksize.width / 2 : anchor.x; ocvAnchor.y = anchor.y < 0 ? ksize.height / 2 : anchor.y; @@ -1496,7 +1718,7 @@ void cv::boxFilter( InputArray _src, OutputArray _dst, int ddepth, ippBorderType == BORDER_CONSTANT) && ocvAnchor == ippAnchor && _dst.cols() != ksize.width && _dst.rows() != ksize.height), ipp_boxfilter( _src, _dst, ddepth, ksize, anchor, normalize, borderType)); - +#endif Ptr f = createBoxFilter( src.type(), dst.type(), ksize, anchor, normalize, borderType ); From a65f2b4bd3a75fe53dce502f9f82dcd67527b382 Mon Sep 17 00:00:00 2001 From: StevenPuttemans Date: Mon, 15 Aug 2016 16:18:31 +0200 Subject: [PATCH 148/178] huge overhaul/update of cascade classifier training --- .../images/visualisation_single_stage.png | Bin 0 -> 114233 bytes .../objdetect/images/visualisation_video.png | Bin 0 -> 284988 bytes doc/tutorials/objdetect/traincascade.markdown | 382 +++++++----------- 3 files changed, 135 insertions(+), 247 deletions(-) create mode 100644 doc/tutorials/objdetect/images/visualisation_single_stage.png create mode 100644 doc/tutorials/objdetect/images/visualisation_video.png diff --git a/doc/tutorials/objdetect/images/visualisation_single_stage.png b/doc/tutorials/objdetect/images/visualisation_single_stage.png new file mode 100644 index 0000000000000000000000000000000000000000..e87bc225fb092142585b4d1466a3ed6b368692c3 GIT binary patch literal 114233 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%0AyCUQnA!bt7G*B>d z8vMCuR{@>;4?S?RT~~V3?5>~oNs~T7qY>l%1p;&YK2`VZ6YXYB+!I2fhw_8EUS9jm zuIRM=qlhXK>pqc5^p|u4U&bqe=~~`ENn?F#gTf<+%B@6EA@ckp@#{7pT6AzU=o6%p zLCY$w!gMW&=%9P4WroeFOmN9!9iWK+{v(^g@#V5@#_S5>(=|tiOTkmC{2(Fr^0jFf zt0?%5#=MAbP?#|pRL758uAyp8+X;SOv{^64qxq%}d*qS~cZm^TC#7)F`);8cx==SH z7&z=Ybb??4iVjo{w4Mp_|9kVoa=0l7x5qGy3cC~kUeDeNhI)`Z3S^|3LGxmV|GBhoP?=<2-4Ft2--d$d$Y<&~t_ygw5lx2v({BF-Rs z&(@feJ_7o0`#3@Ozu#ls!vNC|OOtcbFf~s#v`64hnCrvvrE2Y$LSLeRCY|YA3)^k8 zL^aa^Q?DO~IZnUAqR=BO_O-Ig8mh_BGHRMQ`2nkW9%;rTv7R*##xJVR5uHc-2qV4* zb+&pO5tYyRs)|T&7v3l+d`|2_WL`xJk5$>;*vupmMx}A`AGJq{AXbp3pa+Ks8}NP8i<0d#)Z zIc80|vWD!oH!F7!-&!GqOaez3^IhB8QVB`$+A#Z&Nj!`@w@{XE!%9!*fc#dyOY>U( z_W{>Vq1kfzE(faO1k%1%cYGAkF}f>JxTD-ssuR%9B9m;6|IJ`G-Km{^BEl<`e7?K8 z+uO&-XU|%CBE)d;f~W@WTswb8f(uUV^oN9ele!js-I>c(i~hC#iBg1~2ad2Os960i zXx-pM1uCm5WlTS`oMcs|Z+bJIoHjI%GjV9W_hHyl+S~6Q)bu%vuP0}QpjfBPUoV4S zxn^*Z9>Jke$d$kDysG+jF!Qe37*D47WRbmtT35A^l6!C53p#aMx+57;L+0#1n>WS5 zKI}&JHxib`NV^t4Z;k#d6H@XjyoL$N;Jn=WhB%D0jU7m)rMP45i;dUp+v9pu^m0Kg z7&F@JsIhm?sBAn{WWNLP$E^I{lSPI%%0>Ke$|WEY7VZkKw`L^GPkwAg&H$xDMV_E9 zUmp)3J#BI~y?((!P%%u+M~A_(+1zh@_~Ch6T}{oiku|_G!yx+%CsFF$apGVFQ(3}J z&Xed{csIuszIgcZMVRgY^#1TtVw{>uEzg4);TLRGt>=K>*`m?d>D5PZ$To4?JX%H6 z3@#7iF?4*i|A8UJwYI)o?pmJ}e`kV?Rf-y5)NWY#D00#K&1YFzGaa=k5R;t!Qu&@* z6w{d<{13<1F1HIN%Peey!z(~Cb^9w{^S-zuwyW#w<-asqTf(@in$YIL>3j2A8;IcY zPR!t3*lQCXy7O7!-YzY<2=JB&k*cPp`vPwpL>l^;zrNUUJMJg%1N#&)kjLMQ7_^dLyHr?)TFj!H@Y&7EYM#d&=_F-q#!!tLs7BwRX~zN1B0u?EXJ(Wz z#Z^Y?9)-RzD)CzEnO+T>YM_tB$A?#0P6&V!NRoO6IE#f)I#7k3k_)M;3jqg(_OI5O z{j|P(GcfX0ZM@Ui=WH(DFi+XhfTD#KYQOH-Bd(DBL9PSs95(hwY@@JLR2CXVAD|z) zIlVzT;E+dFpW!|uHs;erK4eM+7P-|$`MliN3aXMPzs}K*_#q!k_=fj?_=5){| z;jSXdhf|ndh3KUfRF5w}O))F9kt+x58&6Cf?f|`m+}^&~1&{A6{NLLH%f=Yn7wKWe zFLA2#*@_qeZxR-FTJtbFZ|>Jrwe#M?D=O-N?dG6c*Q3=vzin#MNZAf?& zp7QBs`Abmm!}pgG_9z|0*nDRLoX6kqZ1O2H$lvpEo`Y2;wOiKmJfsmN|G5xC;rOD? zEV5R!u6DH4EL3b?14*I}%)X2fC1EJ#5K)`J@O5sTGcpoug*=Ul?fZm-d}D3Mf>(qp zERC1`l4_y__FxbZew*8SW{kTIx%nzr^OoxP7BK9Lj~MoP#){#x#C=)}(7ca6{4S{7 zERfV{B4nwEVYq1sem8fR3|KLznP25QhhLv)P$NZ=r4-YJ$QY~zVxYK18BZbbA->v* zJM|r%RlR|Hl?3yhaYIasQZ~Aq2i80Vx$>phaOu2ZW13n(@{GWakA!wT7bX=LScancstg9g(QZS!$iLPm= zhbYN%Q2ES{x~z*F{^{hU2`Waq8Z;{Az&c+l{B;67(X>3{&G$8)_Dd9V0sfF$hpuZL zc(8HZb*s_hDY9=Q5>3}8no(T>?rT*A0M-q+8nn>&9W+el(gH4!}(q`ryZfqTBi?*=4Y^f z=D%AaF7G)HIdmazjXpYFavW0P)J-ou zHU?jHM$UmTQ9n847qtlk_L_)gu1|q_SI-_bGT)NUvxlZ(2;z#L%w{DKefHNZueWPJY1c zm%Y53@Ri_ztG*NqI`Qy&4!MHtZ=VGD3!w`Duze-R!}1lAt;cWx*|^;9awUBm?#&7P z(JoZj*C^6^E2^l^$L)au(h%4hyF-Yj_KPjX{S4uba=X%`ANFzP94&J zl5J-r}UWX=%0I&T6isuG2@v z+B2lQoZDSo;Z6&K>+nB6p0w0AEm5?K70&z;G79`hk0Mu3K1!}VR=X9onS{peUUz}> z<26FA&E?nI)F+;86;7VO*UgwYM)l^2mO9D)4DYk(y~BE2!}}6EgqRhf{z&@)-kQ(3 zWu93FVDq&K4qm%WVDdeK0s_Bl9hT9x+w(!{eT?I+**8&W)IcRE6l}H~V0@1JCm|u& zA@>=-$;HIgat!?g00v3*$3^gl2VZVo>pofj_pibMm}<>1X0Ju6>HkbqH1o?R)p&%t zZrHt0Fcf$WX{*^SEv?6VHZ8fTs~&^?eIc8#-R_z4{lrd?t1hKc6ep@CP3$u3ftgGO z$P$E1Mv4$?%%FRm;Ky#x@jmjzS<630nsx5NDe<~@Hgo;|6uB7y|G}?W?&!tDO=%xW z!8+A0wl|TMuLwDI3pFYak`*9YCJ2|}aL|c2X&j+=#pzz76j6PHk$3~S!T|4;TlIKv zlr-CiOfyMLg?{#Jl9ywIg=k~l_hnrLSG|lQL$0)od}akxABS~|L>^x}cvXG)?PC}@ zjb%jjN=s-8-|ZnkmnUgFg%fO0%`=r!M-y^(`=0T%rr2Wr2-8j|zpLRB;04I@NzUz_ z&4yyahKD4Z2gRexgCA9=*}*OL?HGoK!6a-%_TuDblFqxm=f+((nZpBgo0>Ute z^(t}>eqsd}T03$a5|MU^3=}sUbz$WIG5`1K0rHs*^78hi*rJz%E<;KDnnpS>QjA7y z*u57Xz}|3cMIgl^1i|0}iP~?@r62i|oX0gsStKV`2~68*_f=5pjoLao>4zh~#-6@c zmJNkUUL^98+Qo(9ay!`<8;NFhcJg+_Jq&WfNh*raMvPVcyPk)L%mQ`l2y5&YR~gYW z%>%$!e`^O_ZMv}-b4tM9>&)SQ>^v3EU@l7B_1I9n_3KFlv5nk`c@mv~N#i=+mD04h z)=_F>>5%&X5H{`rlqo6HufQTn?a8E@4)1h9&2XsaEQ14;!J)24;;gi~AUTW6Qx&7X zH+Xwy`2c*jukG1$@y5dPFsqQn-=o|zxjT{jF$Vb*JmxBV7Z>n7Cu5HhBVqn3^8KRh zjcn%v>rRymyzkG|Jaic%!+%tVO9uKlrMlWbT6iyq_nImA;=G8of1_Z1O%e_X0W2I} z9{C;}AYlRuQ&mU?m7FAuT6HYD;dcDa7~vOTwGPuEo2vt$aN~-@)gTN_NeHifhp1KP z*`{hN8%gWa`M3)h!iOJY^NT9)*vvWB|HEQ|zF`T?Nv35HXM$DbPhbwB+JypD{y54OOSlRLPf! zK#}4LmY2N-^H!`o?*Rn6_7DX|zzZ;VCz)m!-?K$M`QY!v2s1q?o)N|Zk51``z+`hH zBO@hHxq^Hgh94M&I!khz1)bJ-e2`xv5r4e#K=WiZpr3wpdx^GND>NG#)Wh!2?lbcy z5HLU0DV`inl0_mT7JozS);&maZ;;$ug$DE1uaOe@mUfs7<7FJ@K zKhG-mc2|xH9=UJJ*6^1Ec?F#! zqJ#KWH7mlTDWO6=AmNKt2Q>2i`iT*jdz6g$J(Q#2+klz8S4^kG24yovE6T z*IS6TBR5Ofb2CnBPxIfEF~vgC)anl2-g7NGIE!&@XE@M@1Q?d6#-_YYk#62Nlbc}9-3e$ne*;~O!qP>8~|C_1045@GWyG}dtd7t+-b7>kG zlB=tvREHtm<`S^L`Y{9rDe{WtByGb7*dr)oJEEGXHLF=%sc z1zO*=d4PwEJa?tpreu0csfm+OvBM7;#|v)*U9M|VH1s}$H9Pbu`-^M)n3C(C?|6eU z7G*>@qL)M}1O+vN9$8x(nF3om$r3L8BEHy(Wvci2PKt_>3c_fK5=`r=G!wlmjc?CP_M{{FmeY>UdCEJt3Mo}g zpLTb#(=KXB6$hp+cvQDWzpu)-ReXk%if+m?qmHG0CA|`S0x1VqB8&<@n+}qlLkOw7 z4_~=PyK-kAMxD_BR91<6i@!9|B%K{W*f>c-t^B6|yGqXxY_2~sW`WRoOjZJ*d<(~i{3Hwc zJ`9pFMVmW$27xk|T;VU$_nrT| zEK;o~1UR+cy;g2yE|HiD(pw)Tb9spuIDR-@AA+nLj)xYh0@7MzZ?`#^rbsq%+5ZX4 zKN=)?G$)wV41Bb`Qc{TRMD!6xenC2?$_tr#hp*^bx1uENy}QSgYcsz;chOQ~P;M)x zQ+#Tvcv|-*-78LRmqJ?tC-(-5XGh&(Zd!`*bUA~&K%oG#abYfaXh@q78?n$xnNFAg zGpI3|Hcx6Ovw1Wuqt|lfd^~$dqFG6sz@wb-zhn0edx=7Uz#MFqhnM4z3Z8p3U~Bik zO>O_q+5P1}%*Q;mX#nu%EKrGWW^;e#GD1VV zA9X2dlAz{*$3_7Kj|D4BPa;XQ+@DN;k|U>K$TfrGFC(US4#m-oXs#k&?jx41vjd?? zM1keo*8)B;9|h}{O|p7)1Pe7L1XRtpzW79d6{m7;hX%#QaC3LPzI0=dRWOdSYK7b= z8dWosJDONC0LTR~1|ljs1M6s2uU6OA*38r+v!{}akzD!cH9Yn;dtnpy-DG|}mK|w` zYiWTl+1KfkUmbin)JUD*!3Q6X&i;KaR`>XetHz_Ag|s=3{CEAD1hbvKiu0%$Dd}y- zz)ZO>(0H?J?Z^H55@}jsG2d{_tv7+s(pn z@e*9Y`PYg@3sr(*yF20H`r8yaH`ag_sq%AO`s{1wn9;4c#kA5ipOUFY7LyisOvnuQ zU=WvUstlZTHn~$ugDsxNH6mws?B?!2?^3&DId|ID9Bm@4!JIttIA~ZQQ^1G2HB>^b z)Qu$ar|Dzd_~VDQMuvVJPg$=jtg(8kH&(X%-Q9t%X|emoayqziX)Dy2DP zr630Gg*j;k?DW;S$wI~356spbuF1Vsan}2=_sIV4=mA=d^tp6sO907lf;7Lsmg@rV z&Fzd-Jcm;rpZF&)Z{&L9FP>RX$D`_K^OR}J-*Mf( z!~-4W_n&I+6R#@8U2cEh69cN@6-iq&U}s{a6HmK^FFG%ZnYyCn;J2}ON z)4G=*y=5P?OYl_8pu3`C$j7huCMZD9B8Fd9gfgq=dE{#^dd`IYdVj>xlQ2V!m z1iOg%{r>!A0*hqLLXRA4i~Exi#KTvUxtsIsuW=D9Ar(bf~bJDNZ)xM*mM%k?OzanMbTyUe!kmb z3@@2)D^mfh@6m`%i-?(2b)Rc`U>QT)oeiy2+vUve7h+QT#HktRECb z6bjfno-NsB-gM)Yo?ioUC!L$dYnZp z+>Yw$G^J9pVSq~}lHk%Ihpi$xSTC0GU8KHyP?l(sla#2rbS=k)a|N6i5BE(mXsE;G z`;wxu#a64+2_O{pToQI-D4V|qC5BKkQ1QAd05N3H0p5a8)U;e-VyXtvfmWrT|)UXoEtKG!egTSZm2(2F8NnCxfBt&IK6IZ;GnX*&{rfG}Wf3#)UwjEx&(le6 zsn4`%F!MoDAi@Pp%GK-~W`@4rSB?XX(B?(Ax%=<~XFZRD206(KSyi6^V_hP$Z2`t? zPcCJe{T%(=-`@`?_y^wV%cJ=wrku6f4id8}IeJh<6GiSL;?{R_kcX^ zEpvyJ@uhdOh*2duF`)Wee%NwQsC{*uhBR(=8bvDWsSL*)pX+ZYTnFDL6 zmL^YWg#D}s)i_E)@D5KrzVG#6KzhN^oesu$r#qH(MMOFh`K?jD3uZOv{UY6HTci>8 zLW5F86k7D+<7vP02N_Qt9YVnKlnPC2504f25&VB=1SK^*lY}!*1LeNl-K3V8Bld5{ zy~LSHjP&f9^C9UX{x1f;=0o}U2RvxvXU3MNNKMhQuN1=29i8!3$4+_nDND4kn%N0{ zxw_<2GhSW*J$|h<)*ny%CV2pmUq>_v5Kfu1#m$i3}(gi+n z`7NYWs&v$rB#rEe=lst$D3dt|r<%CI^C#tkd2ppL+Xw=Nau6EE1APaon!q%O}@vS(99oKRnkWiK&!A8!e;_SL+YTG85e$*%;O zL|T#3>%a_^NApp|n9^we%=0U_&6D@mo@{69lsY2p;h`JTL;lWZHh`DN%5jiXQrVZ9 zKou#MB0y@9hjTG$@u9pEq`ii%0=C|F#GnYusKQPwf>6YrcV#6o!s`Qf6s5nBvM_!2 zniH6)wN4LebWpztr=rq>A!ALmr$y<~K$gq!pxI-IXLW{l-hldX8yGy1PXBM+J=NLO z;P*IJ{{XAqWyiMJZH4O<+>g$8N+RARriAj?LjI`*<{154#sM4PbEGie4 zE`p~5Ok+Xtw<6(}Z|_I?dim~3y+&FneGQl}5jZ>?Kg^vO)aw0+ohTjiddTj%^yBlQ zABqjW`kS!e*7f6T3Em-(JzhQq1ZDq~!m?y2Lkzaesr5ispk4I;)Kxq|X6BCy*7&*cESxHmO-ES&ng&Qll4Fp=&n zhNI%v-CY6g5(i4$@tr1@v^jUN}1cLiS2YnR_%Apr6`W}j{=SK95W zjVUNSM*#}1wmFH_9v>^H2b!f4J}GA>pdZDI3lE~-I%q^A=+CofHy?eTOU=ClG9Ivr)0nDP z8(O*|k=-5XT|c-rJ2&1mek;-MfmLxMRO_Xhm2s~Cf#UZ(8<6PT1lg|bzVGwUDD!~j z9Fcw#3_iZ^xw5_)YvHu+A-MNsQsqXVH@B2PJiVUKC>uW_<qFaT)mzvY|6^DbAu8cPgCRGtJ#^Ym|K9PiY(9G^BV zoNwh8IUjErbhNkLNow$K{K^|vy7#DgU}JssflqDyWZ+U%mqL*8o6j$NeSN8xS0%1q zgS?&BS)6PNT1h@xNVZ!zbSiEi9EARF@JO-*_=8o$`Q-S9#n~t84gR(|S0uK(CnqO6 z4gc>2<5qX)umA7f|4)~Vx0Bz79ax$)x7Wac($+CL*e@8^iKL{YiNV3a z={Ieqk24Eaoz)*PvKNdA9gLRpkX)Kc_P{)&`Ce&WHZ&8oxBd6|#GlOohJfJBz>4f; z9aHD;wj26X_4R!rLEKIPicENSM4Mhxw_o(nZ;np5*D5C#;6Vs4o{{|Y#3jRQ@qNU(6X|(=ik7Q*83{ScYCaB zG^xC#$LeQp_hd`rEj=*Uo1uRFADXT^p6c)aS1OfNc8Ee`hitA?R!G@4D&>5;hizR!7$=j-`=z0MgLED$R%7rWg> zVhe2Q)nv{!9nXATi~^^eoJ?;=EPDlX?o4ham?I{2o$OHXxpol;uZCyx7xGn2j^Tg+gJA6%{6mm#f{64(3?s~n`p`!A^wiP{Y6M)lD4WQ~Y-^3Ewp7@TYJ5M#H#c8KFRPa-2{mVKuq{ zJ}6j}vt0jwaygO=Iccd|=SGCj+Zoh5M5Z}i3MYM5Z`05-BREJzu9>+L|f!zUzL#{*z;#~e%mu;)S2=DVjH_)A#Pa&V3&Gc z6-EXSYd47m{9EKKDT)WTv9VG4(USOp&_qI7o@7}L{sC?W4uzsDd=fXgn-Ivs%ey(Y zP>_W7TwAI{WpG&3O=nCeEBus8t6Y6K@IC28dJqv2n*`a?9~gl!6STcIOK{QN-a5Hj z7%pw&m%Di{QqFf`M}k1;9rX*}?leNxi3f!z^EGbny{K|MZ~>c|G&txBhY#?87u(pX zs;U_DjoSX2aT~IerTx7?|KoA|My!mC!qEm%Lg9WVY;=cRTPAayAkH?Kp*gXNDXpuM zdy#}zd{dl1Jw06|H-2NJdB?0y4ms@@!^ew6;0Dn!LY(;?T673Dy6WhDToEiDltnc< z5aKrGw<8X$xNSWIcgg{qeeB|SZ2ar)c*bYrZSW1^16GSJ3-1eo+BYtap^t(+;XjU1 zz33pK1cC~2nCUxV=jRuB7Mx*}b};R0Vk(@{W_&Mo20=W*P0=fwI_HA5J6u}YBO$7C zwH~#?}t()ozaR7qs*JY>JAM!t%kd;Y`i@sj)fhTd=;V8Sn zR)oW(C9?Q;PnoI#?)zjHSdv-NOyG9?L9u(Vvzv4nS#}WRGU>2XoU+>cZ`T83`Q;|R z)q!uf{Or)yjtKi#zf$wFhcSDeAI!=7UIfQlp&dtGLftmi!RW3~Um9>N-xc9;XT3$? zI$z(;vA_z#rmb$DX;6K{;Tn0_q1j)|*A#ITvQ7hBTBQ12MP0Jlde!B!t{y%6Urj$S zx}J0;ez>3w$DsP{MYX1olhG5OgP=D}Bgv_~m~{S3ED0}zJe>ju3BG4CIk8t<+-=4f zG3%C}hD}{we6g`TI5MHFf9}`wdm>zCgJ|JiUO&#=4O#TRxpwPArc4`#G1b+j>hGos z8yMHU?BUXer=`QmX4YUWIpjV~H}}5DB3BPY3n=jjcCNjiE2ZH|loUO;|3ZGlWd5~X zd$Ucsk$SYk^M#k4Agm=Hx(2$sA3Kf)nY}1(I6gwYLl`uTjI*~sY$la#QfR3CAm8Gm zG|7I3UYCcqlk9!MeZfnWWX~xZt!^%s)6orP28O>r$G-OLZuRB1ZddJjS(>qx-{q%2 zrx>3oi-yrOmzdRxoqrbI!suvpvtwj!kXai0hGXi5A7baPN2X0e4=0u>KUs?s1uF#({A`!otu5NCFsGJdb{%Hc5QZBn|Yt>B-72H_ijUxdUsL+EC_)cJY zwlJ4*FY!5AJaU`+FB#s1sOfB1t^%L*o!~)w3X{o+rL+945U-~UVUJg4SeUk{UtAoN z%yv2J#|$iaKd;(QqLdT%(t|h)uL74vqLLf)!(97F*{Vf9Rdt_ z6kLfy8aAo>Sv)4n88v3-EGRtQD1*j)RiwM7IEE^h|G23dYZ(->N?|)*@^c=hzeZ)phfBTAf`?wEha$ zK&Pcg=|;<$AxX9$;TGR)qQC4tF_?GQZU12S_~z9tcz(6mX42y7%b(c;`NDR%<3`T+ z?^rwDNv*Jm-QA}o20S@499;2mjP{Dg=M%?rK{Cb0EhFEu)54UiHGq z?M}+F)x2}4GUNSW@-apihA$cnOJRM>jf$3TTU<}lN|~`!66AczFFNu)sadPzt$*j& zE2wB)3?FsL=Y&XIW=nW>&(Qw&_VyF4epw> zVas4xG;nMnEx_`K;keg1TYlVj@ulqMr?p7wrKrxLP`Q+x*5F=~_)PNKJF?&&)L4rH z``e9HPMkpsy3B`!*G*j`;7s?~x~(w@>mHT2$gZ+)pSM`j12 zm-rKcl_(}%HTfKzMC(GXJ;85Te!pac@2kE$e{AiXz&CWASeCMx8{j@PepECPl}~=^ zgDXer$k}QTBo|Zo17Iq}%+?9VGe&HBHJkc6Mng8Z>sNAvD7|LTs@!$PewV8{thXFS zTe}!ssN#P&1u0#a?AthHPFpWGn5XZIf=>f+pmH@=&1gfgKdKAp1j$G+ZlVu|FcB$LA&CKxUz(5xHF~X4F3Twqb zlUeaS;)~U=33r^Q79Xwa;8?o_Z^0#p5Z>$KXp;-6B+I359k{~)1>IBF0ft{ANYKst z${E71jaVFJFO`vNr8bmiPb6sn-{0PKe~n8HuU{=Oa9y|xE_ti@Q`>?wV-%PF9np0& zoU+tQox*n?Wb~es|&dWIrM??dB1Rhy~y8b806;o-V`oEI&5rVG~JL( z-(>M*d;WN%!Ebzf3@>ciI29KkKe^ZyZ}^ieXo_i`J`oA?wZh;f?{c-}yS5M6UJB8_ zBZ|tfBoEOlPYpJ0Z{pu7_qAbg)?cvJYhQ#h+x*Ua8=wFBX|^w7++Ng5VQJ&U)=a}BJ1l5yIvTWc z8`3^&>X%>5GhtU)mE;-QBS}`w>=DZduA_D^WNFYv@!$CHkrk!piQ+$GtDp1_#l3{E zY2%Dp2DftcP-l89nlj4^?D6aW{yopTf584KfgCMK!&xs9G7X>o)M2B9K1LY?a1>D z3td#Qyr(iTuTZAoh7q?AsDq6qDl*dCt;qy$etfVFhTpI57%lCn3vbcr)xqm^-9^~TM!u;r#EMNQ7M1Dwf;5p-&bP>LMNhG=XB4A zK6^X6*w{=eQV(PQ+-f6dGBH=Xa{2P`Rvaw5$iLzbyo`j#?D?J^AGApQ?($3M2t_|s zV4weKC5K%MiuMgV1HT~YK1=Qv`c4t8jIRb`#XKR!=mrR`AXm2 z3)}){NkCaTH|?@Ed4?B_kB`5=Z_m1uaI?fo++53>d6foiufQh9$s0sJaS+sgn~U*^ zTavMX1~Grm-RG!G7hPR1ZJNR1@e$npq1m7gs0zey6?4}qMDekI-?+Q($~8GX?HU*u zxY_xRRiJZ*-CxKWy4aUH8Yap*X&6T_NL>nw7H}sWGX2%WB|eHEhYDjtD^p{C8zM^wICU@QR0ZFUHMZTT7{3(=s?M39z2CS=aCN=o_xa7OttxQP zC-E?zR5M-c?Px?YEVXcL!U{AEz=(&7I8bT(Y)kQc>^x&NI69EzS)}6)UIE<2H#FnF z_|CfFxaS5(@c!TEwO_RLGwAiw($bgs_X8_(USOeLGpis4G#+?NTs|J#zxdP%{x0F9 zZyBo^nkNf*h-$ZKC+LrR(ja@%gbO&eHETu9wpmykoCWCtumv zCZ5{y7hdw)^#JEzO+B ztDUpx%y|?7V7j<^X_r8}bCFhX65a-ZXbL`F&3)6Agvf9eNa*C2P2DiB^L34MO?V^? z_yrnvdFCA#R-`ft`{;63Yp73&_Hu=?xdgxP{`v%NN#vweq*B1Jr07m=Q5jweu_v|J zMx$u0Eq1r~{1OtU9TSBvzeopix`*5vu`Nn75K3tU((_hp#;W%=G? zKXW8p-=70m%p_Q?*0Xl$zs`zdgXkW?RSb&hH8>sK9f+#B`%0#xW>0?4x_lI|bR*3x zodcCaoh*OP@tkhPj8-?@4x( zkId8nR;I+FVWPyc2^RYewGN{7 z*b;5hzIJsJ9#6C&;7P<;=(b94Q&)%40YbG=t0efe;EruUYKws7WZZy;2*jW{9|pnV z$|P(qwD;HzH12;BLD9etzbFJ?-+rpZpFf~9+>E_jfzaj7=leGHM;4^F;X=dPuN{=N z)9Eq0-h-IVtu41Y-_3~~IMLeL17In==q)_NO00Y`y&Lf|OV0iw>xDvYGOL`Uwjn9Fl& zY7Q~&n)T6A4bmezTV|D`dB*h5|Nc>Y1g#pIJxRP`Ou;GA%a)T1e6t6YO--{Fh|>ey zH<92M_M7QKou>pmbf$=b5D&k>`M`nA%{MxfYPapq%#zpA!|s| zhFwnD?p@Cw3Ic&?x*^a{I<`w5;21;xcep7=HtU#5t`7jmf?afV;Nbsu0W{l;D4PmE^CW4X0p#~=T{D49IbJdU4bvFXZBGZ+@CN{)u`t z3@)c{fsQI}+IeR)i>q^2}68j)`U_jQKo}S{+#BoJu1ZkUeS_SUQCC1P;u^hp(2zXx+!}T}SvQjnEnY~u&$vKl4{ViVtPMb>lJgmmE0oq_ zd(+B)f#b@pR{qwU04V$Lsm*K?Fs8?op{FMY>!Xukxed{@G6vmt^lCWBqFDz(Oc_md*jRO`W zt(RZl;-LMbu=^6XLTBP6d)>|yR&m>MvdK@owd{=AH7hk?mX=l1fs?dVf%ry~=!<(6 zujd;srD1=Setf)st8i(-7KTL1eC4*xKXtF*U)I(^y-1v%ha&b09-TYqi z;`>q|eLFCDC^SHk2*gx@q_=*)z7xok9%NSQ!|gH`%!T8XOBRW0Av7ETwqS!F3#Q_jYz@_I}| z6`W=!qO1A||MsvJT?nygOY5eTdX7qTelNR$rTFdnWC25PFqP3WK@g&#le3x#exwoz z5*}uXY#j%0^Y-VD-4iG%Fq1frRiF#<)In~;YCRWK2-uHJQ!@zQr9cUAE^YAbL{Rjw z#S{u+D(g20vm~NQU2KrRk)4?FGrjWHWRbeCPAo=brO}@!TS4=!?nbO#_++%SzTHps zWT#bNxHiLb6*{+`a|+iDs9X;VRs--EichD($C-qJK?As_(SNZxwrG)?YrD{?-^au0 zYTp;H4tHk4o1`yg#lI}?alLb!ZB#hVIAR*ZdI068i@v8IN^hpmo;b(>!DqXE?+F1y z-Se+z!Jb*3t{G0EPp8nuSFZwQG#J~%yEzG*{OT8D+G>yxLymJ1Kg}E9K6&-RANz11 zNFiPzgRnhiFEojVsM6r#>Biu|L-~)w=1!!|rqgO%3pq#88HzfKnO~!{x>Yh%W01~; z#ypfzO-sp-Xvmz70O8GdZ{_!YKUvwL7sapPQJ+g;02fTd_LRJSeN6)w2*$t^{CBL> zN;YP+a|eAFJKrS}?C{H=_;M>o`5s}Hp%(zcn)u1aSJn6lkf$S>7eK`L5C0v`M+o4- zudo7g!+CSsZ}!Ga%ry$eoW>JupDW0)&|Q}eBqBjzcoK@0QZxRxYG)Kd;>HmP+ogK& zAZ%Z=1ArQ(AqRzTtp?>D9V*OB`RZ zJ-!V$D?{$-2Wr2)RlcU5tPl}y`1H})8(cQYX?acVu$Bsp*mY0m;^5PDOZTRu^rmqr zRP~88O{WKw4nfK~s!FYw!;=Hv@vA;_|uk!cCX2hQsUVENjPtMAW&QcJ*jcH{_z zVDjt%MRs}rei$fAvo?EkFa!btM7%P{ZpgAcK%w~G?qL38Fz9SR;2w(j93hAE_aiME zgK8lZw;4D~umDGrKw%B4{M7VS_x{6Q^HemVyise9@cn0pwwcP&#sgO=}KI;acz#N_Uoh~(5N;)pB26ME;<5JSk zV90_-H-Agbx|B8^uU&6S14yfKJ9s-#AZLGd^+g@z_y7)9(fTX;?|f<4`y=NViEU_T zz=7?dep@h35rnUs{dRGB4U8Mq$14(R6oL-Rz$CWsa&NNudCAPE?^jL$iYBMTmT$?P zy$6po`}r~-@^oODhnhAkmw8Dt!4F=vKGMhbwnTU=B-%_Yd2L&IwyP}zH!QJ={Mdg7nWi5)O0iMPi_BF(% zo+JjbaT^uqTL;_gOG`NbmRAcg##BKyLdemwWSVBU!A=AXM-@2@JLNVBvSU!KJhX7y z9^L6HTLxt!l+A$J?+bhZDEMnw2(6LYX3|ebg3U)4)0dXz)j0W_Dpe-SKulp5elcZ9prY~KWuKb-8 zq46KTlsJ_=X?yzS@$a{^N6n`Kk$Xo|eM*d%FC}*O$pyhMMHP6EnG_TiE&U5uNBjHV zvjI$dI1Sdd4_H2{?A4-BvhCz|@7{58C<~5_jlBoOG`(k5$m}PgsmeFEO>2QCKki;p zrr-;MC!?Ggc%3M9o}onG4}bn69wAA_A$w8?-T&MsbqNm@tzLj_Irn8Bj|^D39svBy z&d%-;gvvD<3DeuXfZZ7^y9tQy<=5ow@86Kq^j0?>6fY>ij{kl2+M22rDrSS9v8?e> z61J$nqoJYUg;v1RXNm>Af9dDf7e>KkXJhjK;)Nbu-u?GAo{^ie@SDF0qxQ!EG8Kjg z$IQX;!NI{^8)N06-QC3#Vzx!<$cvT*Lw9sh<@~=-u1kD*v}d68Vd$nM^5N;nves+{ z2A2Rmv7P4EWK?V6$;k|985zlBuQnip4&%8EwUJ5YZgxw*J#IygGo z1NHRvqsg(cJC}+^EfMCDQc}x9`MP3~l03j8y?|p0Ek(n4FW#CWMw~wzT3W*N`F-T8 z1l?!Pl|5QtM+}EB9({i_T$Pd7zaWb%cz#F1VG#`>#~(j_a3V=37z!&Q5#J=Dc>Fh> zg*wfom}hWs5DU!N5)Owi8HOwy+BrEr2CSW)TEoF9*i1e4fTaW*p%?n3sakL4=1{z; z>32f|gC!7p6SA_h&Xx8TYT9}Rtb!3&J!!9|s=m%*vg&d8>!e_v$j zqYfJzVaCSBd>;xXe!g2*k9t{5DTxnR3kQctrtWS*X{mN+ zXXg?ii+_}t-vYfeVq#*PoSXoqQ(0V8dupu{F=`(iZ2q&ZZh2$8qC%qbAUypH!@tp5A= zzN16=s7E_w;ORyy_s7!9iMq!o7&P)Dusg}~#RV>-bJt@;!E6B7JA3wv`fnVCzmSUOQW2aPKa6AK@YfBW_=d{pPeUZOO_-P$^^$|=lfymnx=t-XDs#b+q*Lu;Yk9(bae!ucF5B@Zv} zG9bzjOHsU;cfysmw6uC+L>gK?Z&S=z?Hp4RBQ1+GR? zW+uC_si|`_Uo7439&Uf1KHl(IY%;P;EvKo;(!kJ=BH@aS7O1|I9=p1@(5Fg@i*r4E z_)uBClMwR!dEQn1N))OGoci(i!aW6r2Kz4*G~QM|8~gkFDbB@+(vp&1l=G;az5Tbd zh_9D>Ml2ka&TqM{NRP1&5iClieCV~mT`KwHDETYVa{G&;I(B2DNd90**9#<<2TBJT zP5TK9-b}v?A^ohAJp149v_3ZvzXo^Y+$- z!q?v3o^oOYUH*GlnAcL|ls8%d+sW$Q4RS+KX=xuwfA-)9|9qAi+%Y~rK3;+XVpP=S z+K|(qf{_30IifR@L04I;sYYQa-1eTDl}%*J`JN9@e2!sDmQIaaseJmcQ_*AY)sPd4 z^Jd)7_HFGq=RcS&I_kP# zbg_Ss^6}e`T+uo9q*$@|9NUfE29noiagLL#6(4JDW0xsQ~2aQA;^0! zyq)^#qXEf!_a9`+`MJfcY4L8pxEivzqII2_`F%-=unZ`O+I&E3mEgG&Xkl_fiVc#u zRO7m{9!4wy*4+!>8X@N%P9~4vH)LPtS-+Jk_!1rwVILCGIRB+jpYtvwu(s~z=2yS| z{BaX)5?cJ58?TSOMEAh8wgsK#+G0}MM(7_LvikBo!B9Khwkxg&kaHBv215^iF*Fj1Au<38 zLfbzy^Z{5nMUSrem-B`SS{;tHYfunLW(n&rjY& zt8iC4qdxum{hOh@zrX*fQqkf)49Fg5`BsO$> z8dY}#H*kFj+^SX01YbDG*{)wt0H)@0t3mI!H+D(g*v#yMBQm(^sw$hDuM0(17REwb zJHGyKAx8Q2Y9nDQ30hb-Ho+^qk9qw4mcrB^Dx%sg4 z+DgI*s&d2kWiY5ndw~+9^B$>hO41?fvWWzgM-RhU89s6O`2Pv8+`Cku22S3%cJ+{l zhbNl9{>feN8j;{xHMamu(;9K*8#rt1zJBl6SgKi_ua?_X&EGlqdoY+VsQ5eZBcr3s z?NM}K!EdFdr6oYligdKLR{EZs``->zfKX8Jys&?b+Mwg&#f#Bz64G9rNb#s&;xRa| zJhjj}Hu9OEd~&{@@f$zSQeMcwyP~Blw4wERW#813WVKu*MBA@qM$-Q&W-fx89zf<+twV4Lga+%JKuuq1=}fCu&gE{&!$%ptIQ2BJ_`X!#B5a zx3BV=nYH*aRtcBeA=jFB(cUAz`gC4}p^1;xj8We$M@!6;fI!nEveoB)(&^r<3NTu$ zS}=fPj7&_`hY>~$J$o21fre-b+Do4m?Dj1#1AJCRR$_6_0zeS*q?0{m&Hw_=wHD|X z*Z$2*z!1cGO-)TTVC=w4rMUUIxVXY{UmHxyq(118oY8fS&|i2mdi?KS9)$B485yJR zXA5RU=V$?BLP<@{$ZcWlmBdk4VAyeEf4sGdQUA$rG@2<{zrojurF7E|GOW>2!>b`b z@yU-yudworMAoHPQj{p^!OO9eN5`r}ckNPCP-~UidN{SZ}pI)DZzIwVXoXP|rS5nf@^nqk*c=bhU5DYhF zi%mkFJOXCKDqo3{RSy#~%M%_}&?_8{9;?tSzq)AI(DXRSI_pW)9Wz!IjciguiO@Sw zULGDhS68izJXlcE1MaA#0Sr;u zWG@4%#UhB>RUZhQGY{xJOci+h)6>%-s324vX4D_FQQoyQ?uc}KiqO~h&y5`vqMg=qFKcf7SI0UYn4actTu)(eIot=A!`}*8n{y^&)UW-@E{3OnCPk{pa=?Jr?*3@ zTWH&Kf?V9({)>T7ISZoD?43Wi^*UdeHa0?$HQ;2oYZ-)f(4&%UBLo8*M76no9J1X+ z3IS*;DTYaek#K=QEFN~8cd`?qD0t$L#l7ELUXsP>J8aVWN0)J2r z1-F@*nbt;bzcZfm^|6-v* zOXGlC>FAlS|Bj+$On|~S6}a8-qpHe)KKzsDUy+9erZbsSqMZvDOCz82eea`nm58UR z;4XZ&et}l<a~?tRW{=(jDrX3_+>tqv#SCKZ~G;RaUwuco>kyC<1uJd#7yP zIR6o2I=JuSv6L4?rjn$j|pxz`s9mQ1E4 z7q9iFoM$5>)#|r%6$F;BLKT zfZObYa8CEOzQO6*{bP&o-@h+~Ftlb9+$6ZR1DtV%S-3K?ZC5}J}g7k{5rM`rC~UmqWaj)s<@r>>zC%6 zUWVXWq*W#y^58xT5rL*V(pv)$@!gtHcaVN#keY#9e+ zB3S$TBO@bApfEPwy70KoxE0;5c>Dt_4#O42j-U*?JO<4MKmQe%+{EbNOp6#KgZJD~ zM{4K83!D`;IF-TkxBmUF7hrFKoeLG<^ohFq$ln3OspGE>TGsjiqF@gMJ?>}knhx=;wHmX$>Et_iqB?BffRskr_;U{ zBzeQF)%h96;1%1w&68G}oJ94=3qQO1=C~&X|AjOK6MRLP!)$7yJc@oEN#~ zs{k05a+|tSZ~yFBALgvBL}!Q5nX+(YfZ6*1p%f#@p(&02EThYvm&gCtCa)^jG(^xq z;BugwO(?3imJi5ZA2?3`sbXjFjZ!ZzTBaB|Cg0@se`fQqLzgd+Ggm?&4E5L1IHeMTXtb0_~M37qr$V`#As3>fr=VR_veo3KtzoJm*1_d>zBAzL5EkAb&JST$e zh}i#-rU!&6;n7k{_d7RlsjPa>>!HA8N;taY+?hfK*2_XL&}qUwn);~Y+;DsQqpXVy z&cz*SeTHD5`8mxSnY(mod(X$DOyCO7GwjdNlnypG-~Y?rbw1aIYGV1zf^Tqe!wzdZ zPVLV#qx)^;iW8M{KOZJKgH#SYU8mA)E%4vgR*E;~4}+7wxzsTXl=Aj)_)qKKs}1*C z2XsO?8-0CzdO*jFAhZ^Mf|q#jZSP%__r5cSj==35(lsJ!aFQ6KpB%|=@$~bCsrH(B zzyC3ZwlCDRasvWcK&bt6ngTM-kQQ!-@l}rYbl5iT>bVj`WnWCF_!5@ zu&S3G>X?0}oZnn82}Z^5ou*^12kNx27oR^3n>MV}q9d@6E(+iCXzQr0ub+Clt2(If zI@yL(qgvZxx9W)FwcE{Bx&N?~SlUGVsi~#qnoz$8 zvs%FwWHBF`r>jEsJyU$Km1O zR=G~jWRLwHTYj2LsN(nAr5E*546pK*+)=VLHRhU-$`~1io8kmthn0eBH`o@GFP5Qpq=kuvnJAZmJ`r%nOZ*#2`Oj^y%r5^1EK?d1`H_N2xVsC66Fq9739(`f_n)9k z`gpuuTU#66@P)ylvE;2(x|@<~9Kkmlzkgb?E)*Bokx6JJ zv?yD`2+}2h&I?Ps*D0pIZTaEM%5j6g)5Y~Yc#jixmfJP$&vjsUbUpm&226LivHdD0PjwR+*Mi}oUBczbx=CoMD6?P*6P2t|NX6%-Wg?(Kd2aHA{i;YmFJ zvSCadOg#Nl>3B+8lwX4ck1k4_k@o55tdt8U7LE=Mb{-yOPgPbrAJ@3;%Y!MyJ0j4)mK`|43nw-JY)&oV4Y6v(-MtM?i?S&k?qFJ*j)3IkhQ1ec~JkweP*v=C_Fqu&Hgd9a$5j$eohd z9S7W)(+3eJ{R++O?=Hmowg`I%hwm->v}BzHz2pY8caQ8*lP{9ZNyYJiHx!(>1nRu# zE^D2rC|TYe3;pX#kquUNYv#Ww3y7;xKEEH=!(Bq=oU!hmtt4yc9>=c0&&kOoV&U@C z^=4Ek_pq;i;*kd`lvd+U)Z644apwXmf#TkhI({*NnhpB0C3hc2A+ED>?Fc(u8ls;W zgjJXEn7dCl-;rcI7W3-z%O@;p@4E^rB}&+uhGx%>vhsHcCf=ZXrWd?0^Dw_EWVQJX zC_*@!@5C5#asmQS*{c9{mW>{piKa@;z7l8uv(JJCPL*(e&W?OEM)~dHr@dc6*D5%D zvh5Ax9n)Ciu^!}taYjnFXT481KopyztpVh4Hz>CNHkHz(9a@c)Q@Xfwu;@+g869D= zl*dqCA*X-#mxOM7W;%lnThpWSOg7OxZ%Z3+pP>4Q-GAY&D|Z#*wt?E zV}4%HkW~D3FuiiUBmXcB12|n98yk(O*50QAe5eI#luu2--gk8|)y;`o%zFle(Pc4P z#zMOKswOdJ`|%{bs9X=E>7Z`0#B-FxUV9nxWQi9$PlGT5Bw9kUf`#_Ac>iAJ z_R+VC*9(n$Ms<0oOscM?#v8R#3Wu8Ph7X5!j>fyP6bYaEBjpvv|E?I6b9T124}mZ} z{pFRDauGWfcMJN9bjM~uq^<$Q9SmWE&L!jT%=@!3Y(GYj5@$_qmGA9Tt9kr+Sd4FO zPv-vv&;~_VM%8DNurLQ3KJCB1&F_r7kNChqX{({v-PbXRW3yzM&XcA#CdEI}16VR> zO&6KSo9UlD-~0%B>9>QZ%!2@q-ZQ)XgEw#d<`>Pc@!!oB6c+A%NTV=x|E;w?Iq7$V zv_Z3!q~sFlHx*J@T4;Z8QIUJ%QHUG6G#IvwO&U5s51`DC+FIjo49e@z@Sfh8sp)AU zFa!s}j*i~4Or)^5(p4$#d&h}V%m)9San4Lm3IK|dYF5=JP2wyWozOkEt}gzpubVVA zJE|%wOQ5@$ih;3+C5yHgOvTk0g4S7I(R1vRG?gC--3eS&Si6hQH2Hm|%^KkPfS0dQ zyXW(BP60o~1*G;w5H25Ye$s!lcIiH+BLDX6=VrYlwvII*+(HL4K`BX^GfWu7y38`D8>Oxo1P2JdeI2A#C zBN6n_OR23koW}Xr0Mr7WB#itL%+Jv9BUE?J+|j4ixRG8W#1ku^PsZb3?9sbLOo1alTecMf?6 zeS2dW9v;pT@?9F&N+Hq>5~=%wXkmH1)!&MM{%3Pg(K$QYbo;1m;(}med0rfGyW7*X zw4AnHZe9c54Ez;X0V4y>0rxh{Hbt~tpZ>=Jd#r|Nr!50(36n6^m~d^&*ni>r$pURtnw7Rvm70##1gSq88Xdg@I=;#PlHaG(n@&Z8fOaelAZP3vVi0cG>TT4J^n@Ows=i*(u*8fns6?>#mcgguD;MY(I5{C&4wxbn z-TwXxyX;FfQ0PQEInw_Mz(Z;lDBu6fLBEo2hub%eDTbM5?ZBK%Js>lsq;z>UU0zQB zZN>w`!}_TY7Z-*e#tEG9_Vy0j&F#GlK7ai#s95X(j*Yt^ z#{(4Q+pqPZ%1f97`F;v?Cs0{^Pf`F56cgfI)aq*Z-t9ml z&^e9@TVFsQn3}A9T)-B4Z5RAU-lKW`aH0j^r7aJ`EZ>uJ1eMKOc-)1_$q7ITLI1ZJ z2{ADpP1**Z^%MXnm>%;U(6mN>X1SL=`z$c9E@!4fr?L`Nb0I3-RpupN zvA;Dm1ozo->kW8(sQ_XcpoF1)gedVW-v`NQPZ;}(H^kH>?%sWR*z6ftY~gL-wLF)+ z+|i!sUbOULCu;5SX)It5FRYf@)f5EE@L`%w3O_gr7T}!$U#0}Pj-}a~mKG(DTANd< znB#MX3DOc0`ju;*Pjer&g5t34Q&a)A2%IbGNcp*TxO(GWHroRQC)=_KA%%e8=tkdSkGjni&!C;n;FvySbK}%dfKEHjPgG0)cbk%*oQQ(R7 zhCg6TWdNuX{TI$~d(3CP_ySLb2WdWd3TX8}UtplKcxE3aDWyO1wbQVMWUBmBSvqV< zgnHgugMz!7mzS4SZ=O-KtMv?h?U!S!4yrrYr=Mj3K|o1G#US+0-&J1!A7~C;2Hm_J zPo*>J-(f1L-|SpcFc6G7nHpJyk{&QE$T81zz#YC8lrT7cR6bs&$LmNZ>*y{o&>@C7 zhc9TX7q8k2z5ycw(Vt~~3dUa6KLfx6l4C8bnZqOW03{k58+&hmweeuY)Qfl$Amh34 zh)n5A#O=7+p`|&X247Ihi80J|1$~zw4!AcSeK)J|$jUo2-&qrMgk{|3Eb&;BXlcWO zCa*B{y3m7@lOXH3sF)Non1Fxtd4q8ujpe1Yxwn&7-s-ECn^MHROOp_Nn0%e~Rcg-a zqX!vJJ7Nz81_l^=j$2zpA>RBF+lPCg+2Ky8r=9P|kDzLQSRXf0^0qkh^Ce+HLHeYm zoxLa8+DwU_^&%Dr@NS0aQ+hkz34g)d!#aS8X~rkJ{r5)2tHta~)+c z@dw66Bc_sPHG5Qx&r+RO$jZvv1q2vV-;m`-?5iT|60ZX7xDlIN+70*%7V2h5aj5mi zECJ;nXs%jNQx{iXUmtd@u(Wr)!g2WxXbeb+u1@?^qn%72@GmQ(D(H!8*x-8Jl~Psq zfJYz@SKprZ2Ws^)YSco&f}G+k^9O9!SD2J)99sgILTQ@cL;v{$6c583i&81Q6>kMv zsC0PwQV;NBF^}2#1>~2_o(wqZ551RG)*Pu~zQGp@YeF8W|bfW2Iv{W7Jq|057^K{EJhO#^kkq`tHZxLE#LqFUSA zIj_Lf8D-LTPxSNWHx?3nKYDcPM1^;O=aDmBFM2iQL_*Oj>kS8#{vItTGP&1P#Qdf| z&py|num{LZOXA2Q&A-&IV44{Ok18)CX|r!V%Qz2KMB=V`hK~kO&1K zDY1=%_;d!$etdFD0#v3A_EUj|6ll+YmUp2&DjffP_tL@^SPi=uFVtcCSv0QCxcQ%e z4Zqj!Hue((pxaOq+}G;>ges;$ z6H`BZzO4+INGcFppf(05XMi#nYKHJoS^NpD|Dl5ZR33(!`X*LoYA?swJn7hHv6Jd( z935iN9&%E*X8P9EiBpl|MpI*>Fhsxt&}tK7_#5cU5S`hvle77BUwLuXTa8Zux9cIs zR9K&qqgT{D>o_&4-hLRiCTd|tlnu0X>CpkAzMe~AoPpT{A1KLqFjF<8pa%}j*) z3BX_sL?x@junFO24=w2~^XRE5p6s+?o5^VISvdhc!3^~0&6`2U_&=pOAwI}1MxqmF z;q{+kI&$kTfC+v1y1D-etcN@E7yHtn_c%E@N#P5T>5xxArvF+$ zA1JJrRqDa;`N6=|%iNv$2M0co?vs^ui!K*b0_IDVtgNhF>mx!yVY}mhzVu5@JRsbv z%$h>XL4(K@iD}@eP|rojHn`fg4~VESvxA|OD<42h-9n>91s(4b0FzZ&O32^V2mK>{AVPDiLewlOacJmkOC7w*IUYXcNV zNte@hz2=!wyZub3Vbo}|O_EJ-)au(+B-#mK{nfqb>Duo z2ZUpHiNv8-6&9s^AWna?C}o-*ML25+6Im@|81C8!Zq9-cKoTBwD4dW2ml9N`Brj8z zl}E2%_yQU^#DK~hi(g@cX%_8!Jcz1$Qu=J+F(MZ&;nEFvEHH<+NzhP#j+_==42&z z63TIJB4pq+#pPvLU!}b&jdvl6)nprtltp<4iuM4(&A+wkWA{U$DH zB|YIIkqxp8v7-Xjrt6N)IQq_3(EB4qmk5R)Sm~Dv-VQP{cUpHyxH61%`TF@WVP2s` zDk)xj+P`>_U(=QHU_!wEpEsCi{KP+uLP-E|<}tr1SG+9y+*@CEW?jC{n=?0`SZjv) ze?#1L7{uIXEC29+G@W-m)&KkdOL>=(GLD_fJ_p$$E3&tcmrQJINdQ?}VzI`-K>ZH`0+8D~yTfHxUDj{jREAOjzoJk!1^Q)xa%$@vRQfkW zi)gE*pL!!`9=m#Rx-SBN1_Sa}e!#lB?QOx^lmse1KE9Bty7&+lo?p6ufi*$d)YMA%8IMLOZin`EBgd=TgbZ)BpkD3OIg89vA6z3MC=$xB(vQC&~ULrk>*UZ z!JV7E0Rz5%{T|_^*uM6B5lF<7Jw5u+ib>+HMZ;?y?UZ58(b|XJ3Ag7~UznOcrrT#b{SX8EM71~s zz(;@};E6~cy^=*pRe$&+)|qh2w!f-h7;Go5vhAVQJe*E(r7eZt{0Kn+r0czsOy1MK84@a3j+CImg8 zb&@)@!z|t$83zwox(KlXn)QHeL`L~u-Ee*JvQB9k$%{)Cg-*;FYV&!NfM*&j`T5Pqyk>5$n8n-|T;plT%9n{O6XSrS{O$KK<3 zLB~EXo!+Tww-=a8zrte;^1M{aUAA11@DouL8Oz9pE|h>u>>sp^O29un5_riHRPFjR z?03{G!DY%io1O1U`}|^^hV+{xrD%dh9ifAl$<4PK+ZUW0s4^&3MrP@Do9>flCbW(0 z6&{Srvj`ZktUJAqN(pIikf5xU6-pgbDoieC*ey<$A_dkPslgq|D*zqS$t6K={*09GX_!^Deh>adIB{ zgZds<7b|fixX6ay;m{%%<@5nHI;)R;g%L*v90STAKrjpcoACl;pB{ju`l{468)oF= z>E8IzHQ(*5zh4KKg7IT4f4~0#V#JYe2XtHy2hmM$jtL}l9{HQTU9e_aP8;*@`S283 zhi|k29ee%cjo;9MqO3IzPMLCntKxr^+tuIW-pR={0$|SlA7(A54G{QuR!XEj9&a2Z z&xo@AXtQpxgT9kk7R-v@A_(zA7jR!KU2M8MgkN;7HejZgD67?8>p2%W9=(}wGXTccA0 z5iwA23+w(FVu=yrM->U!*<-$id_)0<3{60Qw|T?@RNS9Z|EnAS{nL55zzuXKcMd-n zAVCG!DHcHeX=`gsdh+NUke0MzQGT@?49~;W8!HfR6svJF|7}iG0zJUQE{P}hxtZH= z1>oSNp@#{=7@qXeu76-CU^|9)5B(Epgfi^T{tM@qLDxfA-luc*)`$N>s-DLs+b_>a}a;l!2#^|uh*k7pvx)}9vz2bO;JlAuMJ7S}xR)kqmw zUh$i`bUMN&IpQ3m0&RuVsS!yzL=KGGW7dk{SvO2&hoaUZN(*V+KETbk62{w+!!ET>bL z^3eVx{(I<+amBozpUzc$x$+b=D;Z1W**E!Aj>&B|5jjuyh8m3H7p7Vu$)ymM-vu{?^`u4 z39}1g z0t?^e28-<+ATtiR@o@6Edg@#P4ShW4Hj}>X&jL)}c;auA(lzU5xS);;pIipF6+D5stCl1Nl|Hg?C?jvw%1f^2E zC&dGqoSyyOA=z#3r7}B2wB94-C0B~aTdEyk{x4-;6r`PIzDsu4?s_)Fn2I&JH@qhD z&8);Bkpzdv*@QTewzQYC`3vaHP_!dbGxb)=Xsv$M%;z{SqrZJglw#z0IF<%Lm$y0K z=6U9z#j5Vqn4VQ1hF4pV3bYYqE@AJ*i|Low(0QQ?Ly4NQJ70Jj!gbHrn&wTTPF4+8HS*oU#V8 zENQk>u`MsX^-y*RpI|0SL+Sy)uTp*Q5I0sEt&|}vS6rOPoIK)ZiuMgfDb&i=4 zMV2%D$E?)Pkc8#=L<7m*s1STMM<*&=wRg0Ic;$6F>R4hswws;X#@czF?$^`T$#>+~ z@N_A!bwN+uN*gKvl-@tT{!Y*1@1NDiq1TuZZwpb$4m)G2Q^bnDG3HsH4IZ43L961* z8D9w&RvfP0=n#oysa=KEVL~RVd>Wmb$k>=L=ED;cbzFadZcOY3_&?Y?_ce+{_IGYw zaqPD(MLu11jx8%a5eIc^t~8<*>tZTQbyaH?Nt8rlgOxO+S`(v?>ici`u9eYT`;V;m z-cPKh@set#I(uNbX_p9pWv8JrOA>AVuzRV#2RU8t?$@G)!8~oA{@r^I%#Vj3$yMXhNRApK0 zKl#v3IG#iM>dJ2|cv`#_)ORleUKZ8t*Gd7v$5L2BTEz9zhYB<4JqmJDSu;V+@6M z5@WXHoXXrV=UrO4i$!!1|H2rBT$(;?J;IhZ9x`yXOBx1tHS$dijJOD#Sm@s)`VZwodx)ZR8JC}{Lt)|SH{^DS{t#__t=T3oCOP}a>$`6@$(CP7QAYX zD5@hEE|j%Us}T@GX1Tp@$oQhdzX$rYG+g5b7H}((v>s`Qc^Tm1VyUU9%@{E&Ja;Tc&{H&C3Mr-yj0hy5-R-nt>op7=*8NwYi zi=OV&E0!as9fb*Ws2iI2&pDOj@v6yOh@AEClK1buHSRCH(<$C69L;8kEXUB6kQt<& zKJ{MR*P&TPjD>?tT=_EN;H-vV`#cPZbIjsRA#(CMqnP6n4t9Jkc|_oetR_(VbWoRB z#iGA+-?uSlsTQ@Z{WY*_d;HsZd*6049ft41`#q2%YnE89p(I|UL>UTmPOu}AiK3D(A7I~l#;k6%N(-xM#jZ7Eih7*}C9a~BKyRNK z2E%bFV|?s@m283ykz{#&)&!5_3&dctngGZIG~()jQ1;6%YJj2YrI(X^|5c5&et6!> zIp>HR>d?9N0l31#>F?r`XE(t|MV9t;64xObK6*LM>W8~m{OUEKhrpxHOC!b&`#O$c z|J!c&DYpE;I6rR6K7sRS5y<5i?w37qkAGV->3n#aOqPO2GCFze7l%_TnB(vs zRK_n8S`g)<1nRUIk7f;{6T5XV3`M+#5J|C}F#TTV=$(gM+ph&XVB1fiy|k56U@1!- zLUnp=`X1O;8Puh65#S74>5m>xg?YhUX$k_vuiwA5LT>oai}3$}8DkpxnbItaY>5Jy zHSw7+>**U6Qx6><)#x-FxcP zRO9V40a9ZgoE3a(`_gqsAJY(?b z!d&Dw?RozrbTsKRPE5|y-LSK%BVEDbNwU6hnl=-y2IH`Nq~$9I`B}0LiL0pwhmFRj zafACx_%Aq}Hb!!u8CU5$JbtXYUuhEDL0HXB-`U?`j;DF-D)|YB4a7z)yv|OnEBZU- zvbsf#YS3y?@sX>;x$D~W7u+5p|A>5o{*Gs;Q9QmaJHPa&SNN^ZOGQY>wX)W^Xn!i? z!-!}3WM8U(?pP`pd}ogNqaCt$hWCU7mOm31i*#<@tGV(hq(NlhjGUeZQ*Wa(4137v z;t+NJ?VK5kwYNX)hh`f#k!#?rNPjr!A8{j50?^pq107C(aLG+U-hH)`#-G){Ul>z% zy8dK}PpN~wa>JtZSs3nag{leg)y+R_+Mr9F@+}y^hf!_0Q>D4lF(4Idh73cF(~aYE z)y1ZoBFB^1e*od6KFwZv&*%)m>LY-O`SUgQ0#sSNO{r5X6y5&1p%gMUAUL*acZC%X zi}$#@Wt~rA<(-IB6lCk35M_+;!h0YWK4G~0boe^UkEF9>sQn+kwE`+`B&()tx`^kf zkdz&mU#80bO=csITB}@;Cv%8fx^(72SEtYQ9Gd-F=QKqGpf{rnaWePb?ct)OVhEP< zddOX0NgLqVC|PoiiTrI>4@f()VEK}-RXT%1kX9C$7~;;Hr%KBoR^5f;EvAouUB0~( zYBBE>9bUXf8PzX5{_~+`ytmdyrj zVe9B=SU2Y7fs}4R>ybPX*wVz1`gr}^(9BGtaLJYL(EXRaykhW}qqKT^yfK_p9gC{!KA3>0sD4 zw}^Ai>e1%e!+TN5V-N13xc zyrq?N9S2f#@mxqYIypx)XFkGg!7B*TyZ$>0k=BW%T4|vu*#QtL0@E^OhezhhS0rF4SP#)mPTLjOOHQdpFWPuft(R!I$qn@DE~{L>IG6)jU1Fj zuq8R+_sXXV5_!@8jQgD<5LXJhHYx+J7sI93+bu@({Gokl<42^&7HOw}sUY{Wx|GJ!!De zb7{Mud($|hZp3@B#SS0?R>TXCoslPL_Ui7io$t%!v zcz*vkNgVs9Wf(3*{%^nsSd#V!RdZn-Z%CQQZm!3X@vF30L{OEPTOsY%BK(xFHLX;z zoqsXP;%t7p@W|fTd-)Fod4?gud{ZG>yfMcosAVDK>TX>0w702HAK>B6PAh zJ~eHbpL>*&ai?Cld?TRI_%=UxfMM!A^xeVdA3^t%n9vNo#!Z4L*DPOKY5!FeB)x+% z)bAMh2BB>iVFN&Om(8n9t^d-Qc0TVFPg1NumQVm@*|9)2%2gcT=hpn^19cLvjHcSi z7z5%{l4O7s7{Ic_{V%-f9}7kScFZ&;$l=6Gwk-gvFbhb4pr-Z)qGy%?C+;KtMD{uU zka@uP3RpyYy5uii0k^%xFV&+nrq0cJ`Uz+7GjGAQFz)oq4|TD!feZ;-o%Ih=kCG%4k42Y<&Md}+Dv#&5Of)lT#T%mm({(5<^O07+V| zBpQZ8v`)lUe~R9D&~?g^Z9h0H-vQ3rb4JU>cI!v3{rLk9g>*nJ7g99L;wb_~4@?BJ z9F*O*P`zGCuyEdEx}0;#k*Dl-HB#>(c~fsK-b{F8JCrStcM|7u7E~w9^;g12b8U|n zK4XxuJfA3=Y&HIQLGW##5xKt-w?6X!9}Q@&2eaK%CVRmY2YIUI z9$yAwY1h>A%*n2I>iuqd?M4La;q8yNCGi6**RhDym|^PJTQ^LPUy2lr`1iI_ims`_ z7ppA8cxDCvGHJ99vNH3`mllFb5XFW@W8<0^digB@uTO5=LY(>Edmxv>rlA`fUjPNo5|Fx;@GqW=-{T1&q2ck`0OEu=?X#2P z0Bi+&w*q!_|I0!Yea-uh#*8lI4G9e+mRQ!t5O#hlYIkzX251Rm&8vE?Ee zwi`uGT`WN9Xk(@H5P8GfJCjZ)vhY{=_Vfcp%i$(Q~x>h!ZBh$k*5n~i2I%aS}XpV6_LntCMkg}<`D5=(2PEz{wHqE@zIxJv+9g|&#{vBeImJ6I z4dW8LVMo$qR)*meM$3t(I+u$*Vp@i~!}45N04PZAjrPCyH?`>!kkEZA2uGjFK`Sqr zNz(}~22fm%#hE*9%h>VWF&E$U+DSXm5IZ~3@vpJ5F(0{4xNJBK7#$cB&<<5bUkzIt z(X}~-`L2mJdc^GH-G0Z$9&Jh)+R+TM6tuORkpw!d51o^h#$Xc$Pv_wSYwRKG7)eM?UKlaZ^P~1OsXu_P8(x4Mu+)3pT46k zQGWc)oF!@nHZxJYx(c{X)!`O{B)6Q(*faN^abbQO-`$sqwm%e32_9KL6d>n|&X+u$ z-pZ+w(BfQm!sfiuU3MR|!c=P4gqt|f?_+5ClFFyge?e4~?X*%e#A!f=!Z{)NNP~0+ zm|NCwZAjJY6j>;6O|o1k6wCa6KcE(~I2_(c53W@Iqq+dRZ8K0g%%g0UIq@HyH2Gs-gloeUV zA#;I&*~t@cC?T~zF5djFKd+OXN_~o5g_)mjpoZRvJsNH<%TG;wapq55;>FBP(wIC9 z|C4{LH6^e&M6SmFZPzwF3zO$iy&)*7+?9sJ_OfCoUiHOg@ebQN%c#E0r8mzg+rk2rJdWdR%4JDIJ_yB?&rM^p+= z=qCKJT#gOr0lAPDk43YrtXa9Bb$A~HCT#ny8&Uc*J1On0jjXlezI|gd>jOErtl1l2 zBwK-BHh)_mhTuxm^+ANWaNq7*IGen#j-$cE+&8F%xp~L8hm|Cu0#TC7_p*cef-Wvk z_f<_v@$LM*l$HF|c{>mZUcTJ%K5^e!fsOGn!IC=+H^?YYWFz-UaIDJVo@US?Nm+s> z0tDkUga_`asqyJsiPQaOY?9eNDu0A{Hnj&CV?!m82MGjQMwCJkiN&N^KlHzb6Gb8_ zbx8@P#(LOeB+~`j2*+nNpckU%E1{L@fY>eRd)o7eAP`sN)PRWIRCG4!I_I`o+W-l& zS5+({Y|uC{9>pLE*#gO9B5Ew*ju1qlKlmgo@J&ojP+MxLU!eaxP}xq{5T-}URR3E7ZKl;(SmdO@untz-E=*h z-oF(8UDKZ(Dto*^-2JV_wL$+U``jfaue=x(FT9};a?XG~qA&YSs7L&3&oQEbc*AXt}H_cxthHrr8m#5iuy{)0C z)hVp`-sGQfOOWsex6o47j(3Sm!!TQR_24?%YSJ}-gx@m}GKvd&i$tU5Si5NDqV@e; zU63VRv+9N4hBoo}!`E#PdP>7bqmgF1&eAWK6bZxu_qc|Oly(jkYcGWhg??iEJtNqaUR?B5H623B2qoL;=k@Z7Jwnkl z2p3LxL9E>LF4(N=u}M|-sELQgwmr0*YP`n%X@dytigY0Ng} zOhgV5s?C8>PHU++7tg0WA`|TxG zAr!~>#=hG2SMO6KQNB;v=LCYjrx!$$J=B4#j6h~?5lq*})~Ym&M}B5J>6>ayU;n!l zt5~Pxjk*BVEN*t8mPZ2%U+yK$N~vcv7@(TU(dy2o#=2CGY&-Old=F5HV?Ff5DS{_cP(b|`-Fv0dj~3F;?C zV+!8+%OTrjpn^ti+0X`5Sr?8gFEgny0~Yoq%_d45>h5-ZbLiXtVc8n~irQ?vS0|t_ zi5>mA!Uz~vtY?D)jfOaX6j5M^_?w&==8~!V<=nT zhYW2|+p#byGGC=9hBx(7V~4Ud0=vqMn`1V`PfTPo?_%vvq$#!V?AK*$2Kv9%J(86Xu-x@|NSwJ9b;8W!y46w_jj>+>KUR(C(TFKMrS znz#I4oGI2q!=tqaQgeX^7{Nyvy;mJ%v|AQVU#;RGp3f9gk3*9=$t*AVr6pJ>`{F4C_OE4!7tCN9J7ny7E1=-HZIu90^R5`m5HS# zvviVGNt7r?IPURqe^7%8GmSdE*V^rY1{l#M3fnEBO=FFyX8Ah9kmnvKV6#eDhTp52 z*O3oj2|DmvVpxrv8ouEU)(uBR zq`PA0@7=B47lL#VTiLk?#|cA8DdpT{_58Jx?*-h!ZVZcv`?Vq;9QqHM8)S=#VH|Gm6;rhlVfXpE z+Ey2fbv5DBrOom@}lm^MI5I6T{LaD0Q;m*v$(T%MN2o9>h)}n z-IMV5i~*8Jq*q*kV|d3~jEGy%kMbE9I#0SQ7jk@h#20WHnDl(;|5yOLJNj*6x1=OV zX?YXBR5s5@Te1<)%=t4R#quyRYpoAC8ZvRRK%dQu@8nFmtrO_ z07F=#ytKm4q}bqO@xPHYEh3xOAS@InI1cH z7rAxD7=>fH(; z{1B}BLj0>H8eCp81MYvfp*Ir_O-!-PK0;+{lWBCIDjoJD*M}f5nHwhCrr?$@F**a| z5WV+QIc3>gA@y*U-y$m*QD=>yTUymRoz%S~MtPLPyK_I=>Cq2m^{>HXjlc$Eoayh2Qo_u0-5-vg!yy`3I)u6jBf z@olTNuh*tOTG{wvv04YchXjamk=AL9iuJn>0|cJld+SLL!wPeZz1h#hICM~?%_1Qe z%*QM~E8a=27MQEle#2-T%e54d+y#aoT1O3Q;~$-FXcy)H5ldA zPnRZl{OS@vrXB*67%X-UOv}GfI)3z0yFwRq)#-{Owe`N>RRVc$FGRok{$Y7_h zL1lpp@R1zmnmdX5Ar6<|P44X6=HdHe)v^!yZ{|@akqoOm=%`vg$t)`ZslT2SaF=b3O(7Yktc7^)-ucpi zba#`=I$ic9VZH4=UAzL@x5yEG?5hr=D;cRF4ni&IK%9&_%dM^EVezUsiHME8&hN%< z>($lOZ4VRzKB{Cv4u>_emH%_hDWb)VGu{hxem6`1wbRSSBC#;~<;s_ef~;L;CB*@e zydyX*I;rC}g#dp9Nik+T=cXnkv@dlfk^Oq(YWdR7Un35wu%4*6w1oPwJEJ4dq?KQ< zIj)(O?{sK%mcHuaSji1AK7L z1|Vhs0LJ~TTULygx#H6?JXCv4)txfFmk7jUu0UTYj@Gc}lLOVZU$=S!KM8-h?ujtI z69d2gkjH$j#5kXMTbwRgIRP7>2w< zlsX|zZ?(!%UiA3qe<^WlU145^eJu(U;m_4@6ZME?X^=2!GX0T2It zn&#iKyY7I=!AU=J@AexVC8_a+99D+#v{YPg6Q4BIt&c>E#>9Dwe2p;ry zsd}eMN+LjMl=;|HzyIkievv7@qr44L;*zu!xu(C%Xr(;zYd*g~+F?;|l$pCahP6#5 z{Cjoq2M3#D1-<}zP;%i@5EPFw)#@2=>3By?jkM7q6sjF}7lf9UyAd;xF#oG01)0m% z_u^VXe5pTlC3 z_)4GbJ@MeX-6jJ4o-j-Z-=;rzS%&kR0%;ZpK0Sp9F7pdDM6O#gUrdHBy2uUl`1_V8 z)fdKbS#ib6$3kDL6Q0|QficsV1-r_(y?e9WLY5eRy;^=DNDohkS^M4Gs0~bK)snK5F z&-h2%Ega2It_U6fB;Ws(m3+txQ@oCb%j(SZv3g5jBRk-P6|mtE^cOtEu7?YQm$PP@_+$mg=}_;v={Jm>ydt1Gbwfbt?SvEN=lee z5l2WOTtuP6cbGjHADq;hXl!Ii9c12ND)=%m^1AlKT!&*-8G(hJKtws}a|x3ErhgB@ zNAUjWJnqLQjV|Ja>%gQYh;qpB6@pT^QRxvTC-IP^_jGDBOa1iKQn5WZV&~GeO1|p~ z%=0W_%QM>S!D6JrtG>p^Hu5)Uy=N9(-?=)9{AWauHWeppPcmyVMVchGp;;9hBX4D@ z7OiHPnYMku1nKMl_%#a__XE)`Pe%qHxowP*Z|Cz$VKlh&MxPBkXGO#kI`K)i(G>Wk zjNetnH0eU_8$K{K82OLimsY>1sy_oG!51#r5%feGH3KJZoP1z_PDi<#^`zrc8X+6z z7Ix{$VY=Bd@Jl0uZ;>lW`cyXLKKgBAQDF328hz|rrnuxqRi_uDCy~PKEEo`aJX0ESrBO6F}4W)HMR@v%w%Ze4s&uwhGbwXQkUd{_AOlwH5zHC9t%)39_ zCGtu<5;Y1>=Z%d?fSNR#1KPY1Rs5R1o55S?kj_SL#hmo)SrQSmMi@f}1%ONH zrrwSYCp7cEFE8ypmkM~>$$gX`IqFx;fTa6@`X-bTY7z5{Ky~KN)Zm6tWYb@!UIQ;9 z6K<*~y|VtYQ8kT9{0aYQvHAST$0PET*ffc>*WQKn=Q9FpXCe+iZF#KAnhoIXJyI}t ztI}aBw}E81mOXehw-Mcwjgc4bZw*ME=1CbV^WjSy2A=xC`hGo}aHPuCzStpGC%Ifj zaA*4jBeD;OZC@I1YIyqek2*zo^6fWc%1q#2z~`p!NB$7o9;t7+*{dt>r050fjzyuL zRi2O=;`X>3lQZM^_nKi>gb$?-BLfW&>v9u%oz8eu7Sm~&wv~Zl*kLty1WNYEq+|MO z(wGy$*8?%N^D^H*hR#{0P8)R=COzVnf2_gie&iq)El1i%|4~V!P=xFYX;I2G6|2Zb zM^>&}1UEdN3UgaRz=cnz8Xq`QFQ3Fb3{BYpl@q1;-HnE!w>(4<<>jCJAo?91zpHGD z@%U8vhzk%@ogttD1^a^rRtP6T|Vi zzmA|QFNe>bjl@W8U21DnMTgDr@QBaitRxXRCj2|$A)Xq-8`F%U2=KKe?T@G4GL*ze z**oVB+@?n{`HTY3n~WV$z2_kjwrsmtFA(*bjU^v^({k!7TiEaTmznzdPN|wxMjv#Q zN(+_9Ok~1vvg4t%4gu|q)ID$fA3F!v!+J27yz{rb-A3Yn1nro8oLvjFcH>Szu|@~E zE3Z@bbM?AS9=R85Ti|{)2&Pd*?0<5_g&7<-cmf}j*4;jk-*mPrTpGZLNKoO|_ z9%K=1v~w+(if`@AD1B|%T-Vt{Yoy*Xc%&haL(YR$BJx~H$Q#fxy8i4gs2#liAnNew z$SJ&Nq37$2(trr4g-$;|{wGw<%cDzgDMb*J=2^1(o-5u*h%~CJ!rX?8E&M-BngErR$SIjd6OV z#b{=Xm9e&HhdkWhtv`P8JQemP;&pHjxFkwYqr1@(e<+i+%ELY3!)6@j)!**ZiSuMZ zRmFRak-I^lO9kX#ZFYzi&swqTY(^-egL*KQb6OK*rR+Jjs}P+kiB zD5Zk_hn^ZuPB0SEc*^l*KZrDDc==`@PuH0{Vi6*nl&R8 z$9p#lZb!TxD5OKsQz^IpT%{m<0KN@l3)+=3g(7Z&=eLcm`2kZfC)+MJa>^$5c*b9IqFJfKi~@_l z_)%}F_SPynP*o2Vp9C8t&}%zrXs_)V*<;uUh^|W?HZEkT9oNkZ+5g0_AfC8_nxGdm z$<^EZ3JCEp2SE?+O3FaR&t6bm6VT<-&7|GTERXYdnYAp1+pd|3##erJ+BN0SxPP;Lz2!#3%m#T#-OwO4F@?%{Om3j=}$z)HR?(t%F8Vm%PF=T?Jt{;cFS#pId=f zs^y%ZQunzG_D{HW60E11qy@>G1wu(nxycbs0y!kGN-Cct$C?fDk0Zl&?GT|Jy>sK~ zdd$@AqgB=2OuAv8<4ue@=wtF0#OFJrl4$yvx8840liM;CLWd%bnvdvF%ku~-=hb_N zr+U{vB`ht3B_Ftc?U|%Nw;4Fwk!`={y=xUgg1u%qQW$=0rh!U>VpTe#LJ1Y24t(mz z5)YEKm>BVVT{rL zpt6O`gta#5I@ED3B2f>eVhn$3gv#F$_ZjfzTeENHL!qWSb3g@QtvJN6N zqg=9ddb1xdc?CUn7gHV&m(n8xQ6o&Rvn)1Q9==DP?eq`RC-=bls%^t>4;X_9_Q9iR zme6VGc3EA)2y<1M7p=*%fo`|?9#j36)k6#1Drehux{ssRLEU=eY|biMpjArE^jx+1 zQ%4kFMg-Q@c$WXtaua?Dn8>`M>guF`Y!}bMv}MSDDK81Yp10k7Aln_tzUp?!-|v1f z1%t?DXJ$^v{hpu10nS@ z$tucfgg366d>nQzfWF{T?|t{8H=!oAb|4LBAIr#mUV7F6{pO|gbb(=&0Y~|rt2tM_ z2<#XBk;Txp5p)anjg4`ZaPbgwCi?Z0x2b`F!MDTVcLlZ9pi7yJ2pWUSNU#fY(`=~n ziOaTbw0@-Fm3+&~4gH;#Bm%}1V#h8?57o1QGrPifH9^A~S$>!9wFAbsmU zA$-hGgDkPoEb{m<&c(D4nADI4OcGIDn%+j&dlnM0g7iyyI*Y4~h$v_OamJv|BFlwv zFtOUQ&dY%KME6+anYLiEmxo&3(>uojK67BBfdGl--wS|0HO{LYHB=FEQqAGF;h&{c zTh=Orz@os?VP%Mzq2QJ{+d`59xDY5-I->>kiSxgGdenObSfitVxmz{&8k+xYkcja=$o)?@5P8!9$a?|odA$D?EC8EF)tfF4OVSOExxcor zHv`FQz@CBf`g$N6(d?v+Vae=r*^HUcMVPy-?i+J^bQ_5K)&!D_6*T@NFVN7^(-(VR z-litoA`O*lMf6`*U5vWXbYV_xt4NeXWSuAGySyCqU9J$V;E2-jZqoJD*mJ_ei5s|(+Xzc1LcxL_{! zM>79rq)<0>MD>Gj>Y+aO%&6msZ#iiw0~7ea#VbHs_5#~Owm;^~_b<(<5n7yH)wD^U z9%AEx>m0#Ht!@K)LD;|NsD$$37a6vW7DTM`<1;Ac}x~BWClR900 z>$V5#tF=h1sA6-W<(B4m&De3}!|*uP3z4oD9G~8BjNF)e@)!#jN8{%|1`dx3Q7 zBo_YnBI{4R>c@2}y#AhkX|j7GrZQT|caj|~%m|zd^+33WH8sL!SHsK-Sa$&A?L%&b z`P?n@3bI=QBH90i0?zoKZ*JVY?aG^|1?*@j*BcVL4ygPvGV@`Fjd?_#MmM<4i&g`c zc!s>SWOAaYr4hR(<=ftN{Cl@9M4oT3lH@fNuI{!KY5UBQP&@xSDy_Yg+Hc?#G@1P% zyt;@$UOO=iQ$>XXorZ=YH<{{?v6H zbY0{+Zwz;%1~Z#=pZW8z3YNq4jwq1=8ojP2U)C!z42JX@8QFjRwQ-4FA>}o%*<+Ym zSd6V0)DED9OY=wyi>Luni08k}g<9-RKx^Y}71)Kdxvc6_uWmQH;jr{*dR70|eo;f4Ay5PSOTWy@A;{$JvRsKWmy1A=D!3CTjTCbQSxL zQLR4vS?{p&OUVHpBDi0#^nH_nO=d6J>l&G>MI5Z#tY3cfn3-Yep4L5$o1YQt*C!Y@vVIE4){XT2WaTJ zvHNr_JOVdxJe)bblfAyZq+MmMou%mnSYfDQsZRR*881LdbS7*5dnlf+(ia1KN}FVg zspCd18->*G%}w0lPUEq_EO@Mp1A3hG-yeiCA66I_6p8@_Bdy-$;^vyZ7%3tP8X)SQ zEcp1BMj`^n{0}NIrGuj$G}Y2>pPMwjV=H1PFowC^ku_VnSPJoqvYr0V*e0!nO9 zJ@WYzt3~cqzb9VPk-N2Pw5e{%Fr$Alr~ZCB#NR&R3MKwHFWv?YC!|IrJpzC1NfQke z3K?;_>wVa%-NVoIA7ZxQmGr+KAC-7;#5wb*)(%bR3N|+z~H8oa^ON4D<8ONYC=sfWRL|L&Ebal_iU&D_kHz;q|Scb)x^n*-(h zbG-;L5vX06ltqLUJ6A*1?_H8@T??&JCTHSKwzUe{B&Ja5#o*(#tH(Lvhn81NvtO^0@MEM;a~# zM%Pt(I?k2wOFnUpW2CpA^0}A$aBSf$O+PDHkL~i&dvml5&qQS?&5W(0YwZ~*LHiLH zh|oJYJH~*LzS_fu6UAayeL;AqmlYSW(WqDXdZ;a9qm@jrdnnzt`7%+LYJa;{d&^Z* z1J%lRf_vvv0#*teXsZPu^dV^^xyfF=rjRS7-{k|Y&EW)hO#b}!YnyHx*8WBKS#OR4 zenXlJTHI0FpK*i0?{?L;l9{ZdPO*UEZk^!{EQ5a02fp~+({7RSUb@pcUA9>bY#Q-l zfXIkFZHITxDrxjX4ddic?4#+s@;n^8qyCZDPb{toV9xjAkLD2>11;6#dbsFT9g4c; z^Su15c+J9gehJl=;_CRr2hZ^NNj7lDXV)bB`%!D{wlJN6(f!Er=wZQkB1C+zVZ$vm zCebk*iRYLsiT;1y)$}mNsy~a`f+(=3d6h&_6o|6?BCzGydRMmMJaK>c`h69_&P~;{ z^SzI3O8i3X&G%ZJ&GpJtl^61~!5V~8X0Xd%mwuA#Yy~Xc)ne9UU~OaLjQgT{th_QO ziSE@KnzoacA2RIk&lM7Z)zf^~(b58<#3aas%w<~W8v+*WMymd$w2RB7fWVsKWr0zJz*)?(Qes4m zCWxn?JxufpSxYK#_n?}X`bCd-KkA97!$`xXz>ABOPdW9D! zrUJ_EDAVwLuGateeeG0S`#IPdCD47u_aLAkfeYs1-ka@GP2A-sII#6Tp zxE*>W?%s@P=9TNrsg@ozL19Q3Kq*vWV(8Yey1mAo{oLjw;Ga#q{d*-BXUR2%0kBam z)$~lD;k|lDUz>f1+YRSX?<-BJ{uh~dwKAa}f0$r_`tQe`3=>w%B+lo!1}}BLcVGTK znJhPbc8@82BbP#o#JSz!xW1yHV^Die=Wj42L~>qfnQ1E^x4Kk=Nva3S>-Z z@#QJ<3QcxhI+n#$1ZO& zVxaHcD&S!$P*?V@P-|`SG_LF6W$4&R0fUh#d6U#uh&f(uPDx>*ZLBdz%1*^A6)vXg z$21*Bt7V#}KY`%)Nc#SLgNQVipa>Mh2m$_DepEi3?XMYO7Xt7f zk_>A=x4=yiytCaH3Ti9ELLl|t$yBFA;z+k)?7OeGMvFE$oc{glV6bN1@oV zhn%f&sybFmz1g$?==&IIy2p%owHm3!D~sE9#|9Q3 zX#d$>lMSis`i@%vGY(7svSgextlc=WKvON%uU#}kEiFK(YtNSgH6_&6^pCcwG@6$P zEvC>i@VU_lh4Ofee*)9<{+j9Tbq4?@Z?C8?s3r!WNPfY$(s!cMkUjhJhdQGoiH}r7(t zdROi!aP}yujU5X_;SeD4V>+{!EftN>@_S6bf`03yOUI``H3`g%U}-~&uo>qufxRiY zQ(#&q-f@HNC%Hx6s@0W$>xcCd0;rk-MzBi?O6vPpXV@?2^9H(gBYN1L7p(2)poH@uy}Xu`M*leP%!fozyH*(;%C9oOT&q?mV!g+Dy{e*IT$dhEX#w9h6U@&3 zNKFTDCL`K!Wka783}=;Cd=O|jgTS6Y`gpyH>R>8YLs7gDh$!Cq;l(bl$=ORG+-SX= zXIe|!wBXm>sqyNd|D?l+FQ)RCdHpbuJYVV&T^oZiJSMtgurNx|Sh15ucxzd%hEAgI zGjuWOMS|_4w!I%8C3d+nZ$=)lqSci7T)9?wwpU!9$^gYUh<&bI4tm>3OvKy~cQ`41uTJY)V>tBTlA5*+sfH==BL-@F~ut~vugG3j&n%D+t?6h0ni1nqK6VQ0b~@_(4Q#O4rM?WO7{_ZCy*g+0sFs&VyaWt!%Cx%j(~jQkn}`Pkc3qR1x0M zGwREHnAJMSNcEkJ$kW4Fo>Zx5jAz%;5F5%%5Y~OuH!W{Sak!^fTWsh!C0R?8KdMm$2r9UfWUC(3LM{yjnMDRd|BP%5b zsWL0??g=yqJQ7lK_XlIimj8ro4$JTfv@aE|PePhi$+ZA)GTFTK%CB=WyZZW4w6vid zCPef~2{*Qx&BtOtBpe&&c!udh1k*IjN9(+9PKHx#t-cVa%DUdvze5Ta!qW@PE8n3? z;R<%(-{AP-Gat8x3Rk??LtC6d>0zb!<43>JvMM4cb3D)M)!a<9_?jA44wTct=x^^$xMkV}EOYRriKRjh1y@kO2q?$B zbV96Yqti|B|0=;U)Lp)$p#I}2z}Pv6o=g6`-Ts4)+2Qq>1rv#IyUz4Sxsg_!gRFdiIo%rhY_NO9aT6i7*6%m zdr7b7sH5i&XeDW5d$e3V>W+I!@itREvlH)3R@Z*8}|hwBRSd?jyx=dx)q# zfK3D}9ab^c&grUHXQ1)<2%p#@R5TkD6Ro@kqXr%Q0Ps~+FdIkf>)^ZG%X+o3_@?0) z*S)Axl-c($*|slH?S+2iSP^|A+P!wZRUM>N{|m!;##zc!w+V774Z5=nKMp< zAQVC^L^KPw#+f7_0}h&~-=I|m#o60?OugEsu=dq|-@j>>&YUPQH4PPs z#fFRMU0jH%kAFmk!hrX`rPe(5KEP$e;LBlZ>Gc@}(l=4`ij@pAxNlU{hU1iu>4&s# z!K$#aoA@btdxqq)_n*0bR;Whhg|7i`KASrV!{97I^WpDsZ|APp^PJ9&l)fe zOtfvXxO~}FZ@on?YYrGkbd%>F4X4Bf}|^`LtTImJ3Gw zH0fb6=HbIN+cSFcKpDf0egdu7i{2sw8j9Di4K4);=m=RyR5~~=?x+2bi&VaXpr)g>SPdBbI_AXkMd5lxU0^yo_-SDAvojF3s( z6hRB@*VG~WM`*Ayj93juSMei2y_Z9L3m|wA_v3HGzz?tT&;#*ugOvJ`4ssq}psalk z6K?SJKi3yAw*6?nOeH2(8b^f0sYNHS3_b7hTObiV#LUKUSBq*RxD;|Fi}g z-DddsG8teUHKNbP zY?`!nEyLprid!AVBb3!tPd9+eBeU(Q|B(Iasm(*b;$*aMJ<~`lK|I1we@i?S<7N8yJ z>F_WS*MB9^8G%V`xb0G1l?PbdvBcMcdL+^wRV2Z#EXk zpXMqNkPRnt9#siVqTi30s%?gP9O4OPsFsCWk~>KD_TU2-Ja$@RQ_oYr+BEh(o+;XG zMOzvkI!p@T?{H+;rrS<>Qk7@IRtrobaQ+WrVA(I_i#q zp%CXoFHAc#%yq_tqOzTEn%}W<7w;IS-kxeXNMjY$RRJ767>L`-{wk;P{xO~}wF6^f zuTA&cgpLxbhZbH@cL|}TAZ3~c+nOOP^Fe~tg-9JkiDSfYb+%9~J^N-mDvkwlNp;JS z;BvGz7GWyZ;^V?gLI<%~4JgIMvz4jhThKi{jI}gflr{P0lv~^qd9Z$ildoe1*o7t5-H1ykX4 zS2kArds|QT9`I?GHY-e5Q*&>ul4=tf2O0Cz5ue8eS2Jydqd4Mz&gLedRmDT&zM+Li zd2U>9k?gJ)FXEj|%iv2%3M8{hPO+WiQYG61hC+%@2Mx_Zky@I?G&y73hj^8^hNu0tOF(5+>&uc%Dm;y1h)c}(i_@^>Y?Cl z?T4RQgF$39fuiPB@dV{Fi=3dVpPFIv2t@c~QIf-VcH)Y{nkV&=*`RKQOzp6$ybn^> zMm2QA4!gU(EADnUacZe;P%Fp`A3FP9EktFT-6uhUU9+J7=;w`B&aTctrHGY~ddu#G zmr~f0qq`~~R1iPg$D-}LVKYmhK0~TCbLe-}nkj3ZalV|DKB>YZP1vY@9Bi+s*mYNw zR&wmq17BA*QZO$)3qnoBSLr%S$|_q$uD*FkN}hj$hiSQMTQFbpm-P0Y*7B5D{LimA ze=@S|8iIcylK9s42IaKzBn2F#K%1ERilQ}pLYBPRV?C!&(5Km3mP!8KDg*rkf_DE{CWH!Fd#NiCx3$w1t#0A#^HKuj5x3JX zD&La~m)5sBcUDiEECuJ3MOWzr*kT#Jyp6RY-h=ch0Y1l2Qb@H`Qwt7gzrdrk6#64x zd*7~!6uA&Q7O^wQ2+<$Am&Ob*iNu46qkuBJ8p5~PJd820!H+)}*0%^!%&`z;+|;%_ zzpdMI4Sj1^tJ1U{{0S#ZzE+XvTz6*F(wlh49VK{$nSB4Ix^0_C+9XeRPwF^<^p&r- zcf+1f+gcFtaYu|XHPkm}OiC+#Qt7fH4jm9vSGoJ z10uf#4V1$3Q76i^xW`_NE^PJh`{)bgBJbQb1> zY9{DHp1Hmx4z-<|*M}m{KUjrgvdtbKp*dct!c(YA%lzSie^pBJbkUE%;d?(G1s}M} zW$ebwt+TTy-|10H0ql|%w@oZ(zpq#EB~sqLxpY4yu9oJ9q#3~e^cbp8`#3lHr$C!& z2^F5u4St!yKwaMxuqmCgYUb2QJ>4EV9skAkX2M5SZNclxijN(_Vc6g258xK0|KKkbRwkFSfrSj&(b4df0KWW9`d29r4k`JVX=MY9$hBs75WQG zpZ^K-pkIqPB^MsP_&)gc!fMeG-P2z#aU9wC(%+;xZh8xNwmZC4mY;Au3~4Db(77j% zypsh~9jYg=6nTE&QxMry0isJ=J3EyLb{2?)my-taV7aGNSZ#W1<4~x{vPbd&I)9{6 z&Xm|e7wDdS&fJFdrYDS6LyY}B!MWgD%Joa;Vz+%w=InO96`yhD63eu7TL(C*OFGqo zy!h=AQ=yE_V+@p?UTp_s8&$I!89K)D0*!*Z_qg#xLxFZdsE!2N5EIEDM%}uS^N3I& zu`nzf9?nc$#hrgJNa+{cb~>_~@N7`awmKG)dc}pNVL~=m0MeM;AD4J0M2ELN&}&CU zjz!6tcL)LDKx!EFMTb~1syZZ}h@@=5(5nJ6hYVl`B+W`y74mSs=yu|p;?g*3r?7gn z*e=UwG+6Y!h+TO%P(X7yG?c#E3ArLjq zmt*vAbd*#aT5Do|*75feYIk?6GvRdm+eeI?I0~Abwet={;e}k8w%nzD*w@jeHZkLn zZ|jFz7)C=FECxR0!GlnL8#(Gt@-4c!AC}lLEvBi{hAZTV6w_;9xoH0Kr@efXUu=>$ ztoI8|$2h6sLsb{d;PQS>I7_UZUh)w>#B$Mn%;7at2E(78PRK5s3$f3^J{2sRvSxV6 zFWX|{8YpTcPKXgxV!{L+ENqR5kmjzqy!D9j5>(=BPUzCgx?;umW-9cjx<5cDYFKYc zP?6PFRx~lR9?`qCv&@pA2Xbx6tf)ofjE zb4zg)`@s#zfITd1n3#OtmQQ|Th&fSvGpF$bVRj9DgcefHU7S2CzlqA^VNExh;4Yrv zCj-FPa)d&n_{(xipz6YoEpT}C zJb9^n((l>_^n=SWK23+Ie_ZQ2ygwFAc3S6id2@&>p+JCspdCzbKc_XJ6p8K6(Qzaf z+`CqChq~7-{yDPbwqyN^%n{)5_UwZ0aPhtdC{59P>^;T-ffRttree^JV5#9gVMI)_ z#qvz&R%6Kw*MXwa3tE+2zUPpAx>3_4tv$Jv_7eB+Jd7oi>(D(Kk=$~6B`1Pa{sdxR zqsS%>kK_e{0hP*Rie0|}YHE$T7KgZG7z1J|Er?1?5?1?W@!s8BoqFQ3AQmrQijL2qK;SWm^l-s1@SwJfEbEOD+b zfg}6_aNHWtfx@7fq-}V*G#_S}Saf00n)KDrY@1HLG;L$A4 z^k!;d&t=3rSibSPp{X6-9;jlri^*a~shOdb$O`jPi9wii!oQJIlQ z4s%{3s&-#07%`D}&BwJsa;hA*7?*>4kT?kTb>*3rcDkj-fLrhmL3x3qQ{}_0F%>}G z`yJgCo^p-{_|I_9dib*?UYdYRmD;yAgQcJM*x#{{X!F;;8kzmYnxQ}4)w?<#Pbe^f z?Gw?XB7b*FzUJQZ4SJa-G@6Y+lqHEIL@`_}hC+wqx&WgT%*J~p14ssknlW-(hO1SoOVPrYEl{eD=176z5Ph zO}t3((%SCINzp}?MEG1w3W$w4Ro?VZosKt8(C&`m@e zSu61I*U+oK5zRFXAbEQ>vCzY4mUIp*(7T9VxJ+l;s70kjAW%4AlbLD~iyA0LN2ytcGL*nF0~+j`78U?<6LM;2z? z#D-~>d|@)VzjppoE77d!AWo}iJ;6R2Q@qOBDVksk3W03v!Ls}MqVcs!usO96tjJ6m zzn1skao1sFg$}x!0RpaVRLAaSi@OwjE=)0#0-FVbe+BwFI+8*?uCo|I64Yh^uLebY z)l%STrGAl-pCuj|;A+LlEvQEKn3;t*10tL=@#v_O)1^y{J9J#eZqqxTzU^P@Y~oeL zkmb}6Z!@izv_uZ`Zk6m`sO+>EpOGU8;#i!i7eVNr0-cf^r87f;`^!WZ{C-r!nsT$i}G`bP{Sm>!K_~=0gYdZQPsC??{&hroX!D ze(WkHsHfzL0TkjzeI;v>K%v~-8<(qIlnDe`4h&dgS%Z6?{}9)Sdsb=fCRs z7UGWQ!oJJiz7=<($gH%f)>9E4cy65|Z;?SBu@xeLH5d+wC9DRhl!VX}PZnemfiMK; z&j+|Zy<(Fk8ABKr-zI#@O|5tD8TC8~Ahq&XjaBi5i^!JP#5>Pm{0^4?3a~bM&i1HI z?q|GxnR;=9M4#+Gas3&vH}eOA{w?BGwtJ{r1H1O5)?zn^DzG~<7Ba@dKkZkiK&3oaWvNiN6g*W(y zmLt7RtP1B5At)jvJ&=ddre5$=Nt3fR957<>c(km9??6cfUalatWZ!BosnV(Ast}4jC)-u=k#)#X;Lz)z zqX|VZAWhUCNqvGAhH5xm-mH2XM?`>Vn#!FJwTJ-DjJIJ6DKGVR41#_eBNe(KJgM|{ z4GxL&B;OhHQFveMFFB7)9q^iqLiZtQBp=LF6&8D-+X0HH{zeBD9tJsMzpC}JXX>iN zE`*X5ie-)7f+9X zS&*425(td36KY}f$-jV>+uRFjID79K`Sn5Jz;*P15JR|SPN7RE5HNtVx{8<5{WX=s z1K`DRSFy$Jw8)Nw*PKrqSt}@G_Y&IE?_8BTP5e$PMPUm7yT(K5-T#G zld-GYRaV9~%4o17I7>mX^{EdD(IgaXTpMo*UB!zd|2q=TEB^-{Bgz^j@JB|<6p<-A zz>Ch`;d_EG+92wKw7OhN0;-eHQ)p^*zmb1e*874gplzHy(Se_IruK7-SW* z=yF+l!uL*xPBDBn{4iG>vcevk4Gy_|f_xwI&ROsKuUb?UIC;_=Ao`nKcg;HPYu!I{ zY5u$vK~Q^5s>!$%%cVy&nS6$rLAa)*i}AFJdvp~c)S@83?RBA)O4<&=YInhA^pP)Z z=_(Pc6V_P)60hq)5S~Mcrs!Vs)?)Uh@V842=iv;|l(!F^CC^-IeVsv+MX%@$$Ir`@ zob2;ioofJy=_kZqzfZ$?rp@9kT|$6qe}s1Y&=P5-MHh#3^2qn$;<3uLVto^iB)1TL z6K|KJbET`T!i|@Ar!P69T|XdP&TQx-Y+Y>C2S7u ze4A@q*z6D^L_)8E#wN^5YM&3ri?-lc(Ch<_$hdhQua-)=SG~yg7*b$Vg`J3!(fp^^@Rj*yfxVX-t|9EJFF@phxCb~g#K=w)DYJQiYahmiC2F3+Z`go^3zIS4-V{)FA0 z{Rp0JZr+41WcPjG9nWqW` zEmgnlv{Jggur8U^Z|n?@+>$ zxtB3cyB5`%N*T)BW&EH=YSmI7{R}9K$8KFqQmWmV zK{S+R6hnY*dh+nTs%<@)Fp)tU;?p<)Us13^>HY%}Y; zmtH4|(7B@k^!g^@!K5*DfgniW&$Ana(BM>YQ6^=pLs=RIKkoV6)COAhVa>osL{~5l7NXsF0 z3w6!&_@~}7Lf!hr6!nn`giU$xj)&@&4mETmt7@>b`4OTx6;(o^YGx9D`u*FgHqn1K zN?|bzIX>~s3GDw{5f{thv+;-7aLaF9(PGjt1huVMus%!b48y(X;-uC+2<na3H5E(w^-D7W0SYKRtetMVBO7BSX# zg<~G}G7qnXvpLEeyr0W%V<7pVx6wkP8Z3u1{(3rT zc)vuK3ss(70X~-da#lUDYq*wl-2k*mN$o|#*xvU1plDu=uci}4TRq?TrlX5fU*aW_ zmUzi+&(y$!OJ%)vlcqxVnIELCztXc-oc4U{rEq5=fHDv!QH_qTlH$4g7l3}mNw<9iNy3b zIPvjFo$yFCuE|_j`P@sHAJeIm|I;6gIsI>ANIwiZZ)4m#z!M_P1+tS|e`6g7@1;in zIfT@xv`M~Wh48CPx7fl43bF`x6rT5*B@HFn-4lp%p?DU1@a9t2sKRz21j=U||W>l>HL160nbo@Zsgm}{!JUTBgI9t>5Bu2Y~AC=&#dmi}#SMdAOxf!(v@&~i|$ zSzoM}?X=i;Fg4c6 zXD#&u4EoSJ?7_={Qq(=min4%v3RlR|P>d_2(PUwACsD`x^xrzbS{l7d2mf0 zh}Vt`;hVC56CV5ik)1>4!sOk(-Mg`kx(7M#cxPt5DN^Ws?Z(!nl>)q+)IWDyMqyW? zRfBs(G7)^+#D$P5x0~N#5F5ZRzPpHZ&XiKod5+E26ZAA2>qdxQr9W7SLt(D zi=R|Z`aId)_`IKwV^6l+^HwwW&BU;8gLw&Z?a2Vp%TS%5Apbz zmdV5BBF0#sb1z?d80|q7C)XBAJ~HebJK)X!V5U4C+wWYO#~T6>=ZsEY$eL^K=hel- zbUFCtM$t-(7{R13u8q4_n9kC|!t964>xNU1>kh=MkV*n);qGY5O|MpQAs6zKO9M6g zgKqYN)aM4gR6C2PhBZ0?-)7*Sb~pqr7H3OVwYG*TP-?k*C`6u$`1dc65-#xcg$69I z?)T0QwJ-WJ#>>xP-n_LT_CJVz-6LkK)T^WWYu~xVdAJ+Y`O@vp8_rLD*7z^aGuD_E zeX+W+Y9ejd?t48SA|BM*hOqqNewW^S!13-~)PQ94gpiVr;G3EYv_i1gbXtVo$%ptD+$i~>$<%kyazJXHpNwObK7)oBz zorq{i`$p#dgPtgra|9o$?-oCnhdx*FXRAU`iW$j#CYDrrsNYG>2Kr zCMVXK`|Gb#$A~!HF9KM);O;8oZ`@ys;T`s|z%tTalJ4BDe0%%!(Bi^-^gE<-3AUhZ zUCHVTAt*1i22-&s7^jTb&0O$ahjU z5Tf3C(|y8_13OpM!u~}*vqw%bHm@tR)WB0CAr+5#QZYR%6NDnaUtwvP(-qh)MKBpbNSF)cD`ORiU({pPBcI=9 z-5}R6*j-|YQDnXO%ojkvk4FkV!bfbqA5~p;;~+4cRvdT;D+Dl)mb_K7WBW2sNpWIj zY57?6H)9A2Y$(LOE0bXq$+mo+e^mq-BD+#h%bev0XH1U`uT0^^O%X> zdZJ=@2-XpE??)|3HexwT+#rcku4#N6)dV?{59j_u^?c)x!i?-tESvc|oylP5{lyKa z%UL&(f^lG76;plgZ(CIVSAt=24soFzTL2cU30;=dV*!@^)y;8X^R*b&@oyTo;Zxz3 z#=BH7-h0cN79#c0IVy)TGwam|u*sKHQ%?m2VNG`~K=1QruNz`TrEi--do}3^;?eP1 zY@ZyB{@JlzAxbz0LaB=mPs%RVoWI9^&hK(Q5qeYoubV zp0_*v{^k+e9%H#$m7IDNWPFbq8Qnz=Q;in|IUqWG6N8s>n$qW7s#c1z=5dZSKSsC~@h7Yw<#gaDz&6;bX(yj}0trXg?ic zcdtXsT_p>c=;>;FmKf=LmnW8Ex8QrZ>u9 z*kJYkyN9!0)%^a01pVQ`FmHZYBQg0*sWKBzCn3#gv>@6VEhQ1HC;0MZx$*9q$9We2 zLsnu;&t;6NX^pVW6G9sS$mI}vR6X<)+{Uy1dn7!qD!MHlZ>x~CR` zpfVdm&Pel{`9r{WGELl*)WTQPEtw+aeC2k~vHPK!D5l}X&R=&Kg)BpLrWfevI~BI$ zv|oRIFlJ{Q$nN>Kx~D;3S!;{=qZvam)1E^YM4d?~$rXIUzr-r;Ipg(50&yx&!El@EQ%1$7&?hHuqjM;DY4lNb%&h zm6)vR{$vxKg}jAjKM19V?T|2jPJBj2G>toVM8Gbp;gehT#us`V z$Oj+i%t}j+w9{sVY77CsY@ahDlfHel&hQf0kJ)Tpl35+DaEa3!TMq9;n!H)a_TbFs zUik}6?mmdPHp5kAI9uktK~9hlX%7VTA|FVb`i;gMetFQT1#-_OEIJ>?e0q>cWz<|o zIYZ-Bom$O;g^Zr{DNsBEjvgLedo8cc^s{2fotH|bl%j2i1co+LErZgs1Rx(;y?kDT zSPXGZU7qetmy?<$CG_PVCxi6Ueo1LEcFCYYXn-V;vDtw#`~`hdsu%xTiHhdPx+l}w zeVFA1L|W*K*^lArgyDvXPcLO3cdX0JiKn-nW@Rxt12t>A5M!S2^|y=kRvE&#y@N+i z?!BZ*0GBuP_v|CXV4zsqb6ttYpS61|Ui*7YO3#wtbh@Bf@9hjk_N1e{|R*p7Y|F@6#g#bGf=2tm$WFA{v=5*KZ7c)q(h>Hk^H5a7X zTpZv3B*RpBlJIB-2nBlB@j)M+Xm=V^<=jVGh z=(YmJh}6WB<&A4ju70wl(Vec(VM1ZqZv-7m>xlIOXNEYN4Z+hqr48$FgP+>quzrX` zF+8S>Esp&SK=K5d{yYQeb1>w#pkK>qVU-qVMkgOa>9p{7=hQYET;YFR!IuxmlU>d` zt#y96wq`sESINOhR`*ukQyG}Etz>m{E1>92Sjo@aEvwza!*eYuma4)dM{66q9RN~s z*Yw0?=*=$kzQX^}be`dCzi%5S_Ndx>w6#N35F=_;Yl{&fG!#+0YQ=8t)*eOey&`6+ zYPJ-ic58)}S~ZHARhuWjprjZ{G79kIqM$1X)Aa8q(bg}IeYjA z=;!E9L|_=&PVH%Weq6q}m0VoRumF21w%B_)##Nc8WpkX}xBj1>rlhB(_t#AdQ&7>* z-xpJVZ?LeKsf-GaBd@0p{fV|UT-SkEr9qXVtm2$L%&#(D_T;2m>$(E}bn|3UC#s~# zXZ$_!nrTsQbC>9_3^KlehXE(^=a*7;TD5p0+P}@gHKjib%V1#9boneknR9-z*iy6Q zrDUJ}`;Mu7ED&|u5o$v!u~wWSM-8%)Ucp1*Y&Fhu$NdhXi!>9B8E=U`yBsfv@G=Y$ zqcM@AIN$~A4@4mK(3$%M-@Ol&3XIdMoVTPn3E^r!#N$_r&z4 zvFX5Zv?z07a|HRa4kyRUVUkBhuH)J3FXDAMWvdud?7z2@byrB@dr7)_8MHI`s*6#Y zGSaeWYacItn!i9N)m4VIxQwLivX^7RE%%wR+#ueeP4wH~r9Xdac@I}c1>AyLR4j*~ z+dVe3v}(2t5$PwG(eal+UrYe|u{1FR&KvQSq4EFfdtJ%iCMqQ96GG z{sO4Q7WsSd@-7GvSh&<8TBz+_J1Q{a;|<5m*3~5|r@p&Dq3Ba&U18tEtaSCJ;*n)53n4sdbpSO0%(UogYZn<6a|HfOY-J$4 zicQVZD&akRj5mE$ws;X;d3TcaYdU7}3*#vLP~tIAj+Njmd53N)iK5NuOn%9o$NRtlSpvTwVm`zeX~yZK8*3EatB`IF;EfL zQs4fbS%t$mYqCu6tQxC`H_T=nHJe+T>I?Jpd{zE%>W+Z@Wz2chzE%`9Rm}LiA0*5+wOqS`)0@E=#V^U_oSUMy4v#-^7neN zizc8-+7aiMY99(Q6iVO;X{dM*J4-WM@Ibu_B%dzk)V84aL<3#KREGUULTAL^W5<_z zcPqf~!ke2;cOxxLCIi{pJAoGDTZy#1dr~}O(_&*uRl$Fgz}uF#tdjt##y%cm#~)on z6qE*fo5~^M_qjhly6{;(Q?RoXzfmSPU7y29b3Z$20^4i(d(Dn1CJeG}*4*5DGbhZN zG-j)A=mwv}52c%xm&1vj3FBe?!<*UR*H&C3juIE@Zk0R!|6@sQFh0w z)|zca5ehOc&)Pf+jx||DdbNL3^8l2v)Ay-4jz6B)z5fI2yb*9md1}vimiNu z&QT32H42I?9=EWYxqmGiS)Yq&KhELa-E_(*^pYy?s}~8}OeY=miVLrD*p6D8cP{sf61$gkFIl;IpJ9z!95+OTBV}_C)JiYxb2gbM-Jz^zA zl-5;M2}BZ;pk-GX`Ipsa#;p=*?p?Vo)~fSBI-Fs%2KIgh^oc-gMT*m@1o7tYls!S)g8iZ9dnEjsfMgCmsyKI&w$#<*s+0-m@l_^O`Ew~4#awC>AezB_5}!^US;mXoy2aiGP#A|p1Kh1c^t4L`GIg`QbS3AJp% zLGSBWl1gnQS16R8acxH)>vnP-6KH;6v^6SszmThtOJ*B=Tm=(3wO4P zJk8E|Xz~W!A@BjPU1ei>UdUD4QQ1!U%8eIuT^*u_7nd&;_auH4yfd-i+}Va572c6p zRB?=;YgFZ`>FqoGj#R=|Nxde%LwR#wGfH^wY-!VI9$ zZ7Y4GggUdj#keFXs=nr_a$JH@Y{rBch~s^`C@GdVrO0 zCQF@`Tz09Hq5x}GU;j!odP_Vz2fhtJ8wYPUvq<=UG8Ze$nqiVmxjH-A`tNTnFhy>v z&Gc|U&){R96Y{n-g(|HC)?ox~%X*h9G6q0}Fe=^}7N5`jC88j{0m@MjN zG4e|}&I$_;57>Syp2(&u$eFdwz?qy@%zwvkd!Fkt4GYJ!ybE|~sk*lT#`T4F>1*vI zP~R=}S2e%{f6i*w#lk%PRO}9|x>M{NP7|4slgH#CB#2%YHNfgd)W>zUh2Gc8WF!$U|NZNf^eX4$oZiv-MxP(% z?7!y^4>2)hLhy-{+(}9I+Nf`-;YEFEmOe(=T4g5kth(C2$tbZ{YDwFC0(sxvBomqw z1JuPp{(Cn`|G+mB>c7x+eTB;Me9$;C>Av5^;#^UKRh(s}20$U!hE`^t@x|a3-licQ z-g6eqFJG`IadrwR(N_=!5z!mEqn5m6X5p)PKCDOo+Ro~gpXalLaFn*K!=d?-Xe-_4o!QO25~N)h+Y-@DMR6JJ%E zDm7D{+1uMdU0AH@Ld)do%1#0I`O1TPiRLXy72Ka;_*0MO$A0be2Uq92Y8$GU5?Ur> z_VCdIczO_B{E8*#(8XNfs3ZlQTVx->3#q( zSJwGc-x1T>bGRx*eVo8~+OK;I=fr=d2`)jowwz@7ewqt*dTp_;g|%mLjVe9_%D!xR8>gr0-1~wM_;>D%&T?@hRT@Cvk z?}?t(Lu%(G9}MqnpWHGgd@us!GKq#IybvK*?7P>fGOJ$U4J5Ce87}5DpE+5{TJQ3` zkD93bt_D9@QN#kC?uYm)(Ii=U$tDq^>@Svrme5II^gQCl1MFLMcCy1tH%sIXg$hlF zP2?rL-F=%2+a1Z)1nUBObC6#a>qD9HR&;5>=GZ-|K4C`V`YlVh0USG&lp{SbY;d-nearZxdT9WnC3ocbP zR~uoChuiN&T|HH7p8fm}Uv~QQ_|tJ1HdM+wQ~#yy-e=9dp(j@d2ko8b?KicSTHK1` zI33lB^2PlAG9qjh9$dVnVLALfe2e{i*8-7mLM-Ue|;o7$>|J` zVa~OEHlDY!!7|uVS|ci_hQ_pm>zH?h404f8d8^7IPl*#xa#n_(J_(8>309>kh^|PV z&H#RyQt8obw6Wj|nya;2e1ax#-@)03gXS$;KO1t=RK{^tf75{*v@;1Ah=7WhPev&s zQJ=k*Vxd7Ds-O=`T=62e^9-s0X`dg22w+OTbVjZ-$dqAIEb8=VioCb_6TLhil!Z}J zAjQ7UCkiU}P078ieYV+xSoM_)FyP{e$a50!cL1B0=a5Na>b0t;oU>g$+dM9Mc`JCf z3=-AQQU;cG9oHFBMLZPuU%!NBCRc+hl1?jqoAW{&sLd&-v_zbSL5`xSgnRojME*Ktsa8I;W&WI3trd$Aoc%*RNdt{o$5 zxE|`lkDD;z21lqw=1P;*2(99}7SAp4VsHqD+U7@DYWQ(#;IOfrTGFBwL4?Y<_L+-@#N!Dfw8z(iGPqmkfEP zUW2hAB`@B^!Ch>uV?TKxcfR3UbuXnAA!s}t;et-iR2hLZ)0ZOc>C1u#k_%^G2G%UhW)R=I6K!sfo(<3c|q7BtvTOQ-Njuf(a9SH5m# ziGX2_x^JknulhMLD3G#!?eEfrXr}CA5t?pvB6uCcoS^wHPUE#X5Hpc*e+%k7=E~`| zvxBXz-p&0$L_7Txy5tk_+S?91?Q8MxK3I%!c>tu1quo=9bT~=khTwkR11XZz1ay5O z*Eo!?s%*DKD<;7Hdl&(l7-E-aWLp!|Y2A~oeLabh=@<35xNRI=B;Uv*aqsh71`S=n zzvV9+vSjnlW>i)ZT1+wpd2ew(-UeQJICX15+h=(>zn(u1!+_7y>O9mLEpe^s4C0ZS zyrp}?z9XH3;ijdC@DKEk`_AvigB`!J9RpuZbDJl2PF`&BK44iPaCx+>o#pfmXP^wL zxW1X$3dePno{DP$D1qy*$~VfPf~09%M4hH+D>Dq}ch|o7F}X^*AkRH@f0F&~Ev?MF zn5MJlf_4%n$_`bD1mN^o)p37VzPG(s@&L_y{fd?ol(ihy{k^NjY)9}}moJ(;OPadU zgw*D>b;JUC;LS`K*~nz^klI#Uw64?Z`rHZKO$Lnur(J}&6wY)pY+_`EiDc@9=Cp7! z@GyX}^SR?KAVIux#Uz-9?;)|N0|#x8$kO5t_=V>p!JMbQUqlj)k+E!BCBBe=q>L_W zRRUsZCfSK5e!vG;p(Qz^%Qg#3YFgCd!69IP!a3ur^%axVvhb48GnZjKHPr2?CIcP< zm+x8H;88u<{pp6MB9g%2YF=6EL>rKPG>;BaNO6G70Asz*e}tKq;}u!slI-ldhDhgY zH?)0&fmNi@4-N2((|4pnd*hg-H>t*wvi$`*LHFZojk~Js%~}z?UNk%lw2K;yyx9fx z?u*X;aWsR5%@faZA%FM91d=Bd#VIRWe}tbxA9IoxNI6z{6$_QrWfedlC-d|In@v{& zW>PG^*Gy4&pM=$a{8U#Fi`^P;@^TVda~`fS?_&KqAqDliEa0q)!=(|!aeF@onRhr< zh`A7x{=W*YWA;)N_CgB5tc}>0Yb4^+%ibeu(_)W0!hLK#Z=onD%lk{ywDq|=|7Z&#Jq_Diq-`hr&y=R0Waj}$t- zPT7TrHxzJaUzriUCGvZkuJ$n?zk0Hl<}3ef2be86F5W^8Xpal~tSBP_a8NVCzsHyVKwAnp4-gtxB!8)y1{KO9v4f;{S%f<07Fx`txabB{90% zo`cT1f-gOcl$h*U4!t z>%SuCG-iIQSP0(S%=`SRY!jhu(cOd!U@^x>8D@M^MJI@W?#)3gL>N6BB2oDhk`F{~ z80i|QW63#%KD5~1@tL?G%A;swmuLUsJO?7&>L<}G+3~?OQFO5rH81gxL%xC;712+X zk(Lz?bCsOOH$Y`!f2@c7%{+S4+35aAtgyd5GG4sfuT^*4K>6!iAei#)!-aOAhM}i( zO?fr5KFQ}w4-)JjRK4h4Nvp%*zZ(FdUKb`X+xvbw_8Hv|Cxu=E>aq;+^-rb{oRtB- zv*0RGaM8HlinuhmFDvH_i_?ij^O7`U_34)~vPqMPR_BE`7maSSQ3V)IcpOc%8KUF1 zn8VtdCS4Y`-{J{}ZM4VlTZ-x=6#@1-2)korOBN_o_RgnGC*HTd!<||W0{s?-o&*Yo`kNlk||oe@%58TNUrotyN>SOWQxs+ z7pq(8Z}>A2!ncolMbPUtK3wM83`qnx5;Pb)G@=H@=Bqka!eUCrlb9@Ts8dF>J|b9&NNNVXCRB4|tiT`I{aNHYWwZ)K~pbxpshG`tR)YY|pk9+i%n-5COl^Yfd z@9~P$zD6!p#yy-m=_!;LsSOgKFthuV4Cv$RfjsN2Tl5cuaD3AZ>y!Xk0@an?t+c-C zUaCo!2#cFi#(-LT9^jbf31&^(i14V9|kZu`UtmAf8 zauhQVAxR^0-%j)1sT$dZ`f)#(;;)_?=2G!oNn0^fVCplFaPX=?WPDLEFz@ntb8LHQ zn8<6NhxJ<3&C6j7f%GFC)%V4o%CzZ$Hkpj^vV;K5!1pxw%7Em7#gM%Lidz|S*rEvE zCp(CC!`_WRW>|mZ&Hf>*;IM4@CWr}lk9fS)o$)KH3e!3}DGf=|QOvdMWBrdJ!^QbI zY@KjPE`1DK_pM%AALt=k0@iS>6!PLfwtYQYQWX@;+ouMnK*u8aibw4sYRDq*Ni$*U z98Nejv(I9kdg3ysYR?c~2oMr=XPKfwS+EH|92Km~Q*Q;NWYbF4C6 zUuoc2mDJ@p=H_~EjK_oFcfN+eN6{9xFo1S@Z%mq10-VMZedam0x`wu*sd3%5Lpj_i zD)4<`b||D$0f@6yOVb|BpKww*>o;&Dzs+o1ZqKT4HPb;EN^EapJ90Hd)qN#3=kxjO zq6f8vKhCmt`CE@VJD61+c$%Kew`SfleR`3TH&jPc_HZ*_%dp>}o-p#LU?SJVsnh49 zFC?GA*s0+y7xQL_j%@~{N7_PNr4CC|Utcf4x-iJq@Q<4V>-vURHn@3wdVk~Kk-M0M zVP7KCl;lc4*NFP6>aZbI&2_+LIEuAjLRA*{QhfYT4$}BLtj;Dc4CxXo>N#~;(8Fq) zkmCyTy6Vj-%&YW_OrMRVr$lLLt_H9ew)HY>Ror+(S2&nC^XoJCE6c2tjMVnOGH+u8 zB@DMueqOmn-Bu;W-n#jV3!Ng!433a~bU<7L_3u+bH>}53z8*bzrwa2W1yf3=W7liRFgWJE(_6rcDyW=ikU%77shvg0|_)n*dT~ZImm$Uqe z_>@PKj%|^jv+xg2=e+y`+1RSHtnr}8wAnL^2c5uLp6#8U!?UxXz|(_Oru1coTO1*J zPr_$``CqEZgaQ-9690*824x21OI(Q;&kt-ca0Jksfp|XDY1YchS$26npwK$x8e93G z%VP3J*-<4yEBJpWXC)S*J(Z7oG<)Y)Hhn^*Eo zN!T(`oX<*GuTsaksD8sNgMwd%)|lXLWq6xuh0z`YM|XM89hf;phQEPVKr|a(i}T{{ zf2$<0@zv1lXcV2oI}rPROyiFqdd{6F0#IYG=`1oyV~oCb2cq~sA1d^H)nVDV>lnRN&)L_$%|)JIwKV~63|MrmHL}n3!3s|N`D~1?bvX}KnY8JJmfj5Wwlg_0{;hWt?bgQvR20+Y{ zjsP4nwW`J(h%a0Th#a@IdzHmqZbCKa(Hxv2hjve=mHTfU@#&Kd5fqiIJ28}bFBvaD zB?&D{F#+p_KwiN=js`8b&i%5!?m|aR|3=#?lA^V5;(xVX@z*}%s_nOhOPSZmrcDRD zJ6Q!7xlq^IX$g^Zp})>kn@~kSHrIc7=H9Q{4Dr4b9s8W>Reh{AAH^)&-S+vN6Ykxe zog@z@V(i_?gfuU}c?z|!1Dfcybcf?j`J0xQo=Tnpp>`&S-BJ<>R)C=u5PG5(UgqL3 z%*K}V5geQG81)AA!mq|yTi@b5Rr`AL0@Gx=U%lgme~8w??NeRl12pzR;3zPs;8dG_ z!aS7sN4S~mc0FoT_|_a-j`&YtN-{o(&eyAZ^vjHn?UoSEe|}!B1WqB48*JNQ3p!%G zPN$5wfBEj8)8+*v%my!kx3RsdL+MSoU=qn8fX$C8h3 z1Max(7RJM1udMrRPv0+_ai8iN>evt%E=;zK%D3WM&A}F%EIfwD&^83#jW2pCLx0;L zS@~8AS>Mzz?aD$0G&i~~G~est5XLmj;8|~*2^%Y-M^v~%C)B?rAnp=Ik>mX^h$y%d zegDbv6jjd|^6~NT@NUbG)%)0zOmk!6BlA-FWz4|j(a}+AwsArf(W1JtU@L0O78oLs zK9s9DKLO}kH?^J^Tc)DBS?%^)UT`e0`UnAqH*qKycWb^!aj}0f53l`H*VKi&?Z!YN zdN5oh6yY|!rvG5w@By)|@#kovU znO^aoj3iPPTpQ(RdLW~2`drw|3m|2`6a^Dg-jPf<$Zs)DcB8{{xR8suTOwPX(ui`z zle*kLw3!T^deOCdQEk27aU632P2sY7nL_?cbPMir_W0o#BgWS`4tE%sngplWRB||O?MEg#ME5L{| zZy+dywyT{91?C>4xb+<)tDH~p81$J5H%wdvGRnEkw0<*c7EoS$%8l1+%^zwtBh8A_ zooZM^kF+xAS1H13lRS&M_|Sfew>WvOzhqShzwq}zE>fChVoRUXkojkq>F+Kla}wj0 z?SnZB+5LFTpWjL>3%NOSC?-2@7^RrG;Xo_%EiAu}rQdeTzCQ}o0mrC-*<0j4H+6>v z{UN2q?p+BoEF-g8e|90m@Td72kNaOf?wK(}?>~gzw)R1LpobgCPbAb$0dP!dn62?< zoj7inb%Xc2b#68(fI)GP%b1O3y96(1h+YcVpIo@zl-E8-tI}_am!#+?&q08U$WhsE zauAe-PaBA-!UM%B?liHl)M@2<8@LTIO3jfBBXoRAml&l*Ed{&K4xm}@EiA=UDuh9C z^Noc67aT&dej+I_H7YK9c^4svNlvSof>U(~nY_PBx~XN>Nqp>YCZG=^aBv*Ut<)Kzi>M0pVWDL zxf>dKy4Q0v*^RuP!KU-&$L-_u|IEuMm}Nj_d9(LL@c)uO2wYATOYyn95rGZ3mf)Y_8r=CZY!Lcy zdzJ}lP$}eU=>}0d>=ESVA{p7_72)Sw$#7u4Z_K%J6!PICNZj#PuZJ zSN0rA1QL9#tLh5LB1D|ma&AWN!HxfmWsy;`+I;O?^cL>F@>W zgP?cJ4JSRJTo_Y6Ua*JKpSQmDK`xSqjVHyuu>=xiT=-`aGEo(DmKe{`fRDK`Hp#g5 zCX`u(o-LEL>dxpTbQ5UUS2g{!8eAF%G?q}%gg&qi&-%yISZ>;!L&vgR$9kxvG+d-i zP3Dr-v2?C6A0Y>@vaQ_W^jXjDKiA8}(yApqmOQD_(&jb%F;ZN;BP$auvZ6R+j5+oR z4eji>zB(TweEQe4y7lC`&ESsNoxajnF7C&thwDS@s>iLX)lV)r51Q&<{9$s_O04mX z_;tZ6Y;}DcdVM@((Rl{vSxMQCu-~FZECMhEod_}dFZQqJ|42|6__ay${ZL1Du$;?) zy&#U8ZuAN`Z9(y;*DUa3WAX(DQW0%90%YgstSqmt+*BgO_}E0>O4pi?mMm^+BR7qav@=;?2o1d}Xn zVlgCdVX6Aj8OM=}=st3Fee=FSSI~I7-ulyK4<%^1*Rqs=f15#C02nRxOY3%D74a$N z4L4T6#t{lEuYu-v1z&6%Af;IjMVt9aH_8u$!Do=C5aG38jxk7VW|CJ>^x6FYK`cwW z+)>nfkGl@Dep#uVL3|n2%}1dB_X0$v|D$vJq-gd{m>(PCO;5`TBlar=Hhd-Gc>FH) zN@>?KEsYa@f8e|Ewbf4SwLIJ6v@!JpyeRIbCp@IBv&RkYMw#l(s{v=VhyH56S=KDT z@OovYn>gPI#G;`Q(*7j~=Ui(;v-P<6Eb_3rj|#fI-$11Ki=rHBuJm_)|27DNT71PQ zme`yBStpiQtP-n3THD)$Q##D-;b-vscgnP+1Jd8zWcLgE6&dsAx5QgP<7oWCe?RZC z?Zsi*nl4^s7|y==Q953aCbaspGSBg6==J65&8x+mZ-4ywK}Asw;7*6q6$)>c#RRFI z$T~kB=aR;E2RVP9{?n>6pNPGl53!@ zJ(Itj9EJMDJMImp@?>vfb!)V)vmV8<$mJI&La6f6R)wHS_oE0uSW|ZT0H;VqHCON| z@_oZs-O-y2kE~%|53=-C6li;=Ni9lmAb4#Ve|G`d%8-@J%EWxXmKOYOkY7QS1JOLN zB_T#;9txEld<5m{#s>_fv$Ndf;iHD%}f{(6T`KGdC zN?#sX3WmF0)OWEUdDyfYx_s&j(eccPWcqJH_CJJ?Kvkt5JGGCBcvkgTkA7Lj((A2G zmTGCSh2?M?HFgmJ7p)a1{6&jI{ zWkk{=CAMmyzN%?oKcQrWh*3iptnxLSzqCt&Qm?_z1jl2kZT&6N+nE2}N{N7gCXI{W zp(5!bH0=iI(Rcq2s=!^(NLbj1Sz7}~yC zVsRln9@q!JkG-73i<4tF-S|( zpY@&e9vN61i;FZ0ihDw%!G%MeB3@XxtnwonyCg^#3;>ULFYEee?N)PxU5nyU8Aajw z+1Z)Kvi1Bj@WSM80>$)%K|Ps-^r^&OUM@Jj*=^3SM^D1dvwT6Tjq;+Rkx=qcQ&&qiz;hzp+wxIXezV$lU6<>%a-4!gF6ndlm66FXW0@`9_V`!Zbw>uqZ#DTClL|55AEmHg%z~CZ4<^v++8|8TNrS zG+*mFPv3)iXs4}DxBvN_hmTi$5JE(6TE=>fm!+RAn*s@rWF2hkMN6kn4z{c`!@-qb zrP{yQU#J>w1z-d2XXl0iRn6yCQ>F2veunB`z>Mx)gDznC-OVg9w?1m6evMRH$??fu zPmPT@6{xQ5L!15G-bxRa(9E4>Ji*rk_)Zi@hMmgu#JcxtQ^yY+}Qo;sQupu;tB_u)3S{LtQ+A@~L`1Y#{@n|wM3Zt($GKJqT7^cvEcDu(&mOLNrPx;<5%A)G-*Y$p ztqJFJr|%D=yDWP#Y1C8Z;J2gBW$PwwM~j1SX+?4XQlIfwp3|< zuOOJ#xBCvG_OPFhn^D4LGYSZJYdSQG>(WCXtZ&O+C$*R{mkrfRk)Qf zW2zcx-*$#>$~e;g<9*?xnjAr7N9%E^dWTThsNhB2X;BVZw^WbReAJrII_5=2s$oN} zS6O2W4oXAxRb}}b=r+A=Te}%*_Q|Y!@hBEd+ea?kR3e8Ky+x7yV#%tzo4-HBI&WFz zcHv|C1aY6+3fP$7*hek;ZtQ$IT$l$cK)Dyj47IhqId{S&8vfllLh9uxI}R0$af<+IAZTj^3-Y*<9hoz1Zw=0VB=CYL5m z${lOGBYGm$BpR<80jE%JNCLFq6#K)Rp(ylEcT;tRat2axDiscQos%%3OY;l>>B594ZVo!kzp;%!!>=LAz`!oeuHkwEJ1KqtlKi}IV_PGX}ShUre^f{Dmg-u zxxIwpBirI_o@S-st)HQIJu8Ya=~;xxn4b7^k{Hk5eEEV?l+76bh%_>ttv;(N%uToT zmYqrXKol8?*_%JkC)ONw%T^z$epX5jZsu8om>!UjhK{ZXPt7c;z|PsTv&3%IbopKc zv*mi;SZsQ*#@)8#h5R)tP$(-|GD?xlbNQfFg7S%H;$8roUjbK`vEad%4cIMnK(WXN zLLRGfpN;*cT_#`sGn`o9pOV8gAfS>`KCfO}E5qKSF)$kkulyX#0vMnHqX@G&fUDCVo1+h@{Eh9KJAH85|Z{cPkTt?%jX1n9yl4 z;!atdE+O70J)G$(M1M$=9-+&f4;@wm+q4~e(;=dd6F%<@e35Ox1RXX`ldP$7_Jg3} z=D7G3aj0;`NBckM1Ry+e?+dp2oHZtTHyL%)=;5uf@(R~-72JkL!r%j=*g!kMp}vtMP?@lGk0pDL0O0G~UB z>B`Hhh?IC?_h8-cw;hibcJplggV?@8N9r_G+Cg#u3!MuPkyn|p;+uS916b|lH&Ec zxi=0+{ZN}p>MF%>T~7N1ZLbltavz$j&u13Wvaiu!lBQRbrkt8bFY|RBGB!V_oUDd= z6Cs(&&0z%L^XQNb=h~oz1y}u(2RIzHF*bZIdo^bG$((nLDaG`RmLh%0ZSANJNAV~z zL!}jXM(b?B5RPzI4!9*c*|Ec#mYgO@@xj0Qx68$I?xDP)H{KVY`)dKl1H8A46Z)iS z8oa$`!1`I18(Lg@tr-RUeXJhjz#E(d_!^Rd6bRO<;e;bdO3npjBAFcQa(&VfT{wgO zlRtl7O((P%WYfF;HA>uQYlMNgq|Loazl_jJ4ZopiWnp%jR_=6US9FqR>oaI}3JkSP zSeYqDi~~80-O;K7v+fSvR{nSk0<{?`oljo_q~}_{e}-{08&PwAYi_+-#`;Dx&=pV_ z^y*k*i>mnNoz34khSCXA-&?VR3aJTQ;|u|>d>D43Cii)JJ{E`J28B;9bYS4Pnv||> zBB-;67GC2nD%-OjA;StQf)rYM6fQ1^{c!{r7rnm~DB!g-_>j|LLE0Ga)|g|7fE_d$ zhCq?n9 zX;gbNRLr4`D1cN3tQC$$dVG$wY!#E(C(qnY8J(=w*bk4HF>cy3)x>u#rQ1^7XXIoZicP6r$pkbeYd_Qe2%m0rIHG94=~9st@p>DU)zl4o(&!E zC2H?gd?9Q7n~Jhc%4(c+b7jg$n;Ije0==2|bda~GpI6-2V{%qbv97hqcQ5OY!XTB@ zdERy9+&B1!6qFpF4S2zr6e%PpSCm!M%2if<+ge(@7t>H2ens?Ta9%0eH25OAsQHGI{1LG4@pj(Uht@d|#|g*sopxP!b;!0CQqrZSAN46y^7_3 z9r=Ewft^K9Q{Bc}taJ@;D9W=HD)nFdt0Y!ymWn>Kt!RrxGqDEM_MIRe$B3`jk@!To zx<49v#2=U8btkL92n27Tv&lbw=egd6Wqyuiq|lQ7nCMiLG4ZA(xO!y0<`ZaXF>}3&)6?gK&au#|!_=dm z1m&MkJpR^CF9Z|yXXo_lX$y>pid(;+!q4 z(|P()lKsZ2TWJ;*mhsmas+PA4S>kQM*$7S4oZnhpmtMII1+(Q5$C3Yikrq1D<3Q zpr|m7Av(mEb6B`QF1RU=i+cT;UUiD@ow=}HLUI?sT4nq^_V%W?r40+XWMHR+rU?D+ z0j9coreCbIXpf}4ydUBMEVM9mmIv#i{S{nR>hdQhP$a3j&DyhxB`@qr#2Q|^{B|wt z6&9bkqmGU++ta}(JTSLBrX^C29yP3-f9 zO*pmbb5nW=?O4b6{E<}bk<=+b{|FD(NG@WY7G=T7bu&+~r7TXv^wE|tpIVcRY3e$y zumwFfD$05ts3XXkq6K8cEQguD9wu(DA_0ur+q`LU6sJ?vbh1X1x9j9~PQK%un^0ZS zEqP&VJ7zv!6>=l#d#d$ZqVjPh{PlcBt6xVo(-RIMTH(L9KUAyp-q(aT*Jsg5TGeR@&R^+(bn~xi z%Jdi@)GdcAY_)}*PqsG!{}GPA8Aqbv+@BXuV%8CrEtcxDV3Y0}-NnE9-N~ zdB?i+vEFEw)I$A>$mD22aGj#5Q;zqT?}%!D4b%WVyo);tChqD>O}HtIlokwz|IoDO z?vgIR+}{f3=H5U^7q)%;m|^SiqW+-j@?~fOOph+>vl4qbbjO+A*mI=!4j~}fwYKps zd*`*U*53DS*|vCC%S(737Lp^ZI1?5<546tfepQ-wu-KvT(LxTcJE9SC6H1jKz;bBP zYma!od=og$5I zPUVlvolB815ECNBKmFD0bW;iA-vMr;lH<9jOXo!8ewx;_RD9F~C1dkl_~(3#pr|Uc zt4JCQ_!?qc>GkOT#pI!vU0IhnTRW?vRqKzXbKlZ_YeGHGGd;5-hAh49Y&okbkkE;$ zxI7vAS=`;sQ4Uduxmuc}ROAI(oo&I1!nXB611;rIK*nB)Ia_}<`TG?sm1E12xtK}I z>S571mnb)!x9HO~(^3h&bG#+2lCVWGqbr(Dpy^|nrbC|^GZ(?Pl1N=LBdfINIRsn^ zTe2oWY;ytKzd8(dJXq}PDQ`nYOgVr9JMJ5CKchKj9lO?%)sOuRqSV>Nc%W4wJfu>TZd@Ds(1AFmP0nFz5gFsnnSxPr zK~NGQ1asdUN5XfQ2I3pQVAYNJ)Yi}ZiTht-&jyDN8a1~oh(`*C#btD{mmA#ckN?9U zRbW!+@wQI6Myz3-L_jq@0XTJ6ce-g|+_TMdTHRv!RHH=BHSLi{bQD+uDJU~CC4 z(+Wo7s(B}8Xx_}`Krt4H(ni^d9`yR*(t6vbYz`hsDVOdVODb&OVwB?444vP4dZRE$ zrcR`}A^qxhG@mK|lf|Pk;#0OJJ@Fv>rPzqxlu3`tE15UO-)RO`Z*s*=WKD&Sr-79D zX?lWt9>Fe&DbdXD`v2`cDICQxQRtyr#aMWNTFcjd5bQqLlwvTTVzPDBy^D<}p39L&1(?$iJY~b;uf-FraX8EnFvn^w$@zFCw6K|Mt5<7V>i7UM8m@2gfz(wfIFrNWETc2)IMFr!Ghvc*0nVHbqmip0P zGI$f?=4r!9celgihYDVHJ}KVTkk`no=VzWPR!yWV4+`t@$!@<{#6FnhYv|<@ktZ=; z5zH@YrroG&fBhZ>&g?+f`X&^zz7HTzxj{dNxd)jPYm*W+yIMeN+ zoGBXtqeuFYdSS}c(Vdc@a6q0zA;dA!b$FJo)SKazk;c$_oXFh>R7Q6Ry zCE%SKNr8mFX#y8pe2eCAXgnkg8CKy)+gP5J{WTlzIblQ!@c5O$#i@5J&33^MqdU&- zVIB2bOW) zZBd0~!3L z!$C|g=OVag|HssHo_2BHQW?8WQRR?u*0(C}#=k0fV|#zKbPG>Y+Q+f9)+%Lx0hSUB zx!9JS)8hh_;EHgpo(?0XyJ+>{&3hw7x;izQ9dK!5(kGVnsP%S+aqliq-To-oELsMR zGDI56l;ov3`9!mCFH;73!$aH9H|fUUW_sb{*1f7SBn`Xlv%ry)yb^QZ$J=GZEYFK) zgbyq~e2Pl!Dc%)HiHu{VF{xY`UBx^JD6=XdmuF6GES0|2g79?D^@MyW2+2oO!E%#7 z#3UaT%Yt4%+I|R!k5AzE2|sTtU{(Iecw8>ZKBBRdc$*4*i(D56nYTFms#&03Cs~(G zH|RA?`%Oy!{6Ct`GOWq}?ZY&ZDoBS&GeS}tQR#+l^dzN*NR4g;WYQrWGHL@x*Jz|u zIs_zy(IE;*=(FE*9RHVld+(0x`d**wJkR`)G{m^Hc3JKd_|XRQTiT2gt;$Rr@a1Pl zuuDhnlX#kHD~Xi-&FoY;YiXPQUqB&cpOPPLO`|g_fgXS2Je{?+LiQ9TZWz4;%eG5? zqK3_e!;JRlt8Ly_5zpjZDPbimL;K^+CX(e8mwzmdU<+9g#@69*3C7VCKQDqHOWMq( zLB^Psdw@u!#T%IwrM-a?kYdv`6E4YWYC0P{i?K7zkVisGEsKGvNec-T zTdOjAL^YnF(#f_4fq0i~G+Na=1q8F;*ImSwo@eRj%ye6(mj?aExGly9ZY97d+X5HL z^=XbML_ds$<1Kj^X*WdOK3l-!2sn8BXtkDtS0KqUKArr^)P&I9GEv-k;rnTAU@_a8T&iM1H3r*a+72Lr@J#@t zAwo;6LJnI=Rgr1r5xlqd9eQZc(28 zx4EC(g$&ZYY*O8|g+*h*&POt(k~!?_zX63>&IPvYQQT495McOssk)U$>mAL7560O8 zaF|p)kc`6!QIqHY5$fgx^ramRJ)o?7TeX*~mnUDA+r;>{Bh_mC#N*JY zyLEIDv+zS_`AQL~=0i|n`rTA_-a3BRQx$q%-snM|;}2d)pJ1qWf@;P8qxLeV0Hw7jE5Ujaz1FI1Z60u5vu;s$gnpK z!2azG?@MRU#wE0~RT)NHQ{P{a{nYA9xt6NDgiT8Rt2#zU54+=C{);S@DPUd@2?|7$ zWm?YKY{V%cC8g1wJL6}{WqcSmFXb^rc8BUy{|uIR*68Z#TxM@ z+})C^3<;_tAvO1y$`r` zrcUk~@mIvu>iTxIZdK*$_X|ijeKy5k`Jm})e5nL{n5oQJk|P~^cf8{HlM>~e2A^?` z%a(lXo*R8`$4+a!rH@YDY#@>?^Qk0e$C^xLcu!ce&*vovQ5nvEVd6suwnUYzNj1^P zk4d>ERZX~=w@5RU_YSJ;@P*Xn=YNAjfBI*5)uf_rNhGcYgkFP_&Sk}8fm$q?UV;mZ z+LU4rTYzUt@&%w*;);&8FZ8yOT?v|_JQP|Q@h#_RROhGz* zp){5aXbKRL+BA{QhG4EzrT=pGfVkj*E9CLLr<-N0qd{6VaO8mwgMAEcQdZiJVkQLH zhRo^i)UuEoKasc(sWRoVH45|kSpioPGNrpYd1N59N2}vaE@Spon3&$PKk??~W*Y~b z!sx*iwRQ3a)3X}GMEosG$yIMsw4^_5F${Fh;tX#BCGowQFweica{MFdARZ=w ze?d(m?=>Y`cMUzBRXsf@qQp}0jH}hXb#Y^W(a2^<)o0q-t9JxCfTWAmquZJAP~$OL zl*&EqmtyOlg_v*h}aQuDBSkqTgmw3|l zY%`;D7h3NG@sG*vHT*U2#()2ARFJNH0BZdwJCL?|$xCS22V#dmS<+DuXhPcqw)<(3QDtYiYxLexMqcNTT+7fG=C?UL5Yp!v}e2 z&c$H69cKfLmrMO7GylXcBtdUUnZcF{{91DLG%`*yd2wjqAs*2i|7=V=`V|8Hp|8@D zf&_d0=hREmz$C3?{m4=z_p7&~;$7EUqNKb(GG{x68Isw9Q0`TVHyf)wwD9dg&HECq zGFSZTv~6Q>o~?N_0hQ61RZQieUOT zAA8`-^%PAuaMSI4wr=h-)8u|R5meO+bJ9UtrT zj~01MbDshy@sjO`&Pfv%eEaAvw-Qc`;yp>~{31Rd(7) zXiieH7LRzTGC)m&ZaXzqPHntRg`DBdxLzIJ67HVWDQz`1l*nKm^RI;|gP2>r@hxHX ztS%kAXXalzWf%fJRu=zv^f-!3yn8R!opObIucc05;U?i_9ku+l{o+MRiWmJ#2TlZs z`MGf}AvF!l^5EvJt&x%S3XmMpnhW;;)c*LQytgD~I>=T{rpO|NVkK-)s^Bs$1mAV7 z1e!7=SRp*W8m>ArR4`iVhs77MA|?zxMLqLurCuU%B!_r0+@wGu)dNm;t_2LB?(@J?pYBCle_TvuL?kBof8}?S)Ef0H(sq_4%)DtKK;g{|Q zmnQRKm$5Wza~(da!L}`)XNFO^fUk5K{np?+Rv2ZvPYeLW=2yI^jshO)JbI)ZJYAy^ zI4os9n;CBxQW}gLs4Zpohm5HyrcpcXXBIm5xleN&R;GYlJ=;CdmRhGK_}`By-NgyD zD&Uv=5_F8^?oprR184oaYh#G(T9s9vrQ3aRSJ<^2par(oSL&O`veI4!Ga%r0CJxUno%%UtHhOioPf!F z4C8Pr>kOuI=3!25tPE3ssqkdMb1SsgkF5KK^wV3(*??>KK*9?E%w5)flVD$EHkTIs zG9=4z8ulSw30(VnvPSx_&>ZKsE1r16$(%XD?{Ndu9MHu60adctZ|(@jZ2;AX|NmS zsnLwR@a3$5{+g0`4J#Fah;J)r6BP@vX^(||bzu6=Kp%>Gj+Str3|qPZ0sB?Y+6jaQ zC9B8FiNM&wyOeL%@Ywx0j{}W7-S%fm<0-GT;XwF!lCA1=f*}_xZB;{q!y-|?7Cd9-iuuL^x6_ za*%zG+RqT9pLrnj6+US=TWhpHH!Q^(nEOk+Y%gPAmd=8FfpcWdoAU}t?{fs{qXxD2 zUmol`U?1%Ne8ru4dgFh-GwxZkC}sLp;x{cJLj+jJ-dKOXk5PX4LZH``I!M!Ye;7sc zJH-9(%#$g|MsdnhRc*c1EddHmXPo%wN11rR1aSZ|@|9VL-R2P68xob(xR&W}Sp;B! z0Z-Gt#J`{GjhVf=Cv9(FlCS$y7CGM^(?pY{!)W-^Iht+t(y#dHNm{_xl@prH z{Yy1|lxQecuPSz9y1)@%+-mzNRorJ|Q*mypUH+nUrq~F}&UdI4rc|3>Dh8F~ElzPK zMxAHkb#~dNia#)*dgQ?0B9>z-c-rZhdXLXG0QLF}%_kGY?^H{UDy9T0=s7Z$+VJ|O zk%UEHUSKCPKsdvRzSMz;!5bbP-t|%Tk-Va3{a~%-DfIQE$U86xoy0O*MUkB{rhqHy zi-V@?FYzfGbBh_B!PSLaL);N{wA>Ed^q-0Emny+n;9nhA`3kSUFw)NL#Vt;`lu@o%J5J)*0YQ?j6IW}Laio6)P29V zniy&6v4siIoK%k&)?uZ=aH3gk%)S|dVlQ#jk=hpD&>J*)wbvl4)pK(XzzZnYwdOCu zq~Mm9UjGh_LAo59OmEChwEDGW68ifAW000N$nak?9Qh94089|CTA;-$C_B&xZ)>=x zBX&@qS>PmGmEthJ?L~ShurA_z$Jny|eS1o1(8&;g4WAT>qt`0zhh-u4@(&_>Vmr-G z;EFz)g#bDt>e(L)ee~^PBRWMDsBUm2o{|@v1k?D7mEFVxx6MEphkRSI93NYW*N>IB zQb*&mz@kMK^t!RGkjeWe2K_hbF9hO%IMAUvE{>Vt$RhsyOcC@Xi#3xEfrcsrr1Z8X zAcG@b(aZ^N)&~~n@iZsKK96=8iHHRY53Bw(64Tlyn0ORscMp2qQc6#_o{NwT?nj6B z$RcgEilc4eUB|iB1|Tv!iE>|b#5EL^9a81oKw4lvn$aWE$z4eGPiK&zy`D_p`-U{gZwwkq*g|B&TL+ zSgY}6g&oAOY-kK@+>H1ex&+A1bE6#@a#lLPLKY-7X%m$MyR|Q5lZh6WuMXn;cmqwG zaav$7b-ArHGqt(uT{~`?t(?3~nEV1j_W+{qEG!Wjes8Tfu2de*xsP2}>n*yN<=7;@ z0HxX3ib8arzHT?gT`AYE`gU>__cyioKw=RSy`Cpg4PjDCB=BXW9HV$;!54az8y1Q~}Vl@>@i5BZ00%#jN# z_0H=2FfPbt^(Ilv2x<~gXX8PSMsr$_ySg0~+T|SZwoP@pRf+n|)qXCG zLna6m&dWoacw%-ND=V}kcOf|BrvUhnzwq7xvB2@a|Du<%zxcxc zqKAt;-Bpcu@ys0IB^P$6DN7+O-5WPc|K5unMlBt)Blwe(24Yzy4_4pCc)|@DMmd|- zpMK8b0v?5*?HD)%Q(?K83aQG@YlNm2xwMtp3A=7@cN9YZ-ge;_AOtG$0BU2mU;0l% zO>b)>ACge>D7DaM0jFR=j+AL1-8d#Mst+${{Mrb9E;5}=P2|U{(xlZU~ zza-9@F9?H{&$6}XKOtpgk%wUd%nD{ExP?W-mnK|6SEjU|H)2Jyub0J4c$L#B)KaIi z1sGGP0|txB7pyc5`-NE{JDjJuhEZ#*CDXUOOWUuBo(A=0JQ3N=6C{kj@@*QiIHrwY zp?+j^n1RO0Yrhs>qXpsEq%ue>Rn6R6g}Qqf0`NILFPhL5zR@V({0p z;Hh6xTM?X1itIB{EZr-R7)H)v$2`fU_pjwma`($PaFCjHZf}s*-Y)q3{$m81O`cE= zL0p!Bc{48f#G^5Pl_~XC$b7EdOnWm_{M{QXAFkW7zET0x=lJ&i#h(s1RthF^UvyCO z1SQBB64p$vK+-&7Y3%4Xh^e zU|QKxtYTd^8Uu1U#O@tzrg;JKc#n}=zUYVB6KA!whYs#bV(fD=TnT+O^g7$dbY=Ti zBtAy9gO~BdhRutEWxYfTesv@Takf>?S3EP3&fzlg7OPi3AIU8BD#$D>Wvl#X6MHdV z*1K3d0JT&okZHmMrCnx2S5ODTIxq)74NtqRH@^v{fqi~Ij~6eP!U-{uH~ouTo3h5C zYy>H)_oTaoSt#$-PV2$_GQ-@JN3!{_ga+v5Y~QK%TQ^)sSk~85)!jd@U@CP0;gWZ@ z5m2k`CC+6(Zg`mNS&3wN@K0xNLlz(A`x>_?BAdAx#kVW{PeT8nd)eIiyXwQK9)_~4(^%SNH^Q84$Lgw=At5kI9yh1@ z4H|0H4x3-AwwG_G+XW>6Dd)N6J&B0G?Y8i1Tz`m%KJjU@+pNmP1AhfYELxE7x^+po z7pi6OMKST2k9ai5&&q7%(W^k`mjuqf8x}t$HiaEaLozM1YzpLFH5ZnhQ16PrIcG|ps0;xp36vf+xEteE!8z=u#oVHc zr@GQ!$vRUnSmry$!&+xmOdf_8Xs>l?=E@OUYEZXO*9;C6j3O^?Ivxr87L6c{zj30K zo)DF*Mc94QdCs@~iea#6010Fia{gY`I-qyy`SWw!!)eA$!uYw#iYC<=(rwYqup0rr z4Ym7_*BcWu^dR38`FI|mFiGs|jHJs}70dQ)ZeuM_HMx>K-)wInuAC+Wlxvx;M6Cwg z)9FS@?w4ZvuCje`Siq8}!Os6}4NGe0ImEMJ%2i%Yn)RKPPc(Pk9c>Rj|9kcyIPj^} z^>jv&#vU`t{m@y3>(=LhueYOJx1;~{4BH>AZa05^?7I4Bq;tR8e>pB;ulWKd%K?G` zzT?ojx4+7sL;fCg{XM{sm^g6QjFWsZ138s3Ny@%Aq)(xOZQq7F&DDM}WVSb?lL7xT z9<0WMIz1m9Gb&4N_|5Fr!H|cCRdEe6y3&1}I4$dy_?)h5&6A3ExTjUglwl%V{1{7p z3R+0`mk{2IwpgGeoO#b^^%NIow;$!P3wnkch-H?Qb39ux{651pVz*)1EyhuuQzB)nVc(2S@4f3C8w`*TS9!e-1o+^?78FutG=)m`aLs>aiN84E<1N1~_lHuK=$o$tKyf(cgjI}*v#axyvJ;=ifJOi@xB zE0CKO?27opU_6j^P_t1i>K!o^jcRZ_2^{b;^ujUJ=g$_-^Y!1KRrH9*TXhJ;ttdPp zEb-0nt3u#~>z@&m&br&*ICJFBimvO5(SqCI0-^tQkZG)lbX%YnW3)btz=NItqH4G^ zpg>R2EyL;m-rmpu4C{Y-e*5LQCGH7-C){-|-&KD*_4sbe5E~oy#^YIMgiSbFF9*KY zWr1wf>+3k)knZ|3zCHQ(aFRWYvqi7vRh5b!U*7g!Pifei@a)$r&D^%vKn7KMMjxM( zbXN$@?EN2JQjx9agLli;x!hemkY?ui!5%A+4cf!=fwqRL>ik&LvMs^LBWK`~{||d{ zx29)mCBJL>r}&(kPc!8v&&tk)`mx^cl9&364q#~CVK%F$?3yq{-F~*Ny5Z#9!`xho z+rY;82Si4QT|ben*5b`nC{bs~-F335N7;_ACAJw=tIpu;goz1f7T=Kv#%0bo@xy}3Xp z9OT}bt$*n~^WN-AR+`6^rKei$m>XNXX!i*rQ*-fMr& z$G`vjpk3)&9*?fNzkNywM)TnwEK_Z&{NW6|w?n*IT`ur295 zU#UyaVyv4*L(7C{)?#f>I7OSOR9Vn5T$4+VG$*>X6X9|M<{+dOv?f z`^(l4Oy-=~a7D*>>3tz&p(h|g|K2S!AeQAZwT6K#mYHpx+TFuHnd^ZLZlR;a%tGEZ z9tgB{>wQo$97!gVJn`4t&6gujeiF>SFS%?vA>B~`S<%)jO!cai|A&#;?*?Z4!vy|d zwgj%TY|&tWxAoLR0soz=q(4*Sf<#r~zNzZF*SM(GC)^0j$;%|n7OIkNpsTK;cOEVvs=eqi>1083TV( zgZ6Y=vMDhQ!miMcv%L4domTuuKv^Z3K~&f18Oqie_V2-!J)fdagEqo)WP_h>f3+u# zI!pM#fNcy){IMtCfCa&S1WF*La4mLT6cQrZIj*K$#itl z-8?U}VHy1KgeMP1T^5a2-C|}mqB4a(A z%DfhZ=c7}!V*1YaYp(d?kc6%SWj@u80&lX^^}Xd+K2&($VKpg;4T1Rg!y8?nU~_x> zErZ5fp{C_Nx}T&xy7!!P*%4kZ6c(6%&={-lVL1nRd@YAO42LQWgdWT(X6@J3=6tdR zfkVJL*8O8yadNE_C$bYsjR?QI%(v1s7?NEpmiu~hr&@*A^n$0_xeOM^3n2UK%g2$& z7RsHPf2Cr&$QQ}(l$D>>!?m+j!hi=_@6ogAbe5BB|Hy;of+udNAAf0O8biWT>fTQH{=Fr zxY>YVoCEsFI(Jq#24Ru)!6rHdQZMXB&B4S2%Y!$PczTE3@(uZsbR^tDzeG2Xwhx%d zQ@>2rs^O5xt|)uB`X@m*8=aTysR-ajwFl?iRm3*b{ z9%Q1DZ>}pjPjOy@*WdSRD^owVS z)7O2OeP_;ZgA{nMmNSR#KRRUI0G^1=;2f}wCH6L_XMkpm(bF{A`T%QtZtEHVQ84a) zFGAS8NEieB1$pmibAv1*%*)CokFLEF0~7qW{~fG@90e!PZkm#pM#|}0zc3;bZFsm4 zkQ&{%f=HxwI*qJ}GPrCn^)+oB(%>CcII5zeVtcN_WU%YiTlP0M$F6Ull2sOv8+){S zT;EIWf=KA4&X0^^{QTV zLhfSzZ{5;UPCyTQtTm0V=6&57 z(0S8nncqrck3a%Y3IddR0%ephr0n?%WCYB}#a))!TC~FXjX45=J(U-(ERiqLWBgp?2iKo-7adT5yRV*D%o2ez39K!swWXt_*y6Kf602f=mql=waRbnq6$@6`PswlB zvDkBRB$Am1iIPGY9U;3z3KY-N?%^Iz1 z0KzYqBx;tyd!14hLOvs*cp>nUoK|@?KBKr}XUtQiLpry%8_8iXU1{62X?{5YJTC-! z7kp8=L;eJyzoflpm&Usv6G?>f%N?xhCqgZ3fsbMeXK^j;siLHW|Ii@lCZPr~rb zL(2Jl7_D!!*A6ehp``s3V#AalX|`?Jm-}7t+1xzLTT3W!UaoAu4{NSZ8%Z($%RBx# zQHAN{`9p*BhL?Wt)fELIOifHo2ESJ<{WyLgOWXnBqI}jNHWA@DTE0f#^HrO(_#XqF zAZ*<|=6&Q6ea>8!G97PqS%Q$lwz*;VBi}L0&x0QV%xWd>XfKCAeW1@b=!2oS3OFSF zeMv1~K3L0k32QE4F&_-Ch7|cF6iu;tLo40+AXjAxG0v3^Rr%3g8lY@#1-KmBa1QT; z1x1WN#X)W@K-ReRa;qEQGrrHiuTVFJVMxy`=_vZeZczQ%lRpRzxZS@Q!j;}(hfNA^ zDypT(mIBoDy&+8>kOksKo0gAPv-8ON^~a-t;RnP0?v3}ou zk84C6AT$Oh9M|+5-}hc&uEwnAaOG)LqSPNy245a$fjgQp{ijyOj9}8poHb+h;*%!Z zp7elC5T32$bjJgqOm~esPt+2CAW-kubZeh3!PKLk@9>e%13Q}&@vtbn2QIF?JU&>B zQd0?{RL~o7cfGI2Mq>aa%SYW+md>IYbO;ym>oV%E+yNi6!CFpfd%JsU^^Aul;lG6w zN2_bwjLRP3S)|@@mnsPt$x)%prh%Dw(H7MbZH@w1y3X$?0m<4mrQbn&i#|a5!IB<; zv>t+n*PaJdb~2tLJsQ&WT>J%Y4Fqu+8*5D3!bgIt_c}JU$Bsxe^`WW?4;#7<=HD_; zE@9Lx4~=f}C|-cCyx3146<#m5I~=jA){x^Q358H5i41$z3ey&1jX+eX2ez7t?A*jxdyKO;!LoKd2t54{fAt?l>Lb!`xx}m?xz4p`Y6I^C0owOio8&+Kl#_J znDSh^H}D}AukWd0n*?$LISg1m#|%hF|I2d_BRl|dGTgONKlHbsqXA-OWmn%@wCQW7WmmHDyPuvOc$v!7*CMVtECtcm+ z4kG0v>Qlz!ey_qEMwCJu_k)s*!p@G%VqkaK_xkPe^Y!MOIVo_X%ZXQhe(S$a<}))- zCr4!it2>OV%)t^q#e$kWvJ9a=uPP;$cs|r0a7;ZvVB`qI`)dD|O*lo`;%b}(@r&cl zH93svL0d?kwf7}Eh=Im#ZlnXqELc7$jUW{t^~;Kvkbq9#1^HC5H~u|Ugeh-$JqkU% zvxz~|L+ghrTz~>^d7izTimzXn0&=Wqc?{31dp@7=AQ2c;{M20NrYYR+vLQ`V`R$tp zxr2t|RwfK`qn?Mz4audV#Zs_vha9e-E}+@%JM zxNg*s&lIWF-uGOt)S^Zm7fq?;(&o=>(!lPR=>0q2Erl`3m}GimWv-0SG4b%!v(2T( z)G+fsW*sZ-O&v^`O$~F`%)zE8!CbC!9DAej%<>Dd--&DA)DzeWw2gXdOWnuCo=K0E z?ROkxN6^)vPP}Tw^I?7Ff|B=Gy zloP@IqC~!onWx39xLvo_PG^+ZkwG1Zdy;F0LH7C#kUPPBgBayBPv z<0You4`^SbbAMqha`0EIhUWe+kEgSZwv>WC?*uKJOTVE~Dwf&Q9A0F*TjLK6-0oi< zT%LBw+$lCvo6tNX(c&qrhkx4-bQN0Yw_VTxD)X_tYwhS*#Z56)Vb%sF@0`4NZ?wg5 zx<=2Fh4^%YS^UQmLF%{a5mxo%vBk>0iXUY20PeF(ljL_ICtno$VL#Kk@mS2f0!L$! z5)8+EWYh(;Qolua>Y*@@SmvXERi+Qrer~^9=YK@fxluQuyS>Yf`itpiKX^)oWZJOS zMcW0xb?uFwi~b$d8%sb+@1w@49u9J4W5ahD|52@(iwd3DJ`>b6${=htO>RM>&X@xo$wRiQHe4hpfmB-qp|C}Ldi#7)~~{IR>Xght+=c*7?apRg|Fk6Q^; zEU=^Pl>!-P^@&wD-t1pf{P-0GN%~KKnnNmUm!nD_m6Ub(r>O*yLk#`uwe_sKPLY}c zs(MV{2!mmt07pE@ZAB$w!ED*hLEvc0tEN!Vr z1X?lbn*sa69}7JbZLT1JQu&@EV=8JOB8fX=4SVXe~)!I{=J=h%%6n>GvvKDnWCS*?9|fMM%BKszx7n7H2g+O}5+txphr$(xZN zre`^^wzek@96V2)LX40Y>b(JkRuQ)nOdKdWRI}i#&aN1>77`{LC>dhR7%Pl(oEJ~~ zVI|$!9kMqp5>M$Wz@wcmspwR|M(11z>L|1!GN-`lkjk-A6m z3gOo$K-BhBM5GCa+bUxQ?`crwyz2AsLq7;%d8|&(K1uI$e4{?j7n-XyZ9gb$HY>H8 zf^5(}Oi{Y@3!IEC}!w&NF(P?_CLqx$q6#zh~e{pJdMD zYo?pIa*oX0SxcM|I+)KVw8tE?6J}y;k3Zb(lQVpx9QO_fUjjP*O5|;LB}DT?=`*A* z!W<53mjX|SBIsHYtm(voi>40yH~=7xomp%9daD;kYJIK^!A5U}q&u`+=*`kFmTUzhd<=EfV{1IkDaYMcbmZth2!ykQ#^ox@TnM zgKcAh#PmxJW_$oKC7;Jpt2Y8DD$?V&l5Jf0=mv7Rv}agrNj?~bBkP`ZDW@au%Lg#j z`7x#pL`=6)qr4yOf`0hZ7ca{PVqCC)(2-^$fAqrSRGW>tRL7nW5bmIM)UiW8Zc|>c zweF$mPQtZ!(!#S{||!8`n-YGvzq2sb1od)F0lHcI$}Q*umSTOWK!B ziJsVJ`)%$bo+hfb8vH7n;Nu%IQHgJRLEpwdGKnfew6(m5QvtZ?P9-y9gwC=$nr(tA zS*+EPuqNS`o!f5_Jfq2tuerN(GIz;}wJ!Hf(IWQjK4P8h_-2{)SXg$gjVTSFaaS1UHwYa*q9ZO1zLL>g{(NSWh6y zOZ9y2S4E?h6ara*8v%eicX8eOKed0Br@Jc8+cr-iHh&N4;$8uKe?Hazl;A$8CC7Fm zZrW%<$x7&b)aQLU1zVfb;BYCevfS!Gq*ss`47#n@{Z8P39i0kvyuZHFGOShxm+bN` z)UXKJ)W){D)VBV^^8a;!yfL2FWk$$Z&*4|OzT=OVkj@`cMjk6p?lv6BCSp`dc}=90 zz`9YzLz+v*@E3D?=WM}h`3TLa)fw&$Be9BvE3s$ka0}O8)oUM%M=Rc2n<;^Hw?&B|1pko{{jV4NVPkx2HT2!A7)Ge zz!M&5h8|zd)&4WtWG62}G|JnRR){GN;MqpCjRJ8IjOBp5Ahj}JBVP!2ir}z+pk$#E z@VO7=R+g9beMYotmipX+KgVO2Jymu8wmSk&b-je?4qKPn;Iwm62hRgbqg#{>RN?-75Op<273(nvukW zg|iqR- zTzRkf@zJ5oxv5^HP3fpf=>5j?M-nf1OkInaem|A#@r0r0rq~%O_W#Md|BzMw?Irry zI1`BG@IFy>em0R$EZ}60AH<94@=dI5ACV0;#)IG=>?r~_kKk3E%sCjZ6InK^M6_4t zJ+YYp4{N#6DpRj7bD~<+Q`;b^E^RdFv#*BS( zh=4(qRkjN5XET{{NmrueTWR{m)(53SHvr||9yc0R5?;=kt9_bh)dS9!qS}#EUTBbJ zcXE_XMDZk=t#PvAX!o8B;4|t4MHiYh70@}i=J0Zf&9qmU{b^w3O>ZqbIfOQ70ltu|nuF{p?)vk4efmiPM<9ARo%F*;b!L zVZGO&I8cUm?QPOgJlB2$T@oOcLXg8r+(=fQ#1ACwr{|o^wYW!?6nhri`nxJF?6}of zeY+Qnw?I4C1QEm0$txd+lE>neI}}{Xgt6iqReqRSP_b#O@zB%~UI$IZ zy!Z&C0+-1XqgGy^)zY9Zf9HDa@*B_Ty!_52$DK_lusbh?#JmdReQ1X@9voOn1=Vs_ z7_~Dk#((OT$Ww0kL1!_U4t=bl0lbODU#4DE@KHTNpS^t0r+i3>e7 zeW>tvP6H>-|F+tKJbn25Kh2cby84$ucQ0fyLE;|!OI`|6pEJj+W*5L3E%aeu{yfOL znP!!-0oE=AqHP08oGgWBO<0E5@cK5v@!%nI>w?3vJ=?StYxh5C;%MY|^_Vs;moFV2 zE~?e%mSF*;=!&ai$rF&0r+r5gY32R|Y*0sk>!gzKbLxjBL9Pa7Xab((98CWngQ;Mx zp?&GALr)aGQT)lAl>BC2EZdsIJ4V7!fMV3iOyTAi?9(!MgsT$T+Z zD7EU4{2k_D$wVx&S#^dq&_@ zy5k>9`FJ%u@oV=*w0$Pvp6MYRwx!c7$ES(>{)t8E=B#iu>B`Pukcv zxrA-L=KBbg!tQlr_A9e@fR*gPUHjuDAZ)jiDTP-@HE1r#LmPsFd$Gs3Mk-fZQ1 z$XD(ewe?Fr9K5SozR>uW9p+UpoAsWe&BBM)H#SDI&h3R0TJcYYST$cG>`G;f6A7w} zBLc85v5NtkLb648hw$!%hx-lJ7e2H5cRs^>`x(g0AN(7!r5e)c-Aw}mUmCrV|6>xOu<56_0fc{Fi+ zrAs-|NIbJ^7ZuszyvyAl?tc@a*=^V1c}JR^Qf;Nira9_~Q74L|XS7nd)PIC6&}L06 z3}7NtR+w&AJvmFN9+n2VYaBenRA4Q0wHo70JOOhp^4F}!i8&g#G9;$GulsYgn0|7b zm+3KcK5TeyRLV8{T|`7=O>|dwQ^@wRv@?{Ico37jM^$e*BK5CkZ}4Xht@h3VG4fXh zYDnq9pYY8EhHkit15i#xY39_dx4k?+xomrhq*E91*igh!VB?dIx&3-3w>%;kJg`&FXF0bz6D%?vgRY;&`o&D7&T-_ zNp-s#6BEP7EU#tZI6pkbLqe@EkWgJ`{g{yNge>y^JNn1K9-JX6q!qrWQ&xWP= z!47mjw+@V8SbV&q-2AtDO(J9<4Edq?xYK8EQWertpBU$BSl#34DV`wK`6pF!@|3K7 zKT6q$zBMT>v0RzcNl@z2<^CZc^jbaf4dWAR0+>D+=s+bl`At+ToyFw7D_ED(p$(#*uU=`SizkI@H-F!9cg*_U@eRdv z@+FsLDw9l#=vzq7k@B^OZ+~NKY}Ybv92i?lm&u-FSF5rxKz=J;w6HCTMv#lg*GGx)?WSXbexX z9=kP`4ZD%YM;WUuK|&_G*?m^!bia3aa)~_OSJuo(tTnF`KTr>uTr|--uWs9MP6+1y zXe9NRmWkyeU{$7^i?3Ya6WQECaH4sEYu|ln-`O6wNz(8I&TV}67y)N92J{#NNJ}uN zIH$K{Z6_F4?fPq$N$mCV#I6}i&ZJLhi(k~1&18`j{J4aOWqH50{F>?EzsO=eZCw(9 z&Hr6Q-ieN!il1m9!tj!q8sI>>5*E8D81%QV@eHC(v-|{E10Mkd4k_OfvYIbXwLXr{ z^0wMNt#p#*UM3q-*vHu9H5IsswiFk6r2wmE;y;KdjnEnTg-mdR1aYJw57?u&`i~hE zI~)LgrdaS>l#Nk*9Kas8JCpCy^rU5EzO;>mKR1plf*g+A0kJ89T0skA9+&lmj-V%) z5fyjU&3wQ9wNw`TL1_NY(3m0BNgDw%AgM&sI`7wjsl;L2095osBNzf>Lqr>7-$w;T ztSb_}WRv;c8pwOb`Q|Z3K>%N(_Q~-D%K)G~11x>=U-k+|Z+87U#c1#U3B#ZjskIlm zxm-o{!u1xX?y;NxEjN4C_wZ&qTAkd$yHuO)tAZDOiGL>wxWu&4{elGac_Mc@@?ah? zO6BlVfK&(O_*`PzkV8LMXZvOL%9rA2=J=g6*PgyZ1`H>&t9aof+ixZ^`}oV{}9-!hGb?)ekS;m(G& zn)2z=wSL~V=CaPXAgx@kj0ZL)Il}5HJ8!2OV4(_$1WRYrJ$OQVp0AB4BCOay5hbr- zHrb_lMkHd?GozRgtWKb=H?zNTC{IF>l(dT$q37AR?dyAnSrS$uZdB4}G zwfM50IMISog0p}4^MRV}WrFC0WqsB}0-^WHCAcm%jAQk3CbPme-L8u}uTwDrAz|%& zt)R*Eh8Rz8K*%v1R(kpK^z;;0@u(WVdA1Q^Gfft&d_2Z(A$yYA%Nq+;CnVW(s?~md zS(7ABmCpU$$V0_>b0c$c&pSXNvLfw0%T|vmgkoaEsAn-kD09NU`fq!}L|bib!y>S< zerc+z;X^L|xZ}K}UUFsF{{EqTZ{KgI;|1=}Up#*~zLJ-6WrC~|O5WO-ey`RSr*l60 z)Ss2~*orgEu@B9DlTGiS!sB6b^F&4`GtM6KFtuTZnp3etM3DoTI(e9!s)0XaG6b)Wmbulu?l&*!uKIl-Xq zbER2u9JfeaWU)RzW*2k7a;3EEiNsjakb=H7;a0xi(|~ORl`t^LJLl7v&KC+3vvjec z40vJe;gqR!sweA(nLPxsQ1gt{h-*kY}XAQt3xAg@;`w>hfvK73` zWk+Pvmm17wm^TSp@Szua69G;SP0hmXN*1;wj8GGmk`yHW%dy-A7@3{c;gUi|Ttp;G zOLl56gKpc@f&pCYKp-hUeru1Ubo5-Mc<*Z?OH{r{?xB1iL zI@5q5q@C)^k2#dOFZBnp)*wgY2~Cb$5*_tB|BSLyS1Fag&a=n+-jqpyRk2ZYeksjg z%ki~^t1m;7YR>Olq884VY_n4vu+eFX$t`GHmK?kNx&49al<_{pWE^qzk4xB1ujXGf zJfv~C&9fi`O*kmF{y(MFYd5AE|5DFZJ*)nAbHa+#&M8bE z%ddo&22)pKdGQUbpl_O9N(7t*q#kr5UjkOqSN;W-IcXzMc_|((_09ws8MghO4Dl6v zz9)R*nVy=0o9kv(wVol`;TtKSE*!zWBEJz$k@4eNF)iUiJM)FXm|6Dz%TD)&ddIhQ!^m=c?EcY4TQTn?)L-I8k-+j~Y^vG621;{# ztJzr7vBiEL?h4bbiKjv4&PFj^ov&k`eUG%2*e$qIs0b#-7I(eFRY~ZFz0MJOZnin) zJ8nB(Fq5!Z6j?GB>+J0Gf@!c4-OiR`>3awNr+*?Z>%dbv)}Z436uGHFi7fM!$6t~5 z_Cm3*YZH&F3|lfyYC|;ArhXzJD6^j~PvJ~(tAC(M-8?l+z4gpGjGBS6g)M8F@2kuq z4~7j3IZic^*txbSZ2EbP&_RpzGs&1OiZ%@dQlLdc4%kp&p#KkK&{-#z)};8shsZF9 zcj$fGJ>`9OagJe3C>I9{ATn0iNFf95cXKP2Kq2}@m-A!x@{!ReWspdntfMJDQSHQ$@=5 z{9lhYRQd7~=_%pc;lu?6Ovqv;MGe#dpYZ%^c_7UL$n`?|e&|7;O8*2IPa%Uat2kEL z2}5Qr1*@1Z`;~+ne1#7W%2Slk&*N@_oohXDAKT-q8t-P;idN8T{{);4Q_I7o@6d#I zg=u*yweIPBvs+vs@~eyXZixlR^g=TEBz=BCtzPf5;+ePUv67VcgbW%ELV^&t>5gUr zdvtHQJBFF4t#wnI3Y@7WJQZ|)gJ&Ub`D4+V?}?T{ngH}#tON1PQa%l+_M0AE^-!$c z1-{>_M}g=vH*^P{SjMw4m<>0(yGM+jdx!8ZVj4l8*i0b9I(*gy&;y;WFd zFzFVb`#v``4S-oJ`atoMVY@?2W#H3y5L6vtd2;n-JZp3F{zi zEX^b4p8cEFQ4A}pz=v?^=4$ig?SxE|*MBwK7M&@^NxvBm0*HY7h9P)o4Cu3MbcMJa zH2f=U)RlDucO9n-kKg=DdQ$->?5rDLY$WHykT~ zxqCtf{`@eBK2!Xa`_d?B;g=ft-bNlR zZY>nO7T-yqPV&B33FY+Ru>OCMN!R02HSwuzI40{Gt#{_n51OlOp*gCz?RsYBX&&SRC!2RH_QlnLI7{88;RUevIe`+3$U_(;4tt2~U_8})`YSPV9Brzz5o=N;Ep zhw^s8JFrMLk9kolOu|;!>q`*@8T2+ZhLrEn^g{bgwdRoVcaiN$X8--?wsLx@Tn&L8 zA^y`xVJ%G71^KXryy^1Zow&<xXajWWtUl^!Y ze6aA7XRo+wkX@B%$WQ(P-0PD3`6t7nGsk`LQ^IZ-rzu!*nh_S1nnYD@qyPY=``SjS zaYruk%Fp_}r?;%*5F~U}LYf41+`JSuFV%<823+FwYJs}uR}QNwhq!iWyC-)9a0tU> zoanHg!BI`tW$$3Nm1zxIHjIoo{bus;!a7i$`;ntziKptL!mK_2#A?Z5d&>{}lHBi& z96r(dR^FRWIyv->t+apI6qgUEe^0D<_F$rsLxKy%=eO8)Gn8y~?{_%=+?ivGgt`7> z+n$Fo=`dY$yA2}soQ<0O{FSu;yxtQHDk>=a=@h@2mx&WR?`yDy96FWBlUe0$2Li{dDgdj7WeWaU;DOaB93*qC7}pf}y5oYdcY z=C?wK7kn`spo|ImT9C=-!u;V2kBJe5(1xAjSz-Ri#S&k!^zYH5#Jz(tIyl{x%~yN& z?Ali+q$gMB@!;Uu^i5qlAGy@~3(PjI&bp@=3w5}c{ta@#0B507;Cvi!%JKEJ3&#rG zXZUKe&W{S#<{CWQl3B7OBNXxR>9X{L2g`kwu!lHlA>(_j_uu4Fn37vQDrlx?;pF5@ zlRw0sq>c$vC986ln6P$h{~(YmoE6|U5#dnDCLLlL+N11xO&VdKiRg; z8)xRL2QWS@_P9a~c8twGjfbF^D|zF+HC@a<@Hoa{8; zL5QbiO?ir){!l5qEd?vgla+k0eE4_6Ott$4=yKU?Ie2B6WL6{kBD1CtJZ01=vQW}{ zV8u)GrwDi_bgQLF?{<^y1F1Xv3sDr!ZCnHYjRwC({cyu*g{!5oT;2aTIZcfv zJf086UONxah3eHJj?hh+16H=r%Yoi{L48+DSV6Tcncp39ENAKzdnVfCCrlWn9M4U0 zKtrx+fvUV32}6Z+3&ny3EI*1Zk^j3mJs8sFeppf-V6`+hO=zY0;CuTJ4+7Z zK&VAEiBMY{8N7u48PiVJ9yU>Rs-VbvbkpLjiUNpCM?JHiX>rxGyO)678rbQD;KK*E znc;zhfUvRjJA%)38I%{>wt>-5lU$PJ4}3=#KyHM1DwI zWgjc9sf^f7FoJC5_K6`&aG%NRkE^hcSIbD-g;W*85{>Vv;Q=}mwRc5UqxeuZO^h*vDDQBvKf9iSIllCae zXyQlbIIe8#&Fn`H?Phv0ha`1+1G^vwIqh@lTZUXiwEVaNKaQT_)K?>*JOvA_5;Vta zZ0^qQ$~>f-S%rTH`$2L}^j2Ow?VrY-AlU>Bs|S_m?`MP$3EK`ghp2|bc^hWQpHBwT zl%LrQ)Hnc7KIX_XT?pl6asUbzaUGwtz5)a+!W8$+xx3|g#)!>oV3tcWBtG9 zJWaXjYd~aWk)Z2qlH~C+krXm`Bv*WHqAH7GA_xI>?%!04LO;{HL70!M0n9c7DsLGT+m6w=Pj02@Y0Z*&Mu{87~WJu{J!lo{H+<|*4K zK{gumH;i1y;Mc7JredR+0xrK!8ihoQi$`)=R+}6-WVO$9gvP5p9hO&zQ;pxQ(vA-=q*pugh7@tJ$Hm zSVwPK>r{Nmt5@q3;_){Xt)|*yWXV2W{42iRFJ8l9v1??Bp1C$yNqnqH`0cH|$5*+$ zf_v!^oaLSrD^sY?euE2W$H_nYOsmiQb&`%juIl$G)=u3YP~V>{Oy9_R!lQWjeC_wC z?alnO;A72Y?vPzWiP97=Bt?dmMd5&`4Oykuyo7nlZ0P-oT+O14(5=jd^F*cM_p zm%DaJsh7e+A%{M8BzgI5m}g_)y7XYV>jFs*@i8lpZm5q$LrISqWd>I+{9vi(<~bRy z)a%_Pl}G+0U12vadRy}G66sr&dxy>B?&O%rD2ilBFD+5)iWVl_?a^COO?iH z^^n4j;zbeVc#;gd1=TZ%FdCH?!nMitiKrBs{jc_ry^-4d59sLV5U1SebjoX?JXPyP zrAvSom{o}ic$Zf1Zq5&px9!nimyy?$-<7q}igu2<`>}3q9>4FdLmv{_BT9K*pxnSa z3k!tgwzPFyUF1mBX=|a29GDivyaJw90-5KDQhS@z=s$-Y>Axo7ez3F`zew~FYDaSz z6V#5H4FE?V2+_dwirH1L)GqeLyoyItOECz6CAxWPv3tL>G3W-e?j~tm23TCnal=1_JT8y6B9eI z7$Enx?zv!9Xv~XD=;ScJ*i(mo9b1R;LcYXE2&r--nbr)a^zWhIt=MYeCJAL}@7(@W9#SThYU0a($=tO_AoP);H3e1zeAgv&ZgYy6$ za_0F~z`!Yc4rju?4-iD2LY4H4(PPP=+|gNY;Dv zOMS2yd{*>7$icO^>jva8r_W}#uk=`)wZeN>%>(~gzk-7W0i0^+fzq^eZ`+&4O)cZU zV@S*f1<;TsOW_<_XF2$Cy$=oIG?-W6Yb?-acapkccXQs%96WG_UHV*5H+wqM5Cg6q z6Z+j24!;~3$V3EgIRBHOfiddSR6?(jWN~m^n+gf87;H#n;bmL$#vrLq z%Q9`%Vp%9$p7*?1JlR23F^1Zc`~a6K!ClaPESDH$`l+UAkda{`dUbUR{j^{2G855? zOQbh=m>;nFsZX8}K~}{g(B-=O>3(>lgxSaaVcv*`b$+SZldN8qm^4uyUod z>E7bvW1iV;ekba?HeQpK3t27KfhzWCMsIQIwXaV#nK0s1juKF}w56U7GTU~faz16q z2z%UNA!~I?(?sX9)?qBgfOMKWFest62re3iZ#Mp3_~`qPxEY{R6T$z_DneaSkd??7 zd@MZQ9rT86&|@&q6V4&>FdY+ksw%0{oXl$?N-{(lEHHDB^<8kR}X|H$= zygF+`2&68;W^N1d0^apvz>IA|0v}}V9(=czw{`ewyOUG~-*m)4T@H^s;uLODG)W~) zM8`(oQIh+L=FbU{yoqEt-uftRjygy$4$(Zr;hWE zrY#+w4-?bA?5(%6unoL*Zp24YAyJfl~iv zt@q@xfIMlbKGq~XF@Fc$Llq4cu{FEnKS`3=jgejdqp$@qZ{b$hV;K~`!Uba?CuoA0 zxPI>vAMMajc7uhaP^g;S#*igR3dB{>!{X;&quz&f#HM5LoVh0cLRp;h3X6-nqy1Tu3ehyHHE^@6Q`5gTlC7Wc)g7A zi^lkOPIeO+pLVS2zGSFWRGrVsmKohQ;6(DFv2hP3@S+q1NM^ZzwpaiB&>Ji~m3fMk z3%VAr!A`~gIhW%BI=GMiqcpAL)x90iHp?8_Ym?qKtdk45SjBrAyg6XW1K=JSaEF}K z0=Ma0d!$dN>PAW-;cd5yjhi0vVx&jzq~tq<-b2%ZCcL}g3Z##IO4BsW9`3&?G$KN| zihBfSr^SA0cz>lr8PL$8y!Em?W?zt%b3QtBgE2TSuk)qZ$}4KPv4aw}#O+5Kdv49h z4Cc0|@h_06dg!W*naYRYoaXAlN-Qn1K_Sc}n=Q%!*J}7kX6f<%-ZWe}@U!E;Hh5K0 zS&30>z`I1{qX$oDr`jcIesrj-|5wR`JajLZnFk*Tl7Brb5~d?t+vhzZA4u0t!|SB7 zyGws4`m!yj5EdF?LjR{A@K5lruigaKcP8oVZU6lvO<=?>XH99Vky}CE ztYFjNJ2`LSy)}%T4^rxiNsY7R?d|Q*SFg*QGpNu&khLORx7%^L=OqmyJdd$`>1-E}0cujW%PJgG&wH9lh@J{&?IW|}Tne5#A zNLicCJj4{h&S?M9l#bZ+odfW95%JdEvkvf1L;NV2A)kr? zlc=qUjgpBiZEcKh6P=M)!Z*X)@HYHl$hM!uWJSy;jVDr@0izlU)TVf zgd-KY_>)+d@moMN(QQ18goVtTh4?WH%-P7%tb4J$dE##k5eublg8p^5({t~_a|mSJ zHmpfzetz#%c4I2!ZRajy+LL&J1bRLX4dI(wYF|1AwZ5j>l^`f0GE472{SI>Fo}767 zq=#pZNjXq}^UImv{a7G%@QwtAICjfo7VRfiR%`x+ zwI&JJ9oWPN>6hXZ`haBRK3z4x-hg4$9zbvR6C4Z z_5KvJTl4D6BFNvlCd)RU0hE(yFj&i%{~`EKaC^M!dz%a_&uh6Y@9HH=3SD-cu)K(^ zu-s7AWMW5CrVsNi)>4mGArUqv>$iH(EPpatp^q)c-?Kz-cD{HOrWe+Y&%IS}P{u)o zU1$$fziuf+wBfj9tZKxMJae*K8G|=Ka#n=FT^ne?&P$PVgshSBy*os`UpP6d*r?$# z-9&Iy-5%d)NX)$Yo=lNdrbz|eqp;iMNzM7uX15oGe9XlPA)6u13{0WxxhX>`)gKK1 z%iLpdEiuQ%NS`Z<+E=h(oA*Kuui%0vq|toZEUe3B2p!Cq|8U!m>@_#w!>G39+3-GA zcq57Td7gMk2cnpAV73L>pPO@)?R~pep3UA4mvU6S{q*yK`|*8KgO11!B^P1n8ep+Y zG)a@9oUpdc_$L=mF45|)R8-Kl{&7{nh)j^ZYDGP0!+(@N?}>(RAi;U}YAjOS4!b>= z(&22JI=cm(KfZbP(ylJJDrb;PHOkDhack2BU7L&85Q56rq#6o0d}z*H+!N7YLQu(` zbx!L9g*}D@Gnvip5Pl4cO^EIBGarptD2`g^Iz@0eJt00Jl&tb{)p$v z#)fmp65E7t0hs4$4q)d$L{7qEiTwIZx$!x>ebkAG>3$G{f-hnNAJBTo%4u=TGLkJn zzACqLqT#l)}!bbasw-j}TxM#ie1E)?1@kyg4= zCuH9y3g*~fyJ~#@<|9uU%k;wcAD)?rr6COoJ(%e`v&6twhuPHcLck}~;RjSI>|E&I zk5`@iKfPR_egF|1(a*H2pf2N`4fvr#9+qoxR>YOV_J&F42mN5~iOLA8*Taf(t%I>d zP^~P-!Td?ZGf(}!0NHWQL0Q|lb|1@CA9mc}5dEGqZ;dsp`L@%Z(I~x-$e>H^imyqv zlc2;aFO$x)EjEPg!YAKP4?OxsDTp=WcR1hAy$nKBNo&;Z=$pAbym~fMVhqj35drC2 zBHo!I8yOM3NIBtS4|5IG8ijWz<9y6jnY#zqb!6f+vNbf{#?GtV@$we)!unV;lm75k zPop7ckf=&!P@20tB&Zzq_L&t%#7c5x$=3}v70~k5{_`fNRlFn|oA!OffxHG6*LB(H zAf&O+*m%!^UA}N4dnP+D`?QQ6cY*sK%D2!EK0Qs!zEl>}D*hTd$tGelgn|Zy(&@;8 z_Ov8#)OUEGp&pea1JE`C_6q*cU^hHON6LskV#j|^>ugDS!+$25Y*)Ml`|_3IxmyV? zIhszOcB1Q9v`E=2h#C^MoJ*bUMJ|!EBG(DVcZNdwn4H&~#)JgBMoy9UOB|#EBRq&I zi`QYtHN4_QN5qb^yuXOxR@;Lo6*0ke-6?PAEY=4Q7s0|xF)DhilaIU}xP1&eZ-!a{ zxT~Cr!yXTiWuRp_A8cm5Nq|XXiWA*%ABqj>8hX++B$G?~fo^perRwbQft6$Vm<$D&`hp5# ztXR)7|K#Cdd#$q4UE5!kuJg412PiQ8oPF zvI7uSuQXixlH(+M-K8{G^y%JzuNBc;{faS6JXqM^v7sOsMH*8FhgocOo8U!YHrnc0 z*qC5ff6hrekTJS#QSSH3z-@fA=@41R=k!kg8wOYr8#MDw`{F!8mC{G`BTDF@W76~e zNYjp}NM-7z%*vLHCi(CHW3jD07>X-^BDV z8}5_q|IY%PX{m_bvl!y5WkYJz#1An!a;B{E2ae1$M+6iu>BvTGz9hz+2<3wEEOQ#! z2(g;1nwb=cD<%$Y{m|n%2Te-sB%HoVsHV(Vm|FF5&9GOqD=%6D<&6yj#(TKmf$yDX ze%HnjYZTa1eEe%gHO+^jsua*H`0OPrn^lYlP||hazQ#MTZ*A-FdZ_*l$bB;Il3=r# zQ6L@ea+Ae~L!d^?9sf{8)P5cY^D363vuOH<`|hKNtk$mNz2ZGHUP=drrLbS6v%4}- zJ2ot1knfVbn=T#DH)M>Tc)HH}H|)B9xXjO;Xrf$jfZN*k5iSkk$mx0`cQz=n&EtU2 zG+AAWdQQu&@KXNVa6y~G|A@L}1s|?40Y91WwuT9yFAVg2X@c*ybJC>Os;$9{S^>9%i+W_PhLvb?S83S0Mio+yTu-gK zW2oHYFu~E}Qx(1wi5A#z zVfDW`JVY8t!cMd><@@Wv^^RSQ-5ad7Kbl=SoCoLQl1g5LVJjzEo4yWkJ!j!g!1BYS z(EzgXo(+9Ho5mNJJ?TQx)z`ZB>^m~;KhzX4yp(J{afo#~dx<<)Z&zx3g!9ru6ZB?a z5eQcW0BLpsi}qspNcE;TT1{ub=A&rzEuZ6GeD44J>jau!xA%+LdcUs^#dpMc2)33J z<>>-?NE0)Oi%|{Nq-FoO?aj7}D>Jr5y3e5_7B|vizbDMj;??n(-^O^_KvQORxq#KG zkp+o1`K$opv}KqSpih5#W>&nXKUM1{ zx4sEr3*)LDAG@v2-d|V}946>%vEL7e00*DhDtTt9VF@cRjt;D9I_|jbnGOYgySAx{ zS+(xMhpW{{yU!{5AY?mmMqR*xu=C!#2SwS&@OE(=Tz2;`3n;k+t-m@1z0(f~&YBo& zeL7RAvQJS7h<|oVtg8EakJSyHGC9#plA}&gA?{beA(fazqWORa$1PhbExQF|Q(Rcd zJTvGu;H`b}7X|yDYqj!7TlpQFa=My6=Q22+ZbyC$yPLec4qtrLcwON4UX>HVlrHk- z(Bu#|BF?o2Wc?i{s;{JDZBiQ;rE8T_c#{wYpp>VcD!e-}jrrxUpz1{F6N?9u*n2CM zCftfTc~?%K1V`jNciQ%I+Nm-5%QFfaDKi+8hdm}#PYvz>%v<%=mYMCh;dx;+Ycqi3 z?)?=EtZ^_g%H3K$$c07zh~c}jrYiH(nK+LrTDAHitTK#Fcut5Y_^vC57!sV2d2cE5 zaKi&ULlc%aRBTpd#l|?4f{HB*we+oz4i67MWP$$x)^aLkX%qzePJQlC(m;o!jDJsy za9Dbm_Xty@6VB`t@s{@*{NkV{uxEfecGf_Tm`4>Xw?^v-uBiAd~ zz69dztTtU)ou+{LkM^yqj67`KDCQ2FcdzIhE?7!M-)<(a9Nx#V7 zLfdMCrVMdT`OW%JTQaohRLZq%&{utvdm;9x^gh>k@mIqz9u@2siiZr~+DG;f{@mvn zPY#mXx-wJ)L)1c&!H%#$4ks+m!6?-Vy=Q}GvuO=91;)0JI-9ImpXrVBq=g?NFRb*d z{?}VCHr{7mh+f&hHQ)L6UMF36UK@W{Po-~y8_;pf>*Gg>sB>RP(=&pO>7;;kNeq_iPjw*uQc{v0`l3_%Ujg+fxCbRD7m|ig zs*t>I%xTV*kDh&OYft{=JxFUN*M>Ahdxd=!9uEpsX{kqY;m5>G6E|$9zxTJwLjp$B zf*MDDD_@JhUV)ty#&sJl(kMH4eOrnhq7geOVtWf~EPeYh^g>Arfp1wFZ{33F3Xo#3#W$k*MGyU(5FeX%2fnBI zpvRq^7W}KpVt9^?haS%?%J+HZv3q%qSmO&ZXX-B?2$gAAkyma+%kby*0c7Nh7w38> zY3!iF7jHn10?h>%YYHq1B_9y&s2&!!n%(owS9ZtBkO=bQnGMF#b*S+di785hW&>g^d2n9%e|qN zxXg@Dmek&to@(2CpxfC&kr`_!H=!)8947r-ax)3;Gn`rTtH&kqj#XXC(dFn*qay-q zNhfQQ>0mgUK~8_2&M#$^DJ$Exv6rrIHAmAQrk5a_Y)*V|F^o&Ny_dH~c=DEdl+(_X^{lJHu2n8P5uUoYd{O`j*m6 z8hmW^YF@zY5Dz6}O~JBFdI4rv`ILL1&x;;K(^0*xcyHOg44A#Y?EkL1pv zH`mMOQFl^w7BbvP)(WD42x2q5Am$f+&)yXIK5eO4Z+o9Ta9e>Q`7vB~^g|$6`R?fX^A#3AR;9Q!0ZpPwDkc z>&|e9nfW@u_uYe%RPokhpZoWTL}KdVHkII#!lNCX-M3p>lR``Gs~0&s?J1gui85~f z<06_#p*&7bk`r-0$MOs)=!`lJKUQcMYmGTLL`I`~dSH9b_c~5z2Wqlom)MyxB}nxq zujX>lZ$^ss_(1T``QRyr)DBcfTs5dA4xs6E<~QqioF#05t=6elTmO_B37Bmgm(_i2 zsF&I2d*=G*p8rH(j7OWS(6=HDqYYb2wC1A{mNDi}LeOfx?XV{NV{&?blbY#Q__n%p zR^B%-mGIp^`u0?{nDEzCaPqVP$)+4F8X%p83g(Hf#GQnm!&j~a-~9^`l~j!*P1U5M*XbXShMuehT47gOt-vkj#;0uyA>D<3xG zAKNQc@qa3O7Z(h7pF7a8uw^GV$+o2v5jCMYJ#nyQ@8VFJ90B>EOP)-4pr^3Cn3*mI z@X_rM8tV!HGQPR0?kkv0JsAruEPG7;l}{IpW)_-7C`1Xb(>N+q8FT1g%(%t!Y0|>zecW^ zUvVRZ(%heu*)U?jxaah3eaLD(sDNPz%V;=4NYOX+Rs5OL+D7t$vn4_hAB`f`v_QdS!AU*)o%Cw~8!YV$v^{Yw`(awRWOJWKWD2LqjA42t7P;?Bp_RHK*P51+1Q6Kf!4hD1 zmES6~W)AeIp^bW!wF>9$(KNNGnl$xI&M}Zg@>1FRhN6QR{KC(aE+;smRY{VZaG-o81-GHj^F^-XN?q@`yDSi$o zK=&eLKVm87r`-unNwX4<1Oit=evQq0U}udi4_{kX`Tk9nGqX4@qg()lgC5xpl^X#$ zhrZ>DI2)N)P&##FAk`14q9((Cepq0Wtf$$svg{hV;s=s^k3v8u>!`!dX>c z(l)NIu6FjK!8{CrEI4~jvTpAn`5D;`*45-;buL9+3UhdxD(8k7{3Fz;!~Q^i4>a|h z#@@@Fz}REye@bt!4ABoe;&ZiP$TTY}buyNi00l0vc^KryL&~i79f4Oea2uOOEpo!v zOF;_-?87VWHT@Q>OgHaw5__DtYySk$W*DeN(aW&Av5iz@ih(e{HcwF-$}|ej$2y?s zl?NlNQ{(4!?orRqdwUL{3AD5TR@tZNjXX5G8p#={J@i@Gfm<8WANSu%5%P)QMz45;HOhMc4w0S5-_UNp~Yz;vkXC?#To9$4fo zype+rVBB&VRRJ{_rqSiD(KEv#ktK@Z)0poADV#hg?f#|ItqQ0S9eRSpe${!jsDrYG z&Gh4}QtD4>Vky_mJs2r>|6r6@H zB}Hc+LGSq~D7#N5LTy`=Z4$NcBc>2BPq7lSI`M}qRwAstl-37J(~k-*t}#fLUB09w zF#TrZ=dQu`I7Ry)6zC)Dub(%&Zc=42b$UUxfMcclmWf6EQ6WIYQw2*fB?YFBEs zOfQ<+HTA~-*ie#l>2H#2+5e_U%xygDbpT~52Hy-jhN)vmy+ik{FW9ow2Hz-kG6h}y z(4S8fdhPv@iW%;v#SStMx*ZAIbXHUt&9uB=wa@BC5Sh>;ZKov!diHfc%dY_CjVT)hZ2LzuFzJq&|dOD2~EOSKsG`W z>isR60QbsP759@;zA+^fI;nV_oeuKbgt?z18aBy(=Kl2&)&T0!Wo2sJ=55*cmD2i& z7^ogC`Fy-h(yfvJm#0;;`*caYz`5g7R202}mJN2qovnsEXX?`AzOt%mfLS_Pj?V)6 z8BvY>jdJRi=nmLRT!~`jX&Tuu`9;0;v=G zrQC>9o$}kF2-u&j(kh0Rw-=o!lUn**$eQ%0BkN*rn-?#FgHOt7L$q=zs1N*j>Zp5f z&OPQCd8~hF0{U!-e?aHB&)3)pCjP>JMCKWJM^k+<^`8n*mYE zn0lO@f111YfW0mJXdZT-8`3FBz)4T@Q@+)CoWLFx-y*+B&RgfkG2cS_sk{3X%aDY@ zn;unTRG|OP|2ZJdGr3+JB104s7Bcu3#!XgsR>Es=JAn8Q#Rf-mG_ucDU)3D<5>SSQ za>CL+>TlSQJHhWK;}ZvDsclsNpGjdOwajxemQpZkJ>{qO2k!MD<>e9z*s{Y1%Og+< z8gtFw9%B!o_ipQP^pzjnPE(Sn}vQB;Gombv8{Az zdudGFDt5m~3aZ$JBr`EeTqJiv_@LIFZ(hI~B^1H}1JOHETkFj4ea&nRdU*O4+f!1z z=`HRil~ULcyPE9ZkorX8kocsdD?xd6uT87XcNj)B91T>oYNO{TZpaFP?qAVUVN|UY zC3qqt{S?sIlBQq9k@wvTDdG7a&GZ3WHGR}!?sYxEm23zWD6<^N%FkaM3Yp5iBasNB2h{xYV4PmhyO(XUZV^LU33@&1I$DKQ4n>xGNW}HPnWBg4v>O;M=gD z{Y$&8@8jd+P@p4ub6%p#xcOhc2G%7GNEdNpNk?c|fqLF$Zy_wxsU4pWzpRpO#*ibw z$4J)^Hd7_3mYT`s3_s&zfTh7(rb28hI;kv2LyNC3JZrupns7w`B)5&#xj!Ht z6Ie}Qo1-#;eb6{(c~L=OlY@yVy_6cN@t}ThZnIEHL0W_1GeTbNn6<+BJW!KW;J>%k zJU8~nc%B1G@K-OD_DdHnB^ME&#hi)GKgN}n{Qh!ZUcFXgUXn1}tl7zL*y~f8zWd?r zL__(g4`aiR@wjJ;okjO_Ry z;YHEHQRbZscjXC9B)EHRF~NH`1|2(uB619KWbQaORP>A@T-K7xBnttRN7-?z5O;+w zqb%o01z8jeI`rG7`#sRJ<&^8s z2QJS=GLN`zxSPXP&s!UtGGDe=TR(2NDkMLu+Ye6ndqG4=1Li zqzviYCYN8B?=SfZYehos32*nAO0bkJxi9VKzIB?gkg;tY(SHs(geCy@e^Z5y@##Wh z7iqma)R$l@XCm8w?2|ui^vJia&0SOj#6{*-h5ypa1PiF}yRcj6#dr%nGKp$RCU0_2 zfh|hNeIp(AhQ~@|=nM~=N(x>Zto%8T<^f*JVr)=FX3d#&0$dZ{+HL)Xrw{hy4xMncY?Hr;eN73y!H&PS4!A!UtDz*TGq~&Xq#JXlaJo9-U0%5J;#Usw`xhb z$Ss@n)WU{gZ9rW+0$g_exHG{Z#NcKkP8`{feEPtEltEFSV4A-#E|as+AjRqS6#-L+ z)|TpBXEPj;Qj~sm!zI|uf7{E0A}Z+bL6qR_@pHZdl(YQszTqVGk=Aru2$v7*IHe)`dmP~ZO#7NJ`B7JCp= zO2bJhI@N-XTcI4*(_@#5<|;n4sLKwBx{unG>ACtJV6?NdljM@avRZfSOGX%VY3GO} z=7AKSh!z#Mxk?078RxNtk}gQnJws#{GaLMaBYKU>9ww{VOf@xdD-rs~?iWC-J3t79oM!n@WvuJ&|h5zZr50ZB|t3dw#YxhTG8fR~_ zNOlZqcOLf**Ksi*Q{z(a{UXVh&H1bX3ljFJWxs_fSbm#;wN%>0o-TbV+Mbk3sE(6y zdnU5+B5$a{@4IhBn#RSRVV0f3&)cp8LxVIoDYtW2FB$t>Afh{Z4i7^;(dB$3*~W|t z53YE;U)a{}8-Jf?oNucgcf1i5*9%5f&h(O=>sr?c;SX~K9NUl6)!+2f%?Z^?$?)l8 z0s}uGo-P*+t6MLigOx*6nn;h&MQbA&HJ~LjiD7K@mcmIv{GQa8FBut`>wPCxX4xCu zrNb&?$0z+e`M|esUbr$VP)NYLmz9h3W_#)td*fi;)lF5$6S4ijvXS5d8$J35jqRjH zGJl3|rMU&evz^w2H|wMuGmHBP2g>?m3&_kmw4c^l>aLyciBVi3TSO%2kKDzB(diGo zPkSS=zqiNWAr~561$Mvd-`O9>ZA2V3wg;A(F@{t+IcD9etVkzW?+}YbTqdkbp+*%0 z-w(riB+-G^?Sr>${bfx%2^LmAte)7->(qtb^;5%jc19nPF_qBA!aOS=xu2_MlQ=M2 zyYt5xkg$&&p6wX&|R7<_SL&tMpcGU1%Dgi`0Jh$r;xp1%F_o$PMqV}*SE z>N6D9r|M`w&nt=dKmSy`0&NGg&+ok4cnD9`;^LjWdFxQtF1;J5G~{cqvp?5lGO8uM z-upK@H%E19&%eHP5PYw_-~~zKs$y}-DDxvCm=zvv82+S#`x*WXd^Q64L|nv3i(26e zOgqIajJVJLH;n*XSw&E<>V=xgL+s}F^~LjNlD}_>nNrv`qyXb9L$QpJWSK&A7KUuI zXz)n~@{_gY=Ea|!_MZPo(^-Z!`M+(PkrL7%AOoc9hjfe%K~iF)q`O3FpmYdG43LnJ zl4cvDk&qG?NY^L<3CWQvArjC0AII}*uXc=s`@XOH`d-(0eojM=vVr;2zC4QlOvCP zSb#x7%Ihd?9im%^>oXwB5rD#CQyDv7o?Pp}k$Dr^X!Z|vV zX!@ojjSm*5hz)vwG?p+|USE+uvB;ORfVo=ERf2j@5JKQ1s)D`29W-G?L%2(8wAHHu`zEZ}`(XLJZAY_)sw_PFG2z_gSDG-8c*Ocb0tG~Ej zSG2q8?^9-zJ^gRr-WR|=Ii?gb=omVf;wZX1Arl`XViald1;swZA^A=r08~*(JV?F z?y(*ZRN2;i7g@MJ=@`#jDks1GO)>U61Te1>OR&pAqJ$gE;hC1sS64lzLzeh|#8s}+!ud}c4O zl_P)U6jy3PnRh#D-tQ+x_-X$b9GU3eH7kqO%&<^OP8l9D-c^C}4%GXd*ZweSML|9X z;Jv}0fLv>@U_scx(Ka*o+LNQvey9j}rdBf$F2c^44V zc7!5Gy*Mk>gQ&{yEc1DcNc`SYGQrBiKTcRtq8$d+erD%2Ia??TO*ROlp8_Cduab8H zf0-4lUiji1&t0+r?Gp$YKH?PnBs`$@^bG03>OPL?g~I>t7Jnr4M)3cflx8e;bTT#gKV`)y<_J3CfPF4JZFvCrw7Il8sVfmfbhvdg_D!;Nkl5>j0{_WE zD&kCu6=@QBuIB}E?hSWAE6=kR=4BHHaJ1aEIJ^DO5mxEN%>pi7@wE?~rY(V)3b75( zYVWH^iZLg{E$@jJldW`_o7gW;&{Up;2jsmL%*JswJWP*;-FF4I)A5_=g(RIr8hD)s zqxCGFi` zxi}=Y{ZV#RMzZuoj=EpVpGESc9ZVUGBL_SN&WzVbn*FTKy%v0ZU6xyAKJB4gFDor? zzqz4BGKVnIb7gubUbBCrSg-Nq(OyF9rw%)V{1z-F$BH2XAu{PlRS{5MvHYzPiER1y z5J?*NooiD_t@KY6LK*cU%)qIBRs%7;VPxJJUbN>d_a0!ZY82WuZ3g`79q3{WfP@U* zwOec%l=3|Jn!&MUPAynfjnB`Zs6>l&xOmuGxJbindQkp5q$LpBi5y_#y(hAlo1mJk zhNVmqdE`Xu#JLMUdJyTVrj{5YVI zif;Nd0mGG*j?C5`hvMmI8~3?}#{M=xP8`UY_uB3cy<_{VWqz)boxxUqxJ3rDBZH1| zoov>=%J^Jl0)<|>t^JE>sk?T~4-SyA_V>IyKH{qfezLAgn|ZXGdJ1xXO`1%OdsrFE zj7>E!&^hU$D+kpXrfPi$hANDaOy*QPD{I{Jm~k4_B0 z^X|Wad%_8eA*{OOK)ns0V+WHS>-k|H=RB*SX*FvKtG{~K$IQO@fa-mlCnvAnIKdur z=#aUy+MW;~Q9m}C^l|%ZF%F<(8_Rb!>Q1!4+2X)|(5_KwahHOsD-kT zTMo5!HvtK4NzNg^)m$7@T#ZY)$=i*zF|1BKL`P2)=oT+6=Lz*#0{6q~ec39FpyQv1 zrA9Q9;Tzov0z@f>4xtF;zJ-+12)&(h$CBBQF{>_O-EcQ&9{nCJmPP^Dn4LWTZvTUp zrZxYA-y$SW9|js2d?aWG9~g|u=4eEvn>;0&Jw@7`@-vjXHuG``ai5ihbRr+^x(1-f>4?U%#b9Z>=4_<# zu__T9Ra?v6D=188kuA|?6S7xmUH?h#p?-G}4irR+%bN>a(r%phEH{}A<1Y}ThvCSH z+S$drh72(oq>CF1--TZ#hGayYL5na)Is5nnt8 zLx(%#rzWtfa<5U$vKu6z>u-S*s}3fBDHT-n_`Nze{;8gfHnS&`^F&aot(pb$0qP5v zc=uF`)C`-lbZMt|NT#H$prEiHG^fqtbSWW}M6`-ywJ5GxGb19&uHTkzn_v;jj_XdPL7bbknr|Ft|EOMyTMdkXPS8vk|)rL>2Xrq7i5K=B~Khxsj;4v#q2cIU3;n&9;OCgi;U z%j!6-8+m$b*Lt$3Xcl&%B=TcX4t40f59uwr=d1z=}GAgcZ zzNq2b@DWC*q)oPU;m{&^0nfi8&S_~~tZiugnb`S=-~rM#Ort{Pu}1_e_YJ?4pmbw@ zYmgYXIZTb6HCnjECk95xqSEZ1@N`|kU;5)l{M^jAzWRP8dLKM@49OZM}gQ4&9shsRKlj{pap0>pUVJdWDRh)cKAhmGLx?HV2HV`x)m2eTt}3m-MIGtt zNwWxkrHDhZe8T-fclY6-hj)%3(K9{ftHV z<#a>~7((~;SVF>+In1Q-Qw~#VjaYN)^(I3rP|bOK_t&0p2@6vp>(k|~AB}|nh-)U5 zT_|oQHCJX%vX(1&R9A%GZ#^^b4!}t8yGJ8F7r@|cng@EP-}bIRbYzftSrzRzBk@Ig zhz#Z$=yd!eh6`!HK#)x&?juMs|{6+>72gHxa60M;6x+3Y3b$7P?^1af6m` zBiWDLmA2mUo^{SQR@kH(If|R4v5aUb^r6{NZKvk4;R?4AxGPNTXidZDk&g>uNxDnk zlOlK}R@~@O#Y?QQM{hY_wnQ#ieYV6*F&h1RlyHP56E~76txSe@4m=AY$Onb;Egkh# zlu{p1G6ac8C&a+or9DOs+d$w4+3&0#J$*w8CSt6c$qqCWOi$_22`kbGrJ^%oB~@E< zH=j)9Fs0+G_}h>@mm9D`Xa5~_;@DD(Y}`pZFKd*E2@Z-~un~K$b&SNz5Zd*js;hsT zmDc8KO`JDRBj)rMjJ49UGoS8fbz7DlW0T2A8Q9MQ03)|R=~C;p+8DdX5Dqu`=*=Kv zykR`3Oyb_0*{AoJ;Wk8YrZG0HOFS#zqQau>SfGo$OKCovcUOjn9T=n=KynLv*?>LwvguSr-Nj4aTOj4qLr$ITay%T0KbL3 z>pTrtLg@Z`46TLKq)GA@%zPh}OS)e>J1{%I8hFUGFx;ezy+9m9f}RUip)?K{N`VP< z@M_e!f(y&XpBFR;kG_Vv=zpel-2L$#=cpW=#6{8ZwdFX#CGu4<03nJ;vmwrQw@7e0 z{0__|^Ywwt2@6td=1K+h)i@Kl7QbHyPr6!WPtdg$|GC+}N6RrKX^cdH*dc=6>oT%KeLA~F=S57hY+6FB(##xb#@WV_s@s3K!2Kc4IKcF8(mO5ew3#Z1Fo zQaz)srx;Gs>&00c1D2EQJ(E!pG5UrpI`7)Yk4PFwA*`A#V!HVrBq+w}9Hu#@*v(-s zM*E*&`4}9JF)C7!jTTqcyS{-Cbwzs4(JgxZEoj!xWf;)t+KMO1RO9n2m zt@05g7L@HM7qkj7Oj8Ur=HNKl9G4Uxn)02{r{&h}5WlM4l;Bc=Ss~Cg(!705N`pCm z&Tt`uw?CGj&WFpW%>YhF-OBuOaRZ4-YbjS32S_@5TiA!>h|Lgty;8;Gw<07uR_`;c zjP(Z&eEqSK6`+jj@h73r?)ybVbl?0-0q62ez__^)$Dl0t#l561=un3s&);H_?h7$yC+1_p)-r$O%<1~f8 zarQ->yA+XW^+kF<)H?r5*atgV#F$|+#Oscg3|!s!XfIO;e3Ksuna4Qx4$7%<@7jIQ zGmL%2IW=n2+U~}qg7NV(R4Lt8k?8--_-g!?$tXYyB!Ldq6m_789fmJ88bDMx+_v^y zoMIc*Ydw4X8iy#eiinW(GoHM?I*DqSEaPIzXyFBY4OiTz5AM+8-prp(K0vFN9|WqQ zdXE?2MfD)Vs$}$B*A;PakT3MqM*em)2xqokEQ(>XDR4*MXxh&x) zr)HKn8nsWuiWm-rUsijE51)t0W~DI2wyVkV*5Xk^9~amU z;LT`Jz$vXp+dI*GXjJequDy6`G8!i2J5?|iYkIEyaOYWGxXvICp!q`bZd!Adq7{j^ z-;S17aht0K`G%OzvwEfu*SWX=3rs~jcoE~RlnR4Z+IzQUM^P#KzP`ToVVCRi-^{vx zW*y>!$CX>2g>KLp*TV7lz5h#{a#UdVnf>5yii7AXcU90FqdgtGlv=t@3uiCEy>il) zpj%))f@O7idD%<(YAUq_w~{)XDZ2gbNY{ko+IFdCf_T)XF6>w(VB1bM+3#Nc?ZbtT zAI^s#&a+LtJH7QOnzJ-K%zpEG(<L|WaKhw*U{wNoG@lcT{dJ(iuu5NEej-f^ z?@yhR0re zG;egdva+H$6;@pghCX-#licA3(>*A!HYRVUd9LN9Mht<;ZN4Pom+C^*lQy4=vQ;=n z0DlPp63udofx9pj5iGod1CuC`j_U(OB0!vDbF?h=qNfv`oaGXfb=3?C;z9*(ryh-> z@AM3h8$05x`|3u1)rs02EG-fCUm8jgk;FvFJ;s6?_H;`mtI9T2dGt)-6l0gZ;>z2oQZTxjTl?CKR*)|`kM~8gcW&UA^+^uk1f=6dvJV{)A48JVA)vFwa_1b?5t-uSC{I!_EnWQf8klvQOL8L%QW2KuboRf>R zHlmY+i?nLMR)5?udpN9kJ2}xzN)y9m3gsj=glw`AY`g;?`Y$@p3Q{i1573zjJ%xh< zN&Q9=fLjw4VDAUYlV?m2xNmG^O#|3w&jD@@#}g>e0H5(gf))Y82z?bIk+xsy18iHS z?XJmDTb3S8sD{@ytYv=MQvqvJp^izZdD33sR;Q1k{UU9^ik2|Hw|G6W0{ZiuG1;FltAo*!ya%x~Sj^E=p@#+n2U?SM%(S^N(*g z9(#BH*6sdH{G8lhQ0h_CPNYX*po=IMiIYJ>wUW!uQQ^?9(Y((*&GDR!_4A$C6zk!4 zUMi5VQdyx9GWCEQIg+Q%YCNvmw7Q=`nMwkJ8BS!mkX;>FJe7b%midt6C62K$uQai^ zJ~A-xRRUMIUK3r7CiYmYMb#MyrY}_dj?|2&E7Q+;hOFBUsH7G1%a-NY6dpH~{*wc! zrbWl;NPE_~6i5t81^{Xu0o)))c#d=IMn9h(iO2z& zfJ(KSY!6$797r?5ECWHtpK=Ky@BQdMK&ww|Y_FiY?w@QnWLS0ll3O5IG1l%Xd0caT zaX+#;1-b=tU#Ut@l+!6Kp_5eF&xhpI;NEs8kf6Z#3RIizbdEh4LfB_%58=(EzuZV>^J-aJ+>w$uWG!tDSH$WQc| zM4e5c@gzdt`wMJzsix6Rg08nW_s{JY`VA%=Lhj_Q*-I+K=q%6m<#z${3q{@Xi3i{21T$(wSt$d{$L)7 z@f#xfAn(uxF)G$Zf@VDWq>luDCd-XrCv{<#McvYTaL+ydR)pgiUL~=e)W-ZS+s0FV z-aFaV&1KCgGUl2+1}4ZRBU$1~CnQD%SL07SlK5zChA!84*rIseGa*dLL1 zid<7VZ;IO54*{#`XuJ#q!&3G$I;f!0ATg2cg(w3^HIT@(oCUHn0cOie<^}T(zI}YQ z1iKk~1ADh<2)#gG#QPE+u@hI>KT6z`P+O7JmcJ3E7H zYmkD))_+F|dOs`2e|*6dm7bdV6PnJfzqwCPiDef1Da0+D9O4ra^7r079L7;0g_3h* zjD|sw^y9WErkTofV7N-{q&oTl18dqg#~6MYU?23-am*O5p7~mMlz*H9PIwqP*s2#P zmZ`fJDZcZjN=358EK_5U-cU-N9ZTz0`CLkR;oZ}AEFRV_03%iHD# zerx2*uJlXbG~s6x+#2U;zCiG$^2nos{HG^m*WV}bA+RmM6#GuRZtO>syZ$s zF)IWY9pjSWxh6N+JrnBd`Q)%|KONZ*Cozl-7J&+i6UwJSZE)IWuBSs%3amr1&7w&R_bf5NHPROlIs)g%C)X%_ znbGyk5c!Ae2!kO8Hr$DtRdiUVQwJ z4FTSA`&2t6Oo`E~A1#=#j6os>@g8b^a4cZBcG}e2rykgF3>CGm#vPRpw??v`CH5Fy z-nS1R0o#{UCPvIJ8c`~fPNpXgV$@^YFY5aEv=`vcNOH|Axsr3QFDwW66e-#KBhwbt z$tyzAw>xC7p>Eu@q*OtKRdJD5#ZSyWRqh+dJ4%i_QvzD{lk2CspR(32-^-^>a`A2M z(qg<@2u5>O-O8i>BP*1Me{$BP#Th?#AMNLOekhd-PcirU{fx($Yw-&fOs9C@atz2| z{^iR+ubuyqme*CBw~Fjb?w7}y9;|tlfm!b!36#>PaSWzNK_N}H%MzIr5XiZ>bG<96 zmJ$6u0X~6eB|P_0T~K^FE!GtF;>0n3hM*3<88Bq30u$!_*pshmbWHUjeiTT}49VH) z5UZe1&b@j4MG!p7x%CtiWg=oKItJHBMP<0z{m~?%H#Zn(%NAou%Zl8z1WG`83&qY& zv#5HnC;EWh8Fi=|`x-xv94cGh}Kd_v+H*mB^s?}pIs=LFEeNyw`2Tq3cb(7Kw3=4+M zn-H+!|JOXp0(iG_8Qhz>E5<0L!yiV7Cq4h1?xFCsxmk3A5MNa5^rICf2KQ#c|JMRw zTG{k|LjaIuXmmkp`&+~OUpSuyt~t4A$$o6BM5E?9J8`9y=FzpU^v3^o4=~FhJql4( z%obd;Ff`hfg#L#x;J}AaE*skMeS3KJ8qqg(`58CbB=pPV)fsfFBKb-2Awvvw(iPAH zdj4Fh*I^TQ&j!MHKcrjzK`~hpC*5gjs#37R8_0%4pBscS5gFO{j-9o}*|c8J-l-k> ziYkYV68}J|7k(OU^^4{&oPbh^a$khwzvVq642=rm0!=aeNl`<+s|xYMQWI^pFQ&Uz zzd?!T6eM=XqR8jEh*&4B;#2ccg$>2upRPygYhYJcIq z-!F`q2HZx-O%2g_I&S~`>4zJahkT~O^+p8oG)1^c`5!_n*Suhz5xOY2@A2tpU;TRn zdWP*Og09AD=<1%K+XLtcPV@EZB1XT{Bn)|Ge_k;3xkgL*MUA?&9BvBt z7d?upPZ3DHz)8yWq3|?S$R_^SUkWn@+&Fr_Va{M)^8F`(_>NkHsI(@KR_rN+MJ};uvr?xRoZhwJ(h?lz;+`Z- z%?&aF3PnPRCNR~WzL zlIVjBh9rqSHueJ$E*H-~xyrv#Vr;Byi?lR6c!?lpS7L9VqjobBF*i@<9Lnyx^Zw3r zp|bcm=->nM{gi-f?(*qMhiwE4)sd@?21II&6(QL6OoDTUQpHuDf^eSNj{S;P$_29! zdt_z4TTDy_0wU_iD4R^M&5Z6t9uAwG+FrfONo@-CU(&7pA!{3}wXpcp*0Vc?SG8hJ z^w>+QdvGojfCc$3$TG=&{+`o(?F=Y@LMm%SmN&`+EinJ$0To!-X>&+Nz8n#;+;;F& z6~bO^S?$m31XGnsoMWElf3#0uX1vYP>@Ldk4CjH+M#6pJ?U#a)V>Nrj(N1eRBx-W{ z286S@=>N7Wb!=O^cmvrjGNcRW;b_Z+SH1Jn8(^aPv=zDV)UP10XqafZhj*+UqyTQ; zT-{#uDnhf%l$7gW*_6(rYARp)*yFnD^}6f_3ob?bk3tzFBtF$FBlTCbrEGH)F3B&< zE-Ko%{14DKe#XFV#Z98b2Gd;9Qgx~5jA?m4?F4_5C9bA1+RQRU1HKi{*Hs%);#^iJ zf!QNR;V;zs=!=miO1P<-euMe?V0srMO|Vn?K&iO(v-}V!PHj3W;7+_Lm#7^BEhxqo z94eql2H=KQk`kOXK*KpG3FsUcsGp`Pl~X{VSBs~mkF4V`)I67mcD`0-6Q zwydr8;`5HkN5A6{hDr%iyCB;v_d$wZ*-#wz{q5T9C5tND>4)V?CFZ(x=0p$0?syk~ zhl41m)`#@}4A!4*ZKDMR#~9X7LOe5(GIt=Udswl&##F8E|LP3=^Ajdz0ysN8 zW7<=%amap-(~%wPT4PTOiH9nVvK@RH69lAjKB(>jjaWzHa$EVI(IZkW7LY`#BD^DQ zx~TzypxdsGM&+wL@H9}nEQ|XPM{VVnC>}1% zVJ+zdoRlDs4Clg(Q>bF5Eyz_XJ{JG>9M6^HH>0n3CdMVWx49Wmds%A-yOz}^rI)tK88@+9HZ!_?pUGrL@Ot^O zW!m3QECpKpZoM&23u%+>t7$e^k*5xcS~B9cTZJg+5)|Xhf?iB!sjWoKtw0goI~2m^ z>&ZJ*?VfGKj{m)4m`u@R*nF*7DAglSdHhyiqsddNuE2e_Ub8qOZ})fS@-csyUf^xH zFPs1giaN6}#4h7ON^-X-DqZr2Tr9TqB)*dB2C49|$gMF+upoZIW*n-FIPE?TDVwGu_DOg-u&RGHg5i!udJ`=XScp z5gjhR;Zp6n)oZr3&7V1_r?uV673^L8!#cOH-|T9o&L5K~U-q7N9)}%&eOlTlo=F(@ zErY^mAnZJb{d(;_fl7*#&$R^=kTP| zwBHVlqawWdW04_zw)(DZH=Uia)?Djl^AM!uw(34a%bxbI4y--|^Wi29)PLiFALqq8 zo3F|eNYpra6c&KzX;#N;s~xII=KrNihc%kE0tR}Jo?@|Yyniq|v84ebMo!?uwFCQotBgdawwyRc83B+LA6sGgJIA z9E-wlWZ+Pp92NteVrMOw&kBSPl_Q7djX!bi*59P=%cR4Xx7#n>j-K-*$2nie;e?1_KK0qPiM6Mdl+%M6R~RNSZ^ijTpjc#)_==HIMsnNlJrC3mL(J@ z+kn4XL`NX*V%;e!3vtRHqcsZ?q~9`rB3?3h8KLFBy4mnU#LoI{vx+k%O``KwB%;g& zp%Gk=CW7OkR>?(!bJ7Hg;bZ|Rs7DXabo>20C!cjJG-3m?(sM;i>Hn%IM#Sd?1x(^B zie|rg#*N1vvJRsbFFy8TXG)$$Q6`p*Tis2PP9-$*J}C?iE0|K-xEeHP);`E}R+hD6 zrrR;dktbR_4QaiF=YVDg5#tt{AwzbC^H~gb-U`APX`PIBl14tiedpI5BCzO}=E4Ol z8CpE1$dKf(rVa5zy$&xztQXJ?VqB%KM8h^yLLcoB}^0x$*ixZ@Cp|c9UO-KJ)S#C7j1{SwpY_! zkwY8IXvBU=texrfwJuA8_O*rYTkNuo3CWb?g6E>aq-C~Jg=3k|u2f09|txSAt{fp6^Z@q-BFK=;`;vO|L&jD4( zema7IojLZm2a7<`ZvGMDzbUTnfi{o1k4Zh_hV$>{K6Rb_*rBL0PM6ZYpUCnCdCOGm zisv!}@59BPF1SiYOfVyI3T+EyaW=o(ln`Yg*TakbYI$?hB%6bPRFtiL36ptw|M!Jg z?;m#CH61TL+@_VPINaEs0djW1YfC|Dda&;}GDk>q1I}YrZ&5$#$R**;tzqr?{tZu$ z`rxpUEuZzL%(H$n*`Nv9g3KMYS;(Uyrqt^HK!F2h=7u}rxRo z9&13zJmAOvZP__ia8*&uAuHNc;AFgi$5Sb$g7Yi(i^zt~^j?7N{w_OXj5#%LyR&ut z^C%OYWVx`2)^Kw=YUV?V6SVBvS#3nv-}6u1oj2&0*Jwx8I7fpR)jyB#em?$Y)_sLJ z%qY74asCZAu>bb#X7-u(vnpGgt7Tgi=;8_)efu17tL(sh8$^IHLB6wHv8?)Mtv zl+bog5rTnP(+tbsuKnA<>XQ-J93<~-bc80KB>H1Z0tl&=FTA@+W z{8Bx_foTC2=A1;I?L<(IcGlAL_K)6LZxtC zyR7EP&RS;T*bi-Hz>YU7kq6YD+4iBFvNJ|VSCtmu$@(MVE@eWTwmczXP>;nU)X(wj zkc!E;{L!e_a@T) z5#iQ@w@kP_1%05p7~ps#)8S1;GCbvDwK+gg*8*6(RJLnld@fR12^y2&Vw#=u9>%oX+rOUOL z!}*At`A?4{{){}+6goaWE;=avr@z7=%)VW8U33m|7PMJBGKX|rjGlqrzjH^HCK?(1 zFoit$&dXo7LX`4$elgy2DFPe ze7Qu@fmX~Lp6|H5|M62x3$(k>@t)oOzflTexXa4Ro4J=SaFHS1y1zhMlLuBD*g~Vf zKC`=0@5BFfFG1aZR}Q~@zde7L5+R`<4~a~?(U%(elTdV-a5!Rn`}4eQBJ2p3GoMRQ z=NT8`f$SD}|L_0v>%;fuuJh*F&Qm6)4`8I9+?qc&TrdzKBex-`%8WqHyy-s+(BW@J zxCM6tAnIie)pc02TrvSg(LHl^-_7NrLY8Bbp+9Vg%vz}i<_Z!-lF>#wJ7}?@x{*bw zhpF^Na^PD*ZLh2r{jbK^R{p0-goyitVK^bWeL%m>h0!(zsH3%rtF zh0e-KIn3hp>W=viETYY%3sL(98G?YK0~~;*yi?ZLjm-86;ZOaY<-dEt zD{;a=X-l-chOw_Pk5c7yL>(6*f;V1gliG%$l9z+G(w z1x?R~V-MJr+X7$R6JpH5ugj_W3x5oJDcf1cSyIE7GhA6ZzC5)1OA|En&gmxF$f-3PU(9g6bW1uxb3lkQNc ztVngy6SRli4Z~9F4NR;R&tDEX_O-^M6tZh|PbbKFx2HpbNY#s{3w@bU1tK5D<9k>HNDgX;1r?IzzJ1=rbwH zIA!(9;g6^Pq=x9inm^#1i1`Jm3x4ApLa4Mr0wI0S;Hj?ZVAWE|wiA~~m61Lxx%091 zA&|aUtAZ&>$a;14uolcd0W%bbJt6r#JC8=MyYBN2iqzzJNR*M3hYhoseq}yHL8q+_ z9MXn)Xy=usoy$=-qyPp+!>R2K&U9hB*~l+0HA14Xb`$*9IHpG+?rihwot6*Q>X6!} zI#sbpgn`wCh}(BvVqIssOJgZPeIv}LAPnLbIN<)^M^=?}CtGzV$^mV+o+~R3 z1>HMq#Ag%vxSJNr_!%Oqv$rcm3^==z0F1D_5t=#u_rk=@9j~*)ta}A{>2YK3m3WFt zeG~&DXCm3eTm$X7R%GXX_uBWlR!OTIck$4sH`K%2y2RcxK*-vU`h zG6;g0_?st+3DV>B$+Z24>C^->zr+UPUl!G%rd>@t0`ipL?pzdp$KxDxq2AZaAyUjP za%PII?@nXHjy5(n#A;arH~%#boVautRR<(I0fatHc`}f*Bitpbm~>T`^U)xTJ!gUzh}_9-dG;mgJ9x`S))($Qhgp+x z1iD(ugdg?XfJK-0bj4Lj$b)(Ltu|-uVkktL(EJ!`WLtvYhNiyYfP!%Y#k~?J%G!Gj z{?|GRZgh-u<0~B{EFsnYYXM>2;T?Fug1kqO7H^#h&;1F5G+FJ1pCWCE{r&TwAYWIi zJS&fg`;m-VG<4+C;XLr24dnQmZ0Zkt&ZYDZU(z=BN>eO-IGOG7h`n!7@^=&04$iN3 z;eB|lQty}AR6%M~&-oxa#p(1OR%*Q8-rApCh#Fu#OZ~j0pvJX*Umty^r1o>;r+ZYh zQjDvTgJYshkQhqK>f$U$MfH(_6|0Z}08Qo>y9!ELbk%+jN6RbVNeL@8P~QDLy1WRoY+dvU%FnpzPN5w;BY$jHbc&L~dWk(eMd-oRhS;rN7l=0#otB#{M`_;T+4 z!S5t1S2VO4qohUdoSnQGb_DwB&gwTxMvPAOPqkK`UG&qY=;~UM^~3%8;|yMy$5ZJ2 zQtz-bAY{N;rKXh(EYQeEJRX#XJ2UR&1P)Wj0TS7qKr84}+EGa?R3Vhk2DRaCJ@N{s{R#REuQn^re(7i!ys;d*aLyg>NZRuuJYnmFNoYPbO7v zuKuC^H0^6HHP387BmtaWsBpl-s|xs0KFiAgtYd+jxmW}=z-0)jkAH;ysM*CJF~&S( zmyd1IrFmrqGtpLxeeJW8ZuLPTM;-G1^sP2iWxgiEkvfmv#LuXV(hz8T`!_ul7pxaG zt^D%kOLkQ_ZdtM9ts9&MdeFsSrt)5)3RP56K5mYwHGa?V>mF|Tx<6sVRmlZbp3D*z zpzj#(K?c6njm)R+#5YqCVHc?f$6D=ZmXdWFtOaN`O+$NVEkEmsW7~UDfZ`l9R^7N> z9N$LlV?SYlb5Ee_V%IR-WaRU!c5*{ze;5qlU;Gb%e08CaiZ-nomXIbxm zn7Vv;>cM@+6*wjd=(wq5@r6%5PcRcifqAp>KMe*mwUsY*Gnk{aTM3+|_DGY0M;n>= zL7qP|+^hm!OYtkgr$w!=1q$T({CilO4?>q_o*LwFY7K~0ei+2_cj8^^7XGeNq0$~l zp7?6szh7)+fz3ZTh#u_PYzwovx6~$~xyK64;Lw}Aew$BbOC|oX-UyO(0q>JyDb=3Q ztKTaS5$uRp$NGFW^_t~l>1pJcqd@hnZsr^qa-QLwt;ZjuKYLF!Ttyznd&4SN8iCZo zU{;OkIQU<4wt>8uoFoC>iebL2@fSC%)!5ks8gMO%9F~{!>=*8lx?k@wSD;5L7*{4Q z8TL#Z^XMm2@r8KKa&wOZ71Z|RyRV9JQ@zwx2w~9bVOzh!>rVRZ6csOn7gju7%coh?Uk@9Py|dzNuo4 zq=A^3;SUbp!sEJab>yK&7CR)lfF zA0aJ?04BD2Cs8f*lDowyI;=by_zcz)0DZi<`Qk?E(MbYo7-9|BA%!{C=AW zyF3UpT2bDz*-W%6t1L+}hM8fSD|qu#0QqM8DaV4UAb%Qy8C@Y6eR)!1_A1$IFE|rk+f>JVrK~0AOWhwk2$v^al z6IJ`eDo>!>7>ho1zNxmsymaN{M zk0bn*Qo|i(y~=9w=SxSF{oo%5swAzkVS3}Lp(4(qWn}e>p&riN@}%z;qqAW_@-kmO z8C|cp`*;ZwgK<$yG8ITxKWkQp@fUh9Bj z)@ZO!CH{h&Gs9B&>Bhi0F11mq>*AemLv{A7Xrw#65T_Q*gh19Q|~hE0wE| zs+f#Nh;>Hsks$vIf$L8A!?#>WA-yL5L4o!wn+)WcMT*r{sa8b6HMJvrUn{ z*2-Bq^RY(!l50S5I#EJ!>c_4VPo|b+4srT%egQLr_+Ua1V1(C6s zkM#h*vrp+$yyUNOc}md#8bZo{p5!uZ{bq$YhRSy1F2?t}R$fP|dBDOEg@Kih*#>wJ z?Sl8~6$)M>={Evkg851lA|~}$_pYuZ4#RX)Uo0B^K5E|qH#<`_XqhwGCA{O|e$K&7 zl_MU_-pjs8B5LnKd=H?e*Ar|tV4P6a>u`>~TM*ja=0M@;4-@FDr(Fcu$Lsd&6imAgA zf7)j^Aq0euT@Ev0OTIem^y9zPV0QvjP?;wgd0aUU%VnWd;5M2B|9~4&L%Cuyf=mMB zrCMt=AA{m&F`5-+=OYt<_`a>#LREdw|Iu{TVNJgO+ozEcD&3;=Km_SVP?Q?A4MZ9Q zi4RgEr9q@~QX`}W8;n*M(u@fb(kR_9S|lX&ncw62{k>zyc5L^3U)S|M&+~Pv>V!Ba z>|@f%P{U;{S}Yks3i(zwJ@W#)Y4P=?yvS70gn z&*WB&d`rK6L7%!Y^C#q}#FuqpZ;SVC{mN4MCMw8>O#ZGw8seMp6`bY}!xaMZ{Uzg_ z{&=pnTk*P0Y12Gw5a&fTt=y9)0PXlu);ElBVDn5br!ZE0+d`olH}Z3(*X}UCz$l3_XmxER-gnkY$*>bo|aX_%)r&{(A49D_NbL z@~ZJP2gRcH=X`Z9g(wbuBo3c!-Wf>1-uv&vb!MR<2SoS9kAE-E_=e@FrMtWzuQ1sU z^~iN%M1uEHeQj<^d^?&(T2jDo@K0tub!L|CF;-VjQ;=VYeRRd$sQo0cM@yTB473+| z^I2JXMgNu!HF)nOi2_e)^heO+Ps(;1ZLfTCeGD@}Pck48hyT$-v!7K)_9aa;2d=f* z6Re!A=PyBPiu11_zkpcazA*O(ukOM8)ZlolIa$BeFk~c{CbbLHk?=ft+84jHoV^ZU zgG_jmZOoCe*nV{`^bz;k2hVSvEu5EH4$Wbg7t!}xupt5S=6p?DTD?>mN@gR^C9!xD zx2bItyN5BslQhi!o9Uc;IrTQ&w6A18nH)T)Ve|R)Jc+F(KvieZlr-CZ!n$0E?E>)v zw)$Uo6iZ2b0w1fa_BWIa%F?pS{CS-;?%o?!97@5=K_j!*n(?d6I+z`e*w7mr^YMDJEeHdR=&rqaP!hjdkeg^%gvu^lKg{~o zjFnpdRcVrV`?K@U+=iT0_%`3mDc3*pvVpE3`r<>)fYwp`>aJMoeLcn!GLHMWxsi`80!OCG1Y_$eOf`V4I-Ai|ToJywrC&b| zgH0oX%bN9crd@4!l^(e2H=UBP2A`vQDk#24E>B5?g*WJ%E;bq49pydjLj1k3Vmo-!o0-!NTIIcrr$lK z8@@_C&riZS7`BiH0NRl=iaI|6tWX$HKgYVBWJ()(?UF|2=9UIVvEd z2qlv2+Cr~`E?WvOTmH@HKf@Scby<&qRP&Hkc#~xs=>=gD{l8f|F;@NQpF1zX=4xf^ zxonHy_+n2=iu#{`%YMVqdLlx{ov1WrRsEhGXagTrN(Q5H{Tp`JZjAQbo~At4Gbm{pG@6^wvc@A^A=`%?C1R z|67)iq+m~U^TRx88f3vF>8u6`Yo!0;}Ueo)PTlVc$~P>Oa3H zSj0X%VQo}$*F|kn7GgrC{@Yp@wWsl)e8IB4bQFY;JH1-z^+H(Y>jl6i3>2=HRRQBm ziRbZn^BQPWrGd)asknL;L6Arx41Z{|rH_&cNI~E54G$Vi)=$jcZu1*#ZA)UN&K3J+ zP@RW$Ds%33xD?SG;e`Afzc_j&2WN7apIl0)YYEK&jLN1WTq!_#3ZV4juXWJx%-l82 z9Lv#rJmyuyFQ@ht%SNZ;q+0R*N!)D6ax#Jr^h2-#&77A334Y9ibc?wJaArvQ8CQV{ zgIHqRdNfkK_k7))mC8ebT84EYEdlsN;%v3`FE$+YI`lYiR-Tw5dCGt{l}qI;fhn@= zd}fVU`zH>sWf*=`KaWzMX}_F5@aVYu+VS~%;oy29WPaQ#ipJD;{meDYhIpBT9m|I` zT>n#U{>|V$F6S4C1s}D5)ra^;F9kY>*xH56&nkmzL;uIN{ipK$(<}ZOUn|Zl2h-4@ zlhl!3o95yBJH4mi#Mf}G^740Mrz(=O} zz2pX#@H=08lO;oXc>?NDQZIQo z(N2a|9RqEL2RCDTq7EwGOt_dy&6;dW3ocRlsJ%SRn5x8T2XrXPDblymWT4!36-3j( z3f?}+c^$5cKIB;(pPSFj%`kJ%b`F4xD!eJPM*(xh@cBnHT1@%FvL%7Zs7yO?E;qYZ z6o0sWx!(EI(m`Hcp4i3wKOl0J# zNx0s__koMB0?9qaOM#+D+@G->(_97D|D;6{st}pJVsCqVzA0oB`2fs4La>W^7Y?-ycq%glNsPJ*sS}tvT)!Uu3i!9jc^S8IQielAQHI&FC$ubf7S3tHNZp4qQ*PnvGS^FGBzkTh=Gm z;Y2OI3tRD>w%i^TV4{#K?>f5Y9*x@2iU7{tn&H<;&Fw%3escSGC=)dX=+zF!iON_T zomksH=f9;wI+qzGF5PJqT;s-yzS0e`kt#Pe=%@SfL#y(S-N(EELw0?P->>#_H2F zj@73V!9zW9(rO=F-wSO_MmHtl?(~T#J~dAjF`DNPg3)*S^a}GD>P$0!Z9aHDdB;9JQDR|?&~ zC^Wfxxc9v-G4s5%7?0MZTVx|^2a?{GYzs%lTM?g^H!U?JpFg-}XK6ib^UPYWoHE8^ zOf@g&RUt*Ut%Iq8po5Z1Ni_SJuznMy*;e)khF!hg70meodt5d%zg1!DcTB1dL!?JE zF+L0Q&o^J~t&6_(#!E_^6e{Y3q8P8Mv^={-`Yt&wW~VEOxJ(BA$tOmVFSDbSin3o= zSz9mQ#U=hA#xs4W!Glw#2^tU*e|}lOx85@x{ks9KRKb2uh=)uHrB6;;XHl)|doR-L zQ?3-}JyLYQqNr0%yjgtpzC9hew})?B>lUEbByrG`yV7j9cf!(hNMkcymK1G?Fya3M z5`I`WWC~h0w+D!u1?mX@j#zqt$*`|r<5&(*@gQ2(ZwlBFmzMoi=JxkJ%eUyg!Q47K z8^n$&Hw#%N$>HW8BT|S$ZomGcsUNG&jm}{ci~nSecQLR#O2v`nooBtmRaWQXFUxbi zU-^|%3I!H1u9bL1a@b=Ib|TlPe^p!ga-~$fcj8 zFFm*;@|h!@m4WRBkuO~e$fzW4)#rqb6>ehxn^k>hl+eY405seE3ap8mDs6ri*IeRd zSb-Y;XiXZ6?ljfZBswK|p0qTy8?5ZQfXm4TCw7e7@S`~8+9l@cG#@GvxIQdjjoQRZ z>KzsU5_#Cx2a<%5@uJD~aQ9!%7WhhFC5m)`ZUvYB5&_N4Gyj~M#IqW;^ltVm=GB*E zp{S#JpF05zwO&#{MT)ZE4NQkvycx;YUstBHrgrefA%nP!q98D>}Xe@Bf|DQr_H*{ zEh@k7k9>aqxmDB^QrcPWt&u;m02u>qcA|O4105j8}24*wStkz)^926Z^Ilk?m#vfNexA=GX_MrVR>@7mPSO~a9vq&;cn!L#xoU> z$q4m839298%cxc%FiP4|&5-bm%hjXvqS`f3^7wO;`BLONGYnVWsXdvUAzsZQRyID%)~lTeM5RQPD=TW}U6BI*6iAZrfw;&0M0_+*4^l8ULiLxK zX(w(B_y}wftUcAj=?$oY&kq7E+41d=tT$x4wpUuDC&WE{^Hb(qMN=Z=)%`iL5xiD) z{<>A(xo^1(4|#zRTbpF#!UvH4H;3%NgRTp+q_vfqB(g)(g(^EWtjM2LFpo>gvmf7#JTkne zGb?$j)A)j9{!oDV=7F+Zm|*fXGY!`Jt7(vXatyo^21h7rJWt}8l~ByrEQG_o_Dh<`IcY6$cb-J8RRE|btthTEPZ6HHH3Weec?72wrf#Lm0v zSKfI~v#h6dO=Ru8qy22Z60l|^Q4DJbbhbh#FJteDOckQ!zo|Z0F9WjWu04gl2KaaO z(+q!~pZM-`i#2`MNPd5Fjfptn(=Ijj=_Sp!QVTVrqm)mdYVj0!3(q~l(3;7Wz3KYL zrMoXNCo{=W75$A;gi31oHp2X!!O)D@?Jv*7SSY3XC3$t>^5i&{`rF{qEQB1=?X}Vc?s(10 z`7P~x2IlO%5f@d{qe%!X@k z2N!|Z$07@0yJA_q(}$fikW#9pF?TD8SLM~gNlQh5hQ)l{z!!d}+z#O&=RggZa(eV3cH}Y@j30s{GsNEw_lt z!aA`jB5&g)?z%iY^ofkunRP@ddu)D!_qyKsgRrE<9d43BC6H)~pnE+U0eE_C!k>C9 z&TRmqf9`(=VH!+Ur)^J2R)t4z&kY&N9ZHZ^lhw{ZvtOZCsIAhVWFwWDK{Q6)j)s&L z!q56?`Dh9X$8H}qQb4!z<|8I~IDy~n*@y*MJMpg=Kp6C9ItsjNfHg48c~-ffke7DA zy`a#nXjay^fw+GOE_}xn!QkF$OrQLMsk2P$QmO?ty!i3IGbxk|i{$7^cQ&bvzUN$! zcjRHP60RQ?eIF*3gS%AYNbq*1V&e^FLNhm%lg#v<$V9jS)%+>%$jdOk(5$;1(0G$p zg%agJhu$o#|5c#LcE2uC>Culkkva!c(T}CGdQ9@8y-?3O-EHN&w^oJ&+MO{v5z~no zgJft)8nc*3*NF)vu#a|ja6mU4@farx`7(J!aFI6A0Oxl-niA?e;$h|y{LkG>MC$wg z{rs007`R>v$z-KjXeHW}m)b?niJtbty?@s6J9EOkci$Xu47HU$k$Qza$>by%)=7`3 z1S9+{3abLsy`MVW@g)6H#2i&VN3pB@t&kCHNQSd)Rd`Rv8hzEO``Ahq>7artw?STa z2P(0h>ADTCH|G0lds{d`SvJ9fW#P6Y>V}iSa38@w`o5QxLI;!;h{u3^e=2g?rM|z@ z!RK2gDIf3rIgGveD+Y{Mxmp||0=pP?hZv!WvWV>Gz2b$0ew8h>2YLPJm0kYl&88lrAGFIfT`}zyIZ=Z@*0?7o za%MbSM!eB>eG3RHeGuWorP5ReP`?eOK5N#lw(R+t0-wEECF46Xr0em$pCdeXC2ZY{ z734)14!LWgF6ji%zUgotn$HZo;^h_Xu78;1b7{dCBX82Oar0~vO^*+#=zdCmB7u6` zm61Z^ zs%En!D->raTX%#rU+&Wnt#Q3n}l~}3IzW2e?QlvGy4^o~}&s~cx=_ZkZ zGQRKU=9Afqrp7BrCdU>|INb^1@I&R*BAezLB9TbQS&$Gpn0IGDJXd?>Ea&^ z=XJ==i!&TmwW(_IZujSY_6}bpY{tEx_A5(>!>GsLjSGK)llYz zX$FN&OGmPLf5k$jX|F<&p*vJaaQmcGRk^{6PCIJKnOaSOo|xY;v5<(DEn8uZB6uvK zwN*E>$NQvHCXTGp7KS=1hZU3H*U$(;0DUsP#LIM8(!nn}&O;rMUU)2`rkhnn zm*j9abW?fp`#%T^wXD~5``BN|B|}#}q@HNc#a$~N{rh_ORj z^jA|VM6xZ^vR1lzfOW#dF;kY&gqr$HF6wiY2KsO&RIJMTIGr5`+1N!U_EBsV()Snju9 zG#^xbQ{MtEXS}yJz~)&a9f0F8o{~2XuEtRAghK}_r#CylUMR}vNzy#|h8>TyzmM5R zXsa?iDT=*k#G>wbJ`cP6x&C$U;^JcAc3Og(qyD7ZQ$Lmkb#XO?_Tsnv8(7LzxEeZF zeCwy)WV120N=Lhk6k_#Ao>XnD;?9Crq7IK+mjSKFX|L}u6_x~7N2ZRAw^sB1@CS-` zalF2fN9i~j)a8b9pTsmHodiFB{;DXRLcF^r6ikVB^`2}OP31mrOV>4WfUqDf|Lbic zYnOnV+WjY2EjZES@ZP2RWtQPTSt$5y-v86$@BGE@#8a~SYRXCSoXAFI#nO!Uu7#3U zs(;GPOf7?qukG%_4{qFM2CYI$^D%o7`GgecdhEgVSX5JtxfZ_O(4b+0S+BDuUF?xo zEU_w!8ruth9rCkZI6Y^fZd`bc{3;N~ES4X)WFX2Cr6-ev_?9a<}(klq&<5dF^T+ z{UEr-QvM3-9o;Mpt)|$b|5WD}68j-ms)~v1JG{O5Xf3?HF6*wCTYP0>^4LB*9P?F% z@h@^R3+w_4XA2gVNCMGn9 zxrC6tQ3c*GqPBAN^)%)0c}jiSbe(tTiCGxzl0b|ERm6o)6OFp|mkVd@{(qH4bd{f* zRd(iWm<6w7l1Fp*GY`CKu67Sy=U9QAjuM(;dz0W19!TW&wRyTh{J|}Z-d5Ugh3P` z@q07qdxjzGgujLZmu#}s!f3E*slN`c{GCPkEVF@ZS3BITslVgJ^Pn>Y=#HzR3`2n(j%dUztpA%{KAWD2P#)y4WW-_l9^Y<>+&<8djV* zIBV|K@6F-lfRW`n9_`8k%WOIV#?XWU2QwdV1IT%@tudpXG~6DPHza(Igh-d zt^zZfJW!n}bwj;_k+o1kxyCoO^{m^14JBrM*~V^q9vXVY7Up%iA>R>bLn3yz&bc1? z_xkM4RhwR?;^-gZ-&Oy=SXq>1BV%Y{%ij~5zfIR`!s=-brkm$Rb#Wc)LwR%T?!eCG zLx&8`WK;3tg|^{g*#LWn2~uQo+HjR3P8&aitEY)KHcgQqI%uuCaFI^s3e#0iL29Pw zEetI5T^GggV3Xmdb(v%b>NrV122UorQ`baq+hVfO1iQ*F0B%!m(vl3G&a?gD&)}K^ z7m4PRFM}aeaYBL90MbWRW`iM!C3~J;@!U)9{TcVl(83J6f1pj=p~- z^ZA0U=Yu%Np7+NJScjE|f~r(ACQn^g+T@=J<{82cD>`hv-sX9bO`h~@;-xsB9Pb*1 z!I#Ry8_7UNN;?wv#UiFIA4Soj)o z9G^C?EJusFk<)8%;zb<75N{@GKDJ~rZ)2iwFX1WY3oGg%3wBTrt=R9mO!|Uwpd(Py zh>+-t-5F(p@w5skT8f3o<$x&>Xe!&WkyRzfn927PKdp``=q%VPR<0w|ot-9h9p2_c zSsap{Lu65dB`;9c5NB?=IibLSbSecw&@!xN!v^PsgW`5pI1_kG{Zn52Cy!D8ZTr;i ziEU>C?l#9nP!1V%dl1ZDID9e^0lxZSW}bV)*3bEk8NX7j|N8!>eda&|Vl9FHzP>%g zECng+Z`3H;o+ifH&*0({HX{5MVS>Vd^_0AK}GgTIj@yMD4Q@Ws~cYsX|%i1a#a+X`e z{LR@f41Dj?>f>cgNv=dq18x?zKh%vVm#rdFP~->aYQn@m9L$KFFMMB4$cvveZy_eh zCzfrVn*phzoRH+B>Tq9o<^oPM`1oC(>=&q+fgWW%=xHbNcd&DB#HKapk*PQ({DmS_ zYx;|45=+}vxpI!oeAC-)4@=@tD$a93g zQgI@h1vUJ;R5)=EL@hoB(CHI9HcIpE;oNt7FOcxS z;FHISNQErMDZ1>U$W1a-_WKHepzwKO|9#$~`EF}U^r5xCW`9QHI3?G5;$~#tMeF_# z!zWV^5=hLQ6n9bVW^exoCTV?~jqX+5j46Y34YBn1!Ik;r6edwTXlo;5Ue+@|w?AMy z+8C$7o>0|#H0o>XdAI!WwPI*RX=l<;5sk!Y)^@Yc`vcgZ*NM6H!82;lT>u{>DEhp3 z|K>@?LgVEoU+&6WrPIFGvz$8v|7-$)4f-k(zsVckvdm_P609D6>OMr6e209tx8-TF zko@EMraMgREzBMVFgF~^@wN6F6#CrWWTW&x(e1GTeq-#Nc>N@gwuhS=;99gn~k~LZkb%&7;aLUEjcIDWAToL2aEfgqSGPpbd`z zQb?XFf_{5isZZBE#;W>nr9PS>eca#g0Jq;v@5(IQvjZ#Iy~Kx_vw&^(7=-S^%F(Ue zjSkcXjn0TNKkt`Sz2;Jt=3HHM75`)+buooH2L1ZLLaedxAd1EKk*qe-T(a`j4ns6X zZ^``T?rBcCaxxbxA+b&)iTdEBvXHTLyZlV8k=z>U)SZD@o?#U{-IuSEJ8s621;!#f)eqn*k)9v`1Thq8ke#bI_$*?GGGrDA+d+ zC6U9&F159#J&yUM3R~HL46oeb2sh$y-JlgWCr0upi3~Vo;?Dzp>L3&&5cPd4H?E2d zS%{ag$Tn-CD&iEJlg6~yhfU-tkM`*)=Aub6T7hAF&t&_3zzFXaJ|-z<|CaEw1x{52Ebz?xON%BO-bj{%6ts4-Jg}xB`l5?Q+B&m?--MtWgyI2#Bbo%%VJ6W*xOG^oeq_y4;1!q}Oit1Mlq;si@rJ?o z3*H|~GCaP?(AYj2>iy+=;cK;Pa`udL0QN<(O~q308NX8kloF(L>%VnQY=@yl9J`Og zZKK^6iI90ac=}`cVgvx(Zk;izK1Ik80Ap?-`aWd#mUo!t2BFL$DJABiXv&4?g<(1_ z%8w7p<2i~{FqTAl8-2mn8aGfkQFqbY4BC8U(IA$nD8b9<6P?3aY3u8Tr=d}n)JaOK z!`x^9k6uMYNWre5E18@S{XhXW1(jmFhj+YPNw(`bx62sGb6yFLpA|RVa;n#$`Jjaf z0eit3-AyXm7bV&dJk+2rC?*EO*=c(FKPO5hKQgy9(Qp7)_+Y7bA`JPW#C?{9*2$Hy z9FE&Z=xSW(s;(oVS=d)F2}-Tcxw5U6Gx8Qhy#{c$Whqq}_T2Q~Tno_x|8P8k7jKcW zdf2<|<*JcU`sTbU=krar>E?Yiq9!8R*H`E;&>Aw8BqsLJ%(cACLL;u!;f-+>h)5SG zCfhWbBk?`ZiU8#o_?cZU7!LY6+!1St-9GeblzbBR_y@nR(UX2L`VT$JwM5kOJpaxs zrW77&M`->F4FoCL*Id7|vs6&(HU>hi3FvmUo>LUjk6u+Wa*pg&TgOk_eaRy0Px%Y{ zDm{bIkIwkfKpc~UyphZ2!?Wh>$D}X`UK8grSjAZ_BXs|%{To#D7bzAdt{aa87%(D< z2{@V`KkC2U4lTY_8xQel9Q*#%5G&&nhPtd^B%wen=pdTI1v*hB0I|;cgjSCs{l{Zw zobtgdMxWYSHGP8^&@;-Txw;P0u8W5U*npTPTx5{=;$$iP7EeKZhff{z=@kgy31Pq> z6ED1vtcEm_kK-X{oH2W9m66Fz@L^2=eqkM8Ars2?@+wmVNGdl|H0Bz=Q#(>{<{ zvek*t6jOfN-76~QBC$VDE4m>-?QHfAYZ(NG%`1XHGMKrFJFGtONuByY4>Bb=7INX_ zO22sNKp=2DT4Nv(xvL{TP!WEwooZlEEPr%R+?VkdpmdRG6X{H=r(3GpOO*P5dBl_! zk&te>59x~!dYQ$Mfb?GfIDC;t?d4F9Qk>WpHmpmL7%|A8%%5G9Q8&_uaT{Rbq~C)y z-eSiD{04tPsMq8Ez=WT8c~W-(G~?we!5ch3ry|S)q?)--h&#?;5|l&$WeHJ;)Zk8q zkud18FJLzB32n-f$_6iK*6g~^C;tqbU#o2#I);%rH{ zi9ZEX!9^Zfj_b`ySWPyVFIe%12zpjx+iTctTLWQz#xSR&V`%Scz^ICZrO!Y?;a@po6$feZx ztjGaa8X((J==z{&fo6k4|hNE z;s?25=$36)gm)7KxhaF={tVbuRSVO^)Zji@p({JB^gD|=ti1C>>&JZY$F8gxVzLU{ zG0y8Z1eE7knfs&QQR#Fia(m{NX;7oYbm7`>rYLH>{ldq+yCu3(2I*p{jNHB;Wd_*l zJ=*U85%FQV+m50{$Co-;Q|8-5vF=0vgwXFp^~%x8akk~7TxB#-^Mc~>Of0qIGRkTO=-?@Hkraa{Y%AQN*e zqbR`C;QCrKytoPU^eax(DPZY(zoMF;G(j|Q%n@g&N1=CY?PBHDb;O%OhcOwbFW~tH zY-~!bHiQKSgj1R!u6r%J!1@JVQ)k%5g|4?wbFu*T;|9>L^15?BYh1P4fL?Zgh%QRz zk2J?qL}EB>{~5;I_x%nKu@R1iBN}biS2jCRS+fZ;4Uv2<}MENzJ*RrjM2xZ>Gv9M zl&pyV`r}>)RIF`}-vc z$wn%|uF=}DK{uJ|A7{NbKY;XJi zG7nC%a%XB0p6tq?g8NjixrJpn|J7Ghmb5FAeECCo+!0=J7kFYu(gU(#Ni{XA7!F)V z?52TK!{WaPlknB?9|obnufcClPv#|(`B`ny#HXaxaO**RYZ#5v*%i8d|PL>$4D#FNENJ_NS!1L&%hBLH>tasMhl5R9jDO)ws5T{l(>AYD=dJ}D; zP|YM1!~+s1Sz}BQYGOLPu9&|Rf<4V>fV%v&b$?RpA{gtF&f1@!S{Sy@?Yk>l<})MZ zZMKr>W?wP$uzv&_EGv40XBJNi-`?GPs~ovpb=_~EMloYGT*gTeyfX1v@4s9Jf9I7< zj^a`g#2_uc*aJuz2N2mY`Rg(Jcd|&6Rb(fUb*FB4*acxiSK3G=tY4}c*pwc<+@A%v z?2%o8&^HT1^?BxVJ}j*N7Soqatk$U)ntVI|yX@4;wLt0f}G>Mr!Zt_^xh~OGc?z!m`L#c>wFtp3Y#j|;0%&~pJ{p5#53n! zmDN3Iohl}gu~F&PqefpoFK6cmMiKXXtyW}2tDvo+>|dVm20nDI#{8XFe<1ZlNGAAc z%UX9a#U#fsjV#Xf)6GU}f>dkis|Q7;Qyacj<8|RmcHImJZzV~B#zChe1w#&Hyv#4% zT;Qnp)WD4m(Y?(65HA|MK!5I!JwGL#`G|G>zz4*XVXz#ZfHwOst=O zpA`PtKztbz`E8p6Yn;>{r1Q&1)~}o*K2Sw_bSy&-g4B|pWYs#X@e!G)^@T0jkddD$ z0sS|Dn^5)|&(G!9HP=k4kvD>jbJZ_d(CM|VN`=s2i)r&&Q;qWMvKg)u9qTa%9 z8LYH?YiOtsgx70T?Y`-IyULS|wFvpgq$ytp$~@1X$8^PtQw_HoiGJ?e5Fy$wQ`h!4vIv{$pJ1&>#EOI9{u%A7SCY$_TrLBX}U(H0>357$*M(1JP^zHlZ z+uA>ryEWqZ(I-VdcD}zSnSbS3(mJd74YVlE`{%0_^xQPzk2}6U)ojW?@M`6o3$yey z9H&RJfjZ^5F#p#KpY0`t5O?*0U_~YQRno8f5$SdgmP@+12Y{;^)tbN!52 z2z8Op?IHvTPlD@8Hg3^>A7V*y@G_~=Baik^KI=@QY3zYPT#r!DQKc;e_>=Lnh`eD; zAYlN_sQ#(=6y{JGZd{Es zXaA!*4_4#N(svnR`{#=HRVDslyJ4u`lX3nv%*5H{Q1u8#bOtBU^j`QkO+6p81F7sO z!7KmRhFCx(<{P7f9TwF#u$=pbz~f3y)ft;HohpMh0gf&v#AEoi5dF8whUvPl(~X46 zY#p2lUdED#RR0Mdc{81+XiPy4h*`242&O)-bsK3m|kv1bJhmQks&D%%A z$_I1!N-|;KrU_NLp^TwI2WKM)R)`(+kQML4TR>eL3}$S^_$C`$R~~;xCe|@X6%HB} zuG|=hxg(Mdkm}MceTk@pZGe6!ibBIr$v!z!?e@@WbbRZw3cjZI-S_PeK2gdqf4u~9 zwtZ^-pmd9Xy}LE`yc)am+MC|<{&brLsr^*7Nen$j8d12!N_;k+|VOvUA;-#w2LsGc}!8BH$Mbq zp`&4iLqm*Q>-U8QqgkGc2%6{Rh9vJPO3`>y>QUQHJFsOBuZBW8Jw3{%a=hvE={tLy zceN3d&5!X_zA@X@d;iI3bpCOd< z6@G!yK$gV0UmKkG2(YO2@^qOqL!V&1)Q3&qobuhXQACn27|)nnihE^ z#VLEKW)V=aXvr=-auIYTPdN(5?Q1`@Jd-8WpTFmYvt?}T0lDBKEhsm}R^}ZbsyeK# zz0PH+2bOKzol}$;8SPn?2+Y!sNI|xW*O{T>&3vu#ojF?wp~(A)03fi~h74GMyXIP? z?MKb})4AL#F_*-h1#e3Z>LgTR=M3_6l!a?qV%h$i(DyuK??VpKDnCErDvs%`oQIyb zvh{br>B#F@y%zjTV0^`v#oc2O(J}YiRNn}%>#0xq(a4Wyc5O+TBT4t(x>zyh%|d0N zSgN6mk01X4!@Im!oku>brldp*w373qT}E2`iVyU48o(#!o{Dgv zApg~VQ?{QFrymOq%S%pQrc6Jgcu@K z-yt)R*NjS*Iah{Q?;uDT^Yh|<)DV;mNPg;&VMu;S)aiP;J&ddx&Sf|^*71zT^(!{a-eE}e zR4=UUI4&-obthvXa3a>MZo%G2OWe4IoixiAY=El4_R^4h8Ae})GN3M&d3T5US z848n%1S~gB3UkWH!hL*VSsDY%qpgvbA3p696{wQD;YVP`H-3kQ3uDYojz_ki0il!N z6!v4$^@81SgC+)KQnAZ^;jhA*!?_l9Y6x>eqa=Z~mGcBmvJ%Rc;h+|sSwdVf0k-IS zxA3_17kFL#eeiFKcGYwB8daFuzL$O7LBPR&IJMqB0oL*xH2 zB-mI|}&?QijB9LX2reqnoT?m(cz3ZNad4MeW268CeN z6fk&?{PB=Db;y$H$I2m&{n zx!D?9WZuB{D$<=-Kkrfg|9JuAl{(Vh417hDCBMk-3h^%|TcP(~A`Mo9fgE z_2m7M5^IYtw>hSQ zps$+V8jJxdA0gPmKs7-pq&-qB9N@q_6?Srb!Mkbdx?7_xJi>#-IxXFu-`f6sHZWsD zy-?wZic}8uyuGy{o?{HLs?sf<=`T$^rO9x3P3_`}oa3?17|z>~lnjRfYo!f7axeK2 znxHkoH$~v>>ZJF_0&>Z;6kfR$CSnMZ!9(guZ7|2Mr7pMOIUo@?=L?(LZ3iUnqfz2(IDhFzL~kqA*1O6v3gYDQGjwR^vLB$+?WvFNZ#_>w^*3i9gN zY*__k!^G&>&-^h*@OJ<)COOduD^xZ=7XM#K=N`}G|Nmjf9FlTa4ml;qk<8hgrE;9Z z#t_0ph!}IsG4gSmawvy6M) zoRQ^}cnJC;Kn7-@;l_Zk;|AzISNf0szw1ACrDkSl{r-s#TDL#6(qd+`YN?G8> z3EDj=mr&404!p0;Slp+%L4zJKcQ~x2)ksl@L3(WGMr;wbCAq1Z97B+fma=I`i_Oe_ zcPS)JVC0Ksa=Ba!_DXT*!Zs}p#3kt*2ipp`zjME_3q%iw+~3gLF-3tYFYjixO{YI2 zsa7eto?)mEBl}dVxaK>w(uNh9N_IloIJLq@#9H%DtFnPkw zO!)KCr98UKWL-d?s5*6ZZjlgV5pgC*42Fmm`k}cRY!u2NW}|Bxvcn)|oaNeI$b1ZV z?)`KwOcWXIqF1?l9K%`d?G^T@3K^D=@{f7Hibn^hAsMF^G`+j;t7g0HvDpwNQGcLAocK% zeHeHLH~tQT-n8J4=An$rRsl6nWj_a~LQw4)N7-YH_n)$!`7J}8FjZ1~6sR-Cakjn6 zB5bINfAy|gtK~0+Lf<{p3;)%AEBw}vkG8~61us->OUEfy9f0y41VVaHMSmQ`r33zU za}KgnxB7)?G!ybp@udLHWWYQ_`<08q@e$CgIxlB%{;ra+#A91JC_{O!k=C=6JX=E0 zaGaCyq{$QfHzv%GTOUt*(!^tVZg^)!a(ZA3AC%6mqM$^-7V-pZmYKUnXi&x+&d+r} z7hpY%aw^8?UtJx9zzN^5GDRt9H2tGSo`wZ#{n&M#zL`UbFQ&XpOLRC+HP6bXX8#Xp z<^{fbDy@g(p&3bQ3l-_l=nFS=J%C(g&l!aB8;gwJ!FH4PdO^F zT**21#2Hn1>#DqCaY`G^JZNulQ{clHrd?)MVuo>lM)J6(mxo&9;_UptrA|}AglGtD zApouYUvoJ#bWk0{RByait$t@p@#+AXZF{j<9pKZ~j(F+)c-W`gv*JPFYvfFB`ZrO$ zNuEBTd|iVpV(u=T7UdqZji%LXvs8VyVNWHkPfp9eMf_t2^S1g#wSpu_hXpEht#xlE z0`gwl*_4UL*--P9Z+ftsHytcsR@cL6L((m_a~v?YkpxicA}=|XmOoW0ws9n4c<>se zbh96h^S4Fy_y)%U3N^gn${pN-n{CoBV*GFPZMn}QYx>gdUZhwB4y@g%Ip7 ztn@)cpz;=|*U=&rJAkEAwT&jA^(auJqWrm3U>KPGd47w+?H>ZmBWYdP(T(urm>dV? zR~|t-AL|4my(TLONF^pKABtk1a#p%ICoan z*jb0u6tD5vl$?sTarPCU2a-1z8NM_dRIm2wEcZ1#pS7TJa$%6q(TUC)d6X6M(|)74 zVG}XhNNp!l<~1=>G8Ctwf1gToo!mSSngPIez22M~^EEXI2o<)s^nH^gZGus*wn_sY zpup#at=^T^ey!uNC*N|oYKbu+*%$jL7G5jXNX#4CJhh#dOBb@tyCD4M0lS8Vep`@r zP|M>UJFE2%MfLpf2N#PQ9JyD&teI%e!&Mnmcd71~gC_6%BI$YqfBc7bhe(8xER<9Q z;K*NW&`xikidy*OAD++dV{4&{4}cKOyP*n9!i!l52TF)~x^m?0S77ItInVuB8nAmM zK~bB6F+QToxT1XENt4M>HAwPt@(ii z2@aZYX~gl&iR}?Bkt!K?=rOR^y##d`3fE^5Q!cwjcB9hB=Z4I()gY&F2iYn<;uGQHg}aN&-XVFd!TZTU`H{D~ z!BQsq-^}&X-GyYY*LqXP=}JWOUyHBieJj*l0pgxxQVQ@lrmgMfY%v4Q1W}KF9b`!D z@10G)sK;kdqA!hfI+Nmf3t_!W53dsTbJ9|n3Ko8N83xZrQ9g8aMCkn94SPIqpKt$+ z)5(ja%KOe;)OOwrA~+HA05W{_@B<1gGTY*CKN-@OAoUR!HX`xNC-WgHU%l#@n6{5z zGTe!yC9Fco_<1r4LMG$?RA@apK-0H?bi7=$7A7@2z&!-y!~J7T!Os$3f|mXJGi*g! z38B>`&^v#_YG2hW_uj{PJBHtLucN6z7oG=%c)vp41l;gOb52q1WrdNzS^qfrIJCZfWiePp+g|tV^iIKmw1}S%Dn-qLqjX*tB2^ zFwiGX!?D!#X;YYo3iRqJ#+>x=cI2|**Qr+(h{q@dXm*A2C6{!d*EfZ_f;1heB*nD5woY2(sow7$g&EC-QTLaL+zPj>DdNx0-=WO> z;w>R%o1jeL;SuT352yi@@uH1_-Hrg-F-QozlZMY7m{+0bXheVnq*vLAO9OW!seO8X zcYj|z+qrl#R#G*7_jEfZhKU;=nDx)J@$JucdpqsNb=MNfxcIXwqV^w`C;DVjR1e9% zi3H}5n^l(<$SR_t#4;jRF7gIRXojbl`%>RE6(B8YmeL9IIxfkNo4KS{VQ)77o5{*@ zzN;v(la0$@O|bYHq`6o#$vo{&1$4vd0qL*)rF?^j!B0Xj1e2RE{}Ds0Z{KGvMM_tn zwK#fDzYnZ^lz%gL1K2m`?5!K@+LCgM-8l3p`^uEl7tfEiSxaUNq{4AgC4xpRaw{&f z@-lenBWM`x+0xSMpSd}Id5gCkEcu+u?Prbz)5W&FI8;ZK2`N|o;vvZ3Bp6!}1Ud_~ zE}jc76YP+s9kGH^X7&$j{L587cK0tN)Tj!d7Cg)cn0do@@Co=J-Nz{xb7th6OL=it zz67(POwNHIMwqbA2cYq4i!P?4DPe{8>(eV`n<;wmlCP7=$l*W^j&q-EDH&@+?7t}6 zl7ZiI!YX?GG$4UPreu56fz+b8cN(3ZVzR|Gt1PBg#A}pE_Hpw#DKD5#x<{W|%}y+5 z9B-2b>9Go!HGDi2)JO1tNLYVd+Y|#SMu=B`0JdlyefXw@2G~aCHewZZHSbibxOWEP zl(_;%v-n&0PyeUgr8N zUGpAIFJme#1^DJ%lqjW=T!Zc@^_?y+eg6%?^RywwB1JV(Z?UOcoXU=&^4mrV9%k9A z(yN25fQ5TJu{+rZO%a@Ur$pam!nPGOqp^CY2%mhp(KAQRg_2FAwzGXM%J(-_&QMJg zm?&Bb;MCB#WgfL)KL{F5Z>a5-t-uE)$GDx?gn6!VNwRQ=qxG|~8|e03dT|2y_p*gchE>wOxU_Vb|vQ*Zy ziC*jhOZ&$NcbTgSg4N|uqG!nyr_h5pT3#@a;ui+%hxtYhULZ^LqM~-FXjE2z{B3DpQKV)%@5iwNs+Ez2Be#h!m@EmkCTbg-)&@#8W{QG-9Q z8&A_zvvgCu<*OeMiX`)5n}W7nK|x_w=GXJ*7XrELh4tVkZj?W~7L`FD0<3Q1wxAvT zYjk1&`r{++dM9x_yPoRVXi_fw9Kot1o;~jFL{ENfn|+7u1zB23TpX~-+$WI}TVaIC z=~3dsF01~SWO44)w0MJwjyL-cZZyGj*X<3N6m3J1wEh&xHbRbmY8#TqfC=7*qF1 z{(yfe*ibEX%dFbT3S8n9SvG@{@Xui$0HhDi*K9kwRz|9)2*H8~0~4Cz27Czk<10zb>1M^>oO_Zw4D#M z%%!f**q^G8s@d^MF&t)5DczN?9=R66z8YYd$5xFbcdePulYwHjLirml^SNAA*DgZ6 z%93#e#&V&2;wn|a0lIq9tcSVDUiRJm<{e*a^1fLq6^}TZ&?hD2y`DzRR3QS{ja9!? z2C)=U-@Ai8eeG@%+4(af+(&P_wNKs#2fRQD&bW2Y3!vF{&m4^TEr2ttM!@&nkqj}q zZaF{qLL)8+H*GncP8h#&7svT;Cs?blJ&=^n?=C@JQ||A#tOGc~pLODcs89>!OEl_N zcHKY^uFaE27P1=+muEf^dGloQ_RQ2|m3W!EJ|LEwj{x;;2#;7ab$+2w`QI8?z7Z4t zKPL){g|XU1_`jCgKO@$hz=rR=KhwWyhmWFXs|^4Cp;?uF|6>t->l2N6A9XZ%?|*CH z`x#p4ZP-4Q^n3K|Wb|8-X!PNK%p}#vHt3wmv8^+_46)vH62mr>;>(L}7l)KGw-KYu3mS zyaUWI9mOtym7S#hdx%@mS`wG+?^u|(b7=fpf6XWNon9`E`41-N@tE{l%gKqxVFbXoy*>ifV`}(iTxzE5no3@yrE_sY(RQ7X1s&%2 zG)O`W4H-`IiUO09%JI*bjz%tM*L>K9wkkXCs(-0o-5M16>~sG`@p=8N$^eGSUdCoE z7|RZg(#6=i?6FbuHG;(o+ihPb#)}(?|HwM>HW?VM zMMwl6a}-`^O6i+<|AUA@h|0tQn=`;EE$;q070PR}L&K!L+%(&eG7GHA<(4hw;^g-% zm~ZgqTO5`6_+)ZDBVosjpQq(^hsTh~@(szBp^fuQKdEO!cKQ|u8w=86&JKB67PYWT zG7jPC(Lqg;6T|aktZ*x3)Apv$2o( zdCVAWD>nG0GWf-Gk;XEIC^wIS#lE?FgU?^dMG3wt8w|ArRpB)>q}3Rs_0vk4Co|Y{ zJg?gqb~;Pz9)`>>J)05@3(UIjZTfLW<1V>JmTQmt0kP}+kSpg`>574*{(VgXCUr;Z zYy8UhI};yV_&!*cH`Y(uo8mHw$?F67rOYWWQ$@u%6CRJFiP8>Du+(fqOH84e=oqS5 zX6etjt8F-wFQ7|8T^FBNB^P7$q2F7Zo5SbPiPxfY|HXUkdl`tn|3cK)A=iIN6>6Sy zl@i^L-hGBllO^AWiiNR!#x9vk{(WEj>^UARd#KBq)KwOlldJjfuSfIN$~}ofrf+ z?2N`=R)5BmXF@E7)>c~>TcC>{n%7WNGTQYmq`i zSV27FP1Cc!cfE5 zU=yc4RX)UNUCp<=QqmH%A=4EB8{l>TJbgeRrkKN5QSy0P)8@T+sl)>JWpj}`Q$LYE z`hr9D^P%sNvx+Q-GCG&dUxe{m#eHYxpb4rMzD!DG;1yS&8$I4Vpn4f6hj7XZUt0LZ zGqJx6@kDN!Ci3^e&i!Y@VU{@0q-Z?f5)_X*i=mZaPMe=EIPyJl7N@3UP8_Z41Mly| zn(*{0q&fU62E4N(N~9wSd>G7s$xjF_*MlTq;&H|bCe9ec>sJ~t&g5o}=gimNMGXiK zYIwgwJp}6By%db!`#0|U*RK?PuP&t1N472#6??$~0A(+RIkaSEg_*33L;8CX%S zJ$X6_i1GJ0hsa3@9LT-R2Cz&C!*W$jnmLaI6ECXQl-_oiE;FLKgiP00gC>$4tHMT9 zefp&)ih7+=7O$(BYDh014kys1L0KQ{>fUEd0EDV6TWvR>!JBGdUFWeCLAAL7{J@S9p3AC8SG!ozD>GbD$q}eEe7fXf8Agu-}>- zqdjA*`!&;@J{ZLbIZN(i7y)Ipi95ah`6@UD*3m@kqcp@3Tsy)MUjyA5iW8@$9L*Ij zp@gIE2-|-806cas-Q3WhZHKN5!tRxqMH0Gve+t6m8f~BTd>OaxyEtXR89?=XURZ)H zZI@H~K03|v!SWoZ^-b|+dP%NF%k1D+fcCu+EgDrY+tm|}0mrs-<^wk-G_YfHP?O7{ z^O!8E$hktT1lR^8;aL^~xhLo;FIz`ZcdV>&&cX{SYiK^ZobZRXK;MPTo{p9)F>5LM z2YK8TL2UmO?{#@I)C6w;f-yoU@K{&-sJZlU?x82d<#M6%Xf zJVlEi4a6F;akgqCfYJ=`6Ra>Pbyg2pwNb#V>PM*yYv`kL_XzdUEkRKAdapvuniEE8 zr;z7C-{A&-3DDAN*N&b_Td{MrQ_t^z?c)FqBk0wUwZMz5I@2b+t>DP}c8NB{` zX+Lri=GZD1W~tL_u=eV;C(}KSoX-`B7;vYs73jLl5zqDMKtv0X4k|{c}&D6;tv=VsdN#TjqUZ3gr3Iq%_ z`=R*uYo84LIvz3j#7TGdT}^%I9@>R$>yq6%^K3OZ(CTvC{UBx!fy-sQ%+sKLhq?=p z*&n}@b6hJDyi5Hk>>$-S6-_<6g6pz%$ih$l6W*n9B$Ohl5!s?ZID{@L5gF}o-K(o; zy7DQpIH)qvyp)2zIldRlY!$jY7#C8dKhe-k>9vva(p0|ObVwWK<=q`BT1|m7+Z8e_ zSmgSgM1*A^U2MgiHn)#8dxQLyN?Rw(OBVX_UxUD({TM1O7bfPk3FF^vijyTPkQKax zu!liq8Y3pYrJ#_l49LanHD1`9wGj^5dG+_rlp4sB=LKgxQTK8(f-oPYq~c*43>g;! zXBK@1l7#i^R?NjZWx+1~U=vMw@IA_w7r^Lsy^EnM~ z_6eYvLY8Rz5F`O7e4amzPs~Gl1uTT|<0c-Y6&TnFA{Cw=db1FKxcX-m3}5rYS8|_J zG2`Tz4jEg+3k8^c+XK8X#bx#-x%Qf31*r;5)rxbik%8zs#%Kjd39L`OM_&4G?yn1W zlXtQXlmu>UVa&#T@7BdZyu{DeGX+J=>_BW_&ZUgPD&vCIRfutC-ZZleNO$JM=eC+LN=N&CZn*p8FypcQlxo1RJYQ+wso|5j+ZSg&ATXuMHrrHu-0U+M zGaU{c)1&g=Wc}NGxU7;g9tFP;-FT)I3nNvqmD?!9nkJoZd`g<+e=_R-P;eN4nHZ30 z&!u~OqJyQ~i+7e=R6AjuopjZ$REH~IE>$0NB_S1B5j_S9QnniJIFCiX7lO4(tRh*{Qi?G=vB0fpwbPO z_mi~eDb>+q1Gw^IEfkc5c_6*9!ikgBPpsY6j0HA|ZffCH zzxJ8ZEDAJ>L+G2N@yI{Ug?uBqo(y1AI0@ejU@S7d#%_SjfxEtfheH`2J#S2q;)P@p z>br|_>zkIo(9!XMOpFX*rW#~g%|qHgOnAyRfj}sJXV#Ye|5WISEfq z@@>*3%1V~tEze5>ng`9+dL#9`W~bwVmM+33q3g!!C7Nn-gK&wj*n!UHyTq?9>X6DM zzKJ<_?OoC}&UuP`_jk)Q$FHW#_G8N+tlF79ZJ)!A%De&b9pz$f;cxW%Rhw!cH~+`w z&hA?CR`=NMkfkO7ErRVWRxUKKP?f&%Q*9Z>^V(X3(r9HXj@q7EQ;DgJP36Mn0&w_WaCSBe7-5}EPKg>Y%fa1;>RfBg~QL5Q#uWpWwgc_dgf zNt9Nf;w)bvf6e2><$k)B+yBLb)L8qcjrN{lngNiKy&Mbt`yth~iec^1O?hPhgi0k4 zgz}6Arne}x2a5ff03b*6N(2$_^#$>p8bg(Aeujz)+-cA;}ExxZ_hB{W04JAHILI&&w4Mt=CN+=!aE7rNEnuO z{Wzy^H>uo`JCNevB#5(N=^O5mD@j=^;KbSdg1`@(8ILBmj=pi)kxu2IOitvmsO)D! zed6Y`@0W`DW6BZ+)=O$Xmg`G!aK3v7r#{g?=i;hF0B$DcBDD+i54Tk?CR!l@{_#d zD;0YKE1VokVprk}P@b|fi-JN`oldEvZmKT|Vi$vG76zKYw;YVX$}@*hy88mAo%)9# z_qh4}>?~)IoQkhiFU+IP;5B+84VR(&(IAnMYt2Z{(9sy6W*13|Xszl!pz+zoJGhYD zMpGYYb5IeM!%xl9_KkQe=j=3s&3r0CjvTV0Jhj8lz8u+n*N>sK7o|m6n1Pycijv)S ziO`6jvIwv3r}rb>?%#5{@~#6o!H(;R*9S=5*)V@H;a7>ypV$vrfGEp~k00g> zu0f|YHa<{v?e=fjk)H&;$-B%G`8k-y9uE>+M&~r}&Kz<)xy~Vijc4dAD3&ZC%<)ZM zEc49ak%c?!R$T1)qnw_F5=&;xWtTyME${(14nC#mXw{h7bh1e(mKF0@o6wBe{QxgJ?#ALbceqPl$Y=RpmvnXZhH0wh$UU48 z>5e}yFj5@iPD0hejXteU0rcbw()v1JCG!V~Lj*_p8G3CY&Tl^gnk<{B zUi+tbDKrBf?250qFYhfwSby0K5zgQb7gbZTw@A;cne0(t8%D(9Z;_`=o;#eEm6Exgmog~BS(w5M zHt(nJqEb?WU?aQw&@eN!-?h`rJC6=jjN-AnxIO!)3(lDo1v24j!nwdmSK#vPnj{+ zxtNN-=3AXYjyU@tU83tp!078jm2=?2D_;M-%8#f*zdID1&}<&i_P86$WTqHOz!-z{ ztm_lwQ0PFRc6--?RQ(E65HYaTyWUN8d%>GqmrSGCRg<$LiHcEDVzvWrfY%#zw#<_< zy)N`?8}Vr+22p3U9cpi2&8rlsg8Ds@fSIOk%Dzw)c#N)AT_n;I?tN|s>i=c{V#>{# z)mzMY=riDSKPyS0)+Upk8p>OcQs4+=u@wxoB>mD#+-!eWq@BHTo{tTh#M~$o z=!SJwF|Z#$S0zF4Mn5LY@#|M_8?eh2q{B?pyveusUQZ{B@2z|oGTO&UjR#}&q?0r{O+BW(L`-x*} zT;HjV#DSA!O_tZ2`j+NrL|2dd>{|PeJ_DY}l{xyvNNiqX5vlr^ai>G0Zh=cYq~~Lp zZI7t$4Y7K9gK$ZiX^@(oKq1d>mM3bHS68~y`~0}AmRkyVtgeDyNUh_(T^v|eY}UZ< z$;H_dlt+@SkUK$dx0}dLd;v<8Y32f`%c1&)rV?6FXwEck$rlwP((6BEVkeRbRYs5Q zf3G-L8}Sm6v}1lI2%me~*Al_{`a7+M%NIAvD*x87rp$-62#n0pugN(l_CyzR4dh#m z6c6#d{@ULi(9QsptTg1F+)8nvEL5g^OlEtEkZ%zmUR%t$4Y(Y`mOzoxX7KPH8WmvP z_%ai;=vsBGH)|gOzQdnjYGDAsD0Pk&8i&yTopHEV`wg(J?V0*iyV1+q=9SO;>2?yG z{8tH|awUC|>KFLjI(vtzWSoX#5;m);$g**b7w3NND53BjvZlpzQAFQ@#3Nt66}&s4 zA!a!z)6dsaNp0BUZ_*(dKO`jOBdb(iXx~2*o+Qk$1=oxeL)1rQXLTzsJV_K~fiv5< z(!+}ZxxhTad^x9q5vA_h20u?B4~f^v_*VXLR5avHy+<7MWESvaIr;UK^`ijtO+Ud~ zt#;;(6H&b*+uhH*P?(9P;_(n`=3;IR+iBAwh*dw2GS7~$Q1RrTjK+Nr&q@GJ;a!$`=b&-ul}?nLRP zP3uW)uxT@*v0I(joU(mDwF>u+xryV|s>RC%Q#N-s`fwY^;4l|PXU7_g_!3Zm>7u+0Xm91-EO)UxFL$xkE8nBg8p{|5`-h5i?p z{7GLHr}{1+s=mPpKCvk)WAkNRFqTa}up>KC2!PGqjbETnmKd8459CbnU*L;|K_}JBRj&eJh4Yj!c z)=`U+D<%Y4k#4d2)V-LKfYhu&3mZlzgx}uP8p*4>vbiC&>bwYwYuY-=e=}#94(05y zl~TgJ!s^nnUm|IW^@|S*X#ul$KQ(Rq7JNd`mXQtm(#@5==bG(R`b|XWYzcdHNn1y6 zn-9x9Uhs*J2x)nV?8m77rpe`k;*fG1iLjyOt~6!{HqPgUeNTsQEhyyt57o+C)>-;c z;N*fmzfYS?4WXPe=Ka2j=?7lG{LwcS2DO1?U{94t&54sJ`c}3}JwqkQF>pO2#u9ah zi&rD*d`UzGur7~|QkcgeT`g?2+?$Fe%8uZ!p{xXA-Fr8og(%>2=tqhvuZlNDGrfXn zrq_Sf?v|R~@afF50O3{U61~(laXIF#xpk1Y65%7`o?NyauKZ7!_P~C5X7t3^VxR4i zLB#1~gTZaNUKiC5=^P9~Yh4FvNY=v`v>E?-ImoN^doKqiU)c0f*O&_7Kg-d(d4J~s ziUZ3R+g}D(&P@K42x<1zezL|RJOD-3ksRIb2anUUb7-_W;Sr)i^0|t+mVTeBPT~!2 zKAdZL%;oS;W|Qr~P|lN)nWw9P}L|4($d8a?i4y6~DFxNmV|iYKYzdEwqIK927zhVZomv1Oq| zQn;>w0Ei!_p&2t!`p9uYcICx+l^KB5+s{>LK$08kmb3f&@-Agm=)~0sbRB(ky6GjA zINKT0VsZ1wx+^rg`(sx)rghj~`zV{qGR}yS5;Pk`II!x_m$V1GBh)8tSc=sCXiSU{ zLirUNO4v=6hO(VWumw4~u`MCVZDwDwJ>Mms;^So`jVY#dnSVs3ZO|=f5E>;QRIuyE z@NDi}$$(}b#JvZ`xFs9+d*ZeAke`U^N^RiA4f=I?&cT*)VJnx~)SkiS*DELe-ocUr z%uLu6i=Ly4Z}g=S@36p7EmwzZihE^IoJEe0_nHgYRhX*m=wvIdlwpRn)Ep^05hLqJ z;Om^9!WHC+9@!oZv+y(od81iv9AwPgAoH7*l8CE-|H(!`$FeP;7b6!Zd`@2m7drh_ zp>KelQu0%Uak?Ou++G5-_rd{#-FSYt#V2z*Ic9%U*45(1j5}p9P59Y|NJEA1zn82v z@vzT?_=}BBR@%aStv(4!v!aSSIz6a=$gB>x%tU&agQ6DKf^CT@sEk{30#zU#A2#A` zT{9Y_M99_vNjvsSIRK(k*r^XQi`nT;y=CYM?J^L-O-t9CtF%$(K^>_PG5(|T{1-C* z+U{aA!xh*AbaW(HryVZIL0MQ}nwMrJ;m!<07KtW?s>v51@9P(6v_%V*b!Z&QqZ!8l zp{D{3LMty0^lV`h{Z4sHz)~|Kj}eXfT9UhSSAw*3bkm@X=hze6?$`{~0c&l%B#8Ji z{70$zqRDDOp@&0?$#BSxi+y~}Yw)uh&HuUILxF(F_)x^4{Do%=Hl9RPG9q#bp&5k8N`E9f8djc71udBne6!tWK<=aEw3}UUiCTUyrr&_+-(Snq- zyNs}_VP&y|hMnIUzoMr5%OZwNAEkI10XFS5b#e2Lx7NqwY!!_0k(KP)w@#hDkn+Xm zAh|*Lk7Yl5imNn(U#=${ITSo;!%`dJznU{?PqGB>-(-CZ9S;55E$ zqHW>SiuqY^8Wn<#5knjbB?^Gvr`VCJ<3{Q3`HR~-h+vC$|C2`_agOx$ zI}fev2qTQz*T#>v5?_~$d}FGVdkYqvG7pj+8P@aFBwbx=u5QvcXFSCw(uI_I`_BxZ z+@0QpnztrsBj*s41COvt#TrEjz@NqD})^-2i!b6_vX36}XCm02u^L(WHVKZ2WE zpL{T@o@s-YzNr%K$l2D^Z}>As4bL0#WlkY*oh3)RfUntFpE{)8t*+`eQCFwSy0V6K zpbJ4Xteqg95!l<^E9+Yet_-{La7BMehQRA8KdWG`WOZ)WeFMZ;>WK2CKAaEI7P-Fu z7j`>m%*rJ8Ee+K2A$#%@4J$dVt{}awg3uZsmAJU$AY#3xq9<%^kdCW7S(Bx4PZv1Us zZ+&-l@-&Lu-!kwRVJ}K+sIP+!1N+u{|nIQ=F?1`J8(${L9V-X6nE4Mc5ZCd=;a`pKkK`g*Xd)TrrWw7#B2 z4{ei-%(llvM1nN?R3H`wkyvW!-*2=u=WpqlpV9{(H;8n{G#cwW8m{yoOgiT1WlVF_ zn%TXUnCKUVlW+b0{Nqv6R4BCLo2Ligzkk@Td8G5Xo{-^g+ZM6!^9LJqjQyW<@e?tM z;jMY+YMWj`+VQ4$uLT0(&J?QolU-{wW{+^X|4CL*e-wZfI;>NNSm+Zd5ixQ(which is deprecated and still using the OpenCV1.x interface), then please ignore that tutorial and stick to the opencv_traincascade tool. This tool is a newer version, written in C++ in accordance to the OpenCV 2.x and OpenCV 3.x API. The opencv_traincascade supports both HAAR like wavelet features @cite Viola01 and LBP (Local Binary Patterns) @cite Liao2007 features. LBP features yield integer precision in contrast to HAAR features, yielding floating point precision, so both training and detection with LBP are several times faster then with HAAR features. Regarding the LBP and HAAR detection quality, it mainly depends on the training data used and the training parameters selected. It's possible to train a LBP-based classifier that will provide almost the same quality as HAAR-based one, within a percentage of the training time. -opencv_traincascade and opencv_haartraining store the trained classifier in different file -formats. Note, the newer cascade detection interface (see CascadeClassifier class in objdetect -module) support both formats. opencv_traincascade can save (export) a trained cascade in the older -format. But opencv_traincascade and opencv_haartraining can not load (import) a classifier in -another format for the futher training after interruption. + - The newer cascade classifier detection interface from OpenCV 2.x and OpenCV 3.x (@ref cv::CascadeClassifier) supports working with both old and new model formats. opencv_traincascade can even save (export) a trained cascade in the older format if for some reason you are stuck using the old interface. At least training the model could then be done in the most stable interface. -Note that opencv_traincascade application can use TBB for multi-threading. To use it in multicore -mode OpenCV must be built with TBB. + - The opencv_traincascade application can use TBB for multi-threading. To use it in multicore mode OpenCV must be built with TBB support enabled. -Also there are some auxilary utilities related to the training. +Preparation of the training data +-------------------------------- -- opencv_createsamples is used to prepare a training dataset of positive and test samples. - opencv_createsamples produces dataset of positive samples in a format that is supported by - both opencv_haartraining and opencv_traincascade applications. The output is a file - with \*.vec extension, it is a binary format which contains images. -- opencv_performance may be used to evaluate the quality of classifiers, but for trained by - opencv_haartraining only. It takes a collection of marked up images, runs the classifier and - reports the performance, i.e. number of found objects, number of missed objects, number of - false alarms and other information. - -Since opencv_haartraining is an obsolete application, only opencv_traincascade will be described -futher. opencv_createsamples utility is needed to prepare a training data for opencv_traincascade, -so it will be described too. - -Training data preparation -------------------------- - -For training we need a set of samples. There are two types of samples: negative and positive. -Negative samples correspond to non-object images. Positive samples correspond to images with -detected objects. Set of negative samples must be prepared manually, whereas set of positive samples -is created using opencv_createsamples utility. +For training a boosted cascade of weak classifiers we need a set of positive samples (containing actual objects you want to detect) and a set of negative images (containing everything you do not want to detect). The set of negative samples must be prepared manually, whereas set of positive samples is created using the opencv_createsamples application. ### Negative Samples -Negative samples are taken from arbitrary images. These images must not contain detected objects. -Negative samples are enumerated in a special file. It is a text file in which each line contains an -image filename (relative to the directory of the description file) of negative sample image. This -file must be created manually. Note that negative samples and sample images are also called -background samples or background images, and are used interchangeably in this document. -Described images may be of different sizes. But each image should be (but not nessesarily) larger -than a training window size, because these images are used to subsample negative image to the -training size. +Negative samples are taken from arbitrary images, not containing objects you want to detect. These negative images, from which the samples are generated, should be listed in a special negative image file containing one image path per line (can be absolute or relative). Note that negative samples and sample images are also called background samples or background images, and are used interchangeably in this document. -An example of description file: +Described images may be of different sizes. However, each image should be equal or larger than the desired training window size (which corresponds to the model dimensions, most of the times being the average size of your object), because these images are used to subsample a given negative image into several image samples having this training window size. + +An example of such a negative description file: Directory structure: @code{.text} @@ -72,100 +36,55 @@ Directory structure: img2.jpg bg.txt @endcode + File bg.txt: @code{.text} img/img1.jpg img/img2.jpg @endcode + +Your set of negative window samples will be used to tell the machine learning step, boosting in this case, what not to look for, when trying to find your objects of interest. + ### Positive Samples -Positive samples are created by opencv_createsamples utility. They may be created from a single -image with object or from a collection of previously marked up images. +Positive samples are created by the opencv_createsamples application. They are used by the boosting process to define what the model should actually look for when trying to find your objects of interest. The application supports two ways of generating a positive sample dataset. -Please note that you need a large dataset of positive samples before you give it to the mentioned -utility, because it only applies perspective transformation. For example you may need only one -positive sample for absolutely rigid object like an OpenCV logo, but you definetely need hundreds -and even thousands of positive samples for faces. In the case of faces you should consider all the -race and age groups, emotions and perhaps beard styles. + 1. You can generate a bunch of positives from a single positive object image. + 2. You can supply all the positives yourself and only use the tool to cut them out, resize them and put them in the opencv needed binary format. -So, a single object image may contain a company logo. Then a large set of positive samples is -created from the given object image by random rotating, changing the logo intensity as well as -placing the logo on arbitrary background. The amount and range of randomness can be controlled by -command line arguments of opencv_createsamples utility. +While the first approach works decently for fixed objects, like very rigid logo's, it tends to fail rather soon for less rigid objects. In that case we do suggest to use the second approach. Many tutorials on the web even state that 100 real object images, can lead to a better model than 1000 artificially generated positives, by using the opencv_createsamples application. If you however do decide to take the first approach, keep some things in mind: + + - Please note that you need more than a single positive samples before you give it to the mentioned application, because it only applies perspective transformation. + - If you want a robust model, take samples that cover the wide range of varieties that can occur within your object class. For example in the case of faces you should consider different races and age groups, emotions and perhaps beard styles. This also applies when using the second approach. + +The first approach takes a single object image with for example a company logo and creates a large set of positive samples from the given object image by randomly rotating the object, changing the image intensity as well as placing the image on arbitrary backgrounds. The amount and range of randomness can be controlled by command line arguments of the opencv_createsamples application. Command line arguments: -- -vec \ + - `-vec ` : Name of the output file containing the positive samples for training. - Name of the output file containing the positive samples for training. + - `-img ` : Source object image (e.g., a company logo). -- -img \ + - `-bg ` : Background description file; contains a list of images which are used as a background for randomly distorted versions of the object. - Source object image (e.g., a company logo). + - `-num ` : Number of positive samples to generate. -- -bg \ + - `-bgcolor ` : Background color (currently grayscale images are assumed); the background color denotes the transparent color. Since there might be compression artifacts, the amount of color tolerance can be specified by -bgthresh. All pixels withing bgcolor-bgthresh and bgcolor+bgthresh range are interpreted as transparent. - Background description file; contains a list of images which are used as a background for - randomly distorted versions of the object. + - `-bgthresh ` + - `-inv` : If specified, colors will be inverted. + - `-randinv` : If specified, colors will be inverted randomly. + - `-maxidev ` : Maximal intensity deviation of pixels in foreground samples. + - `-maxxangle ` : Maximal rotation angle towards x-axis, must be given in radians. + - `-maxyangle ` : Maximal rotation angle towards y-axis, must be given in radians. + - `-maxzangle ` : Maximal rotation angle towards z-axis, must be given in radians. + - `-show` : Useful debugging option. If specified, each sample will be shown. Pressing Esc will continue the samples creation process without showing each sample. + - `-w ` : Width (in pixels) of the output samples. + - `-h ` : Height (in pixels) of the output samples. -- -num \ +When running opencv_createsamples in this way, the following procedure is used to create a sample object instance: The given source image is rotated randomly around all three axes. The chosen angle is limited by `-maxxangle`, `-maxyangle` and `-maxzangle`. Then pixels having the intensity from the [bg_color-bg_color_threshold; bg_color+bg_color_threshold] range are interpreted as transparent. White noise is added to the intensities of the foreground. If the `-inv` key is specified then foreground pixel intensities are inverted. If `-randinv` key is specified then algorithm randomly selects whether inversion should be applied to this sample. Finally, the obtained image is placed onto an arbitrary background from the background description file, resized to the desired size specified by `-w` and `-h` and stored to the vec-file, specified by the `-vec` command line option. - Number of positive samples to generate. - -- -bgcolor \ - - Background color (currently grayscale images are assumed); the background color denotes the - transparent color. Since there might be compression artifacts, the amount of color tolerance - can be specified by -bgthresh. All pixels withing bgcolor-bgthresh and bgcolor+bgthresh range - are interpreted as transparent. - -- -bgthresh \ -- -inv - - If specified, colors will be inverted. - -- -randinv - - If specified, colors will be inverted randomly. - -- -maxidev \ - - Maximal intensity deviation of pixels in foreground samples. - -- -maxxangle \ -- -maxyangle \ -- -maxzangle \ - - Maximum rotation angles must be given in radians. - -- -show - - Useful debugging option. If specified, each sample will be shown. Pressing Esc will continue - the samples creation process without. - -- -w \ - - Width (in pixels) of the output samples. - -- -h \ - - Height (in pixels) of the output samples. - -For following procedure is used to create a sample object instance: The source image is rotated -randomly around all three axes. The chosen angle is limited by -maxxangle, -maxyangle and maxzangle. Then pixels having the -intensity from [bg_color-bg_color_threshold; bg_color+bg_color_threshold] range are -interpreted as transparent. White noise is added to the intensities of the foreground. If the -inv -key is specified then foreground pixel intensities are inverted. If -randinv key is specified then -algorithm randomly selects whether inversion should be applied to this sample. Finally, the obtained -image is placed onto an arbitrary background from the background description file, resized to the -desired size specified by -w and -h and stored to the vec-file, specified by the -vec command line -option. - -Positive samples also may be obtained from a collection of previously marked up images. This -collection is described by a text file similar to background description file. Each line of this -file corresponds to an image. The first element of the line is the filename. It is followed by the -number of object instances. The following numbers are the coordinates of objects bounding rectangles -(x, y, width, height). +Positive samples also may be obtained from a collection of previously marked up images, which is the desired way when building robust object models. This collection is described by a text file similar to the background description file. Each line of this file corresponds to an image. The first element of the line is the filename, followed by the number of object annotations, followed by numbers describing the coordinates of the objects bounding rectangles (x, y, width, height). An example of description file: @@ -184,146 +103,115 @@ img/img2.jpg 2 100 200 50 50 50 30 25 25 Image img1.jpg contains single object instance with the following coordinates of bounding rectangle: (140, 100, 45, 45). Image img2.jpg contains two object instances. -In order to create positive samples from such collection, -info argument should be specified instead -of \`-img\`: +In order to create positive samples from such collection, `-info` argument should be specified instead of `-img`: -- -info \ + - `-info ` : Description file of marked up images collection. - Description file of marked up images collection. +Note that in this case, parameters like `-bg, -bgcolor, -bgthreshold, -inv, -randinv, -maxxangle, -maxyangle, -maxzangle` are simply ignored and not used anymore. The scheme of samples creation in this case is as follows. The object instances are taken from the given images, by cutting out the supplied bounding boxes from the original images. Then they are resized to target samples size (defined by `-w` and `-h`) and stored in output vec-file, defined by the `-vec` parameter. No distortion is applied, so the only affecting arguments are `-w`, `-h`, `-show` and `-num`. -The scheme of samples creation in this case is as follows. The object instances are taken from -images. Then they are resized to target samples size and stored in output vec-file. No distortion is -applied, so the only affecting arguments are -w, -h, -show and -num. +The manual process of creating the `-info` file can also been done by using the opencv_annotation tool. This is an open source tool for visually selecting the regions of interest of your object instances in any given images. The following subsection will discuss in more detail on how to use this application. -opencv_createsamples utility may be used for examining samples stored in positive samples file. In -order to do this only -vec, -w and -h parameters should be specified. +#### Extra remarks -Note that for training, it does not matter how vec-files with positive samples are generated. But -opencv_createsamples utility is the only one way to collect/create a vector file of positive -samples, provided by OpenCV. + - opencv_createsamples utility may be used for examining samples stored in any given positive samples file. In order to do this only `-vec`, `-w` and `-h` parameters should be specified. + - Example of vec-file is available here `opencv/data/vec_files/trainingfaces_24-24.vec`. It can be used to train a face detector with the following window size: `-w 24 -h 24`. -Example of vec-file is available here opencv/data/vec_files/trainingfaces_24-24.vec. It can be -used to train a face detector with the following window size: -w 24 -h 24. +### Using OpenCV's integrated annotation tool + +Since OpenCV 3.x the community has been supplying and maintaining a open source annotation tool, used for generating the `-info` file. The tool can be accessed by the command opencv_annotation if the OpenCV applications where build. + +Using the tool is quite straightforward. The tool accepts several required and some optional parameters: + + - `--annotations` (required) : path to annotations txt file, where you want to store your annotations, which is then passed to the `-info` parameter [example - /data/annotations.txt] + - `--images` (required) : path to folder containing the images with your objects [example - /data/testimages/] + - `--maxWindowHeight` (optional) : if the input image is larger in height then the given resolution here, resize the image for easier annotation, using `--resizeFactor`. + - `--resizeFactor` (optional) : factor used to resize the input image when using the `--maxWindowHeight` parameter. + +Note that the optional parameters can only be used together. An example of a command that could be used can be seen below + +@code{.text} +opencv_annotation --annotations=/path/to/annotations/file.txt --images=/path/to/image/folder/ +@endcode + +This command will fire up a window containing the first image and your mouse cursor which will be used for annotation. A video on how to use the annotation tool can be found [here](https://www.youtube.com/watch?v=EV5gmvoCTSk). Basically there are several keystrokes that trigger an action. The left mouse button is used to select the first corner of your object, then keeps drawing until you are fine, and stops when a second left mouse button click is registered. After each selection you have the following choices: + + - Pressing `c` : confirm the annotation, turning the annotation green and confirming it is stored + - Pressing `d` : delete the last annotation from the list of annotations (easy for removing wrong annotations) + - Pressing `n` : continue to the next image + - Pressing `ESC` : this will exit the annotation software + +Finally you will end up with a usable annotation file that can be passed to the `-info` argument of opencv_createsamples. Cascade Training ---------------- -The next step is the training of classifier. As mentioned above opencv_traincascade or -opencv_haartraining may be used to train a cascade classifier, but only the newer -opencv_traincascade will be described futher. +The next step is the actual training of the boosted cascade of weak classifiers, based on the positive and negative dataset that was prepared beforehand. Command line arguments of opencv_traincascade application grouped by purposes: --# Common arguments: +- Common arguments: + - `-data ` : Where the trained classifier should be stored. This folder should be created manually beforehand. + - `-vec ` : vec-file with positive samples (created by opencv_createsamples utility). + - `-bg ` : Background description file. This is the file containing the negative sample images. + - `-numPos ` : Number of positive samples used in training for every classifier stage. + - `-numNeg ` : Number of negative samples used in training for every classifier stage. + - `-numStages ` : Number of cascade stages to be trained. + - `-precalcValBufSize ` : Size of buffer for precalculated feature values (in Mb). The more memory you assign the faster the training process, however keep in mind that `-precalcValBufSize` and `-precalcIdxBufSize` combined should not exceed you available system memory. + - `-precalcIdxBufSize ` : Size of buffer for precalculated feature indices (in Mb). The more memory you assign the faster the training process, however keep in mind that `-precalcValBufSize` and `-precalcIdxBufSize` combined should not exceed you available system memory. + - `-baseFormatSave` : This argument is actual in case of Haar-like features. If it is specified, the cascade will be saved in the old format. This is only available for backwards compatibility reasons and to allow users stuck to the old deprecated interface, to at least train models using the newer interface. + - `-numThreads ` : Maximum number of threads to use during training. Notice that the actual number of used threads may be lower, depending on your machine and compilation options. By default, the maximum available threads are selected if you built OpenCV with TBB support, which is needed for this optimization. + - `-acceptanceRatioBreakValue ` : This argument is used to determine how precise your model should keep learning and when to stop. A good guideline is to train not further than 10e-5, to ensure the model does not overtrain on your training data. By default this value is set to -1 to disable this feature. - - -data \ +- Cascade parameters: + - `-stageType ` : Type of stages. Only boosted classifiers are supported as a stage type at the moment. + - `-featureType<{HAAR(default), LBP}>` : Type of features: HAAR - Haar-like features, LBP - local binary patterns. + - `-w ` : Width of training samples (in pixels). Must have exactly the same value as used during training samples creation (opencv_createsamples utility). + - `-h ` : Height of training samples (in pixels). Must have exactly the same value as used during training samples creation (opencv_createsamples utility). - Where the trained classifier should be stored. +- Boosted classifer parameters: + - `-bt <{DAB, RAB, LB, GAB(default)}>` : Type of boosted classifiers: DAB - Discrete AdaBoost, RAB - Real AdaBoost, LB - LogitBoost, GAB - Gentle AdaBoost. + - `-minHitRate ` : Minimal desired hit rate for each stage of the classifier. Overall hit rate may be estimated as (min_hit_rate ^ number_of_stages), @cite Viola04 §4.1. + - `-maxFalseAlarmRate ` : Maximal desired false alarm rate for each stage of the classifier. Overall false alarm rate may be estimated as (max_false_alarm_rate ^ number_of_stages), @cite Viola04 §4.1. + - `-weightTrimRate ` : Specifies whether trimming should be used and its weight. A decent choice is 0.95. + - `-maxDepth ` : Maximal depth of a weak tree. A decent choice is 1, that is case of stumps. + - `-maxWeakCount ` : Maximal count of weak trees for every cascade stage. The boosted classifier (stage) will have so many weak trees (<=maxWeakCount), as needed to achieve the given `-maxFalseAlarmRate`. - - -vec \ +- Haar-like feature parameters: + - `-mode ` : Selects the type of Haar features set used in training. BASIC use only upright features, while ALL uses the full set of upright and 45 degree rotated feature set. See @cite Lienhart02 for more details. - vec-file with positive samples (created by opencv_createsamples utility). +- Local Binary Patterns parameters: Local Binary Patterns don't have parameters. - - -bg \ - - Background description file. - - - -numPos \ - - -numNeg \ - - Number of positive/negative samples used in training for every classifier stage. - - - -numStages \ - - Number of cascade stages to be trained. - - - -precalcValBufSize \ - - Size of buffer for precalculated feature values (in Mb). - - - -precalcIdxBufSize \ - - Size of buffer for precalculated feature indices (in Mb). The more memory you have the - faster the training process. - - - -baseFormatSave - - This argument is actual in case of Haar-like features. If it is specified, the cascade will - be saved in the old format. - - - -numThreads \ - - Maximum number of threads to use during training. Notice that the actual number of used - threads may be lower, depending on your machine and compilation options. - - - -acceptanceRatioBreakValue \ - - This argument is used to determine how precise your model should keep learning and when to stop. - A good guideline is to train not further than 10e-5, to ensure the model does not overtrain on your training data. - By default this value is set to -1 to disable this feature. - --# Cascade parameters: - - - -stageType \ - - Type of stages. Only boosted classifier are supported as a stage type at the moment. - - - -featureType\<{HAAR(default), LBP}\> - - Type of features: HAAR - Haar-like features, LBP - local binary patterns. - - - -w \ - - -h \ - - Size of training samples (in pixels). Must have exactly the same values as used during - training samples creation (opencv_createsamples utility). - --# Boosted classifer parameters: - - - -bt \<{DAB, RAB, LB, GAB(default)}\> - - Type of boosted classifiers: DAB - Discrete AdaBoost, RAB - Real AdaBoost, LB - LogitBoost, - GAB - Gentle AdaBoost. - - - -minHitRate \ - - Minimal desired hit rate for each stage of the classifier. Overall hit rate may be estimated - as (min_hit_rate ^ number_of_stages), @cite Viola04 §4.1. - - - -maxFalseAlarmRate \ - - Maximal desired false alarm rate for each stage of the classifier. Overall false alarm rate - may be estimated as (max_false_alarm_rate ^ number_of_stages), @cite Viola04 §4.1. - - - -weightTrimRate \ - - Specifies whether trimming should be used and its weight. A decent choice is 0.95. - - - -maxDepth \ - - Maximal depth of a weak tree. A decent choice is 1, that is case of stumps. - - - -maxWeakCount \ - - Maximal count of weak trees for every cascade stage. The boosted classifier (stage) will - have so many weak trees (\<=maxWeakCount), as needed to achieve the - given -maxFalseAlarmRate. - --# Haar-like feature parameters: - - - -mode \ - - Selects the type of Haar features set used in training. BASIC use only upright features, - while ALL uses the full set of upright and 45 degree rotated feature set. See @cite Lienhart02 - for more details. - --# Local Binary Patterns parameters: - - Local Binary Patterns don't have parameters. - -After the opencv_traincascade application has finished its work, the trained cascade will be saved -in cascade.xml file in the folder, which was passed as -data parameter. Other files in this folder -are created for the case of interrupted training, so you may delete them after completion of -training. +After the opencv_traincascade application has finished its work, the trained cascade will be saved in `cascade.xml` file in the `-data` folder. Other files in this folder are created for the case of interrupted training, so you may delete them after completion of training. Training is finished and you can test your cascade classifier! + +Visualising Cascade Classifiers +------------------------------- + +From time to time it can be usefull to visualise the trained cascade, to see which features it selected and how complex its stages are. For this OpenCV supplies a opencv_visualisation application. This application has the following commands: + + - `--image` (required) : path to a reference image for your object model. This should be an annotation with dimensions [`-w`,`-h`] as passed to both opencv_createsamples and opencv_traincascade application. + - `--model` (required) : path to the trained model, which should be in the folder supplied to the `-data` parameter of the opencv_traincascade application. + - `--data` (optional) : if a data folder is supplied, which has to be manually created beforehand, stage output and a video of the features will be stored. + +An example command can be seen below + +@code{.text} +opencv_visualisation --image=/data/object.png --model=/data/model.xml --data=/data/result/ +@endcode + +Some limitations of the current visualisation tool + - Only handles cascade classifier models, trained with the opencv_traincascade tool, containing __stumps__ as decision trees [default settings]. + - The image provided needs to be a sample window with the original model dimensions, passed to the `--image` parameter. + +Example of the HAAR/LBP face model ran on a given window of Angelina Jolie, which had the same preprocessing as cascade classifier files -->24x24 pixel image, grayscale conversion and histogram equalisation: + +_A video is made with for each stage each feature visualised:_ + +![](images/visualisation_video.png) + +_Each stage is stored as an image for future validation of the features:_ + +![](images/visualisation_single_stage.png) + +_This work was created for [OpenCV 3 Blueprints](https://www.packtpub.com/application-development/opencv-3-blueprints) by StevenPuttemans but Packt Publishing agreed integration into OpenCV._ From 2879eada253eaad31b962ae0f45f7d91b0e537a6 Mon Sep 17 00:00:00 2001 From: anirudt Date: Tue, 13 Sep 2016 16:14:05 +0530 Subject: [PATCH 149/178] docs: truncated commit msg --- modules/imgproc/include/opencv2/imgproc.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 15bed25b9b..fef0f6083f 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -3574,10 +3574,8 @@ results are returned in the structure cv::Moments. used for images only. @returns moments. -@note Only applicable to contour moments calculations: For Python users, note that the numpy -type for the input array should be either np.int32 or np.float32, or in general of type CV_32S or CV_32F. -Thus, np.float will not work in this case, as it is the same as np.float64 and does not satisfy the -Point2f type check. +@note Only applicable to contour moments calculations from Python bindings: Note that the numpy +type for the input array should be either np.int32 or np.float32. @sa contourArea, arcLength */ From 2935fcea6262c66a0ce072c578727bae6b30fc73 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 14 Sep 2016 09:22:54 +0300 Subject: [PATCH 150/178] apps: add opencv_version command line tool --- apps/CMakeLists.txt | 1 + apps/version/CMakeLists.txt | 32 ++++++++++++++++++++++++++++++++ apps/version/opencv_version.cpp | 28 ++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 apps/version/CMakeLists.txt create mode 100644 apps/version/opencv_version.cpp diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index e24bd4beff..f2cdc8751c 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -6,3 +6,4 @@ add_subdirectory(createsamples) add_subdirectory(annotation) add_subdirectory(visualisation) add_subdirectory(interactive-calibration) +add_subdirectory(version) diff --git a/apps/version/CMakeLists.txt b/apps/version/CMakeLists.txt new file mode 100644 index 0000000000..6ced527181 --- /dev/null +++ b/apps/version/CMakeLists.txt @@ -0,0 +1,32 @@ +SET(OPENCV_APPLICATION_DEPS opencv_core opencv_highgui opencv_imgproc opencv_imgcodecs opencv_videoio) +ocv_check_dependencies(${OPENCV_APPLICATION_DEPS}) + +if(NOT OCV_DEPENDENCIES_FOUND) + return() +endif() + +project(opencv_version) +set(the_target opencv_version) + +ocv_target_include_directories(${the_target} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" "${OpenCV_SOURCE_DIR}/include/opencv") +ocv_target_include_modules_recurse(${the_target} ${OPENCV_APPLICATION_DEPS}) + +file(GLOB SRCS *.cpp) + +ocv_add_executable(${the_target} ${SRCS}) +ocv_target_link_libraries(${the_target} ${OPENCV_APPLICATION_DEPS}) + +set_target_properties(${the_target} PROPERTIES + DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" + RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} + OUTPUT_NAME "opencv_version") + +set_target_properties(${the_target} PROPERTIES FOLDER "applications") + +if(INSTALL_CREATE_DISTRIB) + if(BUILD_SHARED_LIBS) + install(TARGETS ${the_target} RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} CONFIGURATIONS Release COMPONENT libs) + endif() +else() + install(TARGETS ${the_target} RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT libs) +endif() diff --git a/apps/version/opencv_version.cpp b/apps/version/opencv_version.cpp new file mode 100644 index 0000000000..78f28108ed --- /dev/null +++ b/apps/version/opencv_version.cpp @@ -0,0 +1,28 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#include + +#include + +int main(int argc, const char** argv) +{ + cv::CommandLineParser parser(argc, argv, + "{ help h usage ? | | show this help message }" + "{ verbose v | | show build configuration log }" + ); + if (parser.has("help")) + { + parser.printMessage(); + } + else if (parser.has("verbose")) + { + std::cout << cv::getBuildInformation().c_str() << std::endl; + } + else + { + std::cout << CV_VERSION << std::endl; + } + return 0; +} From ec40b85e755c77526a072509918f7fd71b30a280 Mon Sep 17 00:00:00 2001 From: Vladislav Sovrasov Date: Wed, 14 Sep 2016 12:16:10 +0300 Subject: [PATCH 151/178] Add license to interactive-calibration app sources --- apps/interactive-calibration/calibCommon.hpp | 7 ++++++- apps/interactive-calibration/calibController.cpp | 5 +++++ apps/interactive-calibration/calibController.hpp | 5 +++++ apps/interactive-calibration/calibPipeline.cpp | 6 ++++++ apps/interactive-calibration/calibPipeline.hpp | 6 ++++++ apps/interactive-calibration/frameProcessor.cpp | 5 +++++ apps/interactive-calibration/frameProcessor.hpp | 5 +++++ apps/interactive-calibration/main.cpp | 5 +++++ apps/interactive-calibration/parametersController.cpp | 5 +++++ apps/interactive-calibration/parametersController.hpp | 6 ++++++ apps/interactive-calibration/rotationConverters.cpp | 5 +++++ apps/interactive-calibration/rotationConverters.hpp | 8 ++++++-- 12 files changed, 65 insertions(+), 3 deletions(-) diff --git a/apps/interactive-calibration/calibCommon.hpp b/apps/interactive-calibration/calibCommon.hpp index 31c74b440a..6acf610897 100644 --- a/apps/interactive-calibration/calibCommon.hpp +++ b/apps/interactive-calibration/calibCommon.hpp @@ -1,8 +1,13 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + #ifndef CALIB_COMMON_HPP #define CALIB_COMMON_HPP -#include #include + +#include #include #include diff --git a/apps/interactive-calibration/calibController.cpp b/apps/interactive-calibration/calibController.cpp index 186d373aca..1888ee57db 100644 --- a/apps/interactive-calibration/calibController.cpp +++ b/apps/interactive-calibration/calibController.cpp @@ -1,8 +1,13 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + #include "calibController.hpp" #include #include #include + #include #include diff --git a/apps/interactive-calibration/calibController.hpp b/apps/interactive-calibration/calibController.hpp index 170a80a954..7a0f3f76d0 100644 --- a/apps/interactive-calibration/calibController.hpp +++ b/apps/interactive-calibration/calibController.hpp @@ -1,7 +1,12 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + #ifndef CALIB_CONTROLLER_HPP #define CALIB_CONTROLLER_HPP #include "calibCommon.hpp" + #include #include #include diff --git a/apps/interactive-calibration/calibPipeline.cpp b/apps/interactive-calibration/calibPipeline.cpp index 4575a7024a..1047bfce5f 100644 --- a/apps/interactive-calibration/calibPipeline.cpp +++ b/apps/interactive-calibration/calibPipeline.cpp @@ -1,5 +1,11 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + #include "calibPipeline.hpp" + #include + #include using namespace calib; diff --git a/apps/interactive-calibration/calibPipeline.hpp b/apps/interactive-calibration/calibPipeline.hpp index b5d311e17f..1c22b0d85e 100644 --- a/apps/interactive-calibration/calibPipeline.hpp +++ b/apps/interactive-calibration/calibPipeline.hpp @@ -1,7 +1,13 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + + #ifndef CALIB_PIPELINE_HPP #define CALIB_PIPELINE_HPP #include + #include #include "calibCommon.hpp" diff --git a/apps/interactive-calibration/frameProcessor.cpp b/apps/interactive-calibration/frameProcessor.cpp index 57e1d97d81..1e672b0c45 100644 --- a/apps/interactive-calibration/frameProcessor.cpp +++ b/apps/interactive-calibration/frameProcessor.cpp @@ -1,3 +1,7 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + #include "frameProcessor.hpp" #include "rotationConverters.hpp" @@ -5,6 +9,7 @@ #include #include #include + #include #include #include diff --git a/apps/interactive-calibration/frameProcessor.hpp b/apps/interactive-calibration/frameProcessor.hpp index 119910ad46..4dbb8ab314 100644 --- a/apps/interactive-calibration/frameProcessor.hpp +++ b/apps/interactive-calibration/frameProcessor.hpp @@ -1,9 +1,14 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + #ifndef FRAME_PROCESSOR_HPP #define FRAME_PROCESSOR_HPP #include #include #include + #include "calibCommon.hpp" #include "calibController.hpp" diff --git a/apps/interactive-calibration/main.cpp b/apps/interactive-calibration/main.cpp index 051b24cf2c..af62d4ea40 100644 --- a/apps/interactive-calibration/main.cpp +++ b/apps/interactive-calibration/main.cpp @@ -1,8 +1,13 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + #include #include #include #include #include + #include #include #include diff --git a/apps/interactive-calibration/parametersController.cpp b/apps/interactive-calibration/parametersController.cpp index c9356902da..d581582cb6 100644 --- a/apps/interactive-calibration/parametersController.cpp +++ b/apps/interactive-calibration/parametersController.cpp @@ -1,4 +1,9 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + #include "parametersController.hpp" + #include template diff --git a/apps/interactive-calibration/parametersController.hpp b/apps/interactive-calibration/parametersController.hpp index 6477901990..616f4e7799 100644 --- a/apps/interactive-calibration/parametersController.hpp +++ b/apps/interactive-calibration/parametersController.hpp @@ -1,8 +1,14 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + #ifndef PARAMETERS_CONTROLLER_HPP #define PARAMETERS_CONTROLLER_HPP #include + #include + #include "calibCommon.hpp" namespace calib { diff --git a/apps/interactive-calibration/rotationConverters.cpp b/apps/interactive-calibration/rotationConverters.cpp index dee3b531d6..ff31c9e380 100644 --- a/apps/interactive-calibration/rotationConverters.cpp +++ b/apps/interactive-calibration/rotationConverters.cpp @@ -1,6 +1,11 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + #include "rotationConverters.hpp" #include + #include #include diff --git a/apps/interactive-calibration/rotationConverters.hpp b/apps/interactive-calibration/rotationConverters.hpp index bddce3eb30..fcb5bcc59c 100644 --- a/apps/interactive-calibration/rotationConverters.hpp +++ b/apps/interactive-calibration/rotationConverters.hpp @@ -1,5 +1,9 @@ -#ifndef RAOTATION_CONVERTERS_HPP -#define RAOTATION_CONVERTERS_HPP +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#ifndef ROTATION_CONVERTERS_HPP +#define ROTATION_CONVERTERS_HPP #include From f1dcf71dd7022f3e0440a21ecbaf3612965ed1e5 Mon Sep 17 00:00:00 2001 From: Valeriy Van Date: Wed, 14 Sep 2016 14:48:41 +0300 Subject: [PATCH 152/178] Merge pull request #7178 from valeriyvan:iosfixes * Changes delegate property from assign to weak In modern Objective-C delegate should be weak. In very rare conditions you might want delegate be strong. Assign for delegate is sign of legacy code. This change prevents crash when you forget nil delegate in dealloc and makes rush with nilling delegate unnecessary. This change shouldn't break any existing code. * Adds implementation for setters and getters for weak delegate properties for non ARC Obj-C files For whatever reason compiler can't synthesize these. And yes, it's time to convert all Objective-C stuff to ARC. --- .../videoio/include/opencv2/videoio/cap_ios.h | 4 ++-- modules/videoio/src/cap_ios_photo_camera.mm | 15 +++++++++++---- modules/videoio/src/cap_ios_video_camera.mm | 18 +++++++++++++----- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/modules/videoio/include/opencv2/videoio/cap_ios.h b/modules/videoio/include/opencv2/videoio/cap_ios.h index 9075fe1c80..13bf4b987c 100644 --- a/modules/videoio/include/opencv2/videoio/cap_ios.h +++ b/modules/videoio/include/opencv2/videoio/cap_ios.h @@ -133,7 +133,7 @@ } -@property (nonatomic, assign) id delegate; +@property (nonatomic, weak) id delegate; @property (nonatomic, assign) BOOL grayscaleMode; @property (nonatomic, assign) BOOL recordVideo; @@ -167,7 +167,7 @@ AVCaptureStillImageOutput *stillImageOutput; } -@property (nonatomic, assign) id delegate; +@property (nonatomic, weak) id delegate; - (void)takePicture; diff --git a/modules/videoio/src/cap_ios_photo_camera.mm b/modules/videoio/src/cap_ios_photo_camera.mm index 8cf19226b6..9b44156efc 100644 --- a/modules/videoio/src/cap_ios_photo_camera.mm +++ b/modules/videoio/src/cap_ios_photo_camera.mm @@ -36,6 +36,9 @@ @interface CvPhotoCamera () +{ + id _delegate; +} @property (nonatomic, strong) AVCaptureStillImageOutput* stillImageOutput; @@ -53,8 +56,14 @@ #pragma mark Public @synthesize stillImageOutput; -@synthesize delegate; +- (void)setDelegate:(id)newDelegate { + _delegate = newDelegate; +} + +- (id)delegate { + return _delegate; +} #pragma mark - Public interface @@ -106,9 +115,7 @@ cameraAvailable = YES; NSLog(@"CvPhotoCamera captured image"); - if (self.delegate) { - [self.delegate photoCamera:self capturedImage:newImage]; - } + [self.delegate photoCamera:self capturedImage:newImage]; [self.captureSession startRunning]; }); diff --git a/modules/videoio/src/cap_ios_video_camera.mm b/modules/videoio/src/cap_ios_video_camera.mm index c1a0b4d774..c3704a1f44 100644 --- a/modules/videoio/src/cap_ios_video_camera.mm +++ b/modules/videoio/src/cap_ios_video_camera.mm @@ -61,11 +61,12 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} @implementation CvVideoCamera +{ + id _delegate; +} - -@synthesize delegate; @synthesize grayscaleMode; @synthesize customPreviewLayer; @@ -78,7 +79,13 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} @synthesize recordPixelBufferAdaptor; @synthesize recordAssetWriter; +- (void)setDelegate:(id)newDelegate { + _delegate = newDelegate; +} +- (id)delegate { + return _delegate; +} #pragma mark - Constructors @@ -450,7 +457,8 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} { (void)captureOutput; (void)connection; - if (self.delegate) { + auto strongDelegate = self.delegate; + if (strongDelegate) { // convert from Core Media to Core Video CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); @@ -492,8 +500,8 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} CGImage* dstImage; - if ([self.delegate respondsToSelector:@selector(processImage:)]) { - [self.delegate processImage:image]; + if ([strongDelegate respondsToSelector:@selector(processImage:)]) { + [strongDelegate processImage:image]; } // check if matrix data pointer or dimensions were changed by the delegate From 50d02b9f846cbb66fda8f91ee359af7c01316dc7 Mon Sep 17 00:00:00 2001 From: danil-tolkachev Date: Wed, 14 Sep 2016 21:39:11 +0300 Subject: [PATCH 153/178] supress numpy future warning with `None` comparison --- samples/python/houghcircles.py | 2 +- samples/python/houghlines.py | 2 +- samples/python/tst_scene_render.py | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/samples/python/houghcircles.py b/samples/python/houghcircles.py index 41cce29be7..c766c1cab2 100755 --- a/samples/python/houghcircles.py +++ b/samples/python/houghcircles.py @@ -30,7 +30,7 @@ if __name__ == '__main__': circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 10, np.array([]), 100, 30, 1, 30) - if circles != None: # Check if circles have been found and only then iterate over these and add them to the image + if circles is not None: # Check if circles have been found and only then iterate over these and add them to the image a, b, c = circles.shape for i in range(b): cv2.circle(cimg, (circles[0][i][0], circles[0][i][1]), circles[0][i][2], (0, 0, 255), 3, cv2.LINE_AA) diff --git a/samples/python/houghlines.py b/samples/python/houghlines.py index 445068aef4..76e074cb1b 100755 --- a/samples/python/houghlines.py +++ b/samples/python/houghlines.py @@ -36,7 +36,7 @@ if __name__ == '__main__': else: # HoughLines lines = cv2.HoughLines(dst, 1, math.pi/180.0, 50, np.array([]), 0, 0) - if lines != None: + if lines is not None: a,b,c = lines.shape for i in range(a): rho = lines[i][0][0] diff --git a/samples/python/tst_scene_render.py b/samples/python/tst_scene_render.py index 992baf34f3..78ce478a12 100644 --- a/samples/python/tst_scene_render.py +++ b/samples/python/tst_scene_render.py @@ -21,7 +21,7 @@ class TestSceneRender(): self.deformation = deformation self.speed = speed - if bgImg != None: + if bgImg is not None: self.sceneBg = bgImg.copy() else: self.sceneBg = np.zeros(defaultSize, defaultSize, np.uint8) @@ -29,7 +29,7 @@ class TestSceneRender(): self.w = self.sceneBg.shape[0] self.h = self.sceneBg.shape[1] - if fgImg != None: + if fgImg is not None: self.foreground = fgImg.copy() self.center = self.currentCenter = (int(self.w/2 - fgImg.shape[0]/2), int(self.h/2 - fgImg.shape[1]/2)) @@ -52,7 +52,7 @@ class TestSceneRender(): def getRectInTime(self, time): - if self.foreground != None: + if self.foreground is not None: tmp = np.array(self.center) + np.array((self.getXOffset(time), self.getYOffset(time))) x0, y0 = tmp x1, y1 = tmp + self.foreground.shape[0:2] @@ -64,7 +64,7 @@ class TestSceneRender(): def getCurrentRect(self): - if self.foreground != None: + if self.foreground is not None: x0 = self.currentCenter[0] y0 = self.currentCenter[1] @@ -79,7 +79,7 @@ class TestSceneRender(): def getNextFrame(self): img = self.sceneBg.copy() - if self.foreground != None: + if self.foreground is not None: self.currentCenter = (self.center[0] + self.getXOffset(self.time), self.center[1] + self.getYOffset(self.time)) img[self.currentCenter[0]:self.currentCenter[0]+self.foreground.shape[0], self.currentCenter[1]:self.currentCenter[1]+self.foreground.shape[1]] = self.foreground From 5357e28a2f172b0466471b399a5fed1ae9552b59 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Wed, 14 Sep 2016 16:22:35 -0400 Subject: [PATCH 154/178] Removed some extra semi-colons Fixes clang -Wextra-semi warnings. --- modules/core/include/opencv2/core/utility.hpp | 14 +++++++------- modules/video/src/bgfg_KNN.cpp | 6 +++--- modules/videoio/src/precomp.hpp | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index e465faee5f..01f5c7664a 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -495,8 +495,8 @@ void Mat::forEach_impl(const Functor& operation) { { public: PixelOperationWrapper(Mat_<_Tp>* const frame, const Functor& _operation) - : mat(frame), op(_operation) {}; - virtual ~PixelOperationWrapper(){}; + : mat(frame), op(_operation) {} + virtual ~PixelOperationWrapper(){} // ! Overloaded virtual operator // convert range call to row call. virtual void operator()(const Range &range) const { @@ -525,7 +525,7 @@ void Mat::forEach_impl(const Functor& operation) { this->rowCall(&idx[0], COLS, DIMS); } } - }; + } private: Mat_<_Tp>* const mat; const Functor op; @@ -562,12 +562,12 @@ void Mat::forEach_impl(const Functor& operation) { op(*pixel++, static_cast(idx)); idx[1]++; } - }; + } PixelOperationWrapper& operator=(const PixelOperationWrapper &) { CV_Assert(false); // We can not remove this implementation because Visual Studio warning C4822. return *this; - }; + } }; parallel_for_(cv::Range(0, LINES), PixelOperationWrapper(reinterpret_cast*>(this), operation)); @@ -650,8 +650,8 @@ private: virtual void deleteDataInstance(void* pData) const {delete (T*)pData;} // Wrapper to release data by template // Disable TLS copy operations - TLSData(TLSData &) {}; - TLSData& operator =(const TLSData &) {return *this;}; + TLSData(TLSData &) {} + TLSData& operator =(const TLSData &) {return *this;} }; /** @brief Designed for command line parsing diff --git a/modules/video/src/bgfg_KNN.cpp b/modules/video/src/bgfg_KNN.cpp index 8c92d77acd..66be34a00f 100755 --- a/modules/video/src/bgfg_KNN.cpp +++ b/modules/video/src/bgfg_KNN.cpp @@ -319,7 +319,7 @@ CV_INLINE void { m_nNextShortUpdate[pixel] = (uchar)( rand() % m_nShortUpdate ); }; -}; +} CV_INLINE int _cvCheckPixelBackgroundNP(long pixel, @@ -436,7 +436,7 @@ CV_INLINE int }; } return 0; -}; +} CV_INLINE void icvUpdatePixelBackgroundNP(const Mat& _src, Mat& _dst, @@ -554,7 +554,7 @@ CV_INLINE void i++; } } -}; +} diff --git a/modules/videoio/src/precomp.hpp b/modules/videoio/src/precomp.hpp index 517dc9186b..cb3a775dc9 100644 --- a/modules/videoio/src/precomp.hpp +++ b/modules/videoio/src/precomp.hpp @@ -192,6 +192,6 @@ namespace cv Ptr createGPhoto2Capture(int index); Ptr createGPhoto2Capture(const String& deviceName); -}; +} #endif /* __VIDEOIO_H_ */ From a4a6ee34bf017b33f617bdb596edd8be93903c1d Mon Sep 17 00:00:00 2001 From: stbnps Date: Mon, 29 Aug 2016 22:49:02 +0200 Subject: [PATCH 155/178] Added support for V4L2_PIX_FMT_Y16 --- modules/videoio/src/cap_v4l.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 01a250b41e..f7d0e2ca7d 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -466,12 +466,16 @@ static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) { V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SGBRG8, - V4L2_PIX_FMT_RGB24 + V4L2_PIX_FMT_RGB24, + V4L2_PIX_FMT_Y16 }; for (size_t i = 0; i < sizeof(try_order) / sizeof(__u32); i++) { capture->palette = try_order[i]; if (try_palette_v4l2(capture)) { + if (capture->palette == V4L2_PIX_FMT_Y16) { + capture->convert_rgb = false; + } return 0; } } @@ -558,6 +562,7 @@ static int v4l2_num_channels(__u32 palette) { case V4L2_PIX_FMT_YVU420: case V4L2_PIX_FMT_MJPEG: case V4L2_PIX_FMT_JPEG: + case V4L2_PIX_FMT_Y16: return 1; case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_UYVY: @@ -589,8 +594,14 @@ static void v4l2_create_frame(CvCaptureCAM_V4L *capture) { } /* Set up Image data */ - cvInitImageHeader(&capture->frame, size, IPL_DEPTH_8U, channels); + switch(capture->palette) { + case V4L2_PIX_FMT_Y16: + cvInitImageHeader(&capture->frame, size, IPL_DEPTH_16U, channels); + break; + default: + cvInitImageHeader(&capture->frame, size, IPL_DEPTH_8U, channels); + } /* Allocate space for pixelformat we convert to. * If we do not convert frame is just points to the buffer */ @@ -1546,6 +1557,11 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start, (unsigned char*)capture->frame.imageData); break; + case V4L2_PIX_FMT_Y16: + memcpy((char *)capture->frame.imageData, + (char *)capture->buffers[capture->bufferIndex].start, + capture->frame.imageSize); + break; } return(&capture->frame); From 60b33046a71c4e661b03b7c81f7a69ece02c2290 Mon Sep 17 00:00:00 2001 From: Luis Roberto Morales Iglesias Date: Thu, 15 Sep 2016 14:20:02 +0200 Subject: [PATCH 156/178] [Issue #7290] Fixes OpenNI and OpenNI2 linking conflict --- modules/videoio/src/cap.cpp | 6 ++++++ modules/videoio/src/cap_openni2.cpp | 2 +- modules/videoio/src/precomp.hpp | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/videoio/src/cap.cpp b/modules/videoio/src/cap.cpp index 55c20bef52..a774afbaad 100644 --- a/modules/videoio/src/cap.cpp +++ b/modules/videoio/src/cap.cpp @@ -340,6 +340,12 @@ CV_IMPL CvCapture * cvCreateFileCaptureWithPreference (const char * filename, in if (apiPreference) break; #endif +#ifdef HAVE_OPENNI2 + case CV_CAP_OPENNI2: + TRY_OPEN(result, cvCreateFileCapture_OpenNI2 (filename)) + if (apiPreference) break; +#endif + case CV_CAP_IMAGES: TRY_OPEN(result, cvCreateFileCapture_Images (filename)) } diff --git a/modules/videoio/src/cap_openni2.cpp b/modules/videoio/src/cap_openni2.cpp index aebf1889a1..775038e93f 100644 --- a/modules/videoio/src/cap_openni2.cpp +++ b/modules/videoio/src/cap_openni2.cpp @@ -1086,7 +1086,7 @@ CvCapture* cvCreateCameraCapture_OpenNI2( int index ) return 0; } -CvCapture* cvCreateFileCapture_OpenNI( const char* filename ) +CvCapture* cvCreateFileCapture_OpenNI2( const char* filename ) { CvCapture_OpenNI2* capture = new CvCapture_OpenNI2( filename ); diff --git a/modules/videoio/src/precomp.hpp b/modules/videoio/src/precomp.hpp index cb3a775dc9..e166596cad 100644 --- a/modules/videoio/src/precomp.hpp +++ b/modules/videoio/src/precomp.hpp @@ -124,6 +124,7 @@ CvVideoWriter* cvCreateVideoWriter_MSMF( const char* filename, int fourcc, CvCapture* cvCreateCameraCapture_OpenNI( int index ); CvCapture* cvCreateCameraCapture_OpenNI2( int index ); CvCapture* cvCreateFileCapture_OpenNI( const char* filename ); +CvCapture* cvCreateFileCapture_OpenNI2( const char* filename ); CvCapture* cvCreateCameraCapture_Android( int index ); CvCapture* cvCreateCameraCapture_XIMEA( int index ); CvCapture* cvCreateCameraCapture_AVFoundation(int index); From 0db4b7cebb7b0ee12f2814aedd35b5990f2978f4 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Fri, 16 Sep 2016 08:06:14 +0900 Subject: [PATCH 157/178] fix build error on CUDA + Aarch64 * __fp16 doesn't exist on nvcc, but it slips through ifdef guard --- modules/core/include/opencv2/core/cvdef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index 8011c36ffa..a26cd1caf6 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -310,7 +310,7 @@ enum CpuFeatures { typedef union Cv16suf { short i; -#if ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) ) +#if ( defined (__arm__) || defined (__aarch64__) ) && !defined (__CUDACC__) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) ) __fp16 h; #endif struct _fp16Format From 0d626c8fefa1332b246586a6366fb45021d572a7 Mon Sep 17 00:00:00 2001 From: Gregory Kramida Date: Thu, 15 Sep 2016 16:13:38 -0400 Subject: [PATCH 158/178] v4l2 backend: Y16 default behavior fixed & FOURCC setting added 1) Cameras started with Y16 (V4L2_PIX_FMT_Y16) format via v4l2 backend will now exhibit default camera behavior, i.e. convert the 16-bit image to BGR as with all other formats. 16-bit 1-channel output will now only be produced for Y16 if CV_CAP_PROP_CONVERT_RGB is set to "false" using VideoCap::set method. 2) v4l2 videoio backend now supports setting CV_CAP_PROP_FOURCC explicitly (icvSetPropertyCAM_V4L function in cap_v4l.cpp), allowing users to manually set the codec on cameras that support multiple codecs. --- modules/videoio/src/cap_v4l.cpp | 57 +++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index f7d0e2ca7d..9114108dfd 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -453,6 +453,10 @@ static int try_init_v4l2(CvCaptureCAM_V4L* capture, const char *deviceName) } static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) { + //in case palette is already set and works, no need to setup. + if(capture->palette != 0 and try_palette_v4l2(capture)){ + return 0; + } __u32 try_order[] = { V4L2_PIX_FMT_BGR24, V4L2_PIX_FMT_YVU420, @@ -473,9 +477,6 @@ static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) { for (size_t i = 0; i < sizeof(try_order) / sizeof(__u32); i++) { capture->palette = try_order[i]; if (try_palette_v4l2(capture)) { - if (capture->palette == V4L2_PIX_FMT_Y16) { - capture->convert_rgb = false; - } return 0; } } @@ -578,6 +579,7 @@ static int v4l2_num_channels(__u32 palette) { static void v4l2_create_frame(CvCaptureCAM_V4L *capture) { CvSize size(capture->form.fmt.pix.width, capture->form.fmt.pix.height); int channels = 3; + int depth = IPL_DEPTH_8U; if (!capture->convert_rgb) { channels = v4l2_num_channels(capture->palette); @@ -590,18 +592,17 @@ static void v4l2_create_frame(CvCaptureCAM_V4L *capture) { case V4L2_PIX_FMT_YVU420: size.height = size.height * 3 / 2; // "1.5" channels break; + case V4L2_PIX_FMT_Y16: + if(!capture->convert_rgb){ + depth = IPL_DEPTH_16U; + } + break; } } /* Set up Image data */ - switch(capture->palette) { - case V4L2_PIX_FMT_Y16: - cvInitImageHeader(&capture->frame, size, IPL_DEPTH_16U, channels); - break; - default: - cvInitImageHeader(&capture->frame, size, IPL_DEPTH_8U, channels); + cvInitImageHeader(&capture->frame, size, depth, channels); - } /* Allocate space for pixelformat we convert to. * If we do not convert frame is just points to the buffer */ @@ -1100,6 +1101,15 @@ uyvy_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst) cvtColor(Mat(height, width, CV_8UC2, src), Mat(height, width, CV_8UC3, dst), COLOR_YUV2BGR_UYVY); } + +static inline void +y16_to_rgb24 (int width, int height, unsigned char* src, unsigned char* dst) +{ + Mat gray8; + Mat(height, width, CV_16UC1, src).convertTo(gray8, CV_8U, 0.00390625); + cvtColor(gray8,Mat(height, width, CV_8UC3, dst),COLOR_GRAY2BGR); +} + #ifdef HAVE_JPEG /* convert from mjpeg to rgb24 */ @@ -1558,9 +1568,16 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { (unsigned char*)capture->frame.imageData); break; case V4L2_PIX_FMT_Y16: - memcpy((char *)capture->frame.imageData, - (char *)capture->buffers[capture->bufferIndex].start, - capture->frame.imageSize); + if(capture->convert_rgb){ + y16_to_rgb24(capture->form.fmt.pix.width, + capture->form.fmt.pix.height, + (unsigned char*)capture->buffers[capture->bufferIndex].start, + (unsigned char*)capture->frame.imageData); + }else{ + memcpy((char *)capture->frame.imageData, + (char *)capture->buffers[capture->bufferIndex].start, + capture->frame.imageSize); + } break; } @@ -1780,6 +1797,20 @@ static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, capture->convert_rgb = bool(value) && possible; retval = possible || !bool(value); break; + case CV_CAP_PROP_FOURCC: + { + __u32 old_palette = capture->palette; + __u32 new_palette = static_cast<__u32>(value); + capture->palette = new_palette; + if (v4l2_reset(capture)) { + retval = true; + } else { + capture->palette = old_palette; + v4l2_reset(capture); + retval = false; + } + } + break; default: retval = icvSetControl(capture, property_id, value); break; From 0a9470bf090d51eb4cfff2575d49416559552256 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Fri, 16 Sep 2016 10:03:42 +0300 Subject: [PATCH 159/178] Compatibility fix for Visual Studio 2012; --- modules/core/src/ocl.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 924b360851..8212030c8e 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -45,7 +45,9 @@ #include #include #include // std::cerr +#if !(defined _MSC_VER) || (defined _MSC_VER && _MSC_VER > 1700) #include +#endif #define CV_OPENCL_ALWAYS_SHOW_BUILD_LOG 0 #define CV_OPENCL_SHOW_RUN_ERRORS 0 From 48f132f35f27a4dd189ebca660ed438338c6c01e Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Wed, 7 Sep 2016 18:30:17 +0300 Subject: [PATCH 160/178] Fix Sobel evaluation for image ROI without isolated border. --- modules/imgproc/src/canny.cpp | 3 ++ modules/imgproc/src/deriv.cpp | 6 ++- modules/imgproc/test/ocl/test_canny.cpp | 12 +----- modules/imgproc/test/test_filter.cpp | 50 +++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 784b5ffe24..22ec1f39c8 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -69,6 +69,9 @@ static bool ippCanny(const Mat& _src, const Mat& dx_, const Mat& dy_, Mat& _dst, CV_INSTRUMENT_REGION_IPP() #if USE_IPP_CANNY + if (!useCustomDeriv && _src.isSubmatrix()) + return false; // IPP Sobel doesn't support transparent ROI border + int size = 0, size1 = 0; IppiSize roi = { _src.cols, _src.rows }; diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index aa9183aceb..0dce2fd9e7 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -307,7 +307,7 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, { CV_INSTRUMENT_REGION_IPP() - if ((borderType != BORDER_REPLICATE) || ((3 != ksize) && (5 != ksize))) + if (((borderType & ~BORDER_ISOLATED) != BORDER_REPLICATE) || ((3 != ksize) && (5 != ksize))) return false; if (fabs(delta) > FLT_EPSILON) return false; @@ -317,6 +317,10 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, int bufSize = 0; cv::AutoBuffer buffer; Mat src = _src.getMat(), dst = _dst.getMat(); + + if ((borderType & BORDER_ISOLATED) == 0 && src.isSubmatrix()) + return false; + if ( ddepth < 0 ) ddepth = src.depth(); diff --git a/modules/imgproc/test/ocl/test_canny.cpp b/modules/imgproc/test/ocl/test_canny.cpp index f9c724b049..ca436a4f67 100644 --- a/modules/imgproc/test/ocl/test_canny.cpp +++ b/modules/imgproc/test/ocl/test_canny.cpp @@ -99,11 +99,7 @@ OCL_TEST_P(Canny, Accuracy) generateTestData(); const double low_thresh = 50.0, high_thresh = 100.0; - double eps = 1e-2; -#ifdef ANDROID - if (cv::ocl::Device::getDefault().isNVidia()) - eps = 12e-3; -#endif + double eps = 12e-3; OCL_OFF(cv::Canny(src_roi, dst_roi, low_thresh, high_thresh, aperture_size, useL2gradient)); OCL_ON(cv::Canny(usrc_roi, udst_roi, low_thresh, high_thresh, aperture_size, useL2gradient)); @@ -117,11 +113,7 @@ OCL_TEST_P(Canny, AccuracyCustomGradient) generateTestData(); const double low_thresh = 50.0, high_thresh = 100.0; - double eps = 1e-2; -#ifdef ANDROID - if (cv::ocl::Device::getDefault().isNVidia()) - eps = 12e-3; -#endif + double eps = 12e-3; OCL_OFF(cv::Canny(src_roi, dst_roi, low_thresh, high_thresh, aperture_size, useL2gradient)); OCL_ON( diff --git a/modules/imgproc/test/test_filter.cpp b/modules/imgproc/test/test_filter.cpp index 5994b1b11b..886c5ab90a 100644 --- a/modules/imgproc/test/test_filter.cpp +++ b/modules/imgproc/test/test_filter.cpp @@ -2015,3 +2015,53 @@ TEST(Imgproc_Morphology, iterated) ASSERT_EQ(0.0, norm(dst0, dst2, NORM_INF)); } } + +TEST(Imgproc_Sobel, borderTypes) +{ + int kernelSize = 3; + + /// ksize > src_roi.size() + Mat src = (Mat_(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9), dst, expected_dst; + Mat src_roi = src(Rect(1, 1, 1, 1)); + src_roi.setTo(cv::Scalar::all(0)); + + // should work like !BORDER_ISOLATED, so the function MUST read values in full matrix + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REPLICATE); + EXPECT_EQ(8, dst.at(0, 0)); + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REFLECT); + EXPECT_EQ(8, dst.at(0, 0)); + + // should work like BORDER_ISOLATED + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REPLICATE | BORDER_ISOLATED); + EXPECT_EQ(0, dst.at(0, 0)); + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REFLECT | BORDER_ISOLATED); + EXPECT_EQ(0, dst.at(0, 0)); + + /// ksize <= src_roi.size() + src = Mat(5, 5, CV_8UC1, cv::Scalar(5)); + src_roi = src(Rect(1, 1, 3, 3)); + src_roi.setTo(0); + + // should work like !BORDER_ISOLATED, so the function MUST read values in full matrix + expected_dst = + (Mat_(3, 3) << -15, 0, 15, -20, 0, 20, -15, 0, 15); + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REPLICATE); + EXPECT_EQ(expected_dst.type(), dst.type()); + EXPECT_EQ(expected_dst.size(), dst.size()); + EXPECT_DOUBLE_EQ(0.0, cvtest::norm(expected_dst, dst, NORM_INF)); + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REFLECT); + EXPECT_EQ(expected_dst.type(), dst.type()); + EXPECT_EQ(expected_dst.size(), dst.size()); + EXPECT_DOUBLE_EQ(0.0, cvtest::norm(expected_dst, dst, NORM_INF)); + + // should work like !BORDER_ISOLATED, so the function MUST read values in full matrix + expected_dst = Mat::zeros(3, 3, CV_16SC1); + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REPLICATE | BORDER_ISOLATED); + EXPECT_EQ(expected_dst.type(), dst.type()); + EXPECT_EQ(expected_dst.size(), dst.size()); + EXPECT_DOUBLE_EQ(0.0, cvtest::norm(expected_dst, dst, NORM_INF)); + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REFLECT | BORDER_ISOLATED); + EXPECT_EQ(expected_dst.type(), dst.type()); + EXPECT_EQ(expected_dst.size(), dst.size()); + EXPECT_DOUBLE_EQ(0.0, cvtest::norm(expected_dst, dst, NORM_INF)); +} From 4540260df94510349ddb0261b40f4f386fa0344b Mon Sep 17 00:00:00 2001 From: k-shinotsuka Date: Sat, 17 Sep 2016 16:32:34 +0900 Subject: [PATCH 161/178] improve Luv2RGB_b() --- modules/imgproc/src/color.cpp | 72 ++++++++++++++++------------------- 1 file changed, 32 insertions(+), 40 deletions(-) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 746b303292..524af2b7b2 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -6072,11 +6072,6 @@ struct Luv2RGB_b v_scale = vdupq_n_f32(255.f); v_alpha = vdup_n_u8(ColorChannel::max()); #elif CV_SSE2 - v_scale_inv = _mm_set1_ps(100.f/255.f); - v_coeff1 = _mm_set1_ps(1.388235294117647f); - v_coeff2 = _mm_set1_ps(1.027450980392157f); - v_134 = _mm_set1_ps(134.f); - v_140 = _mm_set1_ps(140.f); v_scale = _mm_set1_ps(255.f); v_zero = _mm_setzero_si128(); haveSIMD = checkHardwareSupport(CV_CPU_SSE2); @@ -6086,6 +6081,7 @@ struct Luv2RGB_b #if CV_SSE2 // 16s x 8 void process(__m128i v_l, __m128i v_u, __m128i v_v, + __m128 v_coeffs, __m128 v_res, float * buf) const { __m128 v_l0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_l, v_zero)); @@ -6096,15 +6092,26 @@ struct Luv2RGB_b __m128 v_u1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_u, v_zero)); __m128 v_v1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_v, v_zero)); - v_l0 = _mm_mul_ps(v_l0, v_scale_inv); - v_l1 = _mm_mul_ps(v_l1, v_scale_inv); + v_l0 = _mm_mul_ps(v_l0, v_coeffs); + v_u1 = _mm_mul_ps(v_u1, v_coeffs); + v_l0 = _mm_sub_ps(v_l0, v_res); + v_u1 = _mm_sub_ps(v_u1, v_res); - v_u0 = _mm_sub_ps(_mm_mul_ps(v_u0, v_coeff1), v_134); - v_u1 = _mm_sub_ps(_mm_mul_ps(v_u1, v_coeff1), v_134); - v_v0 = _mm_sub_ps(_mm_mul_ps(v_v0, v_coeff2), v_140); - v_v1 = _mm_sub_ps(_mm_mul_ps(v_v1, v_coeff2), v_140); + v_coeffs = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_coeffs), 0x49)); + v_res = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_res), 0x49)); - _mm_interleave_ps(v_l0, v_l1, v_u0, v_u1, v_v0, v_v1); + v_l1 = _mm_mul_ps(v_l1, v_coeffs); + v_v0 = _mm_mul_ps(v_v0, v_coeffs); + v_l1 = _mm_sub_ps(v_l1, v_res); + v_v0 = _mm_sub_ps(v_v0, v_res); + + v_coeffs = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_coeffs), 0x49)); + v_res = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_res), 0x49)); + + v_u0 = _mm_mul_ps(v_u0, v_coeffs); + v_v1 = _mm_mul_ps(v_v1, v_coeffs); + v_u0 = _mm_sub_ps(v_u0, v_res); + v_v1 = _mm_sub_ps(v_v1, v_res); _mm_store_ps(buf, v_l0); _mm_store_ps(buf + 4, v_l1); @@ -6121,6 +6128,11 @@ struct Luv2RGB_b uchar alpha = ColorChannel::max(); float CV_DECL_ALIGNED(16) buf[3*BLOCK_SIZE]; + #if CV_SSE2 + __m128 v_coeffs = _mm_set_ps(100.f/255.f, 1.027450980392157f, 1.388235294117647f, 100.f/255.f); + __m128 v_res = _mm_set_ps(0.f, 140.f, 134.f, 0.f); + #endif + for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 ) { int dn = std::min(n - i, (int)BLOCK_SIZE); @@ -6148,36 +6160,16 @@ struct Luv2RGB_b #elif CV_SSE2 if (haveSIMD) { - for ( ; j <= (dn - 32) * 3; j += 96) + for ( ; j <= (dn - 8) * 3; j += 24) { - __m128i v_r0 = _mm_loadu_si128((__m128i const *)(src + j)); - __m128i v_r1 = _mm_loadu_si128((__m128i const *)(src + j + 16)); - __m128i v_g0 = _mm_loadu_si128((__m128i const *)(src + j + 32)); - __m128i v_g1 = _mm_loadu_si128((__m128i const *)(src + j + 48)); - __m128i v_b0 = _mm_loadu_si128((__m128i const *)(src + j + 64)); - __m128i v_b1 = _mm_loadu_si128((__m128i const *)(src + j + 80)); + __m128i v_src0 = _mm_loadu_si128((__m128i const *)(src + j)); + __m128i v_src1 = _mm_loadl_epi64((__m128i const *)(src + j + 16)); - _mm_deinterleave_epi8(v_r0, v_r1, v_g0, v_g1, v_b0, v_b1); - - process(_mm_unpacklo_epi8(v_r0, v_zero), - _mm_unpacklo_epi8(v_g0, v_zero), - _mm_unpacklo_epi8(v_b0, v_zero), + process(_mm_unpacklo_epi8(v_src0, v_zero), + _mm_unpackhi_epi8(v_src0, v_zero), + _mm_unpacklo_epi8(v_src1, v_zero), + v_coeffs, v_res, buf + j); - - process(_mm_unpackhi_epi8(v_r0, v_zero), - _mm_unpackhi_epi8(v_g0, v_zero), - _mm_unpackhi_epi8(v_b0, v_zero), - buf + j + 24); - - process(_mm_unpacklo_epi8(v_r1, v_zero), - _mm_unpacklo_epi8(v_g1, v_zero), - _mm_unpacklo_epi8(v_b1, v_zero), - buf + j + 48); - - process(_mm_unpackhi_epi8(v_r1, v_zero), - _mm_unpackhi_epi8(v_g1, v_zero), - _mm_unpackhi_epi8(v_b1, v_zero), - buf + j + 72); } } #endif @@ -6261,7 +6253,7 @@ struct Luv2RGB_b float32x4_t v_scale, v_scale_inv, v_coeff1, v_coeff2, v_134, v_140; uint8x8_t v_alpha; #elif CV_SSE2 - __m128 v_scale, v_scale_inv, v_coeff1, v_coeff2, v_134, v_140; + __m128 v_scale; __m128i v_zero; bool haveSIMD; #endif From 37be868679252cc54af06f4395e3089c600e5f58 Mon Sep 17 00:00:00 2001 From: k-shinotsuka Date: Sun, 18 Sep 2016 10:05:11 +0900 Subject: [PATCH 162/178] improve RGB2Luv_b() --- modules/imgproc/src/color.cpp | 72 ++++++++++++----------------------- 1 file changed, 25 insertions(+), 47 deletions(-) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 746b303292..c60f7237f2 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -5872,38 +5872,33 @@ struct RGB2Luv_b #elif CV_SSE2 v_zero = _mm_setzero_si128(); v_scale_inv = _mm_set1_ps(1.f/255.f); - v_scale = _mm_set1_ps(2.55f); - v_coeff1 = _mm_set1_ps(0.72033898305084743f); - v_coeff2 = _mm_set1_ps(96.525423728813564f); - v_coeff3 = _mm_set1_ps(0.9732824427480916f); - v_coeff4 = _mm_set1_ps(136.259541984732824f); haveSIMD = checkHardwareSupport(CV_CPU_SSE2); #endif } #if CV_SSE2 void process(const float * buf, - __m128i & v_l, __m128i & v_u, __m128i & v_v) const + __m128 & v_coeffs, __m128 & v_res, uchar * dst) const { __m128 v_l0f = _mm_load_ps(buf); __m128 v_l1f = _mm_load_ps(buf + 4); __m128 v_u0f = _mm_load_ps(buf + 8); __m128 v_u1f = _mm_load_ps(buf + 12); - __m128 v_v0f = _mm_load_ps(buf + 16); - __m128 v_v1f = _mm_load_ps(buf + 20); - _mm_deinterleave_ps(v_l0f, v_l1f, v_u0f, v_u1f, v_v0f, v_v1f); + v_l0f = _mm_add_ps(_mm_mul_ps(v_l0f, v_coeffs), v_res); + v_u1f = _mm_add_ps(_mm_mul_ps(v_u1f, v_coeffs), v_res); + v_coeffs = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_coeffs), 0x92)); + v_res = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_res), 0x92)); + v_u0f = _mm_add_ps(_mm_mul_ps(v_u0f, v_coeffs), v_res); + v_coeffs = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_coeffs), 0x92)); + v_res = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_res), 0x92)); + v_l1f = _mm_add_ps(_mm_mul_ps(v_l1f, v_coeffs), v_res); - v_l0f = _mm_mul_ps(v_l0f, v_scale); - v_l1f = _mm_mul_ps(v_l1f, v_scale); - v_u0f = _mm_add_ps(_mm_mul_ps(v_u0f, v_coeff1), v_coeff2); - v_u1f = _mm_add_ps(_mm_mul_ps(v_u1f, v_coeff1), v_coeff2); - v_v0f = _mm_add_ps(_mm_mul_ps(v_v0f, v_coeff3), v_coeff4); - v_v1f = _mm_add_ps(_mm_mul_ps(v_v1f, v_coeff3), v_coeff4); + __m128i v_l = _mm_packs_epi32(_mm_cvtps_epi32(v_l0f), _mm_cvtps_epi32(v_l1f)); + __m128i v_u = _mm_packs_epi32(_mm_cvtps_epi32(v_u0f), _mm_cvtps_epi32(v_u1f)); + __m128i v_l0 = _mm_packus_epi16(v_l, v_u); - v_l = _mm_packs_epi32(_mm_cvtps_epi32(v_l0f), _mm_cvtps_epi32(v_l1f)); - v_u = _mm_packs_epi32(_mm_cvtps_epi32(v_u0f), _mm_cvtps_epi32(v_u1f)); - v_v = _mm_packs_epi32(_mm_cvtps_epi32(v_v0f), _mm_cvtps_epi32(v_v1f)); + _mm_storeu_si128((__m128i *)(dst), v_l0); } #endif @@ -5912,6 +5907,11 @@ struct RGB2Luv_b int i, j, scn = srccn; float CV_DECL_ALIGNED(16) buf[3*BLOCK_SIZE]; + #if CV_SSE2 + __m128 v_coeffs = _mm_set_ps(2.55f, 0.9732824427480916f, 0.72033898305084743f, 2.55f); + __m128 v_res = _mm_set_ps(0.f, 136.259541984732824f, 96.525423728813564f, 0.f); + #endif + for( i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE*3 ) { int dn = std::min(n - i, (int)BLOCK_SIZE); @@ -5996,38 +5996,16 @@ struct RGB2Luv_b #elif CV_SSE2 if (haveSIMD) { - for ( ; j <= (dn - 32) * 3; j += 96) + for ( ; j <= (dn - 16) * 3; j += 48) { - __m128i v_l_0, v_u_0, v_v_0; process(buf + j, - v_l_0, v_u_0, v_v_0); + v_coeffs, v_res, dst + j); - __m128i v_l_1, v_u_1, v_v_1; - process(buf + j + 24, - v_l_1, v_u_1, v_v_1); + process(buf + j + 16, + v_coeffs, v_res, dst + j + 16); - __m128i v_l0 = _mm_packus_epi16(v_l_0, v_l_1); - __m128i v_u0 = _mm_packus_epi16(v_u_0, v_u_1); - __m128i v_v0 = _mm_packus_epi16(v_v_0, v_v_1); - - process(buf + j + 48, - v_l_0, v_u_0, v_v_0); - - process(buf + j + 72, - v_l_1, v_u_1, v_v_1); - - __m128i v_l1 = _mm_packus_epi16(v_l_0, v_l_1); - __m128i v_u1 = _mm_packus_epi16(v_u_0, v_u_1); - __m128i v_v1 = _mm_packus_epi16(v_v_0, v_v_1); - - _mm_interleave_epi8(v_l0, v_l1, v_u0, v_u1, v_v0, v_v1); - - _mm_storeu_si128((__m128i *)(dst + j), v_l0); - _mm_storeu_si128((__m128i *)(dst + j + 16), v_l1); - _mm_storeu_si128((__m128i *)(dst + j + 32), v_u0); - _mm_storeu_si128((__m128i *)(dst + j + 48), v_u1); - _mm_storeu_si128((__m128i *)(dst + j + 64), v_v0); - _mm_storeu_si128((__m128i *)(dst + j + 80), v_v1); + process(buf + j + 32, + v_coeffs, v_res, dst + j + 32); } } #endif @@ -6048,7 +6026,7 @@ struct RGB2Luv_b float32x4_t v_scale, v_scale_inv, v_coeff1, v_coeff2, v_coeff3, v_coeff4; uint8x8_t v_alpha; #elif CV_SSE2 - __m128 v_scale, v_scale_inv, v_coeff1, v_coeff2, v_coeff3, v_coeff4; + __m128 v_scale_inv; __m128i v_zero; bool haveSIMD; #endif From 1f8aa4f7d3262c49ea4a9f3dbd1ad3bdbe0e5219 Mon Sep 17 00:00:00 2001 From: k-shinotsuka Date: Sun, 18 Sep 2016 14:48:40 +0900 Subject: [PATCH 163/178] improve Lab2RGB_b() --- modules/imgproc/src/color.cpp | 62 ++++++++++++++--------------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 746b303292..5ee0e3d9d8 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -5505,9 +5505,7 @@ struct Lab2RGB_b v_alpha = vdup_n_u8(ColorChannel::max()); v_128 = vdupq_n_f32(128.0f); #elif CV_SSE2 - v_scale_inv = _mm_set1_ps(100.f/255.f); v_scale = _mm_set1_ps(255.f); - v_128 = _mm_set1_ps(128.0f); v_zero = _mm_setzero_si128(); haveSIMD = checkHardwareSupport(CV_CPU_SSE2); #endif @@ -5516,6 +5514,7 @@ struct Lab2RGB_b #if CV_SSE2 // 16s x 8 void process(__m128i v_r, __m128i v_g, __m128i v_b, + __m128 v_coeffs, __m128 v_res, float * buf) const { __m128 v_r0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_r, v_zero)); @@ -5526,15 +5525,20 @@ struct Lab2RGB_b __m128 v_g1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_g, v_zero)); __m128 v_b1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_b, v_zero)); - v_r0 = _mm_mul_ps(v_r0, v_scale_inv); - v_r1 = _mm_mul_ps(v_r1, v_scale_inv); + v_r0 = _mm_sub_ps(_mm_mul_ps(v_r0, v_coeffs), v_res); + v_g1 = _mm_sub_ps(_mm_mul_ps(v_g1, v_coeffs), v_res); - v_g0 = _mm_sub_ps(v_g0, v_128); - v_g1 = _mm_sub_ps(v_g1, v_128); - v_b0 = _mm_sub_ps(v_b0, v_128); - v_b1 = _mm_sub_ps(v_b1, v_128); + v_coeffs = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_coeffs), 0x49)); + v_res = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_res), 0x49)); - _mm_interleave_ps(v_r0, v_r1, v_g0, v_g1, v_b0, v_b1); + v_r1 = _mm_sub_ps(_mm_mul_ps(v_r1, v_coeffs), v_res); + v_b0 = _mm_sub_ps(_mm_mul_ps(v_b0, v_coeffs), v_res); + + v_coeffs = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_coeffs), 0x49)); + v_res = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_res), 0x49)); + + v_g0 = _mm_sub_ps(_mm_mul_ps(v_g0, v_coeffs), v_res); + v_b1 = _mm_sub_ps(_mm_mul_ps(v_b1, v_coeffs), v_res); _mm_store_ps(buf, v_r0); _mm_store_ps(buf + 4, v_r1); @@ -5550,6 +5554,10 @@ struct Lab2RGB_b int i, j, dcn = dstcn; uchar alpha = ColorChannel::max(); float CV_DECL_ALIGNED(16) buf[3*BLOCK_SIZE]; + #if CV_SSE2 + __m128 v_coeffs = _mm_set_ps(100.f/255.f, 1.f, 1.f, 100.f/255.f); + __m128 v_res = _mm_set_ps(0.f, 128.f, 128.f, 0.f); + #endif for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 ) { @@ -5578,36 +5586,16 @@ struct Lab2RGB_b #elif CV_SSE2 if (haveSIMD) { - for ( ; j <= (dn - 32) * 3; j += 96) + for ( ; j <= (dn - 8) * 3; j += 24) { - __m128i v_r0 = _mm_loadu_si128((__m128i const *)(src + j)); - __m128i v_r1 = _mm_loadu_si128((__m128i const *)(src + j + 16)); - __m128i v_g0 = _mm_loadu_si128((__m128i const *)(src + j + 32)); - __m128i v_g1 = _mm_loadu_si128((__m128i const *)(src + j + 48)); - __m128i v_b0 = _mm_loadu_si128((__m128i const *)(src + j + 64)); - __m128i v_b1 = _mm_loadu_si128((__m128i const *)(src + j + 80)); + __m128i v_src0 = _mm_loadu_si128((__m128i const *)(src + j)); + __m128i v_src1 = _mm_loadl_epi64((__m128i const *)(src + j + 16)); - _mm_deinterleave_epi8(v_r0, v_r1, v_g0, v_g1, v_b0, v_b1); - - process(_mm_unpacklo_epi8(v_r0, v_zero), - _mm_unpacklo_epi8(v_g0, v_zero), - _mm_unpacklo_epi8(v_b0, v_zero), + process(_mm_unpacklo_epi8(v_src0, v_zero), + _mm_unpackhi_epi8(v_src0, v_zero), + _mm_unpacklo_epi8(v_src1, v_zero), + v_coeffs, v_res, buf + j); - - process(_mm_unpackhi_epi8(v_r0, v_zero), - _mm_unpackhi_epi8(v_g0, v_zero), - _mm_unpackhi_epi8(v_b0, v_zero), - buf + j + 24); - - process(_mm_unpacklo_epi8(v_r1, v_zero), - _mm_unpacklo_epi8(v_g1, v_zero), - _mm_unpacklo_epi8(v_b1, v_zero), - buf + j + 48); - - process(_mm_unpackhi_epi8(v_r1, v_zero), - _mm_unpackhi_epi8(v_g1, v_zero), - _mm_unpackhi_epi8(v_b1, v_zero), - buf + j + 72); } } #endif @@ -5692,7 +5680,7 @@ struct Lab2RGB_b float32x4_t v_scale, v_scale_inv, v_128; uint8x8_t v_alpha; #elif CV_SSE2 - __m128 v_scale, v_scale_inv, v_128; + __m128 v_scale; __m128i v_zero; bool haveSIMD; #endif From 0fc187d7a3a9dacf10c252b3fbc4e993c29d023c Mon Sep 17 00:00:00 2001 From: k-shinotsuka Date: Sun, 18 Sep 2016 15:46:00 +0900 Subject: [PATCH 164/178] improve HLS2RGB_b() --- modules/imgproc/src/color.cpp | 57 ++++++++++++++--------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 746b303292..06601ca96b 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -5004,7 +5004,6 @@ struct HLS2RGB_b v_scale = vdupq_n_f32(255.f); v_alpha = vdup_n_u8(ColorChannel::max()); #elif CV_SSE2 - v_scale_inv = _mm_set1_ps(1.f/255.f); v_scale = _mm_set1_ps(255.f); v_zero = _mm_setzero_si128(); haveSIMD = checkHardwareSupport(CV_CPU_SSE2); @@ -5012,8 +5011,8 @@ struct HLS2RGB_b } #if CV_SSE2 - // 16s x 8 void process(__m128i v_r, __m128i v_g, __m128i v_b, + __m128 v_coeffs, float * buf) const { __m128 v_r0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_r, v_zero)); @@ -5024,13 +5023,18 @@ struct HLS2RGB_b __m128 v_g1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_g, v_zero)); __m128 v_b1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_b, v_zero)); - v_g0 = _mm_mul_ps(v_g0, v_scale_inv); - v_b0 = _mm_mul_ps(v_b0, v_scale_inv); + v_r0 = _mm_mul_ps(v_r0, v_coeffs); + v_g1 = _mm_mul_ps(v_g1, v_coeffs); - v_g1 = _mm_mul_ps(v_g1, v_scale_inv); - v_b1 = _mm_mul_ps(v_b1, v_scale_inv); + v_coeffs = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_coeffs), 0x49)); - _mm_interleave_ps(v_r0, v_r1, v_g0, v_g1, v_b0, v_b1); + v_r1 = _mm_mul_ps(v_r1, v_coeffs); + v_b0 = _mm_mul_ps(v_b0, v_coeffs); + + v_coeffs = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_coeffs), 0x49)); + + v_g0 = _mm_mul_ps(v_g0, v_coeffs); + v_b1 = _mm_mul_ps(v_b1, v_coeffs); _mm_store_ps(buf, v_r0); _mm_store_ps(buf + 4, v_r1); @@ -5046,6 +5050,9 @@ struct HLS2RGB_b int i, j, dcn = dstcn; uchar alpha = ColorChannel::max(); float CV_DECL_ALIGNED(16) buf[3*BLOCK_SIZE]; + #if CV_SSE2 + __m128 v_coeffs = _mm_set_ps(1.f, 1.f/255.f, 1.f/255.f, 1.f); + #endif for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 ) { @@ -5074,36 +5081,16 @@ struct HLS2RGB_b #elif CV_SSE2 if (haveSIMD) { - for ( ; j <= (dn - 32) * 3; j += 96) + for ( ; j <= (dn - 8) * 3; j += 24) { - __m128i v_r0 = _mm_loadu_si128((__m128i const *)(src + j)); - __m128i v_r1 = _mm_loadu_si128((__m128i const *)(src + j + 16)); - __m128i v_g0 = _mm_loadu_si128((__m128i const *)(src + j + 32)); - __m128i v_g1 = _mm_loadu_si128((__m128i const *)(src + j + 48)); - __m128i v_b0 = _mm_loadu_si128((__m128i const *)(src + j + 64)); - __m128i v_b1 = _mm_loadu_si128((__m128i const *)(src + j + 80)); + __m128i v_src0 = _mm_loadu_si128((__m128i const *)(src + j)); + __m128i v_src1 = _mm_loadl_epi64((__m128i const *)(src + j + 16)); - _mm_deinterleave_epi8(v_r0, v_r1, v_g0, v_g1, v_b0, v_b1); - - process(_mm_unpacklo_epi8(v_r0, v_zero), - _mm_unpacklo_epi8(v_g0, v_zero), - _mm_unpacklo_epi8(v_b0, v_zero), + process(_mm_unpacklo_epi8(v_src0, v_zero), + _mm_unpackhi_epi8(v_src0, v_zero), + _mm_unpacklo_epi8(v_src1, v_zero), + v_coeffs, buf + j); - - process(_mm_unpackhi_epi8(v_r0, v_zero), - _mm_unpackhi_epi8(v_g0, v_zero), - _mm_unpackhi_epi8(v_b0, v_zero), - buf + j + 24); - - process(_mm_unpacklo_epi8(v_r1, v_zero), - _mm_unpacklo_epi8(v_g1, v_zero), - _mm_unpacklo_epi8(v_b1, v_zero), - buf + j + 48); - - process(_mm_unpackhi_epi8(v_r1, v_zero), - _mm_unpackhi_epi8(v_g1, v_zero), - _mm_unpackhi_epi8(v_b1, v_zero), - buf + j + 72); } } #endif @@ -5186,7 +5173,7 @@ struct HLS2RGB_b float32x4_t v_scale, v_scale_inv; uint8x8_t v_alpha; #elif CV_SSE2 - __m128 v_scale, v_scale_inv; + __m128 v_scale; __m128i v_zero; bool haveSIMD; #endif From 401537ebab1c40caa05758e0bfc57c9aa1115af2 Mon Sep 17 00:00:00 2001 From: Jeroen Kromwijk Date: Sun, 18 Sep 2016 12:02:33 +0200 Subject: [PATCH 165/178] Detect the correct Python major version --- cmake/OpenCVDetectPython.cmake | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/cmake/OpenCVDetectPython.cmake b/cmake/OpenCVDetectPython.cmake index f304a50a42..f6452eb1e5 100644 --- a/cmake/OpenCVDetectPython.cmake +++ b/cmake/OpenCVDetectPython.cmake @@ -47,19 +47,24 @@ if(NOT ${found}) endforeach() endif() + string(REGEX MATCH "^[0-9]+" _preferred_version_major ${preferred_version}) + find_host_package(PythonInterp "${preferred_version}") if(NOT PYTHONINTERP_FOUND) find_host_package(PythonInterp "${min_version}") endif() if(PYTHONINTERP_FOUND) - # Copy outputs - set(_found ${PYTHONINTERP_FOUND}) - set(_executable ${PYTHON_EXECUTABLE}) - set(_version_string ${PYTHON_VERSION_STRING}) - set(_version_major ${PYTHON_VERSION_MAJOR}) - set(_version_minor ${PYTHON_VERSION_MINOR}) - set(_version_patch ${PYTHON_VERSION_PATCH}) + # Check if python major version is correct + if(${_preferred_version_major} EQUAL ${PYTHON_VERSION_MAJOR}) + # Copy outputs + set(_found ${PYTHONINTERP_FOUND}) + set(_executable ${PYTHON_EXECUTABLE}) + set(_version_string ${PYTHON_VERSION_STRING}) + set(_version_major ${PYTHON_VERSION_MAJOR}) + set(_version_minor ${PYTHON_VERSION_MINOR}) + set(_version_patch ${PYTHON_VERSION_PATCH}) + endif() # Clear find_host_package side effects unset(PYTHONINTERP_FOUND) From 4f22f48e633a9fa24147a2cf63b08cff5250d6b9 Mon Sep 17 00:00:00 2001 From: k-shinotsuka Date: Sun, 18 Sep 2016 23:07:09 +0900 Subject: [PATCH 166/178] improve HSV2RGB_b() --- modules/imgproc/src/color.cpp | 57 ++++++++++++++--------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 746b303292..87d2a400d0 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -4494,7 +4494,6 @@ struct HSV2RGB_b v_scale = vdupq_n_f32(255.f); v_alpha = vdup_n_u8(ColorChannel::max()); #elif CV_SSE2 - v_scale_inv = _mm_set1_ps(1.f/255.f); v_scale = _mm_set1_ps(255.0f); v_zero = _mm_setzero_si128(); haveSIMD = checkHardwareSupport(CV_CPU_SSE2); @@ -4502,8 +4501,8 @@ struct HSV2RGB_b } #if CV_SSE2 - // 16s x 8 void process(__m128i v_r, __m128i v_g, __m128i v_b, + __m128 v_coeffs, float * buf) const { __m128 v_r0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_r, v_zero)); @@ -4514,13 +4513,18 @@ struct HSV2RGB_b __m128 v_g1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_g, v_zero)); __m128 v_b1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_b, v_zero)); - v_g0 = _mm_mul_ps(v_g0, v_scale_inv); - v_b0 = _mm_mul_ps(v_b0, v_scale_inv); + v_r0 = _mm_mul_ps(v_r0, v_coeffs); + v_g1 = _mm_mul_ps(v_g1, v_coeffs); - v_g1 = _mm_mul_ps(v_g1, v_scale_inv); - v_b1 = _mm_mul_ps(v_b1, v_scale_inv); + v_coeffs = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_coeffs), 0x49)); - _mm_interleave_ps(v_r0, v_r1, v_g0, v_g1, v_b0, v_b1); + v_r1 = _mm_mul_ps(v_r1, v_coeffs); + v_b0 = _mm_mul_ps(v_b0, v_coeffs); + + v_coeffs = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_coeffs), 0x49)); + + v_g0 = _mm_mul_ps(v_g0, v_coeffs); + v_b1 = _mm_mul_ps(v_b1, v_coeffs); _mm_store_ps(buf, v_r0); _mm_store_ps(buf + 4, v_r1); @@ -4536,6 +4540,9 @@ struct HSV2RGB_b int i, j, dcn = dstcn; uchar alpha = ColorChannel::max(); float CV_DECL_ALIGNED(16) buf[3*BLOCK_SIZE]; + #if CV_SSE2 + __m128 v_coeffs = _mm_set_ps(1.f, 1.f/255.f, 1.f/255.f, 1.f); + #endif for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 ) { @@ -4564,36 +4571,16 @@ struct HSV2RGB_b #elif CV_SSE2 if (haveSIMD) { - for ( ; j <= (dn - 32) * 3; j += 96) + for ( ; j <= (dn - 8) * 3; j += 24) { - __m128i v_r0 = _mm_loadu_si128((__m128i const *)(src + j)); - __m128i v_r1 = _mm_loadu_si128((__m128i const *)(src + j + 16)); - __m128i v_g0 = _mm_loadu_si128((__m128i const *)(src + j + 32)); - __m128i v_g1 = _mm_loadu_si128((__m128i const *)(src + j + 48)); - __m128i v_b0 = _mm_loadu_si128((__m128i const *)(src + j + 64)); - __m128i v_b1 = _mm_loadu_si128((__m128i const *)(src + j + 80)); + __m128i v_src0 = _mm_loadu_si128((__m128i const *)(src + j)); + __m128i v_src1 = _mm_loadl_epi64((__m128i const *)(src + j + 16)); - _mm_deinterleave_epi8(v_r0, v_r1, v_g0, v_g1, v_b0, v_b1); - - process(_mm_unpacklo_epi8(v_r0, v_zero), - _mm_unpacklo_epi8(v_g0, v_zero), - _mm_unpacklo_epi8(v_b0, v_zero), + process(_mm_unpacklo_epi8(v_src0, v_zero), + _mm_unpackhi_epi8(v_src0, v_zero), + _mm_unpacklo_epi8(v_src1, v_zero), + v_coeffs, buf + j); - - process(_mm_unpackhi_epi8(v_r0, v_zero), - _mm_unpackhi_epi8(v_g0, v_zero), - _mm_unpackhi_epi8(v_b0, v_zero), - buf + j + 24); - - process(_mm_unpacklo_epi8(v_r1, v_zero), - _mm_unpacklo_epi8(v_g1, v_zero), - _mm_unpacklo_epi8(v_b1, v_zero), - buf + j + 48); - - process(_mm_unpackhi_epi8(v_r1, v_zero), - _mm_unpackhi_epi8(v_g1, v_zero), - _mm_unpackhi_epi8(v_b1, v_zero), - buf + j + 72); } } #endif @@ -4677,7 +4664,7 @@ struct HSV2RGB_b float32x4_t v_scale, v_scale_inv; uint8x8_t v_alpha; #elif CV_SSE2 - __m128 v_scale_inv, v_scale; + __m128 v_scale; __m128i v_zero; bool haveSIMD; #endif From 0d85d2cc0ab3bd88d6e43e5f5fdbd7bd6ad35a60 Mon Sep 17 00:00:00 2001 From: k-shinotsuka Date: Sun, 18 Sep 2016 16:45:31 +0900 Subject: [PATCH 167/178] improve RGB2HLS_b() --- modules/imgproc/src/color.cpp | 70 +++++++++++++---------------------- 1 file changed, 25 insertions(+), 45 deletions(-) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 746b303292..e7ca441a51 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -4753,7 +4753,6 @@ struct RGB2HLS_b v_alpha = vdup_n_u8(ColorChannel::max()); #elif CV_SSE2 v_scale_inv = _mm_set1_ps(1.f/255.f); - v_scale = _mm_set1_ps(255.f); v_zero = _mm_setzero_si128(); haveSIMD = checkHardwareSupport(CV_CPU_SSE2); #endif @@ -4761,25 +4760,25 @@ struct RGB2HLS_b #if CV_SSE2 void process(const float * buf, - __m128i & v_h, __m128i & v_l, __m128i & v_s) const + __m128 & v_coeffs, uchar * dst) const { - __m128 v_h0f = _mm_load_ps(buf); - __m128 v_h1f = _mm_load_ps(buf + 4); - __m128 v_l0f = _mm_load_ps(buf + 8); - __m128 v_l1f = _mm_load_ps(buf + 12); - __m128 v_s0f = _mm_load_ps(buf + 16); - __m128 v_s1f = _mm_load_ps(buf + 20); + __m128 v_l0f = _mm_load_ps(buf); + __m128 v_l1f = _mm_load_ps(buf + 4); + __m128 v_u0f = _mm_load_ps(buf + 8); + __m128 v_u1f = _mm_load_ps(buf + 12); - _mm_deinterleave_ps(v_h0f, v_h1f, v_l0f, v_l1f, v_s0f, v_s1f); + v_l0f = _mm_mul_ps(v_l0f, v_coeffs); + v_u1f = _mm_mul_ps(v_u1f, v_coeffs); + v_coeffs = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_coeffs), 0x92)); + v_u0f = _mm_mul_ps(v_u0f, v_coeffs); + v_coeffs = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v_coeffs), 0x92)); + v_l1f = _mm_mul_ps(v_l1f, v_coeffs); - v_l0f = _mm_mul_ps(v_l0f, v_scale); - v_l1f = _mm_mul_ps(v_l1f, v_scale); - v_s0f = _mm_mul_ps(v_s0f, v_scale); - v_s1f = _mm_mul_ps(v_s1f, v_scale); + __m128i v_l = _mm_packs_epi32(_mm_cvtps_epi32(v_l0f), _mm_cvtps_epi32(v_l1f)); + __m128i v_u = _mm_packs_epi32(_mm_cvtps_epi32(v_u0f), _mm_cvtps_epi32(v_u1f)); + __m128i v_l0 = _mm_packus_epi16(v_l, v_u); - v_h = _mm_packs_epi32(_mm_cvtps_epi32(v_h0f), _mm_cvtps_epi32(v_h1f)); - v_l = _mm_packs_epi32(_mm_cvtps_epi32(v_l0f), _mm_cvtps_epi32(v_l1f)); - v_s = _mm_packs_epi32(_mm_cvtps_epi32(v_s0f), _mm_cvtps_epi32(v_s1f)); + _mm_storeu_si128((__m128i *)(dst), v_l0); } #endif @@ -4787,6 +4786,9 @@ struct RGB2HLS_b { int i, j, scn = srccn; float CV_DECL_ALIGNED(16) buf[3*BLOCK_SIZE]; + #if CV_SSE2 + __m128 v_coeffs = _mm_set_ps(1.f, 255.f, 255.f, 1.f); + #endif for( i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE*3 ) { @@ -4871,38 +4873,16 @@ struct RGB2HLS_b #elif CV_SSE2 if (haveSIMD) { - for ( ; j <= (dn - 32) * 3; j += 96) + for ( ; j <= (dn - 16) * 3; j += 48) { - __m128i v_h_0, v_l_0, v_s_0; process(buf + j, - v_h_0, v_l_0, v_s_0); + v_coeffs, dst + j); - __m128i v_h_1, v_l_1, v_s_1; - process(buf + j + 24, - v_h_1, v_l_1, v_s_1); + process(buf + j + 16, + v_coeffs, dst + j + 16); - __m128i v_h0 = _mm_packus_epi16(v_h_0, v_h_1); - __m128i v_l0 = _mm_packus_epi16(v_l_0, v_l_1); - __m128i v_s0 = _mm_packus_epi16(v_s_0, v_s_1); - - process(buf + j + 48, - v_h_0, v_l_0, v_s_0); - - process(buf + j + 72, - v_h_1, v_l_1, v_s_1); - - __m128i v_h1 = _mm_packus_epi16(v_h_0, v_h_1); - __m128i v_l1 = _mm_packus_epi16(v_l_0, v_l_1); - __m128i v_s1 = _mm_packus_epi16(v_s_0, v_s_1); - - _mm_interleave_epi8(v_h0, v_h1, v_l0, v_l1, v_s0, v_s1); - - _mm_storeu_si128((__m128i *)(dst + j), v_h0); - _mm_storeu_si128((__m128i *)(dst + j + 16), v_h1); - _mm_storeu_si128((__m128i *)(dst + j + 32), v_l0); - _mm_storeu_si128((__m128i *)(dst + j + 48), v_l1); - _mm_storeu_si128((__m128i *)(dst + j + 64), v_s0); - _mm_storeu_si128((__m128i *)(dst + j + 80), v_s1); + process(buf + j + 32, + v_coeffs, dst + j + 32); } } #endif @@ -4921,7 +4901,7 @@ struct RGB2HLS_b float32x4_t v_scale, v_scale_inv; uint8x8_t v_alpha; #elif CV_SSE2 - __m128 v_scale, v_scale_inv; + __m128 v_scale_inv; __m128i v_zero; bool haveSIMD; #endif From 5728795cf7501e90964ec2502945aa133d36b25b Mon Sep 17 00:00:00 2001 From: daB0bby Date: Wed, 21 Sep 2016 13:22:58 +0200 Subject: [PATCH 168/178] Merge pull request #7320 from daB0bby:patch-1 * bypass makro * syntax --- modules/objdetect/include/opencv2/objdetect.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/objdetect/include/opencv2/objdetect.hpp b/modules/objdetect/include/opencv2/objdetect.hpp index 87d7ec3ac5..b92467db2c 100644 --- a/modules/objdetect/include/opencv2/objdetect.hpp +++ b/modules/objdetect/include/opencv2/objdetect.hpp @@ -124,7 +124,7 @@ public: SimilarRects(double _eps) : eps(_eps) {} inline bool operator()(const Rect& r1, const Rect& r2) const { - double delta = eps*(std::min(r1.width, r2.width) + std::min(r1.height, r2.height))*0.5; + double delta = eps * ((std::min)(r1.width, r2.width) + (std::min)(r1.height, r2.height)) * 0.5; return std::abs(r1.x - r2.x) <= delta && std::abs(r1.y - r2.y) <= delta && std::abs(r1.x + r1.width - r2.x - r2.width) <= delta && From ae28345ca58ae03f3168ac2ee3df6ba1432332fb Mon Sep 17 00:00:00 2001 From: Vladislav Sovrasov Date: Wed, 21 Sep 2016 17:11:00 +0300 Subject: [PATCH 169/178] Make test_texture_flow.py more robust --- modules/python/test/test_texture_flow.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/modules/python/test/test_texture_flow.py b/modules/python/test/test_texture_flow.py index 7dc3b07040..b0f55207c5 100644 --- a/modules/python/test/test_texture_flow.py +++ b/modules/python/test/test_texture_flow.py @@ -21,31 +21,24 @@ class texture_flow_test(NewOpenCVTests): def test_texture_flow(self): - img = self.get_sample('samples/data/pic6.png') + img = self.get_sample('samples/data/chessboard.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) h, w = img.shape[:2] - eigen = cv2.cornerEigenValsAndVecs(gray, 15, 3) + eigen = cv2.cornerEigenValsAndVecs(gray, 5, 3) eigen = eigen.reshape(h, w, 3, 2) # [[e1, e2], v1, v2] flow = eigen[:,:,2] - vis = img.copy() - vis[:] = (192 + np.uint32(vis)) / 2 - d = 80 + d = 300 + eps = d / 30 + points = np.dstack( np.mgrid[d/2:w:d, d/2:h:d] ).reshape(-1, 2) textureVectors = [] - for x, y in np.int32(points): textureVectors.append(np.int32(flow[y, x]*d)) - eps = 0.05 - - testTextureVectors = [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], - [-38, 70], [-79, 3], [0, 0], [0, 0], [-39, 69], [-79, -1], - [0, 0], [0, 0], [0, -79], [17, -78], [-48, -63], [65, -46], - [-69, -39], [-48, -63], [-45, 66]] - for i in range(len(textureVectors)): - self.assertLessEqual(cv2.norm(textureVectors[i] - testTextureVectors[i], cv2.NORM_L2), eps) \ No newline at end of file + self.assertTrue(cv2.norm(textureVectors[i], cv2.NORM_L2) < eps + or abs(cv2.norm(textureVectors[i], cv2.NORM_L2) - d) < eps) From 2073af2f05421c4d96d1700fda48308ebc2663a8 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Wed, 21 Sep 2016 17:46:51 +0300 Subject: [PATCH 170/178] RGB2Gray array size fix; --- modules/imgproc/src/color.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 25878aca63..04d15f3b3f 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -1549,7 +1549,7 @@ struct RGB2Gray for ( ; i <= n - 8; i += 8, src += scn * 8) { - __m128i v_src[2]; + __m128i v_src[3]; v_src[0] = _mm_loadu_si128((__m128i const *)(src)); v_src[1] = _mm_loadu_si128((__m128i const *)(src + 8)); v_src[2] = _mm_loadu_si128((__m128i const *)(src + 16)); From 7366be696a6ea6b3f950a9464810d9b9300ee138 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 22 Sep 2016 14:51:53 +0300 Subject: [PATCH 171/178] imgproc: fix win32 build --- modules/imgproc/src/color.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 997955b8da..6d0d0f8fad 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -4502,7 +4502,7 @@ struct HSV2RGB_b #if CV_SSE2 void process(__m128i v_r, __m128i v_g, __m128i v_b, - __m128 v_coeffs, + const __m128& v_coeffs_, float * buf) const { __m128 v_r0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_r, v_zero)); @@ -4513,6 +4513,8 @@ struct HSV2RGB_b __m128 v_g1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_g, v_zero)); __m128 v_b1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_b, v_zero)); + __m128 v_coeffs = v_coeffs_; + v_r0 = _mm_mul_ps(v_r0, v_coeffs); v_g1 = _mm_mul_ps(v_g1, v_coeffs); @@ -4979,7 +4981,7 @@ struct HLS2RGB_b #if CV_SSE2 void process(__m128i v_r, __m128i v_g, __m128i v_b, - __m128 v_coeffs, + const __m128& v_coeffs_, float * buf) const { __m128 v_r0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_r, v_zero)); @@ -4990,6 +4992,8 @@ struct HLS2RGB_b __m128 v_g1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_g, v_zero)); __m128 v_b1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_b, v_zero)); + __m128 v_coeffs = v_coeffs_; + v_r0 = _mm_mul_ps(v_r0, v_coeffs); v_g1 = _mm_mul_ps(v_g1, v_coeffs); @@ -5468,7 +5472,7 @@ struct Lab2RGB_b #if CV_SSE2 // 16s x 8 void process(__m128i v_r, __m128i v_g, __m128i v_b, - __m128 v_coeffs, __m128 v_res, + const __m128& v_coeffs_, const __m128& v_res_, float * buf) const { __m128 v_r0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_r, v_zero)); @@ -5479,6 +5483,9 @@ struct Lab2RGB_b __m128 v_g1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_g, v_zero)); __m128 v_b1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_b, v_zero)); + __m128 v_coeffs = v_coeffs_; + __m128 v_res = v_res_; + v_r0 = _mm_sub_ps(_mm_mul_ps(v_r0, v_coeffs), v_res); v_g1 = _mm_sub_ps(_mm_mul_ps(v_g1, v_coeffs), v_res); @@ -6001,7 +6008,7 @@ struct Luv2RGB_b #if CV_SSE2 // 16s x 8 void process(__m128i v_l, __m128i v_u, __m128i v_v, - __m128 v_coeffs, __m128 v_res, + const __m128& v_coeffs_, const __m128& v_res_, float * buf) const { __m128 v_l0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_l, v_zero)); @@ -6012,6 +6019,9 @@ struct Luv2RGB_b __m128 v_u1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_u, v_zero)); __m128 v_v1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_v, v_zero)); + __m128 v_coeffs = v_coeffs_; + __m128 v_res = v_res_; + v_l0 = _mm_mul_ps(v_l0, v_coeffs); v_u1 = _mm_mul_ps(v_u1, v_coeffs); v_l0 = _mm_sub_ps(v_l0, v_res); From f50f34016e5953ec5ce4e69547a5881e9e7024e9 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 21 Sep 2016 17:50:42 +0300 Subject: [PATCH 172/178] test: fix test crash (exception in destructor) --- modules/core/test/test_umat.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/modules/core/test/test_umat.cpp b/modules/core/test/test_umat.cpp index 26b1bbd2b8..9e9835f350 100644 --- a/modules/core/test/test_umat.cpp +++ b/modules/core/test/test_umat.cpp @@ -1304,20 +1304,18 @@ TEST(UMat, testTempObjects_UMat) ASSERT_EQ(0, countNonZero(uDiff)); } -// Disabled due to failure in VS 2015: -// C++11 is enabled by default ==> -// destructors have implicit 'noexcept(true)' specifier ==> -// throwing exception from destructor is not handled correctly -#if defined(_MSC_VER) && _MSC_VER >= 1900 /* MSVC 14 */ -TEST(UMat, DISABLED_testTempObjects_Mat) -#else TEST(UMat, testTempObjects_Mat) -#endif { Mat m(10, 10, CV_8UC1, Scalar(1)); { Mat m2; - ASSERT_ANY_THROW(m2 = m.getUMat(ACCESS_RW).getMat(ACCESS_RW)); + ASSERT_ANY_THROW({ + // Below is unwrapped version of this invalid expression: + // m2 = m.getUMat(ACCESS_RW).getMat(ACCESS_RW) + UMat u = m.getUMat(ACCESS_RW); + m2 = u.getMat(ACCESS_RW); + u.release(); + }); } } From b8bce55270199252245b26bc4ca76a70f917e441 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Tue, 19 Jul 2016 17:24:55 +0300 Subject: [PATCH 173/178] Several chessboard detector improvements: - fixed uninitialized memory access and memory leaks - extracted several code blocks to separate functions - updated part of algorithm to use cv::Mat instead of CvMat and IplImage --- modules/calib3d/src/calibinit.cpp | 887 ++++++++++----------- modules/calib3d/src/checkchessboard.cpp | 280 +++---- modules/calib3d/src/precomp.hpp | 3 + modules/calib3d/test/test_chesscorners.cpp | 37 +- modules/python/test/test_calibration.py | 4 +- 5 files changed, 535 insertions(+), 676 deletions(-) diff --git a/modules/calib3d/src/calibinit.cpp b/modules/calib3d/src/calibinit.cpp index d6f5995587..1bd896463c 100644 --- a/modules/calib3d/src/calibinit.cpp +++ b/modules/calib3d/src/calibinit.cpp @@ -76,6 +76,9 @@ #include #include +using namespace cv; +using namespace std; + //#define ENABLE_TRIM_COL_ROW //#define DEBUG_CHESSBOARD @@ -88,13 +91,9 @@ static int PRINTF( const char* fmt, ... ) return vprintf(fmt, args); } #else -static int PRINTF( const char*, ... ) -{ - return 0; -} +#define PRINTF(...) #endif - //===================================================================================== // Implementation for the enhanced calibration object detection //===================================================================================== @@ -155,10 +154,42 @@ struct CvCBQuad //===================================================================================== -//static CvMat* debug_img = 0; +#ifdef DEBUG_CHESSBOARD +#include "opencv2/highgui.hpp" +#include "opencv2/imgproc.hpp" +static void SHOW(const std::string & name, Mat & img) +{ + imshow(name, img); + while ((uchar)waitKey(0) != 'q') {} +} +static void SHOW_QUADS(const std::string & name, const Mat & img_, CvCBQuad * quads, int quads_count) +{ + Mat img = img_.clone(); + if (img.channels() == 1) + cvtColor(img, img, COLOR_GRAY2BGR); + for (int i = 0; i < quads_count; ++i) + { + CvCBQuad & quad = quads[i]; + for (int j = 0; j < 4; ++j) + { + line(img, quad.corners[j]->pt, quad.corners[(j + 1) % 4]->pt, Scalar(0, 240, 0), 1, LINE_AA); + } + } + imshow(name, img); + while ((uchar)waitKey(0) != 'q') {} +} +#else +#define SHOW(...) +#define SHOW_QUADS(...) +#endif + +//===================================================================================== static int icvGenerateQuads( CvCBQuad **quads, CvCBCorner **corners, - CvMemStorage *storage, CvMat *image, int flags, int *max_quad_buf_size); + CvMemStorage *storage, const Mat &image_, int flags, int *max_quad_buf_size); + +static bool processQuads(CvCBQuad *quads, int quad_count, CvSize pattern_size, int max_quad_buf_size, + CvMemStorage * storage, CvCBCorner *corners, CvPoint2D32f *out_corners, int *out_corner_count, int & prev_sqr_size); /*static int icvGenerateQuadsEx( CvCBQuad **out_quads, CvCBCorner **out_corners, @@ -195,203 +226,198 @@ static void icvRemoveQuadFromGroup(CvCBQuad **quads, int count, CvCBQuad *q0); static int icvCheckBoardMonotony( CvPoint2D32f* corners, CvSize pattern_size ); -int cvCheckChessboardBinary(IplImage* src, CvSize size); - /***************************************************************************************************/ //COMPUTE INTENSITY HISTOGRAM OF INPUT IMAGE -static int icvGetIntensityHistogram( unsigned char* pucImage, int iSizeCols, int iSizeRows, std::vector& piHist ); +static int icvGetIntensityHistogram( const Mat & img, std::vector& piHist ) +{ + // sum up all pixel in row direction and divide by number of columns + for ( int j=0; j& piHist, std::vector& piHistSmooth, int iWidth ); +static int icvSmoothHistogram( const std::vector& piHist, std::vector& piHistSmooth, int iWidth ) +{ + int iIdx; + for ( int i=0; i<256; i++) + { + int iSmooth = 0; + for ( int ii=-iWidth; ii<=iWidth; ii++) + { + iIdx = i+ii; + if (iIdx > 0 && iIdx < 256) + { + iSmooth += piHist[iIdx]; + } + } + piHistSmooth[i] = iSmooth/(2*iWidth+1); + } + return 0; +} +/***************************************************************************************************/ //COMPUTE FAST HISTOGRAM GRADIENT -static int icvGradientOfHistogram( const std::vector& piHist, std::vector& piHistGrad ); +static int icvGradientOfHistogram( const std::vector& piHist, std::vector& piHistGrad ) +{ + piHistGrad[0] = 0; + for ( int i=1; i<255; i++) + { + piHistGrad[i] = piHist[i-1] - piHist[i+1]; + if ( abs(piHistGrad[i]) < 100 ) + { + if ( piHistGrad[i-1] == 0) + piHistGrad[i] = -100; + else + piHistGrad[i] = piHistGrad[i-1]; + } + } + return 0; +} +/***************************************************************************************************/ //PERFORM SMART IMAGE THRESHOLDING BASED ON ANALYSIS OF INTENSTY HISTOGRAM -static bool icvBinarizationHistogramBased( unsigned char* pucImg, int iCols, int iRows ); -/***************************************************************************************************/ -int icvGetIntensityHistogram( unsigned char* pucImage, int iSizeCols, int iSizeRows, std::vector& piHist ) +static bool icvBinarizationHistogramBased( Mat & img ) { - int iVal; + CV_Assert(img.channels() == 1 && img.depth() == CV_8U); + int iCols = img.cols; + int iRows = img.rows; + int iMaxPix = iCols*iRows; + int iMaxPix1 = iMaxPix/100; + const int iNumBins = 256; + std::vector piHistIntensity(iNumBins, 0); + std::vector piHistSmooth(iNumBins, 0); + std::vector piHistGrad(iNumBins, 0); + std::vector piAccumSum(iNumBins, 0); + std::vector piMaxPos(20, 0); + int iThresh = 0; + int iIdx; + int iWidth = 1; - // sum up all pixel in row direction and divide by number of columns - for ( int j=0; j=0; i-- ) { - iVal = (int)pucImage[j*iSizeCols+i]; - piHist[iVal]++; - } - } - return 0; -} -/***************************************************************************************************/ -int icvSmoothHistogram( const std::vector& piHist, std::vector& piHistSmooth, int iWidth ) -{ - int iIdx; - for ( int i=0; i<256; i++) - { - int iSmooth = 0; - for ( int ii=-iWidth; ii<=iWidth; ii++) - { - iIdx = i+ii; - if (iIdx > 0 && iIdx < 256) - { - iSmooth += piHist[iIdx]; - } - } - piHistSmooth[i] = iSmooth/(2*iWidth+1); - } - return 0; -} -/***************************************************************************************************/ -int icvGradientOfHistogram( const std::vector& piHist, std::vector& piHistGrad ) -{ - piHistGrad[0] = 0; - for ( int i=1; i<255; i++) - { - piHistGrad[i] = piHist[i-1] - piHist[i+1]; - if ( abs(piHistGrad[i]) < 100 ) - { - if ( piHistGrad[i-1] == 0) - piHistGrad[i] = -100; - else - piHistGrad[i] = piHistGrad[i-1]; - } - } - return 0; -} -/***************************************************************************************************/ -bool icvBinarizationHistogramBased( unsigned char* pucImg, int iCols, int iRows ) -{ - int iMaxPix = iCols*iRows; - int iMaxPix1 = iMaxPix/100; - const int iNumBins = 256; - std::vector piHistIntensity(iNumBins, 0); - std::vector piHistSmooth(iNumBins, 0); - std::vector piHistGrad(iNumBins, 0); - std::vector piAccumSum(iNumBins, 0); - std::vector piMaxPos(20, 0); - int iThresh = 0; - int iIdx; - int iWidth = 1; - - icvGetIntensityHistogram( pucImg, iCols, iRows, piHistIntensity ); - - // get accumulated sum starting from bright - piAccumSum[iNumBins-1] = piHistIntensity[iNumBins-1]; - for ( int i=iNumBins-2; i>=0; i-- ) - { - piAccumSum[i] = piHistIntensity[i] + piAccumSum[i+1]; - } - - // first smooth the distribution - icvSmoothHistogram( piHistIntensity, piHistSmooth, iWidth ); - - // compute gradient - icvGradientOfHistogram( piHistSmooth, piHistGrad ); - - // check for zeros - int iCntMaxima = 0; - for ( int i=iNumBins-2; (i>2) && (iCntMaxima<20); i--) - { - if ( (piHistGrad[i-1] < 0) && (piHistGrad[i] > 0) ) - { - piMaxPos[iCntMaxima] = i; - iCntMaxima++; - } - } - - iIdx = 0; - int iSumAroundMax = 0; - for ( int i=0; i= 3 - { - // CHECKING THRESHOLD FOR WHITE - int iIdxAccSum = 0, iAccum = 0; - for (int i=iNumBins-1; i>0; i--) - { - iAccum += piHistIntensity[i]; - // iMaxPix/18 is about 5,5%, minimum required number of pixels required for white part of chessboard - if ( iAccum > (iMaxPix/18) ) - { - iIdxAccSum = i; - break; - } + piAccumSum[i] = piHistIntensity[i] + piAccumSum[i+1]; } - int iIdxBGMax = 0; - int iBrightMax = piMaxPos[0]; - // printf("iBrightMax = %d\n", iBrightMax); - for ( int n=0; n2) && (iCntMaxima<20); i--) { - iIdxBGMax = n+1; - if ( piMaxPos[n] < iIdxAccSum ) - { - break; - } - iBrightMax = piMaxPos[n]; + if ( (piHistGrad[i-1] < 0) && (piHistGrad[i] > 0) ) + { + piMaxPos[iCntMaxima] = i; + iCntMaxima++; + } } - // CHECKING THRESHOLD FOR BLACK - int iMaxVal = piHistIntensity[piMaxPos[iIdxBGMax]]; - - //IF TOO CLOSE TO 255, jump to next maximum - if ( piMaxPos[iIdxBGMax] >= 250 && iIdxBGMax < iCntMaxima ) + iIdx = 0; + int iSumAroundMax = 0; + for ( int i=0; i= 3 + { + // CHECKING THRESHOLD FOR WHITE + int iIdxAccSum = 0, iAccum = 0; + for (int i=iNumBins-1; i>0; i--) + { + iAccum += piHistIntensity[i]; + // iMaxPix/18 is about 5,5%, minimum required number of pixels required for white part of chessboard + if ( iAccum > (iMaxPix/18) ) + { + iIdxAccSum = i; + break; + } + } + + int iIdxBGMax = 0; + int iBrightMax = piMaxPos[0]; + // printf("iBrightMax = %d\n", iBrightMax); + for ( int n=0; n= 250 && iIdxBGMax < iCntMaxima ) + { + iIdxBGMax++; + iMaxVal = piHistIntensity[piMaxPos[iIdxBGMax]]; + } + + for ( int n=iIdxBGMax + 1; n= iMaxVal ) + { + iMaxVal = piHistIntensity[piMaxPos[n]]; + iIdxBGMax = n; + } + } + + //SETTING THRESHOLD FOR BINARIZATION + int iDist2 = (iBrightMax - piMaxPos[iIdxBGMax])/2; + iThresh = iBrightMax - iDist2; + PRINTF("THRESHOLD SELECTED = %d, BRIGHTMAX = %d, DARKMAX = %d\n", iThresh, iBrightMax, piMaxPos[iIdxBGMax]); } - for ( int n=iIdxBGMax + 1; n 0 ) { - if ( piHistIntensity[piMaxPos[n]] >= iMaxVal ) - { - iMaxVal = piHistIntensity[piMaxPos[n]]; - iIdxBGMax = n; - } + for ( int jj=0; jj 0 ) - { - for ( int jj=0; jj storage; try { int k = 0; const int min_dilations = 0; const int max_dilations = 7; - cv::Ptr norm_img, thresh_img; - cv::Ptr storage; - - CvMat stub, *img = (CvMat*)arr; - cImgSeg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1 ); - memcpy( cImgSeg->imageData, cvPtr1D( img, 0), img->rows*img->cols ); - - CvMat stub2, *thresh_img_new; - thresh_img_new = cvGetMat( cImgSeg, &stub2, 0, 0 ); - - int expected_corners_num = (pattern_size.width/2+1)*(pattern_size.height/2+1); - - int prev_sqr_size = 0; if( out_corner_count ) *out_corner_count = 0; - int quad_count = 0, group_idx = 0, dilations = 0; + Mat img = cvarrToMat((CvMat*)arr).clone(); - img = cvGetMat( img, &stub ); - //debug_img = img; - - if( CV_MAT_DEPTH( img->type ) != CV_8U || CV_MAT_CN( img->type ) == 2 ) - CV_Error( CV_StsUnsupportedFormat, "Only 8-bit grayscale or color images are supported" ); + if( img.depth() != CV_8U || (img.channels() != 1 && img.channels() != 3) ) + CV_Error( CV_StsUnsupportedFormat, "Only 8-bit grayscale or color images are supported" ); if( pattern_size.width <= 2 || pattern_size.height <= 2 ) CV_Error( CV_StsOutOfRange, "Both width and height of the pattern should have bigger than 2" ); @@ -440,273 +451,124 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, if( !out_corners ) CV_Error( CV_StsNullPtr, "Null pointer to corners" ); - storage.reset(cvCreateMemStorage(0)); - thresh_img.reset(cvCreateMat( img->rows, img->cols, CV_8UC1 )); - - if( CV_MAT_CN(img->type) != 1 || (flags & CV_CALIB_CB_NORMALIZE_IMAGE) ) + if (img.channels() != 1) { - // equalize the input image histogram - - // that should make the contrast between "black" and "white" areas big enough - norm_img.reset(cvCreateMat( img->rows, img->cols, CV_8UC1 )); - - if( CV_MAT_CN(img->type) != 1 ) - { - cvCvtColor( img, norm_img, CV_BGR2GRAY ); - img = norm_img; - } - - if( flags & CV_CALIB_CB_NORMALIZE_IMAGE ) - { - cvEqualizeHist( img, norm_img ); - img = norm_img; - } + cvtColor(img, img, COLOR_BGR2GRAY); } + + Mat thresh_img_new = img.clone(); + icvBinarizationHistogramBased( thresh_img_new ); // process image in-place + SHOW("New binarization", thresh_img_new); + if( flags & CV_CALIB_CB_FAST_CHECK) { //perform new method for checking chessboard using a binary image. //image is binarised using a threshold dependent on the image histogram - icvBinarizationHistogramBased( (unsigned char*) cImgSeg->imageData, cImgSeg->width, cImgSeg->height ); - int check_chessboard_result = cvCheckChessboardBinary(cImgSeg, pattern_size); - if(check_chessboard_result <= 0) //fall back to the old method + if (checkChessboardBinary(thresh_img_new, pattern_size) <= 0) //fall back to the old method { - IplImage _img; - cvGetImage(img, &_img); - check_chessboard_result = cvCheckChessboard(&_img, pattern_size); - if(check_chessboard_result <= 0) + if (checkChessboard(img, pattern_size) <= 0) { - return 0; + return found; } } } + storage.reset(cvCreateMemStorage(0)); + + int prev_sqr_size = 0; + // Try our standard "1" dilation, but if the pattern is not found, iterate the whole procedure with higher dilations. // This is necessary because some squares simply do not separate properly with a single dilation. However, // we want to use the minimum number of dilations possible since dilations cause the squares to become smaller, // making it difficult to detect smaller squares. - for( dilations = min_dilations; dilations <= max_dilations; dilations++ ) + for( int dilations = min_dilations; dilations <= max_dilations; dilations++ ) { - if (found) - break; // already found it + if (found) + break; // already found it - cvFree(&quads); - cvFree(&corners); + //USE BINARY IMAGE COMPUTED USING icvBinarizationHistogramBased METHOD + dilate( thresh_img_new, thresh_img_new, Mat(), Point(-1, -1), 1 ); - int max_quad_buf_size = 0; - - //USE BINARY IMAGE COMPUTED USING icvBinarizationHistogramBased METHOD - cvDilate( thresh_img_new, thresh_img_new, 0, 1 ); - - // So we can find rectangles that go to the edge, we draw a white line around the image edge. - // Otherwise FindContours will miss those clipped rectangle contours. - // The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()... - cvRectangle( thresh_img_new, cvPoint(0,0), cvPoint(thresh_img_new->cols-1, thresh_img_new->rows-1), CV_RGB(255,255,255), 3, 8); - quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img_new, flags, &max_quad_buf_size ); - PRINTF("Quad count: %d/%d\n", quad_count, expected_corners_num); - - if( quad_count <= 0 ) - { - continue; - } - - // Find quad's neighbors - icvFindQuadNeighbors( quads, quad_count ); - - // allocate extra for adding in icvOrderFoundQuads - cvFree(&quad_group); - cvFree(&corner_group); - quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * max_quad_buf_size); - corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * max_quad_buf_size * 4 ); - - for( group_idx = 0; ; group_idx++ ) - { - int count = 0; - count = icvFindConnectedQuads( quads, quad_count, quad_group, group_idx, storage ); - - int icount = count; - if( count == 0 ) - break; - - // order the quad corners globally - // maybe delete or add some - PRINTF("Starting ordering of inner quads\n"); - count = icvOrderFoundConnectedQuads(count, quad_group, &quad_count, &quads, &corners, pattern_size, max_quad_buf_size, storage ); - PRINTF("Orig count: %d After ordering: %d\n", icount, count); - - if (count == 0) - continue; // haven't found inner quads - - // If count is more than it should be, this will remove those quads - // which cause maximum deviation from a nice square pattern. - count = icvCleanFoundConnectedQuads( count, quad_group, pattern_size ); - PRINTF("Connected group: %d orig count: %d cleaned: %d\n", group_idx, icount, count); - - count = icvCheckQuadGroup( quad_group, count, corner_group, pattern_size ); - PRINTF("Connected group: %d count: %d cleaned: %d\n", group_idx, icount, count); - - int n = count > 0 ? pattern_size.width * pattern_size.height : -count; - n = MIN( n, pattern_size.width * pattern_size.height ); - float sum_dist = 0; - int total = 0; - - for(int i = 0; i < n; i++ ) - { - int ni = 0; - float avgi = corner_group[i]->meanDist(&ni); - sum_dist += avgi*ni; - total += ni; - } - prev_sqr_size = cvRound(sum_dist/MAX(total, 1)); - - if( count > 0 || (out_corner_count && -count > *out_corner_count) ) - { - // copy corners to output array - for(int i = 0; i < n; i++ ) - out_corners[i] = corner_group[i]->pt; - - if( out_corner_count ) - *out_corner_count = n; - - if( count == pattern_size.width*pattern_size.height && - icvCheckBoardMonotony( out_corners, pattern_size )) - { - found = 1; - break; - } - } - } - }//dilations + // So we can find rectangles that go to the edge, we draw a white line around the image edge. + // Otherwise FindContours will miss those clipped rectangle contours. + // The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()... + rectangle( thresh_img_new, Point(0,0), Point(thresh_img_new.cols-1, thresh_img_new.rows-1), Scalar(255,255,255), 3, LINE_8); + int max_quad_buf_size = 0; + cvFree(&quads); + cvFree(&corners); + int quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img_new, flags, &max_quad_buf_size ); + PRINTF("Quad count: %d/%d\n", quad_count, (pattern_size.width/2+1)*(pattern_size.height/2+1)); + SHOW_QUADS("New quads", thresh_img_new, quads, quad_count); + if (processQuads(quads, quad_count, pattern_size, max_quad_buf_size, storage, corners, out_corners, out_corner_count, prev_sqr_size)) + found = 1; + } PRINTF("Chessboard detection result 0: %d\n", found); // revert to old, slower, method if detection failed if (!found) { - PRINTF("Fallback to old algorithm\n"); - // empiric threshold level - // thresholding performed here and not inside the cycle to save processing time - int thresh_level; - if ( !(flags & CV_CALIB_CB_ADAPTIVE_THRESH) ) - { - double mean = cvAvg( img ).val[0]; - thresh_level = cvRound( mean - 10 ); - thresh_level = MAX( thresh_level, 10 ); - cvThreshold( img, thresh_img, thresh_level, 255, CV_THRESH_BINARY ); - } - for( k = 0; k < 6; k++ ) - { - int max_quad_buf_size = 0; - for( dilations = min_dilations; dilations <= max_dilations; dilations++ ) + if( flags & CV_CALIB_CB_NORMALIZE_IMAGE ) { - if (found) - break; // already found it + equalizeHist( img, img ); + } - cvFree(&quads); - cvFree(&corners); + Mat thresh_img; + prev_sqr_size = 0; - // convert the input grayscale image to binary (black-n-white) - if( flags & CV_CALIB_CB_ADAPTIVE_THRESH ) - { - int block_size = cvRound(prev_sqr_size == 0 ? - MIN(img->cols,img->rows)*(k%2 == 0 ? 0.2 : 0.1): prev_sqr_size*2)|1; - - // convert to binary - cvAdaptiveThreshold( img, thresh_img, 255, - CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, block_size, (k/2)*5 ); - if (dilations > 0) - cvDilate( thresh_img, thresh_img, 0, dilations-1 ); - } - //if flag CV_CALIB_CB_ADAPTIVE_THRESH is not set it doesn't make sense - //to iterate over k - else - { - k = 6; - cvDilate( thresh_img, thresh_img, 0, 1 ); - } - - // So we can find rectangles that go to the edge, we draw a white line around the image edge. - // Otherwise FindContours will miss those clipped rectangle contours. - // The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()... - cvRectangle( thresh_img, cvPoint(0,0), cvPoint(thresh_img->cols-1, - thresh_img->rows-1), CV_RGB(255,255,255), 3, 8); - - quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img, flags, &max_quad_buf_size); - PRINTF("Quad count: %d/%d\n", quad_count, expected_corners_num); - - if( quad_count <= 0 ) - { - continue; - } - - // Find quad's neighbors - icvFindQuadNeighbors( quads, quad_count ); - - // allocate extra for adding in icvOrderFoundQuads - cvFree(&quad_group); - cvFree(&corner_group); - quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * max_quad_buf_size); - corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * max_quad_buf_size * 4 ); - - for( group_idx = 0; ; group_idx++ ) - { - int count = 0; - count = icvFindConnectedQuads( quads, quad_count, quad_group, group_idx, storage ); - - int icount = count; - if( count == 0 ) - break; - - // order the quad corners globally - // maybe delete or add some - PRINTF("Starting ordering of inner quads\n"); - count = icvOrderFoundConnectedQuads(count, quad_group, &quad_count, &quads, &corners, pattern_size, max_quad_buf_size, storage ); - - PRINTF("Orig count: %d After ordering: %d\n", icount, count); - - if (count == 0) - continue; // haven't found inner quads - - - // If count is more than it should be, this will remove those quads - // which cause maximum deviation from a nice square pattern. - count = icvCleanFoundConnectedQuads( count, quad_group, pattern_size ); - PRINTF("Connected group: %d orig count: %d cleaned: %d\n", group_idx, icount, count); - - count = icvCheckQuadGroup( quad_group, count, corner_group, pattern_size ); - PRINTF("Connected group: %d count: %d cleaned: %d\n", group_idx, icount, count); - - int n = count > 0 ? pattern_size.width * pattern_size.height : -count; - n = MIN( n, pattern_size.width * pattern_size.height ); - float sum_dist = 0; - int total = 0; - - for(int i = 0; i < n; i++ ) + PRINTF("Fallback to old algorithm\n"); + const bool useAdaptive = flags & CV_CALIB_CB_ADAPTIVE_THRESH; + if (!useAdaptive) + { + // empiric threshold level + // thresholding performed here and not inside the cycle to save processing time + double mean = cv::mean(img).val[0]; + int thresh_level = MAX(cvRound( mean - 10 ), 10); + threshold( img, thresh_img, thresh_level, 255, THRESH_BINARY ); + } + //if flag CV_CALIB_CB_ADAPTIVE_THRESH is not set it doesn't make sense to iterate over k + int max_k = useAdaptive ? 6 : 1; + for( k = 0; k < max_k; k++ ) + { + for( int dilations = min_dilations; dilations <= max_dilations; dilations++ ) { - int ni = 0; - float avgi = corner_group[i]->meanDist(&ni); - sum_dist += avgi*ni; - total += ni; + if (found) + break; // already found it + + // convert the input grayscale image to binary (black-n-white) + if (useAdaptive) + { + int block_size = cvRound(prev_sqr_size == 0 + ? MIN(img.cols, img.rows) * (k % 2 == 0 ? 0.2 : 0.1) + : prev_sqr_size * 2); + block_size = block_size | 1; + // convert to binary + adaptiveThreshold( img, thresh_img, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, block_size, (k/2)*5 ); + if (dilations > 0) + dilate( thresh_img, thresh_img, Mat(), Point(-1, -1), dilations-1 ); + + } + else + { + dilate( thresh_img, thresh_img, Mat(), Point(-1, -1), 1 ); + } + SHOW("Old binarization", thresh_img); + + // So we can find rectangles that go to the edge, we draw a white line around the image edge. + // Otherwise FindContours will miss those clipped rectangle contours. + // The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()... + rectangle( thresh_img, Point(0,0), Point(thresh_img.cols-1, thresh_img.rows-1), Scalar(255,255,255), 3, LINE_8); + int max_quad_buf_size = 0; + cvFree(&quads); + cvFree(&corners); + int quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img, flags, &max_quad_buf_size); + PRINTF("Quad count: %d/%d\n", quad_count, (pattern_size.width/2+1)*(pattern_size.height/2+1)); + SHOW_QUADS("Old quads", thresh_img, quads, quad_count); + if (processQuads(quads, quad_count, pattern_size, max_quad_buf_size, storage, corners, out_corners, out_corner_count, prev_sqr_size)) + found = 1; } - prev_sqr_size = cvRound(sum_dist/MAX(total, 1)); - - if( count > 0 || (out_corner_count && -count > *out_corner_count) ) - { - // copy corners to output array - for(int i = 0; i < n; i++ ) - out_corners[i] = corner_group[i]->pt; - - if( out_corner_count ) - *out_corner_count = n; - - if( count == pattern_size.width*pattern_size.height && icvCheckBoardMonotony( out_corners, pattern_size )) - { - found = 1; - break; - } - } - } - }//dilations - }// for k = 0 -> 6 + } } PRINTF("Chessboard detection result 1: %d\n", found); @@ -722,8 +584,8 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, const int BORDER = 8; for( k = 0; k < pattern_size.width*pattern_size.height; k++ ) { - if( out_corners[k].x <= BORDER || out_corners[k].x > img->cols - BORDER || - out_corners[k].y <= BORDER || out_corners[k].y > img->rows - BORDER ) + if( out_corners[k].x <= BORDER || out_corners[k].x > img.cols - BORDER || + out_corners[k].y <= BORDER || out_corners[k].y > img.rows - BORDER ) break; } @@ -734,51 +596,35 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, if( found ) { - if ( pattern_size.height % 2 == 0 && pattern_size.width % 2 == 0 ) - { - int last_row = (pattern_size.height-1)*pattern_size.width; - double dy0 = out_corners[last_row].y - out_corners[0].y; - if( dy0 < 0 ) + if ( pattern_size.height % 2 == 0 && pattern_size.width % 2 == 0 ) { - int n = pattern_size.width*pattern_size.height; - for(int i = 0; i < n/2; i++ ) - { - CvPoint2D32f temp; - CV_SWAP(out_corners[i], out_corners[n-i-1], temp); - } + int last_row = (pattern_size.height-1)*pattern_size.width; + double dy0 = out_corners[last_row].y - out_corners[0].y; + if( dy0 < 0 ) + { + int n = pattern_size.width*pattern_size.height; + for(int i = 0; i < n/2; i++ ) + { + CvPoint2D32f temp; + CV_SWAP(out_corners[i], out_corners[n-i-1], temp); + } + } } - } - cv::Ptr gray; - if( CV_MAT_CN(img->type) != 1 ) - { - gray.reset(cvCreateMat(img->rows, img->cols, CV_8UC1)); - cvCvtColor(img, gray, CV_BGR2GRAY); - } - else - { - gray.reset(cvCloneMat(img)); - } - int wsize = 2; - cvFindCornerSubPix( gray, out_corners, pattern_size.width*pattern_size.height, - cvSize(wsize, wsize), cvSize(-1,-1), - cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 15, 0.1)); + int wsize = 2; + CvMat old_img(img); + cvFindCornerSubPix( &old_img, out_corners, pattern_size.width*pattern_size.height, + cvSize(wsize, wsize), cvSize(-1,-1), + cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 15, 0.1)); } } catch(...) { cvFree(&quads); cvFree(&corners); - cvFree(&quad_group); - cvFree(&corner_group); - cvFree(&cImgSeg); throw; } - cvFree(&quads); cvFree(&corners); - cvFree(&quad_group); - cvFree(&corner_group); - cvFree(&cImgSeg); return found; } @@ -1866,8 +1712,9 @@ static void icvFindQuadNeighbors( CvCBQuad *quads, int quad_count ) static int icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners, - CvMemStorage *storage, CvMat *image, int flags, int *max_quad_buf_size ) + CvMemStorage *storage, const cv::Mat & image_, int flags, int *max_quad_buf_size ) { + CvMat image_old(image_), *image = &image_old; int quad_count = 0; cv::Ptr temp_storage; @@ -2011,6 +1858,88 @@ icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners, return quad_count; } +static bool processQuads(CvCBQuad *quads, int quad_count, CvSize pattern_size, int max_quad_buf_size, + CvMemStorage * storage, CvCBCorner *corners, CvPoint2D32f *out_corners, int *out_corner_count, int & prev_sqr_size) +{ + if( quad_count <= 0 ) + return false; + + bool found = false; + + // Find quad's neighbors + icvFindQuadNeighbors( quads, quad_count ); + + // allocate extra for adding in icvOrderFoundQuads + CvCBQuad **quad_group = 0; + CvCBCorner **corner_group = 0; + + quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * max_quad_buf_size); + corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * max_quad_buf_size * 4 ); + + for( int group_idx = 0; ; group_idx++ ) + { + int count = icvFindConnectedQuads( quads, quad_count, quad_group, group_idx, storage ); + + if( count == 0 ) + break; + + // order the quad corners globally + // maybe delete or add some + PRINTF("Starting ordering of inner quads (%d)\n", count); + count = icvOrderFoundConnectedQuads(count, quad_group, &quad_count, &quads, &corners, + pattern_size, max_quad_buf_size, storage ); + PRINTF("Finished ordering of inner quads (%d)\n", count); + + if (count == 0) + continue; // haven't found inner quads + + // If count is more than it should be, this will remove those quads + // which cause maximum deviation from a nice square pattern. + count = icvCleanFoundConnectedQuads( count, quad_group, pattern_size ); + PRINTF("Connected group: %d, count: %d\n", group_idx, count); + + count = icvCheckQuadGroup( quad_group, count, corner_group, pattern_size ); + PRINTF("Connected group: %d, count: %d\n", group_idx, count); + + int n = count > 0 ? pattern_size.width * pattern_size.height : -count; + n = MIN( n, pattern_size.width * pattern_size.height ); + float sum_dist = 0; + int total = 0; + + for(int i = 0; i < n; i++ ) + { + int ni = 0; + float avgi = corner_group[i]->meanDist(&ni); + sum_dist += avgi*ni; + total += ni; + } + prev_sqr_size = cvRound(sum_dist/MAX(total, 1)); + + if( count > 0 || (out_corner_count && -count > *out_corner_count) ) + { + // copy corners to output array + for(int i = 0; i < n; i++ ) + out_corners[i] = corner_group[i]->pt; + + if( out_corner_count ) + *out_corner_count = n; + + if( count == pattern_size.width*pattern_size.height + && icvCheckBoardMonotony( out_corners, pattern_size )) + { + found = true; + break; + } + } + } + + cvFree(&quad_group); + cvFree(&corner_group); + + return found; +} + +//================================================================================================== CV_IMPL void cvDrawChessboardCorners( CvArr* _image, CvSize pattern_size, diff --git a/modules/calib3d/src/checkchessboard.cpp b/modules/calib3d/src/checkchessboard.cpp index 88c6baf107..ea3487846b 100644 --- a/modules/calib3d/src/checkchessboard.cpp +++ b/modules/calib3d/src/checkchessboard.cpp @@ -46,28 +46,26 @@ #include #include -//#define DEBUG_WINDOWS +using namespace cv; +using namespace std; -#if defined(DEBUG_WINDOWS) -# include "opencv2/opencv_modules.hpp" -# ifdef HAVE_OPENCV_HIGHGUI -# include "opencv2/highgui.hpp" -# else -# undef DEBUG_WINDOWS -# endif -#endif - -int cvCheckChessboardBinary(IplImage* src, CvSize size); - -static void icvGetQuadrangleHypotheses(CvSeq* contours, std::vector >& quads, int class_id) +static void icvGetQuadrangleHypotheses(const std::vector > & contours, const std::vector< cv::Vec4i > & hierarchy, std::vector >& quads, int class_id) { const float min_aspect_ratio = 0.3f; const float max_aspect_ratio = 3.0f; const float min_box_size = 10.0f; - for(CvSeq* seq = contours; seq != NULL; seq = seq->h_next) + typedef std::vector< std::vector< cv::Point > >::const_iterator iter_t; + iter_t i; + for (i = contours.begin(); i != contours.end(); ++i) { - CvBox2D box = cvMinAreaRect2(seq); + const iter_t::difference_type idx = i - contours.begin(); + if (hierarchy.at(idx)[3] != -1) + continue; // skip holes + + const std::vector< cv::Point > & c = *i; + cv::RotatedRect box = cv::minAreaRect(c); + float box_size = MAX(box.size.width, box.size.height); if(box_size < min_box_size) { @@ -98,6 +96,64 @@ inline bool less_pred(const std::pair& p1, const std::pair > & quads) +{ + Mat thresh; + { + vector< vector > contours; + vector< Vec4i > hierarchy; + threshold(white, thresh, white_thresh, 255, THRESH_BINARY); + findContours(thresh, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE); + icvGetQuadrangleHypotheses(contours, hierarchy, quads, 1); + } + + { + vector< vector > contours; + vector< Vec4i > hierarchy; + threshold(black, thresh, black_thresh, 255, THRESH_BINARY_INV); + findContours(thresh, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE); + icvGetQuadrangleHypotheses(contours, hierarchy, quads, 0); + } +} + +static bool checkQuads(vector > & quads, const cv::Size & size) +{ + const size_t min_quads_count = size.width*size.height/2; + std::sort(quads.begin(), quads.end(), less_pred); + + // now check if there are many hypotheses with similar sizes + // do this by floodfill-style algorithm + const float size_rel_dev = 0.4f; + + for(size_t i = 0; i < quads.size(); i++) + { + size_t j = i + 1; + for(; j < quads.size(); j++) + { + if(quads[j].first/quads[i].first > 1.0f + size_rel_dev) + { + break; + } + } + + if(j + 1 > min_quads_count + i) + { + // check the number of black and white squares + std::vector counts; + countClasses(quads, i, j, counts); + const int black_count = cvRound(ceil(size.width/2.0)*ceil(size.height/2.0)); + const int white_count = cvRound(floor(size.width/2.0)*floor(size.height/2.0)); + if(counts[0] < black_count*0.75 || + counts[1] < white_count*0.75) + { + continue; + } + return true; + } + } + return false; +} + // does a fast check if a chessboard is in the input image. This is a workaround to // a problem of cvFindChessboardCorners being slow on images with no chessboard // - src: input image @@ -106,105 +162,32 @@ inline bool less_pred(const std::pair& p1, const std::pairnChannels > 1) - { - cvError(CV_BadNumChannels, "cvCheckChessboard", "supports single-channel images only", - __FILE__, __LINE__); - } + cv::Mat img = cv::cvarrToMat(src); + return checkChessboard(img, size); +} - if(src->depth != 8) - { - cvError(CV_BadDepth, "cvCheckChessboard", "supports depth=8 images only", - __FILE__, __LINE__); - } +int checkChessboard(const cv::Mat & img, const cv::Size & size) +{ + CV_Assert(img.channels() == 1 && img.depth() == CV_8U); const int erosion_count = 1; const float black_level = 20.f; const float white_level = 130.f; const float black_white_gap = 70.f; -#if defined(DEBUG_WINDOWS) - cvNamedWindow("1", 1); - cvShowImage("1", src); - cvWaitKey(0); -#endif //DEBUG_WINDOWS - - CvMemStorage* storage = cvCreateMemStorage(); - - IplImage* white = cvCloneImage(src); - IplImage* black = cvCloneImage(src); - - cvErode(white, white, NULL, erosion_count); - cvDilate(black, black, NULL, erosion_count); - IplImage* thresh = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1); + Mat white; + Mat black; + erode(img, white, Mat(), Point(-1, -1), erosion_count); + dilate(img, black, Mat(), Point(-1, -1), erosion_count); int result = 0; for(float thresh_level = black_level; thresh_level < white_level && !result; thresh_level += 20.0f) { - cvThreshold(white, thresh, thresh_level + black_white_gap, 255, CV_THRESH_BINARY); - -#if defined(DEBUG_WINDOWS) - cvShowImage("1", thresh); - cvWaitKey(0); -#endif //DEBUG_WINDOWS - - CvSeq* first = 0; - std::vector > quads; - cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP); - icvGetQuadrangleHypotheses(first, quads, 1); - - cvThreshold(black, thresh, thresh_level, 255, CV_THRESH_BINARY_INV); - -#if defined(DEBUG_WINDOWS) - cvShowImage("1", thresh); - cvWaitKey(0); -#endif //DEBUG_WINDOWS - - cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP); - icvGetQuadrangleHypotheses(first, quads, 0); - - const size_t min_quads_count = size.width*size.height/2; - std::sort(quads.begin(), quads.end(), less_pred); - - // now check if there are many hypotheses with similar sizes - // do this by floodfill-style algorithm - const float size_rel_dev = 0.4f; - - for(size_t i = 0; i < quads.size(); i++) - { - size_t j = i + 1; - for(; j < quads.size(); j++) - { - if(quads[j].first/quads[i].first > 1.0f + size_rel_dev) - { - break; - } - } - - if(j + 1 > min_quads_count + i) - { - // check the number of black and white squares - std::vector counts; - countClasses(quads, i, j, counts); - const int black_count = cvRound(ceil(size.width/2.0)*ceil(size.height/2.0)); - const int white_count = cvRound(floor(size.width/2.0)*floor(size.height/2.0)); - if(counts[0] < black_count*0.75 || - counts[1] < white_count*0.75) - { - continue; - } - result = 1; - break; - } - } + vector > quads; + fillQuads(white, black, thresh_level + black_white_gap, thresh_level, quads); + if (checkQuads(quads, size)) + result = 1; } - - - cvReleaseImage(&thresh); - cvReleaseImage(&white); - cvReleaseImage(&black); - cvReleaseMemStorage(&storage); - return result; } @@ -214,90 +197,29 @@ int cvCheckChessboard(IplImage* src, CvSize size) // - size: chessboard size // Returns 1 if a chessboard can be in this image and findChessboardCorners should be called, // 0 if there is no chessboard, -1 in case of error -int cvCheckChessboardBinary(IplImage* src, CvSize size) +int checkChessboardBinary(const cv::Mat & img, const cv::Size & size) { - if(src->nChannels > 1) - { - cvError(CV_BadNumChannels, "cvCheckChessboard", "supports single-channel images only", - __FILE__, __LINE__); - } + CV_Assert(img.channels() == 1 && img.depth() == CV_8U); - if(src->depth != 8) - { - cvError(CV_BadDepth, "cvCheckChessboard", "supports depth=8 images only", - __FILE__, __LINE__); - } - - CvMemStorage* storage = cvCreateMemStorage(); - - IplImage* white = cvCloneImage(src); - IplImage* black = cvCloneImage(src); - IplImage* thresh = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1); + Mat white = img.clone(); + Mat black = img.clone(); int result = 0; - for ( int erosion_count = 0; erosion_count <= 3; erosion_count++ ) { - if ( 1 == result ) - break; + if ( 1 == result ) + break; - if ( 0 != erosion_count ) // first iteration keeps original images - { - cvErode(white, white, NULL, 1); - cvDilate(black, black, NULL, 1); - } + if ( 0 != erosion_count ) // first iteration keeps original images + { + erode(white, white, Mat(), Point(-1, -1), 1); + dilate(black, black, Mat(), Point(-1, -1), 1); + } - cvThreshold(white, thresh, 128, 255, CV_THRESH_BINARY); - - CvSeq* first = 0; - std::vector > quads; - cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP); - icvGetQuadrangleHypotheses(first, quads, 1); - - cvThreshold(black, thresh, 128, 255, CV_THRESH_BINARY_INV); - cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP); - icvGetQuadrangleHypotheses(first, quads, 0); - - const size_t min_quads_count = size.width*size.height/2; - std::sort(quads.begin(), quads.end(), less_pred); - - // now check if there are many hypotheses with similar sizes - // do this by floodfill-style algorithm - const float size_rel_dev = 0.4f; - - for(size_t i = 0; i < quads.size(); i++) - { - size_t j = i + 1; - for(; j < quads.size(); j++) - { - if(quads[j].first/quads[i].first > 1.0f + size_rel_dev) - { - break; - } - } - - if(j + 1 > min_quads_count + i) - { - // check the number of black and white squares - std::vector counts; - countClasses(quads, i, j, counts); - const int black_count = cvRound(ceil(size.width/2.0)*ceil(size.height/2.0)); - const int white_count = cvRound(floor(size.width/2.0)*floor(size.height/2.0)); - if(counts[0] < black_count*0.75 || - counts[1] < white_count*0.75) - { - continue; - } - result = 1; - break; - } - } + vector > quads; + fillQuads(white, black, 128, 128, quads); + if (checkQuads(quads, size)) + result = 1; } - - cvReleaseImage(&thresh); - cvReleaseImage(&white); - cvReleaseImage(&black); - cvReleaseMemStorage(&storage); - return result; -} \ No newline at end of file +} diff --git a/modules/calib3d/src/precomp.hpp b/modules/calib3d/src/precomp.hpp index 83a513dcaa..0005f234e2 100644 --- a/modules/calib3d/src/precomp.hpp +++ b/modules/calib3d/src/precomp.hpp @@ -117,4 +117,7 @@ template inline int compressElems( T* ptr, const uchar* mask, int ms } +int checkChessboard(const cv::Mat & img, const cv::Size & size); +int checkChessboardBinary(const cv::Mat & img, const cv::Size & size); + #endif diff --git a/modules/calib3d/test/test_chesscorners.cpp b/modules/calib3d/test/test_chesscorners.cpp index fd3da2e440..f4208a574c 100644 --- a/modules/calib3d/test/test_chesscorners.cpp +++ b/modules/calib3d/test/test_chesscorners.cpp @@ -51,29 +51,31 @@ using namespace cv; #define _L2_ERR -void show_points( const Mat& gray, const Mat& u, const vector& v, Size pattern_size, bool was_found ) +//#define DEBUG_CHESSBOARD + +#ifdef DEBUG_CHESSBOARD +#include "opencv2/highgui.hpp" +void show_points( const Mat& gray, const Mat& expected, const vector& actual, bool was_found ) { Mat rgb( gray.size(), CV_8U); merge(vector(3, gray), rgb); - for(size_t i = 0; i < v.size(); i++ ) - circle( rgb, v[i], 3, Scalar(255, 0, 0), FILLED); + for(size_t i = 0; i < actual.size(); i++ ) + circle( rgb, actual[i], 5, Scalar(0, 0, 200), 1, LINE_AA); - if( !u.empty() ) + if( !expected.empty() ) { - const Point2f* u_data = u.ptr(); - size_t count = u.cols * u.rows; + const Point2f* u_data = expected.ptr(); + size_t count = expected.cols * expected.rows; for(size_t i = 0; i < count; i++ ) - circle( rgb, u_data[i], 3, Scalar(0, 255, 0), FILLED); + circle(rgb, u_data[i], 4, Scalar(0, 240, 0), 1, LINE_AA); } - if (!v.empty()) - { - Mat corners((int)v.size(), 1, CV_32FC2, (void*)&v[0]); - drawChessboardCorners( rgb, pattern_size, corners, was_found ); - } - //namedWindow( "test", 0 ); imshow( "test", rgb ); waitKey(0); + putText(rgb, was_found ? "FOUND !!!" : "NOT FOUND", Point(5, 20), FONT_HERSHEY_PLAIN, 1, Scalar(0, 240, 0)); + imshow( "test", rgb ); while ((uchar)waitKey(0) != 'q') {}; } - +#else +#define show_points(...) +#endif enum Pattern { CHESSBOARD, CIRCLES_GRID, ASYMMETRIC_CIRCLES_GRID }; @@ -253,7 +255,6 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename ) result = findCirclesGrid(gray, pattern_size, v, CALIB_CB_ASYMMETRIC_GRID | algorithmFlags); break; } - show_points( gray, Mat(), v, pattern_size, result ); if( result ^ doesContatinChessboard || v.size() != count_exp ) { @@ -280,7 +281,7 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename ) if( pattern == CHESSBOARD ) cornerSubPix( gray, v, Size(5, 5), Size(-1,-1), TermCriteria(TermCriteria::EPS|TermCriteria::MAX_ITER, 30, 0.1)); //find4QuadCornerSubpix(gray, v, Size(5, 5)); - show_points( gray, expected, v, pattern_size, result ); + show_points( gray, expected, v, result ); #ifndef WRITE_POINTS // printf("called find4QuadCornerSubpix\n"); err = calcError(v, expected); @@ -298,6 +299,10 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename ) max_precise_error = MAX( max_precise_error, err ); #endif } + else + { + show_points( gray, Mat(), v, result ); + } #ifdef WRITE_POINTS Mat mat_v(pattern_size, CV_32FC2, (void*)&v[0]); diff --git a/modules/python/test/test_calibration.py b/modules/python/test/test_calibration.py index 665521862c..584c7e6cbb 100644 --- a/modules/python/test/test_calibration.py +++ b/modules/python/test/test_calibration.py @@ -57,7 +57,7 @@ class calibration_test(NewOpenCVTests): eps = 0.01 normCamEps = 10.0 - normDistEps = 0.001 + normDistEps = 0.05 cameraMatrixTest = [[ 532.80992189, 0., 342.4952186 ], [ 0., 532.93346422, 233.8879292 ], @@ -68,4 +68,4 @@ class calibration_test(NewOpenCVTests): self.assertLess(abs(rms - 0.196334638034), eps) self.assertLess(cv2.norm(camera_matrix - cameraMatrixTest, cv2.NORM_L1), normCamEps) - self.assertLess(cv2.norm(dist_coefs - distCoeffsTest, cv2.NORM_L1), normDistEps) \ No newline at end of file + self.assertLess(cv2.norm(dist_coefs - distCoeffsTest, cv2.NORM_L1), normDistEps) From c7cb116dc08441fe56cf82d5b21f929e5b674c13 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Wed, 21 Sep 2016 15:42:54 +0900 Subject: [PATCH 174/178] check FP16 build condition correctly * use __GNUC_MINOR__ in correct place to check the version of GCC * check processor support of FP16 at run time * check compiler support of FP16 and pass correct compiler option * rely on ENABLE_AVX on gcc since AVX is generated when mf16c is passed * guard correctly using ifdef in case of various configuration * use v_float16x4 correctly by including the right header file --- cmake/OpenCVCompilerOptions.cmake | 45 +++++++++++------- modules/core/include/opencv2/core/cvdef.h | 2 +- modules/core/src/convert.cpp | 11 +++-- modules/core/test/test_intrin.cpp | 56 +++++++++++++---------- 4 files changed, 68 insertions(+), 46 deletions(-) diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake index 15e4db1125..686b0b885e 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -151,7 +151,7 @@ if(CMAKE_COMPILER_IS_GNUCXX) add_extra_compiler_option("-mfp16-format=ieee") endif(ARM) if(ENABLE_NEON) - add_extra_compiler_option("-mfpu=neon-fp16") + add_extra_compiler_option("-mfpu=neon") endif() if(ENABLE_VFPV3 AND NOT ENABLE_NEON) add_extra_compiler_option("-mfpu=vfpv3") @@ -336,6 +336,34 @@ if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_OPENCV_GCC_VERSION_NUM GREATER 399) add_extra_compiler_option(-fvisibility-inlines-hidden) endif() +if(NOT OPENCV_FP16_DISABLE) + if(ARM AND ENABLE_NEON) + set(FP16_OPTION "-mfpu=neon-fp16") + elseif((X86 OR X86_64) AND NOT MSVC AND ENABLE_AVX) + set(FP16_OPTION "-mf16c") + endif() + try_compile(__VALID_FP16 + "${OpenCV_BINARY_DIR}" + "${OpenCV_SOURCE_DIR}/cmake/checks/fp16.cpp" + COMPILE_DEFINITIONS "-DCHECK_FP16" "${FP16_OPTION}" + OUTPUT_VARIABLE TRY_OUT + ) + if(NOT __VALID_FP16) + if((X86 OR X86_64) AND NOT MSVC AND NOT ENABLE_AVX) + # GCC enables AVX when mf16c is passed + message(STATUS "FP16: Feature disabled") + else() + message(STATUS "FP16: Compiler support is not available") + endif() + else() + message(STATUS "FP16: Compiler support is available") + set(HAVE_FP16 1) + if(NOT ${FP16_OPTION} STREQUAL "") + add_extra_compiler_option(${FP16_OPTION}) + endif() + endif() +endif() + #combine all "extra" options set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPENCV_EXTRA_FLAGS} ${OPENCV_EXTRA_C_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPENCV_EXTRA_FLAGS} ${OPENCV_EXTRA_CXX_FLAGS}") @@ -376,21 +404,6 @@ if(MSVC) endif() endif() -if(NOT OPENCV_FP16_DISABLE) - try_compile(__VALID_FP16 - "${OpenCV_BINARY_DIR}" - "${OpenCV_SOURCE_DIR}/cmake/checks/fp16.cpp" - COMPILE_DEFINITIONS "-DCHECK_FP16" - OUTPUT_VARIABLE TRY_OUT - ) - if(NOT __VALID_FP16) - message(STATUS "FP16: Compiler support is not available") - else() - message(STATUS "FP16: Compiler support is available") - set(HAVE_FP16 1) - endif() -endif() - if(APPLE AND NOT CMAKE_CROSSCOMPILING AND NOT DEFINED ENV{LDFLAGS} AND EXISTS "/usr/local/lib") link_directories("/usr/local/lib") endif() diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index a26cd1caf6..87fe88594e 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -310,7 +310,7 @@ enum CpuFeatures { typedef union Cv16suf { short i; -#if ( defined (__arm__) || defined (__aarch64__) ) && !defined (__CUDACC__) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) ) +#if ( defined (__arm__) || defined (__aarch64__) ) && !defined (__CUDACC__) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC_MINOR__ ) ) || ( 5 <= __GNUC__ ) ) ) __fp16 h; #endif struct _fp16Format diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index c405919f17..dc2da5e611 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -44,6 +44,7 @@ #include "precomp.hpp" #include "opencl_kernels_core.hpp" +#include "opencv2/core/hal/intrin.hpp" #ifdef __APPLE__ #undef CV_NEON @@ -4379,7 +4380,7 @@ struct Cvt_SIMD #endif -#if !( ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) ) ) +#if !( ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC_MINOR__ ) ) || ( 5 <= __GNUC__ ) ) ) ) // const numbers for floating points format const unsigned int kShiftSignificand = 13; const unsigned int kMaskFp16Significand = 0x3ff; @@ -4387,7 +4388,7 @@ const unsigned int kBiasFp16Exponent = 15; const unsigned int kBiasFp32Exponent = 127; #endif -#if ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) ) +#if ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC_MINOR__ ) ) || ( 5 <= __GNUC__ ) ) ) static float convertFp16SW(short fp16) { // Fp16 -> Fp32 @@ -4449,7 +4450,7 @@ static float convertFp16SW(short fp16) } #endif -#if ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) ) +#if ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC_MINOR__ ) ) || ( 5 <= __GNUC__ ) ) ) static short convertFp16SW(float fp32) { // Fp32 -> Fp16 @@ -4557,7 +4558,7 @@ cvtScaleHalf_( const float* src, size_t sstep, short* dst, size_t if ( ( (intptr_t)dst & 0xf ) == 0 ) #endif { -#if CV_FP16 +#if CV_FP16 && CV_SIMD128 for ( ; x <= size.width - 4; x += 4) { v_float32x4 v_src = v_load(src + x); @@ -4603,7 +4604,7 @@ cvtScaleHalf_( const short* src, size_t sstep, float* dst, size_t if ( ( (intptr_t)src & 0xf ) == 0 ) #endif { -#if CV_FP16 +#if CV_FP16 && CV_SIMD128 for ( ; x <= size.width - 4; x += 4) { v_float16x4 v_src = v_load_f16(src + x); diff --git a/modules/core/test/test_intrin.cpp b/modules/core/test/test_intrin.cpp index d9704ef432..7ebd8e979c 100644 --- a/modules/core/test/test_intrin.cpp +++ b/modules/core/test/test_intrin.cpp @@ -711,48 +711,56 @@ template struct TheTest return *this; } -#if CV_FP16 TheTest & test_loadstore_fp16() { +#if CV_FP16 AlignedData data; AlignedData out; - // check if addresses are aligned and unaligned respectively - EXPECT_EQ((size_t)0, (size_t)&data.a.d % 16); - EXPECT_NE((size_t)0, (size_t)&data.u.d % 16); - EXPECT_EQ((size_t)0, (size_t)&out.a.d % 16); - EXPECT_NE((size_t)0, (size_t)&out.u.d % 16); + if(checkHardwareSupport(CV_CPU_FP16)) + { + // check if addresses are aligned and unaligned respectively + EXPECT_EQ((size_t)0, (size_t)&data.a.d % 16); + EXPECT_NE((size_t)0, (size_t)&data.u.d % 16); + EXPECT_EQ((size_t)0, (size_t)&out.a.d % 16); + EXPECT_NE((size_t)0, (size_t)&out.u.d % 16); - // check some initialization methods - R r1 = data.u; - R r2 = v_load_f16(data.a.d); - R r3(r2); - EXPECT_EQ(data.u[0], r1.get0()); - EXPECT_EQ(data.a[0], r2.get0()); - EXPECT_EQ(data.a[0], r3.get0()); + // check some initialization methods + R r1 = data.u; + R r2 = v_load_f16(data.a.d); + R r3(r2); + EXPECT_EQ(data.u[0], r1.get0()); + EXPECT_EQ(data.a[0], r2.get0()); + EXPECT_EQ(data.a[0], r3.get0()); - // check some store methods - out.a.clear(); - v_store_f16(out.a.d, r1); - EXPECT_EQ(data.a, out.a); + // check some store methods + out.a.clear(); + v_store_f16(out.a.d, r1); + EXPECT_EQ(data.a, out.a); + } return *this; +#endif } TheTest & test_float_cvt_fp16() { +#if CV_FP16 AlignedData data; - // check conversion - v_float32x4 r1 = v_load(data.a.d); - v_float16x4 r2 = v_cvt_f16(r1); - v_float32x4 r3 = v_cvt_f32(r2); - EXPECT_EQ(0x3c00, r2.get0()); - EXPECT_EQ(r3.get0(), r1.get0()); + if(checkHardwareSupport(CV_CPU_FP16)) + { + // check conversion + v_float32x4 r1 = v_load(data.a.d); + v_float16x4 r2 = v_cvt_f16(r1); + v_float32x4 r3 = v_cvt_f32(r2); + EXPECT_EQ(0x3c00, r2.get0()); + EXPECT_EQ(r3.get0(), r1.get0()); + } return *this; - } #endif + } }; From 7840b07d2f2313dddd7ced90f4319c57f9c1b4ce Mon Sep 17 00:00:00 2001 From: daB0bby Date: Fri, 23 Sep 2016 13:00:30 +0200 Subject: [PATCH 175/178] bypass macro --- modules/flann/include/opencv2/flann/lsh_table.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/flann/include/opencv2/flann/lsh_table.h b/modules/flann/include/opencv2/flann/lsh_table.h index 582dcdb2fc..8ef2bd3810 100644 --- a/modules/flann/include/opencv2/flann/lsh_table.h +++ b/modules/flann/include/opencv2/flann/lsh_table.h @@ -265,7 +265,7 @@ private: { const size_t key_size_lower_bound = 1; //a value (size_t(1) << key_size) must fit the size_t type so key_size has to be strictly less than size of size_t - const size_t key_size_upper_bound = std::min(sizeof(BucketKey) * CHAR_BIT + 1, sizeof(size_t) * CHAR_BIT); + const size_t key_size_upper_bound = (std::min)(sizeof(BucketKey) * CHAR_BIT + 1, sizeof(size_t) * CHAR_BIT); if (key_size < key_size_lower_bound || key_size >= key_size_upper_bound) { CV_Error(cv::Error::StsBadArg, cv::format("Invalid key_size (=%d). Valid values for your system are %d <= key_size < %d.", (int)key_size, (int)key_size_lower_bound, (int)key_size_upper_bound)); From 809bbb472bba197b24368d7df461e776b498e352 Mon Sep 17 00:00:00 2001 From: daB0bby Date: Fri, 23 Sep 2016 13:01:19 +0200 Subject: [PATCH 176/178] bypass macro --- .../opencv2/stitching/detail/warpers_inl.hpp | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/modules/stitching/include/opencv2/stitching/detail/warpers_inl.hpp b/modules/stitching/include/opencv2/stitching/detail/warpers_inl.hpp index 0416ecb5ee..a91dd3f85d 100644 --- a/modules/stitching/include/opencv2/stitching/detail/warpers_inl.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/warpers_inl.hpp @@ -150,10 +150,10 @@ Rect RotationWarperBase

::warpRoi(Size src_size, InputArray K, InputArray R) template void RotationWarperBase

::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) { - float tl_uf = std::numeric_limits::max(); - float tl_vf = std::numeric_limits::max(); - float br_uf = -std::numeric_limits::max(); - float br_vf = -std::numeric_limits::max(); + float tl_uf = (std::numeric_limits::max)(); + float tl_vf = (std::numeric_limits::max)(); + float br_uf = -(std::numeric_limits::max)(); + float br_vf = -(std::numeric_limits::max)(); float u, v; for (int y = 0; y < src_size.height; ++y) @@ -161,8 +161,8 @@ void RotationWarperBase

::detectResultRoi(Size src_size, Point &dst_tl, Point for (int x = 0; x < src_size.width; ++x) { projector_.mapForward(static_cast(x), static_cast(y), u, v); - tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); - br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); + tl_uf = (std::min)(tl_uf, u); tl_vf = (std::min)(tl_vf, v); + br_uf = (std::max)(br_uf, u); br_vf = (std::max)(br_vf, v); } } @@ -176,31 +176,31 @@ void RotationWarperBase

::detectResultRoi(Size src_size, Point &dst_tl, Point template void RotationWarperBase

::detectResultRoiByBorder(Size src_size, Point &dst_tl, Point &dst_br) { - float tl_uf = std::numeric_limits::max(); - float tl_vf = std::numeric_limits::max(); - float br_uf = -std::numeric_limits::max(); - float br_vf = -std::numeric_limits::max(); + float tl_uf = (std::numeric_limits::max)(); + float tl_vf = (std::numeric_limits::max)(); + float br_uf = -(std::numeric_limits::max)(); + float br_vf = -(std::numeric_limits::max)(); float u, v; for (float x = 0; x < src_size.width; ++x) { projector_.mapForward(static_cast(x), 0, u, v); - tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); - br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); + tl_uf = (std::min)(tl_uf, u); tl_vf = (std::min)(tl_vf, v); + br_uf = (std::max)(br_uf, u); br_vf = (std::max)(br_vf, v); projector_.mapForward(static_cast(x), static_cast(src_size.height - 1), u, v); - tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); - br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); + tl_uf = (std::min)(tl_uf, u); tl_vf = (std::min)(tl_vf, v); + br_uf = (std::max)(br_uf, u); br_vf = (std::max)(br_vf, v); } for (int y = 0; y < src_size.height; ++y) { projector_.mapForward(0, static_cast(y), u, v); - tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); - br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); + tl_uf = (std::min)(tl_uf, u); tl_vf = (std::min)(tl_vf, v); + br_uf = (std::max)(br_uf, u); br_vf = (std::max)(br_vf, v); projector_.mapForward(static_cast(src_size.width - 1), static_cast(y), u, v); - tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); - br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); + tl_uf = (std::min)(tl_uf, u); tl_vf = (std::min)(tl_vf, v); + br_uf = (std::max)(br_uf, u); br_vf = (std::max)(br_vf, v); } dst_tl.x = static_cast(tl_uf); From 91002393a52cd816e2b990df5093600bc4cc20c4 Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Mon, 26 Sep 2016 17:13:18 +0300 Subject: [PATCH 177/178] Remove redundant constant definitions --- 3rdparty/openvx/include/openvx_hal.hpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/3rdparty/openvx/include/openvx_hal.hpp b/3rdparty/openvx/include/openvx_hal.hpp index a6547e12bb..26978e6db2 100644 --- a/3rdparty/openvx/include/openvx_hal.hpp +++ b/3rdparty/openvx/include/openvx_hal.hpp @@ -399,13 +399,6 @@ inline int ovx_hal_merge8u(const uchar **src_data, uchar *dst_data, int len, int #if defined OPENCV_IMGPROC_HAL_INTERFACE_H -#define CV_HAL_INTER_NEAREST 0 -#define CV_HAL_INTER_LINEAR 1 -#define CV_HAL_INTER_CUBIC 2 -#define CV_HAL_INTER_AREA 3 -#define CV_HAL_INTER_LANCZOS4 4 -#define MORPH_ERODE 0 -#define MORPH_DILATE 1 inline int ovx_hal_resize(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, double inv_scale_x, double inv_scale_y, int interpolation) { From c0216c518f72a9aec0b9426e9f1627884b5f7f21 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Wed, 28 Sep 2016 08:51:01 +0900 Subject: [PATCH 178/178] let the build available using clang * add if section for clang --- 3rdparty/carotene/hal/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/3rdparty/carotene/hal/CMakeLists.txt b/3rdparty/carotene/hal/CMakeLists.txt index 2fb92b907b..f2ca5fff84 100644 --- a/3rdparty/carotene/hal/CMakeLists.txt +++ b/3rdparty/carotene/hal/CMakeLists.txt @@ -25,6 +25,8 @@ endif() if(CMAKE_COMPILER_IS_GNUCXX) if(X86 OR ARMEABI_V6 OR (MIPS AND ANDROID_COMPILER_VERSION VERSION_LESS "4.6")) list(APPEND TEGRA_COMPILER_FLAGS -fweb -fwrapv -frename-registers -fsched-stalled-insns-dep=100 -fsched-stalled-insns=2) + elseif(CMAKE_COMPILER_IS_CLANGCXX) + list(APPEND TEGRA_COMPILER_FLAGS -fwrapv) else() list(APPEND TEGRA_COMPILER_FLAGS -fweb -fwrapv -frename-registers -fsched2-use-superblocks -fsched2-use-traces -fsched-stalled-insns-dep=100 -fsched-stalled-insns=2)