diff --git a/doc/opencv.bib b/doc/opencv.bib index 4ed9b572ac..aa2bac5062 100644 --- a/doc/opencv.bib +++ b/doc/opencv.bib @@ -180,17 +180,6 @@ volume = {9}, publisher = {Walter de Gruyter} } -@inproceedings{DD02, - author = {Durand, Fr{\'e}do and Dorsey, Julie}, - title = {Fast bilateral filtering for the display of high-dynamic-range images}, - booktitle = {ACM Transactions on Graphics (TOG)}, - year = {2002}, - pages = {257--266}, - volume = {21}, - number = {3}, - publisher = {ACM}, - url = {https://www.researchgate.net/profile/Julie_Dorsey/publication/220184746_Fast_Bilateral_Filtering_for_the_Display_of_High_-_dynamic_-_range_Images/links/54566b000cf26d5090a95f96/Fast-Bilateral-Filtering-for-the-Display-of-High-dynamic-range-Images.pdf} -} @inproceedings{DM03, author = {Drago, Fr{\'e}d{\'e}ric and Myszkowski, Karol and Annen, Thomas and Chiba, Norishige}, title = {Adaptive logarithmic mapping for displaying high contrast scenes}, diff --git a/doc/py_tutorials/py_photo/py_hdr/py_hdr.markdown b/doc/py_tutorials/py_photo/py_hdr/py_hdr.markdown index 497c8a7b34..68788bde65 100644 --- a/doc/py_tutorials/py_photo/py_hdr/py_hdr.markdown +++ b/doc/py_tutorials/py_photo/py_hdr/py_hdr.markdown @@ -85,10 +85,8 @@ we will later have to clip the data in order to avoid overflow. @code{.py} # Tonemap HDR image -tonemap1 = cv.createTonemapDurand(gamma=2.2) +tonemap1 = cv.createTonemap(gamma=2.2) res_debevec = tonemap1.process(hdr_debevec.copy()) -tonemap2 = cv.createTonemapDurand(gamma=1.3) -res_robertson = tonemap2.process(hdr_robertson.copy()) @endcode ### 4. Merge exposures using Mertens fusion @@ -173,5 +171,5 @@ Additional Resources Exercises --------- -1. Try all tonemap algorithms: cv::TonemapDrago, cv::TonemapDurand, cv::TonemapMantiuk and cv::TonemapReinhard +1. Try all tonemap algorithms: cv::TonemapDrago, cv::TonemapMantiuk and cv::TonemapReinhard 2. Try changing the parameters in the HDR calibration and tonemap methods. diff --git a/doc/tutorials/photo/hdr_imaging/hdr_imaging.markdown b/doc/tutorials/photo/hdr_imaging/hdr_imaging.markdown index b8e8b3094b..0bc15fd9b2 100644 --- a/doc/tutorials/photo/hdr_imaging/hdr_imaging.markdown +++ b/doc/tutorials/photo/hdr_imaging/hdr_imaging.markdown @@ -171,7 +171,7 @@ Now it's time to look at the results. Note that HDR image can't be stored in one formats, so we save it to Radiance image (.hdr). Also all HDR imaging functions return results in [0, 1] range so we should multiply result by 255. -You can try other tonemap algorithms: cv::TonemapDrago, cv::TonemapDurand, cv::TonemapMantiuk and cv::TonemapReinhard +You can try other tonemap algorithms: cv::TonemapDrago, cv::TonemapMantiuk and cv::TonemapReinhard You can also adjust the parameters in the HDR calibration and tonemap methods for your own photos. Results diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index b25c7870ed..167af8fa29 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -1333,7 +1333,7 @@ struct InRange_SIMD } }; -#if CV_SIMD128 +#if CV_SIMD template <> struct InRange_SIMD @@ -1342,16 +1342,17 @@ struct InRange_SIMD uchar * dst, int len) const { int x = 0; - const int width = v_uint8x16::nlanes; + const int width = v_uint8::nlanes; for (; x <= len - width; x += width) { - v_uint8x16 values = v_load(src1 + x); - v_uint8x16 low = v_load(src2 + x); - v_uint8x16 high = v_load(src3 + x); + v_uint8 values = vx_load(src1 + x); + v_uint8 low = vx_load(src2 + x); + v_uint8 high = vx_load(src3 + x); v_store(dst + x, (values >= low) & (high >= values)); } + vx_cleanup(); return x; } }; @@ -1363,16 +1364,17 @@ struct InRange_SIMD uchar * dst, int len) const { int x = 0; - const int width = v_int8x16::nlanes; + const int width = v_int8::nlanes; for (; x <= len - width; x += width) { - v_int8x16 values = v_load(src1 + x); - v_int8x16 low = v_load(src2 + x); - v_int8x16 high = v_load(src3 + x); + v_int8 values = vx_load(src1 + x); + v_int8 low = vx_load(src2 + x); + v_int8 high = vx_load(src3 + x); v_store((schar*)(dst + x), (values >= low) & (high >= values)); } + vx_cleanup(); return x; } }; @@ -1384,20 +1386,21 @@ struct InRange_SIMD uchar * dst, int len) const { int x = 0; - const int width = v_uint16x8::nlanes * 2; + const int width = v_uint16::nlanes * 2; for (; x <= len - width; x += width) { - v_uint16x8 values1 = v_load(src1 + x); - v_uint16x8 low1 = v_load(src2 + x); - v_uint16x8 high1 = v_load(src3 + x); + v_uint16 values1 = vx_load(src1 + x); + v_uint16 low1 = vx_load(src2 + x); + v_uint16 high1 = vx_load(src3 + x); - v_uint16x8 values2 = v_load(src1 + x + v_uint16x8::nlanes); - v_uint16x8 low2 = v_load(src2 + x + v_uint16x8::nlanes); - v_uint16x8 high2 = v_load(src3 + x + v_uint16x8::nlanes); + v_uint16 values2 = vx_load(src1 + x + v_uint16::nlanes); + v_uint16 low2 = vx_load(src2 + x + v_uint16::nlanes); + v_uint16 high2 = vx_load(src3 + x + v_uint16::nlanes); v_store(dst + x, v_pack((values1 >= low1) & (high1 >= values1), (values2 >= low2) & (high2 >= values2))); } + vx_cleanup(); return x; } }; @@ -1409,20 +1412,21 @@ struct InRange_SIMD uchar * dst, int len) const { int x = 0; - const int width = (int)v_int16x8::nlanes * 2; + const int width = (int)v_int16::nlanes * 2; for (; x <= len - width; x += width) { - v_int16x8 values1 = v_load(src1 + x); - v_int16x8 low1 = v_load(src2 + x); - v_int16x8 high1 = v_load(src3 + x); + v_int16 values1 = vx_load(src1 + x); + v_int16 low1 = vx_load(src2 + x); + v_int16 high1 = vx_load(src3 + x); - v_int16x8 values2 = v_load(src1 + x + v_int16x8::nlanes); - v_int16x8 low2 = v_load(src2 + x + v_int16x8::nlanes); - v_int16x8 high2 = v_load(src3 + x + v_int16x8::nlanes); + v_int16 values2 = vx_load(src1 + x + v_int16::nlanes); + v_int16 low2 = vx_load(src2 + x + v_int16::nlanes); + v_int16 high2 = vx_load(src3 + x + v_int16::nlanes); v_store((schar*)(dst + x), v_pack((values1 >= low1) & (high1 >= values1), (values2 >= low2) & (high2 >= values2))); } + vx_cleanup(); return x; } }; @@ -1434,20 +1438,21 @@ struct InRange_SIMD uchar * dst, int len) const { int x = 0; - const int width = (int)v_int32x4::nlanes * 2; + const int width = (int)v_int32::nlanes * 2; for (; x <= len - width; x += width) { - v_int32x4 values1 = v_load(src1 + x); - v_int32x4 low1 = v_load(src2 + x); - v_int32x4 high1 = v_load(src3 + x); + v_int32 values1 = vx_load(src1 + x); + v_int32 low1 = vx_load(src2 + x); + v_int32 high1 = vx_load(src3 + x); - v_int32x4 values2 = v_load(src1 + x + v_int32x4::nlanes); - v_int32x4 low2 = v_load(src2 + x + v_int32x4::nlanes); - v_int32x4 high2 = v_load(src3 + x + v_int32x4::nlanes); + v_int32 values2 = vx_load(src1 + x + v_int32::nlanes); + v_int32 low2 = vx_load(src2 + x + v_int32::nlanes); + v_int32 high2 = vx_load(src3 + x + v_int32::nlanes); v_pack_store(dst + x, v_reinterpret_as_u16(v_pack((values1 >= low1) & (high1 >= values1), (values2 >= low2) & (high2 >= values2)))); } + vx_cleanup(); return x; } }; @@ -1459,20 +1464,21 @@ struct InRange_SIMD uchar * dst, int len) const { int x = 0; - const int width = (int)v_float32x4::nlanes * 2; + const int width = (int)v_float32::nlanes * 2; for (; x <= len - width; x += width) { - v_float32x4 values1 = v_load(src1 + x); - v_float32x4 low1 = v_load(src2 + x); - v_float32x4 high1 = v_load(src3 + x); + v_float32 values1 = vx_load(src1 + x); + v_float32 low1 = vx_load(src2 + x); + v_float32 high1 = vx_load(src3 + x); - v_float32x4 values2 = v_load(src1 + x + v_float32x4::nlanes); - v_float32x4 low2 = v_load(src2 + x + v_float32x4::nlanes); - v_float32x4 high2 = v_load(src3 + x + v_float32x4::nlanes); + v_float32 values2 = vx_load(src1 + x + v_float32::nlanes); + v_float32 low2 = vx_load(src2 + x + v_float32::nlanes); + v_float32 high2 = vx_load(src3 + x + v_float32::nlanes); v_pack_store(dst + x, v_pack(v_reinterpret_as_u32((values1 >= low1) & (high1 >= values1)), v_reinterpret_as_u32((values2 >= low2) & (high2 >= values2)))); } + vx_cleanup(); return x; } }; diff --git a/modules/dnn/include/opencv2/dnn/all_layers.hpp b/modules/dnn/include/opencv2/dnn/all_layers.hpp index 5a07be6419..4bede768b2 100644 --- a/modules/dnn/include/opencv2/dnn/all_layers.hpp +++ b/modules/dnn/include/opencv2/dnn/all_layers.hpp @@ -77,6 +77,15 @@ CV__DNN_INLINE_NS_BEGIN static Ptr create(const LayerParams ¶ms); }; + /** + * Constant layer produces the same data blob at an every forward pass. + */ + class CV_EXPORTS ConstLayer : public Layer + { + public: + static Ptr create(const LayerParams ¶ms); + }; + //! LSTM recurrent layer class CV_EXPORTS LSTMLayer : public Layer { diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index b1d81b895b..1e2adef89a 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -88,6 +88,9 @@ CV__DNN_INLINE_NS_BEGIN DNN_TARGET_FPGA }; + CV_EXPORTS std::vector< std::pair > getAvailableBackends(); + CV_EXPORTS std::vector getAvailableTargets(Backend be); + /** @brief This class provides all data needed to initialize layer. * * It includes dictionary with scalar params (which can be read by using Dict interface), diff --git a/modules/dnn/include/opencv2/dnn/version.hpp b/modules/dnn/include/opencv2/dnn/version.hpp index 62f0dd44d6..7d0f125ed2 100644 --- a/modules/dnn/include/opencv2/dnn/version.hpp +++ b/modules/dnn/include/opencv2/dnn/version.hpp @@ -6,7 +6,7 @@ #define OPENCV_DNN_VERSION_HPP /// Use with major OpenCV version only. -#define OPENCV_DNN_API_VERSION 20181121 +#define OPENCV_DNN_API_VERSION 20181205 #if !defined CV_DOXYGEN && !defined CV_DNN_DONT_ADD_INLINE_NS #define CV__DNN_INLINE_NS __CV_CAT(dnn4_v, OPENCV_DNN_API_VERSION) diff --git a/modules/dnn/perf/perf_net.cpp b/modules/dnn/perf/perf_net.cpp index 03d7a233f3..cc95cc58ae 100644 --- a/modules/dnn/perf/perf_net.cpp +++ b/modules/dnn/perf/perf_net.cpp @@ -31,23 +31,6 @@ public: void processNet(std::string weights, std::string proto, std::string halide_scheduler, const Mat& input, const std::string& outputLayer = "") { - if (backend == DNN_BACKEND_OPENCV && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) - { -#if defined(HAVE_OPENCL) - if (!cv::ocl::useOpenCL()) -#endif - { - throw cvtest::SkipTestException("OpenCL is not available/disabled in OpenCV"); - } - } - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - { - if (!checkIETarget(DNN_TARGET_MYRIAD)) - { - throw SkipTestException("Myriad is not available/disabled in OpenCV"); - } - } - randu(input, 0.0f, 1.0f); weights = findDataFile(weights, false); diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index 58717c2a3a..9208b249d0 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -85,6 +85,111 @@ using std::map; using std::make_pair; using std::set; +//================================================================================================== + +class BackendRegistry +{ +public: + typedef std::vector< std::pair > BackendsList; + const BackendsList & getBackends() const { return backends; } + static BackendRegistry & getRegistry() + { + static BackendRegistry impl; + return impl; + } +private: + BackendRegistry() + { +#ifdef HAVE_HALIDE + backends.push_back(std::make_pair(DNN_BACKEND_HALIDE, DNN_TARGET_CPU)); +# ifdef HAVE_OPENCL + if (cv::ocl::useOpenCL()) + backends.push_back(std::make_pair(DNN_BACKEND_HALIDE, DNN_TARGET_OPENCL)); +# endif +#endif // HAVE_HALIDE + +#ifdef HAVE_INF_ENGINE + if (checkIETarget(DNN_TARGET_CPU)) + backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_CPU)); + if (checkIETarget(DNN_TARGET_MYRIAD)) + backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_MYRIAD)); + if (checkIETarget(DNN_TARGET_FPGA)) + backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_FPGA)); +# ifdef HAVE_OPENCL + if (cv::ocl::useOpenCL() && ocl::Device::getDefault().isIntel()) + { + if (checkIETarget(DNN_TARGET_OPENCL)) + backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL)); + if (checkIETarget(DNN_TARGET_OPENCL_FP16)) + backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL_FP16)); + } +# endif +#endif // HAVE_INF_ENGINE + +#ifdef HAVE_OPENCL + if (cv::ocl::useOpenCL()) + { + backends.push_back(std::make_pair(DNN_BACKEND_OPENCV, DNN_TARGET_OPENCL)); + backends.push_back(std::make_pair(DNN_BACKEND_OPENCV, DNN_TARGET_OPENCL_FP16)); + } +#endif + + backends.push_back(std::make_pair(DNN_BACKEND_OPENCV, DNN_TARGET_CPU)); + +#ifdef HAVE_VULKAN + backends.push_back(std::make_pair(DNN_BACKEND_VKCOM, DNN_TARGET_VULKAN)); // TODO Add device check +#endif + } + static inline bool checkIETarget(int target) + { +#ifndef HAVE_INF_ENGINE + return false; +#else + cv::dnn::Net net; + cv::dnn::LayerParams lp; + net.addLayerToPrev("testLayer", "Identity", lp); + net.setPreferableBackend(cv::dnn::DNN_BACKEND_INFERENCE_ENGINE); + net.setPreferableTarget(target); + static int inpDims[] = {1, 2, 3, 4}; + net.setInput(cv::Mat(4, &inpDims[0], CV_32FC1, cv::Scalar(0))); + try + { + net.forward(); + } + catch(...) + { + return false; + } + return true; +#endif + } + + BackendsList backends; +}; + + +std::vector< std::pair > getAvailableBackends() +{ + return BackendRegistry::getRegistry().getBackends(); +} + +std::vector getAvailableTargets(Backend be) +{ + if (be == DNN_BACKEND_DEFAULT) + be = (Backend)PARAM_DNN_BACKEND_DEFAULT; + + std::vector result; + const BackendRegistry::BackendsList all_backends = getAvailableBackends(); + for(BackendRegistry::BackendsList::const_iterator i = all_backends.begin(); i != all_backends.end(); ++i ) + { + if (i->first == be) + result.push_back(i->second); + } + return result; +} + +//================================================================================================== + namespace { typedef std::vector ShapesVec; diff --git a/modules/dnn/src/init.cpp b/modules/dnn/src/init.cpp index 7178456068..4ebded1436 100644 --- a/modules/dnn/src/init.cpp +++ b/modules/dnn/src/init.cpp @@ -112,6 +112,7 @@ void initializeLayerFactory() CV_DNN_REGISTER_LAYER_CLASS(Dropout, BlankLayer); CV_DNN_REGISTER_LAYER_CLASS(Identity, BlankLayer); CV_DNN_REGISTER_LAYER_CLASS(Silence, BlankLayer); + CV_DNN_REGISTER_LAYER_CLASS(Const, ConstLayer); CV_DNN_REGISTER_LAYER_CLASS(Crop, CropLayer); CV_DNN_REGISTER_LAYER_CLASS(Eltwise, EltwiseLayer); diff --git a/modules/dnn/src/layers/const_layer.cpp b/modules/dnn/src/layers/const_layer.cpp new file mode 100644 index 0000000000..339f2ec255 --- /dev/null +++ b/modules/dnn/src/layers/const_layer.cpp @@ -0,0 +1,68 @@ +// 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. + +// Copyright (C) 2018, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. + +#include "../precomp.hpp" +#include "layers_common.hpp" + +#ifdef HAVE_OPENCL +#include "opencl_kernels_dnn.hpp" +#endif + +namespace cv { namespace dnn { + +class ConstLayerImpl CV_FINAL : public ConstLayer +{ +public: + ConstLayerImpl(const LayerParams& params) + { + setParamsFrom(params); + CV_Assert(blobs.size() == 1); + } + + virtual bool getMemoryShapes(const std::vector &inputs, + const int requiredOutputs, + std::vector &outputs, + std::vector &internals) const CV_OVERRIDE + { + CV_Assert(inputs.empty()); + outputs.assign(1, shape(blobs[0])); + return false; + } + +#ifdef HAVE_OPENCL + bool forward_ocl(InputArrayOfArrays inps, OutputArrayOfArrays outs, OutputArrayOfArrays internals) + { + std::vector outputs; + outs.getUMatVector(outputs); + if (outs.depth() == CV_16S) + convertFp16(blobs[0], outputs[0]); + else + blobs[0].copyTo(outputs[0]); + return true; + } +#endif + + void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE + { + CV_TRACE_FUNCTION(); + CV_TRACE_ARG_VALUE(name, "name", name.c_str()); + + CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget), + forward_ocl(inputs_arr, outputs_arr, internals_arr)) + + std::vector outputs; + outputs_arr.getMatVector(outputs); + blobs[0].copyTo(outputs[0]); + } +}; + +Ptr ConstLayer::create(const LayerParams& params) +{ + return Ptr(new ConstLayerImpl(params)); +} + +}} // namespace cv::dnn diff --git a/modules/dnn/src/tensorflow/tf_importer.cpp b/modules/dnn/src/tensorflow/tf_importer.cpp index 237e9750f1..ea88a1aabb 100644 --- a/modules/dnn/src/tensorflow/tf_importer.cpp +++ b/modules/dnn/src/tensorflow/tf_importer.cpp @@ -1266,14 +1266,31 @@ void TFImporter::populateNet(Net dstNet) axis = toNCHW(axis); layerParams.set("axis", axis); - int id = dstNet.addLayer(name, "Concat", layerParams); - layer_id[name] = id; - - + // input(0) or input(n-1) is concat_dim int from = (type == "Concat" ? 1 : 0); int to = (type == "Concat" ? layer.input_size() : layer.input_size() - 1); - // input(0) or input(n-1) is concat_dim + for (int ii = from; ii < to; ii++) + { + Pin inp = parsePin(layer.input(ii)); + if (layer_id.find(inp.name) == layer_id.end()) + { + // There are constant inputs. + LayerParams lp; + lp.name = inp.name; + lp.type = "Const"; + lp.blobs.resize(1); + blobFromTensor(getConstBlob(layer, value_id, ii), lp.blobs.back()); + CV_Assert_N(!lp.blobs[0].empty(), lp.blobs[0].type() == CV_32F); + + int constInpId = dstNet.addLayer(lp.name, lp.type, lp); + layer_id[lp.name] = constInpId; + } + } + + int id = dstNet.addLayer(name, "Concat", layerParams); + layer_id[name] = id; + for (int ii = from; ii < to; ii++) { Pin inp = parsePin(layer.input(ii)); diff --git a/modules/dnn/test/test_caffe_importer.cpp b/modules/dnn/test/test_caffe_importer.cpp index 4ad3d54067..2ed07b301f 100644 --- a/modules/dnn/test/test_caffe_importer.cpp +++ b/modules/dnn/test/test_caffe_importer.cpp @@ -300,10 +300,11 @@ INSTANTIATE_TEST_CASE_P(/**/, Reproducibility_ResNet50, typedef testing::TestWithParam Reproducibility_SqueezeNet_v1_1; TEST_P(Reproducibility_SqueezeNet_v1_1, Accuracy) { + int targetId = GetParam(); + if(targetId == DNN_TARGET_OPENCL_FP16) + throw SkipTestException("This test does not support FP16"); Net net = readNetFromCaffe(findDataFile("dnn/squeezenet_v1.1.prototxt", false), findDataFile("dnn/squeezenet_v1.1.caffemodel", false)); - - int targetId = GetParam(); net.setPreferableBackend(DNN_BACKEND_OPENCV); net.setPreferableTarget(targetId); @@ -324,7 +325,8 @@ TEST_P(Reproducibility_SqueezeNet_v1_1, Accuracy) Mat ref = blobFromNPY(_tf("squeezenet_v1.1_prob.npy")); normAssert(ref, out); } -INSTANTIATE_TEST_CASE_P(/**/, Reproducibility_SqueezeNet_v1_1, availableDnnTargets()); +INSTANTIATE_TEST_CASE_P(/**/, Reproducibility_SqueezeNet_v1_1, + testing::ValuesIn(getAvailableTargets(DNN_BACKEND_OPENCV))); TEST(Reproducibility_AlexNet_fp16, Accuracy) { diff --git a/modules/dnn/test/test_common.hpp b/modules/dnn/test/test_common.hpp index 058a7150cb..21a25168ea 100644 --- a/modules/dnn/test/test_common.hpp +++ b/modules/dnn/test/test_common.hpp @@ -191,30 +191,6 @@ static inline void normAssertDetections(cv::Mat ref, cv::Mat out, const char *co testBoxes, comment, confThreshold, scores_diff, boxes_iou_diff); } -static inline bool checkIETarget(int target) -{ -#ifndef HAVE_INF_ENGINE - return false; -#else - cv::dnn::Net net; - cv::dnn::LayerParams lp; - net.addLayerToPrev("testLayer", "Identity", lp); - net.setPreferableBackend(cv::dnn::DNN_BACKEND_INFERENCE_ENGINE); - net.setPreferableTarget(target); - static int inpDims[] = {1, 2, 3, 4}; - net.setInput(cv::Mat(4, &inpDims[0], CV_32FC1, cv::Scalar(0))); - try - { - net.forward(); - } - catch(...) - { - return false; - } - return true; -#endif -} - static inline bool readFileInMemory(const std::string& filename, std::string& content) { std::ios::openmode mode = std::ios::in | std::ios::binary; @@ -239,52 +215,36 @@ namespace opencv_test { using namespace cv::dnn; static inline -testing::internal::ParamGenerator > dnnBackendsAndTargets( +testing::internal::ParamGenerator< tuple > dnnBackendsAndTargets( bool withInferenceEngine = true, bool withHalide = false, bool withCpuOCV = true, bool withVkCom = true ) { - std::vector > targets; -#ifdef HAVE_HALIDE + std::vector< tuple > targets; + std::vector< Target > available; if (withHalide) { - targets.push_back(make_tuple(DNN_BACKEND_HALIDE, DNN_TARGET_CPU)); -#ifdef HAVE_OPENCL - if (cv::ocl::useOpenCL()) - targets.push_back(make_tuple(DNN_BACKEND_HALIDE, DNN_TARGET_OPENCL)); -#endif + available = getAvailableTargets(DNN_BACKEND_HALIDE); + for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i) + targets.push_back(make_tuple(DNN_BACKEND_HALIDE, *i)); } -#endif -#ifdef HAVE_INF_ENGINE if (withInferenceEngine) { - targets.push_back(make_tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_CPU)); -#ifdef HAVE_OPENCL - if (cv::ocl::useOpenCL() && ocl::Device::getDefault().isIntel()) - { - targets.push_back(make_tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL)); - targets.push_back(make_tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL_FP16)); - } -#endif - if (checkIETarget(DNN_TARGET_MYRIAD)) - targets.push_back(make_tuple(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_MYRIAD)); + available = getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE); + for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i) + targets.push_back(make_tuple(DNN_BACKEND_INFERENCE_ENGINE, *i)); } -#endif - if (withCpuOCV) - targets.push_back(make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU)); -#ifdef HAVE_OPENCL - if (cv::ocl::useOpenCL()) { - targets.push_back(make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_OPENCL)); - targets.push_back(make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_OPENCL_FP16)); + available = getAvailableTargets(DNN_BACKEND_OPENCV); + for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i) + { + if (!withCpuOCV && *i == DNN_TARGET_CPU) + continue; + targets.push_back(make_tuple(DNN_BACKEND_OPENCV, *i)); + } } -#endif -#ifdef HAVE_VULKAN - if (withVkCom) - targets.push_back(make_tuple(DNN_BACKEND_VKCOM, DNN_TARGET_VULKAN)); -#endif if (targets.empty()) // validate at least CPU mode targets.push_back(make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU)); return testing::ValuesIn(targets); @@ -296,21 +256,6 @@ testing::internal::ParamGenerator > dnnBackendsAndTargets namespace opencv_test { using namespace cv::dnn; -static inline -testing::internal::ParamGenerator availableDnnTargets() -{ - static std::vector targets; - if (targets.empty()) - { - targets.push_back(DNN_TARGET_CPU); -#ifdef HAVE_OPENCL - if (cv::ocl::useOpenCL()) - targets.push_back(DNN_TARGET_OPENCL); -#endif - } - return testing::ValuesIn(targets); -} - class DNNTestLayer : public TestWithParam > { public: @@ -339,23 +284,10 @@ public: } } - static void checkBackend(int backend, int target, Mat* inp = 0, Mat* ref = 0) - { - if (backend == DNN_BACKEND_OPENCV && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) - { -#ifdef HAVE_OPENCL - if (!cv::ocl::useOpenCL()) -#endif - { - throw SkipTestException("OpenCL is not available/disabled in OpenCV"); - } - } + static void checkBackend(int backend, int target, Mat* inp = 0, Mat* ref = 0) + { if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) { - if (!checkIETarget(DNN_TARGET_MYRIAD)) - { - throw SkipTestException("Myriad is not available/disabled in OpenCV"); - } #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE < 2018030000 if (inp && ref && inp->size[0] != 1) { diff --git a/modules/dnn/test/test_googlenet.cpp b/modules/dnn/test/test_googlenet.cpp index 37064c35c4..3db0c47997 100644 --- a/modules/dnn/test/test_googlenet.cpp +++ b/modules/dnn/test/test_googlenet.cpp @@ -55,9 +55,11 @@ static std::string _tf(TString filename) typedef testing::TestWithParam Reproducibility_GoogLeNet; TEST_P(Reproducibility_GoogLeNet, Batching) { + const int targetId = GetParam(); + if(targetId == DNN_TARGET_OPENCL_FP16) + throw SkipTestException("This test does not support FP16"); Net net = readNetFromCaffe(findDataFile("dnn/bvlc_googlenet.prototxt", false), findDataFile("dnn/bvlc_googlenet.caffemodel", false)); - int targetId = GetParam(); net.setPreferableBackend(DNN_BACKEND_OPENCV); net.setPreferableTarget(targetId); @@ -84,9 +86,11 @@ TEST_P(Reproducibility_GoogLeNet, Batching) TEST_P(Reproducibility_GoogLeNet, IntermediateBlobs) { + const int targetId = GetParam(); + if(targetId == DNN_TARGET_OPENCL_FP16) + throw SkipTestException("This test does not support FP16"); Net net = readNetFromCaffe(findDataFile("dnn/bvlc_googlenet.prototxt", false), findDataFile("dnn/bvlc_googlenet.caffemodel", false)); - int targetId = GetParam(); net.setPreferableBackend(DNN_BACKEND_OPENCV); net.setPreferableTarget(targetId); @@ -113,9 +117,11 @@ TEST_P(Reproducibility_GoogLeNet, IntermediateBlobs) TEST_P(Reproducibility_GoogLeNet, SeveralCalls) { + const int targetId = GetParam(); + if(targetId == DNN_TARGET_OPENCL_FP16) + throw SkipTestException("This test does not support FP16"); Net net = readNetFromCaffe(findDataFile("dnn/bvlc_googlenet.prototxt", false), findDataFile("dnn/bvlc_googlenet.caffemodel", false)); - int targetId = GetParam(); net.setPreferableBackend(DNN_BACKEND_OPENCV); net.setPreferableTarget(targetId); @@ -143,6 +149,7 @@ TEST_P(Reproducibility_GoogLeNet, SeveralCalls) normAssert(outs[0], ref, "", 1E-4, 1E-2); } -INSTANTIATE_TEST_CASE_P(/**/, Reproducibility_GoogLeNet, availableDnnTargets()); +INSTANTIATE_TEST_CASE_P(/**/, Reproducibility_GoogLeNet, + testing::ValuesIn(getAvailableTargets(DNN_BACKEND_OPENCV))); }} // namespace diff --git a/modules/dnn/test/test_ie_models.cpp b/modules/dnn/test/test_ie_models.cpp index a8404e09a2..db718eb2c5 100644 --- a/modules/dnn/test/test_ie_models.cpp +++ b/modules/dnn/test/test_ie_models.cpp @@ -203,7 +203,8 @@ TEST_P(DNNTestOpenVINO, models) std::map inputsMap; std::map ieOutputsMap, cvOutputsMap; // Single Myriad device cannot be shared across multiple processes. - resetMyriadDevice(); + if (target == DNN_TARGET_MYRIAD) + resetMyriadDevice(); runIE(target, xmlPath, binPath, inputsMap, ieOutputsMap); runCV(target, xmlPath, binPath, inputsMap, cvOutputsMap); @@ -245,27 +246,10 @@ static testing::internal::ParamGenerator intelModels() return ValuesIn(modelsNames); } -static testing::internal::ParamGenerator dnnDLIETargets() -{ - std::vector targets; - targets.push_back(DNN_TARGET_CPU); -#ifdef HAVE_OPENCL - if (cv::ocl::useOpenCL() && ocl::Device::getDefault().isIntel()) - { - targets.push_back(DNN_TARGET_OPENCL); - targets.push_back(DNN_TARGET_OPENCL_FP16); - } -#endif - if (checkIETarget(DNN_TARGET_MYRIAD)) - targets.push_back(DNN_TARGET_MYRIAD); - if (checkIETarget(DNN_TARGET_FPGA)) - targets.push_back(DNN_TARGET_FPGA); - return testing::ValuesIn(targets); -} - -INSTANTIATE_TEST_CASE_P(/**/, DNNTestOpenVINO, Combine( - dnnDLIETargets(), intelModels() -)); +INSTANTIATE_TEST_CASE_P(/**/, + DNNTestOpenVINO, + Combine(testing::ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE)), intelModels()) +); }} #endif // HAVE_INF_ENGINE diff --git a/modules/dnn/test/test_misc.cpp b/modules/dnn/test/test_misc.cpp index 2d8ceef577..fa528b5c4b 100644 --- a/modules/dnn/test/test_misc.cpp +++ b/modules/dnn/test/test_misc.cpp @@ -157,8 +157,6 @@ TEST_P(setInput, normalization) const int target = get<1>(get<3>(GetParam())); const bool kSwapRB = true; - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD && !checkIETarget(DNN_TARGET_MYRIAD)) - throw SkipTestException("Myriad is not available/disabled in OpenCV"); if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16 && dtype != CV_32F) throw SkipTestException(""); if (backend == DNN_BACKEND_VKCOM && dtype != CV_32F) diff --git a/modules/dnn/test/test_tf_importer.cpp b/modules/dnn/test/test_tf_importer.cpp index adb45b86f0..5f944776dc 100644 --- a/modules/dnn/test/test_tf_importer.cpp +++ b/modules/dnn/test/test_tf_importer.cpp @@ -136,6 +136,7 @@ TEST_P(Test_TensorFlow_layers, padding) runTensorFlowNet("padding_same"); runTensorFlowNet("padding_valid"); runTensorFlowNet("spatial_padding"); + runTensorFlowNet("keras_pad_concat"); } TEST_P(Test_TensorFlow_layers, eltwise_add_mul) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index c7d7028bf1..3c529cff64 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -4659,7 +4659,7 @@ LineIterator it2 = it; vector buf(it.count); for(int i = 0; i < it.count; i++, ++it) - buf[i] = *(const Vec3b)*it; + buf[i] = *(const Vec3b*)*it; // alternative way of iterating through the line for(int i = 0; i < it2.count; i++, ++it2) diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 083811971e..55e9661c54 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -376,43 +376,6 @@ results, default value is 0.85. */ CV_EXPORTS_W Ptr createTonemapDrago(float gamma = 1.0f, float saturation = 1.0f, float bias = 0.85f); -/** @brief This algorithm decomposes image into two layers: base layer and detail layer using bilateral filter -and compresses contrast of the base layer thus preserving all the details. - -This implementation uses regular bilateral filter from opencv. - -Saturation enhancement is possible as in ocvTonemapDrago. - -For more information see @cite DD02 . - */ -class CV_EXPORTS_W TonemapDurand : public Tonemap -{ -public: - - CV_WRAP virtual float getSaturation() const = 0; - CV_WRAP virtual void setSaturation(float saturation) = 0; - - CV_WRAP virtual float getContrast() const = 0; - CV_WRAP virtual void setContrast(float contrast) = 0; - - CV_WRAP virtual float getSigmaSpace() const = 0; - CV_WRAP virtual void setSigmaSpace(float sigma_space) = 0; - - CV_WRAP virtual float getSigmaColor() const = 0; - CV_WRAP virtual void setSigmaColor(float sigma_color) = 0; -}; - -/** @brief Creates TonemapDurand object - -@param gamma gamma value for gamma correction. See createTonemap -@param contrast resulting contrast on logarithmic scale, i. e. log(max / min), where max and min -are maximum and minimum luminance values of the resulting image. -@param saturation saturation enhancement value. See createTonemapDrago -@param sigma_space bilateral filter sigma in color space -@param sigma_color bilateral filter sigma in coordinate space - */ -CV_EXPORTS_W Ptr -createTonemapDurand(float gamma = 1.0f, float contrast = 4.0f, float saturation = 1.0f, float sigma_space = 2.0f, float sigma_color = 2.0f); /** @brief This is a global tonemapping operator that models human visual system. diff --git a/modules/photo/src/tonemap.cpp b/modules/photo/src/tonemap.cpp index fd73865d6b..a02c6ad829 100644 --- a/modules/photo/src/tonemap.cpp +++ b/modules/photo/src/tonemap.cpp @@ -193,94 +193,6 @@ Ptr createTonemapDrago(float gamma, float saturation, float bias) return makePtr(gamma, saturation, bias); } -class TonemapDurandImpl CV_FINAL : public TonemapDurand -{ -public: - TonemapDurandImpl(float _gamma, float _contrast, float _saturation, float _sigma_color, float _sigma_space) : - name("TonemapDurand"), - gamma(_gamma), - contrast(_contrast), - saturation(_saturation), - sigma_color(_sigma_color), - sigma_space(_sigma_space) - { - } - - void process(InputArray _src, OutputArray _dst) CV_OVERRIDE - { - CV_INSTRUMENT_REGION(); - - Mat src = _src.getMat(); - CV_Assert(!src.empty()); - _dst.create(src.size(), CV_32FC3); - Mat img = _dst.getMat(); - Ptr linear = createTonemap(1.0f); - linear->process(src, img); - - Mat gray_img; - cvtColor(img, gray_img, COLOR_RGB2GRAY); - Mat log_img; - log_(gray_img, log_img); - Mat map_img; - bilateralFilter(log_img, map_img, -1, sigma_color, sigma_space); - - double min, max; - minMaxLoc(map_img, &min, &max); - float scale = contrast / static_cast(max - min); - exp(map_img * (scale - 1.0f) + log_img, map_img); - log_img.release(); - - mapLuminance(img, img, gray_img, map_img, saturation); - pow(img, 1.0f / gamma, img); - } - - float getGamma() const CV_OVERRIDE { return gamma; } - void setGamma(float val) CV_OVERRIDE { gamma = val; } - - float getSaturation() const CV_OVERRIDE { return saturation; } - void setSaturation(float val) CV_OVERRIDE { saturation = val; } - - float getContrast() const CV_OVERRIDE { return contrast; } - void setContrast(float val) CV_OVERRIDE { contrast = val; } - - float getSigmaColor() const CV_OVERRIDE { return sigma_color; } - void setSigmaColor(float val) CV_OVERRIDE { sigma_color = val; } - - float getSigmaSpace() const CV_OVERRIDE { return sigma_space; } - void setSigmaSpace(float val) CV_OVERRIDE { sigma_space = val; } - - void write(FileStorage& fs) const CV_OVERRIDE - { - writeFormat(fs); - fs << "name" << name - << "gamma" << gamma - << "contrast" << contrast - << "sigma_color" << sigma_color - << "sigma_space" << sigma_space - << "saturation" << saturation; - } - - void read(const FileNode& fn) CV_OVERRIDE - { - FileNode n = fn["name"]; - CV_Assert(n.isString() && String(n) == name); - gamma = fn["gamma"]; - contrast = fn["contrast"]; - sigma_color = fn["sigma_color"]; - sigma_space = fn["sigma_space"]; - saturation = fn["saturation"]; - } - -protected: - String name; - float gamma, contrast, saturation, sigma_color, sigma_space; -}; - -Ptr createTonemapDurand(float gamma, float contrast, float saturation, float sigma_color, float sigma_space) -{ - return makePtr(gamma, contrast, saturation, sigma_color, sigma_space); -} - class TonemapReinhardImpl CV_FINAL : public TonemapReinhard { public: diff --git a/modules/photo/test/test_hdr.cpp b/modules/photo/test/test_hdr.cpp index fd4797fac7..2ac09dbecb 100644 --- a/modules/photo/test/test_hdr.cpp +++ b/modules/photo/test/test_hdr.cpp @@ -105,12 +105,6 @@ TEST(Photo_Tonemap, regression) result.convertTo(result, CV_8UC3, 255); checkEqual(result, expected, 3, "Drago"); - Ptr durand = createTonemapDurand(gamma); - durand->process(img, result); - loadImage(test_path + "durand.png", expected); - result.convertTo(result, CV_8UC3, 255); - checkEqual(result, expected, 3, "Durand"); - Ptr reinhard = createTonemapReinhard(gamma); reinhard->process(img, result); loadImage(test_path + "reinhard.png", expected); diff --git a/modules/stitching/perf/perf_matchers.cpp b/modules/stitching/perf/perf_matchers.cpp index 6065be6ce8..7b3ab6b51b 100644 --- a/modules/stitching/perf/perf_matchers.cpp +++ b/modules/stitching/perf/perf_matchers.cpp @@ -280,7 +280,7 @@ PERF_TEST_P( matchVector, affineBestOf2NearestVectorFeatures, testing::Combine( if (pairwise_matches[i].src_img_idx < 0) continue; - EXPECT_GT(pairwise_matches[i].matches.size(), 200u); + EXPECT_GT(pairwise_matches[i].matches.size(), 150u); EXPECT_FALSE(pairwise_matches[i].H.empty()); ++matches_count; } diff --git a/samples/cpp/tutorial_code/photo/hdr_imaging/hdr_imaging.cpp b/samples/cpp/tutorial_code/photo/hdr_imaging/hdr_imaging.cpp index 492e1524c7..5e8843bcf0 100644 --- a/samples/cpp/tutorial_code/photo/hdr_imaging/hdr_imaging.cpp +++ b/samples/cpp/tutorial_code/photo/hdr_imaging/hdr_imaging.cpp @@ -35,7 +35,7 @@ int main(int argc, char**argv) //! [Tonemap HDR image] Mat ldr; - Ptr tonemap = createTonemapDurand(2.2f); + Ptr tonemap = createTonemap(2.2f); tonemap->process(hdr, ldr); //! [Tonemap HDR image] diff --git a/samples/java/tutorial_code/photo/hdr_imaging/HDRImagingDemo.java b/samples/java/tutorial_code/photo/hdr_imaging/HDRImagingDemo.java index ea201399b8..c6fddfb769 100644 --- a/samples/java/tutorial_code/photo/hdr_imaging/HDRImagingDemo.java +++ b/samples/java/tutorial_code/photo/hdr_imaging/HDRImagingDemo.java @@ -13,7 +13,7 @@ import org.opencv.photo.CalibrateDebevec; import org.opencv.photo.MergeDebevec; import org.opencv.photo.MergeMertens; import org.opencv.photo.Photo; -import org.opencv.photo.TonemapDurand; +import org.opencv.photo.Tonemap; class HDRImaging { public void loadExposureSeq(String path, List images, List times) { @@ -71,7 +71,7 @@ class HDRImaging { //! [Tonemap HDR image] Mat ldr = new Mat(); - TonemapDurand tonemap = Photo.createTonemapDurand(2.2f, 4.0f, 1.0f, 2.0f, 2.0f); + Tonemap tonemap = Photo.createTonemap(2.2f); tonemap.process(hdr, ldr); //! [Tonemap HDR image] diff --git a/samples/python/tutorial_code/photo/hdr_imaging/hdr_imaging.py b/samples/python/tutorial_code/photo/hdr_imaging/hdr_imaging.py index 11243309b9..a5403d3cca 100644 --- a/samples/python/tutorial_code/photo/hdr_imaging/hdr_imaging.py +++ b/samples/python/tutorial_code/photo/hdr_imaging/hdr_imaging.py @@ -40,7 +40,7 @@ hdr = merge_debevec.process(images, times, response) ## [Make HDR image] ## [Tonemap HDR image] -tonemap = cv.createTonemapDurand(2.2) +tonemap = cv.createTonemap(2.2) ldr = tonemap.process(hdr) ## [Tonemap HDR image]