infer.hpp 24 KB

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