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