Merge remote-tracking branch 'upstream/3.4' into merge-3.4
authorAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 22 May 2020 19:06:42 +0000 (19:06 +0000)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 22 May 2020 19:50:14 +0000 (19:50 +0000)
49 files changed:
1  2 
doc/tutorials/calib3d/camera_calibration/camera_calibration.markdown
doc/tutorials/calib3d/camera_calibration_pattern/camera_calibration_pattern.markdown
doc/tutorials/dnn/dnn_android/dnn_android.markdown
doc/tutorials/dnn/dnn_custom_layers/dnn_custom_layers.md
doc/tutorials/dnn/dnn_googlenet/dnn_googlenet.markdown
doc/tutorials/dnn/dnn_halide/dnn_halide.markdown
doc/tutorials/dnn/dnn_yolo/dnn_yolo.markdown
doc/tutorials/features2d/akaze_matching/akaze_matching.markdown
doc/tutorials/features2d/feature_description/feature_description.markdown
doc/tutorials/features2d/feature_detection/feature_detection.markdown
doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.markdown
doc/tutorials/features2d/feature_homography/feature_homography.markdown
doc/tutorials/features2d/homography/homography.markdown
doc/tutorials/features2d/trackingmotion/corner_subpixels/corner_subpixels.markdown
doc/tutorials/features2d/trackingmotion/generic_corner_detector/generic_corner_detector.markdown
doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.markdown
doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.markdown
doc/tutorials/gpu/gpu-basics-similarity/gpu_basics_similarity.markdown
doc/tutorials/gpu/gpu-thrust-interop/gpu_thrust_interop.markdown
doc/tutorials/introduction/android_binary_package/O4A_SDK.markdown
doc/tutorials/introduction/android_binary_package/android_dev_intro.markdown
doc/tutorials/introduction/android_binary_package/android_ocl_intro.markdown
doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.markdown
doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown
doc/tutorials/introduction/display_image/display_image.markdown
doc/tutorials/introduction/linux_install/linux_install.markdown
doc/tutorials/introduction/transition_guide/transition_guide.markdown
doc/tutorials/introduction/windows_visual_studio_opencv/windows_visual_studio_opencv.markdown
doc/tutorials/ml/introduction_to_pca/introduction_to_pca.markdown
doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown
doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown
doc/tutorials/objdetect/cascade_classifier/cascade_classifier.markdown
doc/tutorials/objdetect/traincascade.markdown
doc/tutorials/video/background_subtraction/background_subtraction.markdown
doc/tutorials/video/meanshift/meanshift.markdown
doc/tutorials/video/optical_flow/optical_flow.markdown
doc/tutorials/videoio/intelperc.markdown
doc/tutorials/videoio/kinect_openni.markdown
doc/tutorials/videoio/video-input-psnr-ssim/video_input_psnr_ssim.markdown
doc/tutorials/videoio/video-write/video_write.markdown
modules/dnn/include/opencv2/dnn/all_layers.hpp
modules/dnn/src/caffe/caffe_importer.cpp
modules/dnn/src/init.cpp
modules/dnn/src/layers/convolution_layer.cpp
modules/dnn/src/layers/flow_warp_layer.cpp
modules/dnn/src/layers/resize_layer.cpp
modules/dnn/src/layers/scale_layer.cpp
modules/dnn/test/test_layers.cpp
modules/videoio/src/cap_avfoundation.mm

@@@ -1,11 -1,14 +1,14 @@@
  Create calibration pattern {#tutorial_camera_calibration_pattern}
  =========================================
  
+ @next_tutorial{tutorial_camera_calibration_square_chess}
  The goal of this tutorial is to learn how to create calibration pattern.
  
 -You can find a chessboard pattern in https://github.com/opencv/opencv/blob/3.4/doc/pattern.png
 +You can find a chessboard pattern in https://github.com/opencv/opencv/blob/master/doc/pattern.png
  
 -You can find a circleboard pattern in https://github.com/opencv/opencv/blob/3.4/doc/acircles_pattern.png
 +You can find a circleboard pattern in https://github.com/opencv/opencv/blob/master/doc/acircles_pattern.png
  
  Create your own pattern
  ---------------
@@@ -1,7 -1,8 +1,9 @@@
  Using Creative Senz3D and other Intel Perceptual Computing SDK compatible depth sensors {#tutorial_intelperc}
  =======================================================================================
  
+ @prev_tutorial{tutorial_kinect_openni}
 +**Note**: this tutorial is partially obsolete since PerC SDK has been replaced with RealSense SDK
  
  Depth sensors compatible with Intel Perceptual Computing SDK are supported through VideoCapture
  class. Depth map, RGB image and some other formats of output can be retrieved by using familiar
@@@ -465,6 -465,35 +465,35 @@@ public
                  net.mutable_layer(li)->mutable_bottom()->RemoveLast();
                  type = "Eltwise";
              }
 -                String interp = layerParams.get<String>("type").toLowerCase();
+             else if (type == "Resample")
+             {
+                 CV_Assert(layer.bottom_size() == 1 || layer.bottom_size() == 2);
+                 type = "Resize";
++                String interp = toLowerCase(layerParams.get<String>("type"));
+                 layerParams.set("interpolation", interp == "linear" ? "bilinear" : interp);
+                 if (layerParams.has("factor"))
+                 {
+                     float factor = layerParams.get<float>("factor");
+                     CV_Assert(layer.bottom_size() != 2 || factor == 1.0);
+                     layerParams.set("zoom_factor", factor);
+                     if ((interp == "linear" && factor != 1.0) ||
+                         (interp == "nearest" && factor < 1.0))
+                         CV_Error(Error::StsNotImplemented, "Unsupported Resample mode");
+                 }
+             }
+             else if ("Convolution" == type)
+             {
+                 CV_Assert(layer.bottom_size() == layer.top_size());
+                 for (int i = 0; i < layer.bottom_size(); i++)
+                 {
+                     int conv_id = dstNet.addLayer(layer.top(i), type, layerParams);
+                     addInput(layer.bottom(i), conv_id, 0, dstNet);
+                     addedBlobs.push_back(BlobNote(layer.top(i), conv_id, 0));
+                 }
+                 continue;
+             }
              else if ("ConvolutionDepthwise" == type)
              {
                  type = "Convolution";
Simple merge
@@@ -1471,74 -1319,12 +1478,78 @@@ public
              ParallelConv::run(inputs[0], outputs[0], weightsMat, biasvec, reluslope,
                              kernel_size, strides, pads_begin, pads_end, dilations, activ.get(), ngroups, nstripes);
          }
+ #if CV_TRY_SSE
+         _MM_SET_FLUSH_ZERO_MODE(ftzMode);
+         _MM_SET_DENORMALS_ZERO_MODE(dazMode);
+ #endif
      }
  
 +#ifdef HAVE_CUDA
 +    Ptr<BackendNode> initCUDA(
 +        void *context_,
 +        const std::vector<Ptr<BackendWrapper>>& inputs,
 +        const std::vector<Ptr<BackendWrapper>>& outputs
 +    ) override
 +    {
 +        auto context = reinterpret_cast<csl::CSLContext*>(context_);
 +
 +        CV_Assert(inputs.size() == 1);
 +        auto input_wrapper = inputs[0].dynamicCast<CUDABackendWrapper>();
 +        auto input_shape = input_wrapper->getShape();
 +
 +        CV_Assert(outputs.size() == 1);
 +        auto output_wrapper = outputs[0].dynamicCast<CUDABackendWrapper>();
 +        auto output_shape = output_wrapper->getShape();
 +
 +        const auto output_feature_maps = blobs[0].size[0];
 +        const auto input_feature_maps = input_shape[1];
 +        const auto input_feature_maps_per_group = blobs[0].size[1];
 +        const auto groups = input_feature_maps / input_feature_maps_per_group;
 +
 +        ConvolutionConfiguration config;
 +        config.kernel_size.assign(std::begin(kernel_size), std::end(kernel_size));
 +        config.dilations.assign(std::begin(dilations), std::end(dilations));
 +        config.strides.assign(std::begin(strides), std::end(strides));
 +
 +        if (padMode.empty())
 +        {
 +            config.padMode = ConvolutionConfiguration::PaddingMode::MANUAL;
 +            config.pads_begin.assign(std::begin(pads_begin), std::end(pads_begin));
 +            config.pads_end.assign(std::begin(pads_end), std::end(pads_end));
 +        }
 +        else if (padMode == "VALID")
 +        {
 +            config.padMode = ConvolutionConfiguration::PaddingMode::VALID;
 +        }
 +        else if (padMode == "SAME")
 +        {
 +            config.padMode = ConvolutionConfiguration::PaddingMode::SAME;
 +        }
 +        else
 +        {
 +            CV_Error(Error::StsNotImplemented, padMode + " padding mode not supported by ConvolutionLayer");
 +        }
 +
 +        config.input_shape.assign(std::begin(input_shape), std::end(input_shape));
 +        config.output_shape.assign(std::begin(output_shape), std::end(output_shape));
 +        config.groups = groups;
 +
 +        config.activation_type = cudaActType;
 +        config.relu_negative_slope = cuda_relu_slope;
 +        config.crelu_floor = cuda_crelu_floor;
 +        config.crelu_ceil = cuda_crelu_ceil;
 +        config.power_exp = cuda_power_exp;
 +
 +        Mat filtersMat = fusedWeights ? weightsMat : blobs[0];
 +        Mat biasMat = (hasBias() || fusedBias) ? Mat(output_feature_maps, 1, CV_32F, biasvec.data()) : Mat();
 +        if (countNonZero(biasMat) == 0)
 +            biasMat = Mat();
 +
 +        return make_cuda_node<cuda4dnn::ConvolutionOp>(
 +            preferableTarget, std::move(context->stream), std::move(context->cudnn_handle), config, filtersMat, biasMat);
 +    }
 +#endif
 +
      virtual int64 getFLOPS(const std::vector<MatShape> &inputs,
                             const std::vector<MatShape> &outputs) const CV_OVERRIDE
      {
index 0000000,5d0f9f4..95dd638
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,117 +1,117 @@@
 -        String fill_string = params.get<String>("FillParameter", "ZERO").toLowerCase();
+ // 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) 2020, Intel Corporation, all rights reserved.
+ // Third party copyrights are property of their respective owners.
+ #include "../precomp.hpp"
+ #include "layers_common.hpp"
+ namespace cv { namespace dnn {
+ class FlowWarpLayerImpl CV_FINAL : public FlowWarpLayer
+ {
+ public:
+     FlowWarpLayerImpl(const LayerParams& params)
+     {
+         setParamsFrom(params);
++        String fill_string = toLowerCase(params.get<String>("FillParameter", "ZERO"));
+         if (fill_string != "zero")
+             CV_Error(Error::StsNotImplemented, "Only zero filling supported.");
+         fill_value = 0;
+     }
+     virtual bool getMemoryShapes(const std::vector<MatShape> &inputs,
+                                  const int requiredOutputs,
+                                  std::vector<MatShape> &outputs,
+                                  std::vector<MatShape> &internals) const CV_OVERRIDE
+     {
+         CV_Assert(inputs.size() == 2);
+         CV_Assert_N(inputs[0][0] == inputs[1][0], inputs[1][1] == 2,
+                     inputs[0][2] == inputs[1][2], inputs[0][3] == inputs[1][3]);
+         outputs.assign(1, inputs[0]);
+         return false;
+     }
+     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());
+         std::vector<Mat> inputs, outputs;
+         inputs_arr.getMatVector(inputs);
+         outputs_arr.getMatVector(outputs);
+         const int out_n = outputs[0].size[0];
+         const int out_c = outputs[0].size[1];
+         const int out_h = outputs[0].size[2];
+         const int out_w = outputs[0].size[3];
+         const int area = out_w * out_h;
+         const int total = area * out_c;
+         const float* image_data = inputs[0].ptr<float>();
+         const float* flow_data  = inputs[1].ptr<float>();
+         float* out_data = outputs[0].ptr<float>();
+         for (int n = 0; n < out_n; n++)
+         {
+             int off = total * n;
+             for (int x = 0; x < out_w; x++)
+             {
+                 for (int y = 0; y < out_h; y++)
+                 {
+                     int idx = 2 * area * n + y * out_w + x;
+                     float fx = flow_data[idx];
+                     float fy = flow_data[idx + area];
+                     float x2 = x + fx;
+                     float y2 = y + fy;
+                     if (x2 >= 0 && y2 >= 0 && x2 < out_w && y2 < out_h)
+                     {
+                         int ix2_L = x2;
+                         float alpha = x2 - ix2_L;
+                         int iy2_T = y2;
+                         float beta = y2 - iy2_T;
+                         int ix2_R = std::min(ix2_L + 1, out_w - 1);
+                         int iy2_B = std::min(iy2_T + 1, out_h - 1);
+                         for (int c = 0; c < out_c; c++)
+                         {
+                             float TL = image_data[off + c * area + iy2_T * out_w + ix2_L];
+                             float TR = image_data[off + c * area + iy2_T * out_w + ix2_R];
+                             float BL = image_data[off + c * area + iy2_B * out_w + ix2_L];
+                             float BR = image_data[off + c * area + iy2_B * out_w + ix2_R];
+                             out_data[off + c * area + y * out_w + x] = (1 - alpha) * (1 - beta) * TL +
+                                                                        (1 - alpha) * beta       * BL +
+                                                                         alpha      * (1 - beta) * TR +
+                                                                         alpha      * beta       * BR;
+                         }
+                     }
+                     else
+                     {
+                         for (int c = 0; c < out_c; c++)
+                             out_data[off + c * area + y * out_w + x] = fill_value;
+                     }
+                 }
+             }
+         }
+     }
+ private:
+     float fill_value;
+ };
+ Ptr<FlowWarpLayer> FlowWarpLayer::create(const LayerParams& params)
+ {
+     return Ptr<FlowWarpLayer>(new FlowWarpLayerImpl(params));
+ }
+ }}  // namespace cv::dnn
@@@ -103,12 -104,35 +104,35 @@@ public
          String prototxt = _tf(basename + ".prototxt");
          String caffemodel = _tf(basename + ".caffemodel");
  
-         String inpfile = (useCommonInputBlob) ? _tf("blob.npy") : _tf(basename + ".input.npy");
-         String outfile = _tf(basename + ".npy");
-         Mat inp = blobFromNPY(inpfile);
-         Mat ref = blobFromNPY(outfile);
-         checkBackend(&inp, &ref);
+         std::vector<Mat> inps, refs, outs;
+         if (numInps > 1)
+         {
+             for (int i = 0; i < numInps; i++)
+             {
 -                String inpfile = _tf(basename + ".input_" + (i + '0') + ".npy");
++                String inpfile = _tf(basename + cv::format(".input_%d.npy", i));
+                 inps.push_back(blobFromNPY(inpfile));
+             }
+         }
+         else
+         {
+             String inpfile = (useCommonInputBlob) ? _tf("blob.npy") : _tf(basename + ".input.npy");
+             inps.push_back(blobFromNPY(inpfile));
+         }
+         if (numOuts > 1)
+         {
+             for (int i = 0; i < numOuts; i++)
+             {
 -                String outfile = _tf(basename + "_" + (i + '0') + ".npy");
++                String outfile = _tf(basename + cv::format("_%d.npy", i));
+                 refs.push_back(blobFromNPY(outfile));
+             }
+         }
+         else
+         {
+             String outfile = _tf(basename + ".npy");
+             refs.push_back(blobFromNPY(outfile));
+         }
  
          Net net = readNetFromCaffe(prototxt, (useCaffeModel) ? caffemodel : String());
          ASSERT_FALSE(net.empty());
          net.setPreferableBackend(backend);
          net.setPreferableTarget(target);
  
-         net.setInput(inp, "input");
-         Mat out = net.forward("output");
-         normAssert(ref, out, "", l1 ? l1 : default_l1, lInf ? lInf : default_lInf);
+         String inp_name = "input";
+         if (numInps > 1)
+         {
+             for (int i = 0; i < numInps; i++)
+             {
 -                net.setInput(inps[i], inp_name + "_" + (i + '0'));
++                net.setInput(inps[i], inp_name + cv::format("_%d", i));
+             }
+         }
+         else
+         {
+             net.setInput(inps.back(), inp_name);
+         }
+         net.forward(outs);
+         for (int i = 0; i < refs.size(); i++)
+         {
+             normAssert(refs[i], outs[i], "", l1 ? l1 : default_l1, lInf ? lInf : default_lInf);
+         }
      }
  };