garray.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html.
  4. //
  5. // Copyright (C) 2018-2020 Intel Corporation
  6. #ifndef OPENCV_GAPI_GARRAY_HPP
  7. #define OPENCV_GAPI_GARRAY_HPP
  8. #include <functional>
  9. #include <ostream>
  10. #include <vector>
  11. #include <memory>
  12. #include <opencv2/gapi/own/exports.hpp>
  13. #include <opencv2/gapi/opencv_includes.hpp>
  14. #include <opencv2/gapi/util/variant.hpp>
  15. #include <opencv2/gapi/util/throw.hpp>
  16. #include <opencv2/gapi/own/assert.hpp>
  17. #include <opencv2/gapi/gmat.hpp> // flatten_g only!
  18. #include <opencv2/gapi/gscalar.hpp> // flatten_g only!
  19. namespace cv
  20. {
  21. // Forward declaration; GNode and GOrigin are an internal
  22. // (user-inaccessible) classes.
  23. class GNode;
  24. struct GOrigin;
  25. template<typename T> class GArray;
  26. /**
  27. * \addtogroup gapi_meta_args
  28. * @{
  29. */
  30. struct GAPI_EXPORTS_W_SIMPLE GArrayDesc
  31. {
  32. // FIXME: Body
  33. // FIXME: Also implement proper operator== then
  34. bool operator== (const GArrayDesc&) const { return true; }
  35. };
  36. template<typename U> GArrayDesc descr_of(const std::vector<U> &) { return {};}
  37. GAPI_EXPORTS_W inline GArrayDesc empty_array_desc() {return {}; }
  38. /** @} */
  39. std::ostream& operator<<(std::ostream& os, const cv::GArrayDesc &desc);
  40. namespace detail
  41. {
  42. // ConstructVec is a callback which stores information about T and is used by
  43. // G-API runtime to construct arrays in host memory (T remains opaque for G-API).
  44. // ConstructVec is carried into G-API internals by GArrayU.
  45. // Currently it is suitable for Host (CPU) plugins only, real offload may require
  46. // more information for manual memory allocation on-device.
  47. class VectorRef;
  48. using ConstructVec = std::function<void(VectorRef&)>;
  49. // This is the base struct for GArrayU type holder
  50. struct TypeHintBase{virtual ~TypeHintBase() = default;};
  51. // This class holds type of initial GArray to be checked from GArrayU
  52. template <typename T>
  53. struct TypeHint final : public TypeHintBase{};
  54. // This class strips type information from GArray<T> and makes it usable
  55. // in the G-API graph compiler (expression unrolling, graph generation, etc).
  56. // Part of GProtoArg.
  57. class GAPI_EXPORTS GArrayU
  58. {
  59. public:
  60. GArrayU(const GNode &n, std::size_t out); // Operation result constructor
  61. template <typename T>
  62. bool holds() const; // Check if was created from GArray<T>
  63. GOrigin& priv(); // Internal use only
  64. const GOrigin& priv() const; // Internal use only
  65. protected:
  66. GArrayU(); // Default constructor
  67. GArrayU(const detail::VectorRef& vref); // Constant value constructor
  68. template<class> friend class cv::GArray; // (available to GArray<T> only)
  69. void setConstructFcn(ConstructVec &&cv); // Store T-aware constructor
  70. template <typename T>
  71. void specifyType(); // Store type of initial GArray<T>
  72. template <typename T>
  73. void storeKind();
  74. void setKind(cv::detail::OpaqueKind);
  75. std::shared_ptr<GOrigin> m_priv;
  76. std::shared_ptr<TypeHintBase> m_hint;
  77. };
  78. template <typename T>
  79. bool GArrayU::holds() const{
  80. GAPI_Assert(m_hint != nullptr);
  81. using U = typename std::decay<T>::type;
  82. return dynamic_cast<TypeHint<U>*>(m_hint.get()) != nullptr;
  83. };
  84. template <typename T>
  85. void GArrayU::specifyType(){
  86. m_hint.reset(new TypeHint<typename std::decay<T>::type>);
  87. };
  88. template <typename T>
  89. void GArrayU::storeKind(){
  90. setKind(cv::detail::GOpaqueTraits<T>::kind);
  91. };
  92. // This class represents a typed STL vector reference.
  93. // Depending on origins, this reference may be either "just a" reference to
  94. // an object created externally, OR actually own the underlying object
  95. // (be value holder).
  96. class BasicVectorRef
  97. {
  98. public:
  99. // These fields are set by the derived class(es)
  100. std::size_t m_elemSize = 0ul;
  101. cv::GArrayDesc m_desc;
  102. virtual ~BasicVectorRef() {}
  103. virtual void mov(BasicVectorRef &ref) = 0;
  104. virtual const void* ptr() const = 0;
  105. virtual std::size_t size() const = 0;
  106. };
  107. template<typename T> class VectorRefT final: public BasicVectorRef
  108. {
  109. using empty_t = util::monostate;
  110. using ro_ext_t = const std::vector<T> *;
  111. using rw_ext_t = std::vector<T> *;
  112. using rw_own_t = std::vector<T> ;
  113. util::variant<empty_t, ro_ext_t, rw_ext_t, rw_own_t> m_ref;
  114. inline bool isEmpty() const { return util::holds_alternative<empty_t>(m_ref); }
  115. inline bool isROExt() const { return util::holds_alternative<ro_ext_t>(m_ref); }
  116. inline bool isRWExt() const { return util::holds_alternative<rw_ext_t>(m_ref); }
  117. inline bool isRWOwn() const { return util::holds_alternative<rw_own_t>(m_ref); }
  118. void init(const std::vector<T>* vec = nullptr)
  119. {
  120. m_elemSize = sizeof(T);
  121. if (vec) m_desc = cv::descr_of(*vec);
  122. }
  123. public:
  124. VectorRefT() { init(); }
  125. virtual ~VectorRefT() {}
  126. explicit VectorRefT(const std::vector<T>& vec) : m_ref(&vec) { init(&vec); }
  127. explicit VectorRefT(std::vector<T>& vec) : m_ref(&vec) { init(&vec); }
  128. explicit VectorRefT(std::vector<T>&& vec) : m_ref(std::move(vec)) { init(&vec); }
  129. // Reset a VectorRefT. Called only for objects instantiated
  130. // internally in G-API (e.g. temporary GArray<T>'s within a
  131. // computation). Reset here means both initialization
  132. // (creating an object) and reset (discarding its existing
  133. // content before the next execution). Must never be called
  134. // for external VectorRefTs.
  135. void reset()
  136. {
  137. if (isEmpty())
  138. {
  139. std::vector<T> empty_vector;
  140. m_desc = cv::descr_of(empty_vector);
  141. m_ref = std::move(empty_vector);
  142. GAPI_Assert(isRWOwn());
  143. }
  144. else if (isRWOwn())
  145. {
  146. util::get<rw_own_t>(m_ref).clear();
  147. }
  148. else GAPI_Assert(false); // shouldn't be called in *EXT modes
  149. }
  150. // Obtain a WRITE reference to underlying object
  151. // Used by CPU kernel API wrappers when a kernel execution frame
  152. // is created
  153. std::vector<T>& wref()
  154. {
  155. GAPI_Assert(isRWExt() || isRWOwn());
  156. if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
  157. if (isRWOwn()) return util::get<rw_own_t>(m_ref);
  158. util::throw_error(std::logic_error("Impossible happened"));
  159. }
  160. // Obtain a READ reference to underlying object
  161. // Used by CPU kernel API wrappers when a kernel execution frame
  162. // is created
  163. const std::vector<T>& rref() const
  164. {
  165. // ANY vector can be accessed for reading, even if it declared for
  166. // output. Example -- a GComputation from [in] to [out1,out2]
  167. // where [out2] is a result of operation applied to [out1]:
  168. //
  169. // GComputation boundary
  170. // . . . . . . .
  171. // . .
  172. // [in] ----> foo() ----> [out1]
  173. // . . :
  174. // . . . .:. . .
  175. // . V .
  176. // . bar() ---> [out2]
  177. // . . . . . . . . . . . .
  178. //
  179. if (isROExt()) return *util::get<ro_ext_t>(m_ref);
  180. if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
  181. if (isRWOwn()) return util::get<rw_own_t>(m_ref);
  182. util::throw_error(std::logic_error("Impossible happened"));
  183. }
  184. virtual void mov(BasicVectorRef &v) override {
  185. VectorRefT<T> *tv = dynamic_cast<VectorRefT<T>*>(&v);
  186. GAPI_Assert(tv != nullptr);
  187. wref() = std::move(tv->wref());
  188. }
  189. virtual const void* ptr() const override { return &rref(); }
  190. virtual std::size_t size() const override { return rref().size(); }
  191. };
  192. // This class strips type information from VectorRefT<> and makes it usable
  193. // in the G-API executables (carrying run-time data/information to kernels).
  194. // Part of GRunArg.
  195. // Its methods are typed proxies to VectorRefT<T>.
  196. // VectorRef maintains "reference" semantics so two copies of VectoRef refer
  197. // to the same underlying object.
  198. // FIXME: Put a good explanation on why cv::OutputArray doesn't fit this role
  199. class VectorRef
  200. {
  201. std::shared_ptr<BasicVectorRef> m_ref;
  202. cv::detail::OpaqueKind m_kind = cv::detail::OpaqueKind::CV_UNKNOWN;
  203. template<typename T> inline void check() const
  204. {
  205. GAPI_DbgAssert(dynamic_cast<VectorRefT<T>*>(m_ref.get()) != nullptr);
  206. GAPI_Assert(sizeof(T) == m_ref->m_elemSize);
  207. }
  208. public:
  209. VectorRef() = default;
  210. template<typename T> explicit VectorRef(const std::vector<T>& vec)
  211. : m_ref(new VectorRefT<T>(vec))
  212. , m_kind(GOpaqueTraits<T>::kind)
  213. {}
  214. template<typename T> explicit VectorRef(std::vector<T>& vec)
  215. : m_ref(new VectorRefT<T>(vec))
  216. , m_kind(GOpaqueTraits<T>::kind)
  217. {}
  218. template<typename T> explicit VectorRef(std::vector<T>&& vec)
  219. : m_ref(new VectorRefT<T>(std::move(vec)))
  220. , m_kind(GOpaqueTraits<T>::kind)
  221. {}
  222. cv::detail::OpaqueKind getKind() const
  223. {
  224. return m_kind;
  225. }
  226. template<typename T> void reset()
  227. {
  228. if (!m_ref) m_ref.reset(new VectorRefT<T>());
  229. check<T>();
  230. storeKind<T>();
  231. static_cast<VectorRefT<T>&>(*m_ref).reset();
  232. }
  233. template <typename T>
  234. void storeKind()
  235. {
  236. m_kind = cv::detail::GOpaqueTraits<T>::kind;
  237. }
  238. template<typename T> std::vector<T>& wref()
  239. {
  240. check<T>();
  241. return static_cast<VectorRefT<T>&>(*m_ref).wref();
  242. }
  243. template<typename T> const std::vector<T>& rref() const
  244. {
  245. check<T>();
  246. return static_cast<VectorRefT<T>&>(*m_ref).rref();
  247. }
  248. // Check if was created for/from std::vector<T>
  249. template <typename T> bool holds() const
  250. {
  251. if (!m_ref) return false;
  252. using U = typename std::decay<T>::type;
  253. return dynamic_cast<VectorRefT<U>*>(m_ref.get()) != nullptr;
  254. }
  255. void mov(VectorRef &v)
  256. {
  257. m_ref->mov(*v.m_ref);
  258. }
  259. cv::GArrayDesc descr_of() const
  260. {
  261. return m_ref->m_desc;
  262. }
  263. std::size_t size() const
  264. {
  265. return m_ref->size();
  266. }
  267. // May be used to uniquely identify this object internally
  268. const void *ptr() const { return m_ref->ptr(); }
  269. };
  270. // Helper (FIXME: work-around?)
  271. // stripping G types to their host types
  272. // like cv::GArray<GMat> would still map to std::vector<cv::Mat>
  273. // but not to std::vector<cv::GMat>
  274. #if defined(GAPI_STANDALONE)
  275. # define FLATTEN_NS cv::gapi::own
  276. #else
  277. # define FLATTEN_NS cv
  278. #endif
  279. template<class T> struct flatten_g;
  280. template<> struct flatten_g<cv::GMat> { using type = FLATTEN_NS::Mat; };
  281. template<> struct flatten_g<cv::GScalar> { using type = FLATTEN_NS::Scalar; };
  282. template<class T> struct flatten_g<GArray<T>> { using type = std::vector<T>; };
  283. template<class T> struct flatten_g { using type = T; };
  284. #undef FLATTEN_NS
  285. // FIXME: the above mainly duplicates "ProtoToParam" thing from gtyped.hpp
  286. // but I decided not to include gtyped here - probably worth moving that stuff
  287. // to some common place? (DM)
  288. } // namespace detail
  289. /** \addtogroup gapi_data_objects
  290. * @{
  291. */
  292. /**
  293. * @brief `cv::GArray<T>` template class represents a list of objects
  294. * of class `T` in the graph.
  295. *
  296. * `cv::GArray<T>` describes a functional relationship between
  297. * operations consuming and producing arrays of objects of class
  298. * `T`. The primary purpose of `cv::GArray<T>` is to represent a
  299. * dynamic list of objects -- where the size of the list is not known
  300. * at the graph construction or compile time. Examples include: corner
  301. * and feature detectors (`cv::GArray<cv::Point>`), object detection
  302. * and tracking results (`cv::GArray<cv::Rect>`). Programmers can use
  303. * their own types with `cv::GArray<T>` in the custom operations.
  304. *
  305. * Similar to `cv::GScalar`, `cv::GArray<T>` may be value-initialized
  306. * -- in this case a graph-constant value is associated with the object.
  307. *
  308. * `GArray<T>` is a virtual counterpart of `std::vector<T>`, which is
  309. * usually used to represent the `GArray<T>` data in G-API during the
  310. * execution.
  311. *
  312. * @sa `cv::GOpaque<T>`
  313. */
  314. template<typename T> class GArray
  315. {
  316. public:
  317. // Host type (or Flat type) - the type this GArray is actually
  318. // specified to.
  319. /// @private
  320. using HT = typename detail::flatten_g<typename std::decay<T>::type>::type;
  321. /**
  322. * @brief Constructs a value-initialized `cv::GArray<T>`
  323. *
  324. * `cv::GArray<T>` objects may have their values
  325. * be associated at graph construction time. It is useful when
  326. * some operation has a `cv::GArray<T>` input which doesn't change during
  327. * the program execution, and is set only once. In this case,
  328. * there is no need to declare such `cv::GArray<T>` as a graph input.
  329. *
  330. * @note The value of `cv::GArray<T>` may be overwritten by assigning some
  331. * other `cv::GArray<T>` to the object using `operator=` -- on the
  332. * assignment, the old association or value is discarded.
  333. *
  334. * @param v a std::vector<T> to associate with this
  335. * `cv::GArray<T>` object. Vector data is copied into the
  336. * `cv::GArray<T>` (no reference to the passed data is held).
  337. */
  338. explicit GArray(const std::vector<HT>& v) // Constant value constructor
  339. : m_ref(detail::GArrayU(detail::VectorRef(v))) { putDetails(); }
  340. /**
  341. * @overload
  342. * @brief Constructs a value-initialized `cv::GArray<T>`
  343. *
  344. * @param v a std::vector<T> to associate with this
  345. * `cv::GArray<T>` object. Vector data is moved into the `cv::GArray<T>`.
  346. */
  347. explicit GArray(std::vector<HT>&& v) // Move-constructor
  348. : m_ref(detail::GArrayU(detail::VectorRef(std::move(v)))) { putDetails(); }
  349. /**
  350. * @brief Constructs an empty `cv::GArray<T>`
  351. *
  352. * Normally, empty G-API data objects denote a starting point of
  353. * the graph. When an empty `cv::GArray<T>` is assigned to a result
  354. * of some operation, it obtains a functional link to this
  355. * operation (and is not empty anymore).
  356. */
  357. GArray() { putDetails(); } // Empty constructor
  358. /// @private
  359. explicit GArray(detail::GArrayU &&ref) // GArrayU-based constructor
  360. : m_ref(ref) { putDetails(); } // (used by GCall, not for users)
  361. /// @private
  362. detail::GArrayU strip() const {
  363. return m_ref;
  364. }
  365. /// @private
  366. static void VCtor(detail::VectorRef& vref) {
  367. vref.reset<HT>();
  368. }
  369. private:
  370. void putDetails() {
  371. m_ref.setConstructFcn(&VCtor);
  372. m_ref.specifyType<HT>(); // FIXME: to unify those 2 to avoid excessive dynamic_cast
  373. m_ref.storeKind<HT>(); //
  374. }
  375. detail::GArrayU m_ref;
  376. };
  377. /** @} */
  378. } // namespace cv
  379. #endif // OPENCV_GAPI_GARRAY_HPP