From 3a2f40ac6fa5eb3c2dde9ec0fd20a42d82f12dc9 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 6 Mar 2020 12:52:00 +0000 Subject: [PATCH 1/7] core: don't allow reallocation in add/div/sub/bitwise aug operators --- .../core/include/opencv2/core/operations.hpp | 80 +++++++++---------- modules/core/test/test_operations.cpp | 17 ++++ 2 files changed, 57 insertions(+), 40 deletions(-) diff --git a/modules/core/include/opencv2/core/operations.hpp b/modules/core/include/opencv2/core/operations.hpp index 4a2a6a4468..ef1808a8a1 100644 --- a/modules/core/include/opencv2/core/operations.hpp +++ b/modules/core/include/opencv2/core/operations.hpp @@ -256,21 +256,21 @@ Matx<_Tp, n, l> Matx<_Tp, m, n>::solve(const Matx<_Tp, m, l>& rhs, int method) c template static inline A& operator op (A& a, const Matx<_Tp,m,n>& b) { cvop; return a; } \ template static inline const A& operator op (const A& a, const Matx<_Tp,m,n>& b) { cvop; return a; } -CV_MAT_AUG_OPERATOR (+=, cv::add(a,b,a), Mat, Mat) -CV_MAT_AUG_OPERATOR (+=, cv::add(a,b,a), Mat, Scalar) -CV_MAT_AUG_OPERATOR_T(+=, cv::add(a,b,a), Mat_<_Tp>, Mat) -CV_MAT_AUG_OPERATOR_T(+=, cv::add(a,b,a), Mat_<_Tp>, Scalar) -CV_MAT_AUG_OPERATOR_T(+=, cv::add(a,b,a), Mat_<_Tp>, Mat_<_Tp>) -CV_MAT_AUG_OPERATOR_TN(+=, cv::add(a,Mat(b),a), Mat) -CV_MAT_AUG_OPERATOR_TN(+=, cv::add(a,Mat(b),a), Mat_<_Tp>) +CV_MAT_AUG_OPERATOR (+=, cv::add(a, b, (const Mat&)a), Mat, Mat) +CV_MAT_AUG_OPERATOR (+=, cv::add(a, b, (const Mat&)a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(+=, cv::add(a, b, (const Mat&)a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(+=, cv::add(a, b, (const Mat&)a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(+=, cv::add(a, b, (const Mat&)a), Mat_<_Tp>, Mat_<_Tp>) +CV_MAT_AUG_OPERATOR_TN(+=, cv::add(a, Mat(b), (const Mat&)a), Mat) +CV_MAT_AUG_OPERATOR_TN(+=, cv::add(a, Mat(b), (const Mat&)a), Mat_<_Tp>) -CV_MAT_AUG_OPERATOR (-=, cv::subtract(a,b,a), Mat, Mat) -CV_MAT_AUG_OPERATOR (-=, cv::subtract(a,b,a), Mat, Scalar) -CV_MAT_AUG_OPERATOR_T(-=, cv::subtract(a,b,a), Mat_<_Tp>, Mat) -CV_MAT_AUG_OPERATOR_T(-=, cv::subtract(a,b,a), Mat_<_Tp>, Scalar) -CV_MAT_AUG_OPERATOR_T(-=, cv::subtract(a,b,a), Mat_<_Tp>, Mat_<_Tp>) -CV_MAT_AUG_OPERATOR_TN(-=, cv::subtract(a,Mat(b),a), Mat) -CV_MAT_AUG_OPERATOR_TN(-=, cv::subtract(a,Mat(b),a), Mat_<_Tp>) +CV_MAT_AUG_OPERATOR (-=, cv::subtract(a, b, (const Mat&)a), Mat, Mat) +CV_MAT_AUG_OPERATOR (-=, cv::subtract(a, b, (const Mat&)a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(-=, cv::subtract(a, b, (const Mat&)a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(-=, cv::subtract(a, b, (const Mat&)a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(-=, cv::subtract(a, b, (const Mat&)a), Mat_<_Tp>, Mat_<_Tp>) +CV_MAT_AUG_OPERATOR_TN(-=, cv::subtract(a, Mat(b), (const Mat&)a), Mat) +CV_MAT_AUG_OPERATOR_TN(-=, cv::subtract(a, Mat(b), (const Mat&)a), Mat_<_Tp>) CV_MAT_AUG_OPERATOR (*=, cv::gemm(a, b, 1, Mat(), 0, a, 0), Mat, Mat) CV_MAT_AUG_OPERATOR_T(*=, cv::gemm(a, b, 1, Mat(), 0, a, 0), Mat_<_Tp>, Mat) @@ -280,37 +280,37 @@ CV_MAT_AUG_OPERATOR_T(*=, a.convertTo(a, -1, b), Mat_<_Tp>, double) CV_MAT_AUG_OPERATOR_TN(*=, cv::gemm(a, Mat(b), 1, Mat(), 0, a, 0), Mat) CV_MAT_AUG_OPERATOR_TN(*=, cv::gemm(a, Mat(b), 1, Mat(), 0, a, 0), Mat_<_Tp>) -CV_MAT_AUG_OPERATOR (/=, cv::divide(a,b,a), Mat, Mat) -CV_MAT_AUG_OPERATOR_T(/=, cv::divide(a,b,a), Mat_<_Tp>, Mat) -CV_MAT_AUG_OPERATOR_T(/=, cv::divide(a,b,a), Mat_<_Tp>, Mat_<_Tp>) +CV_MAT_AUG_OPERATOR (/=, cv::divide(a, b, (const Mat&)a), Mat, Mat) +CV_MAT_AUG_OPERATOR_T(/=, cv::divide(a, b, (const Mat&)a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(/=, cv::divide(a, b, (const Mat&)a), Mat_<_Tp>, Mat_<_Tp>) CV_MAT_AUG_OPERATOR (/=, a.convertTo((Mat&)a, -1, 1./b), Mat, double) CV_MAT_AUG_OPERATOR_T(/=, a.convertTo((Mat&)a, -1, 1./b), Mat_<_Tp>, double) -CV_MAT_AUG_OPERATOR_TN(/=, cv::divide(a, Mat(b), a), Mat) -CV_MAT_AUG_OPERATOR_TN(/=, cv::divide(a, Mat(b), a), Mat_<_Tp>) +CV_MAT_AUG_OPERATOR_TN(/=, cv::divide(a, Mat(b), (const Mat&)a), Mat) +CV_MAT_AUG_OPERATOR_TN(/=, cv::divide(a, Mat(b), (const Mat&)a), Mat_<_Tp>) -CV_MAT_AUG_OPERATOR (&=, cv::bitwise_and(a,b,a), Mat, Mat) -CV_MAT_AUG_OPERATOR (&=, cv::bitwise_and(a,b,a), Mat, Scalar) -CV_MAT_AUG_OPERATOR_T(&=, cv::bitwise_and(a,b,a), Mat_<_Tp>, Mat) -CV_MAT_AUG_OPERATOR_T(&=, cv::bitwise_and(a,b,a), Mat_<_Tp>, Scalar) -CV_MAT_AUG_OPERATOR_T(&=, cv::bitwise_and(a,b,a), Mat_<_Tp>, Mat_<_Tp>) -CV_MAT_AUG_OPERATOR_TN(&=, cv::bitwise_and(a, Mat(b), a), Mat) -CV_MAT_AUG_OPERATOR_TN(&=, cv::bitwise_and(a, Mat(b), a), Mat_<_Tp>) +CV_MAT_AUG_OPERATOR (&=, cv::bitwise_and(a, b, (const Mat&)a), Mat, Mat) +CV_MAT_AUG_OPERATOR (&=, cv::bitwise_and(a, b, (const Mat&)a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(&=, cv::bitwise_and(a, b, (const Mat&)a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(&=, cv::bitwise_and(a, b, (const Mat&)a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(&=, cv::bitwise_and(a, b, (const Mat&)a), Mat_<_Tp>, Mat_<_Tp>) +CV_MAT_AUG_OPERATOR_TN(&=, cv::bitwise_and(a, Mat(b), (const Mat&)a), Mat) +CV_MAT_AUG_OPERATOR_TN(&=, cv::bitwise_and(a, Mat(b), (const Mat&)a), Mat_<_Tp>) -CV_MAT_AUG_OPERATOR (|=, cv::bitwise_or(a,b,a), Mat, Mat) -CV_MAT_AUG_OPERATOR (|=, cv::bitwise_or(a,b,a), Mat, Scalar) -CV_MAT_AUG_OPERATOR_T(|=, cv::bitwise_or(a,b,a), Mat_<_Tp>, Mat) -CV_MAT_AUG_OPERATOR_T(|=, cv::bitwise_or(a,b,a), Mat_<_Tp>, Scalar) -CV_MAT_AUG_OPERATOR_T(|=, cv::bitwise_or(a,b,a), Mat_<_Tp>, Mat_<_Tp>) -CV_MAT_AUG_OPERATOR_TN(|=, cv::bitwise_or(a, Mat(b), a), Mat) -CV_MAT_AUG_OPERATOR_TN(|=, cv::bitwise_or(a, Mat(b), a), Mat_<_Tp>) +CV_MAT_AUG_OPERATOR (|=, cv::bitwise_or(a, b, (const Mat&)a), Mat, Mat) +CV_MAT_AUG_OPERATOR (|=, cv::bitwise_or(a, b, (const Mat&)a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(|=, cv::bitwise_or(a, b, (const Mat&)a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(|=, cv::bitwise_or(a, b, (const Mat&)a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(|=, cv::bitwise_or(a, b, (const Mat&)a), Mat_<_Tp>, Mat_<_Tp>) +CV_MAT_AUG_OPERATOR_TN(|=, cv::bitwise_or(a, Mat(b), (const Mat&)a), Mat) +CV_MAT_AUG_OPERATOR_TN(|=, cv::bitwise_or(a, Mat(b), (const Mat&)a), Mat_<_Tp>) -CV_MAT_AUG_OPERATOR (^=, cv::bitwise_xor(a,b,a), Mat, Mat) -CV_MAT_AUG_OPERATOR (^=, cv::bitwise_xor(a,b,a), Mat, Scalar) -CV_MAT_AUG_OPERATOR_T(^=, cv::bitwise_xor(a,b,a), Mat_<_Tp>, Mat) -CV_MAT_AUG_OPERATOR_T(^=, cv::bitwise_xor(a,b,a), Mat_<_Tp>, Scalar) -CV_MAT_AUG_OPERATOR_T(^=, cv::bitwise_xor(a,b,a), Mat_<_Tp>, Mat_<_Tp>) -CV_MAT_AUG_OPERATOR_TN(^=, cv::bitwise_xor(a, Mat(b), a), Mat) -CV_MAT_AUG_OPERATOR_TN(^=, cv::bitwise_xor(a, Mat(b), a), Mat_<_Tp>) +CV_MAT_AUG_OPERATOR (^=, cv::bitwise_xor(a, b, (const Mat&)a), Mat, Mat) +CV_MAT_AUG_OPERATOR (^=, cv::bitwise_xor(a, b, (const Mat&)a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(^=, cv::bitwise_xor(a, b, (const Mat&)a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(^=, cv::bitwise_xor(a, b, (const Mat&)a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(^=, cv::bitwise_xor(a, b, (const Mat&)a), Mat_<_Tp>, Mat_<_Tp>) +CV_MAT_AUG_OPERATOR_TN(^=, cv::bitwise_xor(a, Mat(b), (const Mat&)a), Mat) +CV_MAT_AUG_OPERATOR_TN(^=, cv::bitwise_xor(a, Mat(b), (const Mat&)a), Mat_<_Tp>) #undef CV_MAT_AUG_OPERATOR_TN #undef CV_MAT_AUG_OPERATOR_T diff --git a/modules/core/test/test_operations.cpp b/modules/core/test/test_operations.cpp index caef417883..645045674a 100644 --- a/modules/core/test/test_operations.cpp +++ b/modules/core/test/test_operations.cpp @@ -1519,6 +1519,23 @@ TEST(Core_sortIdx, regression_8941) "expected=" << std::endl << expected; } +TEST(Core_Mat, augmentation_operations_9688) +{ + { + Mat x(1, 1, CV_64FC1, 1.0f); + Mat p(1, 4, CV_64FC1, 5.0f); + EXPECT_ANY_THROW( + x += p; + ) << x; + } + { + Mat x(1, 1, CV_64FC1, 1.0f); + Mat p(1, 4, CV_64FC1, 5.0f); + EXPECT_ANY_THROW( + x -= p; + ) << x; + } +} //These tests guard regressions against running MatExpr //operations on empty operands and giving bogus From 490908f0fffcf08b6e076c2b931a78dfb2df9667 Mon Sep 17 00:00:00 2001 From: Yashas Samaga B L Date: Tue, 10 Mar 2020 15:15:19 +0530 Subject: [PATCH 2/7] Merge pull request #16436 from YashasSamaga:feature-enetb0-yolo dnn(darknet-importer): add grouped convolutions, sigmoid, swish, scale_channels * update darknet importer to support enetb0-yolo * remove dropout (pr16438) and fix formatting * add test for scale_channels * disable batch testing for scale channels * do not set LayerParams::name * merge all activations into setActivation --- modules/dnn/src/darknet/darknet_io.cpp | 80 ++++++++++++++++++---- modules/dnn/test/test_darknet_importer.cpp | 10 ++- 2 files changed, 76 insertions(+), 14 deletions(-) diff --git a/modules/dnn/src/darknet/darknet_io.cpp b/modules/dnn/src/darknet/darknet_io.cpp index b93d740109..ff322bc188 100644 --- a/modules/dnn/src/darknet/darknet_io.cpp +++ b/modules/dnn/src/darknet/darknet_io.cpp @@ -149,7 +149,7 @@ namespace cv { void setConvolution(int kernel, int pad, int stride, - int filters_num, int channels_num, int use_batch_normalize) + int filters_num, int channels_num, int groups, int use_batch_normalize) { cv::dnn::LayerParams conv_param = getParamConvolution(kernel, pad, stride, filters_num); @@ -162,6 +162,8 @@ namespace cv { conv_param.set("bias_term", true); } + conv_param.set("group", groups); + lp.layer_name = layer_name; lp.layer_type = conv_param.type; lp.layerParams = conv_param; @@ -215,15 +217,30 @@ namespace cv { fused_layer_names.push_back(last_layer); } - void setReLU() + void setActivation(String type) { cv::dnn::LayerParams activation_param; - activation_param.set("negative_slope", 0.1f); - activation_param.name = "ReLU-name"; - activation_param.type = "ReLU"; + if (type == "relu") + { + activation_param.set("negative_slope", 0.1f); + activation_param.type = "ReLU"; + } + else if (type == "swish") + { + activation_param.type = "Swish"; + } + else if (type == "logistic") + { + activation_param.type = "Sigmoid"; + } + else + { + CV_Error(cv::Error::StsParseError, "Unsupported activation: " + type); + } + + std::string layer_name = cv::format("%s_%d", type.c_str(), layer_id); darknet::LayerParameter lp; - std::string layer_name = cv::format("relu_%d", layer_id); lp.layer_name = layer_name; lp.layer_type = activation_param.type; lp.layerParams = activation_param; @@ -487,6 +504,25 @@ namespace cv { fused_layer_names.push_back(last_layer); } + void setScaleChannels(int from) + { + cv::dnn::LayerParams shortcut_param; + shortcut_param.type = "Scale"; + + darknet::LayerParameter lp; + std::string layer_name = cv::format("scale_channels_%d", layer_id); + lp.layer_name = layer_name; + lp.layer_type = shortcut_param.type; + lp.layerParams = shortcut_param; + lp.bottom_indexes.push_back(fused_layer_names.at(from)); + lp.bottom_indexes.push_back(last_layer); + last_layer = layer_name; + net->layers.push_back(lp); + + layer_id++; + fused_layer_names.push_back(last_layer); + } + void setUpsample(int scaleFactor) { cv::dnn::LayerParams param; @@ -608,6 +644,7 @@ namespace cv { int padding = getParam(layer_params, "padding", 0); int stride = getParam(layer_params, "stride", 1); int filters = getParam(layer_params, "filters", -1); + int groups = getParam(layer_params, "groups", 1); bool batch_normalize = getParam(layer_params, "batch_normalize", 0) == 1; int flipped = getParam(layer_params, "flipped", 0); if (flipped == 1) @@ -618,9 +655,10 @@ namespace cv { CV_Assert(kernel_size > 0 && filters > 0); CV_Assert(tensor_shape[0] > 0); + CV_Assert(tensor_shape[0] % groups == 0); setParams.setConvolution(kernel_size, padding, stride, filters, tensor_shape[0], - batch_normalize); + groups, batch_normalize); tensor_shape[0] = filters; tensor_shape[1] = (tensor_shape[1] - kernel_size + 2 * padding) / stride + 1; @@ -727,6 +765,14 @@ namespace cv { from = from < 0 ? from + layers_counter : from; setParams.setShortcut(from, alpha); } + else if (layer_type == "scale_channels") + { + std::string bottom_layer = getParam(layer_params, "from", ""); + CV_Assert(!bottom_layer.empty()); + int from = std::atoi(bottom_layer.c_str()); + from = from < 0 ? from + layers_counter : from; + setParams.setScaleChannels(from); + } else if (layer_type == "upsample") { int scaleFactor = getParam(layer_params, "stride", 1); @@ -761,7 +807,15 @@ namespace cv { std::string activation = getParam(layer_params, "activation", "linear"); if (activation == "leaky") { - setParams.setReLU(); + setParams.setActivation("relu"); + } + else if (activation == "swish") + { + setParams.setActivation("swish"); + } + else if (activation == "logistic") + { + setParams.setActivation("logistic"); } else if (activation != "linear") CV_Error(cv::Error::StsParseError, "Unsupported activation: " + activation); @@ -818,13 +872,15 @@ namespace cv { { int kernel_size = getParam(layer_params, "size", -1); filters = getParam(layer_params, "filters", -1); + int groups = getParam(layer_params, "groups", 1); use_batch_normalize = getParam(layer_params, "batch_normalize", 0) == 1; CV_Assert(kernel_size > 0 && filters > 0); CV_Assert(tensor_shape[0] > 0); + CV_Assert(tensor_shape[0] % groups == 0); - weights_size = filters * tensor_shape[0] * kernel_size * kernel_size; - int sizes_weights[] = { filters, tensor_shape[0], kernel_size, kernel_size }; + weights_size = filters * (tensor_shape[0] / groups) * kernel_size * kernel_size; + int sizes_weights[] = { filters, tensor_shape[0] / groups, kernel_size, kernel_size }; weightsBlob.create(4, sizes_weights, CV_32F); } else @@ -879,8 +935,8 @@ namespace cv { } std::string activation = getParam(layer_params, "activation", "linear"); - if(activation == "leaky") - ++cv_layers_counter; // For ReLU + if(activation == "leaky" || activation == "swish" || activation == "logistic") + ++cv_layers_counter; // For ReLU, Swish, Sigmoid if(!darknet_layers_counter) tensor_shape.resize(1); diff --git a/modules/dnn/test/test_darknet_importer.cpp b/modules/dnn/test/test_darknet_importer.cpp index 068f85eb48..58faaa1388 100644 --- a/modules/dnn/test/test_darknet_importer.cpp +++ b/modules/dnn/test/test_darknet_importer.cpp @@ -97,7 +97,7 @@ TEST(Test_Darknet, read_yolo_voc_stream) class Test_Darknet_layers : public DNNTestLayer { public: - void testDarknetLayer(const std::string& name, bool hasWeights = false) + void testDarknetLayer(const std::string& name, bool hasWeights = false, bool testBatchProcessing = true) { SCOPED_TRACE(name); Mat inp = blobFromNPY(findDataFile("dnn/darknet/" + name + "_in.npy")); @@ -117,7 +117,7 @@ public: Mat out = net.forward(); normAssert(out, ref, "", default_l1, default_lInf); - if (inp.size[0] == 1) // test handling of batch size + if (inp.size[0] == 1 && testBatchProcessing) // test handling of batch size { SCOPED_TRACE("batch size 2"); @@ -552,6 +552,12 @@ TEST_P(Test_Darknet_layers, convolutional) testDarknetLayer("convolutional", true); } +TEST_P(Test_Darknet_layers, scale_channels) +{ + // TODO: test fails for batches due to a bug/missing feature in ScaleLayer + testDarknetLayer("scale_channels", false, false); +} + TEST_P(Test_Darknet_layers, connected) { if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) From db95aec4a7981fb6cebc49169b48861074f2dad3 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 6 Mar 2020 13:43:23 +0000 Subject: [PATCH 3/7] dnn(ie): switch to nGraph backend by default --- modules/dnn/CMakeLists.txt | 2 +- modules/dnn/include/opencv2/dnn/dnn.hpp | 4 ++-- modules/dnn/src/op_inf_engine.cpp | 8 +++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/modules/dnn/CMakeLists.txt b/modules/dnn/CMakeLists.txt index c7e07c5543..b454a3db45 100644 --- a/modules/dnn/CMakeLists.txt +++ b/modules/dnn/CMakeLists.txt @@ -92,7 +92,7 @@ endif() set(dnn_runtime_libs "") if(INF_ENGINE_TARGET) - ocv_option(OPENCV_DNN_IE_NN_BUILDER_2019 "Build with Inference Engine NN Builder API support" ON) + ocv_option(OPENCV_DNN_IE_NN_BUILDER_2019 "Build with Inference Engine NN Builder API support" ON) # future: NOT HAVE_NGRAPH if(OPENCV_DNN_IE_NN_BUILDER_2019) message(STATUS "DNN: Enabling Inference Engine NN Builder API support") add_definitions(-DHAVE_DNN_IE_NN_BUILDER_2019=1) diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index 113893813c..e67a465334 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -47,9 +47,9 @@ #include "opencv2/core/async.hpp" #if !defined CV_DOXYGEN && !defined CV_STATIC_ANALYSIS && !defined CV_DNN_DONT_ADD_EXPERIMENTAL_NS -#define CV__DNN_EXPERIMENTAL_NS_BEGIN namespace experimental_dnn_34_v16 { +#define CV__DNN_EXPERIMENTAL_NS_BEGIN namespace experimental_dnn_34_v17 { #define CV__DNN_EXPERIMENTAL_NS_END } -namespace cv { namespace dnn { namespace experimental_dnn_34_v16 { } using namespace experimental_dnn_34_v16; }} +namespace cv { namespace dnn { namespace experimental_dnn_34_v17 { } using namespace experimental_dnn_34_v17; }} #else #define CV__DNN_EXPERIMENTAL_NS_BEGIN #define CV__DNN_EXPERIMENTAL_NS_END diff --git a/modules/dnn/src/op_inf_engine.cpp b/modules/dnn/src/op_inf_engine.cpp index cea4f3fb77..9c74032a33 100644 --- a/modules/dnn/src/op_inf_engine.cpp +++ b/modules/dnn/src/op_inf_engine.cpp @@ -41,11 +41,13 @@ static const char* dumpInferenceEngineBackendType(Backend backend) Backend& getInferenceEngineBackendTypeParam() { static Backend param = parseInferenceEngineBackendType( - utils::getConfigurationParameterString("OPENCV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019_TYPE", -#ifndef HAVE_DNN_IE_NN_BUILDER_2019 + utils::getConfigurationParameterString("OPENCV_DNN_BACKEND_INFERENCE_ENGINE_TYPE", +#ifdef HAVE_DNN_NGRAPH CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH -#else +#elif defined(HAVE_DNN_IE_NN_BUILDER_2019) CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API +#else +#error "Build configuration error: nGraph or NN Builder API backend should be enabled" #endif ) ); From b7ecaceda8eeb767a341cc896802aad87befb5f3 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 10 Mar 2020 14:53:43 +0300 Subject: [PATCH 4/7] pre: OpenCV 3.4.10 (version++) - Android Manager version is not increased (stuck on 3.49) --- doc/tutorials/dnn/dnn_android/dnn_android.markdown | 2 +- .../cross_referencing/tutorial_cross_referencing.markdown | 4 ++-- modules/core/include/opencv2/core/version.hpp | 4 ++-- modules/python/package/setup.py | 2 +- platforms/android/build_sdk.py | 2 +- platforms/android/service/readme.txt | 2 +- platforms/maven/opencv-it/pom.xml | 2 +- platforms/maven/opencv/pom.xml | 2 +- platforms/maven/pom.xml | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/tutorials/dnn/dnn_android/dnn_android.markdown b/doc/tutorials/dnn/dnn_android/dnn_android.markdown index a88a72f2e4..1a3f9224a9 100644 --- a/doc/tutorials/dnn/dnn_android/dnn_android.markdown +++ b/doc/tutorials/dnn/dnn_android/dnn_android.markdown @@ -12,7 +12,7 @@ Tutorial was written for the following versions of corresponding software: - Download and install Android Studio from https://developer.android.com/studio. -- Get the latest pre-built OpenCV for Android release from https://github.com/opencv/opencv/releases and unpack it (for example, `opencv-3.4.9-android-sdk.zip`). +- Get the latest pre-built OpenCV for Android release from https://github.com/opencv/opencv/releases and unpack it (for example, `opencv-3.4.10-android-sdk.zip`). - Download MobileNet object detection model from https://github.com/chuanqi305/MobileNet-SSD. We need a configuration file `MobileNetSSD_deploy.prototxt` and weights `MobileNetSSD_deploy.caffemodel`. diff --git a/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown b/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown index 0c164b03b9..c64c012028 100644 --- a/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown +++ b/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown @@ -36,14 +36,14 @@ Open your Doxyfile using your favorite text editor and search for the key `TAGFILES`. Change it as follows: @code -TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.9 +TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.10 @endcode If you had other definitions already, you can append the line using a `\`: @code TAGFILES = ./docs/doxygen-tags/libstdc++.tag=https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen \ - ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.9 + ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.10 @endcode Doxygen can now use the information from the tag file to link to the OpenCV diff --git a/modules/core/include/opencv2/core/version.hpp b/modules/core/include/opencv2/core/version.hpp index 5a372feb8c..571745a2c5 100644 --- a/modules/core/include/opencv2/core/version.hpp +++ b/modules/core/include/opencv2/core/version.hpp @@ -7,8 +7,8 @@ #define CV_VERSION_MAJOR 3 #define CV_VERSION_MINOR 4 -#define CV_VERSION_REVISION 9 -#define CV_VERSION_STATUS "-dev" +#define CV_VERSION_REVISION 10 +#define CV_VERSION_STATUS "-pre" #define CVAUX_STR_EXP(__A) #__A #define CVAUX_STR(__A) CVAUX_STR_EXP(__A) diff --git a/modules/python/package/setup.py b/modules/python/package/setup.py index 6bd06c65b7..4aeb1815a7 100644 --- a/modules/python/package/setup.py +++ b/modules/python/package/setup.py @@ -9,7 +9,7 @@ def main(): os.chdir(SCRIPT_DIR) package_name = 'opencv' - package_version = os.environ.get('OPENCV_VERSION', '3.4.9') # TODO + package_version = os.environ.get('OPENCV_VERSION', '3.4.10') # TODO long_description = 'Open Source Computer Vision Library Python bindings' # TODO diff --git a/platforms/android/build_sdk.py b/platforms/android/build_sdk.py index 8c0ef8978f..61df24141f 100755 --- a/platforms/android/build_sdk.py +++ b/platforms/android/build_sdk.py @@ -267,7 +267,7 @@ class Builder: # Add extra data apkxmldest = check_dir(os.path.join(apkdest, "res", "xml"), create=True) apklibdest = check_dir(os.path.join(apkdest, "libs", abi.name), create=True) - for ver, d in self.extra_packs + [("3.4.9", os.path.join(self.libdest, "lib"))]: + for ver, d in self.extra_packs + [("3.4.10", os.path.join(self.libdest, "lib"))]: r = ET.Element("library", attrib={"version": ver}) log.info("Adding libraries from %s", d) diff --git a/platforms/android/service/readme.txt b/platforms/android/service/readme.txt index 7720ab37db..14647a6ffe 100644 --- a/platforms/android/service/readme.txt +++ b/platforms/android/service/readme.txt @@ -12,7 +12,7 @@ manually using adb tool: adb install /apk/OpenCV__Manager__.apk -Example: OpenCV_3.4.9-dev_Manager_3.49_armeabi-v7a.apk +Example: OpenCV_3.4.10-dev_Manager_3.49_armeabi-v7a.apk Use the list of platforms below to determine proper OpenCV Manager package for your device: diff --git a/platforms/maven/opencv-it/pom.xml b/platforms/maven/opencv-it/pom.xml index 84109391f5..bcdde87ef3 100644 --- a/platforms/maven/opencv-it/pom.xml +++ b/platforms/maven/opencv-it/pom.xml @@ -4,7 +4,7 @@ org.opencv opencv-parent - 3.4.9 + 3.4.10 org.opencv opencv-it diff --git a/platforms/maven/opencv/pom.xml b/platforms/maven/opencv/pom.xml index f0a4103bcf..f08fe0945c 100644 --- a/platforms/maven/opencv/pom.xml +++ b/platforms/maven/opencv/pom.xml @@ -4,7 +4,7 @@ org.opencv opencv-parent - 3.4.9 + 3.4.10 org.opencv opencv diff --git a/platforms/maven/pom.xml b/platforms/maven/pom.xml index 4f02f32fbd..86ce61c6b4 100644 --- a/platforms/maven/pom.xml +++ b/platforms/maven/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.opencv opencv-parent - 3.4.9 + 3.4.10 pom OpenCV Parent POM From 09fe66e87f87683ab22afee4e43cce9d970dab0c Mon Sep 17 00:00:00 2001 From: Vadim Levin Date: Tue, 10 Mar 2020 16:44:22 +0300 Subject: [PATCH 5/7] Merge pull request #16713 from VadimLevin:dev/vlevin/ffmpeg_video_capture_bitrate * feature: Add video capture bitrate read-only property for FFMPEG backend * test: For WIN32 property should be either expected or 0. Added `IsOneOf` helper function, enabled only for _WIN32. --- modules/videoio/include/opencv2/videoio.hpp | 1 + modules/videoio/src/cap_ffmpeg_api.hpp | 3 +- modules/videoio/src/cap_ffmpeg_impl.hpp | 8 ++- modules/videoio/test/test_ffmpeg.cpp | 63 +++++++++++++++++++++ 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/modules/videoio/include/opencv2/videoio.hpp b/modules/videoio/include/opencv2/videoio.hpp index cf91a0d83d..d09e62c15d 100644 --- a/modules/videoio/include/opencv2/videoio.hpp +++ b/modules/videoio/include/opencv2/videoio.hpp @@ -176,6 +176,7 @@ enum VideoCaptureProperties { CAP_PROP_AUTO_WB =44, //!< enable/ disable auto white-balance CAP_PROP_WB_TEMPERATURE=45, //!< white-balance color temperature CAP_PROP_CODEC_PIXEL_FORMAT =46, //!< (read-only) codec's pixel format. 4-character code - see VideoWriter::fourcc . Subset of [AV_PIX_FMT_*](https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/raw.c) or -1 if unknown + CAP_PROP_BITRATE =47, //!< (read-only) Video bitrate in kbits/s #ifndef CV_DOXYGEN CV__CAP_PROP_LATEST #endif diff --git a/modules/videoio/src/cap_ffmpeg_api.hpp b/modules/videoio/src/cap_ffmpeg_api.hpp index 2366ee13a3..004758099c 100644 --- a/modules/videoio/src/cap_ffmpeg_api.hpp +++ b/modules/videoio/src/cap_ffmpeg_api.hpp @@ -27,7 +27,8 @@ enum CV_FFMPEG_CAP_PROP_FORMAT=8, CV_FFMPEG_CAP_PROP_SAR_NUM=40, CV_FFMPEG_CAP_PROP_SAR_DEN=41, - CV_FFMPEG_CAP_PROP_CODEC_PIXEL_FORMAT=46 + CV_FFMPEG_CAP_PROP_CODEC_PIXEL_FORMAT=46, + CV_FFMPEG_CAP_PROP_BITRATE=47 }; typedef struct CvCapture_FFMPEG CvCapture_FFMPEG; diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index c69cd74509..fae85425b0 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -492,7 +492,7 @@ struct CvCapture_FFMPEG int64_t get_total_frames() const; double get_duration_sec() const; double get_fps() const; - int get_bitrate() const; + int64_t get_bitrate() const; double r2d(AVRational r) const; int64_t dts_to_frame_number(int64_t dts); @@ -1433,6 +1433,8 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const if (rawMode) return -1; break; + case CV_FFMPEG_CAP_PROP_BITRATE: + return static_cast(get_bitrate()); default: break; } @@ -1457,9 +1459,9 @@ double CvCapture_FFMPEG::get_duration_sec() const return sec; } -int CvCapture_FFMPEG::get_bitrate() const +int64_t CvCapture_FFMPEG::get_bitrate() const { - return ic->bit_rate; + return ic->bit_rate / 1000; } double CvCapture_FFMPEG::get_fps() const diff --git a/modules/videoio/test/test_ffmpeg.cpp b/modules/videoio/test/test_ffmpeg.cpp index 10f41daf7a..0251261b81 100644 --- a/modules/videoio/test/test_ffmpeg.cpp +++ b/modules/videoio/test/test_ffmpeg.cpp @@ -573,5 +573,68 @@ TEST(Videoio_Video_parallel_writers_and_readers, accuracy) readers.clear(); } +typedef std::pair cap_property_t; +typedef std::vector cap_properties_t; +typedef std::pair ffmpeg_cap_properties_param_t; +typedef testing::TestWithParam ffmpeg_cap_properties; + +#ifdef _WIN32 +namespace { +::testing::AssertionResult IsOneOf(double value, double expected1, double expected2) +{ + // internal floating point class is used to perform accurate floating point types comparison + typedef ::testing::internal::FloatingPoint FloatingPoint; + + FloatingPoint val(value); + if (val.AlmostEquals(FloatingPoint(expected1)) || val.AlmostEquals(FloatingPoint(expected2))) + { + return ::testing::AssertionSuccess(); + } + else + { + return ::testing::AssertionFailure() + << value << " is neither equal to " << expected1 << " nor " << expected2; + } +} +} +#endif + +TEST_P(ffmpeg_cap_properties, can_read_property) +{ + ffmpeg_cap_properties_param_t parameters = GetParam(); + const std::string path = parameters.first; + const cap_properties_t properties = parameters.second; + + VideoCapture cap(findDataFile(path), CAP_FFMPEG); + ASSERT_TRUE(cap.isOpened()) << "Can not open " << findDataFile(path); + + for (std::size_t i = 0; i < properties.size(); ++i) + { + const cap_property_t& prop = properties[i]; + const double actualValue = cap.get(static_cast(prop.first)); + #ifndef _WIN32 + EXPECT_DOUBLE_EQ(actualValue, prop.second) + << "Property " << static_cast(prop.first) << " has wrong value"; + #else + EXPECT_TRUE(IsOneOf(actualValue, prop.second, 0.0)) + << "Property " << static_cast(prop.first) << " has wrong value"; + #endif + } +} + +cap_properties_t loadBigBuckBunnyFFProbeResults() { + cap_property_t properties[] = { cap_property_t(CAP_PROP_BITRATE, 5851.), + cap_property_t(CAP_PROP_FPS, 24.), + cap_property_t(CAP_PROP_FRAME_HEIGHT, 384.), + cap_property_t(CAP_PROP_FRAME_WIDTH, 672.) }; + return cap_properties_t(properties, properties + sizeof(properties) / sizeof(cap_property_t)); +} + +const ffmpeg_cap_properties_param_t videoio_ffmpeg_properties[] = { + ffmpeg_cap_properties_param_t("video/big_buck_bunny.avi", loadBigBuckBunnyFFProbeResults()) +}; + +INSTANTIATE_TEST_CASE_P(videoio, ffmpeg_cap_properties, testing::ValuesIn(videoio_ffmpeg_properties)); + #endif }} // namespace From 155b751a7513d7d027abc8c26c91c89750924f71 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 10 Mar 2020 19:01:01 +0000 Subject: [PATCH 6/7] ffmpeg/3.4: update FFmpeg wrapper - FFmpeg 3.4.7 --- 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 81513655de..8e211b58ae 100644 --- a/3rdparty/ffmpeg/ffmpeg.cmake +++ b/3rdparty/ffmpeg/ffmpeg.cmake @@ -1,8 +1,8 @@ -# Binaries branch name: ffmpeg/3.4_20191118 -# Binaries were created for OpenCV: 3f431a16a38be35e52b4887a3591d23030d34fc5 -ocv_update(FFMPEG_BINARIES_COMMIT "548e3c997a80d65f710b9048f1d33371e3a203ac") -ocv_update(FFMPEG_FILE_HASH_BIN32 "168635a192fc2d2ae7d7d40150f0b349") -ocv_update(FFMPEG_FILE_HASH_BIN64 "cbc25f8f2954475b127c7558558c18e6") +# Binaries branch name: ffmpeg/3.4_20200310 +# Binaries were created for OpenCV: 4966186e10e2a940514d8c20447ca4a828af5f46 +ocv_update(FFMPEG_BINARIES_COMMIT "e81ccda615672833b578c6cefdb859ad69c560ba") +ocv_update(FFMPEG_FILE_HASH_BIN32 "301ae2000e25f800ab8e0065f277ad28") +ocv_update(FFMPEG_FILE_HASH_BIN64 "d87ce032289c3f811d02f0c3d8dbe366") ocv_update(FFMPEG_FILE_HASH_CMAKE "3b90f67f4b429e77d3da36698cef700c") function(download_win_ffmpeg script_var) From 83e1d794032a7ec59852ff713dc15955d03571b3 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 25 Feb 2020 17:04:27 +0300 Subject: [PATCH 7/7] core: update CPUs detection - cache value, evaluate once - better support for MINGW - anything in 'cv' namespace - test: dump number of active threads --- modules/core/src/parallel.cpp | 45 +++++++++++++++++++++-------------- modules/ts/src/ts.cpp | 17 +++++++------ 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/modules/core/src/parallel.cpp b/modules/core/src/parallel.cpp index e7393ed584..1b53cfa0e3 100644 --- a/modules/core/src/parallel.cpp +++ b/modules/core/src/parallel.cpp @@ -140,13 +140,12 @@ using namespace cv; -namespace cv -{ - ParallelLoopBody::~ParallelLoopBody() {} -} +namespace cv { + +ParallelLoopBody::~ParallelLoopBody() {} + +namespace { -namespace -{ #ifdef CV_PARALLEL_FRAMEWORK #ifdef ENABLE_INSTRUMENTATION static void SyncNodes(cv::instr::InstrNode *pNode) @@ -445,7 +444,7 @@ static SchedPtr pplScheduler; #endif // CV_PARALLEL_FRAMEWORK -} //namespace +} // namespace anon /* ================================ parallel_for_ ================================ */ @@ -453,7 +452,7 @@ static SchedPtr pplScheduler; static void parallel_for_impl(const cv::Range& range, const cv::ParallelLoopBody& body, double nstripes); // forward declaration #endif -void cv::parallel_for_(const cv::Range& range, const cv::ParallelLoopBody& body, double nstripes) +void parallel_for_(const cv::Range& range, const cv::ParallelLoopBody& body, double nstripes) { #ifdef OPENCV_TRACE CV__TRACE_OPENCV_FUNCTION_NAME_("parallel_for", 0); @@ -573,7 +572,7 @@ static void parallel_for_impl(const cv::Range& range, const cv::ParallelLoopBody #endif // CV_PARALLEL_FRAMEWORK -int cv::getNumThreads(void) +int getNumThreads(void) { #ifdef CV_PARALLEL_FRAMEWORK @@ -634,7 +633,6 @@ int cv::getNumThreads(void) #endif } -namespace cv { unsigned defaultNumberOfThreads() { #ifdef __ANDROID__ @@ -656,9 +654,8 @@ unsigned defaultNumberOfThreads() } return result; } -} -void cv::setNumThreads( int threads_ ) +void setNumThreads( int threads_ ) { CV_UNUSED(threads_); #ifdef CV_PARALLEL_FRAMEWORK @@ -719,7 +716,7 @@ void cv::setNumThreads( int threads_ ) } -int cv::getThreadNum(void) +int getThreadNum() { #if defined HAVE_TBB #if TBB_INTERFACE_VERSION >= 9100 @@ -841,14 +838,17 @@ T minNonZero(const T& val_1, const T& val_2) return (val_1 != 0) ? val_1 : val_2; } -int cv::getNumberOfCPUs(void) +static +int getNumberOfCPUs_() { /* * Logic here is to try different methods of getting CPU counts and return * the minimum most value as it has high probablity of being right and safe. * Return 1 if we get 0 or not found on all methods. */ -#if defined CV_CXX11 +#if defined CV_CXX11 \ + && !defined(__MINGW32__) /* not implemented (2020-03) */ \ + /* * Check for this standard C++11 way, we do not return directly because * running in a docker or K8s environment will mean this is the host @@ -862,13 +862,13 @@ int cv::getNumberOfCPUs(void) #if defined _WIN32 - SYSTEM_INFO sysinfo; + SYSTEM_INFO sysinfo = {}; #if (defined(_M_ARM) || defined(_M_ARM64) || defined(_M_X64) || defined(WINRT)) && _WIN32_WINNT >= 0x501 GetNativeSystemInfo( &sysinfo ); #else GetSystemInfo( &sysinfo ); #endif - unsigned ncpus_sysinfo = sysinfo.dwNumberOfProcessors < 0 ? 1 : sysinfo.dwNumberOfProcessors; /* Just a fail safe */ + unsigned ncpus_sysinfo = sysinfo.dwNumberOfProcessors; ncpus = minNonZero(ncpus, ncpus_sysinfo); #elif defined __APPLE__ @@ -911,6 +911,7 @@ int cv::getNumberOfCPUs(void) #endif #if defined _GNU_SOURCE \ + && !defined(__MINGW32__) /* not implemented (2020-03) */ \ && !defined(__EMSCRIPTEN__) \ && !defined(__ANDROID__) // TODO: add check for modern Android NDK @@ -933,7 +934,13 @@ int cv::getNumberOfCPUs(void) return ncpus != 0 ? ncpus : 1; } -const char* cv::currentParallelFramework() { +int getNumberOfCPUs() +{ + static int nCPUs = getNumberOfCPUs_(); + return nCPUs; // cached value +} + +const char* currentParallelFramework() { #ifdef CV_PARALLEL_FRAMEWORK return CV_PARALLEL_FRAMEWORK; #else @@ -941,6 +948,8 @@ const char* cv::currentParallelFramework() { #endif } +} // namespace cv:: + CV_IMPL void cvSetNumThreads(int nt) { cv::setNumThreads(nt); diff --git a/modules/ts/src/ts.cpp b/modules/ts/src/ts.cpp index d319ec1d7b..bad799dc4d 100644 --- a/modules/ts/src/ts.cpp +++ b/modules/ts/src/ts.cpp @@ -1099,14 +1099,6 @@ inline static void recordPropertyVerbose(const std::string & property, } } -inline static void recordPropertyVerbose(const std::string& property, const std::string& msg, - const char* value, const char* build_value = NULL) -{ - return recordPropertyVerbose(property, msg, - value ? std::string(value) : std::string(), - build_value ? std::string(build_value) : std::string()); -} - #ifdef _DEBUG #define CV_TEST_BUILD_CONFIG "Debug" #else @@ -1120,7 +1112,14 @@ void SystemInfoCollector::OnTestProgramStart(const testing::UnitTest&) recordPropertyVerbose("cv_vcs_version", "OpenCV VCS version", getSnippetFromConfig("Version control:", "\n")); recordPropertyVerbose("cv_build_type", "Build type", getSnippetFromConfig("Configuration:", "\n"), CV_TEST_BUILD_CONFIG); recordPropertyVerbose("cv_compiler", "Compiler", getSnippetFromConfig("C++ Compiler:", "\n")); - recordPropertyVerbose("cv_parallel_framework", "Parallel framework", cv::currentParallelFramework()); + const char* parallelFramework = cv::currentParallelFramework(); + if (parallelFramework) + { + ::testing::Test::RecordProperty("cv_parallel_framework", parallelFramework); + int threads = testThreads > 0 ? testThreads : cv::getNumThreads(); + ::testing::Test::RecordProperty("cv_parallel_threads", threads); + std::cout << "Parallel framework: " << parallelFramework << " (nthreads=" << threads << ")" << std::endl; + } recordPropertyVerbose("cv_cpu_features", "CPU features", cv::getCPUFeaturesLine()); #ifdef HAVE_IPP recordPropertyVerbose("cv_ipp_version", "Intel(R) IPP version", cv::ipp::useIPP() ? cv::ipp::getIppVersion() : "disabled");