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 
7 
8 #ifndef OPENCV_GAPI_GCOMMON_HPP
9 #define OPENCV_GAPI_GCOMMON_HPP
10 
11 #include <functional>   // std::hash
12 #include <vector>       // std::vector
13 #include <type_traits>  // decay
14 
15 #include <opencv2/gapi/opencv_includes.hpp>
16 
17 #include <opencv2/gapi/util/any.hpp>
18 #include <opencv2/gapi/util/optional.hpp>
19 #include <opencv2/gapi/own/exports.hpp>
20 #include <opencv2/gapi/own/assert.hpp>
21 #include <opencv2/gapi/render/render_types.hpp>
22 #include <opencv2/gapi/s11n/base.hpp>
23 
24 namespace cv {
25 
26 class GMat; // FIXME: forward declaration for GOpaqueTraits
27 
28 namespace detail
29 {
30     // This is a trait-like structure to mark backend-specific compile arguments
31     // with tags
32     template<typename T> struct CompileArgTag;
33 
34     // These structures are tags which separate kernels and transformations
35     struct KernelTag
36     {};
37     struct TransformTag
38     {};
39 
40     // This enum is utilized mostly by GArray and GOpaque to store and recognize their internal data
41     // types (aka Host type). Also it is widely used during serialization routine.
42     enum class OpaqueKind: int
43     {
44         CV_UNKNOWN,    // Unknown, generic, opaque-to-GAPI data type unsupported in graph seriallization
45         CV_BOOL,       // bool user G-API data
46         CV_INT,        // int user G-API data
47         CV_INT64,      // int64_t user G-API data
48         CV_DOUBLE,     // double user G-API data
49         CV_FLOAT,      // float user G-API data
50         CV_UINT64,     // uint64_t user G-API data
51         CV_STRING,     // std::string user G-API data
52         CV_POINT,      // cv::Point user G-API data
53         CV_POINT2F,    // cv::Point2f user G-API data
54         CV_SIZE,       // cv::Size user G-API data
55         CV_RECT,       // cv::Rect user G-API data
56         CV_SCALAR,     // cv::Scalar user G-API data
57         CV_MAT,        // cv::Mat user G-API data
58         CV_DRAW_PRIM,  // cv::gapi::wip::draw::Prim user G-API data
59     };
60 
61     // Type traits helper which simplifies the extraction of kind from type
62     template<typename T> struct GOpaqueTraits;
63     template<typename T> struct GOpaqueTraits    { static constexpr const OpaqueKind kind = OpaqueKind::CV_UNKNOWN; };
64     template<> struct GOpaqueTraits<int>         { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT; };
65     template<> struct GOpaqueTraits<int64_t>     { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT64; };
66     template<> struct GOpaqueTraits<double>      { static constexpr const OpaqueKind kind = OpaqueKind::CV_DOUBLE; };
67     template<> struct GOpaqueTraits<float>       { static constexpr const OpaqueKind kind = OpaqueKind::CV_FLOAT; };
68     template<> struct GOpaqueTraits<uint64_t>    { static constexpr const OpaqueKind kind = OpaqueKind::CV_UINT64; };
69     template<> struct GOpaqueTraits<bool>        { static constexpr const OpaqueKind kind = OpaqueKind::CV_BOOL; };
70     template<> struct GOpaqueTraits<std::string> { static constexpr const OpaqueKind kind = OpaqueKind::CV_STRING; };
71     template<> struct GOpaqueTraits<cv::Size>    { static constexpr const OpaqueKind kind = OpaqueKind::CV_SIZE; };
72     template<> struct GOpaqueTraits<cv::Scalar>  { static constexpr const OpaqueKind kind = OpaqueKind::CV_SCALAR; };
73     template<> struct GOpaqueTraits<cv::Point>   { static constexpr const OpaqueKind kind = OpaqueKind::CV_POINT; };
74     template<> struct GOpaqueTraits<cv::Point2f> { static constexpr const OpaqueKind kind = OpaqueKind::CV_POINT2F; };
75     template<> struct GOpaqueTraits<cv::Mat>     { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; };
76     template<> struct GOpaqueTraits<cv::Rect>    { static constexpr const OpaqueKind kind = OpaqueKind::CV_RECT; };
77     template<> struct GOpaqueTraits<cv::GMat>    { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; };
78     template<> struct GOpaqueTraits<cv::gapi::wip::draw::Prim>
79                                                  { static constexpr const OpaqueKind kind = OpaqueKind::CV_DRAW_PRIM; };
80     using GOpaqueTraitsArrayTypes = std::tuple<int, double, float, uint64_t, bool, std::string, cv::Size, cv::Scalar, cv::Point, cv::Point2f,
81                                                cv::Mat, cv::Rect, cv::gapi::wip::draw::Prim>;
82     // GOpaque is not supporting cv::Mat and cv::Scalar since there are GScalar and GMat types
83     using GOpaqueTraitsOpaqueTypes = std::tuple<int, double, float, uint64_t, bool, std::string, cv::Size, cv::Point, cv::Point2f, cv::Rect,
84                                                 cv::gapi::wip::draw::Prim>;
85 } // namespace detail
86 
87 // This definition is here because it is reused by both public(?) and internal
88 // modules. Keeping it here wouldn't expose public details (e.g., API-level)
89 // to components which are internal and operate on a lower-level entities
90 // (e.g., compiler, backends).
91 // FIXME: merge with ArgKind?
92 // FIXME: replace with variant[format desc]?
93 enum class GShape: int
94 {
95     GMAT,
96     GSCALAR,
97     GARRAY,
98     GOPAQUE,
99     GFRAME,
100 };
101 
102 namespace gapi {
103 namespace s11n {
104 namespace detail {
105 template<typename T> struct wrap_serialize;
106 } // namespace detail
107 } // namespace s11n
108 } // namespace gapi
109 
110 
111 struct GCompileArg;
112 
113 namespace detail {
114     template<typename T>
115     using is_compile_arg = std::is_same<GCompileArg, typename std::decay<T>::type>;
116 } // namespace detail
117 
118 // CompileArg is an unified interface over backend-specific compilation
119 // information
120 // FIXME: Move to a separate file?
121 /** \addtogroup gapi_compile_args
122  * @{
123  *
124  * @brief Compilation arguments: data structures controlling the
125  * compilation process
126  *
127  * G-API comes with a number of graph compilation options which can be
128  * passed to cv::GComputation::apply() or
129  * cv::GComputation::compile(). Known compilation options are listed
130  * in this page, while extra backends may introduce their own
131  * compilation options (G-API transparently accepts _everything_ which
132  * can be passed to cv::compile_args(), it depends on underlying
133  * backends if an option would be interpreted or not).
134  *
135  * For example, if an example computation is executed like this:
136  *
137  * @snippet modules/gapi/samples/api_ref_snippets.cpp graph_decl_apply
138  *
139  * Extra parameter specifying which kernels to compile with can be
140  * passed like this:
141  *
142  * @snippet modules/gapi/samples/api_ref_snippets.cpp apply_with_param
143  */
144 
145 /**
146  * @brief Represents an arbitrary compilation argument.
147  *
148  * Any value can be wrapped into cv::GCompileArg, but only known ones
149  * (to G-API or its backends) can be interpreted correctly.
150  *
151  * Normally objects of this class shouldn't be created manually, use
152  * cv::compile_args() function which automatically wraps everything
153  * passed in (a variadic template parameter pack) into a vector of
154  * cv::GCompileArg objects.
155  */
156 struct GCompileArg
157 {
158 public:
159     // NB: Required for pythnon bindings
160     GCompileArg() = default;
161 
162     std::string tag;
163 
164     // FIXME: use decay in GArg/other trait-based wrapper before leg is shot!
165     template<typename T, typename std::enable_if<!detail::is_compile_arg<T>::value, int>::type = 0>
GCompileArgcv::GCompileArg166     explicit GCompileArg(T &&t)
167         : tag(detail::CompileArgTag<typename std::decay<T>::type>::tag())
168         , serializeF(cv::gapi::s11n::detail::has_S11N_spec<T>::value ?
169                      &cv::gapi::s11n::detail::wrap_serialize<T>::serialize :
170                      nullptr)
171         , arg(t)
172     {
173     }
174 
getcv::GCompileArg175     template<typename T> T& get()
176     {
177         return util::any_cast<T>(arg);
178     }
179 
getcv::GCompileArg180     template<typename T> const T& get() const
181     {
182         return util::any_cast<T>(arg);
183     }
184 
serializecv::GCompileArg185     void serialize(cv::gapi::s11n::IOStream& os) const
186     {
187         if (serializeF)
188         {
189             serializeF(os, *this);
190         }
191     }
192 
193 private:
194     std::function<void(cv::gapi::s11n::IOStream&, const GCompileArg&)> serializeF;
195     util::any arg;
196 };
197 
198 using GCompileArgs = std::vector<GCompileArg>;
199 
operator +=(cv::GCompileArgs & lhs,const cv::GCompileArgs & rhs)200 inline cv::GCompileArgs& operator += (      cv::GCompileArgs &lhs,
201                                       const cv::GCompileArgs &rhs)
202 {
203     lhs.reserve(lhs.size() + rhs.size());
204     lhs.insert(lhs.end(), rhs.begin(), rhs.end());
205     return lhs;
206 }
207 
208 /**
209  * @brief Wraps a list of arguments (a parameter pack) into a vector of
210  *        compilation arguments (cv::GCompileArg).
211  */
compile_args(Ts &&...args)212 template<typename... Ts> GCompileArgs compile_args(Ts&&... args)
213 {
214     return GCompileArgs{ GCompileArg(args)... };
215 }
216 
217 namespace gapi
218 {
219 /**
220  * @brief Retrieves particular compilation argument by its type from
221  *        cv::GCompileArgs
222  */
223 template<typename T>
getCompileArg(const cv::GCompileArgs & args)224 inline cv::util::optional<T> getCompileArg(const cv::GCompileArgs &args)
225 {
226     for (auto &compile_arg : args)
227     {
228         if (compile_arg.tag == cv::detail::CompileArgTag<T>::tag())
229         {
230             return cv::util::optional<T>(compile_arg.get<T>());
231         }
232     }
233     return cv::util::optional<T>();
234 }
235 
236 namespace s11n {
237 namespace detail {
238 template<typename T> struct wrap_serialize
239 {
serializecv::gapi::s11n::detail::wrap_serialize240     static void serialize(IOStream& os, const GCompileArg& arg)
241     {
242         using DT = typename std::decay<T>::type;
243         S11N<DT>::serialize(os, arg.get<DT>());
244     }
245 };
246 } // namespace detail
247 } // namespace s11n
248 } // namespace gapi
249 
250 /**
251  * @brief Ask G-API to dump compiled graph in Graphviz format under
252  * the given file name.
253  *
254  * Specifies a graph dump path (path to .dot file to be generated).
255  * G-API will dump a .dot file under specified path during a
256  * compilation process if this flag is passed.
257  */
258 struct graph_dump_path
259 {
260     std::string m_dump_path;
261 };
262 /** @} */
263 
264 namespace detail
265 {
266     template<> struct CompileArgTag<cv::graph_dump_path>
267     {
tagcv::detail::CompileArgTag268         static const char* tag() { return "gapi.graph_dump_path"; }
269     };
270 }
271 
272 } // namespace cv
273 
274 // std::hash overload for GShape
275 namespace std
276 {
277 template<> struct hash<cv::GShape>
278 {
operator ()std::hash279     size_t operator() (cv::GShape sh) const
280     {
281         return std::hash<int>()(static_cast<int>(sh));
282     }
283 };
284 } // namespace std
285 
286 
287 #endif // OPENCV_GAPI_GCOMMON_HPP
288