github.com/kaydxh/golang@v0.0.131/pkg/gocv/cgo/third_path/opencv4/include/opencv2/gapi/fluid/gfluidkernel.hpp (about)

     1  // This file is part of OpenCV project.
     2  // It is subject to the license terms in the LICENSE file found in the top-level directory
     3  // of this distribution and at http://opencv.org/license.html.
     4  //
     5  // Copyright (C) 2018-2019 Intel Corporation
     6  
     7  
     8  #ifndef OPENCV_GAPI_FLUID_KERNEL_HPP
     9  #define OPENCV_GAPI_FLUID_KERNEL_HPP
    10  
    11  #include <vector>
    12  #include <functional>
    13  #include <map>
    14  #include <unordered_map>
    15  
    16  #include <opencv2/gapi/opencv_includes.hpp>
    17  #include <opencv2/gapi/gcommon.hpp>
    18  #include <opencv2/gapi/gkernel.hpp>
    19  #include <opencv2/gapi/garg.hpp>
    20  
    21  #include <opencv2/gapi/fluid/gfluidbuffer.hpp>
    22  
    23  // FIXME: namespace scheme for backends?
    24  namespace cv {
    25  
    26  namespace gapi
    27  {
    28  /**
    29   * @brief This namespace contains G-API Fluid backend functions, structures, and symbols.
    30   */
    31  namespace fluid
    32  {
    33      /**
    34       * \addtogroup gapi_std_backends G-API Standard Backends
    35       * @{
    36       */
    37      /**
    38       * @brief Get a reference to Fluid backend.
    39       *
    40       * @sa gapi_std_backends
    41       */
    42      GAPI_EXPORTS cv::gapi::GBackend backend();
    43      /** @} */
    44  } // namespace fluid
    45  } // namespace gapi
    46  
    47  
    48  class GAPI_EXPORTS GFluidKernel
    49  {
    50  public:
    51      enum class Kind
    52      {
    53          Filter,
    54          Resize,
    55          YUV420toRGB //Color conversion of 4:2:0 chroma sub-sampling formats (NV12, I420 ..etc) to RGB
    56      };
    57  
    58      // This function is a generic "doWork" callback
    59      using F = std::function<void(const cv::GArgs&, const std::vector<gapi::fluid::Buffer*> &)>;
    60  
    61      // This function is a generic "initScratch" callback
    62      using IS = std::function<void(const cv::GMetaArgs &, const cv::GArgs&, gapi::fluid::Buffer &)>;
    63  
    64      // This function is a generic "resetScratch" callback
    65      using RS = std::function<void(gapi::fluid::Buffer &)>;
    66  
    67      // This function describes kernel metadata inference rule.
    68      using M = std::function<GMetaArgs(const GMetaArgs &, const GArgs &)>;
    69  
    70      // This function is a generic "getBorder" callback (extracts border-related data from kernel's input parameters)
    71      using B = std::function<gapi::fluid::BorderOpt(const GMetaArgs&, const GArgs&)>;
    72  
    73      // This function is a generic "getWindow" callback (extracts window-related data from kernel's input parameters)
    74      using GW = std::function<int(const GMetaArgs&, const GArgs&)>;
    75  
    76      // FIXME: move implementations out of header file
    77      GFluidKernel() {}
    78      GFluidKernel(Kind k, int l, bool scratch, const F& f, const IS &is, const RS &rs, const B& b, const GW& win)
    79          : m_kind(k)
    80          , m_lpi(l)
    81          , m_scratch(scratch)
    82          , m_f(f)
    83          , m_is(is)
    84          , m_rs(rs)
    85          , m_b(b)
    86          , m_gw(win) {}
    87  
    88      Kind m_kind;
    89      const int  m_lpi     = -1;
    90      const bool m_scratch = false;
    91  
    92      const F    m_f;
    93      const IS   m_is;
    94      const RS   m_rs;
    95      const B    m_b;
    96      const GW   m_gw;
    97  };
    98  
    99  // FIXME!!!
   100  // This is the temporary and experimental API
   101  // which should be replaced by runtime roi-based scheduling
   102  /** \addtogroup gapi_compile_args
   103   * @{
   104   */
   105  /**
   106   * @brief This structure allows to control the output image region
   107   * which Fluid backend will produce in the graph.
   108   *
   109   * This feature is useful for external tiling and parallelism, but
   110   * will be deprecated in the future releases.
   111   */
   112  struct GFluidOutputRois
   113  {
   114      std::vector<cv::Rect> rois;
   115  };
   116  
   117  /**
   118   * @brief This structure forces Fluid backend to generate multiple
   119   * parallel output regions in the graph. These regions execute in parallel.
   120   *
   121   * This feature may be deprecated in the future releases.
   122   */
   123  struct GFluidParallelOutputRois
   124  {
   125      std::vector<GFluidOutputRois> parallel_rois;
   126  };
   127  
   128  /**
   129   * @brief This structure allows to customize the way how Fluid executes
   130   * parallel regions.
   131   *
   132   * For example, user can utilize his own threading runtime via this parameter.
   133   * The `parallel_for` member functor is called by the Fluid runtime with the
   134   * following arguments:
   135   *
   136   * @param size Size of the parallel range to process
   137   * @param f A function which should be called for every integer index
   138   *   in this range by the specified parallel_for implementation.
   139   *
   140   * This feature may be deprecated in the future releases.
   141   */
   142  struct GFluidParallelFor
   143  {
   144      //this function accepts:
   145      // - size of the "parallel" range as the first argument
   146      // - and a function to be called on the range items, designated by item index
   147      std::function<void(std::size_t size, std::function<void(std::size_t index)>)> parallel_for;
   148  };
   149  /** @} gapi_compile_args */
   150  
   151  namespace detail
   152  {
   153  template<> struct CompileArgTag<GFluidOutputRois>
   154  {
   155      static const char* tag() { return "gapi.fluid.outputRois"; }
   156  };
   157  
   158  template<> struct CompileArgTag<GFluidParallelFor>
   159  {
   160      static const char* tag() { return "gapi.fluid.parallelFor"; }
   161  };
   162  
   163  template<> struct CompileArgTag<GFluidParallelOutputRois>
   164  {
   165      static const char* tag() { return "gapi.fluid.parallelOutputRois"; }
   166  };
   167  
   168  } // namespace detail
   169  
   170  namespace detail
   171  {
   172  template<class T> struct fluid_get_in;
   173  template<> struct fluid_get_in<cv::GMat>
   174  {
   175      static const cv::gapi::fluid::View& get(const cv::GArgs &in_args, int idx)
   176      {
   177          return *in_args[idx].unsafe_get<cv::gapi::fluid::View*>();
   178      }
   179  };
   180  
   181  template<> struct fluid_get_in<cv::GScalar>
   182  {
   183      // FIXME: change to return by reference when moved to own::Scalar
   184      static const cv::Scalar get(const cv::GArgs &in_args, int idx)
   185      {
   186          return in_args[idx].unsafe_get<cv::Scalar>();
   187      }
   188  };
   189  
   190  template<typename U> struct fluid_get_in<cv::GArray<U>>
   191  {
   192      static const std::vector<U>& get(const cv::GArgs &in_args, int idx)
   193      {
   194          return in_args.at(idx).unsafe_get<cv::detail::VectorRef>().rref<U>();
   195      }
   196  };
   197  
   198  template<typename U> struct fluid_get_in<cv::GOpaque<U>>
   199  {
   200      static const U& get(const cv::GArgs &in_args, int idx)
   201      {
   202          return in_args.at(idx).unsafe_get<cv::detail::OpaqueRef>().rref<U>();
   203      }
   204  };
   205  
   206  template<class T> struct fluid_get_in
   207  {
   208      static const T& get(const cv::GArgs &in_args, int idx)
   209      {
   210          return in_args[idx].unsafe_get<T>();
   211      }
   212  };
   213  
   214  template<bool, typename Impl, typename... Ins>
   215  struct scratch_helper;
   216  
   217  template<typename Impl, typename... Ins>
   218  struct scratch_helper<true, Impl, Ins...>
   219  {
   220      // Init
   221      template<int... IIs>
   222      static void help_init_impl(const cv::GMetaArgs &metas,
   223                                 const cv::GArgs     &in_args,
   224                                 gapi::fluid::Buffer &scratch_buf,
   225                                 detail::Seq<IIs...>)
   226      {
   227          Impl::initScratch(get_in_meta<Ins>(metas, in_args, IIs)..., scratch_buf);
   228      }
   229  
   230      static void help_init(const cv::GMetaArgs &metas,
   231                            const cv::GArgs     &in_args,
   232                            gapi::fluid::Buffer &b)
   233      {
   234          help_init_impl(metas, in_args, b, typename detail::MkSeq<sizeof...(Ins)>::type());
   235      }
   236  
   237      // Reset
   238      static void help_reset(gapi::fluid::Buffer &b)
   239      {
   240          Impl::resetScratch(b);
   241      }
   242  };
   243  
   244  template<typename Impl, typename... Ins>
   245  struct scratch_helper<false, Impl, Ins...>
   246  {
   247      static void help_init(const cv::GMetaArgs &,
   248                            const cv::GArgs     &,
   249                            gapi::fluid::Buffer &)
   250      {
   251          GAPI_Assert(false);
   252      }
   253      static void help_reset(gapi::fluid::Buffer &)
   254      {
   255          GAPI_Assert(false);
   256      }
   257  };
   258  
   259  template<typename T> struct is_gmat_type
   260  {
   261      static const constexpr bool value = std::is_same<cv::GMat, T>::value;
   262  };
   263  
   264  template<bool CallCustomGetBorder, typename Impl, typename... Ins>
   265  struct get_border_helper;
   266  
   267  template<typename Impl, typename... Ins>
   268  struct get_border_helper<true, Impl, Ins...>
   269  {
   270      template<int... IIs>
   271      static gapi::fluid::BorderOpt get_border_impl(const GMetaArgs &metas,
   272                                                    const cv::GArgs &in_args,
   273                                                    cv::detail::Seq<IIs...>)
   274      {
   275          return util::make_optional(Impl::getBorder(cv::detail::get_in_meta<Ins>(metas, in_args, IIs)...));
   276      }
   277  
   278      static gapi::fluid::BorderOpt help(const GMetaArgs &metas,
   279                                         const cv::GArgs &in_args)
   280      {
   281          return get_border_impl(metas, in_args, typename detail::MkSeq<sizeof...(Ins)>::type());
   282      }
   283  };
   284  
   285  template<typename Impl, typename... Ins>
   286  struct get_border_helper<false, Impl, Ins...>
   287  {
   288      static gapi::fluid::BorderOpt help(const cv::GMetaArgs &,
   289                                         const cv::GArgs     &)
   290      {
   291          return {};
   292      }
   293  };
   294  
   295  template<bool CallCustomGetWindow, typename, typename... Ins>
   296  struct get_window_helper;
   297  
   298  template<typename Impl, typename... Ins>
   299  struct get_window_helper<true, Impl, Ins...>
   300  {
   301      template<int... IIs>
   302      static int get_window_impl(const GMetaArgs &metas,
   303                                 const cv::GArgs &in_args,
   304                                 cv::detail::Seq<IIs...>)
   305      {
   306          return Impl::getWindow(cv::detail::get_in_meta<Ins>(metas, in_args, IIs)...);
   307      }
   308  
   309      static int help(const GMetaArgs &metas, const cv::GArgs &in_args)
   310      {
   311          return get_window_impl(metas, in_args, typename detail::MkSeq<sizeof...(Ins)>::type());
   312      }
   313  };
   314  
   315  template<typename Impl, typename... Ins>
   316  struct get_window_helper<false, Impl, Ins...>
   317  {
   318      static int help(const cv::GMetaArgs &,
   319                      const cv::GArgs     &)
   320      {
   321          return Impl::Window;
   322      }
   323  };
   324  
   325  template<typename C, typename T>
   326  struct has_Window
   327  {
   328  private:
   329      template<class U>
   330      static constexpr auto Check(U*) -> typename std::is_same<decltype(U::Window), T>::type;
   331  
   332      template<typename>
   333      static constexpr std::false_type Check(...);
   334  
   335      typedef decltype(Check<C>(0)) Result;
   336  
   337  public:
   338      static constexpr bool value = Result::value;
   339  };
   340  
   341  template<bool hasWindow, typename Impl>
   342  struct callCustomGetBorder;
   343  
   344  template<typename Impl>
   345  struct callCustomGetBorder<true, Impl>
   346  {
   347      static constexpr bool value = (Impl::Window != 1);
   348  };
   349  
   350  template<typename Impl>
   351  struct callCustomGetBorder<false, Impl>
   352  {
   353      static constexpr bool value = true;
   354  };
   355  
   356  template<typename, typename, typename, bool UseScratch>
   357  struct FluidCallHelper;
   358  
   359  template<typename Impl, typename... Ins, typename... Outs, bool UseScratch>
   360  struct FluidCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>, UseScratch>
   361  {
   362      static_assert(all_satisfy<is_gmat_type, Outs...>::value, "return type must be GMat");
   363      static_assert(contains<GMat, Ins...>::value, "input must contain at least one GMat");
   364  
   365      // Execution dispatcher ////////////////////////////////////////////////////
   366      template<int... IIs, int... OIs>
   367      static void call_impl(const cv::GArgs &in_args,
   368                            const std::vector<gapi::fluid::Buffer*> &out_bufs,
   369                            detail::Seq<IIs...>,
   370                            detail::Seq<OIs...>)
   371      {
   372          Impl::run(fluid_get_in<Ins>::get(in_args, IIs)..., *out_bufs[OIs]...);
   373      }
   374  
   375      static void call(const cv::GArgs &in_args,
   376                       const std::vector<gapi::fluid::Buffer*> &out_bufs)
   377      {
   378          constexpr int numOuts = (sizeof...(Outs)) + (UseScratch ? 1 : 0);
   379          call_impl(in_args, out_bufs,
   380                    typename detail::MkSeq<sizeof...(Ins)>::type(),
   381                    typename detail::MkSeq<numOuts>::type());
   382      }
   383  
   384      // Scratch buffer initialization dispatcher ////////////////////////////////
   385      static void init_scratch(const GMetaArgs &metas,
   386                               const cv::GArgs &in_args,
   387                               gapi::fluid::Buffer &b)
   388      {
   389          scratch_helper<UseScratch, Impl, Ins...>::help_init(metas, in_args, b);
   390      }
   391  
   392      // Scratch buffer reset dispatcher /////////////////////////////////////////
   393      static void reset_scratch(gapi::fluid::Buffer &scratch_buf)
   394      {
   395          scratch_helper<UseScratch, Impl, Ins...>::help_reset(scratch_buf);
   396      }
   397  
   398      static gapi::fluid::BorderOpt getBorder(const GMetaArgs &metas, const cv::GArgs &in_args)
   399      {
   400          constexpr bool hasWindow = has_Window<Impl, const int>::value;
   401  
   402          // User must provide "init" callback if Window != 1
   403          // TODO: move to constexpr if when we enable C++17
   404          return get_border_helper<callCustomGetBorder<hasWindow, Impl>::value, Impl, Ins...>::help(metas, in_args);
   405      }
   406  
   407      static int getWindow(const GMetaArgs &metas, const cv::GArgs &in_args)
   408      {
   409          constexpr bool callCustomGetWindow = !(has_Window<Impl, const int>::value);
   410          return get_window_helper<callCustomGetWindow, Impl, Ins...>::help(metas, in_args);
   411      }
   412  };
   413  } // namespace detail
   414  
   415  
   416  template<class Impl, class K, bool UseScratch>
   417  class GFluidKernelImpl : public cv::detail::KernelTag
   418  {
   419      static const int LPI = 1;
   420      static const auto Kind = GFluidKernel::Kind::Filter;
   421      using P = detail::FluidCallHelper<Impl, typename K::InArgs, typename K::OutArgs, UseScratch>;
   422  
   423  public:
   424      using API = K;
   425  
   426      static GFluidKernel kernel()
   427      {
   428          // FIXME: call() and getOutMeta() needs to be renamed so it is clear these
   429          // functions are internal wrappers, not user API
   430          return GFluidKernel(Impl::Kind, Impl::LPI,
   431                              UseScratch,
   432                              &P::call, &P::init_scratch, &P::reset_scratch, &P::getBorder, &P::getWindow);
   433      }
   434  
   435      static cv::gapi::GBackend backend() { return cv::gapi::fluid::backend(); }
   436  };
   437  
   438  #define GAPI_FLUID_KERNEL(Name, API, Scratch) struct Name: public cv::GFluidKernelImpl<Name, API, Scratch>
   439  
   440  } // namespace cv
   441  
   442  #endif // OPENCV_GAPI_GCPUKERNEL_HPP