Merge remote-tracking branch 'upstream/3.4' into merge-3.4
authorAlexander Alekhin <alexander.alekhin@intel.com>
Tue, 4 Sep 2018 16:35:38 +0000 (19:35 +0300)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Tue, 4 Sep 2018 18:39:03 +0000 (18:39 +0000)
21 files changed:
1  2 
cmake/OpenCVFindLibsPerf.cmake
cmake/templates/cvconfig.h.in
doc/Doxyfile.in
doc/tutorials/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.markdown
doc/tutorials/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.markdown
modules/core/include/opencv2/core/mat.hpp
modules/core/include/opencv2/core/mat.inl.hpp
modules/core/src/arithm.cpp
modules/core/src/count_non_zero.cpp
modules/core/src/norm.cpp
modules/core/test/test_mat.cpp
modules/dnn/include/opencv2/dnn/dnn.hpp
modules/dnn/src/dnn.cpp
modules/dnn/src/tensorflow/tf_graph_simplifier.cpp
modules/dnn/src/tensorflow/tf_graph_simplifier.hpp
modules/dnn/src/tensorflow/tf_importer.cpp
modules/dnn/test/test_common.hpp
modules/imgcodecs/src/loadsave.cpp
modules/imgproc/src/smooth.cpp
modules/js/src/embindgen.py
modules/videoio/src/cap_v4l.cpp

Simple merge
Simple merge
diff --cc doc/Doxyfile.in
Simple merge
@@@ -196,9 -204,16 +202,12 @@@ public
      _InputArray(const UMat& um);
      _InputArray(const std::vector<UMat>& umv);
  
 -#ifdef CV_CXX_STD_ARRAY
      template<typename _Tp, std::size_t _Nm> _InputArray(const std::array<_Tp, _Nm>& arr);
      template<std::size_t _Nm> _InputArray(const std::array<Mat, _Nm>& arr);
 -#endif
  
 -#ifdef CV_CXX_STD_ARRAY
+     template<typename _Tp> static _InputArray rawIn(const std::vector<_Tp>& vec);
 -#endif
+     template<typename _Tp, std::size_t _Nm> static _InputArray rawIn(const std::array<_Tp, _Nm>& arr);
      Mat getMat(int idx=-1) const;
      Mat getMat_(int idx=-1) const;
      UMat getUMat(int idx=-1) const;
@@@ -328,12 -343,17 +337,13 @@@ public
      _OutputArray(const UMat& m);
      _OutputArray(const std::vector<UMat>& vec);
  
--#ifdef CV_CXX_STD_ARRAY
      template<typename _Tp, std::size_t _Nm> _OutputArray(std::array<_Tp, _Nm>& arr);
      template<typename _Tp, std::size_t _Nm> _OutputArray(const std::array<_Tp, _Nm>& arr);
      template<std::size_t _Nm> _OutputArray(std::array<Mat, _Nm>& arr);
      template<std::size_t _Nm> _OutputArray(const std::array<Mat, _Nm>& arr);
--#endif
+     template<typename _Tp> static _OutputArray rawOut(std::vector<_Tp>& vec);
 -#ifdef CV_CXX_STD_ARRAY
+     template<typename _Tp, std::size_t _Nm> static _OutputArray rawOut(std::array<_Tp, _Nm>& arr);
 -#endif
  
      bool fixedSize() const;
      bool fixedType() const;
@@@ -397,12 -417,17 +407,13 @@@ public
      _InputOutputArray(const UMat& m);
      _InputOutputArray(const std::vector<UMat>& vec);
  
--#ifdef CV_CXX_STD_ARRAY
      template<typename _Tp, std::size_t _Nm> _InputOutputArray(std::array<_Tp, _Nm>& arr);
      template<typename _Tp, std::size_t _Nm> _InputOutputArray(const std::array<_Tp, _Nm>& arr);
      template<std::size_t _Nm> _InputOutputArray(std::array<Mat, _Nm>& arr);
      template<std::size_t _Nm> _InputOutputArray(const std::array<Mat, _Nm>& arr);
--#endif
+     template<typename _Tp> static _InputOutputArray rawInOut(std::vector<_Tp>& vec);
 -#ifdef CV_CXX_STD_ARRAY
+     template<typename _Tp, std::size_t _Nm> _InputOutputArray rawInOut(std::array<_Tp, _Nm>& arr);
 -#endif
  
  };
  
@@@ -990,12 -1023,13 +1008,10 @@@ public
      /** @overload
      */
      template<typename _Tp> explicit Mat(const std::initializer_list<int> sizes, const std::initializer_list<_Tp> list);
 -#endif
  
--#ifdef CV_CXX_STD_ARRAY
      /** @overload
      */
      template<typename _Tp, size_t _Nm> explicit Mat(const std::array<_Tp, _Nm>& arr, bool copyData=false);
--#endif
  
      /** @overload
      */
      template<typename _Tp, int n> operator Vec<_Tp, n>() const;
      template<typename _Tp, int m, int n> operator Matx<_Tp, m, n>() const;
  
--#ifdef CV_CXX_STD_ARRAY
      template<typename _Tp, std::size_t _Nm> operator std::array<_Tp, _Nm>() const;
--#endif
  
      /** @brief Reports whether the matrix is continuous or not.
  
@@@ -2211,12 -2247,14 +2225,10 @@@ public
      explicit Mat_(const Point3_<typename DataType<_Tp>::channel_type>& pt, bool copyData=true);
      explicit Mat_(const MatCommaInitializer_<_Tp>& commaInitializer);
  
 -#ifdef CV_CXX11
      Mat_(std::initializer_list<_Tp> values);
      explicit Mat_(const std::initializer_list<int> sizes, const std::initializer_list<_Tp> values);
 -#endif
  
--#ifdef CV_CXX_STD_ARRAY
      template <std::size_t _Nm> explicit Mat_(const std::array<_Tp, _Nm>& arr, bool copyData=false);
--#endif
  
      Mat_& operator = (const Mat& m);
      Mat_& operator = (const Mat_& m);
      //! conversion to vector.
      operator std::vector<_Tp>() const;
  
--#ifdef CV_CXX_STD_ARRAY
      //! conversion to array.
      template<std::size_t _Nm> operator std::array<_Tp, _Nm>() const;
--#endif
  
      //! conversion to Vec
      template<int n> operator Vec<typename DataType<_Tp>::channel_type, n>() const;
@@@ -134,6 -150,27 +144,25 @@@ inline _InputArray::_InputArray(const o
  inline _InputArray::_InputArray(const cuda::HostMem& cuda_mem)
  { init(CUDA_HOST_MEM + ACCESS_READ, &cuda_mem); }
  
 -#ifdef CV_CXX_STD_ARRAY
+ template<typename _Tp> inline
+ _InputArray _InputArray::rawIn(const std::vector<_Tp>& vec)
+ {
+     _InputArray v;
+     v.flags = _InputArray::FIXED_TYPE + _InputArray::STD_VECTOR + rawType<_Tp>() + ACCESS_READ;
+     v.obj = (void*)&vec;
+     return v;
+ }
 -#endif
+ template<typename _Tp, std::size_t _Nm> inline
+ _InputArray _InputArray::rawIn(const std::array<_Tp, _Nm>& arr)
+ {
+     _InputArray v;
+     v.flags = FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_READ;
+     v.obj = (void*)arr.data();
+     v.sz = Size(1, _Nm);
+     return v;
+ }
  inline _InputArray::~_InputArray() {}
  
  inline Mat _InputArray::getMat(int i) const
@@@ -261,6 -310,27 +290,25 @@@ inline _OutputArray::_OutputArray(cons
  inline _OutputArray::_OutputArray(const cuda::HostMem& cuda_mem)
  { init(FIXED_TYPE + FIXED_SIZE + CUDA_HOST_MEM + ACCESS_WRITE, &cuda_mem); }
  
 -#ifdef CV_CXX_STD_ARRAY
+ template<typename _Tp> inline
+ _OutputArray _OutputArray::rawOut(std::vector<_Tp>& vec)
+ {
+     _OutputArray v;
+     v.flags = _InputArray::FIXED_TYPE + _InputArray::STD_VECTOR + rawType<_Tp>() + ACCESS_WRITE;
+     v.obj = (void*)&vec;
+     return v;
+ }
 -#endif
+ template<typename _Tp, std::size_t _Nm> inline
+ _OutputArray _OutputArray::rawOut(std::array<_Tp, _Nm>& arr)
+ {
+     _OutputArray v;
+     v.flags = FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_WRITE;
+     v.obj = (void*)arr.data();
+     v.sz = Size(1, _Nm);
+     return v;
+ }
  ///////////////////////////////////////////////////////////////////////////////////////////
  
  inline _InputOutputArray::_InputOutputArray() { init(ACCESS_RW, 0); }
@@@ -370,6 -447,32 +418,30 @@@ inline _InputOutputArray::_InputOutputA
  inline _InputOutputArray::_InputOutputArray(const cuda::HostMem& cuda_mem)
  { init(FIXED_TYPE + FIXED_SIZE + CUDA_HOST_MEM + ACCESS_RW, &cuda_mem); }
  
 -#ifdef CV_CXX_STD_ARRAY
+ template<typename _Tp> inline
+ _InputOutputArray _InputOutputArray::rawInOut(std::vector<_Tp>& vec)
+ {
+     _InputOutputArray v;
+     v.flags = _InputArray::FIXED_TYPE + _InputArray::STD_VECTOR + rawType<_Tp>() + ACCESS_RW;
+     v.obj = (void*)&vec;
+     return v;
+ }
 -#endif
+ template<typename _Tp, std::size_t _Nm> inline
+ _InputOutputArray _InputOutputArray::rawInOut(std::array<_Tp, _Nm>& arr)
+ {
+     _InputOutputArray v;
+     v.flags = FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_RW;
+     v.obj = (void*)arr.data();
+     v.sz = Size(1, _Nm);
+     return v;
+ }
+ template<typename _Tp> static inline _InputArray rawIn(_Tp& v) { return _InputArray::rawIn(v); }
+ template<typename _Tp> static inline _OutputArray rawOut(_Tp& v) { return _OutputArray::rawOut(v); }
+ template<typename _Tp> static inline _InputOutputArray rawInOut(_Tp& v) { return _InputOutputArray::rawInOut(v); }
  CV__DEBUG_NS_END
  
  //////////////////////////////////////////// Mat //////////////////////////////////////////
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -782,7 -782,109 +782,109 @@@ void releaseTensor(tensorflow::TensorPr
      }
  }
  
 -CV__DNN_EXPERIMENTAL_NS_END
+ static void permute(google::protobuf::RepeatedPtrField<tensorflow::NodeDef>* data,
+                     const std::vector<int>& indices)
+ {
+     const int num = data->size();
+     CV_Assert(num == indices.size());
+     std::vector<int> elemIdToPos(num);
+     std::vector<int> posToElemId(num);
+     for (int i = 0; i < num; ++i)
+     {
+         elemIdToPos[i] = i;
+         posToElemId[i] = i;
+     }
+     for (int i = 0; i < num; ++i)
+     {
+         int elemId = indices[i];
+         int pos = elemIdToPos[elemId];
+         if (pos != i)
+         {
+             data->SwapElements(i, pos);
+             const int swappedElemId = posToElemId[i];
+             elemIdToPos[elemId] = i;
+             elemIdToPos[swappedElemId] = pos;
+             posToElemId[i] = elemId;
+             posToElemId[pos] = swappedElemId;
+         }
+     }
+ }
+ // Is based on tensorflow::graph_transforms::SortByExecutionOrder
+ void sortByExecutionOrder(tensorflow::GraphDef& net)
+ {
+     // Maps node's name to index at net.node() list.
+     std::map<std::string, int> nodesMap;
+     std::map<std::string, int>::iterator nodesMapIt;
+     for (int i = 0; i < net.node_size(); ++i)
+     {
+         const tensorflow::NodeDef& node = net.node(i);
+         nodesMap.insert(std::make_pair(node.name(), i));
+     }
+     // Indices of nodes which use specific node as input.
+     std::vector<std::vector<int> > edges(nodesMap.size());
+     std::vector<int> numRefsToAdd(nodesMap.size(), 0);
+     std::vector<int> nodesToAdd;
+     for (int i = 0; i < net.node_size(); ++i)
+     {
+         const tensorflow::NodeDef& node = net.node(i);
+         for (int j = 0; j < node.input_size(); ++j)
+         {
+             std::string inpName = node.input(j);
+             inpName = inpName.substr(0, inpName.rfind(':'));
+             inpName = inpName.substr(inpName.find('^') + 1);
+             nodesMapIt = nodesMap.find(inpName);
+             CV_Assert(nodesMapIt != nodesMap.end());
+             edges[nodesMapIt->second].push_back(i);
+         }
+         if (node.input_size() == 0)
+             nodesToAdd.push_back(i);
+         else
+         {
+             if (node.op() == "Merge" || node.op() == "RefMerge")
+             {
+                 int numControlEdges = 0;
+                 for (int j = 0; j < node.input_size(); ++j)
+                     numControlEdges += node.input(j)[0] == '^';
+                 numRefsToAdd[i] = numControlEdges + 1;
+             }
+             else
+                 numRefsToAdd[i] = node.input_size();
+         }
+     }
+     std::vector<int> permIds;
+     permIds.reserve(net.node_size());
+     while (!nodesToAdd.empty())
+     {
+         int nodeToAdd = nodesToAdd.back();
+         nodesToAdd.pop_back();
+         permIds.push_back(nodeToAdd);
+         // std::cout << net.node(nodeToAdd).name() << '\n';
+         for (int i = 0; i < edges[nodeToAdd].size(); ++i)
+         {
+             int consumerId = edges[nodeToAdd][i];
+             if (numRefsToAdd[consumerId] > 0)
+             {
+                 if (numRefsToAdd[consumerId] == 1)
+                     nodesToAdd.push_back(consumerId);
+                 else
+                     CV_Assert(numRefsToAdd[consumerId] >= 0);
+                 numRefsToAdd[consumerId] -= 1;
+             }
+         }
+     }
+     CV_Assert(permIds.size() == net.node_size());
+     permute(net.mutable_node(), permIds);
+ }
 +CV__DNN_INLINE_NS_END
  }}  // namespace dnn, namespace cv
  
  #endif  // HAVE_PROTOBUF
@@@ -25,7 -25,9 +25,9 @@@ Mat getTensorContent(const tensorflow::
  
  void releaseTensor(tensorflow::TensorProto* tensor);
  
 -CV__DNN_EXPERIMENTAL_NS_END
+ void sortByExecutionOrder(tensorflow::GraphDef& net);
 +CV__DNN_INLINE_NS_END
  }}  // namespace dnn, namespace cv
  
  #endif  // HAVE_PROTOBUF
@@@ -1950,5 -1950,34 +1950,34 @@@ Net readNetFromTensorflow(const std::ve
                                   bufferConfigPtr, bufferConfig.size());
  }
  
 -CV__DNN_EXPERIMENTAL_NS_END
+ void writeTextGraph(const String& _model, const String& output)
+ {
+     String model = _model;
+     const std::string modelExt = model.substr(model.rfind('.') + 1);
+     if (modelExt != "pb")
+         CV_Error(Error::StsNotImplemented, "Only TensorFlow models support export to text file");
+     tensorflow::GraphDef net;
+     ReadTFNetParamsFromBinaryFileOrDie(model.c_str(), &net);
+     sortByExecutionOrder(net);
+     RepeatedPtrField<tensorflow::NodeDef>::iterator it;
+     for (it = net.mutable_node()->begin(); it != net.mutable_node()->end(); ++it)
+     {
+         if (it->op() == "Const")
+         {
+             it->mutable_attr()->at("value").mutable_tensor()->clear_tensor_content();
+         }
+     }
+     std::string content;
+     google::protobuf::TextFormat::PrintToString(net, &content);
+     std::ofstream ofs(output.c_str());
+     ofs << content;
+     ofs.close();
+ }
 +CV__DNN_INLINE_NS_END
  }} // namespace
  #ifndef __OPENCV_TEST_COMMON_HPP__
  #define __OPENCV_TEST_COMMON_HPP__
  
 -CV__DNN_EXPERIMENTAL_NS_BEGIN
+ #ifdef HAVE_OPENCL
+ #include "opencv2/core/ocl.hpp"
+ #endif
+ namespace cv { namespace dnn {
 -CV__DNN_EXPERIMENTAL_NS_END
++CV__DNN_INLINE_NS_BEGIN
+ static inline void PrintTo(const cv::dnn::Backend& v, std::ostream* os)
+ {
+     switch (v) {
+     case DNN_BACKEND_DEFAULT: *os << "DEFAULT"; return;
+     case DNN_BACKEND_HALIDE: *os << "HALIDE"; return;
+     case DNN_BACKEND_INFERENCE_ENGINE: *os << "DLIE"; return;
+     case DNN_BACKEND_OPENCV: *os << "OCV"; return;
+     } // don't use "default:" to emit compiler warnings
+     *os << "DNN_BACKEND_UNKNOWN(" << v << ")";
+ }
+ static inline void PrintTo(const cv::dnn::Target& v, std::ostream* os)
+ {
+     switch (v) {
+     case DNN_TARGET_CPU: *os << "CPU"; return;
+     case DNN_TARGET_OPENCL: *os << "OCL"; return;
+     case DNN_TARGET_OPENCL_FP16: *os << "OCL_FP16"; return;
+     case DNN_TARGET_MYRIAD: *os << "MYRIAD"; return;
+     } // don't use "default:" to emit compiler warnings
+     *os << "DNN_TARGET_UNKNOWN(" << v << ")";
+ }
+ using opencv_test::tuple;
+ using opencv_test::get;
+ static inline void PrintTo(const tuple<cv::dnn::Backend, cv::dnn::Target> v, std::ostream* os)
+ {
+     PrintTo(get<0>(v), os);
+     *os << "/";
+     PrintTo(get<1>(v), os);
+ }
++CV__DNN_INLINE_NS_END
+ }} // namespace
  static inline const std::string &getOpenCVExtraDir()
  {
      return cvtest::TS::ptr()->get_data_path();
Simple merge
Simple merge
Simple merge
Simple merge