mirror of
https://github.com/opencv/opencv.git
synced 2025-01-18 22:44:02 +08:00
Merge pull request #14648 from smirnov-alexey:as/gapi_transform
* Introduce GAPI_TRANSFORM initial interface Comes along with simple tests and kernel package changes * Fix documentation and adjust combine() function * Fix stuff after rebasing on master * Remove redundant functionality * Refactoring according to review feedback provided * Fixes according to review feedback * Reconsider transformations return and fix a warning * Fixes from code review * Add a new simple test * Cleanup, added tests on GScalar, GMatP, GArray
This commit is contained in:
parent
66d7956e67
commit
7f9a9f2a09
@ -2,7 +2,7 @@
|
||||
// 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 Intel Corporation
|
||||
// Copyright (C) 2018-2019 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GCPUKERNEL_HPP
|
||||
@ -19,6 +19,7 @@
|
||||
#include <opencv2/gapi/garg.hpp>
|
||||
#include <opencv2/gapi/own/convert.hpp> //to_ocv
|
||||
#include <opencv2/gapi/util/compiler_hints.hpp> //suppress_unused_warning
|
||||
#include <opencv2/gapi/util/util.hpp>
|
||||
|
||||
// FIXME: namespace scheme for backends?
|
||||
namespace cv {
|
||||
@ -258,7 +259,8 @@ struct OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
|
||||
} // namespace detail
|
||||
|
||||
template<class Impl, class K>
|
||||
class GCPUKernelImpl: public detail::OCVCallHelper<Impl, typename K::InArgs, typename K::OutArgs>
|
||||
class GCPUKernelImpl: public cv::detail::OCVCallHelper<Impl, typename K::InArgs, typename K::OutArgs>,
|
||||
public cv::detail::KernelTag
|
||||
{
|
||||
using P = detail::OCVCallHelper<Impl, typename K::InArgs, typename K::OutArgs>;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// 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 Intel Corporation
|
||||
// Copyright (C) 2018-2019 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_FLUID_KERNEL_HPP
|
||||
@ -275,7 +275,7 @@ struct FluidCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>, UseScratch
|
||||
|
||||
|
||||
template<class Impl, class K, bool UseScratch>
|
||||
class GFluidKernelImpl
|
||||
class GFluidKernelImpl : public cv::detail::KernelTag
|
||||
{
|
||||
static const int LPI = 1;
|
||||
static const auto Kind = GFluidKernel::Kind::Filter;
|
||||
|
@ -29,6 +29,12 @@ namespace detail
|
||||
{
|
||||
static const char* tag() { return ""; };
|
||||
};
|
||||
|
||||
// These structures are tags which separate kernels and transformations
|
||||
struct KernelTag
|
||||
{};
|
||||
struct TransformTag
|
||||
{};
|
||||
}
|
||||
|
||||
// This definition is here because it is reused by both public(?) and internal
|
||||
|
@ -2,7 +2,7 @@
|
||||
// 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 Intel Corporation
|
||||
// Copyright (C) 2018-2019 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GCOMPOUNDKERNEL_HPP
|
||||
@ -65,22 +65,6 @@ template<typename U> struct get_compound_in<cv::GArray<U>>
|
||||
}
|
||||
};
|
||||
|
||||
// Kernel may return one object(GMat, GScalar) or a tuple of objects.
|
||||
// This helper is needed to cast return value to the same form(tuple)
|
||||
template<typename>
|
||||
struct tuple_wrap_helper;
|
||||
|
||||
template<typename T> struct tuple_wrap_helper
|
||||
{
|
||||
static std::tuple<T> get(T&& obj) { return std::make_tuple(std::move(obj)); }
|
||||
};
|
||||
|
||||
template<typename... Objs>
|
||||
struct tuple_wrap_helper<std::tuple<Objs...>>
|
||||
{
|
||||
static std::tuple<Objs...> get(std::tuple<Objs...>&& objs) { return std::forward<std::tuple<Objs...>>(objs); }
|
||||
};
|
||||
|
||||
template<typename, typename, typename>
|
||||
struct GCompoundCallHelper;
|
||||
|
||||
@ -104,7 +88,8 @@ struct GCompoundCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
|
||||
};
|
||||
|
||||
template<class Impl, class K>
|
||||
class GCompoundKernelImpl: public cv::detail::GCompoundCallHelper<Impl, typename K::InArgs, typename K::OutArgs>
|
||||
class GCompoundKernelImpl: public cv::detail::GCompoundCallHelper<Impl, typename K::InArgs, typename K::OutArgs>,
|
||||
public cv::detail::KernelTag
|
||||
{
|
||||
using P = cv::detail::GCompoundCallHelper<Impl, typename K::InArgs, typename K::OutArgs>;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// 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 Intel Corporation
|
||||
// Copyright (C) 2018-2019 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GKERNEL_HPP
|
||||
@ -22,6 +22,7 @@
|
||||
#include <opencv2/gapi/gmetaarg.hpp> // GMetaArg
|
||||
#include <opencv2/gapi/gtype_traits.hpp> // GTypeTraits
|
||||
#include <opencv2/gapi/util/compiler_hints.hpp> //suppress_unused_warning
|
||||
#include <opencv2/gapi/gtransform.hpp>
|
||||
|
||||
namespace cv {
|
||||
|
||||
@ -170,12 +171,12 @@ namespace detail
|
||||
// GKernelType and GKernelTypeM are base classes which implement typed ::on()
|
||||
// method based on kernel signature. GKernelTypeM stands for multiple-return-value kernels
|
||||
//
|
||||
// G_TYPED_KERNEL and G_TYPED_KERNEK_M macros inherit user classes from GKernelType and
|
||||
// G_TYPED_KERNEL and G_TYPED_KERNEL_M macros inherit user classes from GKernelType and
|
||||
// GKernelTypeM respectively.
|
||||
|
||||
template<typename K, typename... R, typename... Args>
|
||||
class GKernelTypeM<K, std::function<std::tuple<R...>(Args...)> >:
|
||||
public detail::MetaHelper<K, std::tuple<Args...>, std::tuple<R...> >
|
||||
public detail::MetaHelper<K, std::tuple<Args...>, std::tuple<R...>>
|
||||
{
|
||||
template<int... IIs>
|
||||
static std::tuple<R...> yield(cv::GCall &call, detail::Seq<IIs...>)
|
||||
@ -199,7 +200,7 @@ template<typename, typename> class GKernelType;
|
||||
|
||||
template<typename K, typename R, typename... Args>
|
||||
class GKernelType<K, std::function<R(Args...)> >:
|
||||
public detail::MetaHelper<K, std::tuple<Args...>, R >
|
||||
public detail::MetaHelper<K, std::tuple<Args...>, R>
|
||||
{
|
||||
public:
|
||||
using InArgs = std::tuple<Args...>;
|
||||
@ -240,7 +241,7 @@ public:
|
||||
#define G_TYPED_KERNEL_M(Class, API, Id) \
|
||||
G_ID_HELPER_BODY(Class, Id) \
|
||||
struct Class final: public cv::GKernelTypeM<Class, std::function API >, \
|
||||
public detail::G_ID_HELPER_CLASS(Class) \
|
||||
public detail::G_ID_HELPER_CLASS(Class)
|
||||
// {body} is to be defined by user
|
||||
|
||||
namespace cv
|
||||
@ -296,12 +297,13 @@ namespace gapi {
|
||||
// FIXME: Hide implementation
|
||||
/**
|
||||
* @brief A container class for heterogeneous kernel
|
||||
* implementation collections.
|
||||
* implementation collections and graph transformations.
|
||||
*
|
||||
* GKernelPackage is a special container class which stores kernel
|
||||
* _implementations_. Objects of this class are created and passed
|
||||
* to cv::GComputation::compile() to specify which kernels to use
|
||||
* in the compiled graph. GKernelPackage may contain kernels of
|
||||
* _implementations_ and graph _transformations_. Objects of this class
|
||||
* are created and passed to cv::GComputation::compile() to specify
|
||||
* which kernels to use and which transformations to apply in the
|
||||
* compiled graph. GKernelPackage may contain kernels of
|
||||
* different backends, e.g. be heterogeneous.
|
||||
*
|
||||
* The most easy way to create a kernel package is to use function
|
||||
@ -313,7 +315,8 @@ namespace gapi {
|
||||
* with an empty package (created with the default constructor)
|
||||
* and then by populating it with kernels via call to
|
||||
* GKernelPackage::include(). Note this method is also a template
|
||||
* one since G-API kernel implementations are _types_, not objects.
|
||||
* one since G-API kernel and transformation implementations are _types_,
|
||||
* not objects.
|
||||
*
|
||||
* Finally, two kernel packages can be combined into a new one
|
||||
* with function cv::gapi::combine().
|
||||
@ -327,6 +330,9 @@ namespace gapi {
|
||||
/// @private
|
||||
M m_id_kernels;
|
||||
|
||||
/// @private
|
||||
std::vector<GTransform> m_transformations;
|
||||
|
||||
protected:
|
||||
/// @private
|
||||
// Check if package contains ANY implementation of a kernel API
|
||||
@ -337,26 +343,61 @@ namespace gapi {
|
||||
// Remove ALL implementations of the given API (identified by ID)
|
||||
void removeAPI(const std::string &id);
|
||||
|
||||
/// @private
|
||||
// Partial include() specialization for kernels
|
||||
template <typename KImpl>
|
||||
typename std::enable_if<(std::is_base_of<detail::KernelTag, KImpl>::value), void>::type
|
||||
includeHelper()
|
||||
{
|
||||
auto backend = KImpl::backend();
|
||||
auto kernel_id = KImpl::API::id();
|
||||
auto kernel_impl = GKernelImpl{KImpl::kernel()};
|
||||
removeAPI(kernel_id);
|
||||
|
||||
m_id_kernels[kernel_id] = std::make_pair(backend, kernel_impl);
|
||||
}
|
||||
|
||||
/// @private
|
||||
// Partial include() specialization for transformations
|
||||
template <typename TImpl>
|
||||
typename std::enable_if<(std::is_base_of<detail::TransformTag, TImpl>::value), void>::type
|
||||
includeHelper()
|
||||
{
|
||||
m_transformations.emplace_back(TImpl::transformation());
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Returns total number of kernels in the package
|
||||
* (across all backends included)
|
||||
* @brief Returns total number of kernels
|
||||
* in the package (across all backends included)
|
||||
*
|
||||
* @return a number of kernels in the package
|
||||
*/
|
||||
std::size_t size() const;
|
||||
|
||||
/**
|
||||
* @brief Returns vector of transformations included in the package
|
||||
*
|
||||
* @return vector of transformations included in the package
|
||||
*/
|
||||
const std::vector<GTransform>& get_transformations() const;
|
||||
|
||||
/**
|
||||
* @brief Test if a particular kernel _implementation_ KImpl is
|
||||
* included in this kernel package.
|
||||
*
|
||||
* @sa includesAPI()
|
||||
*
|
||||
* @note cannot be applied to transformations
|
||||
*
|
||||
* @return true if there is such kernel, false otherwise.
|
||||
*/
|
||||
template<typename KImpl>
|
||||
bool includes() const
|
||||
{
|
||||
static_assert(std::is_base_of<detail::KernelTag, KImpl>::value,
|
||||
"includes() can be applied to kernels only");
|
||||
|
||||
auto kernel_it = m_id_kernels.find(KImpl::API::id());
|
||||
return kernel_it != m_id_kernels.end() &&
|
||||
kernel_it->second.first == KImpl::backend();
|
||||
@ -417,17 +458,13 @@ namespace gapi {
|
||||
|
||||
// FIXME: No overwrites allowed?
|
||||
/**
|
||||
* @brief Put a new kernel implementation KImpl into package.
|
||||
* @brief Put a new kernel implementation or a new transformation
|
||||
* KImpl into the package.
|
||||
*/
|
||||
template<typename KImpl>
|
||||
void include()
|
||||
{
|
||||
auto backend = KImpl::backend();
|
||||
auto kernel_id = KImpl::API::id();
|
||||
auto kernel_impl = GKernelImpl{KImpl::kernel()};
|
||||
removeAPI(kernel_id);
|
||||
|
||||
m_id_kernels[kernel_id] = std::make_pair(backend, kernel_impl);
|
||||
includeHelper<KImpl>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -452,15 +489,15 @@ namespace gapi {
|
||||
|
||||
/**
|
||||
* @brief Create a kernel package object containing kernels
|
||||
* specified in variadic template argument.
|
||||
* and transformations specified in variadic template argument.
|
||||
*
|
||||
* In G-API, kernel implementations are _types_. Every backend has
|
||||
* its own kernel API (like GAPI_OCV_KERNEL() and
|
||||
* In G-API, kernel implementations and transformations are _types_.
|
||||
* Every backend has its own kernel API (like GAPI_OCV_KERNEL() and
|
||||
* GAPI_FLUID_KERNEL()) but all of that APIs define a new type for
|
||||
* each kernel implementation.
|
||||
*
|
||||
* Use this function to pass kernel implementations (defined in
|
||||
* either way) to the system. Example:
|
||||
* either way) and transformations to the system. Example:
|
||||
*
|
||||
* @snippet modules/gapi/samples/api_ref_snippets.cpp kernels_snippet
|
||||
*
|
||||
@ -470,6 +507,10 @@ namespace gapi {
|
||||
*/
|
||||
template<typename... KK> GKernelPackage kernels()
|
||||
{
|
||||
// FIXME: currently there is no check that transformations' signatures are unique
|
||||
// and won't be any intersection in graph compilation stage
|
||||
static_assert(detail::all_unique<typename KK::API...>::value, "Kernels API must be unique");
|
||||
|
||||
GKernelPackage pkg;
|
||||
|
||||
// For those who wonder - below is a trick to call a number of
|
||||
@ -478,8 +519,6 @@ namespace gapi {
|
||||
// Just note that `f(),a` always equals to `a` (with f() called!)
|
||||
// and parentheses are used to hide function call in the expanded sequence.
|
||||
// Leading 0 helps to handle case when KK is an empty list (kernels<>()).
|
||||
|
||||
static_assert(detail::all_unique<typename KK::API...>::value, "Kernels API must be unique");
|
||||
int unused[] = { 0, (pkg.include<KK>(), 0)... };
|
||||
cv::util::suppress_unused_warning(unused);
|
||||
return pkg;
|
||||
|
98
modules/gapi/include/opencv2/gapi/gtransform.hpp
Normal file
98
modules/gapi/include/opencv2/gapi/gtransform.hpp
Normal file
@ -0,0 +1,98 @@
|
||||
// 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) 2019 Intel Corporation
|
||||
|
||||
#ifndef OPENCV_GAPI_GTRANSFORM_HPP
|
||||
#define OPENCV_GAPI_GTRANSFORM_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <opencv2/gapi/gcommon.hpp>
|
||||
#include <opencv2/gapi/util/util.hpp>
|
||||
#include <opencv2/gapi/garg.hpp>
|
||||
#include <opencv2/gapi/gtype_traits.hpp>
|
||||
#include <opencv2/gapi/util/compiler_hints.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
struct GAPI_EXPORTS GTransform
|
||||
{
|
||||
using F = std::function<GArgs(const GArgs &)>;
|
||||
|
||||
std::string description;
|
||||
F pattern;
|
||||
F substitute;
|
||||
|
||||
GTransform(const std::string& d, const F &p, const F &s) : description(d), pattern(p), substitute(s){};
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename, typename, typename>
|
||||
struct TransHelper;
|
||||
|
||||
template <typename K, typename... Ins, typename Out>
|
||||
struct TransHelper<K, std::tuple<Ins...>, Out>
|
||||
{
|
||||
template <typename Callable, int... IIs, int... OIs>
|
||||
static GArgs invoke(Callable f, const GArgs &in_args, Seq<IIs...>, Seq<OIs...>)
|
||||
{
|
||||
const auto r = tuple_wrap_helper<Out>::get(f(in_args.at(IIs).template get<Ins>()...));
|
||||
return GArgs{GArg(std::get<OIs>(r))...};
|
||||
}
|
||||
|
||||
static GArgs get_pattern(const GArgs &in_args)
|
||||
{
|
||||
return invoke(K::pattern, in_args, typename MkSeq<sizeof...(Ins)>::type(),
|
||||
typename MkSeq<std::tuple_size<typename tuple_wrap_helper<Out>::type>::value>::type());
|
||||
}
|
||||
static GArgs get_substitute(const GArgs &in_args)
|
||||
{
|
||||
return invoke(K::substitute, in_args, typename MkSeq<sizeof...(Ins)>::type(),
|
||||
typename MkSeq<std::tuple_size<typename tuple_wrap_helper<Out>::type>::value>::type());
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <typename, typename>
|
||||
class GTransformImpl;
|
||||
|
||||
template <typename K, typename R, typename... Args>
|
||||
class GTransformImpl<K, std::function<R(Args...)>> : public cv::detail::TransHelper<K, std::tuple<Args...>, R>,
|
||||
public cv::detail::TransformTag
|
||||
{
|
||||
public:
|
||||
// FIXME: currently there is no check that transformations' signatures are unique
|
||||
// and won't be any intersection in graph compilation stage
|
||||
using API = K;
|
||||
|
||||
static GTransform transformation()
|
||||
{
|
||||
return GTransform(K::descr(), &K::get_pattern, &K::get_substitute);
|
||||
}
|
||||
};
|
||||
} // namespace cv
|
||||
|
||||
#define G_DESCR_HELPER_CLASS(Class) Class##DescrHelper
|
||||
|
||||
#define G_DESCR_HELPER_BODY(Class, Descr) \
|
||||
namespace detail \
|
||||
{ \
|
||||
struct G_DESCR_HELPER_CLASS(Class) \
|
||||
{ \
|
||||
static constexpr const char *descr() { return Descr; }; \
|
||||
}; \
|
||||
}
|
||||
|
||||
#define GAPI_TRANSFORM(Class, API, Descr) \
|
||||
G_DESCR_HELPER_BODY(Class, Descr) \
|
||||
struct Class final : public cv::GTransformImpl<Class, std::function API>, \
|
||||
public detail::G_DESCR_HELPER_CLASS(Class)
|
||||
|
||||
#endif // OPENCV_GAPI_GTRANSFORM_HPP
|
@ -2,7 +2,7 @@
|
||||
// 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 Intel Corporation
|
||||
// Copyright (C) 2018-2019 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GOCLKERNEL_HPP
|
||||
@ -226,7 +226,8 @@ struct OCLCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
|
||||
} // namespace detail
|
||||
|
||||
template<class Impl, class K>
|
||||
class GOCLKernelImpl: public detail::OCLCallHelper<Impl, typename K::InArgs, typename K::OutArgs>
|
||||
class GOCLKernelImpl: public cv::detail::OCLCallHelper<Impl, typename K::InArgs, typename K::OutArgs>,
|
||||
public cv::detail::KernelTag
|
||||
{
|
||||
using P = detail::OCLCallHelper<Impl, typename K::InArgs, typename K::OutArgs>;
|
||||
|
||||
|
@ -2,13 +2,13 @@
|
||||
// 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 Intel Corporation
|
||||
// Copyright (C) 2018-2019 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_UTIL_HPP
|
||||
#define OPENCV_GAPI_UTIL_HPP
|
||||
|
||||
#include <utility> // std::tuple
|
||||
#include <tuple>
|
||||
|
||||
// \cond HIDDEN_SYMBOLS
|
||||
// This header file contains some generic utility functions which are
|
||||
@ -97,6 +97,22 @@ namespace detail
|
||||
template <typename T1, typename... Ts>
|
||||
struct all_unique<T1, Ts...> : std::integral_constant<bool, !contains<T1, Ts...>::value &&
|
||||
all_unique<Ts...>::value> {};
|
||||
|
||||
template<typename>
|
||||
struct tuple_wrap_helper;
|
||||
|
||||
template<typename T> struct tuple_wrap_helper
|
||||
{
|
||||
using type = std::tuple<T>;
|
||||
static type get(T&& obj) { return std::make_tuple(std::move(obj)); }
|
||||
};
|
||||
|
||||
template<typename... Objs>
|
||||
struct tuple_wrap_helper<std::tuple<Objs...>>
|
||||
{
|
||||
using type = std::tuple<Objs...>;
|
||||
static type get(std::tuple<Objs...>&& objs) { return std::forward<std::tuple<Objs...>>(objs); }
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace cv
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// 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 Intel Corporation
|
||||
// Copyright (C) 2018-2019 Intel Corporation
|
||||
|
||||
|
||||
#include "precomp.hpp"
|
||||
@ -50,6 +50,11 @@ std::size_t cv::gapi::GKernelPackage::size() const
|
||||
return m_id_kernels.size();
|
||||
}
|
||||
|
||||
const std::vector<cv::GTransform> &cv::gapi::GKernelPackage::get_transformations() const
|
||||
{
|
||||
return m_transformations;
|
||||
}
|
||||
|
||||
cv::gapi::GKernelPackage cv::gapi::combine(const GKernelPackage &lhs,
|
||||
const GKernelPackage &rhs)
|
||||
{
|
||||
@ -66,6 +71,9 @@ cv::gapi::GKernelPackage cv::gapi::combine(const GKernelPackage &lhs,
|
||||
result.m_id_kernels.emplace(kernel.first, kernel.second);
|
||||
}
|
||||
}
|
||||
for (const auto &transforms : lhs.m_transformations){
|
||||
result.m_transformations.push_back(transforms);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace
|
||||
// 1. Get GCompoundKernel implementation
|
||||
// 2. Create GCompoundContext
|
||||
// 3. Run GCompoundKernel with GCompoundContext
|
||||
// 4. Build subgraph from imputs/outputs GCompoundKernel
|
||||
// 4. Build subgraph from inputs/outputs GCompoundKernel
|
||||
// 5. Replace compound node to subgraph
|
||||
|
||||
void expand(ade::Graph& g, ade::NodeHandle nh, const ImplInfo& impl_info)
|
||||
|
183
modules/gapi/test/gapi_transform_tests.cpp
Normal file
183
modules/gapi/test/gapi_transform_tests.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
// 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) 2019 Intel Corporation
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include "opencv2/gapi/gtransform.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
using GMat = cv::GMat;
|
||||
using GMat2 = std::tuple<GMat, GMat>;
|
||||
using GMat3 = std::tuple<GMat, GMat, GMat>;
|
||||
using GScalar = cv::GScalar;
|
||||
template <typename T> using GArray = cv::GArray<T>;
|
||||
|
||||
GAPI_TRANSFORM(gmat_in_gmat_out, <GMat(GMat)>, "gmat_in_gmat_out")
|
||||
{
|
||||
static GMat pattern(GMat) { return {}; }
|
||||
static GMat substitute(GMat) { return {}; }
|
||||
};
|
||||
|
||||
GAPI_TRANSFORM(gmat2_in_gmat_out, <GMat(GMat, GMat)>, "gmat2_in_gmat_out")
|
||||
{
|
||||
static GMat pattern(GMat, GMat) { return {}; }
|
||||
static GMat substitute(GMat, GMat) { return {}; }
|
||||
};
|
||||
|
||||
GAPI_TRANSFORM(gmat2_in_gmat3_out, <GMat3(GMat, GMat)>, "gmat2_in_gmat3_out")
|
||||
{
|
||||
static GMat3 pattern(GMat, GMat) { return {}; }
|
||||
static GMat3 substitute(GMat, GMat) { return {}; }
|
||||
};
|
||||
|
||||
GAPI_TRANSFORM(gmatp_in_gmatp_out, <GMatP(GMatP)>, "gmatp_in_gmatp_out")
|
||||
{
|
||||
static GMatP pattern(GMatP) { return {}; }
|
||||
static GMatP substitute(GMatP) { return {}; }
|
||||
};
|
||||
|
||||
GAPI_TRANSFORM(gsc_in_gmat_out, <GMat(GScalar)>, "gsc_in_gmat_out")
|
||||
{
|
||||
static GMat pattern(GScalar) { return {}; }
|
||||
static GMat substitute(GScalar) { return {}; }
|
||||
};
|
||||
|
||||
GAPI_TRANSFORM(gmat_in_gsc_out, <GScalar(GMat)>, "gmat_in_gsc_out")
|
||||
{
|
||||
static GScalar pattern(GMat) { return {}; }
|
||||
static GScalar substitute(GMat) { return {}; }
|
||||
};
|
||||
|
||||
GAPI_TRANSFORM(garr_in_gmat_out, <GMat(GArray<int>)>, "garr_in_gmat_out")
|
||||
{
|
||||
static GMat pattern(GArray<int>) { return {}; }
|
||||
static GMat substitute(GArray<int>) { return {}; }
|
||||
};
|
||||
|
||||
GAPI_TRANSFORM(gmat_in_garr_out, <GArray<int>(GMat)>, "gmat_in_garr_out")
|
||||
{
|
||||
static GArray<int> pattern(GMat) { return {}; }
|
||||
static GArray<int> substitute(GMat) { return {}; }
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
TEST(KernelPackageTransform, CreatePackage)
|
||||
{
|
||||
auto pkg = cv::gapi::kernels
|
||||
< gmat_in_gmat_out
|
||||
, gmat2_in_gmat_out
|
||||
, gmat2_in_gmat3_out
|
||||
, gsc_in_gmat_out
|
||||
, gmat_in_gsc_out
|
||||
>();
|
||||
|
||||
auto tr = pkg.get_transformations();
|
||||
EXPECT_EQ(5u, tr.size());
|
||||
}
|
||||
|
||||
TEST(KernelPackageTransform, Include)
|
||||
{
|
||||
cv::gapi::GKernelPackage pkg;
|
||||
pkg.include<gmat_in_gmat_out>();
|
||||
pkg.include<gmat2_in_gmat_out>();
|
||||
pkg.include<gmat2_in_gmat3_out>();
|
||||
auto tr = pkg.get_transformations();
|
||||
EXPECT_EQ(3u, tr.size());
|
||||
}
|
||||
|
||||
TEST(KernelPackageTransform, Combine)
|
||||
{
|
||||
auto pkg1 = cv::gapi::kernels<gmat_in_gmat_out>();
|
||||
auto pkg2 = cv::gapi::kernels<gmat2_in_gmat_out>();
|
||||
auto pkg_comb = cv::gapi::combine(pkg1, pkg2);
|
||||
auto tr = pkg_comb.get_transformations();
|
||||
EXPECT_EQ(2u, tr.size());
|
||||
}
|
||||
|
||||
TEST(KernelPackageTransform, Pattern)
|
||||
{
|
||||
auto tr = gmat2_in_gmat3_out::transformation();
|
||||
GMat a, b;
|
||||
auto pattern = tr.pattern({cv::GArg(a), cv::GArg(b)});
|
||||
|
||||
// return type of '2gmat_in_gmat3_out' is GMat3
|
||||
EXPECT_EQ(3u, pattern.size());
|
||||
for (const auto& p : pattern)
|
||||
{
|
||||
EXPECT_NO_THROW(p.get<GMat>());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(KernelPackageTransform, Substitute)
|
||||
{
|
||||
auto tr = gmat2_in_gmat3_out::transformation();
|
||||
GMat a, b;
|
||||
auto subst = tr.substitute({cv::GArg(a), cv::GArg(b)});
|
||||
|
||||
EXPECT_EQ(3u, subst.size());
|
||||
for (const auto& s : subst)
|
||||
{
|
||||
EXPECT_NO_THROW(s.get<GMat>());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Transformation, typename InType, typename OutType>
|
||||
static void transformTest()
|
||||
{
|
||||
auto tr = Transformation::transformation();
|
||||
InType in;
|
||||
auto pattern = tr.pattern({cv::GArg(in)});
|
||||
auto subst = tr.substitute({cv::GArg(in)});
|
||||
|
||||
EXPECT_EQ(1u, pattern.size());
|
||||
EXPECT_EQ(1u, subst.size());
|
||||
|
||||
auto checkOut = [](GArg& garg) {
|
||||
EXPECT_TRUE(garg.kind == cv::detail::GTypeTraits<OutType>::kind);
|
||||
EXPECT_NO_THROW(garg.get<OutType>());
|
||||
};
|
||||
|
||||
checkOut(pattern[0]);
|
||||
checkOut(subst[0]);
|
||||
}
|
||||
|
||||
TEST(KernelPackageTransform, GMat)
|
||||
{
|
||||
transformTest<gmat_in_gmat_out, GMat, GMat>();
|
||||
}
|
||||
|
||||
TEST(KernelPackageTransform, GMatP)
|
||||
{
|
||||
transformTest<gmatp_in_gmatp_out, GMatP, GMatP>();
|
||||
}
|
||||
|
||||
TEST(KernelPackageTransform, GScalarIn)
|
||||
{
|
||||
transformTest<gsc_in_gmat_out, GScalar, GMat>();
|
||||
}
|
||||
|
||||
TEST(KernelPackageTransform, GScalarOut)
|
||||
{
|
||||
transformTest<gmat_in_gsc_out, GMat, GScalar>();
|
||||
}
|
||||
|
||||
TEST(KernelPackageTransform, DISABLED_GArrayIn)
|
||||
{
|
||||
transformTest<garr_in_gmat_out, GArray<int>, GMat>();
|
||||
}
|
||||
|
||||
TEST(KernelPackageTransform, DISABLED_GArrayOut)
|
||||
{
|
||||
transformTest<gmat_in_garr_out, GMat, GArray<int>>();
|
||||
}
|
||||
|
||||
} // namespace opencv_test
|
Loading…
Reference in New Issue
Block a user