| 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 Intel Corporation |
| 6 | |
| 7 | #ifndef OPENCV_GAPI_GTRANSFORM_HPP |
| 8 | #define OPENCV_GAPI_GTRANSFORM_HPP |
| 9 | |
| 10 | #include <functional> |
| 11 | #include <type_traits> |
| 12 | #include <utility> |
| 13 | |
| 14 | #include <opencv2/gapi/gcommon.hpp> |
| 15 | #include <opencv2/gapi/util/util.hpp> |
| 16 | #include <opencv2/gapi/garg.hpp> |
| 17 | #include <opencv2/gapi/gtype_traits.hpp> |
| 18 | #include <opencv2/gapi/util/compiler_hints.hpp> |
| 19 | #include <opencv2/gapi/gcomputation.hpp> |
| 20 | |
| 21 | namespace cv |
| 22 | { |
| 23 | |
| 24 | struct GAPI_EXPORTS GTransform |
| 25 | { |
| 26 | // FIXME: consider another simplified |
| 27 | // class instead of GComputation |
| 28 | using F = std::function<GComputation()>; |
| 29 | |
| 30 | std::string description; |
| 31 | F pattern; |
| 32 | F substitute; |
| 33 | |
| 34 | GTransform(const std::string& d, const F &p, const F &s) : description(d), pattern(p), substitute(s) {} |
| 35 | }; |
| 36 | |
| 37 | namespace detail |
| 38 | { |
| 39 | |
| 40 | template <typename, typename, typename> |
| 41 | struct TransHelper; |
| 42 | |
| 43 | template <typename K, typename... Ins, typename Out> |
| 44 | struct TransHelper<K, std::tuple<Ins...>, Out> |
| 45 | { |
| 46 | template <typename Callable, int... IIs, int... OIs> |
| 47 | static GComputation invoke(Callable f, Seq<IIs...>, Seq<OIs...>) |
| 48 | { |
| 49 | const std::tuple<Ins...> ins; |
| 50 | const auto r = tuple_wrap_helper<Out>::get(f(std::get<IIs>(ins)...)); |
| 51 | return GComputation(cv::GIn(std::get<IIs>(ins)...), |
| 52 | cv::GOut(std::get<OIs>(r)...)); |
| 53 | } |
| 54 | |
| 55 | static GComputation get_pattern() |
| 56 | { |
| 57 | return invoke(K::pattern, typename MkSeq<sizeof...(Ins)>::type(), |
| 58 | typename MkSeq<std::tuple_size<typename tuple_wrap_helper<Out>::type>::value>::type()); |
| 59 | } |
| 60 | static GComputation get_substitute() |
| 61 | { |
| 62 | return invoke(K::substitute, typename MkSeq<sizeof...(Ins)>::type(), |
| 63 | typename MkSeq<std::tuple_size<typename tuple_wrap_helper<Out>::type>::value>::type()); |
| 64 | } |
| 65 | }; |
| 66 | } // namespace detail |
| 67 | |
| 68 | template <typename, typename> |
| 69 | class GTransformImpl; |
| 70 | |
| 71 | template <typename K, typename R, typename... Args> |
| 72 | class GTransformImpl<K, std::function<R(Args...)>> : public cv::detail::TransHelper<K, std::tuple<Args...>, R>, |
| 73 | public cv::detail::TransformTag |
| 74 | { |
| 75 | public: |
| 76 | // FIXME: currently there is no check that transformations' signatures are unique |
| 77 | // and won't be any intersection in graph compilation stage |
| 78 | using API = K; |
| 79 | |
| 80 | static GTransform transformation() |
| 81 | { |
| 82 | return GTransform(K::descr(), &K::get_pattern, &K::get_substitute); |
| 83 | } |
| 84 | }; |
| 85 | } // namespace cv |
| 86 | |
| 87 | #define G_DESCR_HELPER_CLASS(Class) Class##DescrHelper |
| 88 | |
| 89 | #define G_DESCR_HELPER_BODY(Class, Descr) \ |
| 90 | namespace detail \ |
| 91 | { \ |
| 92 | struct G_DESCR_HELPER_CLASS(Class) \ |
| 93 | { \ |
| 94 | static constexpr const char *descr() { return Descr; } \ |
| 95 | }; \ |
| 96 | } |
| 97 | |
| 98 | #define GAPI_TRANSFORM(Class, API, Descr) \ |
| 99 | G_DESCR_HELPER_BODY(Class, Descr) \ |
| 100 | struct Class final : public cv::GTransformImpl<Class, std::function API>, \ |
| 101 | public detail::G_DESCR_HELPER_CLASS(Class) |
| 102 | |
| 103 | #endif // OPENCV_GAPI_GTRANSFORM_HPP |
| 104 | |