infer.hpp 24 KB

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