diff --git a/modules/core/include/opencv2/core/cvstd.inl.hpp b/modules/core/include/opencv2/core/cvstd.inl.hpp index 4a85bfd062..37ad1e6906 100644 --- a/modules/core/include/opencv2/core/cvstd.inl.hpp +++ b/modules/core/include/opencv2/core/cvstd.inl.hpp @@ -46,6 +46,7 @@ #include #include +#include //! @cond IGNORED diff --git a/modules/core/src/minmax.cpp b/modules/core/src/minmax.cpp index b4e5e4632a..43785d839b 100644 --- a/modules/core/src/minmax.cpp +++ b/modules/core/src/minmax.cpp @@ -1089,6 +1089,7 @@ bool ocl_minMaxIdx( InputArray _src, double* minVal, double* maxVal, int* minLoc getMinMaxRes }; + CV_Assert(ddepth <= CV_64F); getMinMaxResFunc func = functab[ddepth]; int locTemp[2]; diff --git a/modules/core/src/norm.cpp b/modules/core/src/norm.cpp index e25874e975..8611d1eab5 100644 --- a/modules/core/src/norm.cpp +++ b/modules/core/src/norm.cpp @@ -710,67 +710,78 @@ double cv::norm( InputArray _src, int normType, InputArray _mask ) result; result.d = 0; NAryMatIterator it(arrays, ptrs); - int j, total = (int)it.size, blockSize = total; - bool blockSum = depth == CV_16F || (normType == NORM_L1 && depth <= CV_16S) || - ((normType == NORM_L2 || normType == NORM_L2SQR) && depth <= CV_8S); - int isum = 0; - int *ibuf = &result.i; - AutoBuffer fltbuf_; - float* fltbuf = 0; - size_t esz = 0; + CV_CheckLT((size_t)it.size, (size_t)INT_MAX, ""); - if( blockSum ) + if ((normType == NORM_L1 && depth <= CV_16S) || + ((normType == NORM_L2 || normType == NORM_L2SQR) && depth <= CV_8S)) { - esz = src.elemSize(); + // special case to handle "integer" overflow in accumulator + const size_t esz = src.elemSize(); + const int total = (int)it.size; + const int intSumBlockSize = (normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15))/cn; + const int blockSize = std::min(total, intSumBlockSize); + int isum = 0; + int count = 0; - if( depth == CV_16F ) + for (size_t i = 0; i < it.nplanes; i++, ++it) { - blockSize = std::min(blockSize, 1024); - fltbuf_.allocate(blockSize); - fltbuf = fltbuf_.data(); - } - else - { - int intSumBlockSize = (normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15))/cn; - blockSize = std::min(blockSize, intSumBlockSize); - ibuf = &isum; + for (int j = 0; j < total; j += blockSize) + { + int bsz = std::min(total - j, blockSize); + func(ptrs[0], ptrs[1], (uchar*)&isum, bsz, cn); + count += bsz; + if (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) + { + result.d += isum; + isum = 0; + count = 0; + } + ptrs[0] += bsz*esz; + if (ptrs[1]) + ptrs[1] += bsz; + } } } - - for( size_t i = 0; i < it.nplanes; i++, ++it ) + else if (depth == CV_16F) { - for( j = 0; j < total; j += blockSize ) + const size_t esz = src.elemSize(); + const int total = (int)it.size; + const int blockSize = std::min(total, divUp(1024, cn)); + AutoBuffer fltbuf(blockSize); + float* data0 = fltbuf.data(); + for (size_t i = 0; i < it.nplanes; i++, ++it) { - int bsz = std::min(total - j, blockSize); - const uchar* data = ptrs[0]; - if( depth == CV_16F ) + for (int j = 0; j < total; j += blockSize) { - hal::cvt16f32f((const float16_t*)ptrs[0], fltbuf, bsz); - data = (const uchar*)fltbuf; + int bsz = std::min(total - j, blockSize); + hal::cvt16f32f((const float16_t*)ptrs[0], data0, bsz * cn); + func((uchar*)data0, ptrs[1], (uchar*)&result.d, bsz, cn); + ptrs[0] += bsz*esz; + if (ptrs[1]) + ptrs[1] += bsz; } - func( data, ptrs[1], (uchar*)ibuf, bsz, cn ); - if( blockSum && depth != CV_16F ) - { - result.d += isum; - isum = 0; - } - ptrs[0] += bsz*esz; - if( ptrs[1] ) - ptrs[1] += bsz; + } + } + else + { + // generic implementation + for (size_t i = 0; i < it.nplanes; i++, ++it) + { + func(ptrs[0], ptrs[1], (uchar*)&result, (int)it.size, cn); } } if( normType == NORM_INF ) { - if( depth == CV_64F ) - ; - else if( depth == CV_32F ) - result.d = result.f; + if(depth == CV_64F || depth == CV_16F) + return result.d; + else if (depth == CV_32F) + return result.f; else - result.d = result.i; + return result.i; } else if( normType == NORM_L2 ) - result.d = std::sqrt(result.d); + return std::sqrt(result.d); return result.d; } @@ -1186,70 +1197,82 @@ double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _m result; result.d = 0; NAryMatIterator it(arrays, ptrs); - int j, total = (int)it.size, blockSize = total; - bool blockSum = depth == CV_16F || (normType == NORM_L1 && depth <= CV_16S) || - ((normType == NORM_L2 || normType == NORM_L2SQR) && depth <= CV_8S); - unsigned isum = 0; - unsigned *ibuf = &result.u; - AutoBuffer fltbuf_; - float* fltbuf = 0; - size_t esz = 0; + CV_CheckLT((size_t)it.size, (size_t)INT_MAX, ""); - if( blockSum ) + if ((normType == NORM_L1 && depth <= CV_16S) || + ((normType == NORM_L2 || normType == NORM_L2SQR) && depth <= CV_8S)) { - esz = src1.elemSize(); + // special case to handle "integer" overflow in accumulator + const size_t esz = src1.elemSize(); + const int total = (int)it.size; + const int intSumBlockSize = normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15); + const int blockSize = std::min(total, intSumBlockSize); + int isum = 0; + int count = 0; - if( depth == CV_16F ) + for (size_t i = 0; i < it.nplanes; i++, ++it) { - blockSize = std::min(blockSize, 1024); - fltbuf_.allocate(blockSize*2); - fltbuf = fltbuf_.data(); - } - else - { - int intSumBlockSize = (normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15))/cn; - blockSize = std::min(blockSize, intSumBlockSize); - ibuf = &isum; + for (int j = 0; j < total; j += blockSize) + { + int bsz = std::min(total - j, blockSize); + func(ptrs[0], ptrs[1], ptrs[2], (uchar*)&isum, bsz, cn); + count += bsz; + if (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) + { + result.d += isum; + isum = 0; + count = 0; + } + ptrs[0] += bsz*esz; + ptrs[1] += bsz*esz; + if (ptrs[2]) + ptrs[2] += bsz; + } } } - - for( size_t i = 0; i < it.nplanes; i++, ++it ) + else if (depth == CV_16F) { - for( j = 0; j < total; j += blockSize ) + const size_t esz = src1.elemSize(); + const int total = (int)it.size; + const int blockSize = std::min(total, divUp(512, cn)); + AutoBuffer fltbuf(blockSize * 2); + float* data0 = fltbuf.data(); + float* data1 = fltbuf.data() + blockSize * cn; + for (size_t i = 0; i < it.nplanes; i++, ++it) { - int bsz = std::min(total - j, blockSize); - const uchar *data0 = ptrs[0], *data1 = ptrs[1]; - if( depth == CV_16F ) + for (int j = 0; j < total; j += blockSize) { - hal::cvt16f32f((const float16_t*)ptrs[0], fltbuf, bsz); - hal::cvt16f32f((const float16_t*)ptrs[1], fltbuf + bsz, bsz); - data0 = (const uchar*)fltbuf; - data1 = (const uchar*)(fltbuf + bsz); + int bsz = std::min(total - j, blockSize); + hal::cvt16f32f((const float16_t*)ptrs[0], data0, bsz * cn); + hal::cvt16f32f((const float16_t*)ptrs[1], data1, bsz * cn); + func((uchar*)data0, (uchar*)data1, ptrs[2], (uchar*)&result.d, bsz, cn); + ptrs[0] += bsz*esz; + ptrs[1] += bsz*esz; + if (ptrs[2]) + ptrs[2] += bsz; } - func( data0, data1, ptrs[2], (uchar*)ibuf, bsz, cn ); - if( blockSum && depth != CV_16F ) - { - result.d += isum; - isum = 0; - } - ptrs[0] += bsz*esz; - ptrs[1] += bsz*esz; - if( ptrs[2] ) - ptrs[2] += bsz; + } + } + else + { + // generic implementation + for (size_t i = 0; i < it.nplanes; i++, ++it) + { + func(ptrs[0], ptrs[1], ptrs[2], (uchar*)&result, (int)it.size, cn); } } if( normType == NORM_INF ) { - if( depth == CV_64F ) - ; - else if( depth == CV_32F ) - result.d = result.f; + if (depth == CV_64F || depth == CV_16F) + return result.d; + else if (depth == CV_32F) + return result.f; else - result.d = result.u; + return result.u; } else if( normType == NORM_L2 ) - result.d = std::sqrt(result.d); + return std::sqrt(result.d); return result.d; } diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 0025e37095..3301a7dcdd 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -6451,16 +6451,19 @@ struct Image2D::Impl CL_MEM_OBJECT_IMAGE2D, numFormats, NULL, &numFormats); CV_OCL_DBG_CHECK_RESULT(err, "clGetSupportedImageFormats(CL_MEM_OBJECT_IMAGE2D, NULL)"); - AutoBuffer formats(numFormats); - err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, - CL_MEM_OBJECT_IMAGE2D, numFormats, - formats.data(), NULL); - CV_OCL_DBG_CHECK_RESULT(err, "clGetSupportedImageFormats(CL_MEM_OBJECT_IMAGE2D, formats)"); - for (cl_uint i = 0; i < numFormats; ++i) + if (numFormats > 0) { - if (!memcmp(&formats[i], &format, sizeof(format))) + AutoBuffer formats(numFormats); + err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, + CL_MEM_OBJECT_IMAGE2D, numFormats, + formats.data(), NULL); + CV_OCL_DBG_CHECK_RESULT(err, "clGetSupportedImageFormats(CL_MEM_OBJECT_IMAGE2D, formats)"); + for (cl_uint i = 0; i < numFormats; ++i) { - return true; + if (!memcmp(&formats[i], &format, sizeof(format))) + { + return true; + } } } return false; diff --git a/modules/dnn/src/layers/blank_layer.cpp b/modules/dnn/src/layers/blank_layer.cpp index 229590ebdb..d639f378ab 100644 --- a/modules/dnn/src/layers/blank_layer.cpp +++ b/modules/dnn/src/layers/blank_layer.cpp @@ -115,17 +115,6 @@ public: inputs[i].copyTo(outputs[i]); } -#ifdef HAVE_CUDA - Ptr initCUDA( - void *context_, - const std::vector>& inputs, - const std::vector>& outputs - ) override - { - auto context = reinterpret_cast(context_); - return make_cuda_node(preferableTarget, std::move(context->stream)); - } -#endif #ifdef HAVE_DNN_IE_NN_BUILDER_2019 virtual Ptr initInfEngine(const std::vector >& inputs) CV_OVERRIDE @@ -163,6 +152,20 @@ public: return Ptr(new InfEngineNgraphNode(blank)); } #endif // HAVE_DNN_NGRAPH + + +#ifdef HAVE_CUDA + Ptr initCUDA( + void *context_, + const std::vector>& inputs, + const std::vector>& outputs + ) override + { + auto context = reinterpret_cast(context_); + return make_cuda_node(preferableTarget, std::move(context->stream)); + } +#endif + }; Ptr BlankLayer::create(const LayerParams& params) diff --git a/modules/dnn/src/layers/const_layer.cpp b/modules/dnn/src/layers/const_layer.cpp index afca48ba8d..bbea3e3f2c 100644 --- a/modules/dnn/src/layers/const_layer.cpp +++ b/modules/dnn/src/layers/const_layer.cpp @@ -75,6 +75,7 @@ public: blobs[0].copyTo(outputs[0]); } + #ifdef HAVE_DNN_IE_NN_BUILDER_2019 virtual Ptr initInfEngine(const std::vector >&) CV_OVERRIDE { @@ -84,6 +85,7 @@ public: } #endif // HAVE_DNN_IE_NN_BUILDER_2019 + #ifdef HAVE_DNN_NGRAPH virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE @@ -93,7 +95,8 @@ public: blobs[0].data); return Ptr(new InfEngineNgraphNode(node)); } -#endif // HAVE_DNN_IE_NN_BUILDER_2019 +#endif // HAVE_DNN_NGRAPH + #ifdef HAVE_CUDA Ptr initCUDA( diff --git a/modules/dnn/src/layers/flatten_layer.cpp b/modules/dnn/src/layers/flatten_layer.cpp index fc3f5fc37f..b5ecd8b8ee 100644 --- a/modules/dnn/src/layers/flatten_layer.cpp +++ b/modules/dnn/src/layers/flatten_layer.cpp @@ -171,17 +171,6 @@ public: } } -#ifdef HAVE_CUDA - Ptr initCUDA( - void *context_, - const std::vector>& inputs, - const std::vector>& outputs - ) override - { - auto context = reinterpret_cast(context_); - return make_cuda_node(preferableTarget, std::move(context->stream)); - } -#endif #ifdef HAVE_DNN_IE_NN_BUILDER_2019 virtual Ptr initInfEngine(const std::vector >& inputs) CV_OVERRIDE @@ -197,6 +186,7 @@ public: } #endif // HAVE_DNN_IE_NN_BUILDER_2019 + #ifdef HAVE_DNN_NGRAPH virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE @@ -224,6 +214,20 @@ virtual Ptr initNgraph(const std::vector >& inp } #endif // HAVE_DNN_NGRAPH + +#ifdef HAVE_CUDA + Ptr initCUDA( + void *context_, + const std::vector>& inputs, + const std::vector>& outputs + ) override + { + auto context = reinterpret_cast(context_); + return make_cuda_node(preferableTarget, std::move(context->stream)); + } +#endif + + int _startAxis; int _endAxis; }; diff --git a/modules/dnn/src/layers/normalize_bbox_layer.cpp b/modules/dnn/src/layers/normalize_bbox_layer.cpp index e669e0d90f..3958e504f9 100644 --- a/modules/dnn/src/layers/normalize_bbox_layer.cpp +++ b/modules/dnn/src/layers/normalize_bbox_layer.cpp @@ -268,32 +268,6 @@ public: } } -#ifdef HAVE_CUDA - Ptr initCUDA( - void *context_, - const std::vector>& inputs, - const std::vector>& outputs - ) override - { - auto context = reinterpret_cast(context_); - - if(pnorm != 1 && pnorm != 2) - CV_Error(Error::StsNotImplemented, "Unsupported normalization mode"); - - auto input_wrapper = inputs[0].dynamicCast(); - auto input_shape = input_wrapper->getShape(); - - NormalizeConfiguration config; - config.input_shape.assign(std::begin(input_shape), std::end(input_shape)); - config.axis_start = clamp(startAxis, input_shape.size()); - config.axis_end = clamp(endAxis, input_shape.size()) + 1; /* +1 because NormalizeOp follows [start, end) convention */ - config.norm = pnorm; - config.eps = epsilon; - - const auto& weightsMat = blobs.empty() ? Mat() : blobs[0]; - return make_cuda_node(preferableTarget, std::move(context->stream), weightsMat, config); - } -#endif #ifdef HAVE_DNN_IE_NN_BUILDER_2019 virtual Ptr initInfEngine(const std::vector >& inputs) CV_OVERRIDE @@ -346,6 +320,7 @@ public: } #endif // HAVE_DNN_IE_NN_BUILDER_2019 + #ifdef HAVE_DNN_NGRAPH virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE @@ -384,6 +359,35 @@ public: } #endif // HAVE_DNN_NGRAPH + +#ifdef HAVE_CUDA + Ptr initCUDA( + void *context_, + const std::vector>& inputs, + const std::vector>& outputs + ) override + { + auto context = reinterpret_cast(context_); + + if(pnorm != 1 && pnorm != 2) + CV_Error(Error::StsNotImplemented, "Unsupported normalization mode"); + + auto input_wrapper = inputs[0].dynamicCast(); + auto input_shape = input_wrapper->getShape(); + + NormalizeConfiguration config; + config.input_shape.assign(std::begin(input_shape), std::end(input_shape)); + config.axis_start = clamp(startAxis, input_shape.size()); + config.axis_end = clamp(endAxis, input_shape.size()) + 1; /* +1 because NormalizeOp follows [start, end) convention */ + config.norm = pnorm; + config.eps = epsilon; + + const auto& weightsMat = blobs.empty() ? Mat() : blobs[0]; + return make_cuda_node(preferableTarget, std::move(context->stream), weightsMat, config); + } +#endif + + private: int startAxis, endAxis; }; diff --git a/modules/dnn/src/layers/permute_layer.cpp b/modules/dnn/src/layers/permute_layer.cpp index 8624740e7c..eac279f06d 100644 --- a/modules/dnn/src/layers/permute_layer.cpp +++ b/modules/dnn/src/layers/permute_layer.cpp @@ -381,27 +381,6 @@ public: } } -#ifdef HAVE_CUDA - Ptr initCUDA( - void *context_, - const std::vector>& inputs, - const std::vector>& outputs - ) override - { - auto context = reinterpret_cast(context_); - return make_cuda_node(preferableTarget, std::move(context->stream), _order); - } -#endif - - virtual Ptr initVkCom(const std::vector > &input) CV_OVERRIDE - { -#ifdef HAVE_VULKAN - CV_Assert(!_order.empty()); - std::shared_ptr op(new vkcom::OpPermute(_order)); - return Ptr(new VkComBackendNode(input, op)); -#endif // HAVE_VULKAN - return Ptr(); - } #ifdef HAVE_DNN_IE_NN_BUILDER_2019 virtual Ptr initInfEngine(const std::vector >&) CV_OVERRIDE @@ -412,6 +391,7 @@ public: } #endif // HAVE_DNN_IE_NN_BUILDER_2019 + #ifdef HAVE_DNN_NGRAPH virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE @@ -424,6 +404,30 @@ public: } #endif // HAVE_DNN_NGRAPH + +#ifdef HAVE_CUDA + Ptr initCUDA( + void *context_, + const std::vector>& inputs, + const std::vector>& outputs + ) override + { + auto context = reinterpret_cast(context_); + return make_cuda_node(preferableTarget, std::move(context->stream), _order); + } +#endif + + +#ifdef HAVE_VULKAN + virtual Ptr initVkCom(const std::vector > &input) CV_OVERRIDE + { + CV_Assert(!_order.empty()); + std::shared_ptr op(new vkcom::OpPermute(_order)); + return Ptr(new VkComBackendNode(input, op)); + } +#endif // HAVE_VULKAN + + size_t _count; std::vector _order; diff --git a/modules/dnn/src/layers/pooling_layer.cpp b/modules/dnn/src/layers/pooling_layer.cpp index 8ed3a11a21..a932f04816 100644 --- a/modules/dnn/src/layers/pooling_layer.cpp +++ b/modules/dnn/src/layers/pooling_layer.cpp @@ -189,7 +189,7 @@ public: return type == MAX || type == AVE || type == ROI; } #ifdef HAVE_DNN_IE_NN_BUILDER_2019 - else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { if (computeMaxIdx) return false; @@ -207,11 +207,11 @@ public: return type != STOCHASTIC; } #endif - else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) { return !computeMaxIdx && type != STOCHASTIC; } - else if (backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE || backendId == DNN_BACKEND_VKCOM) + if (backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE || backendId == DNN_BACKEND_VKCOM) { if (kernel_size.size() == 3) return (backendId == DNN_BACKEND_OPENCV && preferableTarget == DNN_TARGET_CPU); @@ -409,9 +409,10 @@ public: } #endif + +#ifdef HAVE_VULKAN virtual Ptr initVkCom(const std::vector > &inputs) CV_OVERRIDE { -#ifdef HAVE_VULKAN int padding_mode; vkcom::PoolType pool_type; int filter_size[2] = {kernel.height, kernel.width}; @@ -440,9 +441,9 @@ public: stride_size, padding_mode, pool_type, avePoolPaddedArea)); return Ptr(new VkComBackendNode(inputs, op)); -#endif - return Ptr(); } +#endif + virtual Ptr initHalide(const std::vector > &inputs) CV_OVERRIDE { @@ -503,47 +504,46 @@ public: #endif // HAVE_DNN_IE_NN_BUILDER_2019 - #ifdef HAVE_DNN_NGRAPH -virtual Ptr initNgraph(const std::vector >& inputs, - const std::vector >& nodes) CV_OVERRIDE -{ - CV_Assert_N((inputs.size() == 1 && (type == MAX || type == AVE)) || inputs.size() == 2, nodes.size() == inputs.size()); - auto& ieInpNode = nodes[0].dynamicCast()->node; + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + CV_Assert_N((inputs.size() == 1 && (type == MAX || type == AVE)) || inputs.size() == 2, nodes.size() == inputs.size()); + auto& ieInpNode = nodes[0].dynamicCast()->node; - ngraph::op::PadType pad_type = ngraph::op::PadType::EXPLICIT; - if (!padMode.empty()) - pad_type = padMode == "VALID" ? ngraph::op::PadType::VALID : ngraph::op::PadType::SAME_UPPER; + ngraph::op::PadType pad_type = ngraph::op::PadType::EXPLICIT; + if (!padMode.empty()) + pad_type = padMode == "VALID" ? ngraph::op::PadType::VALID : ngraph::op::PadType::SAME_UPPER; - auto rounding_type = ceilMode ? ngraph::op::RoundingType::CEIL : ngraph::op::RoundingType::FLOOR; - if (type == AVE) { - auto exclude_pad = !avePoolPaddedArea; - auto ave_pool = std::make_shared(ieInpNode, ngraph::Strides(strides), - ngraph::Shape(pads_begin), ngraph::Shape(pads_end), ngraph::Shape(kernel_size), - exclude_pad, rounding_type, pad_type); - return Ptr(new InfEngineNgraphNode(ave_pool)); + auto rounding_type = ceilMode ? ngraph::op::RoundingType::CEIL : ngraph::op::RoundingType::FLOOR; + if (type == AVE) { + auto exclude_pad = !avePoolPaddedArea; + auto ave_pool = std::make_shared(ieInpNode, ngraph::Strides(strides), + ngraph::Shape(pads_begin), ngraph::Shape(pads_end), ngraph::Shape(kernel_size), + exclude_pad, rounding_type, pad_type); + return Ptr(new InfEngineNgraphNode(ave_pool)); + } + else if (type == MAX) { + auto max_pool = std::make_shared(ieInpNode, ngraph::Strides(strides), + ngraph::Shape(pads_begin), ngraph::Shape(pads_end), ngraph::Shape(kernel_size), + rounding_type, pad_type); + return Ptr(new InfEngineNgraphNode(max_pool)); + } + else if (type == ROI) { + auto& coords = nodes[1].dynamicCast()->node; + auto roi = std::make_shared(ieInpNode, coords, + ngraph::Shape{(size_t)pooledSize.height, (size_t)pooledSize.width}, spatialScale, "max"); + return Ptr(new InfEngineNgraphNode(roi)); + } + else if (type == PSROI) { + auto& coords = nodes[1].dynamicCast()->node; + auto psroi = std::make_shared(ieInpNode, coords, + (size_t)psRoiOutChannels, (size_t)pooledSize.width, spatialScale, 1, 1, "average"); + return Ptr(new InfEngineNgraphNode(psroi)); + } + else + CV_Error(Error::StsNotImplemented, "Unsupported pooling type"); } - else if (type == MAX) { - auto max_pool = std::make_shared(ieInpNode, ngraph::Strides(strides), - ngraph::Shape(pads_begin), ngraph::Shape(pads_end), ngraph::Shape(kernel_size), - rounding_type, pad_type); - return Ptr(new InfEngineNgraphNode(max_pool)); - } - else if (type == ROI) { - auto& coords = nodes[1].dynamicCast()->node; - auto roi = std::make_shared(ieInpNode, coords, - ngraph::Shape{(size_t)pooledSize.height, (size_t)pooledSize.width}, spatialScale, "max"); - return Ptr(new InfEngineNgraphNode(roi)); - } - else if (type == PSROI) { - auto& coords = nodes[1].dynamicCast()->node; - auto psroi = std::make_shared(ieInpNode, coords, - (size_t)psRoiOutChannels, (size_t)pooledSize.width, spatialScale, 1, 1, "average"); - return Ptr(new InfEngineNgraphNode(psroi)); - } - else - CV_Error(Error::StsNotImplemented, "Unsupported pooling type"); -} #endif // HAVE_DNN_NGRAPH diff --git a/modules/dnn/src/layers/prior_box_layer.cpp b/modules/dnn/src/layers/prior_box_layer.cpp index 053e6dabdb..c06065d566 100644 --- a/modules/dnn/src/layers/prior_box_layer.cpp +++ b/modules/dnn/src/layers/prior_box_layer.cpp @@ -504,56 +504,6 @@ public: } } -#ifdef HAVE_CUDA - Ptr initCUDA( - void *context_, - const std::vector>& inputs, - const std::vector>& outputs - ) override - { - auto context = reinterpret_cast(context_); - - auto feature_map_wrapper = inputs[0].dynamicCast(); - auto feature_map_shape = feature_map_wrapper->getShape(); - - auto image_wrapper = inputs[1].dynamicCast(); - auto image_shape = image_wrapper->getShape(); - - PriorBoxConfiguration config; - config.feature_map_width = feature_map_shape.rbegin()[0]; - config.feature_map_height = feature_map_shape.rbegin()[1]; - config.image_width = image_shape.rbegin()[0]; - config.image_height = image_shape.rbegin()[1]; - - config.num_priors = _numPriors; - config.box_widths = _boxWidths; - config.box_heights = _boxHeights; - config.offsets_x = _offsetsX; - config.offsets_y = _offsetsY; - config.stepX = _stepX; - config.stepY = _stepY; - - config.variance = _variance; - - config.clip = _clip; - config.normalize = _bboxesNormalized; - - return make_cuda_node(preferableTarget, std::move(context->stream), config); - } -#endif - - virtual Ptr initVkCom(const std::vector > &input) CV_OVERRIDE - { -#ifdef HAVE_VULKAN - std::shared_ptr op(new vkcom::OpPriorBox(_stepX, _stepY, - _clip, _numPriors, - _variance, _offsetsX, - _offsetsY, _boxWidths, - _boxHeights)); - return Ptr(new VkComBackendNode(input, op)); -#endif // HAVE_VULKAN - return Ptr(); - } #ifdef HAVE_DNN_IE_NN_BUILDER_2019 virtual Ptr initInfEngine(const std::vector >&) CV_OVERRIDE @@ -617,6 +567,7 @@ public: } #endif // HAVE_DNN_IE_NN_BUILDER_2019 + #ifdef HAVE_DNN_NGRAPH virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE { @@ -679,6 +630,58 @@ public: #endif // HAVE_DNN_NGRAPH +#ifdef HAVE_CUDA + Ptr initCUDA( + void *context_, + const std::vector>& inputs, + const std::vector>& outputs + ) override + { + auto context = reinterpret_cast(context_); + + auto feature_map_wrapper = inputs[0].dynamicCast(); + auto feature_map_shape = feature_map_wrapper->getShape(); + + auto image_wrapper = inputs[1].dynamicCast(); + auto image_shape = image_wrapper->getShape(); + + PriorBoxConfiguration config; + config.feature_map_width = feature_map_shape.rbegin()[0]; + config.feature_map_height = feature_map_shape.rbegin()[1]; + config.image_width = image_shape.rbegin()[0]; + config.image_height = image_shape.rbegin()[1]; + + config.num_priors = _numPriors; + config.box_widths = _boxWidths; + config.box_heights = _boxHeights; + config.offsets_x = _offsetsX; + config.offsets_y = _offsetsY; + config.stepX = _stepX; + config.stepY = _stepY; + + config.variance = _variance; + + config.clip = _clip; + config.normalize = _bboxesNormalized; + + return make_cuda_node(preferableTarget, std::move(context->stream), config); + } +#endif + + +#ifdef HAVE_VULKAN + virtual Ptr initVkCom(const std::vector > &input) CV_OVERRIDE + { + std::shared_ptr op(new vkcom::OpPriorBox(_stepX, _stepY, + _clip, _numPriors, + _variance, _offsetsX, + _offsetsY, _boxWidths, + _boxHeights)); + return Ptr(new VkComBackendNode(input, op)); + } +#endif // HAVE_VULKAN + + virtual int64 getFLOPS(const std::vector &inputs, const std::vector &outputs) const CV_OVERRIDE { diff --git a/modules/dnn/src/layers/reorg_layer.cpp b/modules/dnn/src/layers/reorg_layer.cpp index 9764088aa1..df76eb6edf 100644 --- a/modules/dnn/src/layers/reorg_layer.cpp +++ b/modules/dnn/src/layers/reorg_layer.cpp @@ -193,6 +193,28 @@ public: permute->forward(inputs, outputs, internals_arr); } + +#ifdef HAVE_DNN_IE_NN_BUILDER_2019 + virtual Ptr initInfEngine(const std::vector >&) CV_OVERRIDE + { + InferenceEngine::Builder::ReorgYoloLayer ieLayer(name); + ieLayer.setStride(reorgStride); + return Ptr(new InfEngineBackendNode(ieLayer)); + } +#endif // HAVE_DNN_IE_NN_BUILDER_2019 + + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector > &inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto& ieInpNode = nodes[0].dynamicCast()->node; + auto reorg = std::make_shared(ieInpNode, ngraph::Strides{(size_t)reorgStride}); + return Ptr(new InfEngineNgraphNode(reorg)); + } +#endif // HAVE_DNN_NGRAPH + + #ifdef HAVE_CUDA Ptr initCUDA( void *context_, @@ -205,24 +227,6 @@ public: } #endif -#ifdef HAVE_DNN_IE_NN_BUILDER_2019 - virtual Ptr initInfEngine(const std::vector >&) CV_OVERRIDE - { - InferenceEngine::Builder::ReorgYoloLayer ieLayer(name); - ieLayer.setStride(reorgStride); - return Ptr(new InfEngineBackendNode(ieLayer)); - } -#endif // HAVE_DNN_IE_NN_BUILDER_2019 - -#ifdef HAVE_DNN_NGRAPH - virtual Ptr initNgraph(const std::vector > &inputs, - const std::vector >& nodes) CV_OVERRIDE - { - auto& ieInpNode = nodes[0].dynamicCast()->node; - auto reorg = std::make_shared(ieInpNode, ngraph::Strides{(size_t)reorgStride}); - return Ptr(new InfEngineNgraphNode(reorg)); - } -#endif // HAVE_DNN_NGRAPH virtual int64 getFLOPS(const std::vector &inputs, const std::vector &outputs) const CV_OVERRIDE diff --git a/modules/dnn/src/layers/reshape_layer.cpp b/modules/dnn/src/layers/reshape_layer.cpp index 62774dbe27..dbea5d55f4 100644 --- a/modules/dnn/src/layers/reshape_layer.cpp +++ b/modules/dnn/src/layers/reshape_layer.cpp @@ -267,17 +267,6 @@ public: } } -#ifdef HAVE_CUDA - Ptr initCUDA( - void *context_, - const std::vector>& inputs, - const std::vector>& outputs - ) override - { - auto context = reinterpret_cast(context_); - return make_cuda_node(preferableTarget, std::move(context->stream)); - } -#endif #ifdef HAVE_DNN_IE_NN_BUILDER_2019 virtual Ptr initInfEngine(const std::vector >& inputs) CV_OVERRIDE @@ -289,6 +278,7 @@ public: } #endif // HAVE_DNN_IE_NN_BUILDER_2019 + #ifdef HAVE_DNN_NGRAPH virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE @@ -304,6 +294,20 @@ public: } #endif // HAVE_DNN_NGRAPH + +#ifdef HAVE_CUDA + Ptr initCUDA( + void *context_, + const std::vector>& inputs, + const std::vector>& outputs + ) override + { + auto context = reinterpret_cast(context_); + return make_cuda_node(preferableTarget, std::move(context->stream)); + } +#endif + + private: std::vector outShapes; }; diff --git a/modules/dnn/src/layers/resize_layer.cpp b/modules/dnn/src/layers/resize_layer.cpp index e29b953daa..091a47b7dd 100644 --- a/modules/dnn/src/layers/resize_layer.cpp +++ b/modules/dnn/src/layers/resize_layer.cpp @@ -170,26 +170,6 @@ public: CV_Error(Error::StsNotImplemented, "Unknown interpolation: " + interpolation); } -#ifdef HAVE_CUDA - Ptr initCUDA( - void *context_, - const std::vector>& inputs, - const std::vector>& outputs - ) override - { - auto context = reinterpret_cast(context_); - - cuda4dnn::InterpolationType itype; - if (interpolation == "nearest") - itype = InterpolationType::NEAREST_NEIGHBOUR; - else if (interpolation == "bilinear") - itype = InterpolationType::BILINEAR; - else - CV_Error(Error::StsNotImplemented, "Requested interpolation mode is not available in resize layer."); - - return make_cuda_node(preferableTarget, std::move(context->stream), itype, scaleHeight, scaleWidth); - } -#endif #ifdef HAVE_DNN_IE_NN_BUILDER_2019 virtual Ptr initInfEngine(const std::vector >&) CV_OVERRIDE @@ -251,6 +231,29 @@ public: } #endif // HAVE_DNN_NGRAPH + +#ifdef HAVE_CUDA + Ptr initCUDA( + void *context_, + const std::vector>& inputs, + const std::vector>& outputs + ) override + { + auto context = reinterpret_cast(context_); + + cuda4dnn::InterpolationType itype; + if (interpolation == "nearest") + itype = InterpolationType::NEAREST_NEIGHBOUR; + else if (interpolation == "bilinear") + itype = InterpolationType::BILINEAR; + else + CV_Error(Error::StsNotImplemented, "Requested interpolation mode is not available in resize layer."); + + return make_cuda_node(preferableTarget, std::move(context->stream), itype, scaleHeight, scaleWidth); + } +#endif + + protected: int outWidth, outHeight; const int zoomFactorWidth, zoomFactorHeight; diff --git a/modules/dnn/src/layers/scale_layer.cpp b/modules/dnn/src/layers/scale_layer.cpp index f316d94fae..bc74e78a56 100644 --- a/modules/dnn/src/layers/scale_layer.cpp +++ b/modules/dnn/src/layers/scale_layer.cpp @@ -52,7 +52,7 @@ public: { std::vector inputs; inputs_arr.getMatVector(inputs); - hasWeights = blobs.size() == 2 || (blobs.size() == 1 && !hasBias); + hasWeights = blobs.size() == 2 || (blobs.size() <= 1 && !hasBias); CV_Assert((inputs.size() == 2 && blobs.empty()) || blobs.size() == (int)hasWeights + (int)hasBias); } @@ -86,10 +86,9 @@ public: Mat &outBlob = outputs[0]; // There is a mode when we multiply a first blob by a second one // instead of trainable weights. - Mat weights = blobs.empty() ? inputs[1] : (hasWeights ? blobs[0] : Mat()); - Mat bias = hasBias ? blobs.back().reshape(1, 1) : Mat(); - if (!weights.empty()) - weights = weights.reshape(1, 1); + Mat weights = hasWeights ? (blobs.empty() ? inputs[1] : blobs[0]).reshape(1, 1) : Mat();; + Mat bias = hasBias ? (blobs.empty() ? inputs[1] : blobs.back()).reshape(1, 1) : Mat(); + MatShape inpShape = shape(inpBlob); const int numWeights = !weights.empty() ? weights.total() : bias.total(); CV_Assert(numWeights != 0); @@ -259,28 +258,40 @@ public: #ifdef HAVE_DNN_NGRAPH virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE { - CV_Assert(!blobs.empty()); - const size_t numChannels = blobs[0].total(); - auto ieInpNode = nodes[0].dynamicCast()->node; + auto ieInpNode0 = nodes[0].dynamicCast()->node; + auto ieInpNode1 = nodes.size() > 1 ? nodes[1].dynamicCast()->node : nullptr; - std::vector shape(ieInpNode->get_shape().size(), 1); + size_t numChannels = 1; + if (blobs.empty()) + for (const size_t& dim : ieInpNode1->get_shape()) + numChannels *= dim; + else + numChannels = blobs[0].total(); + + std::vector shape(ieInpNode0->get_shape().size(), 1); int cAxis = clamp(axis, shape.size()); shape[cAxis] = numChannels; - auto node = ieInpNode; + auto node = ieInpNode0; if (hasWeights) { - auto weight = std::make_shared(ngraph::element::f32, - ngraph::Shape(shape), blobs[0].data); + auto weight = blobs.empty() ? ieInpNode1 : + std::make_shared(ngraph::element::f32, ngraph::Shape(shape), blobs[0].data); + node = std::make_shared(node, weight, ngraph::op::AutoBroadcastType::NUMPY); } if (hasBias || !hasWeights) { - auto bias = hasBias ? - std::make_shared(ngraph::element::f32, - ngraph::Shape(shape), blobs.back().data) : - std::make_shared(ngraph::element::f32, - ngraph::Shape(shape), std::vector(numChannels, 0).data()); + std::shared_ptr bias; + if (hasBias) + { + bias = blobs.empty() ? ieInpNode1 : + std::make_shared(ngraph::element::f32, + ngraph::Shape(shape), blobs.back().data); + } + else + bias = std::make_shared(ngraph::element::f32, + ngraph::Shape(shape), std::vector(numChannels, 0).data()); node = std::make_shared(node, bias, ngraph::op::AutoBroadcastType::NUMPY); } return Ptr(new InfEngineNgraphNode(node)); @@ -289,8 +300,8 @@ public: void getScaleShift(Mat& scale, Mat& shift) const CV_OVERRIDE { - scale = hasWeights ? blobs[0] : Mat(); - shift = hasBias ? blobs.back() : Mat(); + scale = (hasWeights && !blobs.empty()) ? blobs[0] : Mat(); + shift = (hasBias && !blobs.empty()) ? blobs.back() : Mat(); } virtual int64 getFLOPS(const std::vector &inputs, diff --git a/modules/dnn/src/layers/slice_layer.cpp b/modules/dnn/src/layers/slice_layer.cpp index 80d3d8668b..701e64f953 100644 --- a/modules/dnn/src/layers/slice_layer.cpp +++ b/modules/dnn/src/layers/slice_layer.cpp @@ -273,27 +273,6 @@ public: } } -#ifdef HAVE_CUDA - Ptr initCUDA( - void *context_, - const std::vector>& inputs, - const std::vector>& outputs - ) override - { - auto context = reinterpret_cast(context_); - - std::vector> offsets; - for (const auto& ranges : sliceRanges) - { - std::vector offsets_i; - for (const auto& range : ranges) - offsets_i.push_back(range.start); - offsets.push_back(std::move(offsets_i)); - } - - return make_cuda_node(preferableTarget, std::move(context->stream), std::move(offsets)); - } -#endif #ifdef HAVE_DNN_IE_NN_BUILDER_2019 #if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2019R1) @@ -352,6 +331,7 @@ public: #endif #endif + #ifdef HAVE_DNN_NGRAPH virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE @@ -381,6 +361,29 @@ public: } #endif // HAVE_DNN_NGRAPH + +#ifdef HAVE_CUDA + Ptr initCUDA( + void *context_, + const std::vector>& inputs, + const std::vector>& outputs + ) override + { + auto context = reinterpret_cast(context_); + + std::vector> offsets; + for (const auto& ranges : sliceRanges) + { + std::vector offsets_i; + for (const auto& range : ranges) + offsets_i.push_back(range.start); + offsets.push_back(std::move(offsets_i)); + } + + return make_cuda_node(preferableTarget, std::move(context->stream), std::move(offsets)); + } +#endif + }; class CropLayerImpl CV_FINAL : public SliceLayerImpl diff --git a/modules/dnn/src/onnx/onnx_importer.cpp b/modules/dnn/src/onnx/onnx_importer.cpp index 0c8fdf3833..714d4bfd9a 100644 --- a/modules/dnn/src/onnx/onnx_importer.cpp +++ b/modules/dnn/src/onnx/onnx_importer.cpp @@ -427,24 +427,57 @@ void ONNXImporter::populateNet(Net dstNet) } layerParams.type = "Slice"; } - else if (layer_type == "Add" || layer_type == "Sum") + else if (layer_type == "Add" || layer_type == "Sum" || layer_type == "Sub") { + bool isSub = layer_type == "Sub"; + CV_CheckEQ(node_proto.input_size(), 2, ""); if (layer_id.find(node_proto.input(1)) == layer_id.end()) { Mat blob = getBlob(node_proto, constBlobs, 1); blob = blob.reshape(1, 1); if (blob.total() == 1) { layerParams.type = "Power"; - layerParams.set("shift", blob.at(0)); + layerParams.set("shift", (isSub ? -1 : 1) * blob.at(0)); } else { layerParams.type = "Scale"; layerParams.set("bias_term", true); - layerParams.blobs.push_back(blob); + layerParams.blobs.push_back((isSub ? -1 : 1) * blob); } } - else { + else if (outShapes[node_proto.input(0)] == outShapes[node_proto.input(1)]) + { layerParams.type = "Eltwise"; + if (isSub) + { + static float subCoeffs[] = {1.f, -1.f}; + layerParams.set("coeff", DictValue::arrayReal(subCoeffs, 2)); + } + } + else + { + if (isSub) + { + LayerParams powerParams; + powerParams.name = layerParams.name + "/neg"; + powerParams.type = "Power"; + powerParams.set("scale", -1); + + //Create Power layer + int id = dstNet.addLayer(powerParams.name, powerParams.type, powerParams); + //Connect to input + layerId = layer_id.find(node_proto.input(1)); + CV_Assert(layerId != layer_id.end()); + dstNet.connect(layerId->second.layerId, layerId->second.outputId, id, 0); + //Add shape + layer_id.insert(std::make_pair(powerParams.name, LayerInfo(id, 0))); + outShapes[powerParams.name] = outShapes[node_proto.input(1)]; + + //Replace input to Power + node_proto.set_input(1, powerParams.name); + } + layerParams.type = "Scale"; + layerParams.set("bias_term", true); } } else if (layer_type == "Max") @@ -452,19 +485,6 @@ void ONNXImporter::populateNet(Net dstNet) layerParams.type = "Eltwise"; layerParams.set("operation", "max"); } - else if (layer_type == "Sub") - { - Mat blob = getBlob(node_proto, constBlobs, 1); - if (blob.total() == 1) { - layerParams.type = "Power"; - layerParams.set("shift", -blob.at(0)); - } - else { - layerParams.type = "Scale"; - layerParams.set("has_bias", true); - layerParams.blobs.push_back(-1.0f * blob.reshape(1, 1)); - } - } else if (layer_type == "Neg") { layerParams.type = "Power"; @@ -643,10 +663,35 @@ void ONNXImporter::populateNet(Net dstNet) layerParams.type = "Scale"; } } - else { + else if (outShapes[node_proto.input(0)] == outShapes[node_proto.input(1)]) + { layerParams.type = "Eltwise"; layerParams.set("operation", isDiv ? "div" : "prod"); } + else + { + if (isDiv) + { + LayerParams powerParams; + powerParams.name = layerParams.name + "/inv"; + powerParams.type = "Power"; + powerParams.set("power", -1); + + //Create Power layer + int id = dstNet.addLayer(powerParams.name, powerParams.type, powerParams); + //Connect to input + layerId = layer_id.find(node_proto.input(1)); + CV_Assert(layerId != layer_id.end()); + dstNet.connect(layerId->second.layerId, layerId->second.outputId, id, 0); + //Add shape + layer_id.insert(std::make_pair(powerParams.name, LayerInfo(id, 0))); + outShapes[powerParams.name] = outShapes[node_proto.input(1)]; + + //Replace input to Power + node_proto.set_input(1, powerParams.name); + } + layerParams.type = "Scale"; + } if (!haveVariables) { diff --git a/modules/dnn/test/test_onnx_importer.cpp b/modules/dnn/test/test_onnx_importer.cpp index 3e8c67f186..c5c40d957c 100644 --- a/modules/dnn/test/test_onnx_importer.cpp +++ b/modules/dnn/test/test_onnx_importer.cpp @@ -32,29 +32,33 @@ public: void testONNXModels(const String& basename, const Extension ext = npy, const double l1 = 0, const float lInf = 0, const bool useSoftmax = false, - bool checkNoFallbacks = true) + bool checkNoFallbacks = true, int numInps = 1) { String onnxmodel = _tf("models/" + basename + ".onnx", required); - Mat inp, ref; + std::vector inps(numInps); + Mat ref; if (ext == npy) { - inp = blobFromNPY(_tf("data/input_" + basename + ".npy")); + for (int i = 0; i < numInps; ++i) + inps[i] = blobFromNPY(_tf("data/input_" + basename + (numInps > 1 ? format("_%d", i) : "") + ".npy")); ref = blobFromNPY(_tf("data/output_" + basename + ".npy")); } else if (ext == pb) { - inp = readTensorFromONNX(_tf("data/input_" + basename + ".pb")); + for (int i = 0; i < numInps; ++i) + inps[i] = readTensorFromONNX(_tf("data/input_" + basename + (numInps > 1 ? format("_%d", i) : "") + ".pb")); ref = readTensorFromONNX(_tf("data/output_" + basename + ".pb")); } else CV_Error(Error::StsUnsupportedFormat, "Unsupported extension"); - checkBackend(&inp, &ref); + checkBackend(&inps[0], &ref); Net net = readNetFromONNX(onnxmodel); ASSERT_FALSE(net.empty()); net.setPreferableBackend(backend); net.setPreferableTarget(target); - net.setInput(inp); + for (int i = 0; i < numInps; ++i) + net.setInput(inps[i], numInps > 1 ? format("%d", i) : ""); Mat out = net.forward(""); if (useSoftmax) @@ -352,25 +356,14 @@ TEST_P(Test_ONNX_layers, ResizeUnfused) TEST_P(Test_ONNX_layers, MultyInputs) { - const String model = _tf("models/multy_inputs.onnx"); + testONNXModels("multy_inputs", npy, 0, 0, false, true, 2); +} - Net net = readNetFromONNX(model); - ASSERT_FALSE(net.empty()); - - net.setPreferableBackend(backend); - net.setPreferableTarget(target); - - Mat inp1 = blobFromNPY(_tf("data/input_multy_inputs_0.npy")); - Mat inp2 = blobFromNPY(_tf("data/input_multy_inputs_1.npy")); - Mat ref = blobFromNPY(_tf("data/output_multy_inputs.npy")); - checkBackend(&inp1, &ref); - - net.setInput(inp1, "0"); - net.setInput(inp2, "1"); - Mat out = net.forward(); - - normAssert(ref, out, "", default_l1, default_lInf); - expectNoFallbacksFromIE(net); +TEST_P(Test_ONNX_layers, Broadcast) +{ + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + testONNXModels("channel_broadcast", npy, 0, 0, false, true, 2); } TEST_P(Test_ONNX_layers, Div) diff --git a/modules/imgcodecs/src/grfmt_jpeg.cpp b/modules/imgcodecs/src/grfmt_jpeg.cpp index d60bbadf78..cbc1bedaee 100644 --- a/modules/imgcodecs/src/grfmt_jpeg.cpp +++ b/modules/imgcodecs/src/grfmt_jpeg.cpp @@ -75,6 +75,17 @@ extern "C" { #include "jpeglib.h" } +#ifndef CV_MANUAL_JPEG_STD_HUFF_TABLES + #if defined(LIBJPEG_TURBO_VERSION_NUMBER) && LIBJPEG_TURBO_VERSION_NUMBER >= 1003090 + #define CV_MANUAL_JPEG_STD_HUFF_TABLES 0 // libjpeg-turbo handles standard huffman tables itself (jstdhuff.c) + #else + #define CV_MANUAL_JPEG_STD_HUFF_TABLES 1 + #endif +#endif +#if CV_MANUAL_JPEG_STD_HUFF_TABLES == 0 + #undef CV_MANUAL_JPEG_STD_HUFF_TABLES +#endif + namespace cv { @@ -252,6 +263,7 @@ bool JpegDecoder::readHeader() return result; } +#ifdef CV_MANUAL_JPEG_STD_HUFF_TABLES /*************************************************************************** * following code is for supporting MJPEG image files * based on a message of Laurent Pinchart on the video4linux mailing list @@ -385,6 +397,7 @@ int my_jpeg_load_dht (struct jpeg_decompress_struct *info, unsigned char *dht, * end of code for supportting MJPEG image files * based on a message of Laurent Pinchart on the video4linux mailing list ***************************************************************************/ +#endif // CV_MANUAL_JPEG_STD_HUFF_TABLES bool JpegDecoder::readData( Mat& img ) { @@ -400,6 +413,7 @@ bool JpegDecoder::readData( Mat& img ) if( setjmp( jerr->setjmp_buffer ) == 0 ) { +#ifdef CV_MANUAL_JPEG_STD_HUFF_TABLES /* check if this is a mjpeg image format */ if ( cinfo->ac_huff_tbl_ptrs[0] == NULL && cinfo->ac_huff_tbl_ptrs[1] == NULL && @@ -413,6 +427,7 @@ bool JpegDecoder::readData( Mat& img ) cinfo->ac_huff_tbl_ptrs, cinfo->dc_huff_tbl_ptrs ); } +#endif if( color ) {