gcomputation.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  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 Intel Corporation
  6. #ifndef OPENCV_GAPI_GCOMPUTATION_HPP
  7. #define OPENCV_GAPI_GCOMPUTATION_HPP
  8. #include <functional>
  9. #include "opencv2/gapi/util/util.hpp"
  10. #include "opencv2/gapi/gcommon.hpp"
  11. #include "opencv2/gapi/gproto.hpp"
  12. #include "opencv2/gapi/garg.hpp"
  13. #include "opencv2/gapi/gcompiled.hpp"
  14. namespace cv {
  15. namespace detail
  16. {
  17. // FIXME: move to algorithm, cover with separate tests
  18. // FIXME: replace with O(1) version (both memory and compilation time)
  19. template<typename...>
  20. struct last_type;
  21. template<typename T>
  22. struct last_type<T> { using type = T;};
  23. template<typename T, typename... Ts>
  24. struct last_type<T, Ts...> { using type = typename last_type<Ts...>::type; };
  25. template<typename... Ts>
  26. using last_type_t = typename last_type<Ts...>::type;
  27. }
  28. /**
  29. * \addtogroup gapi_main_classes
  30. * @{
  31. */
  32. /**
  33. * @brief GComputation class represents a captured computation
  34. * graph. GComputation objects form boundaries for expression code
  35. * user writes with G-API, allowing to compile and execute it.
  36. *
  37. * G-API computations are defined with input/output data
  38. * objects. G-API will track automatically which operations connect
  39. * specified outputs to the inputs, forming up a call graph to be
  40. * executed. The below example expresses calculation of Sobel operator
  41. * for edge detection (\f$G = \sqrt{G_x^2 + G_y^2}\f$):
  42. *
  43. * @snippet modules/gapi/samples/api_ref_snippets.cpp graph_def
  44. *
  45. * Full pipeline can be now captured with this object declaration:
  46. *
  47. * @snippet modules/gapi/samples/api_ref_snippets.cpp graph_cap_full
  48. *
  49. * Input/output data objects on which a call graph should be
  50. * reconstructed are passed using special wrappers cv::GIn and
  51. * cv::GOut. G-API will track automatically which operations form a
  52. * path from inputs to outputs and build the execution graph appropriately.
  53. *
  54. * Note that cv::GComputation doesn't take ownership on data objects
  55. * it is defined. Moreover, multiple GComputation objects may be
  56. * defined on the same expressions, e.g. a smaller pipeline which
  57. * expects that image gradients are already pre-calculated may be
  58. * defined like this:
  59. *
  60. * @snippet modules/gapi/samples/api_ref_snippets.cpp graph_cap_sub
  61. *
  62. * The resulting graph would expect two inputs and produce one
  63. * output. In this case, it doesn't matter if gx/gy data objects are
  64. * results of cv::gapi::Sobel operators -- G-API will stop unrolling
  65. * expressions and building the underlying graph one reaching this
  66. * data objects.
  67. *
  68. * The way how GComputation is defined is important as its definition
  69. * specifies graph _protocol_ -- the way how the graph should be
  70. * used. Protocol is defined by number of inputs, number of outputs,
  71. * and shapes of inputs and outputs.
  72. *
  73. * In the above example, sobelEdge expects one Mat on input and
  74. * produces one Mat; while sobelEdgeSub expects two Mats on input and
  75. * produces one Mat. GComputation's protocol defines how other
  76. * computaion methods should be used -- cv::GComputation::compile() and
  77. * cv::GComputation::apply(). For example, if a graph is defined on
  78. * two GMat inputs, two cv::Mat objects have to be passed to apply()
  79. * for execution. GComputation checks protocol correctness in runtime
  80. * so passing a different number of objects in apply() or passing
  81. * cv::Scalar instead of cv::Mat there would compile well as a C++
  82. * source but raise an exception in run-time. G-API also comes with a
  83. * typed wrapper cv::GComputationT<> which introduces this type-checking in
  84. * compile-time.
  85. *
  86. * cv::GComputation itself is a thin object which just captures what
  87. * the graph is. The compiled graph (which actually process data) is
  88. * represented by class GCompiled. Use compile() method to generate a
  89. * compiled graph with given compile options. cv::GComputation can
  90. * also be used to process data with implicit graph compilation
  91. * on-the-fly, see apply() for details.
  92. *
  93. * GComputation is a reference-counted object -- once defined, all its
  94. * copies will refer to the same instance.
  95. *
  96. * @sa GCompiled
  97. */
  98. class GAPI_EXPORTS GComputation
  99. {
  100. public:
  101. class Priv;
  102. typedef std::function<GComputation()> Generator;
  103. // Various constructors enable different ways to define a computation: /////
  104. // 1. Generic constructors
  105. /**
  106. * @brief Define a computation using a generator function.
  107. *
  108. * Graph can be defined in-place directly at the moment of its
  109. * construction with a lambda:
  110. *
  111. * @snippet modules/gapi/samples/api_ref_snippets.cpp graph_gen
  112. *
  113. * This may be useful since all temporary objects (cv::GMats) and
  114. * namespaces can be localized to scope of lambda, without
  115. * contaminating the parent scope with probably unnecessary objects
  116. * and information.
  117. *
  118. * @param gen generator function which returns a cv::GComputation,
  119. * see Generator.
  120. */
  121. GComputation(const Generator& gen); // Generator
  122. // overload
  123. /**
  124. * @brief Generic GComputation constructor.
  125. *
  126. * Constructs a new graph with a given protocol, specified as a
  127. * flow of operations connecting input/output objects. Throws if
  128. * the passed boundaries are invalid, e.g. if there's no
  129. * functional dependency (path) between given outputs and inputs.
  130. *
  131. * @param ins Input data vector.
  132. * @param outs Output data vector.
  133. *
  134. * @note Don't construct GProtoInputArgs/GProtoOutputArgs objects
  135. * directly, use cv::GIn()/cv::GOut() wrapper functions instead.
  136. *
  137. * @sa @ref gapi_data_objects
  138. */
  139. GComputation(GProtoInputArgs &&ins,
  140. GProtoOutputArgs &&outs); // Arg-to-arg overload
  141. // 2. Syntax sugar and compatibility overloads
  142. /**
  143. * @brief Defines an unary (one input -- one output) computation
  144. *
  145. * @overload
  146. * @param in input GMat of the defined unary computation
  147. * @param out output GMat of the defined unary computation
  148. */
  149. GComputation(GMat in, GMat out); // Unary overload
  150. /**
  151. * @brief Defines an unary (one input -- one output) computation
  152. *
  153. * @overload
  154. * @param in input GMat of the defined unary computation
  155. * @param out output GScalar of the defined unary computation
  156. */
  157. GComputation(GMat in, GScalar out); // Unary overload (scalar)
  158. /**
  159. * @brief Defines a binary (two inputs -- one output) computation
  160. *
  161. * @overload
  162. * @param in1 first input GMat of the defined binary computation
  163. * @param in2 second input GMat of the defined binary computation
  164. * @param out output GMat of the defined binary computation
  165. */
  166. GComputation(GMat in1, GMat in2, GMat out); // Binary overload
  167. /**
  168. * @brief Defines a binary (two inputs -- one output) computation
  169. *
  170. * @overload
  171. * @param in1 first input GMat of the defined binary computation
  172. * @param in2 second input GMat of the defined binary computation
  173. * @param out output GScalar of the defined binary computation
  174. */
  175. GComputation(GMat in1, GMat in2, GScalar out); // Binary
  176. // overload
  177. // (scalar)
  178. /**
  179. * @brief Defines a computation with arbitrary input/output number.
  180. *
  181. * @overload
  182. * @param ins vector of inputs GMats for this computation
  183. * @param outs vector of outputs GMats for this computation
  184. *
  185. * Use this overload for cases when number of computation
  186. * inputs/outputs is not known in compile-time -- e.g. when graph
  187. * is programmatically generated to build an image pyramid with
  188. * the given number of levels, etc.
  189. */
  190. GComputation(const std::vector<GMat> &ins, // Compatibility overload
  191. const std::vector<GMat> &outs);
  192. // Various versions of apply(): ////////////////////////////////////////////
  193. // 1. Generic apply()
  194. /**
  195. * @brief Compile graph on-the-fly and immediately execute it on
  196. * the inputs data vectors.
  197. *
  198. * Number of input/output data objects must match GComputation's
  199. * protocol, also types of host data objects (cv::Mat, cv::Scalar)
  200. * must match the shapes of data objects from protocol (cv::GMat,
  201. * cv::GScalar). If there's a mismatch, a run-time exception will
  202. * be generated.
  203. *
  204. * Internally, a cv::GCompiled object is created for the given
  205. * input format configuration, which then is executed on the input
  206. * data immediately. cv::GComputation caches compiled objects
  207. * produced within apply() -- if this method would be called next
  208. * time with the same input parameters (image formats, image
  209. * resolution, etc), the underlying compiled graph will be reused
  210. * without recompilation. If new metadata doesn't match the cached
  211. * one, the underlying compiled graph is regenerated.
  212. *
  213. * @note compile() always triggers a compilation process and
  214. * produces a new GCompiled object regardless if a similar one has
  215. * been cached via apply() or not.
  216. *
  217. * @param ins vector of input data to process. Don't create
  218. * GRunArgs object manually, use cv::gin() wrapper instead.
  219. * @param outs vector of output data to fill results in. cv::Mat
  220. * objects may be empty in this vector, G-API will automatically
  221. * initialize it with the required format & dimensions. Don't
  222. * create GRunArgsP object manually, use cv::gout() wrapper instead.
  223. * @param args a list of compilation arguments to pass to the
  224. * underlying compilation process. Don't create GCompileArgs
  225. * object manually, use cv::compile_args() wrapper instead.
  226. *
  227. * @sa @ref gapi_data_objects, @ref gapi_compile_args
  228. */
  229. void apply(GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args = {}); // Arg-to-arg overload
  230. /// @private -- Exclude this function from OpenCV documentation
  231. void apply(const std::vector<cv::gapi::own::Mat>& ins, // Compatibility overload
  232. const std::vector<cv::gapi::own::Mat>& outs,
  233. GCompileArgs &&args = {});
  234. // 2. Syntax sugar and compatibility overloads
  235. #if !defined(GAPI_STANDALONE)
  236. /**
  237. * @brief Execute an unary computation (with compilation on the fly)
  238. *
  239. * @overload
  240. * @param in input cv::Mat for unary computation
  241. * @param out output cv::Mat for unary computation
  242. * @param args compilation arguments for underlying compilation
  243. * process.
  244. */
  245. void apply(cv::Mat in, cv::Mat &out, GCompileArgs &&args = {}); // Unary overload
  246. /**
  247. * @brief Execute an unary computation (with compilation on the fly)
  248. *
  249. * @overload
  250. * @param in input cv::Mat for unary computation
  251. * @param out output cv::Scalar for unary computation
  252. * @param args compilation arguments for underlying compilation
  253. * process.
  254. */
  255. void apply(cv::Mat in, cv::Scalar &out, GCompileArgs &&args = {}); // Unary overload (scalar)
  256. /**
  257. * @brief Execute a binary computation (with compilation on the fly)
  258. *
  259. * @overload
  260. * @param in1 first input cv::Mat for binary computation
  261. * @param in2 second input cv::Mat for binary computation
  262. * @param out output cv::Mat for binary computation
  263. * @param args compilation arguments for underlying compilation
  264. * process.
  265. */
  266. void apply(cv::Mat in1, cv::Mat in2, cv::Mat &out, GCompileArgs &&args = {}); // Binary overload
  267. /**
  268. * @brief Execute an binary computation (with compilation on the fly)
  269. *
  270. * @overload
  271. * @param in1 first input cv::Mat for binary computation
  272. * @param in2 second input cv::Mat for binary computation
  273. * @param out output cv::Scalar for binary computation
  274. * @param args compilation arguments for underlying compilation
  275. * process.
  276. */
  277. void apply(cv::Mat in1, cv::Mat in2, cv::Scalar &out, GCompileArgs &&args = {}); // Binary overload (scalar)
  278. /**
  279. * @brief Execute a computation with arbitrary number of
  280. * inputs/outputs (with compilation on-the-fly).
  281. *
  282. * @overload
  283. * @param ins vector of input cv::Mat objects to process by the
  284. * computation.
  285. * @param outs vector of output cv::Mat objects to produce by the
  286. * computation.
  287. * @param args compilation arguments for underlying compilation
  288. * process.
  289. *
  290. * Numbers of elements in ins/outs vectos must match numbers of
  291. * inputs/outputs which were used to define this GComputation.
  292. */
  293. void apply(const std::vector<cv::Mat>& ins, // Compatibility overload
  294. const std::vector<cv::Mat>& outs,
  295. GCompileArgs &&args = {});
  296. #endif // !defined(GAPI_STANDALONE)
  297. // Various versions of compile(): //////////////////////////////////////////
  298. // 1. Generic compile() - requires metas to be passed as vector
  299. /**
  300. * @brief Compile the computation for specific input format(s).
  301. *
  302. * This method triggers compilation process and produces a new
  303. * GCompiled object which then can process data of the given
  304. * format. Passing data with different format to the compiled
  305. * computation will generate a run-time exception.
  306. *
  307. * @param in_metas vector of input metadata configuration. Grab
  308. * metadata from real data objects (like cv::Mat or cv::Scalar)
  309. * using cv::descr_of(), or create it on your own.
  310. * @param args compilation arguments for this compilation
  311. * process. Compilation arguments directly affect what kind of
  312. * executable object would be produced, e.g. which kernels (and
  313. * thus, devices) would be used to execute computation.
  314. *
  315. * @return GCompiled, an executable computation compiled
  316. * specifically for the given input parameters.
  317. *
  318. * @sa @ref gapi_compile_args
  319. */
  320. GCompiled compile(GMetaArgs &&in_metas, GCompileArgs &&args = {});
  321. // 2. Syntax sugar - variadic list of metas, no extra compile args
  322. // FIXME: SFINAE looks ugly in the generated documentation
  323. /**
  324. * @overload
  325. *
  326. * Takes a variadic parameter pack with metadata
  327. * descriptors for which a compiled object needs to be produced.
  328. *
  329. * @return GCompiled, an executable computation compiled
  330. * specifically for the given input parameters.
  331. */
  332. template<typename... Ts>
  333. auto compile(const Ts&... metas) ->
  334. typename std::enable_if<detail::are_meta_descrs<Ts...>::value, GCompiled>::type
  335. {
  336. return compile(GMetaArgs{GMetaArg(metas)...}, GCompileArgs());
  337. }
  338. // 3. Syntax sugar - variadic list of metas, extra compile args
  339. // (seems optional parameters don't work well when there's an variadic template
  340. // comes first)
  341. //
  342. // Ideally it should look like:
  343. //
  344. // template<typename... Ts>
  345. // GCompiled compile(const Ts&... metas, GCompileArgs &&args)
  346. //
  347. // But not all compilers can hande this (and seems they shouldn't be able to).
  348. // FIXME: SFINAE looks ugly in the generated documentation
  349. /**
  350. * @overload
  351. *
  352. * Takes a variadic parameter pack with metadata
  353. * descriptors for which a compiled object needs to be produced,
  354. * followed by GCompileArgs object representing compilation
  355. * arguments for this process.
  356. *
  357. * @return GCompiled, an executable computation compiled
  358. * specifically for the given input parameters.
  359. */
  360. template<typename... Ts>
  361. auto compile(const Ts&... meta_and_compile_args) ->
  362. typename std::enable_if<detail::are_meta_descrs_but_last<Ts...>::value
  363. && std::is_same<GCompileArgs, detail::last_type_t<Ts...> >::value,
  364. GCompiled>::type
  365. {
  366. //FIXME: wrapping meta_and_compile_args into a tuple to unwrap them inside a helper function is the overkill
  367. return compile(std::make_tuple(meta_and_compile_args...),
  368. typename detail::MkSeq<sizeof...(Ts)-1>::type());
  369. }
  370. // Internal use only
  371. /// @private
  372. Priv& priv();
  373. /// @private
  374. const Priv& priv() const;
  375. protected:
  376. // 4. Helper method for (3)
  377. /// @private
  378. template<typename... Ts, int... IIs>
  379. GCompiled compile(const std::tuple<Ts...> &meta_and_compile_args, detail::Seq<IIs...>)
  380. {
  381. GMetaArgs meta_args = {GMetaArg(std::get<IIs>(meta_and_compile_args))...};
  382. GCompileArgs comp_args = std::get<sizeof...(Ts)-1>(meta_and_compile_args);
  383. return compile(std::move(meta_args), std::move(comp_args));
  384. }
  385. /// @private
  386. std::shared_ptr<Priv> m_priv;
  387. };
  388. /** @} */
  389. namespace gapi
  390. {
  391. // FIXME: all these standalone functions need to be added to some
  392. // common documentation section
  393. /**
  394. * @brief Define an tagged island (subgraph) within a computation.
  395. *
  396. * Declare an Island tagged with `name` and defined from `ins` to `outs`
  397. * (exclusively, as ins/outs are data objects, and regioning is done on
  398. * operations level).
  399. * Throws if any operation between `ins` and `outs` are already assigned
  400. * to another island.
  401. *
  402. * Islands allow to partition graph into subgraphs, fine-tuning
  403. * the way it is scheduled by the underlying executor.
  404. *
  405. * @param name name of the Island to create
  406. * @param ins vector of input data objects where the subgraph
  407. * begins
  408. * @param outs vector of output data objects where the subgraph
  409. * ends.
  410. *
  411. * The way how an island is defined is similar to how
  412. * cv::GComputation is defined on input/output data objects.
  413. * Same rules apply here as well -- if there's no functional
  414. * dependency between inputs and outputs or there's not enough
  415. * input data objects were specified to properly calculate all
  416. * outputs, an exception is thrown.
  417. *
  418. * Use cv::GIn() / cv::GOut() to specify input/output vectors.
  419. */
  420. void GAPI_EXPORTS island(const std::string &name,
  421. GProtoInputArgs &&ins,
  422. GProtoOutputArgs &&outs);
  423. } // namespace gapi
  424. } // namespace cv
  425. #endif // OPENCV_GAPI_GCOMPUTATION_HPP