Update fluid to 7c22cd49a7eb76ae1d9606672ee467fb52383de0 (#2407)

* Update fluid to 7c22cd49a7eb76ae1d9606672ee467fb52383de0

   OpenCV 4.5.0

* Fix windows build
This commit is contained in:
Artemy Skrebkov
2020-09-24 22:14:14 +03:00
committed by Vladislav Vinogradov
parent 4a46be7631
commit 7cd76c1d29
187 changed files with 13741 additions and 1957 deletions

View File

@@ -1 +1 @@
72f63b276e710e3c626e0ab3c072fdfd
d8947b3280c8644f9828fac2b36f5f5a

View File

@@ -13,14 +13,29 @@ if(NOT TARGET ade)
return()
endif()
if(INF_ENGINE_TARGET)
ocv_option(OPENCV_GAPI_INF_ENGINE "Build GraphAPI module with Inference Engine support" ON)
endif()
set(the_description "OpenCV G-API Core Module")
ocv_add_module(gapi opencv_imgproc)
ocv_add_module(gapi
REQUIRED
opencv_imgproc
OPTIONAL
opencv_video
WRAP
python
)
if(MSVC)
# Disable obsollete warning C4503 popping up on MSVC <<2017
# https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-1-c4503?view=vs-2019
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4503)
if (OPENCV_GAPI_INF_ENGINE AND NOT INF_ENGINE_RELEASE VERSION_GREATER "2021000000")
# Disable IE deprecated code warning C4996 for releases < 2021.1
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4996)
endif()
endif()
file(GLOB gapi_ext_hdrs
@@ -46,6 +61,7 @@ set(gapi_srcs
src/api/garray.cpp
src/api/gopaque.cpp
src/api/gscalar.cpp
src/api/gframe.cpp
src/api/gkernel.cpp
src/api/gbackend.cpp
src/api/gproto.cpp
@@ -55,6 +71,8 @@ set(gapi_srcs
src/api/operators.cpp
src/api/kernels_core.cpp
src/api/kernels_imgproc.cpp
src/api/kernels_video.cpp
src/api/kernels_nnparsers.cpp
src/api/render.cpp
src/api/render_ocv.cpp
src/api/ginfer.cpp
@@ -87,7 +105,9 @@ set(gapi_srcs
src/backends/cpu/gcpubackend.cpp
src/backends/cpu/gcpukernel.cpp
src/backends/cpu/gcpuimgproc.cpp
src/backends/cpu/gcpuvideo.cpp
src/backends/cpu/gcpucore.cpp
src/backends/cpu/gnnparsers.cpp
# Fluid Backend (also built-in, FIXME:move away)
src/backends/fluid/gfluidbuffer.cpp
@@ -105,6 +125,7 @@ set(gapi_srcs
# IE Backend. FIXME: should be included by CMake
# if and only if IE support is enabled
src/backends/ie/giebackend.cpp
src/backends/ie/giebackend/giewrapper.cpp
# Render Backend.
src/backends/render/grenderocvbackend.cpp
@@ -117,6 +138,10 @@ set(gapi_srcs
# Compound
src/backends/common/gcompoundbackend.cpp
src/backends/common/gcompoundkernel.cpp
# Serialization API and routines
src/api/s11n.cpp
src/backends/common/serialization.cpp
)
ocv_add_dispatched_file(backends/fluid/gfluidimgproc_func SSE4_1 AVX2)
@@ -132,12 +157,20 @@ ocv_module_include_directories("${CMAKE_CURRENT_LIST_DIR}/src")
ocv_create_module()
ocv_target_link_libraries(${the_module} PRIVATE ade ${INF_ENGINE_TARGET})
ocv_target_link_libraries(${the_module} PRIVATE ade)
if(OPENCV_GAPI_INF_ENGINE)
ocv_target_link_libraries(${the_module} PRIVATE ${INF_ENGINE_TARGET})
endif()
if(HAVE_TBB)
ocv_target_link_libraries(${the_module} PRIVATE tbb)
endif()
ocv_add_accuracy_tests(${INF_ENGINE_TARGET})
set(__test_extra_deps "")
if(OPENCV_GAPI_INF_ENGINE)
list(APPEND __test_extra_deps ${INF_ENGINE_TARGET})
endif()
ocv_add_accuracy_tests(${__test_extra_deps})
# FIXME: test binary is linked with ADE directly since ADE symbols
# are not exported from libopencv_gapi.so in any form - thus
# there're two copies of ADE code in memory when tests run (!)
@@ -165,5 +198,10 @@ if(HAVE_PLAIDML)
ocv_target_include_directories(${the_module} SYSTEM PRIVATE ${PLAIDML_INCLUDE_DIRS})
endif()
if(WIN32)
# Required for htonl/ntohl on Windows
ocv_target_link_libraries(${the_module} PRIVATE wsock32 ws2_32)
endif()
ocv_add_perf_tests()
ocv_add_samples()

View File

@@ -45,3 +45,8 @@ if(MSVC)
endif()
target_link_libraries(${FLUID_TARGET} PRIVATE ade)
if(WIN32)
# Required for htonl/ntohl on Windows
target_link_libraries(${FLUID_TARGET} PRIVATE wsock32 ws2_32)
endif()

View File

@@ -31,7 +31,7 @@ namespace core {
using GMat2 = std::tuple<GMat,GMat>;
using GMat3 = std::tuple<GMat,GMat,GMat>; // FIXME: how to avoid this?
using GMat4 = std::tuple<GMat,GMat,GMat,GMat>;
using GMatScalar = std::tuple<GMat, GScalar>;
using GMatScalar = std::tuple<GMat, GScalar>;
G_TYPED_KERNEL(GAdd, <GMat(GMat, GMat, int)>, "org.opencv.core.math.add") {
static GMatDesc outMeta(GMatDesc a, GMatDesc b, int ddepth) {
@@ -392,10 +392,10 @@ namespace core {
}
else
{
GAPI_Assert(fx != 0. && fy != 0.);
return in.withSize
(Size(static_cast<int>(round(in.size.width * fx)),
static_cast<int>(round(in.size.height * fy))));
int outSz_w = static_cast<int>(round(in.size.width * fx));
int outSz_h = static_cast<int>(round(in.size.height * fy));
GAPI_Assert(outSz_w > 0 && outSz_h > 0);
return in.withSize(Size(outSz_w, outSz_h));
}
}
};
@@ -501,6 +501,18 @@ namespace core {
return in.withType(in.depth, in.chan).withSize(dsize);
}
};
G_TYPED_KERNEL(GSize, <GOpaque<Size>(GMat)>, "org.opencv.core.size") {
static GOpaqueDesc outMeta(const GMatDesc&) {
return empty_gopaque_desc();
}
};
G_TYPED_KERNEL(GSizeR, <GOpaque<Size>(GOpaque<Rect>)>, "org.opencv.core.sizeR") {
static GOpaqueDesc outMeta(const GOpaqueDesc&) {
return empty_gopaque_desc();
}
};
}
//! @addtogroup gapi_math
@@ -528,7 +540,7 @@ Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref
@param ddepth optional depth of the output matrix.
@sa sub, addWeighted
*/
GAPI_EXPORTS GMat add(const GMat& src1, const GMat& src2, int ddepth = -1);
GAPI_EXPORTS_W GMat add(const GMat& src1, const GMat& src2, int ddepth = -1);
/** @brief Calculates the per-element sum of matrix and given scalar.
@@ -744,7 +756,7 @@ Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref
@note Function textual ID is "org.opencv.core.math.mean"
@param src input matrix.
*/
GAPI_EXPORTS GScalar mean(const GMat& src);
GAPI_EXPORTS_W GScalar mean(const GMat& src);
/** @brief Calculates x and y coordinates of 2D vectors from their magnitude and angle.
@@ -1434,7 +1446,7 @@ All output matrices must be in @ref CV_8UC1.
@sa merge3, merge4
*/
GAPI_EXPORTS std::tuple<GMat, GMat, GMat,GMat> split4(const GMat& src);
GAPI_EXPORTS std::tuple<GMat, GMat, GMat> split3(const GMat& src);
GAPI_EXPORTS_W std::tuple<GMat, GMat, GMat> split3(const GMat& src);
/** @brief Applies a generic geometrical transformation to an image.
@@ -1720,6 +1732,24 @@ GAPI_EXPORTS GMat warpAffine(const GMat& src, const Mat& M, const Size& dsize, i
int borderMode = cv::BORDER_CONSTANT, const Scalar& borderValue = Scalar());
//! @} gapi_transform
/** @brief Gets dimensions from Mat.
@note Function textual ID is "org.opencv.core.size"
@param src Input tensor
@return Size (tensor dimensions).
*/
GAPI_EXPORTS GOpaque<Size> size(const GMat& src);
/** @overload
Gets dimensions from rectangle.
@note Function textual ID is "org.opencv.core.sizeR"
@param r Input rectangle.
@return Size (rectangle dimensions).
*/
GAPI_EXPORTS GOpaque<Size> size(const GOpaque<Rect>& r);
} //namespace gapi
} //namespace cv

View File

@@ -16,7 +16,7 @@ namespace gapi {
namespace core {
namespace cpu {
GAPI_EXPORTS GKernelPackage kernels();
GAPI_EXPORTS_W cv::gapi::GKernelPackage kernels();
} // namespace cpu
} // namespace core

View File

@@ -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-2019 Intel Corporation
// Copyright (C) 2018-2020 Intel Corporation
#ifndef OPENCV_GAPI_GCPUKERNEL_HPP
@@ -17,7 +17,7 @@
#include <opencv2/gapi/gcommon.hpp>
#include <opencv2/gapi/gkernel.hpp>
#include <opencv2/gapi/garg.hpp>
#include <opencv2/gapi/own/convert.hpp> //to_ocv
#include <opencv2/gapi/gmetaarg.hpp>
#include <opencv2/gapi/util/compiler_hints.hpp> //suppress_unused_warning
#include <opencv2/gapi/util/util.hpp>
@@ -96,8 +96,8 @@ public:
const T& inArg(int input) { return m_args.at(input).get<T>(); }
// Syntax sugar
const cv::gapi::own::Mat& inMat(int input);
cv::gapi::own::Mat& outMatR(int output); // FIXME: Avoid cv::gapi::own::Mat m = ctx.outMatR()
const cv::Mat& inMat(int input);
cv::Mat& outMatR(int output); // FIXME: Avoid cv::Mat m = ctx.outMatR()
const cv::Scalar& inVal(int input);
cv::Scalar& outValR(int output); // FIXME: Avoid cv::Scalar s = ctx.outValR()
@@ -110,11 +110,17 @@ public:
return outOpaqueRef(output).wref<T>();
}
GArg state()
{
return m_state;
}
protected:
detail::VectorRef& outVecRef(int output);
detail::OpaqueRef& outOpaqueRef(int output);
std::vector<GArg> m_args;
GArg m_state;
//FIXME: avoid conversion of arguments from internal representation to OpenCV one on each call
//to OCV kernel. (This can be achieved by a two single time conversions in GCPUExecutable::run,
@@ -128,16 +134,19 @@ protected:
class GAPI_EXPORTS GCPUKernel
{
public:
// This function is kernel's execution entry point (does the processing work)
using F = std::function<void(GCPUContext &)>;
// This function is a kernel's execution entry point (does the processing work)
using RunF = std::function<void(GCPUContext &)>;
// This function is a stateful kernel's setup routine (configures state)
using SetupF = std::function<void(const GMetaArgs &, const GArgs &,
GArg &, const GCompileArgs &)>;
GCPUKernel();
explicit GCPUKernel(const F& f);
GCPUKernel(const RunF& runF, const SetupF& setupF = nullptr);
void apply(GCPUContext &ctx);
RunF m_runF = nullptr;
SetupF m_setupF = nullptr;
protected:
F m_f;
bool m_isStateful = false;
};
// FIXME: This is an ugly ad-hoc implementation. TODO: refactor
@@ -147,12 +156,16 @@ namespace detail
template<class T> struct get_in;
template<> struct get_in<cv::GMat>
{
static cv::Mat get(GCPUContext &ctx, int idx) { return to_ocv(ctx.inMat(idx)); }
static cv::Mat get(GCPUContext &ctx, int idx) { return ctx.inMat(idx); }
};
template<> struct get_in<cv::GMatP>
{
static cv::Mat get(GCPUContext &ctx, int idx) { return get_in<cv::GMat>::get(ctx, idx); }
};
template<> struct get_in<cv::GFrame>
{
static cv::Mat get(GCPUContext &ctx, int idx) { return get_in<cv::GMat>::get(ctx, idx); }
};
template<> struct get_in<cv::GScalar>
{
static cv::Scalar get(GCPUContext &ctx, int idx) { return ctx.inVal(idx); }
@@ -192,7 +205,7 @@ template<class T> struct get_in
};
struct tracked_cv_mat{
tracked_cv_mat(cv::gapi::own::Mat& m) : r{to_ocv(m)}, original_data{m.data} {}
tracked_cv_mat(cv::Mat& m) : r{m}, original_data{m.data} {}
cv::Mat r;
uchar* original_data;
@@ -252,6 +265,12 @@ template<typename U> struct get_out<cv::GArray<U>>
return ctx.outVecR<U>(idx);
}
};
//FIXME(dm): GArray<Mat>/GArray<GMat> conversion should be done more gracefully in the system
template<> struct get_out<cv::GArray<cv::GMat> >: public get_out<cv::GArray<cv::Mat> >
{
};
template<typename U> struct get_out<cv::GOpaque<U>>
{
static U& get(GCPUContext &ctx, int idx)
@@ -260,12 +279,73 @@ template<typename U> struct get_out<cv::GOpaque<U>>
}
};
template<typename, typename>
struct OCVSetupHelper;
template<typename Impl, typename... Ins>
struct OCVSetupHelper<Impl, std::tuple<Ins...>>
{
// Using 'auto' return type and 'decltype' specifier in both 'setup_impl' versions
// to check existence of required 'Impl::setup' functions.
// While 'decltype' specifier accepts expression we pass expression with 'comma-operator'
// where first operand of comma-operator is call attempt to desired 'Impl::setup' and
// the second operand is 'void()' expression.
//
// SFINAE for 'Impl::setup' which accepts compile arguments.
template<int... IIs>
static auto setup_impl(const GMetaArgs &metaArgs, const GArgs &args,
GArg &state, const GCompileArgs &compileArgs,
detail::Seq<IIs...>) ->
decltype(Impl::setup(detail::get_in_meta<Ins>(metaArgs, args, IIs)...,
std::declval<typename std::add_lvalue_reference<
std::shared_ptr<typename Impl::State>
>::type
>(),
compileArgs)
, void())
{
// TODO: unique_ptr <-> shared_ptr conversion ?
// To check: Conversion is possible only if the state which should be passed to
// 'setup' user callback isn't required to have previous value
std::shared_ptr<typename Impl::State> stPtr;
Impl::setup(detail::get_in_meta<Ins>(metaArgs, args, IIs)..., stPtr, compileArgs);
state = GArg(stPtr);
}
// SFINAE for 'Impl::setup' which doesn't accept compile arguments.
template<int... IIs>
static auto setup_impl(const GMetaArgs &metaArgs, const GArgs &args,
GArg &state, const GCompileArgs &/* compileArgs */,
detail::Seq<IIs...>) ->
decltype(Impl::setup(detail::get_in_meta<Ins>(metaArgs, args, IIs)...,
std::declval<typename std::add_lvalue_reference<
std::shared_ptr<typename Impl::State>
>::type
>()
)
, void())
{
// The same comment as in 'setup' above.
std::shared_ptr<typename Impl::State> stPtr;
Impl::setup(detail::get_in_meta<Ins>(metaArgs, args, IIs)..., stPtr);
state = GArg(stPtr);
}
static void setup(const GMetaArgs &metaArgs, const GArgs &args,
GArg& state, const GCompileArgs &compileArgs)
{
setup_impl(metaArgs, args, state, compileArgs,
typename detail::MkSeq<sizeof...(Ins)>::type());
}
};
// OCVCallHelper is a helper class to call stateless OCV kernels and OCV kernel functors.
template<typename, typename, typename>
struct OCVCallHelper;
// FIXME: probably can be simplified with std::apply or analogue.
template<typename Impl, typename... Ins, typename... Outs>
struct OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
struct OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>>
{
template<typename... Inputs>
struct call_and_postprocess
@@ -293,19 +373,16 @@ struct OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
//by comparing it's state (data ptr) before and after the call.
//This is done by converting each output Mat into tracked_cv_mat object, and binding
//them to parameters of ad-hoc function
//Convert own::Scalar to cv::Scalar before call kernel and run kernel
//convert cv::Scalar to own::Scalar after call kernel and write back results
call_and_postprocess<decltype(get_in<Ins>::get(ctx, IIs))...>
::call(get_in<Ins>::get(ctx, IIs)...,
get_out<Outs>::get(ctx, OIs)...);
::call(get_in<Ins>::get(ctx, IIs)..., get_out<Outs>::get(ctx, OIs)...);
}
template<int... IIs, int... OIs>
static void call_impl(cv::GCPUContext &ctx, Impl& impl, detail::Seq<IIs...>, detail::Seq<OIs...>)
static void call_impl(cv::GCPUContext &ctx, Impl& impl,
detail::Seq<IIs...>, detail::Seq<OIs...>)
{
call_and_postprocess<decltype(cv::detail::get_in<Ins>::get(ctx, IIs))...>
::call(impl, cv::detail::get_in<Ins>::get(ctx, IIs)...,
cv::detail::get_out<Outs>::get(ctx, OIs)...);
call_and_postprocess<decltype(get_in<Ins>::get(ctx, IIs))...>
::call(impl, get_in<Ins>::get(ctx, IIs)..., get_out<Outs>::get(ctx, OIs)...);
}
static void call(GCPUContext &ctx)
@@ -326,30 +403,86 @@ struct OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
}
};
// OCVStCallHelper is a helper class to call stateful OCV kernels.
template<typename, typename, typename>
struct OCVStCallHelper;
template<typename Impl, typename... Ins, typename... Outs>
struct OCVStCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>> :
OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>>
{
template<typename... Inputs>
struct call_and_postprocess
{
template<typename... Outputs>
static void call(typename Impl::State& st, Inputs&&... ins, Outputs&&... outs)
{
Impl::run(std::forward<Inputs>(ins)..., outs..., st);
postprocess(outs...);
}
};
template<int... IIs, int... OIs>
static void call_impl(GCPUContext &ctx, detail::Seq<IIs...>, detail::Seq<OIs...>)
{
auto& st = *ctx.state().get<std::shared_ptr<typename Impl::State>>();
call_and_postprocess<decltype(get_in<Ins>::get(ctx, IIs))...>
::call(st, get_in<Ins>::get(ctx, IIs)..., get_out<Outs>::get(ctx, OIs)...);
}
static void call(GCPUContext &ctx)
{
call_impl(ctx,
typename detail::MkSeq<sizeof...(Ins)>::type(),
typename detail::MkSeq<sizeof...(Outs)>::type());
}
};
} // namespace detail
template<class Impl, class K>
class GCPUKernelImpl: public cv::detail::OCVCallHelper<Impl, typename K::InArgs, typename K::OutArgs>,
public cv::detail::KernelTag
class GCPUKernelImpl: public cv::detail::KernelTag
{
using P = detail::OCVCallHelper<Impl, typename K::InArgs, typename K::OutArgs>;
using CallHelper = detail::OCVCallHelper<Impl, typename K::InArgs, typename K::OutArgs>;
public:
using API = K;
static cv::gapi::GBackend backend() { return cv::gapi::cpu::backend(); }
static cv::GCPUKernel kernel() { return GCPUKernel(&P::call); }
static cv::gapi::GBackend backend() { return cv::gapi::cpu::backend(); }
static cv::GCPUKernel kernel() { return GCPUKernel(&CallHelper::call); }
};
template<class Impl, class K, class S>
class GCPUStKernelImpl: public cv::detail::KernelTag
{
using StSetupHelper = detail::OCVSetupHelper<Impl, typename K::InArgs>;
using StCallHelper = detail::OCVStCallHelper<Impl, typename K::InArgs, typename K::OutArgs>;
public:
using API = K;
using State = S;
static cv::gapi::GBackend backend() { return cv::gapi::cpu::backend(); }
static cv::GCPUKernel kernel() { return GCPUKernel(&StCallHelper::call,
&StSetupHelper::setup); }
};
#define GAPI_OCV_KERNEL(Name, API) struct Name: public cv::GCPUKernelImpl<Name, API>
// TODO: Reuse Anatoliy's logic for support of types with commas in macro.
// Retrieve the common part from Anatoliy's logic to the separate place.
#define GAPI_OCV_KERNEL_ST(Name, API, State) \
struct Name: public cv::GCPUStKernelImpl<Name, API, State> \
class gapi::cpu::GOCVFunctor : public gapi::GFunctor
{
public:
using Impl = std::function<void(GCPUContext &)>;
using Meta = cv::GKernel::M;
GOCVFunctor(const char* id, const Impl& impl)
: gapi::GFunctor(id), impl_{GCPUKernel(impl)}
GOCVFunctor(const char* id, const Meta &meta, const Impl& impl)
: gapi::GFunctor(id), impl_{GCPUKernel(impl), meta}
{
}
@@ -365,14 +498,20 @@ template<typename K, typename Callable>
gapi::cpu::GOCVFunctor gapi::cpu::ocv_kernel(Callable& c)
{
using P = detail::OCVCallHelper<Callable, typename K::InArgs, typename K::OutArgs>;
return GOCVFunctor(K::id(), std::bind(&P::callFunctor, std::placeholders::_1, std::ref(c)));
return GOCVFunctor{ K::id()
, &K::getOutMeta
, std::bind(&P::callFunctor, std::placeholders::_1, std::ref(c))
};
}
template<typename K, typename Callable>
gapi::cpu::GOCVFunctor gapi::cpu::ocv_kernel(const Callable& c)
{
using P = detail::OCVCallHelper<Callable, typename K::InArgs, typename K::OutArgs>;
return GOCVFunctor(K::id(), std::bind(&P::callFunctor, std::placeholders::_1, c));
return GOCVFunctor{ K::id()
, &K::getOutMeta
, std::bind(&P::callFunctor, std::placeholders::_1, c)
};
}
//! @endcond

View File

@@ -0,0 +1,25 @@
// 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) 2020 Intel Corporation
#ifndef OPENCV_GAPI_CPU_VIDEO_API_HPP
#define OPENCV_GAPI_CPU_VIDEO_API_HPP
#include <opencv2/gapi/gkernel.hpp> // GKernelPackage
namespace cv {
namespace gapi {
namespace video {
namespace cpu {
GAPI_EXPORTS GKernelPackage kernels();
} // namespace cpu
} // namespace video
} // namespace gapi
} // namespace cv
#endif // OPENCV_GAPI_CPU_VIDEO_API_HPP

View File

@@ -13,7 +13,7 @@
namespace cv { namespace gapi { namespace core { namespace fluid {
GAPI_EXPORTS GKernelPackage kernels();
GAPI_EXPORTS_W cv::gapi::GKernelPackage kernels();
}}}}

View File

@@ -14,11 +14,9 @@
#include <cstdint> // uint8_t
#include <opencv2/gapi/opencv_includes.hpp>
#include <opencv2/gapi/own/mat.hpp>
#include <opencv2/gapi/gmat.hpp>
#include <opencv2/gapi/util/optional.hpp>
#include <opencv2/gapi/own/mat.hpp>
namespace cv {
namespace gapi {
@@ -58,8 +56,6 @@ public:
}
};
View() = default;
const inline uint8_t* InLineB(int index) const // -(w-1)/2...0...+(w-1)/2 for Filters
{
return m_cache->linePtr(index);
@@ -82,11 +78,15 @@ public:
Priv& priv(); // internal use only
const Priv& priv() const; // internal use only
View(Priv* p);
View();
View(std::unique_ptr<Priv>&& p);
View(View&& v);
View& operator=(View&& v);
~View();
private:
std::shared_ptr<Priv> m_priv;
const Cache* m_cache;
std::unique_ptr<Priv> m_priv;
const Cache* m_cache = nullptr;
};
class GAPI_EXPORTS Buffer
@@ -111,7 +111,9 @@ public:
int wlpi,
BorderOpt border);
// Constructor for in/out buffers (for tests)
Buffer(const cv::gapi::own::Mat &data, bool is_input);
Buffer(const cv::Mat &data, bool is_input);
~Buffer();
Buffer& operator=(Buffer&&);
inline uint8_t* OutLineB(int index = 0)
{
@@ -134,13 +136,14 @@ public:
inline const GMatDesc& meta() const { return m_cache->m_desc; }
View mkView(int borderSize, bool ownStorage);
void addView(const View* v);
class GAPI_EXPORTS Priv; // internal use only
Priv& priv(); // internal use only
const Priv& priv() const; // internal use only
private:
std::shared_ptr<Priv> m_priv;
std::unique_ptr<Priv> m_priv;
const Cache* m_cache;
};

View File

@@ -171,7 +171,7 @@ template<> struct fluid_get_in<cv::GMat>
{
static const cv::gapi::fluid::View& get(const cv::GArgs &in_args, int idx)
{
return in_args[idx].unsafe_get<cv::gapi::fluid::View>();
return *in_args[idx].unsafe_get<cv::gapi::fluid::View*>();
}
};

View File

@@ -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-2020 Intel Corporation
#ifndef OPENCV_GAPI_GARG_HPP
@@ -46,6 +46,7 @@ public:
template<typename T, typename std::enable_if<!detail::is_garg<T>::value, int>::type = 0>
explicit GArg(const T &t)
: kind(detail::GTypeTraits<T>::kind)
, opaque_kind(detail::GOpaqueTraits<T>::kind)
, value(detail::wrap_gapi_helper<T>::wrap(t))
{
}
@@ -53,6 +54,7 @@ public:
template<typename T, typename std::enable_if<!detail::is_garg<T>::value, int>::type = 0>
explicit GArg(T &&t)
: kind(detail::GTypeTraits<typename std::decay<T>::type>::kind)
, opaque_kind(detail::GOpaqueTraits<typename std::decay<T>::type>::kind)
, value(detail::wrap_gapi_helper<T>::wrap(t))
{
}
@@ -78,6 +80,7 @@ public:
}
detail::ArgKind kind = detail::ArgKind::OPAQUE_VAL;
detail::OpaqueKind opaque_kind = detail::OpaqueKind::CV_UNKNOWN;
protected:
util::any value;
@@ -89,17 +92,33 @@ using GArgs = std::vector<GArg>;
// FIXME: Move to a separate file!
using GRunArg = util::variant<
#if !defined(GAPI_STANDALONE)
cv::Mat,
cv::UMat,
#endif // !defined(GAPI_STANDALONE)
cv::gapi::wip::IStreamSource::Ptr,
cv::gapi::own::Mat,
cv::Mat,
cv::Scalar,
cv::detail::VectorRef,
cv::detail::OpaqueRef
>;
using GRunArgs = std::vector<GRunArg>;
// TODO: Think about the addition operator
/**
* @brief This operator allows to complement the input vector at runtime.
*
* It's an ordinary overload of addition assignment operator.
*
* Example of usage:
* @snippet dynamic_graph.cpp GRunArgs usage
*
*/
inline GRunArgs& operator += (GRunArgs &lhs, const GRunArgs &rhs)
{
lhs.reserve(lhs.size() + rhs.size());
lhs.insert(lhs.end(), rhs.begin(), rhs.end());
return lhs;
}
namespace gapi
{
namespace wip
@@ -122,16 +141,38 @@ struct Data: public GRunArg
using GRunArgP = util::variant<
#if !defined(GAPI_STANDALONE)
cv::Mat*,
cv::UMat*,
#endif // !defined(GAPI_STANDALONE)
cv::gapi::own::Mat*,
cv::Mat*,
cv::Scalar*,
cv::detail::VectorRef,
cv::detail::OpaqueRef
>;
using GRunArgsP = std::vector<GRunArgP>;
// TODO: Think about the addition operator
/**
* @brief This operator allows to complement the output vector at runtime.
*
* It's an ordinary overload of addition assignment operator.
*
* Example of usage:
* @snippet dynamic_graph.cpp GRunArgsP usage
*
*/
inline GRunArgsP& operator += (GRunArgsP &lhs, const GRunArgsP &rhs)
{
lhs.reserve(lhs.size() + rhs.size());
lhs.insert(lhs.end(), rhs.begin(), rhs.end());
return lhs;
}
namespace gapi
{
GAPI_EXPORTS cv::GRunArgsP bind(cv::GRunArgs &results);
GAPI_EXPORTS cv::GRunArg bind(cv::GRunArgP &out); // FIXME: think more about it
}
template<typename... Ts> inline GRunArgs gin(const Ts&... args)
{
return GRunArgs{ GRunArg(detail::wrap_host_helper<Ts>::wrap_in(args))... };

View File

@@ -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-2020 Intel Corporation
#ifndef OPENCV_GAPI_GARRAY_HPP
@@ -29,7 +29,6 @@ namespace cv
// (user-inaccessible) classes.
class GNode;
struct GOrigin;
template<typename T> class GArray;
/**
@@ -81,6 +80,7 @@ namespace detail
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
@@ -88,6 +88,11 @@ namespace detail
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;
};
@@ -104,6 +109,11 @@ namespace detail
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
@@ -111,11 +121,14 @@ namespace detail
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
@@ -208,6 +221,9 @@ namespace detail
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
@@ -220,6 +236,7 @@ namespace detail
class VectorRef
{
std::shared_ptr<BasicVectorRef> m_ref;
cv::detail::OpaqueKind m_kind;
template<typename T> inline void check() const
{
@@ -229,18 +246,32 @@ namespace detail
public:
VectorRef() = default;
template<typename T> explicit VectorRef(const std::vector<T>& vec) : m_ref(new VectorRefT<T>(vec)) {}
template<typename T> explicit VectorRef(std::vector<T>& vec) : m_ref(new VectorRefT<T>(vec)) {}
template<typename T> explicit VectorRef(std::vector<T>&& vec) : m_ref(new VectorRefT<T>(vec)) {}
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>();
@@ -262,6 +293,14 @@ namespace detail
{
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?)
@@ -290,6 +329,14 @@ namespace detail
template<typename T> class GArray
{
public:
// Host type (or Flat type) - the type this GArray is actually
// specified to.
using HT = typename detail::flatten_g<typename std::decay<T>::type>::type;
explicit GArray(const std::vector<HT>& v) // Constant value constructor
: m_ref(detail::GArrayU(detail::VectorRef(v))) { putDetails(); }
explicit GArray(std::vector<HT>&& v) // Move-constructor
: m_ref(detail::GArrayU(detail::VectorRef(std::move(v)))) { putDetails(); }
GArray() { putDetails(); } // Empty constructor
explicit GArray(detail::GArrayU &&ref) // GArrayU-based constructor
: m_ref(ref) { putDetails(); } // (used by GCall, not for users)
@@ -297,16 +344,14 @@ public:
detail::GArrayU strip() const { return m_ref; }
private:
// Host type (or Flat type) - the type this GArray is actually
// specified to.
using HT = typename detail::flatten_g<typename std::decay<T>::type>::type;
static void VCTor(detail::VectorRef& vref) {
vref.reset<HT>();
vref.storeKind<HT>();
}
void putDetails() {
m_ref.setConstructFcn(&VCTor);
m_ref.specifyType<HT>();
m_ref.specifyType<HT>(); // FIXME: to unify those 2 to avoid excessive dynamic_cast
m_ref.storeKind<HT>(); //
}
detail::GArrayU m_ref;

View File

@@ -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-2020 Intel Corporation
#ifndef OPENCV_GAPI_GCOMMON_HPP
@@ -15,11 +15,15 @@
#include <opencv2/gapi/opencv_includes.hpp>
#include <opencv2/gapi/util/any.hpp>
#include <opencv2/gapi/util/optional.hpp>
#include <opencv2/gapi/own/exports.hpp>
#include <opencv2/gapi/own/assert.hpp>
#include <opencv2/gapi/render/render_types.hpp>
namespace cv {
class GMat; // FIXME: forward declaration for GOpaqueTraits
namespace detail
{
// This is a trait-like structure to mark backend-specific compile arguments
@@ -31,7 +35,42 @@ namespace detail
{};
struct TransformTag
{};
}
// This enum is utilized mostly by GArray and GOpaque to store and recognize their internal data
// types (aka Host type). Also it is widely used during serialization routine.
enum class OpaqueKind: int
{
CV_UNKNOWN, // Unknown, generic, opaque-to-GAPI data type unsupported in graph seriallization
CV_BOOL, // bool user G-API data
CV_INT, // int user G-API data
CV_DOUBLE, // double user G-API data
CV_POINT, // cv::Point user G-API data
CV_SIZE, // cv::Size user G-API data
CV_RECT, // cv::Rect user G-API data
CV_SCALAR, // cv::Scalar user G-API data
CV_MAT, // cv::Mat user G-API data
CV_PRIM, // cv::gapi::wip::draw::Prim user G-API data
};
// Type traits helper which simplifies the extraction of kind from type
template<typename T> struct GOpaqueTraits;
template<typename T> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_UNKNOWN; };
template<> struct GOpaqueTraits<int> { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT; };
template<> struct GOpaqueTraits<double> { static constexpr const OpaqueKind kind = OpaqueKind::CV_DOUBLE; };
template<> struct GOpaqueTraits<cv::Size> { static constexpr const OpaqueKind kind = OpaqueKind::CV_SIZE; };
template<> struct GOpaqueTraits<bool> { static constexpr const OpaqueKind kind = OpaqueKind::CV_BOOL; };
template<> struct GOpaqueTraits<cv::Scalar> { static constexpr const OpaqueKind kind = OpaqueKind::CV_SCALAR; };
template<> struct GOpaqueTraits<cv::Point> { static constexpr const OpaqueKind kind = OpaqueKind::CV_POINT; };
template<> struct GOpaqueTraits<cv::Mat> { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; };
template<> struct GOpaqueTraits<cv::Rect> { static constexpr const OpaqueKind kind = OpaqueKind::CV_RECT; };
template<> struct GOpaqueTraits<cv::GMat> { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; };
template<> struct GOpaqueTraits<cv::gapi::wip::draw::Prim>
{ static constexpr const OpaqueKind kind = OpaqueKind::CV_PRIM; };
// GArray is not supporting bool type for now due to difference in std::vector<bool> implementation
using GOpaqueTraitsArrayTypes = std::tuple<int, double, cv::Size, cv::Scalar, cv::Point, cv::Mat, cv::Rect, cv::gapi::wip::draw::Prim>;
// GOpaque is not supporting cv::Mat and cv::Scalar since there are GScalar and GMat types
using GOpaqueTraitsOpaqueTypes = std::tuple<bool, int, double, cv::Size, cv::Point, cv::Rect, cv::gapi::wip::draw::Prim>;
} // namespace detail
// This definition is here because it is reused by both public(?) and internal
// modules. Keeping it here wouldn't expose public details (e.g., API-level)
@@ -45,6 +84,7 @@ enum class GShape: int
GSCALAR,
GARRAY,
GOPAQUE,
GFRAME,
};
struct GCompileArg;
@@ -52,7 +92,8 @@ struct GCompileArg;
namespace detail {
template<typename T>
using is_compile_arg = std::is_same<GCompileArg, typename std::decay<T>::type>;
}
} // namespace detail
// CompileArg is an unified interface over backend-specific compilation
// information
// FIXME: Move to a separate file?
@@ -91,9 +132,12 @@ namespace detail {
* passed in (a variadic template parameter pack) into a vector of
* cv::GCompileArg objects.
*/
struct GAPI_EXPORTS GCompileArg
struct GAPI_EXPORTS_W_SIMPLE GCompileArg
{
public:
// NB: Required for pythnon bindings
GCompileArg() = default;
std::string tag;
// FIXME: use decay in GArg/other trait-based wrapper before leg is shot!
@@ -121,14 +165,34 @@ private:
using GCompileArgs = std::vector<GCompileArg>;
/**
* Wraps a list of arguments (a parameter pack) into a vector of
* compilation arguments (cv::GCompileArg).
* @brief Wraps a list of arguments (a parameter pack) into a vector of
* compilation arguments (cv::GCompileArg).
*/
template<typename... Ts> GCompileArgs compile_args(Ts&&... args)
{
return GCompileArgs{ GCompileArg(args)... };
}
/**
* @brief Retrieves particular compilation argument by its type from
* cv::GCompileArgs
*/
namespace gapi
{
template<typename T>
inline cv::util::optional<T> getCompileArg(const cv::GCompileArgs &args)
{
for (auto &compile_arg : args)
{
if (compile_arg.tag == cv::detail::CompileArgTag<T>::tag())
{
return cv::util::optional<T>(compile_arg.get<T>());
}
}
return cv::util::optional<T>();
}
} // namespace gapi
/**
* @brief Ask G-API to dump compiled graph in Graphviz format under
* the given file name.

View File

@@ -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-2020 Intel Corporation
#ifndef OPENCV_GAPI_GCOMPILED_HPP
@@ -208,6 +208,19 @@ public:
// FIXME: Why it requires compile args?
void reshape(const GMetaArgs& inMetas, const GCompileArgs& args);
/**
* @brief Prepare inner kernels states for a new video-stream.
*
* GCompiled objects may be used to process video streams frame by frame.
* In this case, a GCompiled is called on every image frame individually.
* Starting OpenCV 4.4, some kernels in the graph may have their internal
* states (see GAPI_OCV_KERNEL_ST for the OpenCV backend).
* In this case, if user starts processing another video stream with
* this GCompiled, this method needs to be called to let kernels re-initialize
* their internal states to a new video stream.
*/
void prepareForNewStream();
protected:
/// @private
std::shared_ptr<Priv> m_priv;

View File

@@ -75,6 +75,16 @@ template<typename U> struct get_compound_in<cv::GOpaque<U>>
}
};
template<> struct get_compound_in<cv::GMatP>
{
static cv::GMatP get(GCompoundContext &ctx, int idx)
{
auto mat = cv::GMatP();
ctx.m_args[idx] = GArg(mat);
return mat;
}
};
template<typename, typename, typename>
struct GCompoundCallHelper;

View File

@@ -36,6 +36,16 @@ namespace detail
using last_type_t = typename last_type<Ts...>::type;
}
// Forward-declare the serialization objects
namespace gimpl {
namespace s11n {
namespace I {
struct IStream;
struct OStream;
} // namespace I
} // namespace s11n
} // namespace gimpl
/**
* \addtogroup gapi_main_classes
* @{
@@ -108,7 +118,7 @@ namespace detail
*
* @sa GCompiled
*/
class GAPI_EXPORTS GComputation
class GAPI_EXPORTS_W GComputation
{
public:
class Priv;
@@ -151,8 +161,8 @@ public:
*
* @sa @ref gapi_data_objects
*/
GComputation(GProtoInputArgs &&ins,
GProtoOutputArgs &&outs); // Arg-to-arg overload
GAPI_WRAP GComputation(GProtoInputArgs &&ins,
GProtoOutputArgs &&outs); // Arg-to-arg overload
// 2. Syntax sugar and compatibility overloads
/**
@@ -162,7 +172,7 @@ public:
* @param in input GMat of the defined unary computation
* @param out output GMat of the defined unary computation
*/
GComputation(GMat in, GMat out); // Unary overload
GAPI_WRAP GComputation(GMat in, GMat out); // Unary overload
/**
* @brief Defines an unary (one input -- one output) computation
@@ -171,7 +181,7 @@ public:
* @param in input GMat of the defined unary computation
* @param out output GScalar of the defined unary computation
*/
GComputation(GMat in, GScalar out); // Unary overload (scalar)
GAPI_WRAP GComputation(GMat in, GScalar out); // Unary overload (scalar)
/**
* @brief Defines a binary (two inputs -- one output) computation
@@ -181,7 +191,7 @@ public:
* @param in2 second input GMat of the defined binary computation
* @param out output GMat of the defined binary computation
*/
GComputation(GMat in1, GMat in2, GMat out); // Binary overload
GAPI_WRAP GComputation(GMat in1, GMat in2, GMat out); // Binary overload
/**
* @brief Defines a binary (two inputs -- one output) computation
@@ -250,8 +260,8 @@ public:
void apply(GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args = {}); // Arg-to-arg overload
/// @private -- Exclude this function from OpenCV documentation
void apply(const std::vector<cv::gapi::own::Mat>& ins, // Compatibility overload
const std::vector<cv::gapi::own::Mat>& outs,
void apply(const std::vector<cv::Mat>& ins, // Compatibility overload
const std::vector<cv::Mat>& outs,
GCompileArgs &&args = {});
// 2. Syntax sugar and compatibility overloads
@@ -265,7 +275,7 @@ public:
* @param args compilation arguments for underlying compilation
* process.
*/
void apply(cv::Mat in, cv::Mat &out, GCompileArgs &&args = {}); // Unary overload
void apply(cv::Mat in, cv::Mat &out, GCompileArgs &&args = {}); // Unary overload
/**
* @brief Execute an unary computation (with compilation on the fly)
@@ -276,7 +286,7 @@ public:
* @param args compilation arguments for underlying compilation
* process.
*/
void apply(cv::Mat in, cv::Scalar &out, GCompileArgs &&args = {}); // Unary overload (scalar)
GAPI_WRAP void apply(cv::Mat in, CV_OUT cv::Scalar &out, GCompileArgs &&args = {}); // Unary overload (scalar)
/**
* @brief Execute a binary computation (with compilation on the fly)
@@ -288,7 +298,7 @@ public:
* @param args compilation arguments for underlying compilation
* process.
*/
void apply(cv::Mat in1, cv::Mat in2, cv::Mat &out, GCompileArgs &&args = {}); // Binary overload
GAPI_WRAP void apply(cv::Mat in1, cv::Mat in2, CV_OUT cv::Mat &out, GCompileArgs &&args = {}); // Binary overload
/**
* @brief Execute an binary computation (with compilation on the fly)
@@ -495,6 +505,10 @@ public:
Priv& priv();
/// @private
const Priv& priv() const;
/// @private
explicit GComputation(cv::gimpl::s11n::I::IStream &);
/// @private
void serialize(cv::gimpl::s11n::I::OStream &) const;
protected:

View File

@@ -0,0 +1,59 @@
// 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) 2020 Intel Corporation
#ifndef OPENCV_GAPI_GFRAME_HPP
#define OPENCV_GAPI_GFRAME_HPP
#include <ostream>
#include <memory> // std::shared_ptr
#include <opencv2/gapi/opencv_includes.hpp>
#include <opencv2/gapi/gcommon.hpp> // GShape
#include <opencv2/gapi/gmat.hpp>
#include <opencv2/gapi/own/assert.hpp>
// TODO GAPI_EXPORTS or so
namespace cv
{
// Forward declaration; GNode and GOrigin are an internal
// (user-inaccessible) classes.
class GNode;
struct GOrigin;
/** \addtogroup gapi_data_objects
* @{
*/
class GAPI_EXPORTS_W_SIMPLE GFrame
{
public:
GAPI_WRAP GFrame(); // Empty constructor
GFrame(const GNode &n, std::size_t out); // Operation result constructor
GOrigin& priv(); // Internal use only
const GOrigin& priv() const; // Internal use only
private:
std::shared_ptr<GOrigin> m_priv;
};
/** @} */
/**
* \addtogroup gapi_meta_args
* @{
*/
struct GAPI_EXPORTS GFrameDesc
{
};
static inline GFrameDesc empty_gframe_desc() { return GFrameDesc{}; }
/** @} */
GAPI_EXPORTS std::ostream& operator<<(std::ostream& os, const cv::GFrameDesc &desc);
} // namespace cv
#endif // OPENCV_GAPI_GFRAME_HPP

View File

@@ -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-2019 Intel Corporation
// Copyright (C) 2018-2020 Intel Corporation
#ifndef OPENCV_GAPI_GKERNEL_HPP
@@ -27,6 +27,7 @@
namespace cv {
using GShapes = std::vector<GShape>;
using GKinds = std::vector<cv::detail::OpaqueKind>;
// GKernel describes kernel API to the system
// FIXME: add attributes of a kernel, (e.g. number and types
@@ -35,16 +36,20 @@ struct GAPI_EXPORTS GKernel
{
using M = std::function<GMetaArgs(const GMetaArgs &, const GArgs &)>;
const std::string name; // kernel ID, defined by its API (signature)
const std::string tag; // some (implementation-specific) tag
const M outMeta; // generic adaptor to API::outMeta(...)
const GShapes outShapes; // types (shapes) kernel's outputs
std::string name; // kernel ID, defined by its API (signature)
std::string tag; // some (implementation-specific) tag
M outMeta; // generic adaptor to API::outMeta(...)
GShapes outShapes; // types (shapes) kernel's outputs
GKinds inKinds; // kinds of kernel's inputs (fixme: below)
};
// TODO: It's questionable if inKinds should really be here. Instead,
// this information could come from meta.
// GKernelImpl describes particular kernel implementation to the system
struct GAPI_EXPORTS GKernelImpl
{
util::any opaque; // backend-specific opaque info
GKernel::M outMeta; // for deserialized graphs, the outMeta is taken here
};
template<typename, typename> class GKernelTypeM;
@@ -90,6 +95,7 @@ namespace detail
template<typename T> struct MetaType;
template<> struct MetaType<cv::GMat> { using type = GMatDesc; };
template<> struct MetaType<cv::GMatP> { using type = GMatDesc; };
template<> struct MetaType<cv::GFrame> { using type = GMatDesc; };
template<> struct MetaType<cv::GScalar> { using type = GScalarDesc; };
template<typename U> struct MetaType<cv::GArray<U> > { using type = GArrayDesc; };
template<typename U> struct MetaType<cv::GOpaque<U> > { using type = GOpaqueDesc; };
@@ -201,10 +207,15 @@ public:
using InArgs = std::tuple<Args...>;
using OutArgs = std::tuple<R...>;
// TODO: Args&&... here?
static std::tuple<R...> on(Args... args)
{
cv::GCall call(GKernel{K::id(), K::tag(), &K::getOutMeta, {detail::GTypeTraits<R>::shape...}});
call.pass(args...);
cv::GCall call(GKernel{ K::id()
, K::tag()
, &K::getOutMeta
, {detail::GTypeTraits<R>::shape...}
, {detail::GTypeTraits<Args>::op_kind...}});
call.pass(args...); // TODO: std::forward() here?
return yield(call, typename detail::MkSeq<sizeof...(R)>::type());
}
};
@@ -220,9 +231,15 @@ public:
using InArgs = std::tuple<Args...>;
using OutArgs = std::tuple<R>;
static_assert(!cv::detail::contains<GFrame, OutArgs>::value, "Values of GFrame type can't be used as operation outputs");
static R on(Args... args)
{
cv::GCall call(GKernel{K::id(), K::tag(), &K::getOutMeta, {detail::GTypeTraits<R>::shape}});
cv::GCall call(GKernel{ K::id()
, K::tag()
, &K::getOutMeta
, {detail::GTypeTraits<R>::shape}
, {detail::GTypeTraits<Args>::op_kind...}});
call.pass(args...);
return detail::Yield<R>::yield(call, 0);
}
@@ -428,7 +445,7 @@ namespace gapi {
* Finally, two kernel packages can be combined into a new one
* with function cv::gapi::combine().
*/
class GAPI_EXPORTS GKernelPackage
class GAPI_EXPORTS_W_SIMPLE GKernelPackage
{
/// @private
@@ -453,12 +470,12 @@ namespace gapi {
/// @private
// Partial include() specialization for kernels
template <typename KImpl>
typename std::enable_if<(std::is_base_of<detail::KernelTag, KImpl>::value), void>::type
typename std::enable_if<(std::is_base_of<cv::detail::KernelTag, KImpl>::value), void>::type
includeHelper()
{
auto backend = KImpl::backend();
auto kernel_id = KImpl::API::id();
auto kernel_impl = GKernelImpl{KImpl::kernel()};
auto kernel_impl = GKernelImpl{KImpl::kernel(), &KImpl::API::getOutMeta};
removeAPI(kernel_id);
m_id_kernels[kernel_id] = std::make_pair(backend, kernel_impl);
@@ -467,7 +484,7 @@ namespace gapi {
/// @private
// Partial include() specialization for transformations
template <typename TImpl>
typename std::enable_if<(std::is_base_of<detail::TransformTag, TImpl>::value), void>::type
typename std::enable_if<(std::is_base_of<cv::detail::TransformTag, TImpl>::value), void>::type
includeHelper()
{
m_transformations.emplace_back(TImpl::transformation());
@@ -506,7 +523,7 @@ namespace gapi {
template<typename KImpl>
bool includes() const
{
static_assert(std::is_base_of<detail::KernelTag, KImpl>::value,
static_assert(std::is_base_of<cv::detail::KernelTag, KImpl>::value,
"includes() can be applied to kernels only");
auto kernel_it = m_id_kernels.find(KImpl::API::id());
@@ -621,7 +638,7 @@ namespace gapi {
{
// 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");
static_assert(cv::detail::all_unique<typename KK::API...>::value, "Kernels API must be unique");
GKernelPackage pkg;
@@ -695,6 +712,7 @@ namespace detail
static const char* tag() { return "gapi.use_only"; }
};
} // namespace detail
} // namespace cv
#endif // OPENCV_GAPI_GKERNEL_HPP

View File

@@ -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-2020 Intel Corporation
#ifndef OPENCV_GAPI_GMAT_HPP
@@ -46,10 +46,10 @@ struct GOrigin;
* `cv::GArray<T>` | std::vector<T>
* `cv::GOpaque<T>` | T
*/
class GAPI_EXPORTS GMat
class GAPI_EXPORTS_W_SIMPLE GMat
{
public:
GMat(); // Empty constructor
GAPI_WRAP GMat(); // Empty constructor
GMat(const GNode &n, std::size_t out); // Operation result constructor
GOrigin& priv(); // Internal use only
@@ -65,10 +65,6 @@ public:
using GMat::GMat;
};
namespace gapi { namespace own {
class Mat;
}}//gapi::own
/** @} */
/**
@@ -115,7 +111,7 @@ struct GAPI_EXPORTS GMatDesc
// (it handles the case when
// 1-channel mat can be reinterpreted as is (1-channel mat)
// and as a 3-channel planar mat with height divided by 3)
bool canDescribe(const cv::gapi::own::Mat& mat) const;
bool canDescribe(const cv::Mat& mat) const;
// Meta combinator: return a new GMatDesc which differs in size by delta
// (all other fields are taken unchanged from this GMatDesc)
@@ -126,9 +122,6 @@ struct GAPI_EXPORTS GMatDesc
desc.size += delta;
return desc;
}
#if !defined(GAPI_STANDALONE)
bool canDescribe(const cv::Mat& mat) const;
#endif // !defined(GAPI_STANDALONE)
// Meta combinator: return a new GMatDesc which differs in size by delta
// (all other fields are taken unchanged from this GMatDesc)
//
@@ -207,18 +200,23 @@ struct GAPI_EXPORTS GMatDesc
static inline GMatDesc empty_gmat_desc() { return GMatDesc{-1,-1,{-1,-1}}; }
#if !defined(GAPI_STANDALONE)
class Mat;
GAPI_EXPORTS GMatDesc descr_of(const cv::Mat &mat);
GAPI_EXPORTS GMatDesc descr_of(const cv::UMat &mat);
#endif // !defined(GAPI_STANDALONE)
/** @} */
// FIXME: WHY??? WHY it is under different namespace?
//Fwd declarations
namespace gapi { namespace own {
class Mat;
GAPI_EXPORTS GMatDesc descr_of(const Mat &mat);
}}//gapi::own
#if !defined(GAPI_STANDALONE)
GAPI_EXPORTS GMatDesc descr_of(const cv::Mat &mat);
#else
using gapi::own::descr_of;
#endif
/** @} */
GAPI_EXPORTS std::ostream& operator<<(std::ostream& os, const cv::GMatDesc &desc);
} // namespace cv

View File

@@ -66,12 +66,10 @@ namespace detail
// Note: descr_of(std::vector<..>) returns a GArrayDesc, while
// descrs_of(std::vector<..>) returns an array of Meta args!
class Mat;
class UMat;
GAPI_EXPORTS cv::GMetaArgs descrs_of(const std::vector<cv::Mat> &vec);
GAPI_EXPORTS cv::GMetaArgs descrs_of(const std::vector<cv::UMat> &vec);
namespace gapi { namespace own {
class Mat;
GAPI_EXPORTS cv::GMetaArgs descrs_of(const std::vector<Mat> &vec);
}} // namespace gapi::own

View File

@@ -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) 2019 Intel Corporation
// Copyright (C) 2019-2020 Intel Corporation
#ifndef OPENCV_GAPI_GOPAQUE_HPP
@@ -17,6 +17,7 @@
#include <opencv2/gapi/util/variant.hpp>
#include <opencv2/gapi/util/throw.hpp>
#include <opencv2/gapi/util/type_traits.hpp>
#include <opencv2/gapi/own/assert.hpp>
namespace cv
@@ -25,7 +26,6 @@ namespace cv
// (user-inaccessible) classes.
class GNode;
struct GOrigin;
template<typename T> class GOpaque;
/**
@@ -80,6 +80,11 @@ namespace detail
template <typename T>
void specifyType(); // Store type of initial GOpaque<T>
template <typename T>
void storeKind();
void setKind(cv::detail::OpaqueKind);
std::shared_ptr<GOrigin> m_priv;
std::shared_ptr<TypeHintBase> m_hint;
};
@@ -87,13 +92,19 @@ namespace detail
template <typename T>
bool GOpaqueU::holds() const{
GAPI_Assert(m_hint != nullptr);
using U = typename std::decay<T>::type;
using U = util::decay_t<T>;
return dynamic_cast<TypeHint<U>*>(m_hint.get()) != nullptr;
};
template <typename T>
void GOpaqueU::specifyType(){
m_hint.reset(new TypeHint<typename std::decay<T>::type>);
m_hint.reset(new TypeHint<util::decay_t<T>>);
};
template <typename T>
void GOpaqueU::storeKind(){
// FIXME: Add assert here on cv::Mat and cv::Scalar?
setKind(cv::detail::GOpaqueTraits<T>::kind);
};
// This class represents a typed object reference.
@@ -107,6 +118,7 @@ namespace detail
virtual ~BasicOpaqueRef() {}
virtual void mov(BasicOpaqueRef &ref) = 0;
virtual const void* ptr() const = 0;
};
template<typename T> class OpaqueRefT final: public BasicOpaqueRef
@@ -198,6 +210,8 @@ namespace detail
GAPI_Assert(tv != nullptr);
wref() = std::move(tv->wref());
}
virtual const void* ptr() const override { return &rref(); }
};
// This class strips type information from OpaqueRefT<> and makes it usable
@@ -209,6 +223,7 @@ namespace detail
class OpaqueRef
{
std::shared_ptr<BasicOpaqueRef> m_ref;
cv::detail::OpaqueKind m_kind;
template<typename T> inline void check() const
{
@@ -218,17 +233,34 @@ namespace detail
public:
OpaqueRef() = default;
template<typename T> explicit OpaqueRef(T&& obj) :
m_ref(new OpaqueRefT<typename std::decay<T>::type>(std::forward<T>(obj))) {}
template<
typename T,
typename = util::are_different_t<OpaqueRef, T>
>
// FIXME: probably won't work with const object
explicit OpaqueRef(T&& obj) :
m_ref(new OpaqueRefT<util::decay_t<T>>(std::forward<T>(obj))),
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 OpaqueRefT<T>());
check<T>();
storeKind<T>();
static_cast<OpaqueRefT<T>&>(*m_ref).reset();
}
template <typename T>
void storeKind()
{
m_kind = cv::detail::GOpaqueTraits<T>::kind;
}
template<typename T> T& wref()
{
check<T>();
@@ -250,6 +282,9 @@ namespace detail
{
return m_ref->m_desc;
}
// May be used to uniquely identify this object internally
const void *ptr() const { return m_ref->ptr(); }
};
} // namespace detail
@@ -269,14 +304,16 @@ public:
private:
// Host type (or Flat type) - the type this GOpaque is actually
// specified to.
using HT = typename detail::flatten_g<typename std::decay<T>::type>::type;
using HT = typename detail::flatten_g<util::decay_t<T>>::type;
static void CTor(detail::OpaqueRef& ref) {
ref.reset<HT>();
ref.storeKind<HT>();
}
void putDetails() {
m_ref.setConstructFcn(&CTor);
m_ref.specifyType<HT>();
m_ref.specifyType<HT>(); // FIXME: to unify those 2 to avoid excessive dynamic_cast
m_ref.storeKind<HT>(); //
}
detail::GOpaqueU m_ref;

View File

@@ -36,6 +36,7 @@ namespace cv {
using GProtoArg = util::variant
< GMat
, GMatP
, GFrame
, GScalar
, detail::GArrayU // instead of GArray<T>
, detail::GOpaqueU // instead of GOpaque<T>
@@ -56,12 +57,35 @@ template<class Tag>
struct GIOProtoArgs
{
public:
// NB: Used by python wrapper
GIOProtoArgs() = default;
explicit GIOProtoArgs(const GProtoArgs& args) : m_args(args) {}
explicit GIOProtoArgs(GProtoArgs &&args) : m_args(std::move(args)) {}
GProtoArgs m_args;
// TODO: Think about the addition operator
/**
* @brief This operator allows to complement the proto vectors at runtime.
*
* It's an ordinary overload of addition assignment operator.
*
* Example of usage:
* @snippet dynamic_graph.cpp GIOProtoArgs usage
*
*/
template<typename Tg>
friend GIOProtoArgs<Tg>& operator += (GIOProtoArgs<Tg> &lhs, const GIOProtoArgs<Tg> &rhs);
};
template<typename Tg>
cv::GIOProtoArgs<Tg>& operator += (cv::GIOProtoArgs<Tg> &lhs, const cv::GIOProtoArgs<Tg> &rhs)
{
lhs.m_args.reserve(lhs.m_args.size() + rhs.m_args.size());
lhs.m_args.insert(lhs.m_args.end(), rhs.m_args.begin(), rhs.m_args.end());
return lhs;
}
struct In_Tag{};
struct Out_Tag{};

View File

@@ -26,10 +26,10 @@ struct GOrigin;
* @{
*/
class GAPI_EXPORTS GScalar
class GAPI_EXPORTS_W_SIMPLE GScalar
{
public:
GScalar(); // Empty constructor
GAPI_WRAP GScalar(); // Empty constructor
explicit GScalar(const cv::Scalar& s); // Constant value constructor from cv::Scalar
explicit GScalar(cv::Scalar&& s); // Constant value move-constructor from cv::Scalar

View File

@@ -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-2020 Intel Corporation
#ifndef OPENCV_GAPI_GTYPE_TRAITS_HPP
@@ -15,9 +15,9 @@
#include <opencv2/gapi/gscalar.hpp>
#include <opencv2/gapi/garray.hpp>
#include <opencv2/gapi/gopaque.hpp>
#include <opencv2/gapi/gframe.hpp>
#include <opencv2/gapi/streaming/source.hpp>
#include <opencv2/gapi/gcommon.hpp>
#include <opencv2/gapi/own/convert.hpp>
namespace cv
{
@@ -36,6 +36,7 @@ namespace detail
GOBJREF, // <internal> reference to object
GMAT, // a cv::GMat
GMATP, // a cv::GMatP
GFRAME, // a cv::GFrame
GSCALAR, // a cv::GScalar
GARRAY, // a cv::GArrayU (note - exactly GArrayU, not GArray<T>!)
GOPAQUE, // a cv::GOpaqueU (note - exactly GOpaqueU, not GOpaque<T>!)
@@ -49,26 +50,37 @@ namespace detail
template<typename T> struct GTypeTraits
{
static constexpr const ArgKind kind = ArgKind::OPAQUE_VAL;
static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
};
template<> struct GTypeTraits<cv::GMat>
{
static constexpr const ArgKind kind = ArgKind::GMAT;
static constexpr const GShape shape = GShape::GMAT;
static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
};
template<> struct GTypeTraits<cv::GMatP>
{
static constexpr const ArgKind kind = ArgKind::GMATP;
static constexpr const GShape shape = GShape::GMAT;
static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
};
template<> struct GTypeTraits<cv::GFrame>
{
static constexpr const ArgKind kind = ArgKind::GFRAME;
static constexpr const GShape shape = GShape::GMAT;
static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
};
template<> struct GTypeTraits<cv::GScalar>
{
static constexpr const ArgKind kind = ArgKind::GSCALAR;
static constexpr const GShape shape = GShape::GSCALAR;
static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
};
template<class T> struct GTypeTraits<cv::GArray<T> >
{
static constexpr const ArgKind kind = ArgKind::GARRAY;
static constexpr const GShape shape = GShape::GARRAY;
static constexpr const OpaqueKind op_kind = GOpaqueTraits<T>::kind;
using host_type = std::vector<T>;
using strip_type = cv::detail::VectorRef;
static cv::detail::GArrayU wrap_value(const cv::GArray<T> &t) { return t.strip();}
@@ -79,6 +91,7 @@ namespace detail
{
static constexpr const ArgKind kind = ArgKind::GOPAQUE;
static constexpr const GShape shape = GShape::GOPAQUE;
static constexpr const OpaqueKind op_kind = GOpaqueTraits<T>::kind;
using host_type = T;
using strip_type = cv::detail::OpaqueRef;
static cv::detail::GOpaqueU wrap_value(const cv::GOpaque<T> &t) { return t.strip();}
@@ -105,10 +118,9 @@ namespace detail
// and GMat behavior is correct for GMatP)
template<typename T> struct GTypeOf;
#if !defined(GAPI_STANDALONE)
template<> struct GTypeOf<cv::Mat> { using type = cv::GMat; };
template<> struct GTypeOf<cv::UMat> { using type = cv::GMat; };
#endif // !defined(GAPI_STANDALONE)
template<> struct GTypeOf<cv::gapi::own::Mat> { using type = cv::GMat; };
template<> struct GTypeOf<cv::Mat> { using type = cv::GMat; };
template<> struct GTypeOf<cv::Scalar> { using type = cv::GScalar; };
template<typename U> struct GTypeOf<std::vector<U> > { using type = cv::GArray<U>; };
template<typename U> struct GTypeOf { using type = cv::GOpaque<U>;};

View File

@@ -26,6 +26,7 @@ namespace detail
template<> struct ProtoToParam<cv::GMat> { using type = cv::Mat; };
template<> struct ProtoToParam<cv::GScalar> { using type = cv::Scalar; };
template<typename U> struct ProtoToParam<cv::GArray<U> > { using type = std::vector<U>; };
template<> struct ProtoToParam<cv::GArray<cv::GMat>> { using type = std::vector<cv::Mat>; };
template<typename U> struct ProtoToParam<cv::GOpaque<U> > { using type = U; };
template<typename T> using ProtoToParamT = typename ProtoToParam<T>::type;
@@ -132,12 +133,20 @@ public:
{
}
void apply(detail::ProtoToParamT<Args>... inArgs,
detail::ProtoToParamT<R> &outArg,
GCompileArgs &&args)
{
m_comp.apply(cv::gin(inArgs...), cv::gout(outArg), std::move(args));
}
void apply(detail::ProtoToParamT<Args>... inArgs,
detail::ProtoToParamT<R> &outArg)
{
m_comp.apply(cv::gin(inArgs...), cv::gout(outArg));
apply(inArgs..., outArg, GCompileArgs());
}
GCompiledT compile(detail::ProtoToMetaT<Args>... inDescs)
{
GMetaArgs inMetas = { GMetaArg(inDescs)... };
@@ -205,12 +214,20 @@ public:
{
}
void apply(detail::ProtoToParamT<Args>... inArgs,
detail::ProtoToParamT<R>&... outArgs,
GCompileArgs &&args)
{
m_comp.apply(cv::gin(inArgs...), cv::gout(outArgs...), std::move(args));
}
void apply(detail::ProtoToParamT<Args>... inArgs,
detail::ProtoToParamT<R>&... outArgs)
{
m_comp.apply(cv::gin(inArgs...), cv::gout(outArgs...));
apply(inArgs..., outArgs..., GCompileArgs());
}
GCompiledT compile(detail::ProtoToMetaT<Args>... inDescs)
{
GMetaArgs inMetas = { GMetaArg(inDescs)... };

View File

@@ -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-2020 Intel Corporation
#ifndef OPENCV_GAPI_IMGPROC_HPP
@@ -90,6 +90,20 @@ namespace imgproc {
}
};
G_TYPED_KERNEL(GLaplacian, <GMat(GMat,int, int, double, double, int)>,
"org.opencv.imgproc.filters.laplacian") {
static GMatDesc outMeta(GMatDesc in, int ddepth, int, double, double, int) {
return in.withDepth(ddepth);
}
};
G_TYPED_KERNEL(GBilateralFilter, <GMat(GMat,int, double, double, int)>,
"org.opencv.imgproc.filters.bilateralfilter") {
static GMatDesc outMeta(GMatDesc in, int, double, double, int) {
return in;
}
};
G_TYPED_KERNEL(GEqHist, <GMat(GMat)>, "org.opencv.imgproc.equalizeHist"){
static GMatDesc outMeta(GMatDesc in) {
return in.withType(CV_8U, 1);
@@ -102,6 +116,14 @@ namespace imgproc {
}
};
G_TYPED_KERNEL(GGoodFeatures,
<cv::GArray<cv::Point2f>(GMat,int,double,double,Mat,int,bool,double)>,
"org.opencv.imgproc.goodFeaturesToTrack") {
static GArrayDesc outMeta(GMatDesc, int, double, double, const Mat&, int, bool, double) {
return empty_array_desc();
}
};
G_TYPED_KERNEL(GRGB2YUV, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.rgb2yuv") {
static GMatDesc outMeta(GMatDesc in) {
return in; // type still remains CV_8UC3;
@@ -251,8 +273,7 @@ namespace imgproc {
}
};
}
} //namespace imgproc
//! @addtogroup gapi_filters
//! @{
@@ -298,7 +319,7 @@ according to the specified border mode.
The function does actually compute correlation, not the convolution:
\f[\texttt{dst} (x,y) = \sum _{ \stackrel{0\leq x' < \texttt{kernel.cols},}{0\leq y' < \texttt{kernel.rows}} } \texttt{kernel} (x',y')* \texttt{src} (x+x'- \texttt{anchor.x} ,y+y'- \texttt{anchor.y} )\f]
\f[\texttt{dst} (x,y) = \sum _{ \substack{0\leq x' < \texttt{kernel.cols}\\{0\leq y' < \texttt{kernel.rows}}}} \texttt{kernel} (x',y')* \texttt{src} (x+x'- \texttt{anchor.x} ,y+y'- \texttt{anchor.y} )\f]
That is, the kernel is not mirrored around the anchor point. If you need a real convolution, flip
the kernel using flip and set the new anchor to `(kernel.cols - anchor.x - 1, kernel.rows -
@@ -335,7 +356,7 @@ The function smooths an image using the kernel:
where
\f[\alpha = \fork{\frac{1}{\texttt{ksize.width*ksize.height}}}{when \texttt{normalize=true}}{1}{otherwise}\f]
\f[\alpha = \begin{cases} \frac{1}{\texttt{ksize.width*ksize.height}} & \texttt{when } \texttt{normalize=true} \\1 & \texttt{otherwise} \end{cases}\f]
Unnormalized box filter is useful for computing various integral characteristics over each pixel
neighborhood, such as covariance matrices of image derivatives (used in dense optical flow
@@ -367,8 +388,8 @@ The function smooths an image using the kernel:
\f[\texttt{K} = \frac{1}{\texttt{ksize.width*ksize.height}} \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 & 1 \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \hdotsfor{6} \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \end{bmatrix}\f]
The call `blur(src, dst, ksize, anchor, borderType)` is equivalent to `boxFilter(src, dst, src.type(),
anchor, true, borderType)`.
The call `blur(src, ksize, anchor, borderType)` is equivalent to `boxFilter(src, src.type(), ksize, anchor,
true, borderType)`.
Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
Output image must have the same type, size, and number of channels as the input image.
@@ -636,6 +657,68 @@ GAPI_EXPORTS std::tuple<GMat, GMat> SobelXY(const GMat& src, int ddepth, int ord
int borderType = BORDER_DEFAULT,
const Scalar& borderValue = Scalar(0));
/** @brief Calculates the Laplacian of an image.
The function calculates the Laplacian of the source image by adding up the second x and y
derivatives calculated using the Sobel operator:
\f[\texttt{dst} = \Delta \texttt{src} = \frac{\partial^2 \texttt{src}}{\partial x^2} + \frac{\partial^2 \texttt{src}}{\partial y^2}\f]
This is done when `ksize > 1`. When `ksize == 1`, the Laplacian is computed by filtering the image
with the following \f$3 \times 3\f$ aperture:
\f[\vecthreethree {0}{1}{0}{1}{-4}{1}{0}{1}{0}\f]
@note Function textual ID is "org.opencv.imgproc.filters.laplacian"
@param src Source image.
@param ddepth Desired depth of the destination image.
@param ksize Aperture size used to compute the second-derivative filters. See #getDerivKernels for
details. The size must be positive and odd.
@param scale Optional scale factor for the computed Laplacian values. By default, no scaling is
applied. See #getDerivKernels for details.
@param delta Optional delta value that is added to the results prior to storing them in dst .
@param borderType Pixel extrapolation method, see #BorderTypes. #BORDER_WRAP is not supported.
@return Destination image of the same size and the same number of channels as src.
@sa Sobel, Scharr
*/
GAPI_EXPORTS GMat Laplacian(const GMat& src, int ddepth, int ksize = 1,
double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT);
/** @brief Applies the bilateral filter to an image.
The function applies bilateral filtering to the input image, as described in
http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html
bilateralFilter can reduce unwanted noise very well while keeping edges fairly sharp. However, it is
very slow compared to most filters.
_Sigma values_: For simplicity, you can set the 2 sigma values to be the same. If they are small (\<
10), the filter will not have much effect, whereas if they are large (\> 150), they will have a very
strong effect, making the image look "cartoonish".
_Filter size_: Large filters (d \> 5) are very slow, so it is recommended to use d=5 for real-time
applications, and perhaps d=9 for offline applications that need heavy noise filtering.
This filter does not work inplace.
@note Function textual ID is "org.opencv.imgproc.filters.bilateralfilter"
@param src Source 8-bit or floating-point, 1-channel or 3-channel image.
@param d Diameter of each pixel neighborhood that is used during filtering. If it is non-positive,
it is computed from sigmaSpace.
@param sigmaColor Filter sigma in the color space. A larger value of the parameter means that
farther colors within the pixel neighborhood (see sigmaSpace) will be mixed together, resulting
in larger areas of semi-equal color.
@param sigmaSpace Filter sigma in the coordinate space. A larger value of the parameter means that
farther pixels will influence each other as long as their colors are close enough (see sigmaColor
). When d\>0, it specifies the neighborhood size regardless of sigmaSpace. Otherwise, d is
proportional to sigmaSpace.
@param borderType border mode used to extrapolate pixels outside of the image, see #BorderTypes
@return Destination image of the same size and type as src.
*/
GAPI_EXPORTS GMat bilateralFilter(const GMat& src, int d, double sigmaColor, double sigmaSpace,
int borderType = BORDER_DEFAULT);
/** @brief Finds edges in an image using the Canny algorithm.
The function finds edges in the input image and marks them in the output map edges using the
@@ -657,6 +740,59 @@ L2gradient=false ).
GAPI_EXPORTS GMat Canny(const GMat& image, double threshold1, double threshold2,
int apertureSize = 3, bool L2gradient = false);
/** @brief Determines strong corners on an image.
The function finds the most prominent corners in the image or in the specified image region, as
described in @cite Shi94
- Function calculates the corner quality measure at every source image pixel using the
#cornerMinEigenVal or #cornerHarris .
- Function performs a non-maximum suppression (the local maximums in *3 x 3* neighborhood are
retained).
- The corners with the minimal eigenvalue less than
\f$\texttt{qualityLevel} \cdot \max_{x,y} qualityMeasureMap(x,y)\f$ are rejected.
- The remaining corners are sorted by the quality measure in the descending order.
- Function throws away each corner for which there is a stronger corner at a distance less than
maxDistance.
The function can be used to initialize a point-based tracker of an object.
@note If the function is called with different values A and B of the parameter qualityLevel , and
A \> B, the vector of returned corners with qualityLevel=A will be the prefix of the output vector
with qualityLevel=B .
@note Function textual ID is "org.opencv.imgproc.goodFeaturesToTrack"
@param image Input 8-bit or floating-point 32-bit, single-channel image.
@param maxCorners Maximum number of corners to return. If there are more corners than are found,
the strongest of them is returned. `maxCorners <= 0` implies that no limit on the maximum is set
and all detected corners are returned.
@param qualityLevel Parameter characterizing the minimal accepted quality of image corners. The
parameter value is multiplied by the best corner quality measure, which is the minimal eigenvalue
(see #cornerMinEigenVal ) or the Harris function response (see #cornerHarris ). The corners with the
quality measure less than the product are rejected. For example, if the best corner has the
quality measure = 1500, and the qualityLevel=0.01 , then all the corners with the quality measure
less than 15 are rejected.
@param minDistance Minimum possible Euclidean distance between the returned corners.
@param mask Optional region of interest. If the image is not empty (it needs to have the type
CV_8UC1 and the same size as image ), it specifies the region in which the corners are detected.
@param blockSize Size of an average block for computing a derivative covariation matrix over each
pixel neighborhood. See cornerEigenValsAndVecs .
@param useHarrisDetector Parameter indicating whether to use a Harris detector (see #cornerHarris)
or #cornerMinEigenVal.
@param k Free parameter of the Harris detector.
@return vector of detected corners.
*/
GAPI_EXPORTS GArray<Point2f> goodFeaturesToTrack(const GMat &image,
int maxCorners,
double qualityLevel,
double minDistance,
const Mat &mask = Mat(),
int blockSize = 3,
bool useHarrisDetector = false,
double k = 0.04);
/** @brief Equalizes the histogram of a grayscale image.
The function equalizes the histogram of the input image using the following algorithm:

View File

@@ -14,6 +14,7 @@
#include <functional>
#include <string> // string
#include <utility> // tuple
#include <type_traits> // is_same, false_type
#include <opencv2/gapi/util/any.hpp> // any<>
#include <opencv2/gapi/gkernel.hpp> // GKernelType[M], GBackend
@@ -25,6 +26,43 @@ namespace cv {
template<typename, typename> class GNetworkType;
namespace detail {
template<typename, typename>
struct valid_infer2_types;
// Terminal case 1 (50/50 success)
template<typename T>
struct valid_infer2_types< std::tuple<cv::GMat>, std::tuple<T> > {
// By default, Nets are limited to GMat argument types only
// for infer2, every GMat argument may translate to either
// GArray<GMat> or GArray<Rect>. GArray<> part is stripped
// already at this point.
static constexpr const auto value =
std::is_same<typename std::decay<T>::type, cv::GMat>::value
|| std::is_same<typename std::decay<T>::type, cv::Rect>::value;
};
// Terminal case 2 (100% failure)
template<typename... Ts>
struct valid_infer2_types< std::tuple<>, std::tuple<Ts...> >
: public std::false_type {
};
// Terminal case 3 (100% failure)
template<typename... Ns>
struct valid_infer2_types< std::tuple<Ns...>, std::tuple<> >
: public std::false_type {
};
// Recursion -- generic
template<typename... Ns, typename T, typename...Ts>
struct valid_infer2_types< std::tuple<cv::GMat,Ns...>, std::tuple<T,Ts...> > {
static constexpr const auto value =
valid_infer2_types< std::tuple<cv::GMat>, std::tuple<T> >::value
&& valid_infer2_types< std::tuple<Ns...>, std::tuple<Ts...> >::value;
};
} // namespace detail
// TODO: maybe tuple_wrap_helper from util.hpp may help with this.
// Multiple-return-value network definition (specialized base class)
template<typename K, typename... R, typename... Args>
@@ -56,6 +94,17 @@ public:
using APIList = std::function<ResultL(cv::GArray<cv::Rect>, Args...)>;
};
// APIList2 is also template to allow different calling options
// (GArray<cv::Rect> vs GArray<cv::GMat> per input)
template<class Net, class... Ts>
struct InferAPIList2 {
using type = typename std::enable_if
< cv::detail::valid_infer2_types< typename Net::InArgs
, std::tuple<Ts...> >::value,
std::function<typename Net::ResultL(cv::GMat, cv::GArray<Ts>...)>
>::type;
};
// Base "Infer" kernel. Note - for whatever network, kernel ID
// is always the same. Different inference calls are distinguished by
// network _tag_ (an extra field in GCall)
@@ -77,10 +126,21 @@ struct GInferBase {
// All notes from "Infer" kernel apply here as well.
struct GInferListBase {
static constexpr const char * id() {
return "org.opencv.dnn.infer-roi"; // Universal stub
return "org.opencv.dnn.infer-roi"; // Universal stub
}
static GMetaArgs getOutMeta(const GMetaArgs &, const GArgs &) {
return GMetaArgs{}; // One more universal stub
return GMetaArgs{}; // One more universal stub
}
};
// Base "Infer list 2" kernel.
// All notes from "Infer" kernel apply here as well.
struct GInferList2Base {
static constexpr const char * id() {
return "org.opencv.dnn.infer-roi-list"; // Universal stub
}
static GMetaArgs getOutMeta(const GMetaArgs &, const GArgs &) {
return GMetaArgs{}; // One more universal stub
}
};
@@ -109,6 +169,21 @@ struct GInferList final
static constexpr const char* tag() { return Net::tag(); }
};
// An even more generic roi-list inference kernel. API (::on()) is
// derived from the Net template parameter (see more in infer<>
// overload).
// Takes an extra variadic template list to reflect how this network
// was called (with Rects or GMats as array parameters)
template<typename Net, typename... Args>
struct GInferList2 final
: public GInferList2Base
, public detail::KernelTypeMedium< GInferList2<Net, Args...>
, typename InferAPIList2<Net, Args...>::type > {
using GInferList2Base::getOutMeta; // FIXME: name lookup conflict workaround?
static constexpr const char* tag() { return Net::tag(); }
};
} // namespace cv
// FIXME: Probably the <API> signature makes a function/tuple/function round-trip
@@ -139,6 +214,30 @@ typename Net::ResultL infer(cv::GArray<cv::Rect> roi, Args&&... args) {
return GInferList<Net>::on(roi, std::forward<Args>(args)...);
}
/** @brief Calculates responses for the specified network (template
* parameter) for every region in the source image, extended version.
*
* @tparam A network type defined with G_API_NET() macro.
* @param image A source image containing regions of interest
* @param args GArray<> objects of cv::Rect or cv::GMat, one per every
* network input:
* - If a cv::GArray<cv::Rect> is passed, the appropriate
* regions are taken from `image` and preprocessed to this particular
* network input;
* - If a cv::GArray<cv::GMat> is passed, the underlying data traited
* as tensor (no automatic preprocessing happen).
* @return a list of objects of return type as defined in G_API_NET().
* If a network has multiple return values (defined with a tuple), a tuple of
* GArray<> objects is returned with the appropriate types inside.
* @sa G_API_NET()
*/
template<typename Net, typename... Args>
typename Net::ResultL infer2(cv::GMat image, cv::GArray<Args>... args) {
// FIXME: Declared as "2" because in the current form it steals
// overloads from the regular infer
return GInferList2<Net, Args...>::on(image, args...);
}
/**
* @brief Calculates response for the specified network (template
* parameter) given the input data.

View File

@@ -78,8 +78,8 @@ public:
const std::string &weights,
const std::string &device)
: desc{ model, weights, device, {}, {}, {}
, std::tuple_size<typename Net::InArgs>::value
, std::tuple_size<typename Net::OutArgs>::value
, std::tuple_size<typename Net::InArgs>::value // num_in
, std::tuple_size<typename Net::OutArgs>::value // num_out
} {
};

View File

@@ -0,0 +1,125 @@
// 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) 2020 Intel Corporation
#ifndef OPENCV_GAPI_PARSERS_HPP
#define OPENCV_GAPI_PARSERS_HPP
#include <utility> // std::tuple
#include <opencv2/gapi/gmat.hpp>
#include <opencv2/gapi/gkernel.hpp>
namespace cv { namespace gapi {
namespace nn {
namespace parsers {
using GRects = GArray<Rect>;
using GDetections = std::tuple<GArray<Rect>, GArray<int>>;
G_TYPED_KERNEL(GParseSSDBL, <GDetections(GMat, GOpaque<Size>, float, int)>,
"org.opencv.nn.parsers.parseSSD_BL") {
static std::tuple<GArrayDesc,GArrayDesc> outMeta(const GMatDesc&, const GOpaqueDesc&, float, int) {
return std::make_tuple(empty_array_desc(), empty_array_desc());
}
};
G_TYPED_KERNEL(GParseSSD, <GRects(GMat, GOpaque<Size>, float, bool, bool)>,
"org.opencv.nn.parsers.parseSSD") {
static GArrayDesc outMeta(const GMatDesc&, const GOpaqueDesc&, float, bool, bool) {
return empty_array_desc();
}
};
G_TYPED_KERNEL(GParseYolo, <GDetections(GMat, GOpaque<Size>, float, float, std::vector<float>)>,
"org.opencv.nn.parsers.parseYolo") {
static std::tuple<GArrayDesc, GArrayDesc> outMeta(const GMatDesc&, const GOpaqueDesc&,
float, float, const std::vector<float>&) {
return std::make_tuple(empty_array_desc(), empty_array_desc());
}
static const std::vector<float>& defaultAnchors() {
static std::vector<float> anchors {
0.57273f, 0.677385f, 1.87446f, 2.06253f, 3.33843f, 5.47434f, 7.88282f, 3.52778f, 9.77052f, 9.16828f
};
return anchors;
}
};
} // namespace parsers
} // namespace nn
/** @brief Parses output of SSD network.
Extracts detection information (box, confidence, label) from SSD output and
filters it by given confidence and label.
@note Function textual ID is "org.opencv.nn.parsers.parseSSD_BL"
@param in Input CV_32F tensor with {1,1,N,7} dimensions.
@param inSz Size to project detected boxes to (size of the input image).
@param confidenceThreshold If confidence of the
detection is smaller than confidence threshold, detection is rejected.
@param filterLabel If provided (!= -1), only detections with
given label will get to the output.
@return a tuple with a vector of detected boxes and a vector of appropriate labels.
*/
GAPI_EXPORTS std::tuple<GArray<Rect>, GArray<int>> parseSSD(const GMat& in,
const GOpaque<Size>& inSz,
const float confidenceThreshold = 0.5f,
const int filterLabel = -1);
/** @overload
Extracts detection information (box, confidence) from SSD output and
filters it by given confidence and by going out of bounds.
@note Function textual ID is "org.opencv.nn.parsers.parseSSD"
@param in Input CV_32F tensor with {1,1,N,7} dimensions.
@param inSz Size to project detected boxes to (size of the input image).
@param confidenceThreshold If confidence of the
detection is smaller than confidence threshold, detection is rejected.
@param alignmentToSquare If provided true, bounding boxes are extended to squares.
The center of the rectangle remains unchanged, the side of the square is
the larger side of the rectangle.
@param filterOutOfBounds If provided true, out-of-frame boxes are filtered.
@return a vector of detected bounding boxes.
*/
GAPI_EXPORTS GArray<Rect> parseSSD(const GMat& in,
const GOpaque<Size>& inSz,
const float confidenceThreshold = 0.5f,
const bool alignmentToSquare = false,
const bool filterOutOfBounds = false);
/** @brief Parses output of Yolo network.
Extracts detection information (box, confidence, label) from Yolo output,
filters it by given confidence and performs non-maximum supression for overlapping boxes.
@note Function textual ID is "org.opencv.nn.parsers.parseYolo"
@param in Input CV_32F tensor with {1,13,13,N} dimensions, N should satisfy:
\f[\texttt{N} = (\texttt{num_classes} + \texttt{5}) * \texttt{5},\f]
where num_classes - a number of classes Yolo network was trained with.
@param inSz Size to project detected boxes to (size of the input image).
@param confidenceThreshold If confidence of the
detection is smaller than confidence threshold, detection is rejected.
@param nmsThreshold Non-maximum supression threshold which controls minimum
relative box intersection area required for rejecting the box with a smaller confidence.
If 1.f, nms is not performed and no boxes are rejected.
@param anchors Anchors Yolo network was trained with.
@note The default anchor values are taken from openvinotoolkit docs:
https://docs.openvinotoolkit.org/latest/omz_models_intel_yolo_v2_tiny_vehicle_detection_0001_description_yolo_v2_tiny_vehicle_detection_0001.html#output.
@return a tuple with a vector of detected boxes and a vector of appropriate labels.
*/
GAPI_EXPORTS std::tuple<GArray<Rect>, GArray<int>> parseYolo(const GMat& in,
const GOpaque<Size>& inSz,
const float confidenceThreshold = 0.5f,
const float nmsThreshold = 0.5f,
const std::vector<float>& anchors
= nn::parsers::GParseYolo::defaultAnchors());
} // namespace gapi
} // namespace cv
#endif // OPENCV_GAPI_PARSERS_HPP

View File

@@ -16,7 +16,7 @@ namespace gapi {
namespace core {
namespace ocl {
GAPI_EXPORTS GKernelPackage kernels();
GAPI_EXPORTS_W cv::gapi::GKernelPackage kernels();
} // namespace ocl
} // namespace core

View File

@@ -16,6 +16,17 @@
# include <opencv2/core/base.hpp>
#else // Without OpenCV
# include <opencv2/gapi/own/cvdefs.hpp>
# include <opencv2/gapi/own/types.hpp> // cv::gapi::own::Rect/Size/Point
# include <opencv2/gapi/own/scalar.hpp> // cv::gapi::own::Scalar
# include <opencv2/gapi/own/mat.hpp>
// replacement of cv's structures:
namespace cv {
using Rect = gapi::own::Rect;
using Size = gapi::own::Size;
using Point = gapi::own::Point;
using Scalar = gapi::own::Scalar;
using Mat = gapi::own::Mat;
} // namespace cv
#endif // !defined(GAPI_STANDALONE)
#endif // OPENCV_GAPI_OPENCV_INCLUDES_HPP

View File

@@ -11,6 +11,8 @@
#include <opencv2/gapi/gmat.hpp>
#include <opencv2/gapi/gscalar.hpp>
namespace cv
{
GAPI_EXPORTS cv::GMat operator+(const cv::GMat& lhs, const cv::GMat& rhs);
GAPI_EXPORTS cv::GMat operator+(const cv::GMat& lhs, const cv::GScalar& rhs);
@@ -63,7 +65,6 @@ GAPI_EXPORTS cv::GMat operator<(const cv::GScalar& lhs, const cv::GMat& rhs);
GAPI_EXPORTS cv::GMat operator<=(const cv::GScalar& lhs, const cv::GMat& rhs);
GAPI_EXPORTS cv::GMat operator==(const cv::GScalar& lhs, const cv::GMat& rhs);
GAPI_EXPORTS cv::GMat operator!=(const cv::GScalar& lhs, const cv::GMat& rhs);
} // cv
#endif // OPENCV_GAPI_OPERATORS_HPP

View File

@@ -20,7 +20,7 @@
namespace detail
{
inline void assert_abort(const char* str, int line, const char* file, const char* func)
[[noreturn]] inline void assert_abort(const char* str, int line, const char* file, const char* func)
{
std::stringstream ss;
ss << file << ":" << line << ": Assertion " << str << " in function " << func << " failed\n";

View File

@@ -25,23 +25,27 @@ namespace cv
return result;
}
cv::gapi::own::Mat to_own(Mat&&) = delete;
cv::gapi::own::Mat to_own(Mat&&) = delete;
inline cv::gapi::own::Mat to_own(Mat const& m) {
return (m.dims == 2)
? cv::gapi::own::Mat{m.rows, m.cols, m.type(), m.data, m.step}
: cv::gapi::own::Mat{to_own<int>(m.size), m.type(), m.data};
};
namespace gapi
{
namespace own
{
inline cv::Mat to_ocv(Mat const& m) {
return m.dims.empty()
? cv::Mat{m.rows, m.cols, m.type(), m.data, m.step}
: cv::Mat{m.dims, m.type(), m.data};
}
cv::Mat to_ocv(Mat&&) = delete;
cv::Mat to_ocv(Mat&&) = delete;
} // namespace own
} // namespace gapi
} // namespace cv

View File

@@ -9,9 +9,6 @@
#define OPENCV_GAPI_CV_DEFS_HPP
#if defined(GAPI_STANDALONE)
#include <opencv2/gapi/own/types.hpp> // cv::gapi::own::Rect/Size/Point
#include <opencv2/gapi/own/scalar.hpp> // cv::gapi::own::Scalar
// Simulate OpenCV definitions taken from various
// OpenCV interface headers if G-API is built in a
// standalone mode.
@@ -139,11 +136,6 @@ enum InterpolationFlags{
INTER_LINEAR_EXACT = 5,
INTER_MAX = 7,
};
// replacement of cv's structures:
using Rect = gapi::own::Rect;
using Size = gapi::own::Size;
using Point = gapi::own::Point;
using Scalar = gapi::own::Scalar;
} // namespace cv
static inline int cvFloor( double value )

View File

@@ -11,8 +11,15 @@
# if defined(__OPENCV_BUILD)
# include <opencv2/core/base.hpp>
# define GAPI_EXPORTS CV_EXPORTS
/* special informative macros for wrapper generators */
# define GAPI_WRAP CV_WRAP
# define GAPI_EXPORTS_W_SIMPLE CV_EXPORTS_W_SIMPLE
# define GAPI_EXPORTS_W CV_EXPORTS_W
# else
# define GAPI_WRAP
# define GAPI_EXPORTS
# define GAPI_EXPORTS_W_SIMPLE
# define GAPI_EXPORTS_W
#if 0 // Note: the following version currently is not needed for non-OpenCV build
# if defined _WIN32

View File

@@ -17,6 +17,7 @@
#include <memory> //std::shared_ptr
#include <cstring> //std::memcpy
#include <numeric> //std::accumulate
#include <vector>
#include <opencv2/gapi/util/throw.hpp>
namespace cv { namespace gapi { namespace own {
@@ -123,11 +124,11 @@ namespace cv { namespace gapi { namespace own {
data = ptr(roi.y, roi.x);
}
Mat(Mat const& src) = default;
Mat(Mat&& src) = default;
Mat(Mat const& ) = default;
Mat(Mat&& ) = default;
Mat& operator=(Mat const& src) = default;
Mat& operator=(Mat&& src) = default;
Mat& operator=(Mat const& ) = default;
Mat& operator=(Mat&& ) = default;
/** @brief Sets all or some of the array elements to the specified value.
@param s Assigned scalar converted to the actual array type.

View File

@@ -13,7 +13,7 @@
namespace cv { namespace gapi { namespace core { namespace plaidml {
GAPI_EXPORTS GKernelPackage kernels();
GAPI_EXPORTS cv::gapi::GKernelPackage kernels();
}}}}

View File

@@ -2,23 +2,16 @@
// 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-2019 Intel Corporation
// Copyright (C) 2018-2020 Intel Corporation
#ifndef OPENCV_GAPI_RENDER_HPP
#define OPENCV_GAPI_RENDER_HPP
#include <string>
#include <vector>
#include <opencv2/gapi/render/render_types.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/gapi.hpp>
#include <opencv2/gapi/opencv_includes.hpp>
#include <opencv2/gapi/util/variant.hpp>
#include <opencv2/gapi/own/exports.hpp>
/** \defgroup gapi_draw G-API Drawing and composition functionality
* @{
*
@@ -77,309 +70,9 @@ namespace wip
namespace draw
{
/**
* @brief This structure specifies which FreeType font to use by FText primitives.
*/
struct freetype_font
{
/*@{*/
std::string path; //!< The path to the font file (.ttf)
/*@{*/
};
//! @addtogroup gapi_draw_prims
//! @{
/**
* @brief This structure represents a text string to draw.
*
* Parameters match cv::putText().
*/
struct Text
{
/**
* @brief Text constructor
*
* @param text_ The text string to be drawn
* @param org_ The bottom-left corner of the text string in the image
* @param ff_ The font type, see #HersheyFonts
* @param fs_ The font scale factor that is multiplied by the font-specific base size
* @param color_ The text color
* @param thick_ The thickness of the lines used to draw a text
* @param lt_ The line type. See #LineTypes
* @param bottom_left_origin_ When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
*/
Text(const std::string& text_,
const cv::Point& org_,
int ff_,
double fs_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = cv::LINE_8,
bool bottom_left_origin_ = false) :
text(text_), org(org_), ff(ff_), fs(fs_),
color(color_), thick(thick_), lt(lt_), bottom_left_origin(bottom_left_origin_)
{
}
/*@{*/
std::string text; //!< The text string to be drawn
cv::Point org; //!< The bottom-left corner of the text string in the image
int ff; //!< The font type, see #HersheyFonts
double fs; //!< The font scale factor that is multiplied by the font-specific base size
cv::Scalar color; //!< The text color
int thick; //!< The thickness of the lines used to draw a text
int lt; //!< The line type. See #LineTypes
bool bottom_left_origin; //!< When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
/*@{*/
};
/**
* @brief This structure represents a text string to draw using
* FreeType renderer.
*
* If OpenCV is built without FreeType support, this primitive will
* fail at the execution stage.
*/
struct FText
{
/**
* @brief FText constructor
*
* @param text_ The text string to be drawn
* @param org_ The bottom-left corner of the text string in the image
* @param fh_ The height of text
* @param color_ The text color
*/
FText(const std::wstring& text_,
const cv::Point& org_,
int fh_,
const cv::Scalar& color_) :
text(text_), org(org_), fh(fh_), color(color_)
{
}
/*@{*/
std::wstring text; //!< The text string to be drawn
cv::Point org; //!< The bottom-left corner of the text string in the image
int fh; //!< The height of text
cv::Scalar color; //!< The text color
/*@{*/
};
/**
* @brief This structure represents a rectangle to draw.
*
* Parameters match cv::rectangle().
*/
struct Rect
{
/**
* @brief Rect constructor
*
* @param rect_ Coordinates of the rectangle
* @param color_ The bottom-left corner of the text string in the image
* @param thick_ The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle
* @param lt_ The type of the line. See #LineTypes
* @param shift_ The number of fractional bits in the point coordinates
*/
Rect(const cv::Rect& rect_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = cv::LINE_8,
int shift_ = 0) :
rect(rect_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
/*@{*/
cv::Rect rect; //!< Coordinates of the rectangle
cv::Scalar color; //!< The rectangle color or brightness (grayscale image)
int thick; //!< The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle
int lt; //!< The type of the line. See #LineTypes
int shift; //!< The number of fractional bits in the point coordinates
/*@{*/
};
/**
* @brief This structure represents a circle to draw.
*
* Parameters match cv::circle().
*/
struct Circle
{
/**
* @brief Circle constructor
*
* @param center_ The center of the circle
* @param radius_ The radius of the circle
* @param color_ The color of the circle
* @param thick_ The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
* @param lt_ The Type of the circle boundary. See #LineTypes
* @param shift_ The Number of fractional bits in the coordinates of the center and in the radius value
*/
Circle(const cv::Point& center_,
int radius_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = cv::LINE_8,
int shift_ = 0) :
center(center_), radius(radius_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
/*@{*/
cv::Point center; //!< The center of the circle
int radius; //!< The radius of the circle
cv::Scalar color; //!< The color of the circle
int thick; //!< The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
int lt; //!< The Type of the circle boundary. See #LineTypes
int shift; //!< The Number of fractional bits in the coordinates of the center and in the radius value
/*@{*/
};
/**
* @brief This structure represents a line to draw.
*
* Parameters match cv::line().
*/
struct Line
{
/**
* @brief Line constructor
*
* @param pt1_ The first point of the line segment
* @param pt2_ The second point of the line segment
* @param color_ The line color
* @param thick_ The thickness of line
* @param lt_ The Type of the line. See #LineTypes
* @param shift_ The number of fractional bits in the point coordinates
*/
Line(const cv::Point& pt1_,
const cv::Point& pt2_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = cv::LINE_8,
int shift_ = 0) :
pt1(pt1_), pt2(pt2_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
/*@{*/
cv::Point pt1; //!< The first point of the line segment
cv::Point pt2; //!< The second point of the line segment
cv::Scalar color; //!< The line color
int thick; //!< The thickness of line
int lt; //!< The Type of the line. See #LineTypes
int shift; //!< The number of fractional bits in the point coordinates
/*@{*/
};
/**
* @brief This structure represents a mosaicing operation.
*
* Mosaicing is a very basic method to obfuscate regions in the image.
*/
struct Mosaic
{
/**
* @brief Mosaic constructor
*
* @param mos_ Coordinates of the mosaic
* @param cellSz_ Cell size (same for X, Y)
* @param decim_ Decimation (0 stands for no decimation)
*/
Mosaic(const cv::Rect& mos_,
int cellSz_,
int decim_) :
mos(mos_), cellSz(cellSz_), decim(decim_)
{
}
/*@{*/
cv::Rect mos; //!< Coordinates of the mosaic
int cellSz; //!< Cell size (same for X, Y)
int decim; //!< Decimation (0 stands for no decimation)
/*@{*/
};
/**
* @brief This structure represents an image to draw.
*
* Image is blended on a frame using the specified mask.
*/
struct Image
{
/**
* @brief Mosaic constructor
*
* @param org_ The bottom-left corner of the image
* @param img_ Image to draw
* @param alpha_ Alpha channel for image to draw (same size and number of channels)
*/
Image(const cv::Point& org_,
const cv::Mat& img_,
const cv::Mat& alpha_) :
org(org_), img(img_), alpha(alpha_)
{
}
/*@{*/
cv::Point org; //!< The bottom-left corner of the image
cv::Mat img; //!< Image to draw
cv::Mat alpha; //!< Alpha channel for image to draw (same size and number of channels)
/*@{*/
};
/**
* @brief This structure represents a polygon to draw.
*/
struct Poly
{
/**
* @brief Mosaic constructor
*
* @param points_ Points to connect
* @param color_ The line color
* @param thick_ The thickness of line
* @param lt_ The Type of the line. See #LineTypes
* @param shift_ The number of fractional bits in the point coordinate
*/
Poly(const std::vector<cv::Point>& points_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = cv::LINE_8,
int shift_ = 0) :
points(points_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
/*@{*/
std::vector<cv::Point> points; //!< Points to connect
cv::Scalar color; //!< The line color
int thick; //!< The thickness of line
int lt; //!< The Type of the line. See #LineTypes
int shift; //!< The number of fractional bits in the point coordinate
/*@{*/
};
using Prim = util::variant
< Text
, FText
, Rect
, Circle
, Line
, Mosaic
, Image
, Poly
>;
using Prims = std::vector<Prim>;
//! @} gapi_draw_prims
using GMat2 = std::tuple<cv::GMat,cv::GMat>;
using GMatDesc2 = std::tuple<cv::GMatDesc,cv::GMatDesc>;
//! @addtogroup gapi_draw_api
//! @{
/** @brief The function renders on the input image passed drawing primitivies

View File

@@ -0,0 +1,347 @@
// 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) 2020 Intel Corporation
#ifndef OPENCV_GAPI_RENDER_TYPES_HPP
#define OPENCV_GAPI_RENDER_TYPES_HPP
#include <string>
#include <vector>
#include <opencv2/gapi/opencv_includes.hpp>
#include <opencv2/gapi/util/variant.hpp>
#include <opencv2/gapi/own/exports.hpp>
namespace cv
{
namespace gapi
{
namespace wip
{
namespace draw
{
/**
* @brief This structure specifies which FreeType font to use by FText primitives.
*/
struct freetype_font
{
/*@{*/
std::string path; //!< The path to the font file (.ttf)
/*@{*/
};
//! @addtogroup gapi_draw_prims
//! @{
/**
* @brief This structure represents a text string to draw.
*
* Parameters match cv::putText().
*/
struct Text
{
/**
* @brief Text constructor
*
* @param text_ The text string to be drawn
* @param org_ The bottom-left corner of the text string in the image
* @param ff_ The font type, see #HersheyFonts
* @param fs_ The font scale factor that is multiplied by the font-specific base size
* @param color_ The text color
* @param thick_ The thickness of the lines used to draw a text
* @param lt_ The line type. See #LineTypes
* @param bottom_left_origin_ When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
*/
Text(const std::string& text_,
const cv::Point& org_,
int ff_,
double fs_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = 8,
bool bottom_left_origin_ = false) :
text(text_), org(org_), ff(ff_), fs(fs_),
color(color_), thick(thick_), lt(lt_), bottom_left_origin(bottom_left_origin_)
{
}
Text() = default;
/*@{*/
std::string text; //!< The text string to be drawn
cv::Point org; //!< The bottom-left corner of the text string in the image
int ff; //!< The font type, see #HersheyFonts
double fs; //!< The font scale factor that is multiplied by the font-specific base size
cv::Scalar color; //!< The text color
int thick; //!< The thickness of the lines used to draw a text
int lt; //!< The line type. See #LineTypes
bool bottom_left_origin; //!< When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
/*@{*/
};
/**
* @brief This structure represents a text string to draw using
* FreeType renderer.
*
* If OpenCV is built without FreeType support, this primitive will
* fail at the execution stage.
*/
struct FText
{
/**
* @brief FText constructor
*
* @param text_ The text string to be drawn
* @param org_ The bottom-left corner of the text string in the image
* @param fh_ The height of text
* @param color_ The text color
*/
FText(const std::wstring& text_,
const cv::Point& org_,
int fh_,
const cv::Scalar& color_) :
text(text_), org(org_), fh(fh_), color(color_)
{
}
FText() = default;
/*@{*/
std::wstring text; //!< The text string to be drawn
cv::Point org; //!< The bottom-left corner of the text string in the image
int fh; //!< The height of text
cv::Scalar color; //!< The text color
/*@{*/
};
/**
* @brief This structure represents a rectangle to draw.
*
* Parameters match cv::rectangle().
*/
struct Rect
{
/**
* @brief Rect constructor
*
* @param rect_ Coordinates of the rectangle
* @param color_ The bottom-left corner of the text string in the image
* @param thick_ The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle
* @param lt_ The type of the line. See #LineTypes
* @param shift_ The number of fractional bits in the point coordinates
*/
Rect(const cv::Rect& rect_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = 8,
int shift_ = 0) :
rect(rect_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
Rect() = default;
/*@{*/
cv::Rect rect; //!< Coordinates of the rectangle
cv::Scalar color; //!< The rectangle color or brightness (grayscale image)
int thick; //!< The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle
int lt; //!< The type of the line. See #LineTypes
int shift; //!< The number of fractional bits in the point coordinates
/*@{*/
};
/**
* @brief This structure represents a circle to draw.
*
* Parameters match cv::circle().
*/
struct Circle
{
/**
* @brief Circle constructor
*
* @param center_ The center of the circle
* @param radius_ The radius of the circle
* @param color_ The color of the circle
* @param thick_ The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
* @param lt_ The Type of the circle boundary. See #LineTypes
* @param shift_ The Number of fractional bits in the coordinates of the center and in the radius value
*/
Circle(const cv::Point& center_,
int radius_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = 8,
int shift_ = 0) :
center(center_), radius(radius_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
Circle() = default;
/*@{*/
cv::Point center; //!< The center of the circle
int radius; //!< The radius of the circle
cv::Scalar color; //!< The color of the circle
int thick; //!< The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
int lt; //!< The Type of the circle boundary. See #LineTypes
int shift; //!< The Number of fractional bits in the coordinates of the center and in the radius value
/*@{*/
};
/**
* @brief This structure represents a line to draw.
*
* Parameters match cv::line().
*/
struct Line
{
/**
* @brief Line constructor
*
* @param pt1_ The first point of the line segment
* @param pt2_ The second point of the line segment
* @param color_ The line color
* @param thick_ The thickness of line
* @param lt_ The Type of the line. See #LineTypes
* @param shift_ The number of fractional bits in the point coordinates
*/
Line(const cv::Point& pt1_,
const cv::Point& pt2_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = 8,
int shift_ = 0) :
pt1(pt1_), pt2(pt2_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
Line() = default;
/*@{*/
cv::Point pt1; //!< The first point of the line segment
cv::Point pt2; //!< The second point of the line segment
cv::Scalar color; //!< The line color
int thick; //!< The thickness of line
int lt; //!< The Type of the line. See #LineTypes
int shift; //!< The number of fractional bits in the point coordinates
/*@{*/
};
/**
* @brief This structure represents a mosaicing operation.
*
* Mosaicing is a very basic method to obfuscate regions in the image.
*/
struct Mosaic
{
/**
* @brief Mosaic constructor
*
* @param mos_ Coordinates of the mosaic
* @param cellSz_ Cell size (same for X, Y)
* @param decim_ Decimation (0 stands for no decimation)
*/
Mosaic(const cv::Rect& mos_,
int cellSz_,
int decim_) :
mos(mos_), cellSz(cellSz_), decim(decim_)
{
}
Mosaic() = default;
/*@{*/
cv::Rect mos; //!< Coordinates of the mosaic
int cellSz; //!< Cell size (same for X, Y)
int decim; //!< Decimation (0 stands for no decimation)
/*@{*/
};
/**
* @brief This structure represents an image to draw.
*
* Image is blended on a frame using the specified mask.
*/
struct Image
{
/**
* @brief Mosaic constructor
*
* @param org_ The bottom-left corner of the image
* @param img_ Image to draw
* @param alpha_ Alpha channel for image to draw (same size and number of channels)
*/
Image(const cv::Point& org_,
const cv::Mat& img_,
const cv::Mat& alpha_) :
org(org_), img(img_), alpha(alpha_)
{
}
Image() = default;
/*@{*/
cv::Point org; //!< The bottom-left corner of the image
cv::Mat img; //!< Image to draw
cv::Mat alpha; //!< Alpha channel for image to draw (same size and number of channels)
/*@{*/
};
/**
* @brief This structure represents a polygon to draw.
*/
struct Poly
{
/**
* @brief Mosaic constructor
*
* @param points_ Points to connect
* @param color_ The line color
* @param thick_ The thickness of line
* @param lt_ The Type of the line. See #LineTypes
* @param shift_ The number of fractional bits in the point coordinate
*/
Poly(const std::vector<cv::Point>& points_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = 8,
int shift_ = 0) :
points(points_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
Poly() = default;
/*@{*/
std::vector<cv::Point> points; //!< Points to connect
cv::Scalar color; //!< The line color
int thick; //!< The thickness of line
int lt; //!< The Type of the line. See #LineTypes
int shift; //!< The number of fractional bits in the point coordinate
/*@{*/
};
using Prim = util::variant
< Text
, FText
, Rect
, Circle
, Line
, Mosaic
, Image
, Poly
>;
using Prims = std::vector<Prim>;
//! @} gapi_draw_prims
} // namespace draw
} // namespace wip
} // namespace gapi
} // namespace cv
#endif // OPENCV_GAPI_RENDER_TYPES_HPP

View File

@@ -0,0 +1,124 @@
// 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) 2020 Intel Corporation
#ifndef OPENCV_GAPI_RMAT_HPP
#define OPENCV_GAPI_RMAT_HPP
#include <opencv2/gapi/gmat.hpp>
namespace cv {
// "Remote Mat", a general class which provides an abstraction layer over the data
// storage and placement (host, remote device etc) and allows to access this data.
//
// The device specific implementation is hidden in the RMat::Adapter class
//
// The basic flow is the following:
// * Backend which is aware of the remote device:
// - Implements own AdapterT class which is derived from RMat::Adapter
// - Wraps device memory into RMat via make_rmat utility function:
// cv::RMat rmat = cv::make_rmat<AdapterT>(args);
//
// * End user:
// - Writes the code which works with RMats without any knowledge of the remote device:
// void func(const cv::RMat& in_rmat, cv::RMat& out_rmat) {
// // Fetch input data from the device, get mapped memory for output
// cv::RMat::View in_view = in_rmat.access(Access::R);
// cv::RMat::View out_view = out_rmat.access(Access::W);
// performCalculations(in_view, out_view);
// // data from out_view is transferred to the device when out_view is destroyed
// }
class RMat
{
public:
// A lightweight wrapper on image data:
// - Doesn't own the memory;
// - Doesn't implement copy semantics (it's assumed that a view is created each time
// wrapped data is being accessed);
// - Has an optional callback which is called when the view is destroyed.
class View
{
public:
using DestroyCallback = std::function<void()>;
View() = default;
View(const GMatDesc& desc, uchar* data, size_t step = 0u, DestroyCallback&& cb = nullptr)
: m_desc(desc), m_data(data), m_step(step == 0u ? elemSize()*cols() : step), m_cb(cb)
{}
View(const View&) = delete;
View(View&&) = default;
View& operator=(const View&) = delete;
View& operator=(View&&) = default;
~View() { if (m_cb) m_cb(); }
cv::Size size() const { return m_desc.size; }
const std::vector<int>& dims() const { return m_desc.dims; }
int cols() const { return m_desc.size.width; }
int rows() const { return m_desc.size.height; }
int type() const { return CV_MAKE_TYPE(depth(), chan()); }
int depth() const { return m_desc.depth; }
int chan() const { return m_desc.chan; }
size_t elemSize() const { return CV_ELEM_SIZE(type()); }
template<typename T = uchar> T* ptr(int y = 0, int x = 0) {
return reinterpret_cast<T*>(m_data + m_step*y + x*CV_ELEM_SIZE(type()));
}
template<typename T = uchar> const T* ptr(int y = 0, int x = 0) const {
return reinterpret_cast<const T*>(m_data + m_step*y + x*CV_ELEM_SIZE(type()));
}
size_t step() const { return m_step; }
private:
GMatDesc m_desc;
uchar* m_data = nullptr;
size_t m_step = 0u;
DestroyCallback m_cb = nullptr;
};
enum class Access { R, W };
class Adapter
{
public:
virtual ~Adapter() = default;
virtual GMatDesc desc() const = 0;
// Implementation is responsible for setting the appropriate callback to
// the view when accessed for writing, to ensure that the data from the view
// is transferred to the device when the view is destroyed
virtual View access(Access) const = 0;
};
using AdapterP = std::shared_ptr<Adapter>;
RMat() = default;
RMat(AdapterP&& a) : m_adapter(std::move(a)) {}
GMatDesc desc() const { return m_adapter->desc(); }
// Note: When accessed for write there is no guarantee that returned view
// will contain actual snapshot of the mapped device memory
// (no guarantee that fetch from a device is performed). The only
// guaranty is that when the view is destroyed, its data will be
// transferred to the device
View access(Access a) const { return m_adapter->access(a); }
// Cast underlying RMat adapter to the particular adapter type,
// return nullptr if underlying type is different
template<typename T> T* get() const
{
static_assert(std::is_base_of<Adapter, T>::value, "T is not derived from Adapter!");
GAPI_Assert(m_adapter != nullptr);
return dynamic_cast<T*>(m_adapter.get());
}
private:
AdapterP m_adapter = nullptr;
};
template<typename T, typename... Ts>
RMat make_rmat(Ts&&... args) { return { std::make_shared<T>(std::forward<Ts>(args)...) }; }
} //namespace cv
#endif /* OPENCV_GAPI_RMAT_HPP */

View File

@@ -0,0 +1,58 @@
// 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) 2020 Intel Corporation
#ifndef OPENCV_GAPI_S11N_HPP
#define OPENCV_GAPI_S11N_HPP
#include <vector>
#include <opencv2/gapi/gcomputation.hpp>
namespace cv {
namespace gapi {
namespace detail {
GAPI_EXPORTS cv::GComputation getGraph(const std::vector<char> &p);
} // namespace detail
namespace detail {
GAPI_EXPORTS cv::GMetaArgs getMetaArgs(const std::vector<char> &p);
} // namespace detail
namespace detail {
GAPI_EXPORTS cv::GRunArgs getRunArgs(const std::vector<char> &p);
} // namespace detail
GAPI_EXPORTS std::vector<char> serialize(const cv::GComputation &c);
//namespace{
template<typename T> static inline
T deserialize(const std::vector<char> &p);
//} //ananymous namespace
GAPI_EXPORTS std::vector<char> serialize(const cv::GMetaArgs&);
GAPI_EXPORTS std::vector<char> serialize(const cv::GRunArgs&);
template<> inline
cv::GComputation deserialize(const std::vector<char> &p) {
return detail::getGraph(p);
}
template<> inline
cv::GMetaArgs deserialize(const std::vector<char> &p) {
return detail::getMetaArgs(p);
}
template<> inline
cv::GRunArgs deserialize(const std::vector<char> &p) {
return detail::getRunArgs(p);
}
} // namespace gapi
} // namespace cv
#endif // OPENCV_GAPI_S11N_HPP

View File

@@ -0,0 +1,31 @@
// 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) 2020 Intel Corporation
#ifndef OPENCV_GAPI_UTIL_TYPE_TRAITS_HPP
#define OPENCV_GAPI_UTIL_TYPE_TRAITS_HPP
#include <type_traits>
namespace cv
{
namespace util
{
//these are C++14 parts of type_traits :
template< bool B, class T = void >
using enable_if_t = typename std::enable_if<B,T>::type;
template<typename T>
using decay_t = typename std::decay<T>::type;
//this is not part of C++14 but still, of pretty common usage
template<class T, class U, class V = void>
using are_different_t = enable_if_t< !std::is_same<decay_t<T>, decay_t<U>>::value, V>;
} // namespace cv
} // namespace util
#endif // OPENCV_GAPI_UTIL_TYPE_TRAITS_HPP

View File

@@ -13,6 +13,7 @@
#include <opencv2/gapi/util/throw.hpp>
#include <opencv2/gapi/util/util.hpp> // max_of_t
#include <opencv2/gapi/util/type_traits.hpp>
// A poor man's `variant` implementation, incompletely modeled against C++17 spec.
namespace cv
@@ -35,12 +36,6 @@ namespace util
static_assert(std::is_same<Target, First>::value, "Type not found");
static const constexpr std::size_t value = I;
};
template<class T, class U, class V> using are_different =
std::enable_if<!std::is_same<typename std::decay<T>::type,
typename std::decay<U>::type>::value,
V>;
}
template<typename Target, typename... Types>
@@ -79,18 +74,20 @@ namespace util
}
};
template<typename T> struct vctr_h {
static void help(Memory memory, const void* pval) {
new (memory) T(*reinterpret_cast<const T*>(pval));
}
};
template<typename T> struct mctr_h {
static void help(Memory memory, void *pval) {
new (memory) T(std::move(*reinterpret_cast<T*>(pval)));
}
};
//FIXME: unify with cctr_h and mctr_h
template<typename T> struct cnvrt_ctor_h {
static void help(Memory memory, void* from) {
using util::decay_t;
new (memory) decay_t<T>(std::forward<T>(*reinterpret_cast<decay_t<T>*>(from)));
}
};
template<typename T> struct copy_h {
static void help(Memory to, const Memory from) {
*reinterpret_cast<T*>(to) = *reinterpret_cast<const T*>(from);
@@ -98,8 +95,16 @@ namespace util
};
template<typename T> struct move_h {
static void help(Memory to, const Memory from) {
*reinterpret_cast<T*>(to) = std::move(*reinterpret_cast<const T*>(from));
static void help(Memory to, Memory from) {
*reinterpret_cast<T*>(to) = std::move(*reinterpret_cast<T*>(from));
}
};
//FIXME: unify with copy_h and move_h
template<typename T> struct cnvrt_assign_h {
static void help(Memory to, void* from) {
using util::decay_t;
*reinterpret_cast<decay_t<T>*>(to) = std::forward<T>(*reinterpret_cast<decay_t<T>*>(from));
}
};
@@ -125,28 +130,50 @@ namespace util
};
typedef void (*CCtr) (Memory, const Memory); // Copy c-tor (variant)
typedef void (*VCtr) (Memory, const void*); // Copy c-tor (value)
typedef void (*MCtr) (Memory, void*); // Generic move c-tor
typedef void (*Copy) (Memory, const Memory); // Copy assignment
typedef void (*Move) (Memory, const Memory); // Move assignment
typedef void (*Move) (Memory, Memory); // Move assignment
typedef void (*Swap) (Memory, Memory); // Swap
typedef void (*Dtor) (Memory); // Destructor
using cnvrt_assgn_t = void (*) (Memory, void*); // Converting assignment (via std::forward)
using cnvrt_ctor_t = void (*) (Memory, void*); // Converting constructor (via std::forward)
typedef bool (*Equal)(const Memory, const Memory); // Equality test (external)
static constexpr std::array<CCtr, sizeof...(Ts)> cctrs(){ return {{(&cctr_h<Ts>::help)...}};}
static constexpr std::array<VCtr, sizeof...(Ts)> vctrs(){ return {{(&vctr_h<Ts>::help)...}};}
static constexpr std::array<MCtr, sizeof...(Ts)> mctrs(){ return {{(&mctr_h<Ts>::help)...}};}
static constexpr std::array<Copy, sizeof...(Ts)> cpyrs(){ return {{(&copy_h<Ts>::help)...}};}
static constexpr std::array<Move, sizeof...(Ts)> mvers(){ return {{(&move_h<Ts>::help)...}};}
static constexpr std::array<Swap, sizeof...(Ts)> swprs(){ return {{(&swap_h<Ts>::help)...}};}
static constexpr std::array<Dtor, sizeof...(Ts)> dtors(){ return {{(&dtor_h<Ts>::help)...}};}
template<bool cond, typename T>
struct conditional_ref : std::conditional<cond, typename std::remove_reference<T>::type&, typename std::remove_reference<T>::type > {};
template<bool cond, typename T>
using conditional_ref_t = typename conditional_ref<cond, T>::type;
template<bool is_lvalue_arg>
static constexpr std::array<cnvrt_assgn_t, sizeof...(Ts)> cnvrt_assgnrs(){
return {{(&cnvrt_assign_h<conditional_ref_t<is_lvalue_arg,Ts>>::help)...}};
}
template<bool is_lvalue_arg>
static constexpr std::array<cnvrt_ctor_t, sizeof...(Ts)> cnvrt_ctors(){
return {{(&cnvrt_ctor_h<conditional_ref_t<is_lvalue_arg,Ts>>::help)...}};
}
std::size_t m_index = 0;
protected:
template<typename T, typename... Us> friend T& get(variant<Us...> &v);
template<typename T, typename... Us> friend const T& get(const variant<Us...> &v);
template<typename T, typename... Us> friend T* get_if(variant<Us...> *v) noexcept;
template<typename T, typename... Us> friend const T* get_if(const variant<Us...> *v) noexcept;
template<typename... Us> friend bool operator==(const variant<Us...> &lhs,
const variant<Us...> &rhs);
Memory memory;
@@ -156,11 +183,14 @@ namespace util
variant() noexcept;
variant(const variant& other);
variant(variant&& other) noexcept;
template<typename T> explicit variant(const T& t);
// are_different is a SFINAE trick to avoid variant(T &&t) with T=variant
// are_different_t is a SFINAE trick to avoid variant(T &&t) with T=variant
// for some reason, this version is called instead of variant(variant&& o) when
// variant is used in STL containers (examples: vector assignment)
template<typename T> explicit variant(T&& t, typename detail::are_different<variant, T, int>::type = 0);
// variant is used in STL containers (examples: vector assignment).
template<
typename T,
typename = util::are_different_t<variant, T>
>
explicit variant(T&& t);
// template<class T, class... Args> explicit variant(Args&&... args);
// FIXME: other constructors
@@ -172,9 +202,11 @@ namespace util
variant& operator=(variant &&rhs) noexcept;
// SFINAE trick to avoid operator=(T&&) with T=variant<>, see comment above
template<class T>
typename detail::are_different<variant, T, variant&>
::type operator=(T&& t) noexcept;
template<
typename T,
typename = util::are_different_t<variant, T>
>
variant& operator=(T&& t) noexcept;
// Observers
std::size_t index() const noexcept;
@@ -189,6 +221,11 @@ namespace util
};
// FIMXE: visit
template<typename T, typename... Types>
T* get_if(util::variant<Types...>* v) noexcept;
template<typename T, typename... Types>
const T* get_if(const util::variant<Types...>* v) noexcept;
template<typename T, typename... Types>
T& get(util::variant<Types...> &v);
@@ -224,19 +261,12 @@ namespace util
}
template<typename... Ts>
template<class T>
variant<Ts...>::variant(const T& t)
: m_index(util::type_list_index<T, Ts...>::value)
template<class T, typename>
variant<Ts...>::variant(T&& t)
: m_index(util::type_list_index<util::decay_t<T>, Ts...>::value)
{
(vctrs()[m_index])(memory, &t);
}
template<typename... Ts>
template<class T>
variant<Ts...>::variant(T&& t, typename detail::are_different<variant, T, int>::type)
: m_index(util::type_list_index<typename std::remove_reference<T>::type, Ts...>::value)
{
(mctrs()[m_index])(memory, &t);
const constexpr bool is_lvalue_arg = std::is_lvalue_reference<T>::value;
(cnvrt_ctors<is_lvalue_arg>()[m_index])(memory, const_cast<util::decay_t<T> *>(&t));
}
template<typename... Ts>
@@ -278,20 +308,28 @@ namespace util
}
template<typename... Ts>
template<class T> typename detail::are_different<variant<Ts...>, T, variant<Ts...>&>
::type variant<Ts...>::operator=(T&& t) noexcept
template<typename T, typename>
variant<Ts...>& variant<Ts...>::operator=(T&& t) noexcept
{
using decayed_t = typename std::decay<T>::type;
using decayed_t = util::decay_t<T>;
// FIXME: No version with implicit type conversion available!
static const constexpr std::size_t t_index =
const constexpr std::size_t t_index =
util::type_list_index<decayed_t, Ts...>::value;
if (t_index == m_index)
const constexpr bool is_lvalue_arg = std::is_lvalue_reference<T>::value;
if (t_index != m_index)
{
util::get<decayed_t>(*this) = std::move(t);
return *this;
(dtors()[m_index])(memory);
(cnvrt_ctors<is_lvalue_arg>()[t_index])(memory, &t);
m_index = t_index;
}
else return (*this = variant(std::move(t)));
else
{
(cnvrt_assgnrs<is_lvalue_arg>()[m_index])(memory, &t);
}
return *this;
}
template<typename... Ts>
@@ -323,14 +361,34 @@ namespace util
}
template<typename T, typename... Types>
T& get(util::variant<Types...> &v)
T* get_if(util::variant<Types...>* v) noexcept
{
const constexpr std::size_t t_index =
util::type_list_index<T, Types...>::value;
if (v.index() == t_index)
return *(T*)(&v.memory); // workaround for ICC 2019
if (v && v->index() == t_index)
return (T*)(&v->memory); // workaround for ICC 2019
// original code: return reinterpret_cast<T&>(v.memory);
return nullptr;
}
template<typename T, typename... Types>
const T* get_if(const util::variant<Types...>* v) noexcept
{
const constexpr std::size_t t_index =
util::type_list_index<T, Types...>::value;
if (v && v->index() == t_index)
return (const T*)(&v->memory); // workaround for ICC 2019
// original code: return reinterpret_cast<const T&>(v.memory);
return nullptr;
}
template<typename T, typename... Types>
T& get(util::variant<Types...> &v)
{
if (auto* p = get_if<T>(&v))
return *p;
else
throw_error(bad_variant_access());
}
@@ -338,12 +396,8 @@ namespace util
template<typename T, typename... Types>
const T& get(const util::variant<Types...> &v)
{
const constexpr std::size_t t_index =
util::type_list_index<T, Types...>::value;
if (v.index() == t_index)
return *(const T*)(&v.memory); // workaround for ICC 2019
// original code: return reinterpret_cast<const T&>(v.memory);
if (auto* p = get_if<T>(&v))
return *p;
else
throw_error(bad_variant_access());
}

View File

@@ -0,0 +1,176 @@
// 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) 2020 Intel Corporation
#ifndef OPENCV_GAPI_VIDEO_HPP
#define OPENCV_GAPI_VIDEO_HPP
#include <utility> // std::tuple
#include <opencv2/gapi/gkernel.hpp>
/** \defgroup gapi_video G-API Video processing functionality
*/
namespace cv { namespace gapi {
namespace video
{
using GBuildPyrOutput = std::tuple<GArray<GMat>, GScalar>;
using GOptFlowLKOutput = std::tuple<cv::GArray<cv::Point2f>,
cv::GArray<uchar>,
cv::GArray<float>>;
G_TYPED_KERNEL(GBuildOptFlowPyramid, <GBuildPyrOutput(GMat,Size,GScalar,bool,int,int,bool)>,
"org.opencv.video.buildOpticalFlowPyramid")
{
static std::tuple<GArrayDesc,GScalarDesc>
outMeta(GMatDesc,const Size&,GScalarDesc,bool,int,int,bool)
{
return std::make_tuple(empty_array_desc(), empty_scalar_desc());
}
};
G_TYPED_KERNEL(GCalcOptFlowLK,
<GOptFlowLKOutput(GMat,GMat,cv::GArray<cv::Point2f>,cv::GArray<cv::Point2f>,Size,
GScalar,TermCriteria,int,double)>,
"org.opencv.video.calcOpticalFlowPyrLK")
{
static std::tuple<GArrayDesc,GArrayDesc,GArrayDesc> outMeta(GMatDesc,GMatDesc,GArrayDesc,
GArrayDesc,const Size&,GScalarDesc,
const TermCriteria&,int,double)
{
return std::make_tuple(empty_array_desc(), empty_array_desc(), empty_array_desc());
}
};
G_TYPED_KERNEL(GCalcOptFlowLKForPyr,
<GOptFlowLKOutput(cv::GArray<cv::GMat>,cv::GArray<cv::GMat>,
cv::GArray<cv::Point2f>,cv::GArray<cv::Point2f>,Size,GScalar,
TermCriteria,int,double)>,
"org.opencv.video.calcOpticalFlowPyrLKForPyr")
{
static std::tuple<GArrayDesc,GArrayDesc,GArrayDesc> outMeta(GArrayDesc,GArrayDesc,
GArrayDesc,GArrayDesc,
const Size&,GScalarDesc,
const TermCriteria&,int,double)
{
return std::make_tuple(empty_array_desc(), empty_array_desc(), empty_array_desc());
}
};
} //namespace video
//! @addtogroup gapi_video
//! @{
/** @brief Constructs the image pyramid which can be passed to calcOpticalFlowPyrLK.
@note Function textual ID is "org.opencv.video.buildOpticalFlowPyramid"
@param img 8-bit input image.
@param winSize window size of optical flow algorithm. Must be not less than winSize
argument of calcOpticalFlowPyrLK. It is needed to calculate required
padding for pyramid levels.
@param maxLevel 0-based maximal pyramid level number.
@param withDerivatives set to precompute gradients for the every pyramid level. If pyramid is
constructed without the gradients then calcOpticalFlowPyrLK will calculate
them internally.
@param pyrBorder the border mode for pyramid layers.
@param derivBorder the border mode for gradients.
@param tryReuseInputImage put ROI of input image into the pyramid if possible. You can pass false
to force data copying.
@return output pyramid.
@return number of levels in constructed pyramid. Can be less than maxLevel.
*/
GAPI_EXPORTS std::tuple<GArray<GMat>, GScalar>
buildOpticalFlowPyramid(const GMat &img,
const Size &winSize,
const GScalar &maxLevel,
bool withDerivatives = true,
int pyrBorder = BORDER_REFLECT_101,
int derivBorder = BORDER_CONSTANT,
bool tryReuseInputImage = true);
/** @brief Calculates an optical flow for a sparse feature set using the iterative Lucas-Kanade
method with pyramids.
See @cite Bouguet00 .
@note Function textual ID is "org.opencv.video.calcOpticalFlowPyrLK"
@param prevImg first 8-bit input image (GMat) or pyramid (GArray<GMat>) constructed by
buildOpticalFlowPyramid.
@param nextImg second input image (GMat) or pyramid (GArray<GMat>) of the same size and the same
type as prevImg.
@param prevPts GArray of 2D points for which the flow needs to be found; point coordinates must be
single-precision floating-point numbers.
@param predPts GArray of 2D points initial for the flow search; make sense only when
OPTFLOW_USE_INITIAL_FLOW flag is passed; in that case the vector must have the same size as in
the input.
@param winSize size of the search window at each pyramid level.
@param maxLevel 0-based maximal pyramid level number; if set to 0, pyramids are not used (single
level), if set to 1, two levels are used, and so on; if pyramids are passed to input then
algorithm will use as many levels as pyramids have but no more than maxLevel.
@param criteria parameter, specifying the termination criteria of the iterative search algorithm
(after the specified maximum number of iterations criteria.maxCount or when the search window
moves by less than criteria.epsilon).
@param flags operation flags:
- **OPTFLOW_USE_INITIAL_FLOW** uses initial estimations, stored in nextPts; if the flag is
not set, then prevPts is copied to nextPts and is considered the initial estimate.
- **OPTFLOW_LK_GET_MIN_EIGENVALS** use minimum eigen values as an error measure (see
minEigThreshold description); if the flag is not set, then L1 distance between patches
around the original and a moved point, divided by number of pixels in a window, is used as a
error measure.
@param minEigThresh the algorithm calculates the minimum eigen value of a 2x2 normal matrix of
optical flow equations (this matrix is called a spatial gradient matrix in @cite Bouguet00), divided
by number of pixels in a window; if this value is less than minEigThreshold, then a corresponding
feature is filtered out and its flow is not processed, so it allows to remove bad points and get a
performance boost.
@return GArray of 2D points (with single-precision floating-point coordinates)
containing the calculated new positions of input features in the second image.
@return status GArray (of unsigned chars); each element of the vector is set to 1 if
the flow for the corresponding features has been found, otherwise, it is set to 0.
@return GArray of errors (doubles); each element of the vector is set to an error for the
corresponding feature, type of the error measure can be set in flags parameter; if the flow wasn't
found then the error is not defined (use the status parameter to find such cases).
*/
GAPI_EXPORTS std::tuple<GArray<Point2f>, GArray<uchar>, GArray<float>>
calcOpticalFlowPyrLK(const GMat &prevImg,
const GMat &nextImg,
const GArray<Point2f> &prevPts,
const GArray<Point2f> &predPts,
const Size &winSize = Size(21, 21),
const GScalar &maxLevel = 3,
const TermCriteria &criteria = TermCriteria(TermCriteria::COUNT |
TermCriteria::EPS,
30, 0.01),
int flags = 0,
double minEigThresh = 1e-4);
/**
@overload
@note Function textual ID is "org.opencv.video.calcOpticalFlowPyrLKForPyr"
*/
GAPI_EXPORTS std::tuple<GArray<Point2f>, GArray<uchar>, GArray<float>>
calcOpticalFlowPyrLK(const GArray<GMat> &prevPyr,
const GArray<GMat> &nextPyr,
const GArray<Point2f> &prevPts,
const GArray<Point2f> &predPts,
const Size &winSize = Size(21, 21),
const GScalar &maxLevel = 3,
const TermCriteria &criteria = TermCriteria(TermCriteria::COUNT |
TermCriteria::EPS,
30, 0.01),
int flags = 0,
double minEigThresh = 1e-4);
//! @} gapi_video
} //namespace gapi
} //namespace cv
#endif // OPENCV_GAPI_VIDEO_HPP

View File

@@ -0,0 +1,45 @@
using gapi_GKernelPackage = cv::gapi::GKernelPackage;
template<>
bool pyopencv_to(PyObject* obj, std::vector<GCompileArg>& value, const ArgInfo& info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
template<>
PyObject* pyopencv_from(const std::vector<GCompileArg>& value)
{
return pyopencv_from_generic_vec(value);
}
template <typename T>
static PyObject* extract_proto_args(PyObject* py_args, PyObject* kw)
{
using namespace cv;
GProtoArgs args;
Py_ssize_t size = PyTuple_Size(py_args);
for (int i = 0; i < size; ++i) {
PyObject* item = PyTuple_GetItem(py_args, i);
if (PyObject_TypeCheck(item, reinterpret_cast<PyTypeObject*>(pyopencv_GScalar_TypePtr))) {
args.emplace_back(reinterpret_cast<pyopencv_GScalar_t*>(item)->v);
} else if (PyObject_TypeCheck(item, reinterpret_cast<PyTypeObject*>(pyopencv_GMat_TypePtr))) {
args.emplace_back(reinterpret_cast<pyopencv_GMat_t*>(item)->v);
} else {
PyErr_SetString(PyExc_TypeError, "cv.GIn() supports only cv.GMat and cv.GScalar");
return NULL;
}
}
return pyopencv_from<T>(T{std::move(args)});
}
static PyObject* pyopencv_cv_GIn(PyObject* , PyObject* py_args, PyObject* kw)
{
return extract_proto_args<GProtoInputArgs>(py_args, kw);
}
static PyObject* pyopencv_cv_GOut(PyObject* , PyObject* py_args, PyObject* kw)
{
return extract_proto_args<GProtoOutputArgs>(py_args, kw);
}

View File

@@ -0,0 +1,13 @@
#error This is a shadow header file, which is not intended for processing by any compiler. \
Only bindings parser should handle this file.
namespace cv
{
GAPI_EXPORTS_W GCompileArgs compile_args(gapi::GKernelPackage pkg);
class GAPI_EXPORTS_W_SIMPLE GProtoArg { };
class GAPI_EXPORTS_W_SIMPLE GProtoInputArgs { };
class GAPI_EXPORTS_W_SIMPLE GProtoOutputArgs { };
using GProtoInputArgs = GIOProtoArgs<In_Tag>;
using GProtoOutputArgs = GIOProtoArgs<Out_Tag>;
} // namespace cv

View File

@@ -0,0 +1,60 @@
#!/usr/bin/env python
import numpy as np
import cv2 as cv
from tests_common import NewOpenCVTests
# Plaidml is an optional backend
pkgs = [
cv.gapi.core.ocl.kernels(),
cv.gapi.core.cpu.kernels(),
cv.gapi.core.fluid.kernels()
# cv.gapi.core.plaidml.kernels()
]
class gapi_core_test(NewOpenCVTests):
def test_add(self):
# TODO: Extend to use any type and size here
sz = (1280, 720)
in1 = np.random.randint(0, 100, sz).astype(np.uint8)
in2 = np.random.randint(0, 100, sz).astype(np.uint8)
# OpenCV
expected = in1 + in2
# G-API
g_in1 = cv.GMat()
g_in2 = cv.GMat()
g_out = cv.gapi.add(g_in1, g_in2)
comp = cv.GComputation(cv.GIn(g_in1, g_in2), cv.GOut(g_out))
for pkg in pkgs:
actual = comp.apply(in1, in2, args=cv.compile_args(pkg))
# Comparison
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
def test_mean(self):
sz = (1280, 720, 3)
in_mat = np.random.randint(0, 100, sz).astype(np.uint8)
# OpenCV
expected = cv.mean(in_mat)
# G-API
g_in = cv.GMat()
g_out = cv.gapi.mean(g_in)
comp = cv.GComputation(g_in, g_out)
for pkg in pkgs:
actual = comp.apply(in_mat, args=cv.compile_args(pkg))
# Comparison
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
if __name__ == '__main__':
NewOpenCVTests.bootstrap()

View File

@@ -0,0 +1,42 @@
#!/usr/bin/env python
import numpy as np
import cv2 as cv
from tests_common import NewOpenCVTests
# Plaidml is an optional backend
pkgs = [
cv.gapi.core.ocl.kernels(),
cv.gapi.core.cpu.kernels(),
cv.gapi.core.fluid.kernels()
# cv.gapi.core.plaidml.kernels()
]
class gapi_sample_pipelines(NewOpenCVTests):
# NB: This test check multiple outputs for operation
def test_mean_over_r(self):
sz = (100, 100, 3)
in_mat = np.random.randint(0, 100, sz).astype(np.uint8)
# # OpenCV
_, _, r_ch = cv.split(in_mat)
expected = cv.mean(r_ch)
# G-API
g_in = cv.GMat()
b, g, r = cv.gapi.split3(g_in)
g_out = cv.gapi.mean(r)
comp = cv.GComputation(g_in, g_out)
for pkg in pkgs:
actual = comp.apply(in_mat, args=cv.compile_args(pkg))
# Comparison
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
if __name__ == '__main__':
NewOpenCVTests.bootstrap()

View File

@@ -10,6 +10,7 @@
#include "../../test/common/gapi_tests_common.hpp"
#include "../../test/common/gapi_parsers_tests_common.hpp"
#include <opencv2/gapi/core.hpp>
namespace opencv_test
@@ -42,8 +43,8 @@ namespace opencv_test
class Polar2CartPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class Cart2PolarPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class CmpPerfTest : public TestPerfParams<tuple<CmpTypes, cv::Size, MatType, cv::GCompileArgs>> {};
class CmpWithScalarPerfTest : public TestPerfParams<tuple<CmpTypes, cv::Size, MatType, cv::GCompileArgs>> {};
class BitwisePerfTest : public TestPerfParams<tuple<bitwiseOp, cv::Size, MatType, cv::GCompileArgs>> {};
class CmpWithScalarPerfTest : public TestPerfParams<tuple<compare_f, CmpTypes, cv::Size, MatType, cv::GCompileArgs>> {};
class BitwisePerfTest : public TestPerfParams<tuple<bitwiseOp, bool, cv::Size, MatType, cv::GCompileArgs>> {};
class BitwiseNotPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
class SelectPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
class MinPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
@@ -70,8 +71,13 @@ namespace opencv_test
class ConcatVertPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
class ConcatVertVecPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
class LUTPerfTest : public TestPerfParams<tuple<MatType, MatType, cv::Size, cv::GCompileArgs>> {};
class ConvertToPerfTest : public TestPerfParams<tuple<MatType, int, cv::Size, cv::GCompileArgs>> {};
class ConvertToPerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, double, double, cv::GCompileArgs>> {};
class ResizePerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, cv::Size, cv::GCompileArgs>> {};
class ResizeFxFyPerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, double, double, cv::GCompileArgs>> {};
class ParseSSDBLPerfTest : public TestPerfParams<tuple<cv::Size, float, int, cv::GCompileArgs>>, public ParserSSDTest {};
class ParseSSDPerfTest : public TestPerfParams<tuple<cv::Size, float, bool, bool, cv::GCompileArgs>>, public ParserSSDTest {};
class ParseYoloPerfTest : public TestPerfParams<tuple<cv::Size, float, float, int, cv::GCompileArgs>>, public ParserYoloTest {};
class SizePerfTest : public TestPerfParams<tuple<MatType, cv::Size, cv::GCompileArgs>> {};
class SizeRPerfTest : public TestPerfParams<tuple<cv::Size, cv::GCompileArgs>> {};
}
#endif // OPENCV_GAPI_CORE_PERF_TESTS_HPP

View File

@@ -402,10 +402,6 @@ PERF_TEST_P_(DivRCPerfTest, TestPerformance)
// FIXIT Unstable input data for divide
initMatsRandU(type, sz, dtype, false);
// FIXIT Unstable input data for divide, don't process zeros
sc += Scalar::all(1);
in_mat1 += 1;
// OpenCV code ///////////////////////////////////////////////////////////
cv::divide(sc, in_mat1, out_mat_ocv, 1.0, dtype);
@@ -426,7 +422,7 @@ PERF_TEST_P_(DivRCPerfTest, TestPerformance)
}
// Comparison ////////////////////////////////////////////////////////////
EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
// FIXIT unrealiable check: EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
EXPECT_EQ(out_mat_gapi.size(), sz);
SANITY_CHECK_NOTHING();
@@ -630,10 +626,12 @@ PERF_TEST_P_(CmpPerfTest, TestPerformance)
PERF_TEST_P_(CmpWithScalarPerfTest, TestPerformance)
{
CmpTypes opType = get<0>(GetParam());
cv::Size sz = get<1>(GetParam());
MatType type = get<2>(GetParam());
cv::GCompileArgs compile_args = get<3>(GetParam());
MatType type = -1;
CmpTypes opType = CMP_EQ;
cv::Size sz;
compare_f cmpF;
cv::GCompileArgs compile_args;
std::tie(cmpF, opType, sz, type, compile_args) = GetParam();
initMatsRandU(type, sz, CV_8U, false);
@@ -666,8 +664,8 @@ PERF_TEST_P_(CmpWithScalarPerfTest, TestPerformance)
}
// Comparison ////////////////////////////////////////////////////////////
EXPECT_EQ(0, cvtest::norm(out_mat_gapi, out_mat_ocv, NORM_INF));
EXPECT_EQ(out_mat_gapi.size(), sz);
EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
SANITY_CHECK_NOTHING();
}
@@ -676,50 +674,76 @@ PERF_TEST_P_(CmpWithScalarPerfTest, TestPerformance)
PERF_TEST_P_(BitwisePerfTest, TestPerformance)
{
bitwiseOp opType = get<0>(GetParam());
cv::Size sz = get<1>(GetParam());
MatType type = get<2>(GetParam());
cv::GCompileArgs compile_args = get<3>(GetParam());
MatType type = -1;
bitwiseOp opType = AND;
bool testWithScalar = false;
cv::Size sz;
cv::GCompileArgs compile_args;
std::tie(opType, testWithScalar, sz, type, compile_args) = GetParam();
initMatsRandU(type, sz, type, false);
// G-API code & corresponding OpenCV code ////////////////////////////////
cv::GMat in1, in2, out;
switch (opType)
if( testWithScalar )
{
case AND:
{
out = cv::gapi::bitwise_and(in1, in2);
cv::bitwise_and(in_mat1, in_mat2, out_mat_ocv);
break;
}
case OR:
{
out = cv::gapi::bitwise_or(in1, in2);
cv::bitwise_or(in_mat1, in_mat2, out_mat_ocv);
break;
}
case XOR:
{
out = cv::gapi::bitwise_xor(in1, in2);
cv::bitwise_xor(in_mat1, in_mat2, out_mat_ocv);
break;
}
default:
{
FAIL() << "no such bitwise operation type!";
}
}
cv::GComputation c(GIn(in1, in2), GOut(out));
cv::GScalar sc1;
switch (opType)
{
case AND:
out = cv::gapi::bitwise_and(in1, sc1);
cv::bitwise_and(in_mat1, sc, out_mat_ocv);
break;
case OR:
out = cv::gapi::bitwise_or(in1, sc1);
cv::bitwise_or(in_mat1, sc, out_mat_ocv);
break;
case XOR:
out = cv::gapi::bitwise_xor(in1, sc1);
cv::bitwise_xor(in_mat1, sc, out_mat_ocv);
break;
default:
FAIL() << "no such bitwise operation type!";
}
cv::GComputation c(GIn(in1, sc1), GOut(out));
// Warm-up graph engine:
auto cc = c.compile(descr_of(gin(in_mat1, in_mat2)),
std::move(compile_args));
cc(gin(in_mat1, in_mat2), gout(out_mat_gapi));
// Warm-up graph engine:
c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
TEST_CYCLE()
TEST_CYCLE()
{
c.apply(gin(in_mat1, sc), gout(out_mat_gapi));
}
}
else
{
cc(gin(in_mat1, in_mat2), gout(out_mat_gapi));
switch (opType)
{
case AND:
out = cv::gapi::bitwise_and(in1, in2);
cv::bitwise_and(in_mat1, in_mat2, out_mat_ocv);
break;
case OR:
out = cv::gapi::bitwise_or(in1, in2);
cv::bitwise_or(in_mat1, in_mat2, out_mat_ocv);
break;
case XOR:
out = cv::gapi::bitwise_xor(in1, in2);
cv::bitwise_xor(in_mat1, in_mat2, out_mat_ocv);
break;
default:
FAIL() << "no such bitwise operation type!";
}
cv::GComputation c(GIn(in1, in2), GOut(out));
// Warm-up graph engine:
c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
TEST_CYCLE()
{
c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi));
}
}
// Comparison ////////////////////////////////////////////////////////////
@@ -1805,20 +1829,23 @@ PERF_TEST_P_(LUTPerfTest, TestPerformance)
PERF_TEST_P_(ConvertToPerfTest, TestPerformance)
{
MatType type_mat = get<0>(GetParam());
int depth_to = get<1>(GetParam());
cv::Size sz_in = get<2>(GetParam());
cv::GCompileArgs compile_args = get<3>(GetParam());
int depth_to = -1;
MatType type_mat = -1;
double alpha = 0., beta = 0.;
cv::Size sz_in;
compare_f cmpF;
cv::GCompileArgs compile_args;
std::tie(cmpF, type_mat, depth_to, sz_in, alpha, beta, compile_args) = GetParam();
MatType type_out = CV_MAKETYPE(depth_to, CV_MAT_CN(type_mat));
initMatrixRandU(type_mat, sz_in, type_out);
// OpenCV code ///////////////////////////////////////////////////////////
in_mat1.convertTo(out_mat_ocv, depth_to);
in_mat1.convertTo(out_mat_ocv, depth_to, alpha, beta);
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
auto out = cv::gapi::convertTo(in, depth_to);
auto out = cv::gapi::convertTo(in, depth_to, alpha, beta);
cv::GComputation c(in, out);
// Warm-up graph engine:
@@ -1832,7 +1859,7 @@ PERF_TEST_P_(ConvertToPerfTest, TestPerformance)
}
// Comparison ////////////////////////////////////////////////////////////
// FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
EXPECT_EQ(out_mat_gapi.size(), sz_in);
SANITY_CHECK_NOTHING();
@@ -1930,5 +1957,187 @@ PERF_TEST_P_(ResizeFxFyPerfTest, TestPerformance)
//------------------------------------------------------------------------------
PERF_TEST_P_(ParseSSDBLPerfTest, TestPerformance)
{
cv::Size sz;
float confidence_threshold = 0.0f;
int filter_label = 0;
cv::GCompileArgs compile_args;
std::tie(sz, confidence_threshold, filter_label, compile_args) = GetParam();
cv::Mat in_mat = generateSSDoutput(sz);
std::vector<cv::Rect> boxes_gapi, boxes_ref;
std::vector<int> labels_gapi, labels_ref;
// Reference code //////////////////////////////////////////////////////////
parseSSDBLref(in_mat, sz, confidence_threshold, filter_label, boxes_ref, labels_ref);
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
cv::GOpaque<cv::Size> op_sz;
auto out = cv::gapi::parseSSD(in, op_sz, confidence_threshold, filter_label);
cv::GComputation c(cv::GIn(in, op_sz), cv::GOut(std::get<0>(out), std::get<1>(out)));
// Warm-up graph engine:
auto cc = c.compile(descr_of(in_mat), descr_of(sz), std::move(compile_args));
cc(cv::gin(in_mat, sz), cv::gout(boxes_gapi, labels_gapi));
TEST_CYCLE()
{
cc(cv::gin(in_mat, sz), cv::gout(boxes_gapi, labels_gapi));
}
// Comparison ////////////////////////////////////////////////////////////
{
EXPECT_TRUE(boxes_gapi == boxes_ref);
EXPECT_TRUE(labels_gapi == labels_ref);
}
SANITY_CHECK_NOTHING();
}
//------------------------------------------------------------------------------
PERF_TEST_P_(ParseSSDPerfTest, TestPerformance)
{
cv::Size sz;
float confidence_threshold = 0;
bool alignment_to_square = false, filter_out_of_bounds = false;
cv::GCompileArgs compile_args;
std::tie(sz, confidence_threshold, alignment_to_square, filter_out_of_bounds, compile_args) = GetParam();
cv::Mat in_mat = generateSSDoutput(sz);
std::vector<cv::Rect> boxes_gapi, boxes_ref;
// Reference code //////////////////////////////////////////////////////////
parseSSDref(in_mat, sz, confidence_threshold, alignment_to_square, filter_out_of_bounds, boxes_ref);
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
cv::GOpaque<cv::Size> op_sz;
auto out = cv::gapi::parseSSD(in, op_sz, confidence_threshold, alignment_to_square, filter_out_of_bounds);
cv::GComputation c(cv::GIn(in, op_sz), cv::GOut(out));
// Warm-up graph engine:
auto cc = c.compile(descr_of(in_mat), descr_of(sz), std::move(compile_args));
cc(cv::gin(in_mat, sz), cv::gout(boxes_gapi));
TEST_CYCLE()
{
cc(cv::gin(in_mat, sz), cv::gout(boxes_gapi));
}
// Comparison ////////////////////////////////////////////////////////////
{
EXPECT_TRUE(boxes_gapi == boxes_ref);
}
SANITY_CHECK_NOTHING();
}
//------------------------------------------------------------------------------
PERF_TEST_P_(ParseYoloPerfTest, TestPerformance)
{
cv::Size sz;
float confidence_threshold = 0.0f, nms_threshold = 0.0f;
int num_classes = 0;
cv::GCompileArgs compile_args;
std::tie(sz, confidence_threshold, nms_threshold, num_classes, compile_args) = GetParam();
cv::Mat in_mat = generateYoloOutput(num_classes);
auto anchors = cv::gapi::nn::parsers::GParseYolo::defaultAnchors();
std::vector<cv::Rect> boxes_gapi, boxes_ref;
std::vector<int> labels_gapi, labels_ref;
// Reference code //////////////////////////////////////////////////////////
parseYoloRef(in_mat, sz, confidence_threshold, nms_threshold, num_classes, anchors, boxes_ref, labels_ref);
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
cv::GOpaque<cv::Size> op_sz;
auto out = cv::gapi::parseYolo(in, op_sz, confidence_threshold, nms_threshold, anchors);
cv::GComputation c(cv::GIn(in, op_sz), cv::GOut(std::get<0>(out), std::get<1>(out)));
// Warm-up graph engine:
auto cc = c.compile(descr_of(in_mat), descr_of(sz), std::move(compile_args));
cc(cv::gin(in_mat, sz), cv::gout(boxes_gapi, labels_gapi));
TEST_CYCLE()
{
cc(cv::gin(in_mat, sz), cv::gout(boxes_gapi, labels_gapi));
}
// Comparison ////////////////////////////////////////////////////////////
{
EXPECT_TRUE(boxes_gapi == boxes_ref);
EXPECT_TRUE(labels_gapi == labels_ref);
}
SANITY_CHECK_NOTHING();
}
//------------------------------------------------------------------------------
PERF_TEST_P_(SizePerfTest, TestPerformance)
{
MatType type;
cv::Size sz;
cv::GCompileArgs compile_args;
std::tie(type, sz, compile_args) = GetParam();
in_mat1 = cv::Mat(sz, type);
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
auto out = cv::gapi::size(in);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
cv::Size out_sz;
// Warm-up graph engine:
auto cc = c.compile(descr_of(in_mat1), std::move(compile_args));
cc(cv::gin(in_mat1), cv::gout(out_sz));
TEST_CYCLE()
{
cc(cv::gin(in_mat1), cv::gout(out_sz));
}
// Comparison ////////////////////////////////////////////////////////////
{
EXPECT_EQ(out_sz, sz);
}
SANITY_CHECK_NOTHING();
}
//------------------------------------------------------------------------------
PERF_TEST_P_(SizeRPerfTest, TestPerformance)
{
cv::Size sz;
cv::GCompileArgs compile_args;
std::tie(sz, compile_args) = GetParam();
cv::Rect rect(cv::Point(0,0), sz);
// G-API code //////////////////////////////////////////////////////////////
cv::GOpaque<cv::Rect> op_rect;
auto out = cv::gapi::size(op_rect);
cv::GComputation c(cv::GIn(op_rect), cv::GOut(out));
cv::Size out_sz;
// Warm-up graph engine:
auto cc = c.compile(descr_of(rect), std::move(compile_args));
cc(cv::gin(rect), cv::gout(out_sz));
TEST_CYCLE()
{
cc(cv::gin(rect), cv::gout(out_sz));
}
// Comparison ////////////////////////////////////////////////////////////
{
EXPECT_EQ(out_sz, sz);
}
SANITY_CHECK_NOTHING();
}
}
#endif // OPENCV_GAPI_CORE_PERF_TESTS_INL_HPP

View File

@@ -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-2020 Intel Corporation
#ifndef OPENCV_GAPI_IMGPROC_PERF_TESTS_HPP
@@ -20,31 +20,40 @@ namespace opencv_test
//------------------------------------------------------------------------------
class SepFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, int, cv::GCompileArgs>> {};
class Filter2DPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
class BoxFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
class BlurPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
class GaussianBlurPerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, cv::GCompileArgs>> {};
class MedianBlurPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size, cv::GCompileArgs>> {};
class ErodePerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
class Erode3x3PerfTest : public TestPerfParams<tuple<compare_f, MatType, cv::Size, int, cv::GCompileArgs>> {};
class DilatePerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
class Dilate3x3PerfTest : public TestPerfParams<tuple<compare_f, MatType,cv::Size,int, cv::GCompileArgs>> {};
class SobelPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int,int, cv::GCompileArgs>> {};
class SobelXYPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
class CannyPerfTest : public TestPerfParams<tuple<compare_f, MatType,cv::Size,double,double,int,bool, cv::GCompileArgs>> {};
class EqHistPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
class RGB2GrayPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
class BGR2GrayPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
class RGB2YUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
class YUV2RGBPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
class RGB2LabPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class BGR2LUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class LUV2BGRPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class BGR2YUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class YUV2BGRPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class RGB2HSVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class SepFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
class Filter2DPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
class BoxFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
class BlurPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
class GaussianBlurPerfTest : public TestPerfParams<tuple<compare_f, MatType,int, cv::Size, cv::GCompileArgs>> {};
class MedianBlurPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size, cv::GCompileArgs>> {};
class ErodePerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
class Erode3x3PerfTest : public TestPerfParams<tuple<compare_f, MatType,cv::Size,int, cv::GCompileArgs>> {};
class DilatePerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
class Dilate3x3PerfTest : public TestPerfParams<tuple<compare_f, MatType,cv::Size,int, cv::GCompileArgs>> {};
class SobelPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int,int, cv::GCompileArgs>> {};
class SobelXYPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
class LaplacianPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,
cv::GCompileArgs>> {};
class BilateralFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, double,double,
cv::GCompileArgs>> {};
class CannyPerfTest : public TestPerfParams<tuple<compare_f, MatType,cv::Size,double,double,int,bool,
cv::GCompileArgs>> {};
class GoodFeaturesPerfTest : public TestPerfParams<tuple<compare_vector_f<cv::Point2f>, std::string,
int,int,double,double,int,bool,
cv::GCompileArgs>> {};
class EqHistPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class RGB2GrayPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class BGR2GrayPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class RGB2YUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class YUV2RGBPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class RGB2LabPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class BGR2LUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class LUV2BGRPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class BGR2YUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class YUV2BGRPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class RGB2HSVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class BayerGR2RGBPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class RGB2YUV422PerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
}
} // opencv_test
#endif //OPENCV_GAPI_IMGPROC_PERF_TESTS_HPP

View File

@@ -2,15 +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-2019 Intel Corporation
// Copyright (C) 2018-2020 Intel Corporation
#ifndef OPENCV_GAPI_IMGPROC_PERF_TESTS_INL_HPP
#define OPENCV_GAPI_IMGPROC_PERF_TESTS_INL_HPP
#include <iostream>
#include "gapi_imgproc_perf_tests.hpp"
namespace opencv_test
@@ -579,6 +577,89 @@ PERF_TEST_P_(SobelXYPerfTest, TestPerformance)
//------------------------------------------------------------------------------
PERF_TEST_P_(LaplacianPerfTest, TestPerformance)
{
compare_f cmpF;
MatType type = 0;
int kernSize = 0, dtype = 0;
cv::Size sz;
cv::GCompileArgs compile_args;
std::tie(cmpF, type, kernSize, sz, dtype, compile_args) = GetParam();
initMatrixRandN(type, sz, dtype, false);
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::Laplacian(in_mat1, out_mat_ocv, dtype, kernSize);
}
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
auto out = cv::gapi::Laplacian(in, dtype, kernSize);
cv::GComputation c(in, out);
// Warm-up graph engine:
c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
TEST_CYCLE()
{
c.apply(in_mat1, out_mat_gapi);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
EXPECT_EQ(out_mat_gapi.size(), sz);
}
SANITY_CHECK_NOTHING();
}
//------------------------------------------------------------------------------
PERF_TEST_P_(BilateralFilterPerfTest, TestPerformance)
{
compare_f cmpF;
MatType type = 0;
int dtype = 0, d = 0, borderType = BORDER_DEFAULT;
double sigmaColor = 0, sigmaSpace = 0;
cv::Size sz;
cv::GCompileArgs compile_args;
std::tie(cmpF, type, dtype, sz, d, sigmaColor, sigmaSpace,
compile_args) = GetParam();
initMatrixRandN(type, sz, dtype, false);
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::bilateralFilter(in_mat1, out_mat_ocv, d, sigmaColor, sigmaSpace, borderType);
}
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
auto out = cv::gapi::bilateralFilter(in, d, sigmaColor, sigmaSpace, borderType);
cv::GComputation c(in, out);
// Warm-up graph engine:
c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
TEST_CYCLE()
{
c.apply(in_mat1, out_mat_gapi);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
EXPECT_EQ(out_mat_gapi.size(), sz);
}
SANITY_CHECK_NOTHING();
}
//------------------------------------------------------------------------------
PERF_TEST_P_(CannyPerfTest, TestPerformance)
{
compare_f cmpF;
@@ -622,6 +703,53 @@ PERF_TEST_P_(CannyPerfTest, TestPerformance)
//------------------------------------------------------------------------------
PERF_TEST_P_(GoodFeaturesPerfTest, TestPerformance)
{
double k = 0.04;
compare_vector_f<cv::Point2f> cmpF;
std::string fileName = "";
int type = -1, maxCorners = -1, blockSize = -1;
double qualityLevel = 0.0, minDistance = 0.0;
bool useHarrisDetector = false;
cv::GCompileArgs compileArgs;
std::tie(cmpF, fileName, type, maxCorners, qualityLevel,
minDistance, blockSize, useHarrisDetector, compileArgs) = GetParam();
initMatFromImage(type, fileName);
std::vector<cv::Point2f> outVecOCV, outVecGAPI;
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::goodFeaturesToTrack(in_mat1, outVecOCV, maxCorners, qualityLevel, minDistance,
cv::noArray(), blockSize, useHarrisDetector, k);
}
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
auto out = cv::gapi::goodFeaturesToTrack(in, maxCorners, qualityLevel, minDistance, cv::Mat(),
blockSize, useHarrisDetector, k);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
// Warm-up graph engine:
c.apply(cv::gin(in_mat1), cv::gout(outVecGAPI), std::move(compileArgs));
TEST_CYCLE()
{
c.apply(cv::gin(in_mat1), cv::gout(outVecGAPI));
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(outVecGAPI, outVecOCV));
}
SANITY_CHECK_NOTHING();
}
//------------------------------------------------------------------------------
PERF_TEST_P_(EqHistPerfTest, TestPerformance)
{
compare_f cmpF = get<0>(GetParam());

View File

@@ -0,0 +1,9 @@
// 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) 2020 Intel Corporation
#include "../perf_precomp.hpp"
#include "gapi_render_perf_tests_inl.hpp"

View File

@@ -0,0 +1,43 @@
// 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) 2020 Intel Corporation
#ifndef OPENCV_GAPI_RENDER_PERF_TESTS_HPP
#define OPENCV_GAPI_RENDER_PERF_TESTS_HPP
#include "../../test/common/gapi_tests_common.hpp"
#include <opencv2/gapi/render/render.hpp>
namespace opencv_test
{
using namespace perf;
class RenderTestFTexts : public TestPerfParams<tuple<std::wstring, cv::Size, cv::Point,
int, cv::Scalar, cv::GCompileArgs>> {};
class RenderTestTexts : public TestPerfParams<tuple<std::string, cv::Size, cv::Point,
int, cv::Scalar, int, int,
bool, cv::GCompileArgs>> {};
class RenderTestRects : public TestPerfParams<tuple<cv::Size, cv::Rect, cv::Scalar,
int, int, int, cv::GCompileArgs>> {};
class RenderTestCircles : public TestPerfParams<tuple<cv::Size, cv::Point, int,
cv::Scalar, int, int, int,
cv::GCompileArgs>> {};
class RenderTestLines : public TestPerfParams<tuple<cv::Size, cv::Point, cv::Point,
cv::Scalar, int, int, int,
cv::GCompileArgs>> {};
class RenderTestMosaics : public TestPerfParams<tuple<cv::Size, cv::Rect, int, int,
cv::GCompileArgs>> {};
class RenderTestImages : public TestPerfParams<tuple<cv::Size, cv::Rect, cv::Scalar, double,
cv::GCompileArgs>> {};
class RenderTestPolylines : public TestPerfParams<tuple<cv::Size, std::vector<cv::Point>,
cv::Scalar, int, int, int,
cv::GCompileArgs>> {};
class RenderTestPolyItems : public TestPerfParams<tuple<cv::Size, int, int, int, cv::GCompileArgs>> {};
}
#endif //OPENCV_GAPI_RENDER_PERF_TESTS_HPP

View File

@@ -0,0 +1,827 @@
// 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) 2020 Intel Corporation
#include "gapi_render_perf_tests.hpp"
namespace opencv_test
{
namespace {
void create_rand_mats(const cv::Size &size, MatType type, cv::Mat &ref_mat, cv::Mat &gapi_mat)
{
ref_mat.create(size, type);
cv::randu(ref_mat, cv::Scalar::all(0), cv::Scalar::all(255));
ref_mat.copyTo(gapi_mat);
};
} // namespace
PERF_TEST_P_(RenderTestFTexts, RenderFTextsPerformanceBGROCVTest)
{
std::wstring text;
cv::Size sz;
cv::Point org;
int fh = 0;
cv::Scalar color;
cv::GCompileArgs comp_args;
std::tie(text ,sz ,org ,fh ,color, comp_args) = GetParam();
MatType type = CV_8UC3;
cv::Mat gapi_mat, ref_mat;
create_rand_mats(sz, type, ref_mat, gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::FText{text, org, fh, color});
cv::GMat in;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
cv::GComputation comp(cv::GIn(in, arr),
cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
// Warm-up graph engine:
comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestFTexts, RenderFTextsPerformanceNV12OCVTest)
{
std::wstring text;
cv::Size sz;
cv::Point org;
int fh = 0;
cv::Scalar color;
cv::GCompileArgs comp_args;
std::tie(text ,sz ,org ,fh ,color, comp_args) = GetParam();
cv::Mat y_ref_mat, uv_ref_mat;
cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
y_out_gapi_mat, uv_out_gapi_mat;
create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::FText{text, org, fh, color});
cv::GMat y_in, uv_in, y_out, uv_out;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
// Warm-up graph engine:
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestTexts, RenderTextsPerformanceBGROCVTest)
{
cv::Point org;
int ff = 0;
int thick = 0;
int lt = 0;
double fs = 2.0;
cv::Scalar color;
bool blo = false;
std::string text;
cv::Size sz;
cv::GCompileArgs comp_args;
std::tie(text, sz, org, ff, color, thick, lt, blo, comp_args) = GetParam();
MatType type = CV_8UC3;
cv::Mat gapi_mat, ref_mat;
create_rand_mats(sz, type, ref_mat, gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Text{text, org, ff, fs, color, thick, lt, blo});
cv::GMat in;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
cv::GComputation comp(cv::GIn(in, arr),
cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
// Warm-up graph engine:
comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestTexts, RenderTextsPerformanceNV12OCVTest)
{
cv::Point org;
int ff = 0;
int thick = 0;
int lt = 0;
double fs = 2.0;
cv::Scalar color;
bool blo = false;
std::string text;
cv::Size sz;
cv::GCompileArgs comp_args;
std::tie(text, sz, org, ff, color, thick, lt, blo, comp_args) = GetParam();
cv::Mat y_ref_mat, uv_ref_mat;
cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
y_out_gapi_mat, uv_out_gapi_mat;
create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Text{text, org, ff, fs, color, thick, lt, blo});
cv::GMat y_in, uv_in, y_out, uv_out;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
// Warm-up graph engine:
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestRects, RenderRectsPerformanceBGROCVTest)
{
cv::Rect rect;
cv::Scalar color;
int thick = 0;
int lt = 0;
int shift = 0;
cv::Size sz;
cv::GCompileArgs comp_args;
std::tie(sz, rect, color, thick, lt, shift, comp_args) = GetParam();
MatType type = CV_8UC3;
cv::Mat gapi_mat, ref_mat;
create_rand_mats(sz, type, ref_mat, gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Rect{rect, color, thick, lt, shift});
cv::GMat in;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
cv::GComputation comp(cv::GIn(in, arr),
cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
// Warm-up graph engine:
comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestRects, RenderRectsPerformanceNV12OCVTest)
{
cv::Rect rect;
cv::Scalar color;
int thick = 0;
int lt = 0;
int shift = 0;
cv::Size sz;
cv::GCompileArgs comp_args;
std::tie(sz, rect, color, thick, lt, shift, comp_args) = GetParam();
cv::Mat y_ref_mat, uv_ref_mat;
cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
y_out_gapi_mat, uv_out_gapi_mat;
create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Rect{rect, color, thick, lt, shift});
cv::GMat y_in, uv_in, y_out, uv_out;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
// Warm-up graph engine:
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestCircles, RenderCirclesPerformanceBGROCVTest)
{
cv::Point center;
int radius;
cv::Scalar color;
int thick = 0;
int lt = 0;
int shift = 0;
cv::Size sz;
cv::GCompileArgs comp_args;
std::tie(sz, center, radius, color, thick, lt, shift, comp_args) = GetParam();
MatType type = CV_8UC3;
cv::Mat gapi_mat, ref_mat;
create_rand_mats(sz, type, ref_mat, gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Circle{center, radius, color, thick, lt, shift});
cv::GMat in;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
cv::GComputation comp(cv::GIn(in, arr),
cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
// Warm-up graph engine:
comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestCircles, RenderCirclesPerformanceNV12OCVTest)
{
cv::Point center;
int radius;
cv::Scalar color;
int thick = 0;
int lt = 0;
int shift = 0;
cv::Size sz;
cv::GCompileArgs comp_args;
std::tie(sz, center, radius, color, thick, lt, shift, comp_args) = GetParam();
cv::Mat y_ref_mat, uv_ref_mat;
cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
y_out_gapi_mat, uv_out_gapi_mat;
create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Circle{center, radius, color, thick, lt, shift});
cv::GMat y_in, uv_in, y_out, uv_out;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
// Warm-up graph engine:
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestLines, RenderLinesPerformanceBGROCVTest)
{
cv::Point pt1;
cv::Point pt2;
cv::Scalar color;
int thick = 0;
int lt = 0;
int shift = 0;
compare_f cmpF;
cv::Size sz;
cv::GCompileArgs comp_args;
std::tie(sz, pt1, pt2, color, thick, lt, shift, comp_args) = GetParam();
MatType type = CV_8UC3;
cv::Mat gapi_mat, ref_mat;
create_rand_mats(sz, type, ref_mat, gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Line{pt1, pt2, color, thick, lt, shift});
cv::GMat in;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
cv::GComputation comp(cv::GIn(in, arr),
cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
// Warm-up graph engine:
comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestLines, RenderLinesPerformanceNV12OCVTest)
{
cv::Point pt1;
cv::Point pt2;
cv::Scalar color;
int thick = 0;
int lt = 0;
int shift = 0;
compare_f cmpF;
cv::Size sz;
cv::GCompileArgs comp_args;
std::tie(sz, pt1, pt2, color, thick, lt, shift, comp_args) = GetParam();
cv::Mat y_ref_mat, uv_ref_mat;
cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
y_out_gapi_mat, uv_out_gapi_mat;
create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Line{pt1, pt2, color, thick, lt, shift});
cv::GMat y_in, uv_in, y_out, uv_out;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
// Warm-up graph engine:
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestMosaics, RenderMosaicsPerformanceBGROCVTest)
{
cv::Rect mos;
int cellsz = 0;
int decim = 0;
cv::Size sz;
cv::GCompileArgs comp_args;
std::tie(sz, mos, cellsz, decim, comp_args) = GetParam();
MatType type = CV_8UC3;
cv::Mat gapi_mat, ref_mat;
create_rand_mats(sz, type, ref_mat, gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Mosaic{mos, cellsz, decim});
cv::GMat in;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
cv::GComputation comp(cv::GIn(in, arr),
cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
// Warm-up graph engine:
comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestMosaics, RenderMosaicsPerformanceNV12OCVTest)
{
cv::Rect mos;
int cellsz = 0;
int decim = 0;
cv::Size sz;
cv::GCompileArgs comp_args;
std::tie(sz, mos, cellsz, decim, comp_args) = GetParam();
cv::Mat y_ref_mat, uv_ref_mat;
cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
y_out_gapi_mat, uv_out_gapi_mat;
create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Mosaic{mos, cellsz, decim});
cv::GMat y_in, uv_in, y_out, uv_out;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
// Warm-up graph engine:
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestImages, RenderImagesPerformanceBGROCVTest)
{
cv::Rect rect;
cv::Scalar color;
double transparency = 0.0;
cv::Size sz;
cv::GCompileArgs comp_args;
std::tie(sz, rect, color, transparency, comp_args) = GetParam();
MatType type = CV_8UC3;
cv::Mat gapi_mat, ref_mat;
create_rand_mats(sz, type, ref_mat, gapi_mat);
cv::Mat img(rect.size(), CV_8UC3, color);
cv::Mat alpha(rect.size(), CV_32FC1, transparency);
auto tl = rect.tl();
cv::Point org = {tl.x, tl.y + rect.size().height};
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Image{org, img, alpha});
cv::gapi::wip::draw::render(gapi_mat, prims);
cv::GMat in;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
cv::GComputation comp(cv::GIn(in, arr),
cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
// Warm-up graph engine:
comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestImages, RenderImagesPerformanceNV12OCVTest)
{
cv::Rect rect;
cv::Scalar color;
double transparency = 0.0;
cv::Size sz;
cv::GCompileArgs comp_args;
std::tie(sz, rect, color, transparency, comp_args) = GetParam();
cv::Mat y_ref_mat, uv_ref_mat;
cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
y_out_gapi_mat, uv_out_gapi_mat;
create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
cv::Mat img(rect.size(), CV_8UC3, color);
cv::Mat alpha(rect.size(), CV_32FC1, transparency);
auto tl = rect.tl();
cv::Point org = {tl.x, tl.y + rect.size().height};
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Image{org, img, alpha});
cv::GMat y_in, uv_in, y_out, uv_out;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
// Warm-up graph engine:
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestPolylines, RenderPolylinesPerformanceBGROCVTest)
{
std::vector<cv::Point> points;
cv::Scalar color;
int thick = 0;
int lt = 0;
int shift = 0;
cv::Size sz;
cv::GCompileArgs comp_args;
std::tie(sz, points, color, thick, lt, shift, comp_args) = GetParam();
MatType type = CV_8UC3;
cv::Mat gapi_mat, ref_mat;
create_rand_mats(sz, type, ref_mat, gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Poly{points, color, thick, lt, shift});
cv::GMat in;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
cv::GComputation comp(cv::GIn(in, arr),
cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
// Warm-up graph engine:
comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestPolylines, RenderPolylinesPerformanceNV12OCVTest)
{
std::vector<cv::Point> points;
cv::Scalar color;
int thick = 0;
int lt = 0;
int shift = 0;
cv::Size sz;
cv::GCompileArgs comp_args;
std::tie(sz, points, color, thick, lt, shift, comp_args) = GetParam();
cv::Mat y_ref_mat, uv_ref_mat;
cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
y_out_gapi_mat, uv_out_gapi_mat;
create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Poly{points, color, thick, lt, shift});
cv::GMat y_in, uv_in, y_out, uv_out;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
// Warm-up graph engine:
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestPolyItems, RenderPolyItemsPerformanceBGROCVTest)
{
cv::Size sz;
int rects_num = 0;
int text_num = 0;
int image_num = 0;
cv::GCompileArgs comp_args;
std::tie(sz, rects_num, text_num, image_num, comp_args) = GetParam();
int thick = 2;
int lt = LINE_8;
cv::Scalar color(100, 50, 150);
MatType type = CV_8UC3;
cv::Mat gapi_mat, ref_mat;
create_rand_mats(sz, type, ref_mat, gapi_mat);
cv::Mat gapi_out_mat(sz, type);
gapi_mat.copyTo(gapi_out_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
// Rects
int shift = 0;
for (int i = 0; i < rects_num; ++i) {
cv::Rect rect(200 + i, 200 + i, 200, 200);
prims.emplace_back(cv::gapi::wip::draw::Rect(rect, color, thick, lt, shift));
}
// Mosaic
int cellsz = 25;
int decim = 0;
for (int i = 0; i < rects_num; ++i) {
cv::Rect mos(200 + i, 200 + i, 200, 200);
prims.emplace_back(cv::gapi::wip::draw::Mosaic(mos, cellsz, decim));
}
// Text
std::string text = "Some text";
int ff = FONT_HERSHEY_SIMPLEX;
double fs = 2.0;
bool blo = false;
for (int i = 0; i < text_num; ++i) {
cv::Point org(200 + i, 200 + i);
prims.emplace_back(cv::gapi::wip::draw::Text(text, org, ff, fs, color, thick, lt, blo));
}
// Image
double transparency = 1.0;
cv::Rect rect_img(0 ,0 , 50, 50);
cv::Mat img(rect_img.size(), CV_8UC3, color);
cv::Mat alpha(rect_img.size(), CV_32FC1, transparency);
auto tl = rect_img.tl();
for (int i = 0; i < image_num; ++i) {
cv::Point org_img = {tl.x + i, tl.y + rect_img.size().height + i};
prims.emplace_back(cv::gapi::wip::draw::Image({org_img, img, alpha}));
}
cv::GMat in;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
cv::GComputation comp(cv::GIn(in, arr),
cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
// Warm-up graph engine:
comp.apply(gin(gapi_mat, prims), gout(gapi_out_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(gin(gapi_mat, prims), gout(gapi_out_mat));
}
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(RenderTestPolyItems, RenderPolyItemsPerformanceNV12OCVTest)
{
cv::Size sz;
int rects_num = 0;
int text_num = 0;
int image_num = 0;
cv::GCompileArgs comp_args;
std::tie(sz, rects_num, text_num, image_num, comp_args) = GetParam();
int thick = 2;
int lt = LINE_8;
cv::Scalar color(100, 50, 150);
cv::Mat y_ref_mat, uv_ref_mat;
cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
y_out_gapi_mat, uv_out_gapi_mat;
create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
// Rects
int shift = 0;
for (int i = 0; i < rects_num; ++i) {
cv::Rect rect(200 + i, 200 + i, 200, 200);
prims.emplace_back(cv::gapi::wip::draw::Rect(rect, color, thick, lt, shift));
}
// Mosaic
int cellsz = 25;
int decim = 0;
for (int i = 0; i < rects_num; ++i) {
cv::Rect mos(200 + i, 200 + i, 200, 200);
prims.emplace_back(cv::gapi::wip::draw::Mosaic(mos, cellsz, decim));
}
// Text
std::string text = "Some text";
int ff = FONT_HERSHEY_SIMPLEX;
double fs = 2.0;
bool blo = false;
for (int i = 0; i < text_num; ++i) {
cv::Point org(200 + i, 200 + i);
prims.emplace_back(cv::gapi::wip::draw::Text(text, org, ff, fs, color, thick, lt, blo));
}
// Image
double transparency = 1.0;
cv::Rect rect_img(0 ,0 , 50, 50);
cv::Mat img(rect_img.size(), CV_8UC3, color);
cv::Mat alpha(rect_img.size(), CV_32FC1, transparency);
auto tl = rect_img.tl();
for (int i = 0; i < image_num; ++i) {
cv::Point org_img = {tl.x + i, tl.y + rect_img.size().height + i};
prims.emplace_back(cv::gapi::wip::draw::Image({org_img, img, alpha}));
}
cv::GMat y_in, uv_in, y_out, uv_out;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
// Warm-up graph engine:
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
TEST_CYCLE()
{
comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
}
SANITY_CHECK_NOTHING();
}
} // namespace opencv_test

View File

@@ -0,0 +1,9 @@
// 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) 2020 Intel Corporation
#include "../perf_precomp.hpp"
#include "gapi_video_perf_tests_inl.hpp"

View File

@@ -0,0 +1,31 @@
// 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) 2020 Intel Corporation
#ifndef OPENCV_GAPI_VIDEO_PERF_TESTS_HPP
#define OPENCV_GAPI_VIDEO_PERF_TESTS_HPP
#include "../../test/common/gapi_video_tests_common.hpp"
namespace opencv_test
{
using namespace perf;
//------------------------------------------------------------------------------
class BuildOptFlowPyramidPerfTest : public TestPerfParams<tuple<std::string,int,int,bool,int,int,
bool,GCompileArgs>> {};
class OptFlowLKPerfTest : public TestPerfParams<tuple<std::string,int,tuple<int,int>,int,
cv::TermCriteria,cv::GCompileArgs>> {};
class OptFlowLKForPyrPerfTest : public TestPerfParams<tuple<std::string,int,tuple<int,int>,int,
cv::TermCriteria,bool,
cv::GCompileArgs>> {};
class BuildPyr_CalcOptFlow_PipelinePerfTest : public TestPerfParams<tuple<std::string,int,int,bool,
cv::GCompileArgs>> {};
} // opencv_test
#endif // OPENCV_GAPI_VIDEO_PERF_TESTS_HPP

View File

@@ -0,0 +1,159 @@
// 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) 2020 Intel Corporation
#ifndef OPENCV_GAPI_VIDEO_PERF_TESTS_INL_HPP
#define OPENCV_GAPI_VIDEO_PERF_TESTS_INL_HPP
#include <iostream>
#include "gapi_video_perf_tests.hpp"
namespace opencv_test
{
using namespace perf;
//------------------------------------------------------------------------------
PERF_TEST_P_(BuildOptFlowPyramidPerfTest, TestPerformance)
{
std::vector<Mat> outPyrOCV, outPyrGAPI;
int outMaxLevelOCV = 0, outMaxLevelGAPI = 0;
Scalar outMaxLevelSc;
BuildOpticalFlowPyramidTestParams params;
std::tie(params.fileName, params.winSize,
params.maxLevel, params.withDerivatives,
params.pyrBorder, params.derivBorder,
params.tryReuseInputImage, params.compileArgs) = GetParam();
BuildOpticalFlowPyramidTestOutput outOCV { outPyrOCV, outMaxLevelOCV };
BuildOpticalFlowPyramidTestOutput outGAPI { outPyrGAPI, outMaxLevelGAPI };
GComputation c = runOCVnGAPIBuildOptFlowPyramid(*this, params, outOCV, outGAPI);
declare.in(in_mat1).out(outPyrGAPI);
TEST_CYCLE()
{
c.apply(cv::gin(in_mat1), cv::gout(outPyrGAPI, outMaxLevelSc));
}
outMaxLevelGAPI = static_cast<int>(outMaxLevelSc[0]);
// Comparison //////////////////////////////////////////////////////////////
compareOutputPyramids(outOCV, outGAPI);
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(OptFlowLKPerfTest, TestPerformance)
{
std::vector<cv::Point2f> outPtsOCV, outPtsGAPI, inPts;
std::vector<uchar> outStatusOCV, outStatusGAPI;
std::vector<float> outErrOCV, outErrGAPI;
OptFlowLKTestParams params;
std::tie(params.fileNamePattern, params.channels,
params.pointsNum, params.winSize, params.criteria,
params.compileArgs) = GetParam();
OptFlowLKTestOutput outOCV { outPtsOCV, outStatusOCV, outErrOCV };
OptFlowLKTestOutput outGAPI { outPtsGAPI, outStatusGAPI, outErrGAPI };
cv::GComputation c = runOCVnGAPIOptFlowLK(*this, inPts, params, outOCV, outGAPI);
declare.in(in_mat1, in_mat2, inPts).out(outPtsGAPI, outStatusGAPI, outErrGAPI);
TEST_CYCLE()
{
c.apply(cv::gin(in_mat1, in_mat2, inPts, std::vector<cv::Point2f>{ }),
cv::gout(outPtsGAPI, outStatusGAPI, outErrGAPI));
}
// Comparison //////////////////////////////////////////////////////////////
compareOutputsOptFlow(outOCV, outGAPI);
SANITY_CHECK_NOTHING();
}
//------------------------------------------------------------------------------
PERF_TEST_P_(OptFlowLKForPyrPerfTest, TestPerformance)
{
std::vector<cv::Mat> inPyr1, inPyr2;
std::vector<cv::Point2f> outPtsOCV, outPtsGAPI, inPts;
std::vector<uchar> outStatusOCV, outStatusGAPI;
std::vector<float> outErrOCV, outErrGAPI;
bool withDeriv = false;
OptFlowLKTestParams params;
std::tie(params.fileNamePattern, params.channels,
params.pointsNum, params.winSize, params.criteria,
withDeriv, params.compileArgs) = GetParam();
OptFlowLKTestInput<std::vector<cv::Mat>> in { inPyr1, inPyr2, inPts };
OptFlowLKTestOutput outOCV { outPtsOCV, outStatusOCV, outErrOCV };
OptFlowLKTestOutput outGAPI { outPtsGAPI, outStatusGAPI, outErrGAPI };
cv::GComputation c = runOCVnGAPIOptFlowLKForPyr(*this, in, params, withDeriv, outOCV, outGAPI);
declare.in(inPyr1, inPyr2, inPts).out(outPtsGAPI, outStatusGAPI, outErrGAPI);
TEST_CYCLE()
{
c.apply(cv::gin(inPyr1, inPyr2, inPts, std::vector<cv::Point2f>{ }),
cv::gout(outPtsGAPI, outStatusGAPI, outErrGAPI));
}
// Comparison //////////////////////////////////////////////////////////////
compareOutputsOptFlow(outOCV, outGAPI);
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(BuildPyr_CalcOptFlow_PipelinePerfTest, TestPerformance)
{
std::vector<Point2f> outPtsOCV, outPtsGAPI, inPts;
std::vector<uchar> outStatusOCV, outStatusGAPI;
std::vector<float> outErrOCV, outErrGAPI;
BuildOpticalFlowPyramidTestParams params;
params.pyrBorder = BORDER_DEFAULT;
params.derivBorder = BORDER_DEFAULT;
params.tryReuseInputImage = true;
std::tie(params.fileName, params.winSize,
params.maxLevel, params.withDerivatives,
params.compileArgs) = GetParam();
auto customKernel = gapi::kernels<GCPUMinScalar>();
auto kernels = gapi::combine(customKernel,
params.compileArgs[0].get<gapi::GKernelPackage>());
params.compileArgs = compile_args(kernels);
OptFlowLKTestOutput outOCV { outPtsOCV, outStatusOCV, outErrOCV };
OptFlowLKTestOutput outGAPI { outPtsGAPI, outStatusGAPI, outErrGAPI };
cv::GComputation c = runOCVnGAPIOptFlowPipeline(*this, params, outOCV, outGAPI, inPts);
declare.in(in_mat1, in_mat2, inPts).out(outPtsGAPI, outStatusGAPI, outErrGAPI);
TEST_CYCLE()
{
c.apply(cv::gin(in_mat1, in_mat2, inPts, std::vector<cv::Point2f>{ }),
cv::gout(outPtsGAPI, outStatusGAPI, outErrGAPI));
}
// Comparison //////////////////////////////////////////////////////////////
compareOutputsOptFlow(outOCV, outGAPI);
SANITY_CHECK_NOTHING();
}
//------------------------------------------------------------------------------
} // opencv_test
#endif // OPENCV_GAPI_VIDEO_PERF_TESTS_INL_HPP

View File

@@ -110,16 +110,18 @@ INSTANTIATE_TEST_CASE_P(CmpPerfTestCPU, CmpPerfTest,
Values(cv::compile_args(CORE_CPU))));
INSTANTIATE_TEST_CASE_P(CmpWithScalarPerfTestCPU, CmpWithScalarPerfTest,
Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
Values(cv::compile_args(CORE_CPU))));
Combine(Values(AbsExact().to_compare_f()),
Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
Values(cv::compile_args(CORE_CPU))));
INSTANTIATE_TEST_CASE_P(BitwisePerfTestCPU, BitwisePerfTest,
Combine(Values(AND, OR, XOR),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
Values(cv::compile_args(CORE_CPU))));
testing::Bool(),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
Values(cv::compile_args(CORE_CPU))));
INSTANTIATE_TEST_CASE_P(BitwiseNotPerfTestCPU, BitwiseNotPerfTest,
Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
@@ -266,10 +268,13 @@ INSTANTIATE_TEST_CASE_P(LUTPerfTestCustomCPU, LUTPerfTest,
INSTANTIATE_TEST_CASE_P(ConvertToPerfTestCPU, ConvertToPerfTest,
Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_32FC1),
Values(CV_8U, CV_16U, CV_16S, CV_32F),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(cv::compile_args(CORE_CPU))));
Combine(Values(AbsExact().to_compare_f()),
Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1),
Values(CV_8U, CV_16U, CV_16S, CV_32F),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(2.5, 1.0),
Values(0.0),
Values(cv::compile_args(CORE_CPU))));
INSTANTIATE_TEST_CASE_P(ResizePerfTestCPU, ResizePerfTest,
Combine(Values(AbsExact().to_compare_f()),
@@ -288,4 +293,33 @@ INSTANTIATE_TEST_CASE_P(ResizeFxFyPerfTestCPU, ResizeFxFyPerfTest,
Values(0.5, 0.1),
Values(0.5, 0.1),
Values(cv::compile_args(CORE_CPU))));
INSTANTIATE_TEST_CASE_P(ParseSSDBLPerfTestCPU, ParseSSDBLPerfTest,
Combine(Values(sz720p, sz1080p),
Values(0.3f, 0.7f),
Values(0, 1),
Values(cv::compile_args(CORE_CPU))));
INSTANTIATE_TEST_CASE_P(ParseSSDPerfTestCPU, ParseSSDPerfTest,
Combine(Values(sz720p, sz1080p),
Values(0.3f, 0.7f),
testing::Bool(),
testing::Bool(),
Values(cv::compile_args(CORE_CPU))));
INSTANTIATE_TEST_CASE_P(ParseYoloPerfTestCPU, ParseYoloPerfTest,
Combine(Values(sz720p, sz1080p),
Values(0.3f, 0.7f),
Values(0.5),
Values(7, 80),
Values(cv::compile_args(CORE_CPU))));
INSTANTIATE_TEST_CASE_P(SizePerfTestCPU, SizePerfTest,
Combine(Values(CV_8UC1, CV_8UC3, CV_32FC1),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(cv::compile_args(CORE_CPU))));
INSTANTIATE_TEST_CASE_P(SizeRPerfTestCPU, SizeRPerfTest,
Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
Values(cv::compile_args(CORE_CPU))));
} // opencv_test

View File

@@ -0,0 +1,299 @@
// 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) 2020 Intel Corporation
#include "../perf_precomp.hpp"
#include "../common/gapi_core_perf_tests.hpp"
#define CORE_FLUID cv::gapi::core::fluid::kernels()
namespace opencv_test
{
INSTANTIATE_TEST_CASE_P(AddPerfTestFluid, AddPerfTest,
Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_8UC1, CV_8UC3, CV_16SC1, CV_32FC1),
Values(-1, CV_8U, CV_32F),
Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(AddCPerfTestFluid, AddCPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(-1, CV_8U, CV_16U, CV_32F),
// Values(cv::compile_args(CORE_FLUID))));
INSTANTIATE_TEST_CASE_P(SubPerfTestFluid, SubPerfTest,
Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_8UC1, CV_8UC3, CV_16SC1, CV_32FC1),
Values(-1, CV_8U, CV_32F),
Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(SubCPerfTestFluid, SubCPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(-1, CV_8U, CV_16U, CV_32F),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(SubRCPerfTestFluid, SubRCPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(-1, CV_8U, CV_16U, CV_32F),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(MulPerfTestFluid, MulPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(-1, CV_8U, CV_16U, CV_32F),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(MulDoublePerfTestFluid, MulDoublePerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(-1, CV_8U, CV_16U, CV_32F),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(MulCPerfTestFluid, MulCPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(-1, CV_8U, CV_16U, CV_32F),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(DivPerfTestFluid, DivPerfTest,
// Combine(Values(AbsExact().to_compare_f()),
// Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(-1, CV_8U, CV_16U, CV_32F),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(DivCPerfTestFluid, DivCPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(-1, CV_8U, CV_16U, CV_32F),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(DivRCPerfTestFluid, DivRCPerfTest,
// Combine(Values(AbsExact().to_compare_f()),
// Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(-1, CV_8U, CV_16U, CV_32F),
// Values(cv::compile_args(CORE_FLUID))));
INSTANTIATE_TEST_CASE_P(MaskPerfTestFluid, MaskPerfTest,
Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_8UC1, CV_16UC1, CV_16SC1),
Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(MeanPerfTestFluid, MeanPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(Polar2CartPerfTestFluid, Polar2CartPerfTest,
// Combine(Values(AbsExact().to_compare_f()),
// Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(Cart2PolarPerfTestFluid, Cart2PolarPerfTest,
// Combine(Values(AbsExact().to_compare_f()),
// Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(CmpPerfTestFluid, CmpPerfTest,
// Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
// Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::compile_args(CORE_FLUID))));
INSTANTIATE_TEST_CASE_P(CmpWithScalarPerfTestFluid, CmpWithScalarPerfTest,
Combine(Values(AbsSimilarPoints(1, 0.01).to_compare_f()),
Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_8UC1, CV_8UC3, CV_16SC1, CV_32FC1),
Values(cv::compile_args(CORE_FLUID))));
INSTANTIATE_TEST_CASE_P(BitwisePerfTestFluid, BitwisePerfTest,
Combine(Values(AND, OR, XOR),
testing::Bool(),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
Values(cv::compile_args(CORE_FLUID))));
INSTANTIATE_TEST_CASE_P(BitwiseNotPerfTestFluid, BitwiseNotPerfTest,
Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(SelectPerfTestFluid, SelectPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(MinPerfTestFluid, MinPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(MaxPerfTestFluid, MaxPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::compile_args(CORE_FLUID))));
INSTANTIATE_TEST_CASE_P(AbsDiffPerfTestFluid, AbsDiffPerfTest,
Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
Values(cv::compile_args(CORE_FLUID))));
INSTANTIATE_TEST_CASE_P(AbsDiffCPerfTestFluid, AbsDiffCPerfTest,
Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(SumPerfTestFluid, SumPerfTest,
// Combine(Values(AbsToleranceScalar(0.0).to_compare_f()),
// Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// //Values(0.0),
// Values(cv::compile_args(CORE_FLUID))));
INSTANTIATE_TEST_CASE_P(AddWeightedPerfTestFluid, AddWeightedPerfTest,
Combine(Values(Tolerance_FloatRel_IntAbs(1e-6, 1).to_compare_f()),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
Values(-1, CV_8U, CV_32F),
Values(cv::compile_args(CORE_FLUID))));
INSTANTIATE_TEST_CASE_P(AddWeightedPerfTestFluid_short, AddWeightedPerfTest,
Combine(Values(Tolerance_FloatRel_IntAbs(1e-6, 1).to_compare_f()),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_16UC1, CV_16SC1),
Values(-1),
Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(NormPerfTestFluid, NormPerfTest,
// Combine(Values(AbsToleranceScalar(0.0).to_compare_f()),
// Values(NORM_INF, NORM_L1, NORM_L2),
// Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(IntegralPerfTestFluid, IntegralPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(ThresholdPerfTestFluid, ThresholdPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::THRESH_BINARY, cv::THRESH_BINARY_INV, cv::THRESH_TRUNC, cv::THRESH_TOZERO, cv::THRESH_TOZERO_INV),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(ThresholdPerfTestFluid, ThresholdOTPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1),
// Values(cv::THRESH_OTSU, cv::THRESH_TRIANGLE),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(InRangePerfTestFluid, InRangePerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1),
// Values(cv::compile_args(CORE_FLUID))));
INSTANTIATE_TEST_CASE_P(Split3PerfTestFluid, Split3PerfTest,
Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(Split4PerfTestFluid, Split4PerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(Merge3PerfTestFluid, Merge3PerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(Merge4PerfTestFluid, Merge4PerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(RemapPerfTestFluid, RemapPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(FlipPerfTestFluid, FlipPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(0, 1, -1),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(CropPerfTestFluid, CropPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::Rect(10, 8, 20, 35), cv::Rect(4, 10, 37, 50)),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(CopyPerfTestFluid, CopyPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(ConcatHorPerfTestFluid, ConcatHorPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(ConcatHorVecPerfTestFluid, ConcatHorVecPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(ConcatVertPerfTestFluid, ConcatVertPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(ConcatVertVecPerfTestFluid, ConcatVertVecPerfTest,
// Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(LUTPerfTestFluid, LUTPerfTest,
// Combine(Values(CV_8UC1, CV_8UC3),
// Values(CV_8UC1),
// Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(cv::compile_args(CORE_FLUID))));
// INSTANTIATE_TEST_CASE_P(LUTPerfTestCustomFluid, LUTPerfTest,
// Combine(Values(CV_8UC3),
// Values(CV_8UC3),
// Values(szSmall128, szVGA, sz720p, sz1080p),
// Values(cv::compile_args(CORE_FLUID))));
INSTANTIATE_TEST_CASE_P(ConvertToPerfTestFluid, ConvertToPerfTest,
Combine(Values(Tolerance_FloatRel_IntAbs(1e-5, 2).to_compare_f()),
Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1),
Values(CV_8U, CV_16U, CV_16S, CV_32F),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(2.5, 1.0),
Values(0.0),
Values(cv::compile_args(CORE_FLUID))));
INSTANTIATE_TEST_CASE_P(ResizePerfTestFluid, ResizePerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values(CV_8UC3/*CV_8UC1, CV_16UC1, CV_16SC1*/),
Values(/*cv::INTER_NEAREST,*/ cv::INTER_LINEAR/*, cv::INTER_AREA*/),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(cv::Size(64, 64),
cv::Size(30, 30)),
Values(cv::compile_args(CORE_FLUID))));
INSTANTIATE_TEST_CASE_P(ResizeFxFyPerfTestFluid, ResizeFxFyPerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values(CV_8UC3/*CV_8UC1, CV_16UC1, CV_16SC1*/),
Values(/*cv::INTER_NEAREST,*/ cv::INTER_LINEAR/*, cv::INTER_AREA*/),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(0.5, 0.1),
Values(0.5, 0.1),
Values(cv::compile_args(CORE_FLUID))));
} // opencv_test

View File

@@ -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-2020 Intel Corporation
#include "../perf_precomp.hpp"
@@ -124,6 +124,24 @@ INSTANTIATE_TEST_CASE_P(SobelPerfTestCPU32F, SobelPerfTest,
Values(1, 2),
Values(cv::compile_args(IMGPROC_CPU))));
INSTANTIATE_TEST_CASE_P(LaplacianPerfTestCPU, LaplacianPerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values(CV_8UC1, CV_8UC3),
Values(3),
Values(szVGA, sz720p, sz1080p),
Values(-1),
Values(cv::compile_args(IMGPROC_CPU))));
INSTANTIATE_TEST_CASE_P(BilateralFilterPerfTestCPU, BilateralFilterPerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values(CV_32FC1, CV_32FC3),
Values(-1),
Values(szVGA, sz720p, sz1080p),
Values(3),
Values(20),
Values(10),
Values(cv::compile_args(IMGPROC_CPU))));
INSTANTIATE_TEST_CASE_P(CannyPerfTestCPU, CannyPerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values(CV_8UC1, CV_8UC3),
@@ -134,6 +152,28 @@ INSTANTIATE_TEST_CASE_P(CannyPerfTestCPU, CannyPerfTest,
Values(true, false),
Values(cv::compile_args(IMGPROC_CPU))));
INSTANTIATE_TEST_CASE_P(GoodFeaturesPerfTestCPU, GoodFeaturesPerfTest,
Combine(Values(AbsExactVector<cv::Point2f>().to_compare_f()),
Values("cv/shared/pic5.png", "stitching/a1.png"),
Values(CV_32FC1, CV_8UC1),
Values(100, 500),
Values(0.1, 0.01),
Values(1.0),
Values(3, 5),
Values(true, false),
Values(cv::compile_args(IMGPROC_CPU))));
INSTANTIATE_TEST_CASE_P(GoodFeaturesInternalPerfTestCPU, GoodFeaturesPerfTest,
Combine(Values(AbsExactVector<cv::Point2f>().to_compare_f()),
Values("cv/cascadeandhog/images/audrybt1.png"),
Values(CV_32FC1, CV_8UC1),
Values(100),
Values(0.0000001),
Values(5.0),
Values(3),
Values(true),
Values(cv::compile_args(IMGPROC_CPU))));
INSTANTIATE_TEST_CASE_P(EqHistPerfTestCPU, EqHistPerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values(szVGA, sz720p, sz1080p),
@@ -198,4 +238,4 @@ INSTANTIATE_TEST_CASE_P(RGB2YUV422PerfTestCPU, RGB2YUV422PerfTest,
Combine(Values(ToleranceColor(1e-3).to_compare_f()),
Values(szVGA, sz720p, sz1080p),
Values(cv::compile_args(IMGPROC_CPU))));
}
} // opencv_test

View File

@@ -0,0 +1,103 @@
// 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) 2020 Intel Corporation
#include "../perf_precomp.hpp"
#include "../common/gapi_video_perf_tests.hpp"
#include <opencv2/gapi/cpu/video.hpp>
namespace
{
#define VIDEO_CPU cv::gapi::video::cpu::kernels()
#ifdef HAVE_OPENCV_VIDEO
#define WITH_VIDEO(X) X
#else
#define WITH_VIDEO(X) DISABLED_##X
#endif // HAVE_OPENCV_VIDEO
#define INSTANTIATE_TEST_CASE_MACRO_P(prefix, test_case_name, generator, ...) \
INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator, __VA_ARGS__)
} // namespace
namespace opencv_test
{
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildOptFlowPyramidPerfTestCPU),
BuildOptFlowPyramidPerfTest,
Combine(Values("cv/optflow/rock_1.bmp",
"cv/optflow/frames/1080p_01.png"),
Values(7, 11),
Values(1000),
testing::Bool(),
Values(BORDER_DEFAULT, BORDER_TRANSPARENT),
Values(BORDER_DEFAULT, BORDER_TRANSPARENT),
testing::Bool(),
Values(cv::compile_args(VIDEO_CPU))));
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildOptFlowPyramidInternalPerfTestCPU),
BuildOptFlowPyramidPerfTest,
Combine(Values("cv/optflow/rock_1.bmp"),
Values(15),
Values(3),
Values(true),
Values(BORDER_REFLECT_101),
Values(BORDER_CONSTANT),
Values(true),
Values(cv::compile_args(VIDEO_CPU))));
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(OptFlowLKPerfTestCPU), OptFlowLKPerfTest,
Combine(Values("cv/optflow/rock_%01d.bmp",
"cv/optflow/frames/1080p_%02d.png"),
Values(1, 3, 4),
Values(std::make_tuple(9, 9), std::make_tuple(15, 15)),
Values(7, 11),
Values(cv::TermCriteria(cv::TermCriteria::COUNT |
cv::TermCriteria::EPS,
30, 0.01)),
Values(cv::compile_args(VIDEO_CPU))));
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(OptFlowLKForPyrPerfTestCPU), OptFlowLKForPyrPerfTest,
Combine(Values("cv/optflow/rock_%01d.bmp",
"cv/optflow/frames/1080p_%02d.png"),
Values(1, 3, 4),
Values(std::make_tuple(9, 9), std::make_tuple(15, 15)),
Values(7, 11),
Values(cv::TermCriteria(cv::TermCriteria::COUNT |
cv::TermCriteria::EPS,
30, 0.01)),
Values(true, false),
Values(cv::compile_args(VIDEO_CPU))));
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(OptFlowLKInternalPerfTestCPU),
OptFlowLKForPyrPerfTest,
Combine(Values("cv/optflow/rock_%01d.bmp"),
Values(1),
Values(std::make_tuple(10, 10)),
Values(15),
Values(cv::TermCriteria(cv::TermCriteria::COUNT |
cv::TermCriteria::EPS,
21, 0.05)),
Values(true),
Values(cv::compile_args(VIDEO_CPU))));
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildPyr_CalcOptFlow_PipelinePerfTestCPU),
BuildPyr_CalcOptFlow_PipelinePerfTest,
Combine(Values("cv/optflow/frames/1080p_%02d.png"),
Values(7, 11),
Values(1000),
Values(true, false),
Values(cv::compile_args(VIDEO_CPU))));
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildPyr_CalcOptFlow_PipelineInternalTestPerfCPU),
BuildPyr_CalcOptFlow_PipelinePerfTest,
Combine(Values("cv/optflow/rock_%01d.bmp"),
Values(15),
Values(3),
Values(true),
Values(cv::compile_args(VIDEO_CPU))));
} // opencv_test

View File

@@ -81,12 +81,10 @@ INSTANTIATE_TEST_CASE_P(DivRCPerfTestGPU, DivRCPerfTest,
Values( -1, CV_8U, CV_16U, CV_32F ),
Values(cv::compile_args(CORE_GPU))));
//TODO: mask test doesn't work
#if 0
INSTANTIATE_TEST_CASE_P(MaskPerfTestGPU, MaskPerfTest,
INSTANTIATE_TEST_CASE_P(DISABLED_MaskPerfTestGPU, MaskPerfTest,
Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
Values( CV_8UC1, CV_16UC1, CV_16SC1),
Values(cv::compile_args(CORE_GPU))));
#endif
INSTANTIATE_TEST_CASE_P(MeanPerfTestGPU, MeanPerfTest,
Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
@@ -110,13 +108,15 @@ INSTANTIATE_TEST_CASE_P(CmpPerfTestGPU, CmpPerfTest,
Values(cv::compile_args(CORE_GPU))));
INSTANTIATE_TEST_CASE_P(CmpWithScalarPerfTestGPU, CmpWithScalarPerfTest,
Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
Combine(Values(AbsExact().to_compare_f()),
Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
Values( szSmall128, szVGA, sz720p, sz1080p ),
Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
Values(cv::compile_args(CORE_GPU))));
INSTANTIATE_TEST_CASE_P(BitwisePerfTestGPU, BitwisePerfTest,
Combine(Values(AND, OR, XOR),
testing::Bool(),
Values( szSmall128, szVGA, sz720p, sz1080p ),
Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
Values(cv::compile_args(CORE_GPU))));
@@ -242,18 +242,16 @@ INSTANTIATE_TEST_CASE_P(ConcatVertPerfTestGPU, ConcatVertPerfTest,
Values(cv::compile_args(CORE_GPU))));
//TODO: fix this backend to allow ConcatVertVec ConcatHorVec
#if 0
INSTANTIATE_TEST_CASE_P(ConcatHorVecPerfTestGPU, ConcatHorVecPerfTest,
INSTANTIATE_TEST_CASE_P(DISABLED_ConcatHorVecPerfTestGPU, ConcatHorVecPerfTest,
Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
Values(cv::compile_args(CORE_GPU))));
INSTANTIATE_TEST_CASE_P(ConcatVertVecPerfTestGPU, ConcatVertVecPerfTest,
INSTANTIATE_TEST_CASE_P(DISABLED_ConcatVertVecPerfTestGPU, ConcatVertVecPerfTest,
Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
Values(cv::compile_args(CORE_GPU))));
#endif
INSTANTIATE_TEST_CASE_P(LUTPerfTestGPU, LUTPerfTest,
Combine(Values(CV_8UC1, CV_8UC3),
@@ -269,9 +267,12 @@ INSTANTIATE_TEST_CASE_P(LUTPerfTestCustomGPU, LUTPerfTest,
INSTANTIATE_TEST_CASE_P(ConvertToPerfTestGPU, ConvertToPerfTest,
Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_32FC1),
Combine(Values(AbsExact().to_compare_f()),
Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_32FC1),
Values(CV_8U, CV_16U, CV_16S, CV_32F),
Values( szSmall128, szVGA, sz720p, sz1080p ),
Values(2.5, 1.0),
Values(0.0),
Values(cv::compile_args(CORE_GPU))));
INSTANTIATE_TEST_CASE_P(ResizePerfTestGPU, ResizePerfTest,

View File

@@ -126,6 +126,24 @@ INSTANTIATE_TEST_CASE_P(SobelPerfTestGPU32F, SobelPerfTest,
Values(1, 2),
Values(cv::compile_args(IMGPROC_GPU))));
INSTANTIATE_TEST_CASE_P(LaplacianPerfTestGPU, LaplacianPerfTest,
Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
Values(CV_8UC1, CV_8UC3),
Values(5),
Values(szVGA, sz720p, sz1080p),
Values(-1),
Values(cv::compile_args(IMGPROC_GPU))));
INSTANTIATE_TEST_CASE_P(BilateralFilterPerfTestGPU, BilateralFilterPerfTest,
Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
Values(CV_32FC1, CV_32FC3),
Values(-1),
Values(szVGA, sz720p, sz1080p),
Values(5),
Values(100),
Values(40),
Values(cv::compile_args(IMGPROC_GPU))));
INSTANTIATE_TEST_CASE_P(CannyPerfTestGPU, CannyPerfTest,
Combine(Values(AbsSimilarPoints(1, 0.05).to_compare_f()),
Values(CV_8UC1, CV_8UC3),

View File

@@ -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-2020 Intel Corporation
#ifndef __OPENCV_GAPI_PERF_PRECOMP_HPP__
@@ -14,6 +14,7 @@
#include <opencv2/ts.hpp>
#include <opencv2/gapi.hpp>
#include <opencv2/gapi/imgproc.hpp>
#include <opencv2/gapi/video.hpp>
#include <opencv2/gapi/core.hpp>
#include <opencv2/gapi/cpu/gcpukernel.hpp>
#include <opencv2/gapi/gpu/ggpukernel.hpp>

View File

@@ -0,0 +1,95 @@
// 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) 2020 Intel Corporation
#include "../perf_precomp.hpp"
#include "../common/gapi_render_perf_tests.hpp"
#define RENDER_OCV cv::gapi::render::ocv::kernels()
namespace opencv_test
{
#ifdef HAVE_FREETYPE
INSTANTIATE_TEST_CASE_P(RenderTestFTexts, RenderTestFTexts,
Combine(Values(L"\xe4\xbd\xa0\xe5\xa5\xbd"),
Values(szVGA, sz720p, sz1080p),
Values(cv::Point(50, 50)),
Values(60),
Values(cv::Scalar(200, 100, 25)),
Values(cv::compile_args(RENDER_OCV))));
#endif // HAVE_FREETYPE
INSTANTIATE_TEST_CASE_P(RenderTestTexts, RenderTestTexts,
Combine(Values(std::string("Some text")),
Values(szVGA, sz720p, sz1080p),
Values(cv::Point(200, 200)),
Values(FONT_HERSHEY_SIMPLEX),
Values(cv::Scalar(0, 255, 0)),
Values(2),
Values(LINE_8),
Values(false),
Values(cv::compile_args(RENDER_OCV))));
INSTANTIATE_TEST_CASE_P(RenderTestRects, RenderTestRects,
Combine(Values(szVGA, sz720p, sz1080p),
Values(cv::Rect(100, 100, 200, 200)),
Values(cv::Scalar(100, 50, 150)),
Values(2),
Values(LINE_8),
Values(0),
Values(cv::compile_args(RENDER_OCV))));
INSTANTIATE_TEST_CASE_P(RenderTestCircles, RenderTestCircles,
Combine(Values(szVGA, sz720p, sz1080p),
Values(cv::Point(100, 100)),
Values(10),
Values(cv::Scalar(100, 50, 150)),
Values(2),
Values(LINE_8),
Values(0),
Values(cv::compile_args(RENDER_OCV))));
INSTANTIATE_TEST_CASE_P(RenderTestLines, RenderTestLines,
Combine(Values(szVGA, sz720p, sz1080p),
Values(cv::Point(100, 100)),
Values(cv::Point(200, 200)),
Values(cv::Scalar(100, 50, 150)),
Values(2),
Values(LINE_8),
Values(0),
Values(cv::compile_args(RENDER_OCV))));
INSTANTIATE_TEST_CASE_P(RenderTestMosaics, RenderTestMosaics,
Combine(Values(szVGA, sz720p, sz1080p),
Values(cv::Rect(100, 100, 200, 200)),
Values(25),
Values(0),
Values(cv::compile_args(RENDER_OCV))));
INSTANTIATE_TEST_CASE_P(RenderTestImages, RenderTestImages,
Combine(Values(szVGA, sz720p, sz1080p),
Values(cv::Rect(50, 50, 100, 100)),
Values(cv::Scalar(100, 150, 60)),
Values(1.0),
Values(cv::compile_args(RENDER_OCV))));
INSTANTIATE_TEST_CASE_P(RenderTestPolylines, RenderTestPolylines,
Combine(Values(szVGA, sz720p, sz1080p),
Values(std::vector<cv::Point>{{100, 100}, {200, 200}, {150, 300}, {400, 150}}),
Values(cv::Scalar(100, 150, 60)),
Values(2),
Values(LINE_8),
Values(0),
Values(cv::compile_args(RENDER_OCV))));
INSTANTIATE_TEST_CASE_P(RenderTestPolyItems, RenderTestPolyItems,
Combine(Values(szVGA, sz720p, sz1080p),
Values(50),
Values(50),
Values(50),
Values(cv::compile_args(RENDER_OCV))));
}

View File

@@ -0,0 +1,68 @@
#include <opencv2/gapi.hpp>
#include <opencv2/gapi/core.hpp>
#include <opencv2/gapi/cpu/core.hpp>
int main(int argc, char *argv[])
{
(void) argc;
(void) argv;
bool need_first_conversion = true;
bool need_second_conversion = false;
cv::Size szOut(4, 4);
cv::GComputation cc([&](){
// ! [GIOProtoArgs usage]
auto ins = cv::GIn();
cv::GMat in1;
if (need_first_conversion)
ins += cv::GIn(in1);
cv::GMat in2;
if (need_second_conversion)
ins += cv::GIn(in2);
auto outs = cv::GOut();
cv::GMat out1 = cv::gapi::resize(in1, szOut);
if (need_first_conversion)
outs += cv::GOut(out1);
cv::GMat out2 = cv::gapi::resize(in2, szOut);
if (need_second_conversion)
outs += cv::GOut(out2);
// ! [GIOProtoArgs usage]
return cv::GComputation(std::move(ins), std::move(outs));
});
// ! [GRunArgs usage]
auto in_vector = cv::gin();
cv::Mat in_mat1( 8, 8, CV_8UC3);
cv::Mat in_mat2(16, 16, CV_8UC3);
cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
if (need_first_conversion)
in_vector += cv::gin(in_mat1);
if (need_second_conversion)
in_vector += cv::gin(in_mat2);
// ! [GRunArgs usage]
// ! [GRunArgsP usage]
auto out_vector = cv::gout();
cv::Mat out_mat1, out_mat2;
if (need_first_conversion)
out_vector += cv::gout(out_mat1);
if (need_second_conversion)
out_vector += cv::gout(out_mat2);
// ! [GRunArgsP usage]
auto stream = cc.compileStreaming(cv::compile_args(cv::gapi::core::cpu::kernels()));
stream.setSource(std::move(in_vector));
stream.start();
stream.pull(std::move(out_vector));
stream.stop();
return 0;
}

View File

@@ -0,0 +1,432 @@
#include <algorithm>
#include <iostream>
#include <cctype>
#include <opencv2/gapi.hpp>
#include <opencv2/gapi/core.hpp>
#include <opencv2/gapi/infer.hpp>
#include <opencv2/gapi/infer/ie.hpp>
#include <opencv2/gapi/streaming/cap.hpp>
#include <opencv2/gapi/cpu/gcpukernel.hpp>
#include <opencv2/highgui.hpp> // CommandLineParser
const std::string about =
"This is an OpenCV-based version of Gaze Estimation example";
const std::string keys =
"{ h help | | Print this help message }"
"{ input | | Path to the input video file }"
"{ facem | face-detection-retail-0005.xml | Path to OpenVINO face detection model (.xml) }"
"{ faced | CPU | Target device for the face detection (e.g. CPU, GPU, VPU, ...) }"
"{ landm | facial-landmarks-35-adas-0002.xml | Path to OpenVINO landmarks detector model (.xml) }"
"{ landd | CPU | Target device for the landmarks detector (e.g. CPU, GPU, VPU, ...) }"
"{ headm | head-pose-estimation-adas-0001.xml | Path to OpenVINO head pose estimation model (.xml) }"
"{ headd | CPU | Target device for the head pose estimation inference (e.g. CPU, GPU, VPU, ...) }"
"{ gazem | gaze-estimation-adas-0002.xml | Path to OpenVINO gaze vector estimaiton model (.xml) }"
"{ gazed | CPU | Target device for the gaze vector estimation inference (e.g. CPU, GPU, VPU, ...) }"
;
namespace {
std::string weights_path(const std::string &model_path) {
const auto EXT_LEN = 4u;
const auto sz = model_path.size();
CV_Assert(sz > EXT_LEN);
auto ext = model_path.substr(sz - EXT_LEN);
auto lower = [](unsigned char c) {
return static_cast<unsigned char>(std::tolower(c));
};
std::transform(ext.begin(), ext.end(), ext.begin(), lower);
CV_Assert(ext == ".xml");
return model_path.substr(0u, sz - EXT_LEN) + ".bin";
}
} // anonymous namespace
namespace custom {
namespace {
using GMat3 = std::tuple<cv::GMat,cv::GMat,cv::GMat>;
using GMats = cv::GArray<cv::GMat>;
using GRects = cv::GArray<cv::Rect>;
using GSize = cv::GOpaque<cv::Size>;
G_API_NET(Faces, <cv::GMat(cv::GMat)>, "face-detector" );
G_API_NET(Landmarks, <cv::GMat(cv::GMat)>, "facial-landmarks");
G_API_NET(HeadPose, < GMat3(cv::GMat)>, "head-pose");
G_API_NET(Gaze, <cv::GMat(cv::GMat,cv::GMat,cv::GMat)>, "gaze-vector");
G_API_OP(Size, <GSize(cv::GMat)>, "custom.gapi.size") {
static cv::GOpaqueDesc outMeta(const cv::GMatDesc &) {
return cv::empty_gopaque_desc();
}
};
G_API_OP(ParseSSD,
<GRects(cv::GMat, GSize, bool)>,
"custom.gaze_estimation.parseSSD") {
static cv::GArrayDesc outMeta( const cv::GMatDesc &
, const cv::GOpaqueDesc &
, bool) {
return cv::empty_array_desc();
}
};
// Left/Right eye per every face
G_API_OP(ParseEyes,
<std::tuple<GRects, GRects>(GMats, GRects, GSize)>,
"custom.gaze_estimation.parseEyes") {
static std::tuple<cv::GArrayDesc, cv::GArrayDesc>
outMeta( const cv::GArrayDesc &
, const cv::GArrayDesc &
, const cv::GOpaqueDesc &) {
return std::make_tuple(cv::empty_array_desc(), cv::empty_array_desc());
}
};
// Combine three scalars into a 1x3 vector (per every face)
G_API_OP(ProcessPoses,
<GMats(GMats, GMats, GMats)>,
"custom.gaze_estimation.processPoses") {
static cv::GArrayDesc outMeta( const cv::GArrayDesc &
, const cv::GArrayDesc &
, const cv::GArrayDesc &) {
return cv::empty_array_desc();
}
};
void adjustBoundingBox(cv::Rect& boundingBox) {
auto w = boundingBox.width;
auto h = boundingBox.height;
boundingBox.x -= static_cast<int>(0.067 * w);
boundingBox.y -= static_cast<int>(0.028 * h);
boundingBox.width += static_cast<int>(0.15 * w);
boundingBox.height += static_cast<int>(0.13 * h);
if (boundingBox.width < boundingBox.height) {
auto dx = (boundingBox.height - boundingBox.width);
boundingBox.x -= dx / 2;
boundingBox.width += dx;
} else {
auto dy = (boundingBox.width - boundingBox.height);
boundingBox.y -= dy / 2;
boundingBox.height += dy;
}
}
void gazeVectorToGazeAngles(const cv::Point3f& gazeVector,
cv::Point2f& gazeAngles) {
auto r = cv::norm(gazeVector);
double v0 = static_cast<double>(gazeVector.x);
double v1 = static_cast<double>(gazeVector.y);
double v2 = static_cast<double>(gazeVector.z);
gazeAngles.x = static_cast<float>(180.0 / M_PI * (M_PI_2 + std::atan2(v2, v0)));
gazeAngles.y = static_cast<float>(180.0 / M_PI * (M_PI_2 - std::acos(v1 / r)));
}
GAPI_OCV_KERNEL(OCVSize, Size) {
static void run(const cv::Mat &in, cv::Size &out) {
out = in.size();
}
};
GAPI_OCV_KERNEL(OCVParseSSD, ParseSSD) {
static void run(const cv::Mat &in_ssd_result,
const cv::Size &upscale,
const bool filter_out_of_bounds,
std::vector<cv::Rect> &out_objects) {
const auto &in_ssd_dims = in_ssd_result.size;
CV_Assert(in_ssd_dims.dims() == 4u);
const int MAX_PROPOSALS = in_ssd_dims[2];
const int OBJECT_SIZE = in_ssd_dims[3];
CV_Assert(OBJECT_SIZE == 7); // fixed SSD object size
const cv::Rect surface({0,0}, upscale);
out_objects.clear();
const float *data = in_ssd_result.ptr<float>();
for (int i = 0; i < MAX_PROPOSALS; i++) {
const float image_id = data[i * OBJECT_SIZE + 0];
const float label = data[i * OBJECT_SIZE + 1];
const float confidence = data[i * OBJECT_SIZE + 2];
const float rc_left = data[i * OBJECT_SIZE + 3];
const float rc_top = data[i * OBJECT_SIZE + 4];
const float rc_right = data[i * OBJECT_SIZE + 5];
const float rc_bottom = data[i * OBJECT_SIZE + 6];
(void) label;
if (image_id < 0.f) {
break; // marks end-of-detections
}
if (confidence < 0.5f) {
continue; // skip objects with low confidence
}
cv::Rect rc; // map relative coordinates to the original image scale
rc.x = static_cast<int>(rc_left * upscale.width);
rc.y = static_cast<int>(rc_top * upscale.height);
rc.width = static_cast<int>(rc_right * upscale.width) - rc.x;
rc.height = static_cast<int>(rc_bottom * upscale.height) - rc.y;
adjustBoundingBox(rc); // TODO: new option?
const auto clipped_rc = rc & surface; // TODO: new option?
if (filter_out_of_bounds) {
if (clipped_rc.area() != rc.area()) {
continue;
}
}
out_objects.emplace_back(clipped_rc);
}
}
};
cv::Rect eyeBox(const cv::Rect &face_rc,
float p1_x, float p1_y, float p2_x, float p2_y,
float scale = 1.8f) {
const auto &up = face_rc.size();
const cv::Point p1 = {
static_cast<int>(p1_x*up.width),
static_cast<int>(p1_y*up.height)
};
const cv::Point p2 = {
static_cast<int>(p2_x*up.width),
static_cast<int>(p2_y*up.height)
};
cv::Rect result;
const auto size = static_cast<float>(cv::norm(p1 - p2));
const auto midpoint = (p1 + p2) / 2;
result.width = static_cast<int>(scale * size);
result.height = result.width;
result.x = face_rc.x + midpoint.x - (result.width / 2);
result.y = face_rc.y + midpoint.y - (result.height / 2);
// Shift result to the original frame's absolute coordinates
return result;
}
GAPI_OCV_KERNEL(OCVParseEyes, ParseEyes) {
static void run(const std::vector<cv::Mat> &in_landmarks_per_face,
const std::vector<cv::Rect> &in_face_rcs,
const cv::Size &frame_size,
std::vector<cv::Rect> &out_left_eyes,
std::vector<cv::Rect> &out_right_eyes) {
const size_t numFaces = in_landmarks_per_face.size();
const cv::Rect surface(cv::Point(0,0), frame_size);
GAPI_Assert(numFaces == in_face_rcs.size());
out_left_eyes.clear();
out_right_eyes.clear();
out_left_eyes.reserve(numFaces);
out_right_eyes.reserve(numFaces);
for (std::size_t i = 0u; i < numFaces; i++) {
const auto &lm = in_landmarks_per_face[i];
const auto &rc = in_face_rcs[i];
// Left eye is defined by points 0/1 (x2),
// Right eye is defined by points 2/3 (x2)
const float *data = lm.ptr<float>();
out_left_eyes .push_back(surface & eyeBox(rc, data[0], data[1], data[2], data[3]));
out_right_eyes.push_back(surface & eyeBox(rc, data[4], data[5], data[6], data[7]));
}
}
};
GAPI_OCV_KERNEL(OCVProcessPoses, ProcessPoses) {
static void run(const std::vector<cv::Mat> &in_ys,
const std::vector<cv::Mat> &in_ps,
const std::vector<cv::Mat> &in_rs,
std::vector<cv::Mat> &out_poses) {
const std::size_t sz = in_ys.size();
GAPI_Assert(sz == in_ps.size() && sz == in_rs.size());
out_poses.clear();
for (std::size_t idx = 0u; idx < sz; idx++) {
cv::Mat pose(1, 3, CV_32FC1);
float *ptr = pose.ptr<float>();
ptr[0] = in_ys[idx].ptr<float>()[0];
ptr[1] = in_ps[idx].ptr<float>()[0];
ptr[2] = in_rs[idx].ptr<float>()[0];
out_poses.push_back(std::move(pose));
}
}
};
} // anonymous namespace
} // namespace custom
namespace vis {
namespace {
cv::Point2f midp(const cv::Rect &rc) {
return (rc.tl() + rc.br()) / 2;
};
void bbox(cv::Mat &m, const cv::Rect &rc) {
cv::rectangle(m, rc, cv::Scalar{0,255,0}, 2, cv::LINE_8, 0);
};
void pose(cv::Mat &m, const cv::Mat &p, const cv::Rect &face_rc) {
const auto *posePtr = p.ptr<float>();
const auto yaw = static_cast<double>(posePtr[0]);
const auto pitch = static_cast<double>(posePtr[1]);
const auto roll = static_cast<double>(posePtr[2]);
const auto sinY = std::sin(yaw * M_PI / 180.0);
const auto sinP = std::sin(pitch * M_PI / 180.0);
const auto sinR = std::sin(roll * M_PI / 180.0);
const auto cosY = std::cos(yaw * M_PI / 180.0);
const auto cosP = std::cos(pitch * M_PI / 180.0);
const auto cosR = std::cos(roll * M_PI / 180.0);
const auto axisLength = 0.4 * face_rc.width;
const auto xCenter = face_rc.x + face_rc.width / 2;
const auto yCenter = face_rc.y + face_rc.height / 2;
const auto center = cv::Point{xCenter, yCenter};
const auto axisln = cv::Point2d{axisLength, axisLength};
const auto ctr = cv::Matx<double,2,2>(cosR*cosY, sinY*sinP*sinR, 0.f, cosP*sinR);
const auto ctt = cv::Matx<double,2,2>(cosR*sinY*sinP, cosY*sinR, 0.f, -cosP*cosR);
const auto ctf = cv::Matx<double,2,2>(sinY*cosP, 0.f, 0.f, sinP);
// center to right
cv::line(m, center, center + static_cast<cv::Point>(ctr*axisln), cv::Scalar(0, 0, 255), 2);
// center to top
cv::line(m, center, center + static_cast<cv::Point>(ctt*axisln), cv::Scalar(0, 255, 0), 2);
// center to forward
cv::line(m, center, center + static_cast<cv::Point>(ctf*axisln), cv::Scalar(255, 0, 255), 2);
}
void vvec(cv::Mat &m, const cv::Mat &v, const cv::Rect &face_rc,
const cv::Rect &left_rc, const cv::Rect &right_rc) {
const auto scale = 0.002 * face_rc.width;
cv::Point3f gazeVector;
const auto *gazePtr = v.ptr<float>();
gazeVector.x = gazePtr[0];
gazeVector.y = gazePtr[1];
gazeVector.z = gazePtr[2];
gazeVector = gazeVector / cv::norm(gazeVector);
const double arrowLength = 0.4 * face_rc.width;
const auto left_mid = midp(left_rc);
const auto right_mid = midp(right_rc);
cv::Point2f gazeArrow;
gazeArrow.x = gazeVector.x;
gazeArrow.y = -gazeVector.y;
gazeArrow *= arrowLength;
cv::arrowedLine(m, left_mid, left_mid + gazeArrow, cv::Scalar(255, 0, 0), 2);
cv::arrowedLine(m, right_mid, right_mid + gazeArrow, cv::Scalar(255, 0, 0), 2);
cv::Point2f gazeAngles;
custom::gazeVectorToGazeAngles(gazeVector, gazeAngles);
cv::putText(m,
cv::format("gaze angles: (h=%0.0f, v=%0.0f)",
static_cast<double>(std::round(gazeAngles.x)),
static_cast<double>(std::round(gazeAngles.y))),
cv::Point(static_cast<int>(face_rc.tl().x),
static_cast<int>(face_rc.br().y + 12. * face_rc.width / 100.)),
cv::FONT_HERSHEY_PLAIN, scale * 2, cv::Scalar::all(255), 1);
};
} // anonymous namespace
} // namespace vis
int main(int argc, char *argv[])
{
cv::CommandLineParser cmd(argc, argv, keys);
cmd.about(about);
if (cmd.has("help")) {
cmd.printMessage();
return 0;
}
cv::GMat in;
cv::GMat faces = cv::gapi::infer<custom::Faces>(in);
cv::GOpaque<cv::Size> sz = custom::Size::on(in); // FIXME
cv::GArray<cv::Rect> faces_rc = custom::ParseSSD::on(faces, sz, true);
cv::GArray<cv::GMat> angles_y, angles_p, angles_r;
std::tie(angles_y, angles_p, angles_r) = cv::gapi::infer<custom::HeadPose>(faces_rc, in);
cv::GArray<cv::GMat> heads_pos = custom::ProcessPoses::on(angles_y, angles_p, angles_r);
cv::GArray<cv::GMat> landmarks = cv::gapi::infer<custom::Landmarks>(faces_rc, in);
cv::GArray<cv::Rect> left_eyes, right_eyes;
std::tie(left_eyes, right_eyes) = custom::ParseEyes::on(landmarks, faces_rc, sz);
cv::GArray<cv::GMat> gaze_vectors = cv::gapi::infer2<custom::Gaze>( in
, left_eyes
, right_eyes
, heads_pos);
cv::GComputation graph(cv::GIn(in),
cv::GOut( cv::gapi::copy(in)
, faces_rc
, left_eyes
, right_eyes
, heads_pos
, gaze_vectors));
const auto input_file_name = cmd.get<std::string>("input");
const auto face_model_path = cmd.get<std::string>("facem");
const auto head_model_path = cmd.get<std::string>("headm");
const auto lmrk_model_path = cmd.get<std::string>("landm");
const auto gaze_model_path = cmd.get<std::string>("gazem");
auto face_net = cv::gapi::ie::Params<custom::Faces> {
face_model_path, // path to topology IR
weights_path(face_model_path), // path to weights
cmd.get<std::string>("faced"), /// device specifier
};
auto head_net = cv::gapi::ie::Params<custom::HeadPose> {
head_model_path, // path to topology IR
weights_path(head_model_path), // path to weights
cmd.get<std::string>("headd"), // device specifier
}.cfgOutputLayers({"angle_y_fc", "angle_p_fc", "angle_r_fc"});
auto landmarks_net = cv::gapi::ie::Params<custom::Landmarks> {
lmrk_model_path, // path to topology IR
weights_path(lmrk_model_path), // path to weights
cmd.get<std::string>("landd"), // device specifier
};
auto gaze_net = cv::gapi::ie::Params<custom::Gaze> {
gaze_model_path, // path to topology IR
weights_path(gaze_model_path), // path to weights
cmd.get<std::string>("gazed"), // device specifier
}.cfgInputLayers({"left_eye_image", "right_eye_image", "head_pose_angles"});
auto kernels = cv::gapi::kernels< custom::OCVSize
, custom::OCVParseSSD
, custom::OCVParseEyes
, custom::OCVProcessPoses>();
auto networks = cv::gapi::networks(face_net, head_net, landmarks_net, gaze_net);
auto pipeline = graph.compileStreaming(cv::compile_args(networks, kernels));
cv::TickMeter tm;
cv::Mat image;
std::vector<cv::Rect> out_faces, out_right_eyes, out_left_eyes;
std::vector<cv::Mat> out_poses;
std::vector<cv::Mat> out_gazes;
std::size_t frames = 0u;
std::cout << "Reading " << input_file_name << std::endl;
pipeline.setSource(cv::gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(input_file_name));
pipeline.start();
tm.start();
while (pipeline.pull(cv::gout( image
, out_faces
, out_left_eyes
, out_right_eyes
, out_poses
, out_gazes))) {
frames++;
// Visualize results on the frame
for (auto &&rc : out_faces) vis::bbox(image, rc);
for (auto &&rc : out_left_eyes) vis::bbox(image, rc);
for (auto &&rc : out_right_eyes) vis::bbox(image, rc);
for (std::size_t i = 0u; i < out_faces.size(); i++) {
vis::pose(image, out_poses[i], out_faces[i]);
vis::vvec(image, out_gazes[i], out_faces[i], out_left_eyes[i], out_right_eyes[i]);
}
tm.stop();
const auto fps_str = std::to_string(frames / tm.getTimeSec()) + " FPS";
cv::putText(image, fps_str, {0,32}, cv::FONT_HERSHEY_SIMPLEX, 1.0, {0,255,0}, 2);
cv::imshow("Out", image);
cv::waitKey(1);
tm.start();
}
tm.stop();
std::cout << "Processed " << frames << " frames"
<< " (" << frames / tm.getTimeSec() << " FPS)" << std::endl;
return 0;
}

View File

@@ -21,7 +21,7 @@ const std::string keys =
"{ input | | Path to the input video file }"
"{ platm | vehicle-license-plate-detection-barrier-0106.xml | Path to OpenVINO IE vehicle/plate detection model (.xml) }"
"{ platd | CPU | Target device for vehicle/plate detection model (e.g. CPU, GPU, VPU, ...) }"
"{ facem | face-detection-adas-0001.xml | Path to OpenVINO IE face detection model (.xml) }"
"{ facem | face-detection-retail-0005.xml | Path to OpenVINO IE face detection model (.xml) }"
"{ faced | CPU | Target device for face detection model (e.g. CPU, GPU, VPU, ...) }"
"{ trad | false | Run processing in a traditional (non-pipelined) way }"
"{ noshow | false | Don't display UI (improves performance) }";

View File

@@ -0,0 +1,99 @@
#!/usr/bin/env python3
import sys
import subprocess
import re
from enum import Enum
## Helper functions ##################################################
##
def fmt_bool(x):
return ("true" if x else "false")
def fmt_bin(base, prec, model):
return "%s/%s/%s/%s.xml" % (base, model, prec, model)
## The script itself #################################################
##
if len(sys.argv) != 3:
print("Usage: %s /path/to/input/video /path/to/models" % sys.argv[0])
exit(1)
input_file_path = sys.argv[1]
intel_models_path = sys.argv[2]
app = "bin/example_gapi_privacy_masking_camera"
intel_fd_model = "face-detection-retail-0005"
intel_lpd_model = "vehicle-license-plate-detection-barrier-0106"
output_file = "out_results.csv"
tgts = [ ("CPU", "INT8")
, ("CPU", "FP32")
, ("GPU", "FP16")
]
class Policy(Enum):
Traditional = 1
Streaming = 2
# From mode to cmd arg
mods = [ (Policy.Traditional, True)
, (Policy.Streaming, False)
]
class UI(Enum):
With = 1
Without = 2
# From mode to cmd arg
ui = [ (UI.With, False)
, (UI.Without, True)
]
fd_fmt_bin = lambda prec : fmt_bin(intel_models_path, prec, intel_fd_model)
lpd_fmt_bin = lambda prec : fmt_bin(intel_models_path, prec, intel_lpd_model)
# Performance comparison table
table={}
# Collect the performance data
for m in mods: # Execution mode (trad/stream)
for u in ui: # UI mode (on/off)
for f in tgts: # FD model
for p in tgts: # LPD model
cmd = [ app
, ("--input=%s" % input_file_path) # input file
, ("--faced=%s" % f[0]) # FD device target
, ("--facem=%s" % fd_fmt_bin(f[1])) # FD model @ precision
, ("--platd=%s" % p[0]) # LPD device target
, ("--platm=%s" % lpd_fmt_bin(p[1])) # LPD model @ precision
, ("--trad=%s" % fmt_bool(m[1])) # Execution policy
, ("--noshow=%s" % fmt_bool(u[1])) # UI mode (show/no show)
]
out = str(subprocess.check_output(cmd))
match = re.search('Processed [0-9]+ frames \(([0-9]+\.[0-9]+) FPS\)', out)
fps = float(match.group(1))
print(cmd, fps, "FPS")
table[m[0],u[0],f,p] = fps
# Write the performance summary
# Columns: all other components (mode, ui)
with open(output_file, 'w') as csv:
# CSV header
csv.write("FD,LPD,Serial(UI),Serial(no-UI),Streaming(UI),Streaming(no-UI),Effect(UI),Effect(no-UI)\n")
for f in tgts: # FD model
for p in tgts: # LPD model
row = "%s/%s,%s/%s" % (f[0], f[1], p[0], p[1]) # FD precision, LPD precision
row += ",%f" % table[Policy.Traditional,UI.With, f,p] # Serial/UI
row += ",%f" % table[Policy.Traditional,UI.Without,f,p] # Serial/no UI
row += ",%f" % table[Policy.Streaming, UI.With, f,p] # Streaming/UI
row += ",%f" % table[Policy.Streaming, UI.Without,f,p] # Streaming/no UI
effect_ui = table[Policy.Streaming,UI.With, f,p] / table[Policy.Traditional,UI.With, f,p]
effect_noui = table[Policy.Streaming,UI.Without,f,p] / table[Policy.Traditional,UI.Without,f,p]
row += ",%f,%f" % (effect_ui,effect_noui)
row += "\n"
csv.write(row)
print("DONE: ", output_file)

View File

@@ -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-2020 Intel Corporation
#include "precomp.hpp"
@@ -20,6 +20,11 @@ cv::detail::GArrayU::GArrayU(const GNode &n, std::size_t out)
{
}
cv::detail::GArrayU::GArrayU(const detail::VectorRef& vref)
: m_priv(new GOrigin(GShape::GARRAY, cv::gimpl::ConstVal(vref)))
{
}
cv::GOrigin& cv::detail::GArrayU::priv()
{
return *m_priv;
@@ -35,6 +40,11 @@ void cv::detail::GArrayU::setConstructFcn(ConstructVec &&cv)
m_priv->ctor = std::move(cv);
}
void cv::detail::GArrayU::setKind(cv::detail::OpaqueKind kind)
{
m_priv->kind = kind;
}
namespace cv {
std::ostream& operator<<(std::ostream& os, const cv::GArrayDesc &)
{

View File

@@ -10,7 +10,6 @@
#include <functional> // multiplies
#include <opencv2/gapi/gkernel.hpp>
#include <opencv2/gapi/own/convert.hpp>
#include "api/gbackend_priv.hpp"
#include "backends/common/gbackend.hpp"
@@ -114,36 +113,22 @@ void bindInArg(Mag& mag, const RcDesc &rc, const GRunArg &arg, bool is_umat)
{
switch (arg.index())
{
case GRunArg::index_of<cv::gapi::own::Mat>() :
case GRunArg::index_of<cv::Mat>() :
if (is_umat)
{
#if !defined(GAPI_STANDALONE)
auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
mag_umat = to_ocv(util::get<cv::gapi::own::Mat>(arg)).getUMat(ACCESS_READ);
mag_umat = util::get<cv::Mat>(arg).getUMat(ACCESS_READ);
#else
util::throw_error(std::logic_error("UMat is not supported in standalone build"));
#endif // !defined(GAPI_STANDALONE)
}
else
{
auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
mag_mat = util::get<cv::gapi::own::Mat>(arg);
auto& mag_mat = mag.template slot<cv::Mat>()[rc.id];
mag_mat = util::get<cv::Mat>(arg);
}
break;
#if !defined(GAPI_STANDALONE)
case GRunArg::index_of<cv::Mat>() :
if (is_umat)
{
auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
mag_umat = util::get<cv::Mat>(arg).getUMat(ACCESS_READ);
}
else
{
auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
mag_mat = to_own(util::get<cv::Mat>(arg));
}
break;
#endif // !defined(GAPI_STANDALONE)
default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
}
break;
@@ -182,36 +167,22 @@ void bindOutArg(Mag& mag, const RcDesc &rc, const GRunArgP &arg, bool is_umat)
{
switch (arg.index())
{
case GRunArgP::index_of<cv::gapi::own::Mat*>() :
case GRunArgP::index_of<cv::Mat*>() :
if (is_umat)
{
#if !defined(GAPI_STANDALONE)
auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
mag_umat = to_ocv(*(util::get<cv::gapi::own::Mat*>(arg))).getUMat(ACCESS_RW);
mag_umat = util::get<cv::Mat*>(arg)->getUMat(ACCESS_RW);
#else
util::throw_error(std::logic_error("UMat is not supported in standalone build"));
#endif // !defined(GAPI_STANDALONE)
}
else
{
auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
mag_mat = *util::get<cv::gapi::own::Mat*>(arg);
auto& mag_mat = mag.template slot<cv::Mat>()[rc.id];
mag_mat = *util::get<cv::Mat*>(arg);
}
break;
#if !defined(GAPI_STANDALONE)
case GRunArgP::index_of<cv::Mat*>() :
if (is_umat)
{
auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
mag_umat = util::get<cv::Mat*>(arg)->getUMat(ACCESS_RW);
}
else
{
auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
mag_mat = to_own(*util::get<cv::Mat*>(arg));
}
break;
#endif // !defined(GAPI_STANDALONE)
default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
}
break;
@@ -277,7 +248,7 @@ cv::GRunArg getArg(const Mag& mag, const RcDesc &ref)
// Wrap associated CPU object (either host or an internal one)
switch (ref.shape)
{
case GShape::GMAT: return GRunArg(mag.template slot<cv::gapi::own::Mat>().at(ref.id));
case GShape::GMAT: return GRunArg(mag.template slot<cv::Mat>().at(ref.id));
case GShape::GSCALAR: return GRunArg(mag.template slot<cv::Scalar>().at(ref.id));
// Note: .at() is intentional for GArray and GOpaque as objects MUST be already there
// (and constructed by either bindIn/Out or resetInternal)
@@ -303,7 +274,7 @@ cv::GRunArgP getObjPtr(Mag& mag, const RcDesc &rc, bool is_umat)
#endif // !defined(GAPI_STANDALONE)
}
else
return GRunArgP(&mag.template slot<cv::gapi::own::Mat>()[rc.id]);
return GRunArgP(&mag.template slot<cv::Mat>()[rc.id]);
case GShape::GSCALAR: return GRunArgP(&mag.template slot<cv::Scalar>()[rc.id]);
// Note: .at() is intentional for GArray and GOpaque as objects MUST be already there
// (and constructor by either bindIn/Out or resetInternal)
@@ -347,10 +318,9 @@ void writeBack(const Mag& mag, const RcDesc &rc, GRunArgP &g_arg, bool is_umat)
uchar* out_arg_data = nullptr;
switch (g_arg.index())
{
case GRunArgP::index_of<cv::gapi::own::Mat*>() : out_arg_data = util::get<cv::gapi::own::Mat*>(g_arg)->data; break;
case GRunArgP::index_of<cv::Mat*>() : out_arg_data = util::get<cv::Mat*>(g_arg)->data; break;
#if !defined(GAPI_STANDALONE)
case GRunArgP::index_of<cv::Mat*>() : out_arg_data = util::get<cv::Mat*>(g_arg)->data; break;
case GRunArgP::index_of<cv::UMat*>() : out_arg_data = (util::get<cv::UMat*>(g_arg))->getMat(ACCESS_RW).data; break;
case GRunArgP::index_of<cv::UMat*>() : out_arg_data = (util::get<cv::UMat*>(g_arg))->getMat(ACCESS_RW).data; break;
#endif // !defined(GAPI_STANDALONE)
default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
}
@@ -365,7 +335,7 @@ void writeBack(const Mag& mag, const RcDesc &rc, GRunArgP &g_arg, bool is_umat)
}
else
{
auto& in_mag = mag.template slot<cv::gapi::own::Mat>().at(rc.id);
auto& in_mag = mag.template slot<cv::Mat>().at(rc.id);
GAPI_Assert((out_arg_data == in_mag.data) && " data for output parameters was reallocated ?");
}
break;
@@ -389,24 +359,6 @@ void writeBack(const Mag& mag, const RcDesc &rc, GRunArgP &g_arg, bool is_umat)
} // namespace magazine
void createMat(const cv::GMatDesc &desc, cv::gapi::own::Mat& mat)
{
// FIXME: Refactor (probably start supporting N-Dimensional blobs natively
if (desc.dims.empty())
{
const auto type = desc.planar ? desc.depth : CV_MAKETYPE(desc.depth, desc.chan);
const auto size = desc.planar ? cv::Size{desc.size.width, desc.size.height*desc.chan}
: desc.size;
mat.create(size, type);
}
else
{
GAPI_Assert(!desc.planar);
mat.create(desc.dims, desc.depth);
}
}
#if !defined(GAPI_STANDALONE)
void createMat(const cv::GMatDesc &desc, cv::Mat& mat)
{
// FIXME: Refactor (probably start supporting N-Dimensional blobs natively
@@ -423,7 +375,6 @@ void createMat(const cv::GMatDesc &desc, cv::Mat& mat)
mat.create(desc.dims, desc.depth);
}
}
#endif
} // namespace gimpl
} // namespace cv

View File

@@ -56,19 +56,38 @@ cv::GComputation::GComputation(const std::vector<GMat> &ins,
const std::vector<GMat> &outs)
: m_priv(new Priv())
{
Priv::Expr e;
const auto wrap = [](cv::GMat m) { return GProtoArg(m); };
ade::util::transform(ins, std::back_inserter(m_priv->m_ins), wrap);
ade::util::transform(outs, std::back_inserter(m_priv->m_outs), wrap);
ade::util::transform(ins, std::back_inserter(e.m_ins), wrap);
ade::util::transform(outs, std::back_inserter(e.m_outs), wrap);
m_priv->m_shape = std::move(e);
}
cv::GComputation::GComputation(cv::GProtoInputArgs &&ins,
cv::GProtoOutputArgs &&outs)
: m_priv(new Priv())
{
m_priv->m_ins = std::move(ins.m_args);
m_priv->m_outs = std::move(outs.m_args);
m_priv->m_shape = Priv::Expr{
std::move(ins.m_args)
, std::move(outs.m_args)
};
}
cv::GComputation::GComputation(cv::gimpl::s11n::I::IStream &is)
: m_priv(new Priv())
{
m_priv->m_shape = gimpl::s11n::deserialize(is);
}
void cv::GComputation::serialize(cv::gimpl::s11n::I::OStream &os) const
{
// Build a basic GModel and write the whole thing to the stream
auto pG = cv::gimpl::GCompiler::makeGraph(*m_priv);
std::vector<ade::NodeHandle> nhs(pG->nodes().begin(), pG->nodes().end());
gimpl::s11n::serialize(os, *pG, nhs);
}
cv::GCompiled cv::GComputation::compile(GMetaArgs &&metas, GCompileArgs &&args)
{
// FIXME: Cache gcompiled per parameters here?
@@ -132,16 +151,16 @@ void cv::GComputation::apply(GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&ar
m_priv->m_lastCompiled(std::move(ins), std::move(outs));
}
void cv::GComputation::apply(const std::vector<cv::gapi::own::Mat> &ins,
const std::vector<cv::gapi::own::Mat> &outs,
void cv::GComputation::apply(const std::vector<cv::Mat> &ins,
const std::vector<cv::Mat> &outs,
GCompileArgs &&args)
{
GRunArgs call_ins;
GRunArgsP call_outs;
auto tmp = outs;
for (const cv::gapi::own::Mat &m : ins) { call_ins.emplace_back(m); }
for ( cv::gapi::own::Mat &m : tmp) { call_outs.emplace_back(&m); }
for (const cv::Mat &m : ins) { call_ins.emplace_back(m); }
for ( cv::Mat &m : tmp) { call_outs.emplace_back(&m); }
apply(std::move(call_ins), std::move(call_outs), std::move(args));
}

View File

@@ -8,20 +8,37 @@
#ifndef OPENCV_GAPI_GCOMPUTATION_PRIV_HPP
#define OPENCV_GAPI_GCOMPUTATION_PRIV_HPP
#include <ade/graph.hpp>
#include "opencv2/gapi/util/variant.hpp"
#include "opencv2/gapi.hpp"
#include "opencv2/gapi/gcall.hpp"
#include "opencv2/gapi/util/variant.hpp"
#include "backends/common/serialization.hpp"
namespace cv {
class GComputation::Priv
{
public:
struct Expr {
cv::GProtoArgs m_ins;
cv::GProtoArgs m_outs;
};
using Dump = cv::gimpl::s11n::GSerialized;
using Shape = cv::util::variant
< Expr // An expression-based graph
, Dump // A deserialized graph
>;
GCompiled m_lastCompiled;
GMetaArgs m_lastMetas; // TODO: make GCompiled remember its metas?
GProtoArgs m_ins;
GProtoArgs m_outs;
Shape m_shape;
};
}

View File

@@ -0,0 +1,41 @@
// 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) 2020 Intel Corporation
#include "precomp.hpp"
#include <opencv2/gapi/gframe.hpp>
#include "api/gorigin.hpp"
// cv::GFrame public implementation //////////////////////////////////////////////
cv::GFrame::GFrame()
: m_priv(new GOrigin(GShape::GMAT, GNode::Param())) {
// N.B.: The shape here is still GMAT as currently cv::Mat is used
// as an underlying host type. Will be changed to GFRAME once
// GExecutor & GStreamingExecutor & selected backends will be extended
// to support cv::MediaFrame.
}
cv::GFrame::GFrame(const GNode &n, std::size_t out)
: m_priv(new GOrigin(GShape::GMAT, n, out)) {
// N.B.: GMAT is here for the same reason as above ^
}
cv::GOrigin& cv::GFrame::priv() {
return *m_priv;
}
const cv::GOrigin& cv::GFrame::priv() const {
return *m_priv;
}
namespace cv {
std::ostream& operator<<(std::ostream& os, const cv::GFrameDesc &) {
return os;
}
} // namespace cv

View File

@@ -48,7 +48,6 @@ namespace{
}
}
#if !defined(GAPI_STANDALONE)
cv::GMatDesc cv::descr_of(const cv::Mat &mat)
{
@@ -64,32 +63,34 @@ cv::GMatDesc cv::descr_of(const cv::Mat &mat)
}
return GMatDesc{mat.depth(), std::move(dims)};
}
#endif
cv::GMatDesc cv::gapi::own::descr_of(const Mat &mat)
{
return (mat.dims.empty())
? GMatDesc{mat.depth(), mat.channels(), {mat.cols, mat.rows}}
: GMatDesc{mat.depth(), mat.dims};
}
#if !defined(GAPI_STANDALONE)
cv::GMatDesc cv::descr_of(const cv::UMat &mat)
{
GAPI_Assert(mat.size.dims() == 2);
return GMatDesc{ mat.depth(), mat.channels(),{ mat.cols, mat.rows } };
}
cv::GMetaArgs cv::descrs_of(const std::vector<cv::Mat> &vec)
{
return vec_descr_of(vec);
}
cv::GMetaArgs cv::descrs_of(const std::vector<cv::UMat> &vec)
{
return vec_descr_of(vec);
}
#endif
cv::GMatDesc cv::gapi::own::descr_of(const cv::gapi::own::Mat &mat)
cv::GMetaArgs cv::descrs_of(const std::vector<cv::Mat> &vec)
{
return (mat.dims.empty())
? GMatDesc{mat.depth(), mat.channels(), {mat.cols, mat.rows}}
: GMatDesc{mat.depth(), mat.dims};
return vec_descr_of(vec);
}
cv::GMetaArgs cv::gapi::own::descrs_of(const std::vector<cv::gapi::own::Mat> &vec)
cv::GMetaArgs cv::gapi::own::descrs_of(const std::vector<Mat> &vec)
{
return vec_descr_of(vec);
}
@@ -126,21 +127,14 @@ std::ostream& operator<<(std::ostream& os, const cv::GMatDesc &desc)
namespace {
template<typename M> inline bool canDescribeHelper(const GMatDesc& desc, const M& mat)
{
const auto mat_desc = desc.planar ? descr_of(mat).asPlanar(desc.chan) : descr_of(mat);
const auto mat_desc = desc.planar ? cv::descr_of(mat).asPlanar(desc.chan) : cv::descr_of(mat);
return desc == mat_desc;
}
} // anonymous namespace
bool GMatDesc::canDescribe(const cv::gapi::own::Mat& mat) const
{
return canDescribeHelper(*this, mat);
}
#if !defined(GAPI_STANDALONE)
bool GMatDesc::canDescribe(const cv::Mat& mat) const
{
return canDescribeHelper(*this, mat);
}
#endif
}// namespace cv

View File

@@ -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) 2019 Intel Corporation
// Copyright (C) 2019-2020 Intel Corporation
#include "precomp.hpp"
@@ -35,6 +35,11 @@ void cv::detail::GOpaqueU::setConstructFcn(ConstructOpaque &&co)
m_priv->ctor = std::move(co);
}
void cv::detail::GOpaqueU::setKind(cv::detail::OpaqueKind kind)
{
m_priv->kind = kind;
}
namespace cv {
std::ostream& operator<<(std::ostream& os, const cv::GOpaqueDesc &)
{

View File

@@ -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-2020 Intel Corporation
#include "precomp.hpp"
@@ -14,13 +14,17 @@
cv::GOrigin::GOrigin(GShape s,
const cv::GNode& n,
std::size_t p,
const cv::gimpl::HostCtor c)
: shape(s), node(n), port(p), ctor(c)
const cv::gimpl::HostCtor c,
cv::detail::OpaqueKind k)
: shape(s), node(n), port(p), ctor(c), kind(k)
{
}
cv::GOrigin::GOrigin(GShape s, cv::gimpl::ConstVal v)
: shape(s), node(cv::GNode::Const()), value(v), port(INVALID_PORT)
: shape(s), node(cv::GNode::Const()), value(v), port(INVALID_PORT),
kind(util::holds_alternative<detail::VectorRef>(v)
? util::get<detail::VectorRef>(v).getKind()
: cv::detail::OpaqueKind::CV_UNKNOWN)
{
}

View File

@@ -2,8 +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-2020 Intel Corporation
#ifndef OPENCV_GAPI_GORIGIN_HPP
#define OPENCV_GAPI_GORIGIN_HPP
@@ -30,7 +29,8 @@ struct GOrigin
GOrigin(GShape s,
const GNode& n,
std::size_t p = INVALID_PORT,
const gimpl::HostCtor h = {});
const gimpl::HostCtor h = {},
cv::detail::OpaqueKind kind = cv::detail::OpaqueKind::CV_UNKNOWN);
GOrigin(GShape s, gimpl::ConstVal value);
const GShape shape; // Shape of a produced object
@@ -38,6 +38,7 @@ struct GOrigin
const gimpl::ConstVal value; // Node can have initial constant value, now only scalar is supported
const std::size_t port; // GNode's output number; FIXME: "= max_size" in C++14
gimpl::HostCtor ctor; // FIXME: replace with an interface?
detail::OpaqueKind kind; // primary is needed for GOpaque and GArray
};
namespace detail

View File

@@ -28,6 +28,9 @@ const cv::GOrigin& cv::gimpl::proto::origin_of(const cv::GProtoArg &arg)
case cv::GProtoArg::index_of<cv::GMatP>():
return util::get<cv::GMatP>(arg).priv();
case cv::GProtoArg::index_of<cv::GFrame>():
return util::get<cv::GFrame>(arg).priv();
case cv::GProtoArg::index_of<cv::GScalar>():
return util::get<cv::GScalar>(arg).priv();
@@ -60,6 +63,7 @@ bool cv::gimpl::proto::is_dynamic(const cv::GArg& arg)
{
case detail::ArgKind::GMAT:
case detail::ArgKind::GMATP:
case detail::ArgKind::GFRAME:
case detail::ArgKind::GSCALAR:
case detail::ArgKind::GARRAY:
case detail::ArgKind::GOPAQUE:
@@ -75,6 +79,7 @@ cv::GRunArg cv::value_of(const cv::GOrigin &origin)
switch (origin.shape)
{
case GShape::GSCALAR: return GRunArg(util::get<cv::Scalar>(origin.value));
case GShape::GARRAY: return GRunArg(util::get<cv::detail::VectorRef>(origin.value));
default: util::throw_error(std::logic_error("Unsupported shape for constant"));
}
}
@@ -87,9 +92,10 @@ cv::GProtoArg cv::gimpl::proto::rewrap(const cv::GArg &arg)
{
case detail::ArgKind::GMAT: return GProtoArg(arg.get<cv::GMat>());
case detail::ArgKind::GMATP: return GProtoArg(arg.get<cv::GMatP>());
case detail::ArgKind::GFRAME: return GProtoArg(arg.get<cv::GFrame>());
case detail::ArgKind::GSCALAR: return GProtoArg(arg.get<cv::GScalar>());
case detail::ArgKind::GARRAY: return GProtoArg(arg.get<cv::detail::GArrayU>());
case detail::ArgKind::GOPAQUE: return GProtoArg(arg.get<cv::detail::GOpaqueU>());
case detail::ArgKind::GOPAQUE: return GProtoArg(arg.get<cv::detail::GOpaqueU>());
default: util::throw_error(std::logic_error("Unsupported GArg type"));
}
}
@@ -98,14 +104,8 @@ cv::GMetaArg cv::descr_of(const cv::GRunArg &arg)
{
switch (arg.index())
{
#if !defined(GAPI_STANDALONE)
case GRunArg::index_of<cv::Mat>():
return cv::GMetaArg(descr_of(util::get<cv::Mat>(arg)));
#endif // !defined(GAPI_STANDALONE)
case GRunArg::index_of<cv::gapi::own::Mat>():
return cv::GMetaArg(descr_of(util::get<cv::gapi::own::Mat>(arg)));
return cv::GMetaArg(cv::descr_of(util::get<cv::Mat>(arg)));
case GRunArg::index_of<cv::Scalar>():
return cv::GMetaArg(descr_of(util::get<cv::Scalar>(arg)));
@@ -135,10 +135,9 @@ cv::GMetaArg cv::descr_of(const cv::GRunArgP &argp)
switch (argp.index())
{
#if !defined(GAPI_STANDALONE)
case GRunArgP::index_of<cv::Mat*>(): return GMetaArg(descr_of(*util::get<cv::Mat*>(argp)));
case GRunArgP::index_of<cv::UMat*>(): return GMetaArg(descr_of(*util::get<cv::UMat*>(argp)));
case GRunArgP::index_of<cv::UMat*>(): return GMetaArg(cv::descr_of(*util::get<cv::UMat*>(argp)));
#endif // !defined(GAPI_STANDALONE)
case GRunArgP::index_of<cv::gapi::own::Mat*>(): return GMetaArg(descr_of(*util::get<cv::gapi::own::Mat*>(argp)));
case GRunArgP::index_of<cv::Mat*>(): return GMetaArg(cv::descr_of(*util::get<cv::Mat*>(argp)));
case GRunArgP::index_of<cv::Scalar*>(): return GMetaArg(descr_of(*util::get<cv::Scalar*>(argp)));
case GRunArgP::index_of<cv::detail::VectorRef>(): return GMetaArg(util::get<cv::detail::VectorRef>(argp).descr_of());
case GRunArgP::index_of<cv::detail::OpaqueRef>(): return GMetaArg(util::get<cv::detail::OpaqueRef>(argp).descr_of());
@@ -151,13 +150,11 @@ bool cv::can_describe(const GMetaArg& meta, const GRunArgP& argp)
switch (argp.index())
{
#if !defined(GAPI_STANDALONE)
case GRunArgP::index_of<cv::UMat*>(): return meta == GMetaArg(cv::descr_of(*util::get<cv::UMat*>(argp)));
#endif // !defined(GAPI_STANDALONE)
case GRunArgP::index_of<cv::Mat*>(): return util::holds_alternative<GMatDesc>(meta) &&
util::get<GMatDesc>(meta).canDescribe(*util::get<cv::Mat*>(argp));
case GRunArgP::index_of<cv::UMat*>(): return meta == GMetaArg(descr_of(*util::get<cv::UMat*>(argp)));
#endif // !defined(GAPI_STANDALONE)
case GRunArgP::index_of<cv::gapi::own::Mat*>(): return util::holds_alternative<GMatDesc>(meta) &&
util::get<GMatDesc>(meta).canDescribe(*util::get<cv::gapi::own::Mat*>(argp));
case GRunArgP::index_of<cv::Scalar*>(): return meta == GMetaArg(descr_of(*util::get<cv::Scalar*>(argp)));
case GRunArgP::index_of<cv::Scalar*>(): return meta == GMetaArg(cv::descr_of(*util::get<cv::Scalar*>(argp)));
case GRunArgP::index_of<cv::detail::VectorRef>(): return meta == GMetaArg(util::get<cv::detail::VectorRef>(argp).descr_of());
case GRunArgP::index_of<cv::detail::OpaqueRef>(): return meta == GMetaArg(util::get<cv::detail::OpaqueRef>(argp).descr_of());
default: util::throw_error(std::logic_error("Unsupported GRunArgP type"));
@@ -169,12 +166,10 @@ bool cv::can_describe(const GMetaArg& meta, const GRunArg& arg)
switch (arg.index())
{
#if !defined(GAPI_STANDALONE)
case GRunArg::index_of<cv::Mat>(): return util::holds_alternative<GMatDesc>(meta) &&
util::get<GMatDesc>(meta).canDescribe(util::get<cv::Mat>(arg));
case GRunArg::index_of<cv::UMat>(): return meta == cv::GMetaArg(descr_of(util::get<cv::UMat>(arg)));
#endif // !defined(GAPI_STANDALONE)
case GRunArg::index_of<cv::gapi::own::Mat>(): return util::holds_alternative<GMatDesc>(meta) &&
util::get<GMatDesc>(meta).canDescribe(util::get<cv::gapi::own::Mat>(arg));
case GRunArg::index_of<cv::Mat>(): return util::holds_alternative<GMatDesc>(meta) &&
util::get<GMatDesc>(meta).canDescribe(util::get<cv::Mat>(arg));
case GRunArg::index_of<cv::Scalar>(): return meta == cv::GMetaArg(descr_of(util::get<cv::Scalar>(arg)));
case GRunArg::index_of<cv::detail::VectorRef>(): return meta == cv::GMetaArg(util::get<cv::detail::VectorRef>(arg).descr_of());
case GRunArg::index_of<cv::detail::OpaqueRef>(): return meta == cv::GMetaArg(util::get<cv::detail::OpaqueRef>(arg).descr_of());
@@ -198,21 +193,16 @@ void cv::validate_input_arg(const GRunArg& arg)
switch (arg.index())
{
#if !defined(GAPI_STANDALONE)
case GRunArg::index_of<cv::Mat>():
{
const auto desc = descr_of(util::get<cv::Mat>(arg));
GAPI_Assert(desc.size.height != 0 && desc.size.width != 0 && "incorrect dimensions of cv::Mat!"); break;
}
case GRunArg::index_of<cv::UMat>():
{
const auto desc = descr_of(util::get<cv::UMat>(arg));
const auto desc = cv::descr_of(util::get<cv::UMat>(arg));
GAPI_Assert(desc.size.height != 0 && desc.size.width != 0 && "incorrect dimensions of cv::UMat!"); break;
}
#endif // !defined(GAPI_STANDALONE)
case GRunArg::index_of<cv::gapi::own::Mat>():
case GRunArg::index_of<cv::Mat>():
{
const auto desc = descr_of(util::get<cv::gapi::own::Mat>(arg));
GAPI_Assert(desc.size.height != 0 && desc.size.width != 0 && "incorrect dimensions of own::Mat!"); break;
const auto desc = cv::descr_of(util::get<cv::Mat>(arg));
GAPI_Assert(desc.size.height != 0 && desc.size.width != 0 && "incorrect dimensions of Mat!"); break;
}
default:
// No extra handling
@@ -259,4 +249,25 @@ std::ostream& operator<<(std::ostream& os, const cv::GMetaArg &arg)
return os;
}
} // namespace cv
const void* cv::gimpl::proto::ptr(const GRunArgP &arg)
{
switch (arg.index())
{
#if !defined(GAPI_STANDALONE)
case GRunArgP::index_of<cv::UMat*>():
return static_cast<const void*>(cv::util::get<cv::UMat*>(arg));
#endif
case GRunArgP::index_of<cv::Mat*>():
return static_cast<const void*>(cv::util::get<cv::Mat*>(arg));
case GRunArgP::index_of<cv::Scalar*>():
return static_cast<const void*>(cv::util::get<cv::Scalar*>(arg));
case GRunArgP::index_of<cv::detail::VectorRef>():
return cv::util::get<cv::detail::VectorRef>(arg).ptr();
case GRunArgP::index_of<cv::detail::OpaqueRef>():
return cv::util::get<cv::detail::OpaqueRef>(arg).ptr();
default:
util::throw_error(std::logic_error("Unknown GRunArgP type!"));
}
}

View File

@@ -28,8 +28,14 @@ GAPI_EXPORTS const GOrigin& origin_of (const GArg &arg);
bool is_dynamic(const GArg &arg);
GProtoArg rewrap (const GArg &arg);
// FIXME:: GAPI_EXPORTS because of tests only!!
GAPI_EXPORTS const void* ptr (const GRunArgP &arg);
} // proto
} // gimpl
} // cv
// FIXME: the gproto.cpp file has more functions that listed here
// where those are declared??
#endif // OPENCV_GAPI_GPROTO_PRIV_HPP

View File

@@ -8,7 +8,6 @@
#include "precomp.hpp"
#include <opencv2/gapi/gscalar.hpp>
#include <opencv2/gapi/own/convert.hpp>
#include "api/gorigin.hpp"
// cv::GScalar public implementation ///////////////////////////////////////////
@@ -47,6 +46,8 @@ const cv::GOrigin& cv::GScalar::priv() const
return *m_priv;
}
//N.B. if we ever need more complicated logic for desc_of(cv::(gapi::own::)Scalar)
//dispatching should be done in the same way as for cv::(gapi::own)::Mat
cv::GScalarDesc cv::descr_of(const cv::Scalar &)
{
return empty_scalar_desc();

View File

@@ -383,5 +383,15 @@ GMat warpAffine(const GMat& src, const Mat& M, const Size& dsize, int flags,
return core::GWarpAffine::on(src, M, dsize, flags, borderMode, borderValue);
}
GOpaque<Size> size(const GMat& src)
{
return core::GSize::on(src);
}
GOpaque<Size> size(const GOpaque<Rect>& r)
{
return core::GSizeR::on(r);
}
} //namespace gapi
} //namespace cv

View File

@@ -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-2020 Intel Corporation
#include "precomp.hpp"
@@ -87,6 +87,16 @@ std::tuple<GMat, GMat> SobelXY(const GMat& src, int ddepth, int order, int ksize
return imgproc::GSobelXY::on(src, ddepth, order, ksize, scale, delta, borderType, bordVal);
}
GMat Laplacian(const GMat& src, int ddepth, int ksize, double scale, double delta, int borderType)
{
return imgproc::GLaplacian::on(src, ddepth, ksize, scale, delta, borderType);
}
GMat bilateralFilter(const GMat& src, int d, double sigmaColor, double sigmaSpace, int borderType)
{
return imgproc::GBilateralFilter::on(src, d, sigmaColor, sigmaSpace, borderType);
}
GMat equalizeHist(const GMat& src)
{
return imgproc::GEqHist::on(src);
@@ -97,6 +107,14 @@ GMat Canny(const GMat& src, double thr1, double thr2, int apertureSize, bool l2g
return imgproc::GCanny::on(src, thr1, thr2, apertureSize, l2gradient);
}
cv::GArray<cv::Point2f> goodFeaturesToTrack(const GMat& image, int maxCorners, double qualityLevel,
double minDistance, const Mat& mask, int blockSize,
bool useHarrisDetector, double k)
{
return imgproc::GGoodFeatures::on(image, maxCorners, qualityLevel, minDistance, mask, blockSize,
useHarrisDetector, k);
}
GMat RGB2Gray(const GMat& src)
{
return imgproc::GRGB2Gray::on(src);

View File

@@ -0,0 +1,44 @@
// 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) 2020 Intel Corporation
#include "precomp.hpp"
#include <opencv2/gapi/infer/parsers.hpp>
#include <tuple>
#include <numeric>
namespace cv { namespace gapi {
nn::parsers::GDetections parseSSD(const GMat& in,
const GOpaque<Size>& inSz,
const float confidenceThreshold,
const int filterLabel)
{
return nn::parsers::GParseSSDBL::on(in, inSz, confidenceThreshold, filterLabel);
}
nn::parsers::GRects parseSSD(const GMat& in,
const GOpaque<Size>& inSz,
const float confidenceThreshold,
const bool alignmentToSquare,
const bool filterOutOfBounds)
{
return nn::parsers::GParseSSD::on(in, inSz, confidenceThreshold, alignmentToSquare, filterOutOfBounds);
}
nn::parsers::GDetections parseYolo(const GMat& in,
const GOpaque<Size>& inSz,
const float confidenceThreshold,
const float nmsThreshold,
const std::vector<float>& anchors)
{
return nn::parsers::GParseYolo::on(in, inSz, confidenceThreshold, nmsThreshold, anchors);
}
} //namespace gapi
} //namespace cv

View File

@@ -0,0 +1,56 @@
// 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) 2020 Intel Corporation
#include "precomp.hpp"
#include <opencv2/gapi/video.hpp>
namespace cv { namespace gapi {
using namespace video;
GBuildPyrOutput buildOpticalFlowPyramid(const GMat &img,
const Size &winSize,
const GScalar &maxLevel,
bool withDerivatives,
int pyrBorder,
int derivBorder,
bool tryReuseInputImage)
{
return GBuildOptFlowPyramid::on(img, winSize, maxLevel, withDerivatives, pyrBorder,
derivBorder, tryReuseInputImage);
}
GOptFlowLKOutput calcOpticalFlowPyrLK(const GMat &prevImg,
const GMat &nextImg,
const cv::GArray<cv::Point2f> &prevPts,
const cv::GArray<cv::Point2f> &predPts,
const Size &winSize,
const GScalar &maxLevel,
const TermCriteria &criteria,
int flags,
double minEigThresh)
{
return GCalcOptFlowLK::on(prevImg, nextImg, prevPts, predPts, winSize, maxLevel,
criteria, flags, minEigThresh);
}
GOptFlowLKOutput calcOpticalFlowPyrLK(const cv::GArray<cv::GMat> &prevPyr,
const cv::GArray<cv::GMat> &nextPyr,
const cv::GArray<cv::Point2f> &prevPts,
const cv::GArray<cv::Point2f> &predPts,
const Size &winSize,
const GScalar &maxLevel,
const TermCriteria &criteria,
int flags,
double minEigThresh)
{
return GCalcOptFlowLKForPyr::on(prevPyr, nextPyr, prevPts, predPts, winSize, maxLevel,
criteria, flags, minEigThresh);
}
} //namespace gapi
} //namespace cv

View File

@@ -12,6 +12,8 @@
#include <opencv2/gapi/gscalar.hpp>
#include <opencv2/gapi/operators.hpp>
namespace cv
{
cv::GMat operator+(const cv::GMat& lhs, const cv::GMat& rhs)
{
return cv::gapi::add(lhs, rhs);
@@ -211,3 +213,4 @@ cv::GMat operator!=(const cv::GScalar& lhs, const cv::GMat& rhs)
{
return cv::gapi::cmpNE(rhs, lhs);
}
} // cv

View File

@@ -0,0 +1,114 @@
// 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) 2020 Intel Corporation
#include <opencv2/gapi/s11n.hpp>
#include <opencv2/gapi/garg.hpp>
#include "backends/common/serialization.hpp"
std::vector<char> cv::gapi::serialize(const cv::GComputation &c) {
cv::gimpl::s11n::ByteMemoryOutStream os;
c.serialize(os);
return os.data();
}
cv::GComputation cv::gapi::detail::getGraph(const std::vector<char> &p) {
cv::gimpl::s11n::ByteMemoryInStream is(p);
return cv::GComputation(is);
}
cv::GMetaArgs cv::gapi::detail::getMetaArgs(const std::vector<char> &p) {
cv::gimpl::s11n::ByteMemoryInStream is(p);
return meta_args_deserialize(is);
}
cv::GRunArgs cv::gapi::detail::getRunArgs(const std::vector<char> &p) {
cv::gimpl::s11n::ByteMemoryInStream is(p);
return run_args_deserialize(is);
}
std::vector<char> cv::gapi::serialize(const cv::GMetaArgs& ma)
{
cv::gimpl::s11n::ByteMemoryOutStream os;
serialize(os, ma);
return os.data();
}
std::vector<char> cv::gapi::serialize(const cv::GRunArgs& ra)
{
cv::gimpl::s11n::ByteMemoryOutStream os;
serialize(os, ra);
return os.data();
}
// FIXME: This function should move from S11N to GRunArg-related entities.
// it has nothing to do with the S11N as it is
cv::GRunArgsP cv::gapi::bind(cv::GRunArgs &results)
{
cv::GRunArgsP outputs;
outputs.reserve(results.size());
for (cv::GRunArg &res_obj : results)
{
using T = cv::GRunArg;
switch (res_obj.index())
{
#if !defined(GAPI_STANDALONE)
case T::index_of<cv::UMat>() :
outputs.emplace_back((cv::UMat*)(&(cv::util::get<cv::UMat>(res_obj))));
break;
#endif
case cv::GRunArg::index_of<cv::Mat>() :
outputs.emplace_back((cv::Mat*)(&(cv::util::get<cv::Mat>(res_obj))));
break;
case cv::GRunArg::index_of<cv::Scalar>() :
outputs.emplace_back((cv::Scalar*)(&(cv::util::get<cv::Scalar>(res_obj))));
break;
case T::index_of<cv::detail::VectorRef>() :
outputs.emplace_back(cv::util::get<cv::detail::VectorRef>(res_obj));
break;
case T::index_of<cv::detail::OpaqueRef>() :
outputs.emplace_back(cv::util::get<cv::detail::OpaqueRef>(res_obj));
break;
default:
GAPI_Assert(false && "This value type is not supported!"); // ...maybe because of STANDALONE mode.
break;
}
}
return outputs;
}
// FIXME: move it out of s11n to api/
// FIXME: don't we have such function already?
cv::GRunArg cv::gapi::bind(cv::GRunArgP &out)
{
using T = cv::GRunArgP;
switch (out.index())
{
#if !defined(GAPI_STANDALONE)
case T::index_of<cv::UMat*>() :
GAPI_Assert(false && "Please implement this!");
break;
#endif
case T::index_of<cv::detail::VectorRef>() :
return cv::GRunArg(cv::util::get<cv::detail::VectorRef>(out));
case T::index_of<cv::detail::OpaqueRef>() :
return cv::GRunArg(cv::util::get<cv::detail::OpaqueRef>(out));
case T::index_of<cv::Mat*>() :
return cv::GRunArg(*cv::util::get<cv::Mat*>(out));
case T::index_of<cv::Scalar*>() :
return cv::GRunArg(*cv::util::get<cv::Scalar*>(out));
default:
// ...maybe our types were extended
GAPI_Assert(false && "This value type is UNKNOWN!");
break;
}
return cv::GRunArg();
}

View File

@@ -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-2020 Intel Corporation
#ifndef OPENCV_GAPI_GBACKEND_HPP
@@ -14,7 +14,6 @@
#include <ade/node.hpp>
#include "opencv2/gapi/garg.hpp"
#include "opencv2/gapi/own/mat.hpp"
#include "opencv2/gapi/util/optional.hpp"
@@ -45,9 +44,9 @@ namespace magazine {
} // namespace magazine
#if !defined(GAPI_STANDALONE)
using Mag = magazine::Class<cv::gapi::own::Mat, cv::UMat, cv::Scalar, cv::detail::VectorRef, cv::detail::OpaqueRef>;
using Mag = magazine::Class<cv::Mat, cv::UMat, cv::Scalar, cv::detail::VectorRef, cv::detail::OpaqueRef>;
#else
using Mag = magazine::Class<cv::gapi::own::Mat, cv::Scalar, cv::detail::VectorRef, cv::detail::OpaqueRef>;
using Mag = magazine::Class<cv::Mat, cv::Scalar, cv::detail::VectorRef, cv::detail::OpaqueRef>;
#endif
namespace magazine
@@ -88,20 +87,10 @@ struct GRuntimeArgs
template<typename T>
inline cv::util::optional<T> getCompileArg(const cv::GCompileArgs &args)
{
for (auto &compile_arg : args)
{
if (compile_arg.tag == cv::detail::CompileArgTag<T>::tag())
{
return cv::util::optional<T>(compile_arg.get<T>());
}
}
return cv::util::optional<T>();
return cv::gapi::getCompileArg<T>(args);
}
void createMat(const cv::GMatDesc& desc, cv::gapi::own::Mat& mat);
#if !defined(GAPI_STANDALONE)
void createMat(const cv::GMatDesc& desc, cv::Mat& mat);
#endif
}} // cv::gimpl

View File

@@ -32,7 +32,11 @@ cv::detail::GCompoundContext::GCompoundContext(const cv::GArgs& in_args)
{
case GShape::GMAT : m_args[i] = GArg(GMat()); break;
case GShape::GSCALAR: m_args[i] = GArg(GScalar()); break;
case GShape::GARRAY :/* do nothing - as handled in a special way, see gcompoundkernel.hpp for details */; break;
case GShape::GARRAY :
case GShape::GOPAQUE:
// do nothing - as handled in a special way, see gcompoundkernel.hpp for details
// same applies to GMatP
break;
default: GAPI_Assert(false);
}
}

View File

@@ -0,0 +1,837 @@
// 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) 2020 Intel Corporation
#include <set> // set
#include <map> // map
#include <ade/util/zip_range.hpp> // indexed
#define NOMINMAX
#ifdef _WIN32
#include <winsock.h> // htonl, ntohl
#else
#include <netinet/in.h> // htonl, ntohl
#endif
#include <opencv2/gapi/gtype_traits.hpp>
#include "backends/common/serialization.hpp"
namespace cv {
namespace gimpl {
namespace s11n {
namespace {
void putData(GSerialized& s, const GModel::ConstGraph& cg, const ade::NodeHandle &nh) {
const auto gdata = cg.metadata(nh).get<gimpl::Data>();
const auto it = ade::util::find_if(s.m_datas, [&gdata](const cv::gimpl::Data &cd) {
return cd.rc == gdata.rc && cd.shape == gdata.shape;
});
if (s.m_datas.end() == it) {
s.m_datas.push_back(gdata);
}
}
void putOp(GSerialized& s, const GModel::ConstGraph& cg, const ade::NodeHandle &nh) {
const auto& op = cg.metadata(nh).get<gimpl::Op>();
for (const auto &in_nh : nh->inNodes()) { putData(s, cg, in_nh); }
for (const auto &out_nh : nh->outNodes()) { putData(s, cg, out_nh); }
s.m_ops.push_back(op);
}
void mkDataNode(ade::Graph& g, const cv::gimpl::Data& data) {
GModel::Graph gm(g);
auto nh = gm.createNode();
gm.metadata(nh).set(NodeType{NodeType::DATA});
gm.metadata(nh).set(data);
}
void mkOpNode(ade::Graph& g, const cv::gimpl::Op& op) {
GModel::Graph gm(g);
auto nh = gm.createNode();
gm.metadata(nh).set(NodeType{NodeType::OP});
gm.metadata(nh).set(op);
}
void linkNodes(ade::Graph& g) {
std::map<cv::gimpl::RcDesc, ade::NodeHandle> dataNodes;
GModel::Graph gm(g);
for (const auto& nh : g.nodes()) {
if (gm.metadata(nh).get<NodeType>().t == NodeType::DATA) {
const auto &d = gm.metadata(nh).get<gimpl::Data>();
const auto rc = cv::gimpl::RcDesc{d.rc, d.shape, d.ctor};
dataNodes[rc] = nh;
}
}
for (const auto& nh : g.nodes()) {
if (gm.metadata(nh).get<NodeType>().t == NodeType::OP) {
const auto& op = gm.metadata(nh).get<gimpl::Op>();
for (const auto& in : ade::util::indexed(op.args)) {
const auto& arg = ade::util::value(in);
if (arg.kind == cv::detail::ArgKind::GOBJREF) {
const auto idx = ade::util::index(in);
const auto rc = arg.get<gimpl::RcDesc>();
const auto& in_nh = dataNodes.at(rc);
const auto& in_eh = g.link(in_nh, nh);
gm.metadata(in_eh).set(Input{idx});
}
}
for (const auto& out : ade::util::indexed(op.outs)) {
const auto idx = ade::util::index(out);
const auto rc = ade::util::value(out);
const auto& out_nh = dataNodes.at(rc);
const auto& out_eh = g.link(nh, out_nh);
gm.metadata(out_eh).set(Output{idx});
}
}
}
}
void relinkProto(ade::Graph& g) {
// identify which node handles map to the protocol
// input/output object in the reconstructed graph
using S = std::set<cv::gimpl::RcDesc>; // FIXME: use ...
using M = std::map<cv::gimpl::RcDesc, ade::NodeHandle>; // FIXME: unordered!
cv::gimpl::GModel::Graph gm(g);
auto &proto = gm.metadata().get<Protocol>();
const S set_in(proto.inputs.begin(), proto.inputs.end());
const S set_out(proto.outputs.begin(), proto.outputs.end());
M map_in, map_out;
// Associate the protocol node handles with their resource identifiers
for (auto &&nh : gm.nodes()) {
if (gm.metadata(nh).get<cv::gimpl::NodeType>().t == cv::gimpl::NodeType::DATA) {
const auto &d = gm.metadata(nh).get<cv::gimpl::Data>();
const auto rc = cv::gimpl::RcDesc{d.rc, d.shape, d.ctor};
if (set_in.count(rc) > 0) {
GAPI_DbgAssert(set_out.count(rc) == 0);
map_in[rc] = nh;
} else if (set_out.count(rc) > 0) {
GAPI_DbgAssert(set_in.count(rc) == 0);
map_out[rc] = nh;
}
}
}
// Reconstruct the protocol vectors, ordered
proto.in_nhs.reserve(proto.inputs.size());
proto.in_nhs.clear();
proto.out_nhs.reserve(proto.outputs.size());
proto.out_nhs.clear();
for (auto &rc : proto.inputs) { proto.in_nhs .push_back(map_in .at(rc)); }
for (auto &rc : proto.outputs) { proto.out_nhs.push_back(map_out.at(rc)); }
}
} // anonymous namespace
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Graph dump operators
// OpenCV types ////////////////////////////////////////////////////////////////
I::OStream& operator<< (I::OStream& os, const cv::Point &pt) {
return os << pt.x << pt.y;
}
I::IStream& operator>> (I::IStream& is, cv::Point& pt) {
return is >> pt.x >> pt.y;
}
I::OStream& operator<< (I::OStream& os, const cv::Size &sz) {
return os << sz.width << sz.height;
}
I::IStream& operator>> (I::IStream& is, cv::Size& sz) {
return is >> sz.width >> sz.height;
}
I::OStream& operator<< (I::OStream& os, const cv::Rect &rc) {
return os << rc.x << rc.y << rc.width << rc.height;
}
I::IStream& operator>> (I::IStream& is, cv::Rect& rc) {
return is >> rc.x >> rc.y >> rc.width >> rc.height;
}
I::OStream& operator<< (I::OStream& os, const cv::Scalar &s) {
return os << s.val[0] << s.val[1] << s.val[2] << s.val[3];
}
I::IStream& operator>> (I::IStream& is, cv::Scalar& s) {
return is >> s.val[0] >> s.val[1] >> s.val[2] >> s.val[3];
}
namespace
{
#if !defined(GAPI_STANDALONE)
template<typename T>
void write_plain(I::OStream &os, const T *arr, std::size_t sz) {
for (auto &&it : ade::util::iota(sz)) os << arr[it];
}
template<typename T>
void read_plain(I::IStream &is, T *arr, std::size_t sz) {
for (auto &&it : ade::util::iota(sz)) is >> arr[it];
}
template<typename T>
void write_mat_data(I::OStream &os, const cv::Mat &m) {
// Write every row individually (handles the case when Mat is a view)
for (auto &&r : ade::util::iota(m.rows)) {
write_plain(os, m.ptr<T>(r), m.cols*m.channels());
}
}
template<typename T>
void read_mat_data(I::IStream &is, cv::Mat &m) {
// Write every row individually (handles the case when Mat is aligned)
for (auto &&r : ade::util::iota(m.rows)) {
read_plain(is, m.ptr<T>(r), m.cols*m.channels());
}
}
#else
void write_plain(I::OStream &os, const uchar *arr, std::size_t sz) {
for (auto &&it : ade::util::iota(sz)) os << arr[it];
}
void read_plain(I::IStream &is, uchar *arr, std::size_t sz) {
for (auto &&it : ade::util::iota(sz)) is >> arr[it];
}
template<typename T>
void write_mat_data(I::OStream &os, const cv::Mat &m) {
// Write every row individually (handles the case when Mat is a view)
for (auto &&r : ade::util::iota(m.rows)) {
write_plain(os, m.ptr(r), m.cols*m.channels()*sizeof(T));
}
}
template<typename T>
void read_mat_data(I::IStream &is, cv::Mat &m) {
// Write every row individually (handles the case when Mat is aligned)
for (auto &&r : ade::util::iota(m.rows)) {
read_plain(is, m.ptr(r), m.cols*m.channels()*sizeof(T));
}
}
#endif
} // namespace
I::OStream& operator<< (I::OStream& os, const cv::Mat &m) {
#if !defined(GAPI_STANDALONE)
GAPI_Assert(m.size.dims() == 2 && "Only 2D images are supported now");
#else
GAPI_Assert(m.dims.size() == 2 && "Only 2D images are supported now");
#endif
os << m.rows << m.cols << m.type();
switch (m.depth()) {
case CV_8U: write_mat_data< uint8_t>(os, m); break;
case CV_8S: write_mat_data< char>(os, m); break;
case CV_16U: write_mat_data<uint16_t>(os, m); break;
case CV_16S: write_mat_data< int16_t>(os, m); break;
case CV_32S: write_mat_data< int32_t>(os, m); break;
case CV_32F: write_mat_data< float>(os, m); break;
case CV_64F: write_mat_data< double>(os, m); break;
default: GAPI_Assert(false && "Unsupported Mat depth");
}
return os;
}
I::IStream& operator>> (I::IStream& is, cv::Mat& m) {
int rows = -1, cols = -1, type = 0;
is >> rows >> cols >> type;
m.create(cv::Size(cols, rows), type);
switch (m.depth()) {
case CV_8U: read_mat_data< uint8_t>(is, m); break;
case CV_8S: read_mat_data< char>(is, m); break;
case CV_16U: read_mat_data<uint16_t>(is, m); break;
case CV_16S: read_mat_data< int16_t>(is, m); break;
case CV_32S: read_mat_data< int32_t>(is, m); break;
case CV_32F: read_mat_data< float>(is, m); break;
case CV_64F: read_mat_data< double>(is, m); break;
default: GAPI_Assert(false && "Unsupported Mat depth");
}
return is;
}
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Text &t) {
return os << t.bottom_left_origin << t.color << t.ff << t.fs << t.lt << t.org << t.text << t.thick;
}
I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Text &t) {
return is >> t.bottom_left_origin >> t.color >> t.ff >> t.fs >> t.lt >> t.org >> t.text >> t.thick;
}
I::OStream& operator<< (I::OStream&, const cv::gapi::wip::draw::FText &) {
GAPI_Assert(false && "Serialization: Unsupported << for FText");
}
I::IStream& operator>> (I::IStream&, cv::gapi::wip::draw::FText &) {
GAPI_Assert(false && "Serialization: Unsupported >> for FText");
}
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Circle &c) {
return os << c.center << c.color << c.lt << c.radius << c.shift << c.thick;
}
I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Circle &c) {
return is >> c.center >> c.color >> c.lt >> c.radius >> c.shift >> c.thick;
}
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Rect &r) {
return os << r.color << r.lt << r.rect << r.shift << r.thick;
}
I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Rect &r) {
return is >> r.color >> r.lt >> r.rect >> r.shift >> r.thick;
}
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Image &i) {
return os << i.org << i.alpha << i.img;
}
I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Image &i) {
return is >> i.org >> i.alpha >> i.img;
}
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Mosaic &m) {
return os << m.cellSz << m.decim << m.mos;
}
I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Mosaic &m) {
return is >> m.cellSz >> m.decim >> m.mos;
}
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Poly &p) {
return os << p.color << p.lt << p.points << p.shift << p.thick;
}
I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Poly &p) {
return is >> p.color >> p.lt >> p.points >> p.shift >> p.thick;
}
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Line &l) {
return os << l.color << l.lt << l.pt1 << l.pt2 << l.shift << l.thick;
}
I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Line &l) {
return is >> l.color >> l.lt >> l.pt1 >> l.pt2 >> l.shift >> l.thick;
}
// G-API types /////////////////////////////////////////////////////////////////
// Stubs (empty types)
I::OStream& operator<< (I::OStream& os, cv::util::monostate ) {return os;}
I::IStream& operator>> (I::IStream& is, cv::util::monostate &) {return is;}
I::OStream& operator<< (I::OStream& os, const cv::GScalarDesc &) {return os;}
I::IStream& operator>> (I::IStream& is, cv::GScalarDesc &) {return is;}
I::OStream& operator<< (I::OStream& os, const cv::GOpaqueDesc &) {return os;}
I::IStream& operator>> (I::IStream& is, cv::GOpaqueDesc &) {return is;}
I::OStream& operator<< (I::OStream& os, const cv::GArrayDesc &) {return os;}
I::IStream& operator>> (I::IStream& is, cv::GArrayDesc &) {return is;}
#if !defined(GAPI_STANDALONE)
I::OStream& operator<< (I::OStream& os, const cv::UMat &)
{
GAPI_Assert(false && "Serialization: Unsupported << for UMat");
return os;
}
I::IStream& operator >> (I::IStream& is, cv::UMat &)
{
GAPI_Assert(false && "Serialization: Unsupported >> for UMat");
return is;
}
#endif // !defined(GAPI_STANDALONE)
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::IStreamSource::Ptr &)
{
GAPI_Assert(false && "Serialization: Unsupported << for IStreamSource::Ptr");
return os;
}
I::IStream& operator >> (I::IStream& is, cv::gapi::wip::IStreamSource::Ptr &)
{
GAPI_Assert("Serialization: Unsupported >> for IStreamSource::Ptr");
return is;
}
namespace
{
template<typename Ref, typename T, typename... Ts>
struct putToStream;
template<typename Ref>
struct putToStream<Ref, std::tuple<>>
{
static void put(I::OStream&, const Ref &)
{
GAPI_Assert(false && "Unsupported type for GArray/GOpaque serialization");
}
};
template<typename Ref, typename T, typename... Ts>
struct putToStream<Ref, std::tuple<T, Ts...>>
{
static void put(I::OStream& os, const Ref &r)
{
if (r.getKind() == cv::detail::GOpaqueTraits<T>::kind) {
os << r.template rref<T>();
} else {
putToStream<Ref, std::tuple<Ts...> >::put(os, r);
}
}
};
template<typename Ref, typename T, typename... Ts>
struct getFromStream;
template<typename Ref>
struct getFromStream<Ref, std::tuple<>>
{
static void get(I::IStream&, Ref &, cv::detail::OpaqueKind)
{
GAPI_Assert(false && "Unsupported type for GArray/GOpaque deserialization");
}
};
template<typename Ref, typename T, typename... Ts>
struct getFromStream<Ref, std::tuple<T, Ts...>>
{
static void get(I::IStream& is, Ref &r, cv::detail::OpaqueKind kind) {
if (kind == cv::detail::GOpaqueTraits<T>::kind) {
r.template reset<T>();
auto& val = r.template wref<T>();
is >> val;
} else {
getFromStream<Ref, std::tuple<Ts...> >::get(is, r, kind);
}
}
};
}
I::OStream& operator<< (I::OStream& os, const cv::detail::VectorRef& ref)
{
os << ref.getKind();
putToStream<cv::detail::VectorRef, cv::detail::GOpaqueTraitsArrayTypes>::put(os, ref);
return os;
}
I::IStream& operator >> (I::IStream& is, cv::detail::VectorRef& ref)
{
cv::detail::OpaqueKind kind;
is >> kind;
getFromStream<cv::detail::VectorRef, cv::detail::GOpaqueTraitsArrayTypes>::get(is, ref, kind);
return is;
}
I::OStream& operator<< (I::OStream& os, const cv::detail::OpaqueRef& ref)
{
os << ref.getKind();
putToStream<cv::detail::OpaqueRef, cv::detail::GOpaqueTraitsOpaqueTypes>::put(os, ref);
return os;
}
I::IStream& operator >> (I::IStream& is, cv::detail::OpaqueRef& ref)
{
cv::detail::OpaqueKind kind;
is >> kind;
getFromStream<cv::detail::OpaqueRef, cv::detail::GOpaqueTraitsOpaqueTypes>::get(is, ref, kind);
return is;
}
// Enums and structures
namespace {
template<typename E> I::OStream& put_enum(I::OStream& os, E e) {
return os << static_cast<int>(e);
}
template<typename E> I::IStream& get_enum(I::IStream& is, E &e) {
int x{}; is >> x; e = static_cast<E>(x);
return is;
}
} // anonymous namespace
I::OStream& operator<< (I::OStream& os, cv::GShape sh) {
return put_enum(os, sh);
}
I::IStream& operator>> (I::IStream& is, cv::GShape &sh) {
return get_enum<cv::GShape>(is, sh);
}
I::OStream& operator<< (I::OStream& os, cv::detail::ArgKind k) {
return put_enum(os, k);
}
I::IStream& operator>> (I::IStream& is, cv::detail::ArgKind &k) {
return get_enum<cv::detail::ArgKind>(is, k);
}
I::OStream& operator<< (I::OStream& os, cv::detail::OpaqueKind k) {
return put_enum(os, k);
}
I::IStream& operator>> (I::IStream& is, cv::detail::OpaqueKind &k) {
return get_enum<cv::detail::OpaqueKind>(is, k);
}
I::OStream& operator<< (I::OStream& os, cv::gimpl::Data::Storage s) {
return put_enum(os, s);
}
I::IStream& operator>> (I::IStream& is, cv::gimpl::Data::Storage &s) {
return get_enum<cv::gimpl::Data::Storage>(is, s);
}
I::OStream& operator<< (I::OStream& os, const cv::GArg &arg) {
// Only GOBJREF and OPAQUE_VAL kinds can be serialized/deserialized
GAPI_Assert( arg.kind == cv::detail::ArgKind::OPAQUE_VAL
|| arg.kind == cv::detail::ArgKind::GOBJREF);
os << arg.kind << arg.opaque_kind;
if (arg.kind == cv::detail::ArgKind::GOBJREF) {
os << arg.get<cv::gimpl::RcDesc>();
} else {
GAPI_Assert(arg.kind == cv::detail::ArgKind::OPAQUE_VAL);
GAPI_Assert(arg.opaque_kind != cv::detail::OpaqueKind::CV_UNKNOWN);
switch (arg.opaque_kind) {
case cv::detail::OpaqueKind::CV_BOOL: os << arg.get<bool>(); break;
case cv::detail::OpaqueKind::CV_INT: os << arg.get<int>(); break;
case cv::detail::OpaqueKind::CV_DOUBLE: os << arg.get<double>(); break;
case cv::detail::OpaqueKind::CV_POINT: os << arg.get<cv::Point>(); break;
case cv::detail::OpaqueKind::CV_SIZE: os << arg.get<cv::Size>(); break;
case cv::detail::OpaqueKind::CV_RECT: os << arg.get<cv::Rect>(); break;
case cv::detail::OpaqueKind::CV_SCALAR: os << arg.get<cv::Scalar>(); break;
case cv::detail::OpaqueKind::CV_MAT: os << arg.get<cv::Mat>(); break;
default: GAPI_Assert(false && "GArg: Unsupported (unknown?) opaque value type");
}
}
return os;
}
I::IStream& operator>> (I::IStream& is, cv::GArg &arg) {
is >> arg.kind >> arg.opaque_kind;
// Only GOBJREF and OPAQUE_VAL kinds can be serialized/deserialized
GAPI_Assert( arg.kind == cv::detail::ArgKind::OPAQUE_VAL
|| arg.kind == cv::detail::ArgKind::GOBJREF);
if (arg.kind == cv::detail::ArgKind::GOBJREF) {
cv::gimpl::RcDesc rc;
is >> rc;
arg = (GArg(rc));
} else {
GAPI_Assert(arg.kind == cv::detail::ArgKind::OPAQUE_VAL);
GAPI_Assert(arg.opaque_kind != cv::detail::OpaqueKind::CV_UNKNOWN);
switch (arg.opaque_kind) {
#define HANDLE_CASE(E,T) case cv::detail::OpaqueKind::CV_##E: \
{ T t{}; is >> t; arg = (cv::GArg(t)); } break
HANDLE_CASE(BOOL , bool);
HANDLE_CASE(INT , int);
HANDLE_CASE(DOUBLE , double);
HANDLE_CASE(POINT , cv::Point);
HANDLE_CASE(SIZE , cv::Size);
HANDLE_CASE(RECT , cv::Rect);
HANDLE_CASE(SCALAR , cv::Scalar);
HANDLE_CASE(MAT , cv::Mat);
#undef HANDLE_CASE
default: GAPI_Assert(false && "GArg: Unsupported (unknown?) opaque value type");
}
}
return is;
}
I::OStream& operator<< (I::OStream& os, const cv::GKernel &k) {
return os << k.name << k.tag << k.outShapes;
}
I::IStream& operator>> (I::IStream& is, cv::GKernel &k) {
return is >> const_cast<std::string&>(k.name)
>> const_cast<std::string&>(k.tag)
>> const_cast<cv::GShapes&>(k.outShapes);
}
I::OStream& operator<< (I::OStream& os, const cv::GMatDesc &d) {
return os << d.depth << d.chan << d.size << d.planar << d.dims;
}
I::IStream& operator>> (I::IStream& is, cv::GMatDesc &d) {
return is >> d.depth >> d.chan >> d.size >> d.planar >> d.dims;
}
I::OStream& operator<< (I::OStream& os, const cv::gimpl::RcDesc &rc) {
// FIXME: HostCtor is not serialized!
return os << rc.id << rc.shape;
}
I::IStream& operator>> (I::IStream& is, cv::gimpl::RcDesc &rc) {
// FIXME: HostCtor is not deserialized!
return is >> rc.id >> rc.shape;
}
I::OStream& operator<< (I::OStream& os, const cv::gimpl::Op &op) {
return os << op.k << op.args << op.outs;
}
I::IStream& operator>> (I::IStream& is, cv::gimpl::Op &op) {
return is >> op.k >> op.args >> op.outs;
}
I::OStream& operator<< (I::OStream& os, const cv::gimpl::Data &d) {
// FIXME: HostCtor is not stored here!!
// FIXME: Storage may be incorrect for subgraph-to-graph process
return os << d.shape << d.rc << d.meta << d.storage << d.kind;
}
namespace
{
template<typename Ref, typename T, typename... Ts>
struct initCtor;
template<typename Ref>
struct initCtor<Ref, std::tuple<>>
{
static void init(cv::gimpl::Data&)
{
GAPI_Assert(false && "Unsupported type for GArray/GOpaque deserialization");
}
};
template<typename Ref, typename T, typename... Ts>
struct initCtor<Ref, std::tuple<T, Ts...>>
{
static void init(cv::gimpl::Data& d) {
if (d.kind == cv::detail::GOpaqueTraits<T>::kind) {
static std::function<void(Ref&)> ctor = [](Ref& ref){ref.template reset<T>();};
d.ctor = ctor;
} else {
initCtor<Ref, std::tuple<Ts...> >::init(d);
}
}
};
} // anonymous namespace
I::IStream& operator>> (I::IStream& is, cv::gimpl::Data &d) {
// FIXME: HostCtor is not stored here!!
// FIXME: Storage may be incorrect for subgraph-to-graph process
is >> d.shape >> d.rc >> d.meta >> d.storage >> d.kind;
if (d.shape == cv::GShape::GARRAY)
{
initCtor<cv::detail::VectorRef, cv::detail::GOpaqueTraitsArrayTypes>::init(d);
}
else if (d.shape == cv::GShape::GOPAQUE)
{
initCtor<cv::detail::OpaqueRef, cv::detail::GOpaqueTraitsOpaqueTypes>::init(d);
}
return is;
}
I::OStream& operator<< (I::OStream& os, const cv::gimpl::DataObjectCounter &c) {
return os << c.m_next_data_id;
}
I::IStream& operator>> (I::IStream& is, cv::gimpl::DataObjectCounter &c) {
return is >> c.m_next_data_id;
}
I::OStream& operator<< (I::OStream& os, const cv::gimpl::Protocol &p) {
// NB: in_nhs/out_nhs are not written!
return os << p.inputs << p.outputs;
}
I::IStream& operator>> (I::IStream& is, cv::gimpl::Protocol &p) {
// NB: in_nhs/out_nhs are reconstructed at a later phase
return is >> p.inputs >> p.outputs;
}
void serialize( I::OStream& os
, const ade::Graph &g
, const std::vector<ade::NodeHandle> &nodes) {
cv::gimpl::GModel::ConstGraph cg(g);
serialize(os, g, cg.metadata().get<cv::gimpl::Protocol>(), nodes);
}
void serialize( I::OStream& os
, const ade::Graph &g
, const cv::gimpl::Protocol &p
, const std::vector<ade::NodeHandle> &nodes) {
cv::gimpl::GModel::ConstGraph cg(g);
GSerialized s;
for (auto &nh : nodes) {
switch (cg.metadata(nh).get<NodeType>().t)
{
case NodeType::OP: putOp (s, cg, nh); break;
case NodeType::DATA: putData(s, cg, nh); break;
default: util::throw_error(std::logic_error("Unknown NodeType"));
}
}
s.m_counter = cg.metadata().get<cv::gimpl::DataObjectCounter>();
s.m_proto = p;
os << s.m_ops << s.m_datas << s.m_counter << s.m_proto;
}
GSerialized deserialize(I::IStream &is) {
GSerialized s;
is >> s.m_ops >> s.m_datas >> s.m_counter >> s.m_proto;
return s;
}
void reconstruct(const GSerialized &s, ade::Graph &g) {
GAPI_Assert(g.nodes().empty());
for (const auto& d : s.m_datas) cv::gimpl::s11n::mkDataNode(g, d);
for (const auto& op : s.m_ops) cv::gimpl::s11n::mkOpNode(g, op);
cv::gimpl::s11n::linkNodes(g);
cv::gimpl::GModel::Graph gm(g);
gm.metadata().set(s.m_counter);
gm.metadata().set(s.m_proto);
cv::gimpl::s11n::relinkProto(g);
gm.metadata().set(cv::gimpl::Deserialized{});
}
////////////////////////////////////////////////////////////////////////////////
// Streams /////////////////////////////////////////////////////////////////////
const std::vector<char>& ByteMemoryOutStream::data() const {
return m_storage;
}
I::OStream& ByteMemoryOutStream::operator<< (uint32_t atom) {
m_storage.push_back(0xFF & (atom));
m_storage.push_back(0xFF & (atom >> 8));
m_storage.push_back(0xFF & (atom >> 16));
m_storage.push_back(0xFF & (atom >> 24));
return *this;
}
I::OStream& ByteMemoryOutStream::operator<< (bool atom) {
m_storage.push_back(atom ? 1 : 0);
return *this;
}
I::OStream& ByteMemoryOutStream::operator<< (char atom) {
m_storage.push_back(atom);
return *this;
}
I::OStream& ByteMemoryOutStream::operator<< (unsigned char atom) {
return *this << static_cast<char>(atom);
}
I::OStream& ByteMemoryOutStream::operator<< (short atom) {
static_assert(sizeof(short) == 2, "Expecting sizeof(short) == 2");
m_storage.push_back(0xFF & (atom));
m_storage.push_back(0xFF & (atom >> 8));
return *this;
}
I::OStream& ByteMemoryOutStream::operator<< (unsigned short atom) {
return *this << static_cast<short>(atom);
}
I::OStream& ByteMemoryOutStream::operator<< (int atom) {
static_assert(sizeof(int) == 4, "Expecting sizeof(int) == 4");
return *this << static_cast<uint32_t>(atom);
}
//I::OStream& ByteMemoryOutStream::operator<< (std::size_t atom) {
// // NB: type truncated!
// return *this << static_cast<uint32_t>(atom);
//}
I::OStream& ByteMemoryOutStream::operator<< (float atom) {
static_assert(sizeof(float) == 4, "Expecting sizeof(float) == 4");
uint32_t tmp = 0u;
memcpy(&tmp, &atom, sizeof(float));
return *this << static_cast<uint32_t>(htonl(tmp));
}
I::OStream& ByteMemoryOutStream::operator<< (double atom) {
static_assert(sizeof(double) == 8, "Expecting sizeof(double) == 8");
uint32_t tmp[2] = {0u};
memcpy(tmp, &atom, sizeof(double));
*this << static_cast<uint32_t>(htonl(tmp[0]));
*this << static_cast<uint32_t>(htonl(tmp[1]));
return *this;
}
I::OStream& ByteMemoryOutStream::operator<< (const std::string &str) {
//*this << static_cast<std::size_t>(str.size()); // N.B. Put type explicitly
*this << static_cast<uint32_t>(str.size()); // N.B. Put type explicitly
for (auto c : str) *this << c;
return *this;
}
ByteMemoryInStream::ByteMemoryInStream(const std::vector<char> &data)
: m_storage(data) {
}
I::IStream& ByteMemoryInStream::operator>> (uint32_t &atom) {
check(sizeof(uint32_t));
uint8_t x[4];
x[0] = static_cast<uint8_t>(m_storage[m_idx++]);
x[1] = static_cast<uint8_t>(m_storage[m_idx++]);
x[2] = static_cast<uint8_t>(m_storage[m_idx++]);
x[3] = static_cast<uint8_t>(m_storage[m_idx++]);
atom = ((x[0]) | (x[1] << 8) | (x[2] << 16) | (x[3] << 24));
return *this;
}
I::IStream& ByteMemoryInStream::operator>> (bool& atom) {
check(sizeof(char));
atom = (m_storage[m_idx++] == 0) ? false : true;
return *this;
}
I::IStream& ByteMemoryInStream::operator>> (char &atom) {
check(sizeof(char));
atom = m_storage[m_idx++];
return *this;
}
I::IStream& ByteMemoryInStream::operator>> (unsigned char &atom) {
char c{};
*this >> c;
atom = static_cast<unsigned char>(c);
return *this;
}
I::IStream& ByteMemoryInStream::operator>> (short &atom) {
static_assert(sizeof(short) == 2, "Expecting sizeof(short) == 2");
check(sizeof(short));
uint8_t x[2];
x[0] = static_cast<uint8_t>(m_storage[m_idx++]);
x[1] = static_cast<uint8_t>(m_storage[m_idx++]);
atom = ((x[0]) | (x[1] << 8));
return *this;
}
I::IStream& ByteMemoryInStream::operator>> (unsigned short &atom) {
short s{};
*this >> s;
atom = static_cast<unsigned short>(s);
return *this;
}
I::IStream& ByteMemoryInStream::operator>> (int& atom) {
static_assert(sizeof(int) == 4, "Expecting sizeof(int) == 4");
atom = static_cast<int>(getU32());
return *this;
}
//I::IStream& ByteMemoryInStream::operator>> (std::size_t& atom) {
// // NB. Type was truncated!
// atom = static_cast<std::size_t>(getU32());
// return *this;
//}
I::IStream& ByteMemoryInStream::operator>> (float& atom) {
static_assert(sizeof(float) == 4, "Expecting sizeof(float) == 4");
uint32_t tmp = ntohl(getU32());
memcpy(&atom, &tmp, sizeof(float));
return *this;
}
I::IStream& ByteMemoryInStream::operator>> (double& atom) {
static_assert(sizeof(double) == 8, "Expecting sizeof(double) == 8");
uint32_t tmp[2] = {ntohl(getU32()), ntohl(getU32())};
memcpy(&atom, tmp, sizeof(double));
return *this;
}
I::IStream& ByteMemoryInStream::operator>> (std::string& str) {
//std::size_t sz = 0u;
uint32_t sz = 0u;
*this >> sz;
if (sz == 0u) {
str.clear();
} else {
str.resize(sz);
for (auto &&i : ade::util::iota(sz)) { *this >> str[i]; }
}
return *this;
}
GAPI_EXPORTS void serialize(I::OStream& os, const cv::GMetaArgs &ma) {
os << ma;
}
GAPI_EXPORTS void serialize(I::OStream& os, const cv::GRunArgs &ra) {
os << ra;
}
GAPI_EXPORTS GMetaArgs meta_args_deserialize(I::IStream& is) {
GMetaArgs s;
is >> s;
return s;
}
GAPI_EXPORTS GRunArgs run_args_deserialize(I::IStream& is) {
GRunArgs s;
is >> s;
return s;
}
} // namespace s11n
} // namespace gimpl
} // namespace cv

View File

@@ -0,0 +1,373 @@
#ifndef OPENCV_GAPI_COMMON_SERIALIZATION_HPP
#define OPENCV_GAPI_COMMON_SERIALIZATION_HPP
// 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) 2020 Intel Corporation
#include <iostream>
#include <fstream>
#include <string.h>
#include <ade/util/iota_range.hpp> // used in the vector<</>>
#include "compiler/gmodel.hpp"
#include "opencv2/gapi/render/render_types.hpp"
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
#pragma warning(disable: 4702)
#endif
namespace cv {
namespace gimpl {
namespace s11n {
struct GSerialized {
std::vector<cv::gimpl::Op> m_ops;
std::vector<cv::gimpl::Data> m_datas;
cv::gimpl::DataObjectCounter m_counter;
cv::gimpl::Protocol m_proto;
};
////////////////////////////////////////////////////////////////////////////////
// Stream interfaces, so far temporary
namespace I {
struct GAPI_EXPORTS OStream {
virtual ~OStream() = default;
// Define the native support for basic C++ types at the API level:
virtual OStream& operator<< (bool) = 0;
virtual OStream& operator<< (char) = 0;
virtual OStream& operator<< (unsigned char) = 0;
virtual OStream& operator<< (short) = 0;
virtual OStream& operator<< (unsigned short) = 0;
virtual OStream& operator<< (int) = 0;
//virtual OStream& operator<< (std::size_t) = 0;
virtual OStream& operator<< (uint32_t) = 0;
virtual OStream& operator<< (float) = 0;
virtual OStream& operator<< (double) = 0;
virtual OStream& operator<< (const std::string&) = 0;
};
struct GAPI_EXPORTS IStream {
virtual ~IStream() = default;
virtual IStream& operator>> (bool &) = 0;
virtual IStream& operator>> (char &) = 0;
virtual IStream& operator>> (unsigned char &) = 0;
virtual IStream& operator>> (short &) = 0;
virtual IStream& operator>> (unsigned short &) = 0;
virtual IStream& operator>> (int &) = 0;
virtual IStream& operator>> (float &) = 0;
virtual IStream& operator>> (double &) = 0;
//virtual IStream& operator>> (std::size_t &) = 0;
virtual IStream& operator >> (uint32_t &) = 0;
virtual IStream& operator>> (std::string &) = 0;
};
} // namespace I
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// S11N operators
// Note: operators for basic types are defined in IStream/OStream
// OpenCV types ////////////////////////////////////////////////////////////////
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::Point &pt);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::Point &pt);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::Size &sz);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::Size &sz);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::Rect &rc);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::Rect &rc);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::Scalar &s);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::Scalar &s);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::Mat &m);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::Mat &m);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Text &t);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Text &t);
GAPI_EXPORTS I::OStream& operator<< (I::OStream&, const cv::gapi::wip::draw::FText &);
GAPI_EXPORTS I::IStream& operator>> (I::IStream&, cv::gapi::wip::draw::FText &);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Circle &c);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Circle &c);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Rect &r);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Rect &r);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Image &i);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Image &i);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Mosaic &m);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Mosaic &m);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Poly &p);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Poly &p);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Line &l);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Line &l);
// G-API types /////////////////////////////////////////////////////////////////
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, cv::util::monostate );
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::util::monostate &);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, cv::GShape shape);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GShape &shape);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, cv::detail::ArgKind k);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::detail::ArgKind &k);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, cv::detail::OpaqueKind k);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::detail::OpaqueKind &k);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, cv::gimpl::Data::Storage s);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gimpl::Data::Storage &s);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gimpl::DataObjectCounter &c);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gimpl::DataObjectCounter &c);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gimpl::Protocol &p);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gimpl::Protocol &p);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GArg &arg);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GArg &arg);
//Forward declaration
//I::OStream& operator<< (I::OStream& os, const cv::GRunArg &arg);
//I::IStream& operator>> (I::IStream& is, cv::GRunArg &arg);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GKernel &k);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GKernel &k);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GMatDesc &d);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GMatDesc &d);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GScalarDesc &);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GScalarDesc &);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GOpaqueDesc &);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GOpaqueDesc &);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GArrayDesc &);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GArrayDesc &);
#if !defined(GAPI_STANDALONE)
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::UMat &);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::UMat &);
#endif // !defined(GAPI_STANDALONE)
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::IStreamSource::Ptr &);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::IStreamSource::Ptr &);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::detail::VectorRef &);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::detail::VectorRef &);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::detail::OpaqueRef &);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::detail::OpaqueRef &);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gimpl::RcDesc &rc);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gimpl::RcDesc &rc);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gimpl::Op &op);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gimpl::Op &op);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gimpl::Data &op);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gimpl::Data &op);
// The top-level serialization routine.
// Note it is just a single function which takes a GModel and a list of nodes
// and writes the data to the stream (recursively)
GAPI_EXPORTS void serialize( I::OStream& os
, const ade::Graph &g
, const std::vector<ade::NodeHandle> &nodes);
// The top-level serialization routine.
// Note it is just a single function which takes a GModel and a list of nodes
// and writes the data to the stream (recursively)
GAPI_EXPORTS void serialize( I::OStream& os
, const ade::Graph &g
, const cv::gimpl::Protocol &p
, const std::vector<ade::NodeHandle> &nodes);
// The top-level deserialization routineS.
// Unfortunately the deserialization is a two-step process:
// 1. First we decode a stream into some intermediate representation
// (called "GSerialized");
// 2. Then we produce an ade::Graph from this intermediate representation.
//
// An ade::Graph can't be produced from the stream immediately
// since every GCompiled object has its own unique ade::Graph, so
// we can't do it once and for all since every compilation process
// is individual and _is_ altering the ade::Graph state (structure and metadata).
// At the same time, we can't hold the reference to "is" within the GComputation
// forever since this input stream may be associated with an external resource
// and have side effects.
//
// Summarizing, the `deserialize()` happens *once per GComputation* immediately
// during the cv::gapi::deserialize<GComputation>(), and `reconstruct()` happens
// on every compilation process issued for this GComputation.
GAPI_EXPORTS GSerialized deserialize(I::IStream& is);
GAPI_EXPORTS void reconstruct(const GSerialized &s, ade::Graph &g);
// Legacy //////////////////////////////////////////////////////////////////////
// Generic: unordered_map serialization ////////////////////////////////////////
template<typename K, typename V>
I::OStream& operator<< (I::OStream& os, const std::unordered_map<K, V> &m) {
//const std::size_t sz = m.size(); // explicitly specify type
const uint32_t sz = (uint32_t)m.size(); // explicitly specify type
os << sz;
for (auto &&it : m) os << it.first << it.second;
return os;
}
template<typename K, typename V>
I::IStream& operator>> (I::IStream& is, std::unordered_map<K, V> &m) {
m.clear();
//std::size_t sz = 0u;
uint32_t sz = 0u;
is >> sz;
if (sz != 0u) {
for (auto &&i : ade::util::iota(sz)) {
(void) i;
K k{};
V v{};
is >> k >> v;
m.insert({k,v});
}
GAPI_Assert(sz == m.size());
}
return is;
}
// Generic: variant serialization //////////////////////////////////////////////
namespace detail { // FIXME: breaks old code
template<typename V>
I::OStream& put_v(I::OStream&, const V&, std::size_t) {
GAPI_Assert(false && "variant>>: requested index is invalid");
};
template<typename V, typename X, typename... Xs>
I::OStream& put_v(I::OStream& os, const V& v, std::size_t x) {
return (x == 0u)
? os << cv::util::get<X>(v)
: put_v<V, Xs...>(os, v, x-1);
}
template<typename V>
I::IStream& get_v(I::IStream&, V&, std::size_t, std::size_t) {
GAPI_Assert(false && "variant<<: requested index is invalid");
}
template<typename V, typename X, typename... Xs>
I::IStream& get_v(I::IStream& is, V& v, std::size_t i, std::size_t gi) {
if (i == gi) {
X x{};
is >> x;
v = std::move(x);
return is;
} else return get_v<V, Xs...>(is, v, i+1, gi);
}
} // namespace detail FIXME: breaks old code
template<typename... Ts>
I::OStream& operator<< (I::OStream& os, const cv::util::variant<Ts...> &v) {
os << (uint32_t)v.index();
return detail::put_v<cv::util::variant<Ts...>, Ts...>(os, v, v.index());
}
template<typename... Ts>
I::IStream& operator>> (I::IStream& is, cv::util::variant<Ts...> &v) {
int idx = -1;
is >> idx;
GAPI_Assert(idx >= 0 && idx < (int)sizeof...(Ts));
return detail::get_v<cv::util::variant<Ts...>, Ts...>(is, v, 0u, idx);
}
// Generic: vector serialization ///////////////////////////////////////////////
// Moved here to fix CLang issues https://clang.llvm.org/compatibility.html
// Unqualified lookup in templates
template<typename T>
I::OStream& operator<< (I::OStream& os, const std::vector<T> &ts) {
//const std::size_t sz = ts.size(); // explicitly specify type
const uint32_t sz = (uint32_t)ts.size(); // explicitly specify type
os << sz;
for (auto &&v : ts) os << v;
return os;
}
template<typename T>
I::IStream& operator >> (I::IStream& is, std::vector<T> &ts) {
//std::size_t sz = 0u;
uint32_t sz = 0u;
is >> sz;
if (sz == 0u) {
ts.clear();
}
else {
ts.resize(sz);
for (auto &&i : ade::util::iota(sz)) is >> ts[i];
}
return is;
}
// FIXME: Basic Stream implementaions //////////////////////////////////////////
// Basic in-memory stream implementations.
class GAPI_EXPORTS ByteMemoryOutStream final: public I::OStream {
std::vector<char> m_storage;
//virtual I::OStream& operator << (uint32_t) override;
//virtual I::OStream& operator<< (uint32_t) final;
public:
const std::vector<char>& data() const;
virtual I::OStream& operator<< (bool) override;
virtual I::OStream& operator<< (char) override;
virtual I::OStream& operator<< (unsigned char) override;
virtual I::OStream& operator<< (short) override;
virtual I::OStream& operator<< (unsigned short) override;
virtual I::OStream& operator<< (int) override;
//virtual I::OStream& operator<< (std::size_t) override;
virtual I::OStream& operator<< (float) override;
virtual I::OStream& operator<< (double) override;
virtual I::OStream& operator<< (const std::string&) override;
virtual I::OStream& operator<< (uint32_t) override;
};
class GAPI_EXPORTS ByteMemoryInStream final: public I::IStream {
const std::vector<char>& m_storage;
size_t m_idx = 0u;
void check(std::size_t n) { (void) n; GAPI_DbgAssert(m_idx+n-1 < m_storage.size()); }
uint32_t getU32() { uint32_t v{}; *this >> v; return v; };
//virtual I::IStream& operator>> (uint32_t &) final;
public:
explicit ByteMemoryInStream(const std::vector<char> &data);
virtual I::IStream& operator>> (bool &) override;
virtual I::IStream& operator>> (char &) override;
virtual I::IStream& operator>> (unsigned char &) override;
virtual I::IStream& operator>> (short &) override;
virtual I::IStream& operator>> (unsigned short &) override;
virtual I::IStream& operator>> (int &) override;
virtual I::IStream& operator>> (float &) override;
virtual I::IStream& operator>> (double &) override;
//virtual I::IStream& operator>> (std::size_t &) override;
virtual I::IStream& operator >> (uint32_t &) override;
virtual I::IStream& operator>> (std::string &) override;
};
GAPI_EXPORTS void serialize(I::OStream& os, const cv::GMetaArgs &ma);
GAPI_EXPORTS void serialize(I::OStream& os, const cv::GRunArgs &ra);
GAPI_EXPORTS GMetaArgs meta_args_deserialize(I::IStream& is);
GAPI_EXPORTS GRunArgs run_args_deserialize(I::IStream& is);
} // namespace s11n
} // namespace gimpl
} // namespace cv
#endif // OPENCV_GAPI_COMMON_SERIALIZATION_HPP

View File

@@ -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-2020 Intel Corporation
#include "precomp.hpp"
@@ -33,13 +33,13 @@
//
// If not, we need to introduce that!
using GCPUModel = ade::TypedGraph
< cv::gimpl::Unit
< cv::gimpl::CPUUnit
, cv::gimpl::Protocol
>;
// FIXME: Same issue with Typed and ConstTyped
using GConstGCPUModel = ade::ConstTypedGraph
< cv::gimpl::Unit
< cv::gimpl::CPUUnit
, cv::gimpl::Protocol
>;
@@ -53,14 +53,14 @@ namespace
{
GCPUModel gm(graph);
auto cpu_impl = cv::util::any_cast<cv::GCPUKernel>(impl.opaque);
gm.metadata(op_node).set(cv::gimpl::Unit{cpu_impl});
gm.metadata(op_node).set(cv::gimpl::CPUUnit{cpu_impl});
}
virtual EPtr compile(const ade::Graph &graph,
const cv::GCompileArgs &,
const cv::GCompileArgs &compileArgs,
const std::vector<ade::NodeHandle> &nodes) const override
{
return EPtr{new cv::gimpl::GCPUExecutable(graph, nodes)};
return EPtr{new cv::gimpl::GCPUExecutable(graph, compileArgs, nodes)};
}
};
}
@@ -73,16 +73,29 @@ cv::gapi::GBackend cv::gapi::cpu::backend()
// GCPUExecutable implementation //////////////////////////////////////////////
cv::gimpl::GCPUExecutable::GCPUExecutable(const ade::Graph &g,
const cv::GCompileArgs &compileArgs,
const std::vector<ade::NodeHandle> &nodes)
: m_g(g), m_gm(m_g)
: m_g(g), m_gm(m_g), m_compileArgs(compileArgs)
{
// Convert list of operations (which is topologically sorted already)
// into an execution script.
GConstGCPUModel gcm(m_g);
for (auto &nh : nodes)
{
switch (m_gm.metadata(nh).get<NodeType>().t)
{
case NodeType::OP: m_script.push_back({nh, GModel::collectOutputMeta(m_gm, nh)}); break;
case NodeType::OP:
{
m_script.push_back({nh, GModel::collectOutputMeta(m_gm, nh)});
// If kernel is stateful then prepare storage for its state.
GCPUKernel k = gcm.metadata(nh).get<CPUUnit>().k;
if (k.m_isStateful)
{
m_nodesToStates[nh] = GArg{ };
}
break;
}
case NodeType::DATA:
{
m_dataNodes.push_back(nh);
@@ -96,7 +109,7 @@ cv::gimpl::GCPUExecutable::GCPUExecutable(const ade::Graph &g,
if (desc.storage == Data::Storage::INTERNAL && desc.shape == GShape::GMAT)
{
const auto mat_desc = util::get<cv::GMatDesc>(desc.meta);
auto& mat = m_res.slot<cv::gapi::own::Mat>()[desc.rc];
auto& mat = m_res.slot<cv::Mat>()[desc.rc];
createMat(mat_desc, mat);
}
break;
@@ -104,6 +117,9 @@ cv::gimpl::GCPUExecutable::GCPUExecutable(const ade::Graph &g,
default: util::throw_error(std::logic_error("Unsupported NodeType type"));
}
}
// For each stateful kernel call 'setup' user callback to initialize state.
setupKernelStates();
}
// FIXME: Document what it does
@@ -128,7 +144,7 @@ cv::GArg cv::gimpl::GCPUExecutable::packArg(const GArg &arg)
const cv::gimpl::RcDesc &ref = arg.get<cv::gimpl::RcDesc>();
switch (ref.shape)
{
case GShape::GMAT: return GArg(m_res.slot<cv::gapi::own::Mat>() [ref.id]);
case GShape::GMAT: return GArg(m_res.slot<cv::Mat>() [ref.id]);
case GShape::GSCALAR: return GArg(m_res.slot<cv::Scalar>()[ref.id]);
// Note: .at() is intentional for GArray and GOpaque as objects MUST be already there
// (and constructed by either bindIn/Out or resetInternal)
@@ -140,6 +156,27 @@ cv::GArg cv::gimpl::GCPUExecutable::packArg(const GArg &arg)
}
}
void cv::gimpl::GCPUExecutable::setupKernelStates()
{
GConstGCPUModel gcm(m_g);
for (auto& nodeToState : m_nodesToStates)
{
auto& kernelNode = nodeToState.first;
auto& kernelState = nodeToState.second;
const GCPUKernel& kernel = gcm.metadata(kernelNode).get<CPUUnit>().k;
kernel.m_setupF(GModel::collectInputMeta(m_gm, kernelNode),
m_gm.metadata(kernelNode).get<Op>().args,
kernelState,
m_compileArgs);
}
}
void cv::gimpl::GCPUExecutable::handleNewStream()
{
m_newStreamStarted = true;
}
void cv::gimpl::GCPUExecutable::run(std::vector<InObj> &&input_objs,
std::vector<OutObj> &&output_objs)
{
@@ -157,7 +194,7 @@ void cv::gimpl::GCPUExecutable::run(std::vector<InObj> &&input_objs,
{
const auto &desc = gm.metadata(nh).get<Data>();
if ( desc.storage == Data::Storage::INTERNAL
if ( desc.storage == Data::Storage::INTERNAL // FIXME: to reconsider
&& !util::holds_alternative<util::monostate>(desc.ctor))
{
// FIXME: Note that compile-time constant data objects (like
@@ -167,6 +204,14 @@ void cv::gimpl::GCPUExecutable::run(std::vector<InObj> &&input_objs,
}
}
// In case if new video-stream happens - for each stateful kernel
// call 'setup' user callback to re-initialize state.
if (m_newStreamStarted)
{
setupKernelStates();
m_newStreamStarted = false;
}
// OpenCV backend execution is not a rocket science at all.
// Simply invoke our kernels in the proper order.
GConstGCPUModel gcm(m_g);
@@ -176,7 +221,7 @@ void cv::gimpl::GCPUExecutable::run(std::vector<InObj> &&input_objs,
// Obtain our real execution unit
// TODO: Should kernels be copyable?
GCPUKernel k = gcm.metadata(op_info.nh).get<Unit>().k;
GCPUKernel k = gcm.metadata(op_info.nh).get<CPUUnit>().k;
// Initialize kernel's execution context:
// - Input parameters
@@ -185,8 +230,8 @@ void cv::gimpl::GCPUExecutable::run(std::vector<InObj> &&input_objs,
using namespace std::placeholders;
ade::util::transform(op.args,
std::back_inserter(context.m_args),
std::bind(&GCPUExecutable::packArg, this, _1));
std::back_inserter(context.m_args),
std::bind(&GCPUExecutable::packArg, this, _1));
// - Output parameters.
// FIXME: pre-allocate internal Mats, etc, according to the known meta
@@ -198,8 +243,14 @@ void cv::gimpl::GCPUExecutable::run(std::vector<InObj> &&input_objs,
context.m_results[out_port] = magazine::getObjPtr(m_res, out_desc);
}
// For stateful kernel add state to its execution context
if (k.m_isStateful)
{
context.m_state = m_nodesToStates.at(op_info.nh);
}
// Now trigger the executable unit
k.apply(context);
k.m_runF(context);
//As Kernels are forbidden to allocate memory for (Mat) outputs,
//this code seems redundant, at least for Mats

View File

@@ -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-2020 Intel Corporation
#ifndef OPENCV_GAPI_GCPUBACKEND_HPP
@@ -23,7 +23,7 @@
namespace cv { namespace gimpl {
struct Unit
struct CPUUnit
{
static const char *name() { return "HostKernel"; }
GCPUKernel k;
@@ -33,6 +33,7 @@ class GCPUExecutable final: public GIslandExecutable
{
const ade::Graph &m_g;
GModel::ConstGraph m_gm;
const cv::GCompileArgs m_compileArgs;
struct OperationInfo
{
@@ -42,15 +43,27 @@ class GCPUExecutable final: public GIslandExecutable
// Execution script, currently absolutely naive
std::vector<OperationInfo> m_script;
// TODO: Check that it is thread-safe
// Map of stateful kernel nodes to their kernels' states
std::unordered_map<ade::NodeHandle, GArg,
ade::HandleHasher<ade::Node>> m_nodesToStates;
// List of all resources in graph (both internal and external)
std::vector<ade::NodeHandle> m_dataNodes;
// Actual data of all resources in graph (both internal and external)
Mag m_res;
// Flag which identifies if new stream was started
bool m_newStreamStarted = false;
GArg packArg(const GArg &arg);
void setupKernelStates();
public:
GCPUExecutable(const ade::Graph &graph,
const cv::GCompileArgs &compileArgs,
const std::vector<ade::NodeHandle> &nodes);
virtual inline bool canReshape() const override { return false; }
@@ -62,6 +75,8 @@ public:
util::throw_error(std::logic_error("GCPUExecutable::reshape() should never be called"));
}
virtual void handleNewStream() override;
virtual void run(std::vector<InObj> &&input_objs,
std::vector<OutObj> &&output_objs) override;
};

View File

@@ -6,6 +6,7 @@
#include "precomp.hpp"
#include "gnnparsers.hpp"
#include <opencv2/gapi/core.hpp>
#include <opencv2/gapi/cpu/core.hpp>
@@ -576,6 +577,63 @@ GAPI_OCV_KERNEL(GCPUWarpAffine, cv::gapi::core::GWarpAffine)
}
};
GAPI_OCV_KERNEL(GCPUParseSSDBL, cv::gapi::nn::parsers::GParseSSDBL)
{
static void run(const cv::Mat& in_ssd_result,
const cv::Size& in_size,
const float confidence_threshold,
const int filter_label,
std::vector<cv::Rect>& out_boxes,
std::vector<int>& out_labels)
{
cv::parseSSDBL(in_ssd_result, in_size, confidence_threshold, filter_label, out_boxes, out_labels);
}
};
GAPI_OCV_KERNEL(GOCVParseSSD, cv::gapi::nn::parsers::GParseSSD)
{
static void run(const cv::Mat& in_ssd_result,
const cv::Size& in_size,
const float confidence_threshold,
const bool alignment_to_square,
const bool filter_out_of_bounds,
std::vector<cv::Rect>& out_boxes)
{
cv::parseSSD(in_ssd_result, in_size, confidence_threshold, alignment_to_square, filter_out_of_bounds, out_boxes);
}
};
GAPI_OCV_KERNEL(GCPUParseYolo, cv::gapi::nn::parsers::GParseYolo)
{
static void run(const cv::Mat& in_yolo_result,
const cv::Size& in_size,
const float confidence_threshold,
const float nms_threshold,
const std::vector<float>& anchors,
std::vector<cv::Rect>& out_boxes,
std::vector<int>& out_labels)
{
cv::parseYolo(in_yolo_result, in_size, confidence_threshold, nms_threshold, anchors, out_boxes, out_labels);
}
};
GAPI_OCV_KERNEL(GCPUSize, cv::gapi::core::GSize)
{
static void run(const cv::Mat& in, cv::Size& out)
{
out.width = in.cols;
out.height = in.rows;
}
};
GAPI_OCV_KERNEL(GCPUSizeR, cv::gapi::core::GSizeR)
{
static void run(const cv::Rect& in, cv::Size& out)
{
out.width = in.width;
out.height = in.height;
}
};
cv::gapi::GKernelPackage cv::gapi::core::cpu::kernels()
{
@@ -647,6 +705,11 @@ cv::gapi::GKernelPackage cv::gapi::core::cpu::kernels()
, GCPUNormalize
, GCPUWarpPerspective
, GCPUWarpAffine
, GCPUParseSSDBL
, GOCVParseSSD
, GCPUParseYolo
, GCPUSize
, GCPUSizeR
>();
return pkg;
}

View File

@@ -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-2020 Intel Corporation
#include "precomp.hpp"
@@ -166,6 +166,24 @@ GAPI_OCV_KERNEL(GCPUSobelXY, cv::gapi::imgproc::GSobelXY)
}
};
GAPI_OCV_KERNEL(GCPULaplacian, cv::gapi::imgproc::GLaplacian)
{
static void run(const cv::Mat& in, int ddepth, int ksize, double scale,
double delta, int borderType, cv::Mat &out)
{
cv::Laplacian(in, out, ddepth, ksize, scale, delta, borderType);
}
};
GAPI_OCV_KERNEL(GCPUBilateralFilter, cv::gapi::imgproc::GBilateralFilter)
{
static void run(const cv::Mat& in, int d, double sigmaColor,
double sigmaSpace, int borderType, cv::Mat &out)
{
cv::bilateralFilter(in, out, d, sigmaColor, sigmaSpace, borderType);
}
};
GAPI_OCV_KERNEL(GCPUEqualizeHist, cv::gapi::imgproc::GEqHist)
{
static void run(const cv::Mat& in, cv::Mat &out)
@@ -182,6 +200,17 @@ GAPI_OCV_KERNEL(GCPUCanny, cv::gapi::imgproc::GCanny)
}
};
GAPI_OCV_KERNEL(GCPUGoodFeatures, cv::gapi::imgproc::GGoodFeatures)
{
static void run(const cv::Mat& image, int maxCorners, double qualityLevel, double minDistance,
const cv::Mat& mask, int blockSize, bool useHarrisDetector, double k,
std::vector<cv::Point2f> &out)
{
cv::goodFeaturesToTrack(image, out, maxCorners, qualityLevel, minDistance,
mask, blockSize, useHarrisDetector, k);
}
};
GAPI_OCV_KERNEL(GCPURGB2YUV, cv::gapi::imgproc::GRGB2YUV)
{
static void run(const cv::Mat& in, cv::Mat &out)
@@ -411,7 +440,10 @@ cv::gapi::GKernelPackage cv::gapi::imgproc::cpu::kernels()
, GCPUDilate
, GCPUSobel
, GCPUSobelXY
, GCPULaplacian
, GCPUBilateralFilter
, GCPUCanny
, GCPUGoodFeatures
, GCPUEqualizeHist
, GCPURGB2YUV
, GCPUYUV2RGB

View File

@@ -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-2020 Intel Corporation
#include "precomp.hpp"
@@ -11,14 +11,14 @@
#include <opencv2/gapi/cpu/gcpukernel.hpp>
const cv::gapi::own::Mat& cv::GCPUContext::inMat(int input)
const cv::Mat& cv::GCPUContext::inMat(int input)
{
return inArg<cv::gapi::own::Mat>(input);
return inArg<cv::Mat>(input);
}
cv::gapi::own::Mat& cv::GCPUContext::outMatR(int output)
cv::Mat& cv::GCPUContext::outMatR(int output)
{
return *util::get<cv::gapi::own::Mat*>(m_results.at(output));
return *util::get<cv::Mat*>(m_results.at(output));
}
const cv::Scalar& cv::GCPUContext::inVal(int input)
@@ -45,13 +45,7 @@ cv::GCPUKernel::GCPUKernel()
{
}
cv::GCPUKernel::GCPUKernel(const GCPUKernel::F &f)
: m_f(f)
cv::GCPUKernel::GCPUKernel(const GCPUKernel::RunF &runF, const GCPUKernel::SetupF &setupF)
: m_runF(runF), m_setupF(setupF), m_isStateful(m_setupF != nullptr)
{
}
void cv::GCPUKernel::apply(GCPUContext &ctx)
{
GAPI_Assert(m_f);
m_f(ctx);
}

View File

@@ -0,0 +1,100 @@
// 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) 2020 Intel Corporation
#include "precomp.hpp"
#include <opencv2/gapi/video.hpp>
#include <opencv2/gapi/cpu/video.hpp>
#include <opencv2/gapi/cpu/gcpukernel.hpp>
#ifdef HAVE_OPENCV_VIDEO
#include <opencv2/video.hpp>
#endif // HAVE_OPENCV_VIDEO
#ifdef HAVE_OPENCV_VIDEO
GAPI_OCV_KERNEL(GCPUBuildOptFlowPyramid, cv::gapi::video::GBuildOptFlowPyramid)
{
static void run(const cv::Mat &img,
const cv::Size &winSize,
const cv::Scalar &maxLevel,
bool withDerivatives,
int pyrBorder,
int derivBorder,
bool tryReuseInputImage,
std::vector<cv::Mat> &outPyr,
cv::Scalar &outMaxLevel)
{
outMaxLevel = cv::buildOpticalFlowPyramid(img, outPyr, winSize,
static_cast<int>(maxLevel[0]),
withDerivatives, pyrBorder,
derivBorder, tryReuseInputImage);
}
};
GAPI_OCV_KERNEL(GCPUCalcOptFlowLK, cv::gapi::video::GCalcOptFlowLK)
{
static void run(const cv::Mat &prevImg,
const cv::Mat &nextImg,
const std::vector<cv::Point2f> &prevPts,
const std::vector<cv::Point2f> &predPts,
const cv::Size &winSize,
const cv::Scalar &maxLevel,
const cv::TermCriteria &criteria,
int flags,
double minEigThresh,
std::vector<cv::Point2f> &outPts,
std::vector<uchar> &status,
std::vector<float> &err)
{
if (flags & cv::OPTFLOW_USE_INITIAL_FLOW)
outPts = predPts;
cv::calcOpticalFlowPyrLK(prevImg, nextImg, prevPts, outPts, status, err, winSize,
static_cast<int>(maxLevel[0]), criteria, flags, minEigThresh);
}
};
GAPI_OCV_KERNEL(GCPUCalcOptFlowLKForPyr, cv::gapi::video::GCalcOptFlowLKForPyr)
{
static void run(const std::vector<cv::Mat> &prevPyr,
const std::vector<cv::Mat> &nextPyr,
const std::vector<cv::Point2f> &prevPts,
const std::vector<cv::Point2f> &predPts,
const cv::Size &winSize,
const cv::Scalar &maxLevel,
const cv::TermCriteria &criteria,
int flags,
double minEigThresh,
std::vector<cv::Point2f> &outPts,
std::vector<uchar> &status,
std::vector<float> &err)
{
if (flags & cv::OPTFLOW_USE_INITIAL_FLOW)
outPts = predPts;
cv::calcOpticalFlowPyrLK(prevPyr, nextPyr, prevPts, outPts, status, err, winSize,
static_cast<int>(maxLevel[0]), criteria, flags, minEigThresh);
}
};
cv::gapi::GKernelPackage cv::gapi::video::cpu::kernels()
{
static auto pkg = cv::gapi::kernels
< GCPUBuildOptFlowPyramid
, GCPUCalcOptFlowLK
, GCPUCalcOptFlowLKForPyr
>();
return pkg;
}
#else
cv::gapi::GKernelPackage cv::gapi::video::cpu::kernels()
{
return GKernelPackage();
}
#endif // HAVE_OPENCV_VIDEO

View File

@@ -0,0 +1,338 @@
// 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) 2020 Intel Corporation
#include "gnnparsers.hpp"
namespace cv
{
namespace gapi
{
namespace nn
{
class YoloParser
{
public:
YoloParser(const float* out, const int side, const int lcoords, const int lclasses)
: m_out(out), m_side(side), m_lcoords(lcoords), m_lclasses(lclasses)
{}
float scale(const int i, const int b)
{
int obj_index = index(i, b, m_lcoords);
return m_out[obj_index];
}
double x(const int i, const int b)
{
int box_index = index(i, b, 0);
int col = i % m_side;
return (col + m_out[box_index]) / m_side;
}
double y(const int i, const int b)
{
int box_index = index(i, b, 0);
int row = i / m_side;
return (row + m_out[box_index + m_side * m_side]) / m_side;
}
double width(const int i, const int b, const float anchor)
{
int box_index = index(i, b, 0);
return std::exp(m_out[box_index + 2 * m_side * m_side]) * anchor / m_side;
}
double height(const int i, const int b, const float anchor)
{
int box_index = index(i, b, 0);
return std::exp(m_out[box_index + 3 * m_side * m_side]) * anchor / m_side;
}
float classConf(const int i, const int b, const int label)
{
int class_index = index(i, b, m_lcoords + 1 + label);
return m_out[class_index];
}
cv::Rect toBox(const double x, const double y, const double h, const double w, const cv::Size& in_sz)
{
auto h_scale = in_sz.height;
auto w_scale = in_sz.width;
cv::Rect r;
r.x = static_cast<int>((x - w / 2) * w_scale);
r.y = static_cast<int>((y - h / 2) * h_scale);
r.width = static_cast<int>(w * w_scale);
r.height = static_cast<int>(h * h_scale);
return r;
}
private:
const float* m_out = nullptr;
int m_side = 0, m_lcoords = 0, m_lclasses = 0;
int index(const int i, const int b, const int entry)
{
return b * m_side * m_side * (m_lcoords + m_lclasses + 1) + entry * m_side * m_side + i;
}
};
struct YoloParams
{
int num = 5;
int coords = 4;
};
struct Detection
{
Detection(const cv::Rect& in_rect, const float in_conf, const int in_label)
: rect(in_rect), conf(in_conf), label(in_label)
{}
cv::Rect rect;
float conf = 0.0f;
int label = 0;
};
class SSDParser
{
public:
SSDParser(const cv::MatSize& in_ssd_dims, const cv::Size& in_size, const float* data)
: m_dims(in_ssd_dims), m_maxProp(in_ssd_dims[2]), m_objSize(in_ssd_dims[3]),
m_data(data), m_surface(cv::Rect({0,0}, in_size)), m_size(in_size)
{
GAPI_Assert(in_ssd_dims.dims() == 4u); // Fixed output layout
GAPI_Assert(m_objSize == 7); // Fixed SSD object size
}
void adjustBoundingBox(cv::Rect& boundingBox)
{
auto w = boundingBox.width;
auto h = boundingBox.height;
boundingBox.x -= static_cast<int>(0.067 * w);
boundingBox.y -= static_cast<int>(0.028 * h);
boundingBox.width += static_cast<int>(0.15 * w);
boundingBox.height += static_cast<int>(0.13 * h);
if (boundingBox.width < boundingBox.height)
{
auto dx = (boundingBox.height - boundingBox.width);
boundingBox.x -= dx / 2;
boundingBox.width += dx;
}
else
{
auto dy = (boundingBox.width - boundingBox.height);
boundingBox.y -= dy / 2;
boundingBox.height += dy;
}
}
std::tuple<cv::Rect, float, float, int> extract(const size_t step)
{
const float* it = m_data + step * m_objSize;
float image_id = it[0];
int label = static_cast<int>(it[1]);
float confidence = it[2];
float rc_left = it[3];
float rc_top = it[4];
float rc_right = it[5];
float rc_bottom = it[6];
cv::Rect rc; // Map relative coordinates to the original image scale
rc.x = static_cast<int>(rc_left * m_size.width);
rc.y = static_cast<int>(rc_top * m_size.height);
rc.width = static_cast<int>(rc_right * m_size.width) - rc.x;
rc.height = static_cast<int>(rc_bottom * m_size.height) - rc.y;
return std::make_tuple(rc, image_id, confidence, label);
}
int getMaxProposals()
{
return m_maxProp;
}
cv::Rect getSurface()
{
return m_surface;
}
private:
const cv::MatSize m_dims;
int m_maxProp = 0, m_objSize = 0;
const float* m_data = nullptr;
const cv::Rect m_surface;
const cv::Size m_size;
};
} // namespace nn
} // namespace gapi
void parseSSDBL(const cv::Mat& in_ssd_result,
const cv::Size& in_size,
const float confidence_threshold,
const int filter_label,
std::vector<cv::Rect>& out_boxes,
std::vector<int>& out_labels)
{
cv::gapi::nn::SSDParser parser(in_ssd_result.size, in_size, in_ssd_result.ptr<float>());
out_boxes.clear();
out_labels.clear();
cv::Rect rc;
float image_id, confidence;
int label;
const size_t range = parser.getMaxProposals();
for (size_t i = 0; i < range; ++i)
{
std::tie(rc, image_id, confidence, label) = parser.extract(i);
if (image_id < 0.f)
{
break; // marks end-of-detections
}
if (confidence < confidence_threshold ||
(filter_label != -1 && label != filter_label))
{
continue; // filter out object classes if filter is specified
} // and skip objects with low confidence
out_boxes.emplace_back(rc & parser.getSurface());
out_labels.emplace_back(label);
}
}
void parseSSD(const cv::Mat& in_ssd_result,
const cv::Size& in_size,
const float confidence_threshold,
const bool alignment_to_square,
const bool filter_out_of_bounds,
std::vector<cv::Rect>& out_boxes)
{
cv::gapi::nn::SSDParser parser(in_ssd_result.size, in_size, in_ssd_result.ptr<float>());
out_boxes.clear();
cv::Rect rc;
float image_id, confidence;
int label;
const size_t range = parser.getMaxProposals();
for (size_t i = 0; i < range; ++i)
{
std::tie(rc, image_id, confidence, label) = parser.extract(i);
if (image_id < 0.f)
{
break; // marks end-of-detections
}
if (confidence < confidence_threshold)
{
continue; // skip objects with low confidence
}
if (alignment_to_square)
{
parser.adjustBoundingBox(rc);
}
const auto clipped_rc = rc & parser.getSurface();
if (filter_out_of_bounds)
{
if (clipped_rc.area() != rc.area())
{
continue;
}
}
out_boxes.emplace_back(clipped_rc);
}
}
void parseYolo(const cv::Mat& in_yolo_result,
const cv::Size& in_size,
const float confidence_threshold,
const float nms_threshold,
const std::vector<float>& anchors,
std::vector<cv::Rect>& out_boxes,
std::vector<int>& out_labels)
{
const auto& dims = in_yolo_result.size;
GAPI_Assert(dims.dims() == 4);
GAPI_Assert(dims[0] == 1);
GAPI_Assert(dims[1] == 13);
GAPI_Assert(dims[2] == 13);
GAPI_Assert(dims[3] % 5 == 0); // 5 boxes
const auto num_classes = dims[3] / 5 - 5;
GAPI_Assert(num_classes > 0);
GAPI_Assert(0 < nms_threshold && nms_threshold <= 1);
out_boxes.clear();
out_labels.clear();
gapi::nn::YoloParams params;
constexpr auto side = 13;
constexpr auto side_square = side * side;
const auto output = in_yolo_result.ptr<float>();
gapi::nn::YoloParser parser(output, side, params.coords, num_classes);
std::vector<gapi::nn::Detection> detections;
for (int i = 0; i < side_square; ++i)
{
for (int b = 0; b < params.num; ++b)
{
float scale = parser.scale(i, b);
if (scale < confidence_threshold)
{
continue;
}
double x = parser.x(i, b);
double y = parser.y(i, b);
double height = parser.height(i, b, anchors[2 * b + 1]);
double width = parser.width(i, b, anchors[2 * b]);
for (int label = 0; label < num_classes; ++label)
{
float prob = scale * parser.classConf(i,b,label);
if (prob < confidence_threshold)
{
continue;
}
auto box = parser.toBox(x, y, height, width, in_size);
detections.emplace_back(gapi::nn::Detection(box, prob, label));
}
}
}
std::stable_sort(std::begin(detections), std::end(detections),
[](const gapi::nn::Detection& a, const gapi::nn::Detection& b)
{
return a.conf > b.conf;
});
if (nms_threshold < 1.0f)
{
for (const auto& d : detections)
{
// Reject boxes which overlap with previously pushed ones
// (They are sorted by confidence, so rejected box
// always has a smaller confidence
if (std::end(out_boxes) ==
std::find_if(std::begin(out_boxes), std::end(out_boxes),
[&d, nms_threshold](const cv::Rect& r)
{
float rectOverlap = 1.f - static_cast<float>(jaccardDistance(r, d.rect));
return rectOverlap > nms_threshold;
}))
{
out_boxes. emplace_back(d.rect);
out_labels.emplace_back(d.label);
}
}
}
else
{
for (const auto& d: detections)
{
out_boxes. emplace_back(d.rect);
out_labels.emplace_back(d.label);
}
}
}
} // namespace cv

Some files were not shown because too many files have changed in this diff Show More