github.com/kaydxh/golang@v0.0.131/pkg/gocv/cgo/third_path/opencv4/include/opencv2/gapi/infer.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) 2019-2021 Intel Corporation
     6  
     7  
     8  #ifndef OPENCV_GAPI_INFER_HPP
     9  #define OPENCV_GAPI_INFER_HPP
    10  
    11  // FIXME: Inference API is currently only available in full mode
    12  #if !defined(GAPI_STANDALONE)
    13  
    14  #include <functional>
    15  #include <string>  // string
    16  #include <utility> // tuple
    17  #include <type_traits> // is_same, false_type
    18  
    19  #include <opencv2/gapi/util/util.hpp> // all_satisfy
    20  #include <opencv2/gapi/util/any.hpp>  // any<>
    21  #include <opencv2/gapi/gkernel.hpp>   // GKernelType[M], GBackend
    22  #include <opencv2/gapi/garg.hpp>      // GArg
    23  #include <opencv2/gapi/gcommon.hpp>   // CompileArgTag
    24  #include <opencv2/gapi/gmetaarg.hpp>  // GMetaArg
    25  
    26  namespace cv {
    27  
    28  template<typename, typename> class GNetworkType;
    29  
    30  namespace detail {
    31  
    32  // Infer ///////////////////////////////////////////////////////////////////////
    33  template<typename T>
    34  struct accepted_infer_types {
    35      static constexpr const auto value =
    36              std::is_same<typename std::decay<T>::type, cv::GMat>::value
    37           || std::is_same<typename std::decay<T>::type, cv::GFrame>::value;
    38  };
    39  
    40  template<typename... Ts>
    41  using valid_infer_types = all_satisfy<accepted_infer_types, Ts...>;
    42  
    43  // Infer2 //////////////////////////////////////////////////////////////////////
    44  
    45  template<typename, typename>
    46  struct valid_infer2_types;
    47  
    48  // Terminal case 1 (50/50 success)
    49  template<typename T>
    50  struct valid_infer2_types< std::tuple<cv::GMat>, std::tuple<T> > {
    51      // By default, Nets are limited to GMat argument types only
    52      // for infer2, every GMat argument may translate to either
    53      // GArray<GMat> or GArray<Rect>. GArray<> part is stripped
    54      // already at this point.
    55      static constexpr const auto value =
    56              std::is_same<typename std::decay<T>::type, cv::GMat>::value
    57           || std::is_same<typename std::decay<T>::type, cv::Rect>::value;
    58  };
    59  
    60  // Terminal case 2 (100% failure)
    61  template<typename... Ts>
    62  struct valid_infer2_types< std::tuple<>, std::tuple<Ts...> >
    63      : public std::false_type {
    64  };
    65  
    66  // Terminal case 3 (100% failure)
    67  template<typename... Ns>
    68  struct valid_infer2_types< std::tuple<Ns...>, std::tuple<> >
    69      : public std::false_type {
    70  };
    71  
    72  // Recursion -- generic
    73  template<typename... Ns, typename T, typename...Ts>
    74  struct valid_infer2_types< std::tuple<cv::GMat,Ns...>, std::tuple<T,Ts...> > {
    75      static constexpr const auto value =
    76             valid_infer2_types< std::tuple<cv::GMat>, std::tuple<T> >::value
    77          && valid_infer2_types< std::tuple<Ns...>, std::tuple<Ts...> >::value;
    78  };
    79  
    80  // Struct stores network input/output names.
    81  // Used by infer<Generic>
    82  struct InOutInfo
    83  {
    84      std::vector<std::string> in_names;
    85      std::vector<std::string> out_names;
    86  };
    87  
    88  template <typename OutT>
    89  class GInferOutputsTyped
    90  {
    91  public:
    92      GInferOutputsTyped() = default;
    93      GInferOutputsTyped(std::shared_ptr<cv::GCall> call)
    94          : m_priv(std::make_shared<Priv>(std::move(call)))
    95      {
    96      }
    97  
    98      OutT at(const std::string& name)
    99      {
   100          auto it = m_priv->blobs.find(name);
   101          if (it == m_priv->blobs.end()) {
   102              // FIXME: Avoid modifying GKernel
   103              auto shape = cv::detail::GTypeTraits<OutT>::shape;
   104              m_priv->call->kernel().outShapes.push_back(shape);
   105              m_priv->call->kernel().outCtors.emplace_back(cv::detail::GObtainCtor<OutT>::get());
   106              auto out_idx = static_cast<int>(m_priv->blobs.size());
   107              it = m_priv->blobs.emplace(name,
   108                      cv::detail::Yield<OutT>::yield(*(m_priv->call), out_idx)).first;
   109              m_priv->info->out_names.push_back(name);
   110          }
   111          return it->second;
   112      }
   113  private:
   114      struct Priv
   115      {
   116          Priv(std::shared_ptr<cv::GCall> c)
   117              : call(std::move(c)), info(cv::util::any_cast<InOutInfo>(&call->params()))
   118          {
   119          }
   120  
   121          std::shared_ptr<cv::GCall> call;
   122          InOutInfo* info = nullptr;
   123          std::unordered_map<std::string, OutT> blobs;
   124      };
   125  
   126      std::shared_ptr<Priv> m_priv;
   127  };
   128  
   129  template <typename... Ts>
   130  class GInferInputsTyped
   131  {
   132  public:
   133      GInferInputsTyped()
   134          : m_priv(std::make_shared<Priv>())
   135      {
   136      }
   137  
   138      template <typename U>
   139      GInferInputsTyped<Ts...>& setInput(const std::string& name, U in)
   140      {
   141          m_priv->blobs.emplace(std::piecewise_construct,
   142                                std::forward_as_tuple(name),
   143                                std::forward_as_tuple(in));
   144          return *this;
   145      }
   146  
   147      using StorageT = cv::util::variant<Ts...>;
   148      StorageT& operator[](const std::string& name) {
   149          return m_priv->blobs[name];
   150      }
   151  
   152      using Map = std::unordered_map<std::string, StorageT>;
   153      const Map& getBlobs() const {
   154          return m_priv->blobs;
   155      }
   156  
   157  private:
   158      struct Priv
   159      {
   160          std::unordered_map<std::string, StorageT> blobs;
   161      };
   162  
   163      std::shared_ptr<Priv> m_priv;
   164  };
   165  
   166  template<typename InferT>
   167  std::shared_ptr<cv::GCall> makeCall(const std::string         &tag,
   168                                      std::vector<cv::GArg>    &&args,
   169                                      std::vector<std::string> &&names,
   170                                      cv::GKinds               &&kinds) {
   171      auto call = std::make_shared<cv::GCall>(GKernel{
   172                  InferT::id(),
   173                  tag,
   174                  InferT::getOutMeta,
   175                  {}, // outShape will be filled later
   176                  std::move(kinds),
   177                  {}, // outCtors will be filled later
   178              });
   179  
   180      call->setArgs(std::move(args));
   181      call->params() = cv::detail::InOutInfo{std::move(names), {}};
   182  
   183      return call;
   184  }
   185  
   186  } // namespace detail
   187  
   188  // TODO: maybe tuple_wrap_helper from util.hpp may help with this.
   189  // Multiple-return-value network definition (specialized base class)
   190  template<typename K, typename... R, typename... Args>
   191  class GNetworkType<K, std::function<std::tuple<R...>(Args...)> >
   192  {
   193  public:
   194      using InArgs  = std::tuple<Args...>;
   195      using OutArgs = std::tuple<R...>;
   196  
   197      using Result  = OutArgs;
   198      using API     = std::function<Result(Args...)>;
   199  
   200      using ResultL = std::tuple< cv::GArray<R>... >;
   201  };
   202  
   203  // Single-return-value network definition (specialized base class)
   204  template<typename K, typename R, typename... Args>
   205  class GNetworkType<K, std::function<R(Args...)> >
   206  {
   207  public:
   208      using InArgs  = std::tuple<Args...>;
   209      using OutArgs = std::tuple<R>;
   210  
   211      using Result  = R;
   212      using API     = std::function<R(Args...)>;
   213  
   214      using ResultL = cv::GArray<R>;
   215  };
   216  
   217  // InferAPI: Accepts either GMat or GFrame for very individual network's input
   218  template<class Net, class... Ts>
   219  struct InferAPI {
   220      using type = typename std::enable_if
   221          <    detail::valid_infer_types<Ts...>::value
   222            && std::tuple_size<typename Net::InArgs>::value == sizeof...(Ts)
   223          , std::function<typename Net::Result(Ts...)>
   224          >::type;
   225  };
   226  
   227  // InferAPIRoi: Accepts a rectangle and either GMat or GFrame
   228  template<class Net, class T>
   229  struct InferAPIRoi {
   230      using type = typename std::enable_if
   231          <    detail::valid_infer_types<T>::value
   232            && std::tuple_size<typename Net::InArgs>::value == 1u
   233            , std::function<typename Net::Result(cv::GOpaque<cv::Rect>, T)>
   234          >::type;
   235  };
   236  
   237  // InferAPIList: Accepts a list of rectangles and list of GMat/GFrames;
   238  // crops every input.
   239  template<class Net, class... Ts>
   240  struct InferAPIList {
   241      using type = typename std::enable_if
   242          <    detail::valid_infer_types<Ts...>::value
   243            && std::tuple_size<typename Net::InArgs>::value == sizeof...(Ts)
   244          , std::function<typename Net::ResultL(cv::GArray<cv::Rect>, Ts...)>
   245          >::type;
   246  };
   247  
   248  // APIList2 is also template to allow different calling options
   249  // (GArray<cv::Rect> vs GArray<cv::GMat> per input)
   250  template<class Net, typename T, class... Ts>
   251  struct InferAPIList2 {
   252      using type = typename std::enable_if
   253          < detail::valid_infer_types<T>::value &&
   254            cv::detail::valid_infer2_types< typename Net::InArgs
   255                                          , std::tuple<Ts...> >::value,
   256            std::function<typename Net::ResultL(T, cv::GArray<Ts>...)>
   257          >::type;
   258  };
   259  
   260  // Base "Infer" kernel. Note - for whatever network, kernel ID
   261  // is always the same. Different inference calls are distinguished by
   262  // network _tag_ (an extra field in GCall)
   263  //
   264  // getOutMeta is a stub callback collected by G-API kernel subsystem
   265  // automatically. This is a rare case when this callback is defined by
   266  // a particular backend, not by a network itself.
   267  struct GInferBase {
   268      static constexpr const char * id() {
   269          return "org.opencv.dnn.infer";            // Universal stub
   270      }
   271      static GMetaArgs getOutMeta(const GMetaArgs &, const GArgs &) {
   272          return GMetaArgs{};                       // One more universal stub
   273      }
   274  };
   275  
   276  // Base "InferROI" kernel.
   277  // All notes from "Infer" kernel apply here as well.
   278  struct GInferROIBase {
   279      static constexpr const char * id() {
   280          return "org.opencv.dnn.infer-roi";        // Universal stub
   281      }
   282      static GMetaArgs getOutMeta(const GMetaArgs &, const GArgs &) {
   283          return GMetaArgs{};                       // One more universal stub
   284      }
   285  };
   286  
   287  // Base "Infer list" kernel.
   288  // All notes from "Infer" kernel apply here as well.
   289  struct GInferListBase {
   290      static constexpr const char * id() {
   291          return "org.opencv.dnn.infer-roi-list-1"; // Universal stub
   292      }
   293      static GMetaArgs getOutMeta(const GMetaArgs &, const GArgs &) {
   294          return GMetaArgs{};                       // One more universal stub
   295      }
   296  };
   297  
   298  // Base "Infer list 2" kernel.
   299  // All notes from "Infer" kernel apply here as well.
   300  struct GInferList2Base {
   301      static constexpr const char * id() {
   302          return "org.opencv.dnn.infer-roi-list-2"; // Universal stub
   303      }
   304      static GMetaArgs getOutMeta(const GMetaArgs &, const GArgs &) {
   305          return GMetaArgs{};                       // One more universal stub
   306      }
   307  };
   308  
   309  // A generic inference kernel. API (::on()) is fully defined by the Net
   310  // template parameter.
   311  // Acts as a regular kernel in graph (via KernelTypeMedium).
   312  template<typename Net, typename... Args>
   313  struct GInfer final
   314      : public GInferBase
   315      , public detail::KernelTypeMedium< GInfer<Net, Args...>
   316                                       , typename InferAPI<Net, Args...>::type > {
   317      using GInferBase::getOutMeta; // FIXME: name lookup conflict workaround?
   318  
   319      static constexpr const char* tag() { return Net::tag(); }
   320  };
   321  
   322  // A specific roi-inference kernel. API (::on()) is fixed here and
   323  // verified against Net.
   324  template<typename Net, typename T>
   325  struct GInferROI final
   326      : public GInferROIBase
   327      , public detail::KernelTypeMedium< GInferROI<Net, T>
   328                                       , typename InferAPIRoi<Net, T>::type > {
   329      using GInferROIBase::getOutMeta; // FIXME: name lookup conflict workaround?
   330  
   331      static constexpr const char* tag() { return Net::tag(); }
   332  };
   333  
   334  
   335  // A generic roi-list inference kernel. API (::on()) is derived from
   336  // the Net template parameter (see more in infer<> overload).
   337  template<typename Net, typename... Args>
   338  struct GInferList final
   339      : public GInferListBase
   340      , public detail::KernelTypeMedium< GInferList<Net, Args...>
   341                                       , typename InferAPIList<Net, Args...>::type > {
   342      using GInferListBase::getOutMeta; // FIXME: name lookup conflict workaround?
   343  
   344      static constexpr const char* tag() { return Net::tag(); }
   345  };
   346  
   347  // An even more generic roi-list inference kernel. API (::on()) is
   348  // derived from the Net template parameter (see more in infer<>
   349  // overload).
   350  // Takes an extra variadic template list to reflect how this network
   351  // was called (with Rects or GMats as array parameters)
   352  template<typename Net, typename T, typename... Args>
   353  struct GInferList2 final
   354      : public GInferList2Base
   355      , public detail::KernelTypeMedium< GInferList2<Net, T, Args...>
   356                                       , typename InferAPIList2<Net, T, Args...>::type > {
   357      using GInferList2Base::getOutMeta; // FIXME: name lookup conflict workaround?
   358  
   359      static constexpr const char* tag() { return Net::tag(); }
   360  };
   361  
   362  /**
   363   * @brief G-API object used to collect network inputs
   364   */
   365  using GInferInputs = cv::detail::GInferInputsTyped<cv::GMat, cv::GFrame>;
   366  
   367  /**
   368   * @brief G-API object used to collect the list of network inputs
   369   */
   370  using GInferListInputs = cv::detail::GInferInputsTyped<cv::GArray<cv::GMat>, cv::GArray<cv::Rect>>;
   371  
   372  /**
   373   * @brief G-API object used to collect network outputs
   374   */
   375  using GInferOutputs = cv::detail::GInferOutputsTyped<cv::GMat>;
   376  
   377  /**
   378   * @brief G-API object used to collect the list of network outputs
   379   */
   380  using GInferListOutputs = cv::detail::GInferOutputsTyped<cv::GArray<cv::GMat>>;
   381  
   382  namespace detail {
   383  void inline unpackBlobs(const cv::GInferInputs::Map& blobs,
   384                          std::vector<cv::GArg>& args,
   385                          std::vector<std::string>& names,
   386                          cv::GKinds& kinds)
   387  {
   388      for (auto&& p : blobs) {
   389          names.emplace_back(p.first);
   390          switch (p.second.index()) {
   391              case cv::GInferInputs::StorageT::index_of<cv::GMat>():
   392                  args.emplace_back(cv::util::get<cv::GMat>(p.second));
   393                  kinds.emplace_back(cv::detail::OpaqueKind::CV_MAT);
   394                  break;
   395              case cv::GInferInputs::StorageT::index_of<cv::GFrame>():
   396                  args.emplace_back(cv::util::get<cv::GFrame>(p.second));
   397                  kinds.emplace_back(cv::detail::OpaqueKind::CV_UNKNOWN);
   398                  break;
   399              default:
   400                  GAPI_Assert(false);
   401          }
   402      }
   403  }
   404  
   405  template <typename InferType>
   406  struct InferROITraits;
   407  
   408  template <>
   409  struct InferROITraits<GInferROIBase>
   410  {
   411      using outType = cv::GInferOutputs;
   412      using inType  = cv::GOpaque<cv::Rect>;
   413  };
   414  
   415  template <>
   416  struct InferROITraits<GInferListBase>
   417  {
   418      using outType = cv::GInferListOutputs;
   419      using inType  = cv::GArray<cv::Rect>;
   420  };
   421  
   422  template<typename InferType>
   423  typename InferROITraits<InferType>::outType
   424  inferGenericROI(const std::string& tag,
   425           const typename InferROITraits<InferType>::inType& in,
   426           const cv::GInferInputs& inputs)
   427  {
   428      std::vector<cv::GArg> args;
   429      std::vector<std::string> names;
   430      cv::GKinds kinds;
   431  
   432      args.emplace_back(in);
   433      kinds.emplace_back(cv::detail::OpaqueKind::CV_RECT);
   434  
   435      unpackBlobs(inputs.getBlobs(), args, names, kinds);
   436  
   437      auto call = cv::detail::makeCall<InferType>(tag,
   438                                                  std::move(args),
   439                                                  std::move(names),
   440                                                  std::move(kinds));
   441  
   442      return {std::move(call)};
   443  }
   444  
   445  } // namespace detail
   446  } // namespace cv
   447  
   448  // FIXME: Probably the <API> signature makes a function/tuple/function round-trip
   449  #define G_API_NET(Class, API, Tag)                                      \
   450      struct Class final: public cv::GNetworkType<Class, std::function API> { \
   451          static constexpr const char * tag() { return Tag; }             \
   452      }
   453  
   454  namespace cv {
   455  namespace gapi {
   456  
   457  /** @brief Calculates response for the specified network (template
   458   *     parameter) for the specified region in the source image.
   459   *     Currently expects a single-input network only.
   460   *
   461   * @tparam A network type defined with G_API_NET() macro.
   462   * @param in input image where to take ROI from.
   463   * @param roi an object describing the region of interest
   464   *   in the source image. May be calculated in the same graph dynamically.
   465   * @return an object of return type as defined in G_API_NET().
   466   *   If a network has multiple return values (defined with a tuple), a tuple of
   467   *   objects of appropriate type is returned.
   468   * @sa  G_API_NET()
   469   */
   470  template<typename Net, typename T>
   471  typename Net::Result infer(cv::GOpaque<cv::Rect> roi, T in) {
   472      return GInferROI<Net, T>::on(roi, in);
   473  }
   474  
   475  /** @brief Calculates responses for the specified network (template
   476   *     parameter) for every region in the source image.
   477   *
   478   * @tparam A network type defined with G_API_NET() macro.
   479   * @param roi a list of rectangles describing regions of interest
   480   *   in the source image. Usually an output of object detector or tracker.
   481   * @param args network's input parameters as specified in G_API_NET() macro.
   482   *   NOTE: verified to work reliably with 1-input topologies only.
   483   * @return a list of objects of return type as defined in G_API_NET().
   484   *   If a network has multiple return values (defined with a tuple), a tuple of
   485   *   GArray<> objects is returned with the appropriate types inside.
   486   * @sa  G_API_NET()
   487   */
   488  template<typename Net, typename... Args>
   489  typename Net::ResultL infer(cv::GArray<cv::Rect> roi, Args&&... args) {
   490      return GInferList<Net, Args...>::on(roi, std::forward<Args>(args)...);
   491  }
   492  
   493  /** @brief Calculates responses for the specified network (template
   494   *     parameter) for every region in the source image, extended version.
   495   *
   496   * @tparam A network type defined with G_API_NET() macro.
   497   * @param image A source image containing regions of interest
   498   * @param args GArray<> objects of cv::Rect or cv::GMat, one per every
   499   * network input:
   500   * - If a cv::GArray<cv::Rect> is passed, the appropriate
   501   *   regions are taken from `image` and preprocessed to this particular
   502   *   network input;
   503   * - If a cv::GArray<cv::GMat> is passed, the underlying data traited
   504   *   as tensor (no automatic preprocessing happen).
   505   * @return a list of objects of return type as defined in G_API_NET().
   506   *   If a network has multiple return values (defined with a tuple), a tuple of
   507   *   GArray<> objects is returned with the appropriate types inside.
   508   * @sa  G_API_NET()
   509   */
   510  
   511  template<typename Net, typename T, typename... Args>
   512  typename Net::ResultL infer2(T image, cv::GArray<Args>... args) {
   513      // FIXME: Declared as "2" because in the current form it steals
   514      // overloads from the regular infer
   515      return GInferList2<Net, T, Args...>::on(image, args...);
   516  }
   517  
   518  /**
   519   * @brief Calculates response for the specified network (template
   520   *     parameter) given the input data.
   521   *
   522   * @tparam A network type defined with G_API_NET() macro.
   523   * @param args network's input parameters as specified in G_API_NET() macro.
   524   * @return an object of return type as defined in G_API_NET().
   525   *   If a network has multiple return values (defined with a tuple), a tuple of
   526   *   objects of appropriate type is returned.
   527   * @sa  G_API_NET()
   528   */
   529  template<typename Net, typename... Args>
   530  typename Net::Result infer(Args&&... args) {
   531      return GInfer<Net, Args...>::on(std::forward<Args>(args)...);
   532  }
   533  
   534  /**
   535   * @brief Generic network type: input and output layers are configured dynamically at runtime
   536   *
   537   * Unlike the network types defined with G_API_NET macro, this one
   538   * doesn't fix number of network inputs and outputs at the compilation stage
   539   * thus providing user with an opportunity to program them in runtime.
   540   */
   541  struct Generic { };
   542  
   543  /**
   544   * @brief Calculates response for generic network
   545   *
   546   * @param tag a network tag
   547   * @param inputs networks's inputs
   548   * @return a GInferOutputs
   549   */
   550  template<typename T = Generic> cv::GInferOutputs
   551  infer(const std::string& tag, const cv::GInferInputs& inputs)
   552  {
   553      std::vector<cv::GArg> args;
   554      std::vector<std::string> names;
   555      cv::GKinds kinds;
   556  
   557      cv::detail::unpackBlobs(inputs.getBlobs(), args, names, kinds);
   558  
   559      auto call = cv::detail::makeCall<GInferBase>(tag,
   560                                                   std::move(args),
   561                                                   std::move(names),
   562                                                   std::move(kinds));
   563  
   564      return cv::GInferOutputs{std::move(call)};
   565  }
   566  
   567  /** @brief Calculates response for the generic network
   568   *     for the specified region in the source image.
   569   *     Currently expects a single-input network only.
   570   *
   571   * @param tag a network tag
   572   * @param roi a an object describing the region of interest
   573   *   in the source image. May be calculated in the same graph dynamically.
   574   * @param inputs networks's inputs
   575   * @return a cv::GInferOutputs
   576   */
   577  template<typename T = Generic> cv::GInferOutputs
   578  infer(const std::string& tag, const cv::GOpaque<cv::Rect>& roi, const cv::GInferInputs& inputs)
   579  {
   580      return cv::detail::inferGenericROI<GInferROIBase>(tag, roi, inputs);
   581  }
   582  
   583  /** @brief Calculates responses for the specified network
   584   *     for every region in the source image.
   585   *
   586   * @param tag a network tag
   587   * @param rois a list of rectangles describing regions of interest
   588   *   in the source image. Usually an output of object detector or tracker.
   589   * @param inputs networks's inputs
   590   * @return a cv::GInferListOutputs
   591   */
   592  template<typename T = Generic> cv::GInferListOutputs
   593  infer(const std::string& tag, const cv::GArray<cv::Rect>& rois, const cv::GInferInputs& inputs)
   594  {
   595      return cv::detail::inferGenericROI<GInferListBase>(tag, rois, inputs);
   596  }
   597  
   598  /** @brief Calculates responses for the specified network
   599   *     for every region in the source image, extended version.
   600   *
   601   * @param tag a network tag
   602   * @param in a source image containing regions of interest.
   603   * @param inputs networks's inputs
   604   * @return a cv::GInferListOutputs
   605   */
   606  template<typename T = Generic, typename Input>
   607  typename std::enable_if<cv::detail::accepted_infer_types<Input>::value, cv::GInferListOutputs>::type
   608  infer2(const std::string& tag,
   609         const Input& in,
   610         const cv::GInferListInputs& inputs)
   611  {
   612      std::vector<cv::GArg> args;
   613      std::vector<std::string> names;
   614      cv::GKinds kinds;
   615  
   616      args.emplace_back(in);
   617      auto k = cv::detail::GOpaqueTraits<Input>::kind;
   618      kinds.emplace_back(k);
   619  
   620      for (auto&& p : inputs.getBlobs()) {
   621          names.emplace_back(p.first);
   622          switch (p.second.index()) {
   623              case cv::GInferListInputs::StorageT::index_of<cv::GArray<cv::GMat>>():
   624                  args.emplace_back(cv::util::get<cv::GArray<cv::GMat>>(p.second));
   625                  kinds.emplace_back(cv::detail::OpaqueKind::CV_MAT);
   626                  break;
   627              case cv::GInferListInputs::StorageT::index_of<cv::GArray<cv::Rect>>():
   628                  args.emplace_back(cv::util::get<cv::GArray<cv::Rect>>(p.second));
   629                  kinds.emplace_back(cv::detail::OpaqueKind::CV_RECT);
   630                  break;
   631              default:
   632                  GAPI_Assert(false);
   633          }
   634      }
   635  
   636      auto call = cv::detail::makeCall<GInferList2Base>(tag,
   637                                                        std::move(args),
   638                                                        std::move(names),
   639                                                        std::move(kinds));
   640  
   641      return cv::GInferListOutputs{std::move(call)};
   642  }
   643  
   644  } // namespace gapi
   645  } // namespace cv
   646  
   647  #endif // GAPI_STANDALONE
   648  
   649  namespace cv {
   650  namespace gapi {
   651  
   652  // Note: the below code _is_ part of STANDALONE build,
   653  // just to make our compiler code compileable.
   654  
   655  // A type-erased form of network parameters.
   656  // Similar to how a type-erased GKernel is represented and used.
   657  /// @private
   658  struct GAPI_EXPORTS_W_SIMPLE GNetParam {
   659      std::string tag;     // FIXME: const?
   660      GBackend backend;    // Specifies the execution model
   661      util::any params;    // Backend-interpreted parameter structure
   662  };
   663  
   664  /** \addtogroup gapi_compile_args
   665   * @{
   666   */
   667  /**
   668   * @brief A container class for network configurations. Similar to
   669   * GKernelPackage. Use cv::gapi::networks() to construct this object.
   670   *
   671   * @sa cv::gapi::networks
   672   */
   673  struct GAPI_EXPORTS_W_SIMPLE GNetPackage {
   674      GAPI_WRAP GNetPackage() = default;
   675      GAPI_WRAP explicit GNetPackage(std::vector<GNetParam> nets);
   676      explicit GNetPackage(std::initializer_list<GNetParam> ii);
   677      std::vector<GBackend> backends() const;
   678      std::vector<GNetParam> networks;
   679  };
   680  /** @} gapi_compile_args */
   681  } // namespace gapi
   682  
   683  namespace detail {
   684  template<typename T>
   685  gapi::GNetParam strip(T&& t) {
   686      return gapi::GNetParam { t.tag()
   687                             , t.backend()
   688                             , t.params()
   689                             };
   690  }
   691  
   692  template<> struct CompileArgTag<cv::gapi::GNetPackage> {
   693      static const char* tag() { return "gapi.net_package"; }
   694  };
   695  
   696  } // namespace cv::detail
   697  
   698  namespace gapi {
   699  template<typename... Args>
   700  cv::gapi::GNetPackage networks(Args&&... args) {
   701      return cv::gapi::GNetPackage({ cv::detail::strip(args)... });
   702  }
   703  
   704  inline cv::gapi::GNetPackage& operator += (      cv::gapi::GNetPackage& lhs,
   705                                             const cv::gapi::GNetPackage& rhs) {
   706      lhs.networks.reserve(lhs.networks.size() + rhs.networks.size());
   707      lhs.networks.insert(lhs.networks.end(), rhs.networks.begin(), rhs.networks.end());
   708      return lhs;
   709  }
   710  
   711  } // namespace gapi
   712  } // namespace cv
   713  
   714  #endif // OPENCV_GAPI_INFER_HPP