123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- // This file is part of OpenCV project.
- // It is subject to the license terms in the LICENSE file found in the top-level directory
- // of this distribution and at http://opencv.org/license.html.
- //
- // Copyright (C) 2018-2020 Intel Corporation
- #ifndef OPENCV_GAPI_GARRAY_HPP
- #define OPENCV_GAPI_GARRAY_HPP
- #include <functional>
- #include <ostream>
- #include <vector>
- #include <memory>
- #include <opencv2/gapi/own/exports.hpp>
- #include <opencv2/gapi/opencv_includes.hpp>
- #include <opencv2/gapi/util/variant.hpp>
- #include <opencv2/gapi/util/throw.hpp>
- #include <opencv2/gapi/own/assert.hpp>
- #include <opencv2/gapi/gmat.hpp> // flatten_g only!
- #include <opencv2/gapi/gscalar.hpp> // flatten_g only!
- namespace cv
- {
- // Forward declaration; GNode and GOrigin are an internal
- // (user-inaccessible) classes.
- class GNode;
- struct GOrigin;
- template<typename T> class GArray;
- /**
- * \addtogroup gapi_meta_args
- * @{
- */
- struct GAPI_EXPORTS_W_SIMPLE GArrayDesc
- {
- // FIXME: Body
- // FIXME: Also implement proper operator== then
- bool operator== (const GArrayDesc&) const { return true; }
- };
- template<typename U> GArrayDesc descr_of(const std::vector<U> &) { return {};}
- GAPI_EXPORTS_W inline GArrayDesc empty_array_desc() {return {}; }
- /** @} */
- std::ostream& operator<<(std::ostream& os, const cv::GArrayDesc &desc);
- namespace detail
- {
- // ConstructVec is a callback which stores information about T and is used by
- // G-API runtime to construct arrays in host memory (T remains opaque for G-API).
- // ConstructVec is carried into G-API internals by GArrayU.
- // Currently it is suitable for Host (CPU) plugins only, real offload may require
- // more information for manual memory allocation on-device.
- class VectorRef;
- using ConstructVec = std::function<void(VectorRef&)>;
- // This is the base struct for GArrayU type holder
- struct TypeHintBase{virtual ~TypeHintBase() = default;};
- // This class holds type of initial GArray to be checked from GArrayU
- template <typename T>
- struct TypeHint final : public TypeHintBase{};
- // This class strips type information from GArray<T> and makes it usable
- // in the G-API graph compiler (expression unrolling, graph generation, etc).
- // Part of GProtoArg.
- class GAPI_EXPORTS GArrayU
- {
- public:
- GArrayU(const GNode &n, std::size_t out); // Operation result constructor
- template <typename T>
- bool holds() const; // Check if was created from GArray<T>
- GOrigin& priv(); // Internal use only
- const GOrigin& priv() const; // Internal use only
- protected:
- GArrayU(); // Default constructor
- GArrayU(const detail::VectorRef& vref); // Constant value constructor
- template<class> friend class cv::GArray; // (available to GArray<T> only)
- void setConstructFcn(ConstructVec &&cv); // Store T-aware constructor
- template <typename T>
- void specifyType(); // Store type of initial GArray<T>
- template <typename T>
- void storeKind();
- void setKind(cv::detail::OpaqueKind);
- std::shared_ptr<GOrigin> m_priv;
- std::shared_ptr<TypeHintBase> m_hint;
- };
- template <typename T>
- bool GArrayU::holds() const{
- GAPI_Assert(m_hint != nullptr);
- using U = typename std::decay<T>::type;
- return dynamic_cast<TypeHint<U>*>(m_hint.get()) != nullptr;
- };
- template <typename T>
- void GArrayU::specifyType(){
- m_hint.reset(new TypeHint<typename std::decay<T>::type>);
- };
- template <typename T>
- void GArrayU::storeKind(){
- setKind(cv::detail::GOpaqueTraits<T>::kind);
- };
- // This class represents a typed STL vector reference.
- // Depending on origins, this reference may be either "just a" reference to
- // an object created externally, OR actually own the underlying object
- // (be value holder).
- class BasicVectorRef
- {
- public:
- // These fields are set by the derived class(es)
- std::size_t m_elemSize = 0ul;
- cv::GArrayDesc m_desc;
- virtual ~BasicVectorRef() {}
- virtual void mov(BasicVectorRef &ref) = 0;
- virtual const void* ptr() const = 0;
- virtual std::size_t size() const = 0;
- };
- template<typename T> class VectorRefT final: public BasicVectorRef
- {
- using empty_t = util::monostate;
- using ro_ext_t = const std::vector<T> *;
- using rw_ext_t = std::vector<T> *;
- using rw_own_t = std::vector<T> ;
- util::variant<empty_t, ro_ext_t, rw_ext_t, rw_own_t> m_ref;
- inline bool isEmpty() const { return util::holds_alternative<empty_t>(m_ref); }
- inline bool isROExt() const { return util::holds_alternative<ro_ext_t>(m_ref); }
- inline bool isRWExt() const { return util::holds_alternative<rw_ext_t>(m_ref); }
- inline bool isRWOwn() const { return util::holds_alternative<rw_own_t>(m_ref); }
- void init(const std::vector<T>* vec = nullptr)
- {
- m_elemSize = sizeof(T);
- if (vec) m_desc = cv::descr_of(*vec);
- }
- public:
- VectorRefT() { init(); }
- virtual ~VectorRefT() {}
- explicit VectorRefT(const std::vector<T>& vec) : m_ref(&vec) { init(&vec); }
- explicit VectorRefT(std::vector<T>& vec) : m_ref(&vec) { init(&vec); }
- explicit VectorRefT(std::vector<T>&& vec) : m_ref(std::move(vec)) { init(&vec); }
- // Reset a VectorRefT. Called only for objects instantiated
- // internally in G-API (e.g. temporary GArray<T>'s within a
- // computation). Reset here means both initialization
- // (creating an object) and reset (discarding its existing
- // content before the next execution). Must never be called
- // for external VectorRefTs.
- void reset()
- {
- if (isEmpty())
- {
- std::vector<T> empty_vector;
- m_desc = cv::descr_of(empty_vector);
- m_ref = std::move(empty_vector);
- GAPI_Assert(isRWOwn());
- }
- else if (isRWOwn())
- {
- util::get<rw_own_t>(m_ref).clear();
- }
- else GAPI_Assert(false); // shouldn't be called in *EXT modes
- }
- // Obtain a WRITE reference to underlying object
- // Used by CPU kernel API wrappers when a kernel execution frame
- // is created
- std::vector<T>& wref()
- {
- GAPI_Assert(isRWExt() || isRWOwn());
- if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
- if (isRWOwn()) return util::get<rw_own_t>(m_ref);
- util::throw_error(std::logic_error("Impossible happened"));
- }
- // Obtain a READ reference to underlying object
- // Used by CPU kernel API wrappers when a kernel execution frame
- // is created
- const std::vector<T>& rref() const
- {
- // ANY vector can be accessed for reading, even if it declared for
- // output. Example -- a GComputation from [in] to [out1,out2]
- // where [out2] is a result of operation applied to [out1]:
- //
- // GComputation boundary
- // . . . . . . .
- // . .
- // [in] ----> foo() ----> [out1]
- // . . :
- // . . . .:. . .
- // . V .
- // . bar() ---> [out2]
- // . . . . . . . . . . . .
- //
- if (isROExt()) return *util::get<ro_ext_t>(m_ref);
- if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
- if (isRWOwn()) return util::get<rw_own_t>(m_ref);
- util::throw_error(std::logic_error("Impossible happened"));
- }
- virtual void mov(BasicVectorRef &v) override {
- VectorRefT<T> *tv = dynamic_cast<VectorRefT<T>*>(&v);
- GAPI_Assert(tv != nullptr);
- wref() = std::move(tv->wref());
- }
- virtual const void* ptr() const override { return &rref(); }
- virtual std::size_t size() const override { return rref().size(); }
- };
- // This class strips type information from VectorRefT<> and makes it usable
- // in the G-API executables (carrying run-time data/information to kernels).
- // Part of GRunArg.
- // Its methods are typed proxies to VectorRefT<T>.
- // VectorRef maintains "reference" semantics so two copies of VectoRef refer
- // to the same underlying object.
- // FIXME: Put a good explanation on why cv::OutputArray doesn't fit this role
- class VectorRef
- {
- std::shared_ptr<BasicVectorRef> m_ref;
- cv::detail::OpaqueKind m_kind = cv::detail::OpaqueKind::CV_UNKNOWN;
- template<typename T> inline void check() const
- {
- GAPI_DbgAssert(dynamic_cast<VectorRefT<T>*>(m_ref.get()) != nullptr);
- GAPI_Assert(sizeof(T) == m_ref->m_elemSize);
- }
- public:
- VectorRef() = default;
- template<typename T> explicit VectorRef(const std::vector<T>& vec)
- : m_ref(new VectorRefT<T>(vec))
- , m_kind(GOpaqueTraits<T>::kind)
- {}
- template<typename T> explicit VectorRef(std::vector<T>& vec)
- : m_ref(new VectorRefT<T>(vec))
- , m_kind(GOpaqueTraits<T>::kind)
- {}
- template<typename T> explicit VectorRef(std::vector<T>&& vec)
- : m_ref(new VectorRefT<T>(std::move(vec)))
- , m_kind(GOpaqueTraits<T>::kind)
- {}
- cv::detail::OpaqueKind getKind() const
- {
- return m_kind;
- }
- template<typename T> void reset()
- {
- if (!m_ref) m_ref.reset(new VectorRefT<T>());
- check<T>();
- storeKind<T>();
- static_cast<VectorRefT<T>&>(*m_ref).reset();
- }
- template <typename T>
- void storeKind()
- {
- m_kind = cv::detail::GOpaqueTraits<T>::kind;
- }
- template<typename T> std::vector<T>& wref()
- {
- check<T>();
- return static_cast<VectorRefT<T>&>(*m_ref).wref();
- }
- template<typename T> const std::vector<T>& rref() const
- {
- check<T>();
- return static_cast<VectorRefT<T>&>(*m_ref).rref();
- }
- // Check if was created for/from std::vector<T>
- template <typename T> bool holds() const
- {
- if (!m_ref) return false;
- using U = typename std::decay<T>::type;
- return dynamic_cast<VectorRefT<U>*>(m_ref.get()) != nullptr;
- }
- void mov(VectorRef &v)
- {
- m_ref->mov(*v.m_ref);
- }
- cv::GArrayDesc descr_of() const
- {
- return m_ref->m_desc;
- }
- std::size_t size() const
- {
- return m_ref->size();
- }
- // May be used to uniquely identify this object internally
- const void *ptr() const { return m_ref->ptr(); }
- };
- // Helper (FIXME: work-around?)
- // stripping G types to their host types
- // like cv::GArray<GMat> would still map to std::vector<cv::Mat>
- // but not to std::vector<cv::GMat>
- #if defined(GAPI_STANDALONE)
- # define FLATTEN_NS cv::gapi::own
- #else
- # define FLATTEN_NS cv
- #endif
- template<class T> struct flatten_g;
- template<> struct flatten_g<cv::GMat> { using type = FLATTEN_NS::Mat; };
- template<> struct flatten_g<cv::GScalar> { using type = FLATTEN_NS::Scalar; };
- template<class T> struct flatten_g<GArray<T>> { using type = std::vector<T>; };
- template<class T> struct flatten_g { using type = T; };
- #undef FLATTEN_NS
- // FIXME: the above mainly duplicates "ProtoToParam" thing from gtyped.hpp
- // but I decided not to include gtyped here - probably worth moving that stuff
- // to some common place? (DM)
- } // namespace detail
- /** \addtogroup gapi_data_objects
- * @{
- */
- /**
- * @brief `cv::GArray<T>` template class represents a list of objects
- * of class `T` in the graph.
- *
- * `cv::GArray<T>` describes a functional relationship between
- * operations consuming and producing arrays of objects of class
- * `T`. The primary purpose of `cv::GArray<T>` is to represent a
- * dynamic list of objects -- where the size of the list is not known
- * at the graph construction or compile time. Examples include: corner
- * and feature detectors (`cv::GArray<cv::Point>`), object detection
- * and tracking results (`cv::GArray<cv::Rect>`). Programmers can use
- * their own types with `cv::GArray<T>` in the custom operations.
- *
- * Similar to `cv::GScalar`, `cv::GArray<T>` may be value-initialized
- * -- in this case a graph-constant value is associated with the object.
- *
- * `GArray<T>` is a virtual counterpart of `std::vector<T>`, which is
- * usually used to represent the `GArray<T>` data in G-API during the
- * execution.
- *
- * @sa `cv::GOpaque<T>`
- */
- template<typename T> class GArray
- {
- public:
- // Host type (or Flat type) - the type this GArray is actually
- // specified to.
- /// @private
- using HT = typename detail::flatten_g<typename std::decay<T>::type>::type;
- /**
- * @brief Constructs a value-initialized `cv::GArray<T>`
- *
- * `cv::GArray<T>` objects may have their values
- * be associated at graph construction time. It is useful when
- * some operation has a `cv::GArray<T>` input which doesn't change during
- * the program execution, and is set only once. In this case,
- * there is no need to declare such `cv::GArray<T>` as a graph input.
- *
- * @note The value of `cv::GArray<T>` may be overwritten by assigning some
- * other `cv::GArray<T>` to the object using `operator=` -- on the
- * assignment, the old association or value is discarded.
- *
- * @param v a std::vector<T> to associate with this
- * `cv::GArray<T>` object. Vector data is copied into the
- * `cv::GArray<T>` (no reference to the passed data is held).
- */
- explicit GArray(const std::vector<HT>& v) // Constant value constructor
- : m_ref(detail::GArrayU(detail::VectorRef(v))) { putDetails(); }
- /**
- * @overload
- * @brief Constructs a value-initialized `cv::GArray<T>`
- *
- * @param v a std::vector<T> to associate with this
- * `cv::GArray<T>` object. Vector data is moved into the `cv::GArray<T>`.
- */
- explicit GArray(std::vector<HT>&& v) // Move-constructor
- : m_ref(detail::GArrayU(detail::VectorRef(std::move(v)))) { putDetails(); }
- /**
- * @brief Constructs an empty `cv::GArray<T>`
- *
- * Normally, empty G-API data objects denote a starting point of
- * the graph. When an empty `cv::GArray<T>` is assigned to a result
- * of some operation, it obtains a functional link to this
- * operation (and is not empty anymore).
- */
- GArray() { putDetails(); } // Empty constructor
- /// @private
- explicit GArray(detail::GArrayU &&ref) // GArrayU-based constructor
- : m_ref(ref) { putDetails(); } // (used by GCall, not for users)
- /// @private
- detail::GArrayU strip() const {
- return m_ref;
- }
- /// @private
- static void VCtor(detail::VectorRef& vref) {
- vref.reset<HT>();
- }
- private:
- void putDetails() {
- m_ref.setConstructFcn(&VCtor);
- m_ref.specifyType<HT>(); // FIXME: to unify those 2 to avoid excessive dynamic_cast
- m_ref.storeKind<HT>(); //
- }
- detail::GArrayU m_ref;
- };
- /** @} */
- } // namespace cv
- #endif // OPENCV_GAPI_GARRAY_HPP
|