Merge pull request #12608 from dmatveev:gapi
* G-API Initial code upload * Update G-API code base to Sep-24-2018 * The majority of OpenCV buildbot problems was addressed * Update G-API code base to 24-Sep-18 EOD * G-API code base update 25-Sep-2018 * Linux warnings should be resolved * Documentation build should become green * Number of Windows warnings should be reduced * Update G-API code base to 25-Sep-18 EOD * ARMv7 build issue should be resolved * ADE is bumped to latest version and should fix Clang builds for macOS/iOS * Remaining Windows warnings should be resolved * New Linux32 / ARMv7 warnings should be resolved * G-API code base update 25-Sep-2018-EOD2 * Final Windows warnings should be resolved now * G-API code base update 26-Sep-2018 * Fixed issues with precompiled headers in module and its tests
This commit is contained in:
committed by
Alexander Alekhin
parent
852f061b26
commit
29e88e50ff
@@ -0,0 +1,21 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_HPP
|
||||
#define OPENCV_GAPI_HPP
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "opencv2/gapi/gmat.hpp"
|
||||
#include "opencv2/gapi/garray.hpp"
|
||||
#include "opencv2/gapi/gcomputation.hpp"
|
||||
#include "opencv2/gapi/gcompiled.hpp"
|
||||
#include "opencv2/gapi/gtyped.hpp"
|
||||
#include "opencv2/gapi/gkernel.hpp"
|
||||
#include "opencv2/gapi/operators.hpp"
|
||||
|
||||
#endif // OPENCV_GAPI_HPP
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_CPU_CORE_API_HPP
|
||||
#define OPENCV_GAPI_CPU_CORE_API_HPP
|
||||
|
||||
#include <opencv2/gapi/gkernel.hpp> // GKernelPackage
|
||||
#include "opencv2/gapi/own/exports.hpp" // GAPI_EXPORTS
|
||||
|
||||
namespace cv {
|
||||
namespace gapi {
|
||||
namespace core {
|
||||
namespace cpu {
|
||||
|
||||
GAPI_EXPORTS GKernelPackage kernels();
|
||||
|
||||
} // namespace cpu
|
||||
} // namespace core
|
||||
} // namespace gapi
|
||||
} // namespace cv
|
||||
|
||||
|
||||
#endif // OPENCV_GAPI_CPU_CORE_API_HPP
|
||||
@@ -0,0 +1,236 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GCPUKERNEL_HPP
|
||||
#define OPENCV_GAPI_GCPUKERNEL_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <opencv2/core/mat.hpp>
|
||||
#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/util/compiler_hints.hpp> //suppress_unused_warning
|
||||
|
||||
// FIXME: namespace scheme for backends?
|
||||
namespace cv {
|
||||
|
||||
namespace gimpl
|
||||
{
|
||||
// Forward-declare an internal class
|
||||
class GCPUExecutable;
|
||||
} // namespace gimpl
|
||||
|
||||
namespace gapi
|
||||
{
|
||||
namespace cpu
|
||||
{
|
||||
GAPI_EXPORTS cv::gapi::GBackend backend();
|
||||
} // namespace cpu
|
||||
} // namespace gapi
|
||||
|
||||
// Represents arguments which are passed to a wrapped CPU function
|
||||
// FIXME: put into detail?
|
||||
class GAPI_EXPORTS GCPUContext
|
||||
{
|
||||
public:
|
||||
// Generic accessor API
|
||||
template<typename T>
|
||||
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::gapi::own::Scalar& inVal(int input);
|
||||
cv::gapi::own::Scalar& outValR(int output); // FIXME: Avoid cv::gapi::own::Scalar s = ctx.outValR()
|
||||
template<typename T> std::vector<T>& outVecR(int output) // FIXME: the same issue
|
||||
{
|
||||
return outVecRef(output).wref<T>();
|
||||
}
|
||||
|
||||
protected:
|
||||
detail::VectorRef& outVecRef(int output);
|
||||
|
||||
std::vector<GArg> m_args;
|
||||
|
||||
//FIXME: avoid conversion of arguments from internal representaion to OpenCV one on each call
|
||||
//to OCV kernel. (This can be achieved by a two single time conversions in GCPUExecutable::run,
|
||||
//once on enter for input and output arguments, and once before return for output arguments only
|
||||
std::unordered_map<std::size_t, GRunArgP> m_results;
|
||||
|
||||
friend class gimpl::GCPUExecutable;
|
||||
};
|
||||
|
||||
class GAPI_EXPORTS GCPUKernel
|
||||
{
|
||||
public:
|
||||
// This function is kernel's execution entry point (does the processing work)
|
||||
using F = std::function<void(GCPUContext &)>;
|
||||
|
||||
GCPUKernel();
|
||||
explicit GCPUKernel(const F& f);
|
||||
|
||||
void apply(GCPUContext &ctx);
|
||||
|
||||
protected:
|
||||
F m_f;
|
||||
};
|
||||
|
||||
// FIXME: This is an ugly ad-hoc imlpementation. TODO: refactor
|
||||
|
||||
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)); }
|
||||
};
|
||||
template<> struct get_in<cv::GScalar>
|
||||
{
|
||||
static cv::Scalar get(GCPUContext &ctx, int idx) { return to_ocv(ctx.inVal(idx)); }
|
||||
};
|
||||
template<typename U> struct get_in<cv::GArray<U> >
|
||||
{
|
||||
static const std::vector<U>& get(GCPUContext &ctx, int idx) { return ctx.inArg<VectorRef>(idx).rref<U>(); }
|
||||
};
|
||||
template<class T> struct get_in
|
||||
{
|
||||
static T get(GCPUContext &ctx, int idx) { return ctx.inArg<T>(idx); }
|
||||
};
|
||||
|
||||
struct tracked_cv_mat{
|
||||
tracked_cv_mat(cv::gapi::own::Mat& m) : r{to_ocv(m)}, original_data{m.data} {}
|
||||
cv::Mat r;
|
||||
uchar* original_data;
|
||||
|
||||
operator cv::Mat& (){ return r;}
|
||||
void validate() const{
|
||||
if (r.data != original_data)
|
||||
{
|
||||
util::throw_error
|
||||
(std::logic_error
|
||||
("OpenCV kernel output parameter was reallocated. \n"
|
||||
"Incorrect meta data was provided ?"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct scalar_wrapper
|
||||
{
|
||||
scalar_wrapper(cv::gapi::own::Scalar& s) : m_s{cv::gapi::own::to_ocv(s)}, m_org_s(s) {};
|
||||
operator cv::Scalar& () { return m_s; }
|
||||
void writeBack() const { m_org_s = to_own(m_s); }
|
||||
|
||||
cv::Scalar m_s;
|
||||
cv::gapi::own::Scalar& m_org_s;
|
||||
};
|
||||
|
||||
template<typename... Outputs>
|
||||
void postprocess(Outputs&... outs)
|
||||
{
|
||||
struct
|
||||
{
|
||||
void operator()(tracked_cv_mat* bm) { bm->validate(); }
|
||||
void operator()(scalar_wrapper* sw) { sw->writeBack(); }
|
||||
void operator()(...) { }
|
||||
|
||||
} validate;
|
||||
//dummy array to unfold parameter pack
|
||||
int dummy[] = { 0, (validate(&outs), 0)... };
|
||||
cv::util::suppress_unused_warning(dummy);
|
||||
}
|
||||
|
||||
template<class T> struct get_out;
|
||||
template<> struct get_out<cv::GMat>
|
||||
{
|
||||
static tracked_cv_mat get(GCPUContext &ctx, int idx)
|
||||
{
|
||||
auto& r = ctx.outMatR(idx);
|
||||
return {r};
|
||||
}
|
||||
};
|
||||
template<> struct get_out<cv::GScalar>
|
||||
{
|
||||
static scalar_wrapper get(GCPUContext &ctx, int idx)
|
||||
{
|
||||
auto& s = ctx.outValR(idx);
|
||||
return {s};
|
||||
}
|
||||
};
|
||||
template<typename U> struct get_out<cv::GArray<U>>
|
||||
{
|
||||
static std::vector<U>& get(GCPUContext &ctx, int idx)
|
||||
{
|
||||
return ctx.outVecR<U>(idx);
|
||||
}
|
||||
};
|
||||
|
||||
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...> >
|
||||
{
|
||||
template<typename... Inputs>
|
||||
struct call_and_postprocess
|
||||
{
|
||||
template<typename... Outputs>
|
||||
static void call(Inputs&&... ins, Outputs&&... outs)
|
||||
{
|
||||
//not using a std::forward on outs is deliberate in order to
|
||||
//cause compilation error, by tring to bind rvalue references to lvalue references
|
||||
Impl::run(std::forward<Inputs>(ins)..., outs...);
|
||||
|
||||
postprocess(outs...);
|
||||
}
|
||||
};
|
||||
|
||||
template<int... IIs, int... OIs>
|
||||
static void call_impl(GCPUContext &ctx, detail::Seq<IIs...>, detail::Seq<OIs...>)
|
||||
{
|
||||
//Make sure that OpenCV kernels do not reallocate memory for output parameters
|
||||
//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)...);
|
||||
}
|
||||
|
||||
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 detail::OCVCallHelper<Impl, typename K::InArgs, typename K::OutArgs>
|
||||
{
|
||||
using P = 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); }
|
||||
};
|
||||
|
||||
#define GAPI_OCV_KERNEL(Name, API) struct Name: public cv::GCPUKernelImpl<Name, API>
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GCPUKERNEL_HPP
|
||||
@@ -0,0 +1,27 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_CPU_IMGPROC_API_HPP
|
||||
#define OPENCV_GAPI_CPU_IMGPROC_API_HPP
|
||||
|
||||
#include <opencv2/core/cvdef.h> // GAPI_EXPORTS
|
||||
#include <opencv2/gapi/gkernel.hpp> // GKernelPackage
|
||||
|
||||
namespace cv {
|
||||
namespace gapi {
|
||||
namespace imgproc {
|
||||
namespace cpu {
|
||||
|
||||
GAPI_EXPORTS GKernelPackage kernels();
|
||||
|
||||
} // namespace cpu
|
||||
} // namespace imgproc
|
||||
} // namespace gapi
|
||||
} // namespace cv
|
||||
|
||||
|
||||
#endif // OPENCV_GAPI_CPU_IMGPROC_API_HPP
|
||||
@@ -0,0 +1,120 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_FLUID_BUFFER_HPP
|
||||
#define OPENCV_GAPI_FLUID_BUFFER_HPP
|
||||
|
||||
#include <list>
|
||||
#include <numeric> // accumulate
|
||||
#include <ostream> // ostream
|
||||
#include <cstdint> // uint8_t
|
||||
|
||||
#include <opencv2/gapi/opencv_includes.hpp>
|
||||
#include <opencv2/gapi/gmat.hpp>
|
||||
|
||||
#include "opencv2/gapi/util/optional.hpp"
|
||||
#include "opencv2/gapi/own/scalar.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace gapi {
|
||||
namespace fluid {
|
||||
|
||||
struct Border
|
||||
{
|
||||
#if 1
|
||||
Border(int _type, cv::Scalar _val) : type(_type), value(to_own(_val)) {};
|
||||
#endif
|
||||
Border(int _type, cv::gapi::own::Scalar _val) : type(_type), value(_val) {};
|
||||
int type;
|
||||
cv::gapi::own::Scalar value;
|
||||
};
|
||||
|
||||
using BorderOpt = util::optional<Border>;
|
||||
|
||||
bool operator == (const Border& b1, const Border& b2);
|
||||
|
||||
class GAPI_EXPORTS Buffer;
|
||||
|
||||
class GAPI_EXPORTS View
|
||||
{
|
||||
public:
|
||||
View() = default;
|
||||
|
||||
const uint8_t* InLineB(int index) const; // -(w-1)/2...0...+(w-1)/2 for Filters
|
||||
template<typename T> const T* InLine(int i) const
|
||||
{
|
||||
const uint8_t* ptr = this->InLineB(i);
|
||||
return reinterpret_cast<const T*>(ptr);
|
||||
}
|
||||
|
||||
operator bool() const;
|
||||
bool ready() const;
|
||||
int length() const;
|
||||
int y() const;
|
||||
|
||||
GMatDesc meta() const;
|
||||
|
||||
class GAPI_EXPORTS Priv; // internal use only
|
||||
Priv& priv(); // internal use only
|
||||
const Priv& priv() const; // internal use only
|
||||
|
||||
View(Priv* p);
|
||||
|
||||
private:
|
||||
std::shared_ptr<Priv> m_priv;
|
||||
};
|
||||
|
||||
class GAPI_EXPORTS Buffer
|
||||
{
|
||||
public:
|
||||
// Default constructor (executable creation stage,
|
||||
// all following initialization performed in Priv::init())
|
||||
Buffer();
|
||||
// Scratch constructor (user kernels)
|
||||
Buffer(const cv::GMatDesc &desc);
|
||||
|
||||
// Constructor for intermediate buffers (for tests)
|
||||
Buffer(const cv::GMatDesc &desc,
|
||||
int max_line_consumption, int border_size,
|
||||
int skew,
|
||||
int wlpi,
|
||||
BorderOpt border);
|
||||
// Constructor for in/out buffers (for tests)
|
||||
Buffer(const cv::Mat &data, bool is_input);
|
||||
|
||||
uint8_t* OutLineB(int index = 0);
|
||||
template<typename T> T* OutLine(int index = 0)
|
||||
{
|
||||
uint8_t* ptr = this->OutLineB(index);
|
||||
return reinterpret_cast<T*>(ptr);
|
||||
}
|
||||
|
||||
int y() const;
|
||||
|
||||
int linesReady() const;
|
||||
void debug(std::ostream &os) const;
|
||||
int length() const;
|
||||
int lpi() const; // LPI for WRITER
|
||||
|
||||
GMatDesc meta() const;
|
||||
|
||||
View mkView(int lineConsumption, int borderSize, BorderOpt border, bool ownStorage);
|
||||
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
} // namespace cv::gapi::fluid
|
||||
} // namespace cv::gapi
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_FLUID_BUFFER_HPP
|
||||
@@ -0,0 +1,283 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_FLUID_KERNEL_HPP
|
||||
#define OPENCV_GAPI_FLUID_KERNEL_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <opencv2/gapi/opencv_includes.hpp>
|
||||
#include <opencv2/gapi/gcommon.hpp>
|
||||
#include <opencv2/gapi/gkernel.hpp>
|
||||
#include <opencv2/gapi/garg.hpp>
|
||||
#include <opencv2/gapi/own/types.hpp>
|
||||
|
||||
#include <opencv2/gapi/fluid/gfluidbuffer.hpp>
|
||||
|
||||
// FIXME: namespace scheme for backends?
|
||||
namespace cv {
|
||||
|
||||
namespace gapi
|
||||
{
|
||||
namespace fluid
|
||||
{
|
||||
GAPI_EXPORTS cv::gapi::GBackend backend();
|
||||
} // namespace flud
|
||||
} // namespace gapi
|
||||
|
||||
class GAPI_EXPORTS GFluidKernel
|
||||
{
|
||||
public:
|
||||
enum class Kind
|
||||
{
|
||||
Filter,
|
||||
Resize
|
||||
};
|
||||
|
||||
// This function is a generic "doWork" callback
|
||||
using F = std::function<void(const cv::GArgs&, const std::vector<gapi::fluid::Buffer*> &)>;
|
||||
|
||||
// This function is a generic "initScratch" callback
|
||||
using IS = std::function<void(const cv::GMetaArgs &, const cv::GArgs&, gapi::fluid::Buffer &)>;
|
||||
|
||||
// This function is a generic "resetScratch" callback
|
||||
using RS = std::function<void(gapi::fluid::Buffer &)>;
|
||||
|
||||
// This function describes kernel metadata inference rule.
|
||||
using M = std::function<GMetaArgs(const GMetaArgs &, const GArgs &)>;
|
||||
|
||||
// This function is a generic "getBorder" callback (extracts border-related data from kernel's input parameters)
|
||||
using B = std::function<gapi::fluid::BorderOpt(const GMetaArgs&, const GArgs&)>;
|
||||
|
||||
// FIXME: move implementations out of header file
|
||||
GFluidKernel() {}
|
||||
GFluidKernel(int w, Kind k, int l, bool scratch, const F& f, const IS &is, const RS &rs, const B& b)
|
||||
: m_window(w)
|
||||
, m_kind(k)
|
||||
, m_lpi(l)
|
||||
, m_scratch(scratch)
|
||||
, m_f(f)
|
||||
, m_is(is)
|
||||
, m_rs(rs)
|
||||
, m_b(b) {}
|
||||
|
||||
int m_window = -1;
|
||||
Kind m_kind;
|
||||
const int m_lpi = -1;
|
||||
const bool m_scratch = false;
|
||||
|
||||
const F m_f;
|
||||
const IS m_is;
|
||||
const RS m_rs;
|
||||
const B m_b;
|
||||
};
|
||||
|
||||
// FIXME!!!
|
||||
// This is the temporary and experimental API
|
||||
// which should be replaced by runtime roi-based scheduling
|
||||
struct GFluidOutputRois
|
||||
{
|
||||
std::vector<cv::gapi::own::Rect> rois;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<> struct CompileArgTag<GFluidOutputRois>
|
||||
{
|
||||
static const char* tag() { return "gapi.fluid.outputRois"; }
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<class T> struct fluid_get_in;
|
||||
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].get<cv::gapi::fluid::View>();
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct fluid_get_in<cv::GScalar>
|
||||
{
|
||||
static const cv::Scalar get(const cv::GArgs &in_args, int idx)
|
||||
{
|
||||
return cv::gapi::own::to_ocv(in_args[idx].get<cv::gapi::own::Scalar>());
|
||||
}
|
||||
};
|
||||
template<class T> struct fluid_get_in
|
||||
{
|
||||
static T get(const cv::GArgs &in_args, int idx)
|
||||
{
|
||||
return in_args[idx].get<T>();
|
||||
}
|
||||
};
|
||||
|
||||
template<bool, typename Impl, typename... Ins>
|
||||
struct scratch_helper;
|
||||
|
||||
template<typename Impl, typename... Ins>
|
||||
struct scratch_helper<true, Impl, Ins...>
|
||||
{
|
||||
// Init
|
||||
template<int... IIs>
|
||||
static void help_init_impl(const cv::GMetaArgs &metas,
|
||||
const cv::GArgs &in_args,
|
||||
gapi::fluid::Buffer &scratch_buf,
|
||||
detail::Seq<IIs...>)
|
||||
{
|
||||
Impl::initScratch(get_in_meta<Ins>(metas, in_args, IIs)..., scratch_buf);
|
||||
}
|
||||
|
||||
static void help_init(const cv::GMetaArgs &metas,
|
||||
const cv::GArgs &in_args,
|
||||
gapi::fluid::Buffer &b)
|
||||
{
|
||||
help_init_impl(metas, in_args, b, typename detail::MkSeq<sizeof...(Ins)>::type());
|
||||
}
|
||||
|
||||
// Reset
|
||||
static void help_reset(gapi::fluid::Buffer &b)
|
||||
{
|
||||
Impl::resetScratch(b);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Impl, typename... Ins>
|
||||
struct scratch_helper<false, Impl, Ins...>
|
||||
{
|
||||
static void help_init(const cv::GMetaArgs &,
|
||||
const cv::GArgs &,
|
||||
gapi::fluid::Buffer &)
|
||||
{
|
||||
GAPI_Assert(false);
|
||||
}
|
||||
static void help_reset(gapi::fluid::Buffer &)
|
||||
{
|
||||
GAPI_Assert(false);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct is_gmat_type
|
||||
{
|
||||
static const constexpr bool value = std::is_same<cv::GMat, T>::value;
|
||||
};
|
||||
|
||||
template<bool CallCustomGetBorder, typename Impl, typename... Ins>
|
||||
struct get_border_helper;
|
||||
|
||||
template<typename Impl, typename... Ins>
|
||||
struct get_border_helper<true, Impl, Ins...>
|
||||
{
|
||||
template<int... IIs>
|
||||
static gapi::fluid::BorderOpt get_border_impl(const GMetaArgs &metas,
|
||||
const cv::GArgs &in_args,
|
||||
cv::detail::Seq<IIs...>)
|
||||
{
|
||||
return util::make_optional(Impl::getBorder(cv::detail::get_in_meta<Ins>(metas, in_args, IIs)...));
|
||||
}
|
||||
|
||||
static gapi::fluid::BorderOpt help(const GMetaArgs &metas,
|
||||
const cv::GArgs &in_args)
|
||||
{
|
||||
return get_border_impl(metas, in_args, typename detail::MkSeq<sizeof...(Ins)>::type());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Impl, typename... Ins>
|
||||
struct get_border_helper<false, Impl, Ins...>
|
||||
{
|
||||
static gapi::fluid::BorderOpt help(const cv::GMetaArgs &,
|
||||
const cv::GArgs &)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename, typename, typename, bool UseScratch>
|
||||
struct FluidCallHelper;
|
||||
|
||||
template<typename Impl, typename... Ins, typename... Outs, bool UseScratch>
|
||||
struct FluidCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>, UseScratch>
|
||||
{
|
||||
static_assert(all_satisfy<is_gmat_type, Outs...>::value, "return type must be GMat");
|
||||
|
||||
// Execution dispatcher ////////////////////////////////////////////////////
|
||||
template<int... IIs, int... OIs>
|
||||
static void call_impl(const cv::GArgs &in_args,
|
||||
const std::vector<gapi::fluid::Buffer*> &out_bufs,
|
||||
detail::Seq<IIs...>,
|
||||
detail::Seq<OIs...>)
|
||||
{
|
||||
Impl::run(fluid_get_in<Ins>::get(in_args, IIs)..., *out_bufs[OIs]...);
|
||||
}
|
||||
|
||||
static void call(const cv::GArgs &in_args,
|
||||
const std::vector<gapi::fluid::Buffer*> &out_bufs)
|
||||
{
|
||||
constexpr int numOuts = (sizeof...(Outs)) + (UseScratch ? 1 : 0);
|
||||
call_impl(in_args, out_bufs,
|
||||
typename detail::MkSeq<sizeof...(Ins)>::type(),
|
||||
typename detail::MkSeq<numOuts>::type());
|
||||
}
|
||||
|
||||
// Scratch buffer initialization dispatcher ////////////////////////////////
|
||||
static void init_scratch(const GMetaArgs &metas,
|
||||
const cv::GArgs &in_args,
|
||||
gapi::fluid::Buffer &b)
|
||||
{
|
||||
scratch_helper<UseScratch, Impl, Ins...>::help_init(metas, in_args, b);
|
||||
}
|
||||
|
||||
// Scratch buffer reset dispatcher /////////////////////////////////////////
|
||||
static void reset_scratch(gapi::fluid::Buffer &scratch_buf)
|
||||
{
|
||||
scratch_helper<UseScratch, Impl, Ins...>::help_reset(scratch_buf);
|
||||
}
|
||||
|
||||
static gapi::fluid::BorderOpt getBorder(const GMetaArgs &metas, const cv::GArgs &in_args)
|
||||
{
|
||||
// User must provide "init" callback if Window != 1
|
||||
// TODO: move to constexpr if when we enable C++17
|
||||
constexpr bool callCustomGetBorder = (Impl::Window != 1);
|
||||
return get_border_helper<callCustomGetBorder, Impl, Ins...>::help(metas, in_args);
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
|
||||
template<class Impl, class K, bool UseScratch>
|
||||
class GFluidKernelImpl
|
||||
{
|
||||
static const int LPI = 1;
|
||||
static const auto Kind = GFluidKernel::Kind::Filter;
|
||||
using P = detail::FluidCallHelper<Impl, typename K::InArgs, typename K::OutArgs, UseScratch>;
|
||||
|
||||
public:
|
||||
using API = K;
|
||||
|
||||
static GFluidKernel kernel()
|
||||
{
|
||||
// FIXME: call() and getOutMeta() needs to be renamed so it is clear these
|
||||
// functions are internal wrappers, not user API
|
||||
return GFluidKernel(Impl::Window, Impl::Kind, Impl::LPI,
|
||||
UseScratch,
|
||||
&P::call, &P::init_scratch, &P::reset_scratch, &P::getBorder);
|
||||
}
|
||||
|
||||
static cv::gapi::GBackend backend() { return cv::gapi::fluid::backend(); }
|
||||
};
|
||||
|
||||
#define GAPI_FLUID_KERNEL(Name, API, Scratch) struct Name: public cv::GFluidKernelImpl<Name, API, Scratch>
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GCPUKERNEL_HPP
|
||||
@@ -0,0 +1,98 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GARG_HPP
|
||||
#define OPENCV_GAPI_GARG_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
|
||||
#include <opencv2/gapi/opencv_includes.hpp>
|
||||
#include "opencv2/gapi/own/mat.hpp"
|
||||
|
||||
#include "opencv2/gapi/util/any.hpp"
|
||||
#include "opencv2/gapi/util/variant.hpp"
|
||||
|
||||
#include "opencv2/gapi/gmat.hpp"
|
||||
#include "opencv2/gapi/gscalar.hpp"
|
||||
#include "opencv2/gapi/garray.hpp"
|
||||
#include "opencv2/gapi/gtype_traits.hpp"
|
||||
#include "opencv2/gapi/gmetaarg.hpp"
|
||||
#include "opencv2/gapi/own/scalar.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
class GArg;
|
||||
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
using is_garg = std::is_same<GArg, typename std::decay<T>::type>;
|
||||
}
|
||||
|
||||
// Parameter holder class for a node
|
||||
// Depending on platform capabilities, can either support arbitrary types
|
||||
// (as `boost::any`) or a limited number of types (as `boot::variant`).
|
||||
// FIXME: put into "details" as a user shouldn't use it in his code
|
||||
class GAPI_EXPORTS GArg
|
||||
{
|
||||
public:
|
||||
GArg() {}
|
||||
|
||||
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)
|
||||
, value(detail::wrap_gapi_helper<T>::wrap(t))
|
||||
{
|
||||
}
|
||||
|
||||
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)
|
||||
, value(detail::wrap_gapi_helper<T>::wrap(t))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T> T& get()
|
||||
{
|
||||
return util::any_cast<typename std::remove_reference<T>::type>(value);
|
||||
}
|
||||
|
||||
template<typename T> const T& get() const
|
||||
{
|
||||
return util::any_cast<typename std::remove_reference<T>::type>(value);
|
||||
}
|
||||
|
||||
detail::ArgKind kind = detail::ArgKind::OPAQUE;
|
||||
|
||||
protected:
|
||||
util::any value;
|
||||
};
|
||||
|
||||
using GArgs = std::vector<GArg>;
|
||||
|
||||
// FIXME: Express as M<GProtoArg...>::type
|
||||
// FIXME: Move to a separate file!
|
||||
using GRunArg = util::variant<cv::Mat, cv::gapi::own::Mat, cv::Scalar, cv::gapi::own::Scalar, cv::detail::VectorRef>;
|
||||
using GRunArgs = std::vector<GRunArg>;
|
||||
|
||||
using GRunArgP = util::variant<cv::Mat*, cv::gapi::own::Mat*, cv::Scalar*, cv::gapi::own::Scalar*, cv::detail::VectorRef>;
|
||||
using GRunArgsP = std::vector<GRunArgP>;
|
||||
|
||||
|
||||
template<typename... Ts> inline GRunArgs gin(const Ts&... args)
|
||||
{
|
||||
return GRunArgs{ GRunArg(detail::wrap_host_helper<Ts>::wrap_in(args))... };
|
||||
}
|
||||
|
||||
template<typename... Ts> inline GRunArgsP gout(Ts&... args)
|
||||
{
|
||||
return GRunArgsP{ GRunArgP(detail::wrap_host_helper<Ts>::wrap_out(args))... };
|
||||
}
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GARG_HPP
|
||||
@@ -0,0 +1,239 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GARRAY_HPP
|
||||
#define OPENCV_GAPI_GARRAY_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include <opencv2/gapi/own/exports.hpp>
|
||||
#include <opencv2/gapi/opencv_includes.hpp>
|
||||
|
||||
#include <opencv2/gapi/util/variant.hpp>
|
||||
#include <opencv2/gapi/util/throw.hpp>
|
||||
#include "opencv2/gapi/own/assert.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
// Forward declaration; GNode and GOrigin are an internal
|
||||
// (user-inaccessible) classes.
|
||||
class GNode;
|
||||
struct GOrigin;
|
||||
|
||||
template<typename T> class GArray;
|
||||
|
||||
struct GArrayDesc
|
||||
{
|
||||
// FIXME: Body
|
||||
// FIXME: Also implement proper operator== then
|
||||
bool operator== (const GArrayDesc&) const { return true; }
|
||||
};
|
||||
template<typename U> GArrayDesc descr_of(const std::vector<U> &) { return {};}
|
||||
inline GArrayDesc empty_array_desc() {return {}; }
|
||||
std::ostream& operator<<(std::ostream& os, const cv::GArrayDesc &desc);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// ConstructVec is a callback which stores information about T and is used by
|
||||
// G-API runtime to construct arrays in host memory (T remains opaque for G-API).
|
||||
// ConstructVec is carried into G-API internals by GArrayU.
|
||||
// Currently it is suitable for Host (CPU) plugins only, real offload may require
|
||||
// more information for manual memory allocation on-device.
|
||||
class VectorRef;
|
||||
using ConstructVec = std::function<void(VectorRef&)>;
|
||||
|
||||
|
||||
// This class strips type information from GArray<T> and makes it usable
|
||||
// in the G-API graph compiler (expression unrolling, graph generation, etc).
|
||||
// Part of GProtoArg.
|
||||
class GAPI_EXPORTS GArrayU
|
||||
{
|
||||
public:
|
||||
GArrayU(const GNode &n, std::size_t out); // Operation result constructor
|
||||
|
||||
GOrigin& priv(); // Internal use only
|
||||
const GOrigin& priv() const; // Internal use only
|
||||
|
||||
protected:
|
||||
GArrayU(); // Default constructor
|
||||
template<class> friend class cv::GArray; // (avialable to GArray<T> only)
|
||||
|
||||
void setConstructFcn(ConstructVec &&cv); // Store T-aware constructor
|
||||
|
||||
std::shared_ptr<GOrigin> m_priv;
|
||||
};
|
||||
|
||||
// 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
|
||||
// (be value holder).
|
||||
class BasicVectorRef
|
||||
{
|
||||
public:
|
||||
std::size_t m_elemSize = 0ul;
|
||||
cv::GArrayDesc m_desc;
|
||||
virtual ~BasicVectorRef() {}
|
||||
};
|
||||
|
||||
template<typename T> class VectorRefT: public BasicVectorRef
|
||||
{
|
||||
using empty_t = util::monostate;
|
||||
using ro_ext_t = const std::vector<T> *;
|
||||
using rw_ext_t = std::vector<T> *;
|
||||
using rw_own_t = std::vector<T> ;
|
||||
util::variant<empty_t, ro_ext_t, rw_ext_t, rw_own_t> m_ref;
|
||||
|
||||
inline bool isEmpty() const { return util::holds_alternative<empty_t>(m_ref); }
|
||||
inline bool isROExt() const { return util::holds_alternative<ro_ext_t>(m_ref); }
|
||||
inline bool isRWExt() const { return util::holds_alternative<rw_ext_t>(m_ref); }
|
||||
inline bool isRWOwn() const { return util::holds_alternative<rw_own_t>(m_ref); }
|
||||
|
||||
void init(const std::vector<T>* vec = nullptr)
|
||||
{
|
||||
m_elemSize = sizeof(T);
|
||||
if (vec) m_desc = cv::descr_of(*vec);
|
||||
}
|
||||
|
||||
public:
|
||||
VectorRefT() { init(); }
|
||||
virtual ~VectorRefT() {}
|
||||
|
||||
explicit VectorRefT(const std::vector<T>& vec) : m_ref(&vec) { init(&vec); }
|
||||
explicit VectorRefT(std::vector<T>& vec) : m_ref(&vec) { init(&vec); }
|
||||
explicit VectorRefT(std::vector<T>&& vec) : m_ref(std::move(vec)) { init(&vec); }
|
||||
|
||||
// Reset a VectorRefT. Called only for objects instantiated
|
||||
// internally in G-API (e.g. temporary GArray<T>'s within a
|
||||
// computation). Reset here means both initialization
|
||||
// (creating an object) and reset (discarding its existing
|
||||
// content before the next execution). Must never be called
|
||||
// for external VectorRefTs.
|
||||
void reset()
|
||||
{
|
||||
if (isEmpty())
|
||||
{
|
||||
std::vector<T> empty_vector;
|
||||
m_desc = cv::descr_of(empty_vector);
|
||||
m_ref = std::move(empty_vector);
|
||||
GAPI_Assert(isRWOwn());
|
||||
}
|
||||
else if (isRWOwn())
|
||||
{
|
||||
util::get<rw_own_t>(m_ref).clear();
|
||||
}
|
||||
else GAPI_Assert(false); // shouldn't be called in *EXT modes
|
||||
}
|
||||
|
||||
// Obtain a WRITE reference to underlying object
|
||||
// Used by CPU kernel API wrappers when a kernel execution frame
|
||||
// is created
|
||||
std::vector<T>& wref()
|
||||
{
|
||||
GAPI_Assert(isRWExt() || isRWOwn());
|
||||
if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
|
||||
if (isRWOwn()) return util::get<rw_own_t>(m_ref);
|
||||
util::throw_error(std::logic_error("Impossible happened"));
|
||||
}
|
||||
|
||||
// Obtain a READ reference to underlying object
|
||||
// Used by CPU kernel API wrappers when a kernel execution frame
|
||||
// is created
|
||||
const std::vector<T>& rref() const
|
||||
{
|
||||
// ANY vector can be accessed for reading, even if it declared for
|
||||
// output. Example -- a GComputation from [in] to [out1,out2]
|
||||
// where [out2] is a result of operation applied to [out1]:
|
||||
//
|
||||
// GComputation boundary
|
||||
// . . . . . . .
|
||||
// . .
|
||||
// [in] ----> foo() ----> [out1]
|
||||
// . . :
|
||||
// . . . .:. . .
|
||||
// . V .
|
||||
// . bar() ---> [out2]
|
||||
// . . . . . . . . . . . .
|
||||
//
|
||||
if (isROExt()) return *util::get<ro_ext_t>(m_ref);
|
||||
if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
|
||||
if (isRWOwn()) return util::get<rw_own_t>(m_ref);
|
||||
util::throw_error(std::logic_error("Impossible happened"));
|
||||
}
|
||||
};
|
||||
|
||||
// This class strips type information from VectorRefT<> and makes it usable
|
||||
// in the G-API executables (carrying run-time data/information to kernels).
|
||||
// Part of GRunArg.
|
||||
// Its methods are typed proxies to VectorRefT<T>.
|
||||
// VectorRef maintains "reference" semantics so two copies of VectoRef refer
|
||||
// to the same underlying object.
|
||||
// FIXME: Put a good explanation on why cv::OutputArray doesn't fit this role
|
||||
class VectorRef
|
||||
{
|
||||
std::shared_ptr<BasicVectorRef> m_ref;
|
||||
|
||||
template<typename T> inline void check() const
|
||||
{
|
||||
GAPI_DbgAssert(dynamic_cast<VectorRefT<T>*>(m_ref.get()) != nullptr);
|
||||
GAPI_Assert(sizeof(T) == m_ref->m_elemSize);
|
||||
}
|
||||
|
||||
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> void reset()
|
||||
{
|
||||
if (!m_ref) m_ref.reset(new VectorRefT<T>());
|
||||
|
||||
check<T>();
|
||||
static_cast<VectorRefT<T>&>(*m_ref).reset();
|
||||
}
|
||||
|
||||
template<typename T> std::vector<T>& wref()
|
||||
{
|
||||
check<T>();
|
||||
return static_cast<VectorRefT<T>&>(*m_ref).wref();
|
||||
}
|
||||
|
||||
template<typename T> const std::vector<T>& rref() const
|
||||
{
|
||||
check<T>();
|
||||
return static_cast<VectorRefT<T>&>(*m_ref).rref();
|
||||
}
|
||||
|
||||
cv::GArrayDesc descr_of() const
|
||||
{
|
||||
return m_ref->m_desc;
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template<typename T> class GArray
|
||||
{
|
||||
public:
|
||||
GArray() { putDetails(); } // Empty constructor
|
||||
explicit GArray(detail::GArrayU &&ref) // GArrayU-based constructor
|
||||
: m_ref(ref) { putDetails(); } // (used by GCall, not for users)
|
||||
|
||||
detail::GArrayU strip() const { return m_ref; }
|
||||
|
||||
private:
|
||||
static void VCTor(detail::VectorRef& vref) { vref.reset<T>(); }
|
||||
void putDetails() {m_ref.setConstructFcn(&VCTor); }
|
||||
|
||||
detail::GArrayU m_ref;
|
||||
};
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GARRAY_HPP
|
||||
@@ -0,0 +1,63 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GCALL_HPP
|
||||
#define OPENCV_GAPI_GCALL_HPP
|
||||
|
||||
#include "opencv2/gapi/garg.hpp" // GArg
|
||||
#include "opencv2/gapi/gmat.hpp" // GMat
|
||||
#include "opencv2/gapi/gscalar.hpp" // GScalar
|
||||
#include "opencv2/gapi/garray.hpp" // GArray<T>
|
||||
|
||||
namespace cv {
|
||||
|
||||
struct GKernel;
|
||||
|
||||
// The whole idea of this class is to represent an operation
|
||||
// which is applied to arguments. This is part of public API,
|
||||
// since it is what users should use to define kernel interfaces.
|
||||
|
||||
class GAPI_EXPORTS GCall final
|
||||
{
|
||||
public:
|
||||
class Priv;
|
||||
|
||||
explicit GCall(const GKernel &k);
|
||||
~GCall();
|
||||
|
||||
template<typename... Ts>
|
||||
GCall& pass(Ts&&... args)
|
||||
{
|
||||
setArgs({cv::GArg(std::move(args))...});
|
||||
return *this;
|
||||
}
|
||||
|
||||
// A generic yield method - obtain a link to operator's particular GMat output
|
||||
GMat yield (int output = 0);
|
||||
GScalar yieldScalar(int output = 0);
|
||||
|
||||
template<class T> GArray<T> yieldArray(int output = 0)
|
||||
{
|
||||
return GArray<T>(yieldArray(output));
|
||||
}
|
||||
|
||||
// Internal use only
|
||||
Priv& priv();
|
||||
const Priv& priv() const;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Priv> m_priv;
|
||||
|
||||
void setArgs(std::vector<GArg> &&args);
|
||||
|
||||
// Public version returns a typed array, this one is implementation detail
|
||||
detail::GArrayU yieldArray(int output = 0);
|
||||
};
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GCALL_HPP
|
||||
@@ -0,0 +1,118 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GCOMMON_HPP
|
||||
#define OPENCV_GAPI_GCOMMON_HPP
|
||||
|
||||
#include <functional> // std::hash
|
||||
#include <vector> // std::vector
|
||||
#include <type_traits> // decay
|
||||
|
||||
#include <opencv2/gapi/opencv_includes.hpp>
|
||||
|
||||
#include "opencv2/gapi/util/any.hpp"
|
||||
#include "opencv2/gapi/own/exports.hpp"
|
||||
#include "opencv2/gapi/own/assert.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// This is a trait-like structure to mark backend-specific compile arguments
|
||||
// with tags
|
||||
template<typename T> struct CompileArgTag;
|
||||
template<typename T> struct CompileArgTag
|
||||
{
|
||||
static const char* tag() { return ""; };
|
||||
};
|
||||
}
|
||||
|
||||
// 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)
|
||||
// to components which are internal and operate on a lower-level entities
|
||||
// (e.g., compiler, backends).
|
||||
// FIXME: merge with ArgKind?
|
||||
// FIXME: replace with variant[format desc]?
|
||||
enum class GShape: int
|
||||
{
|
||||
GMAT,
|
||||
GSCALAR,
|
||||
GARRAY,
|
||||
};
|
||||
|
||||
struct GCompileArg;
|
||||
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
using is_compile_arg = std::is_same<GCompileArg, typename std::decay<T>::type>;
|
||||
}
|
||||
// CompileArg is an unified interface over backend-specific compilation
|
||||
// information
|
||||
// FIXME: Move to a separate file?
|
||||
struct GAPI_EXPORTS GCompileArg
|
||||
{
|
||||
public:
|
||||
std::string tag;
|
||||
|
||||
// FIXME: use decay in GArg/other trait-based wrapper before leg is shot!
|
||||
template<typename T, typename std::enable_if<!detail::is_compile_arg<T>::value, int>::type = 0>
|
||||
explicit GCompileArg(T &&t)
|
||||
: tag(detail::CompileArgTag<typename std::decay<T>::type>::tag())
|
||||
, arg(t)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T> T& get()
|
||||
{
|
||||
return util::any_cast<T>(arg);
|
||||
}
|
||||
|
||||
template<typename T> const T& get() const
|
||||
{
|
||||
return util::any_cast<T>(arg);
|
||||
}
|
||||
|
||||
private:
|
||||
util::any arg;
|
||||
};
|
||||
|
||||
using GCompileArgs = std::vector<GCompileArg>;
|
||||
|
||||
template<typename... Ts> GCompileArgs compile_args(Ts&&... args)
|
||||
{
|
||||
return GCompileArgs{ GCompileArg(args)... };
|
||||
}
|
||||
|
||||
struct graph_dump_path
|
||||
{
|
||||
std::string m_dump_path;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<> struct CompileArgTag<cv::graph_dump_path>
|
||||
{
|
||||
static const char* tag() { return "gapi.graph_dump_path"; }
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace cv
|
||||
|
||||
// std::hash overload for GShape
|
||||
namespace std
|
||||
{
|
||||
template<> struct hash<cv::GShape>
|
||||
{
|
||||
size_t operator() (cv::GShape sh) const
|
||||
{
|
||||
return std::hash<int>()(static_cast<int>(sh));
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
|
||||
#endif // OPENCV_GAPI_GCOMMON_HPP
|
||||
@@ -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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GCOMPILED_HPP
|
||||
#define OPENCV_GAPI_GCOMPILED_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "opencv2/gapi/own/assert.hpp"
|
||||
#include "opencv2/core/mat.hpp"
|
||||
|
||||
#include "opencv2/gapi/garg.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
// This class represents a compiled computation.
|
||||
// In theory (and ideally), it can be used w/o the rest of APIs.
|
||||
// In theory (and ideally), it can be serialized/deserialized.
|
||||
// It can enable scenarious like deployment to an autonomous devince, FuSa, etc.
|
||||
//
|
||||
// Currently GCompiled assumes all GMats you used to pass data to G-API
|
||||
// are valid and not destroyed while you use a GCompiled object.
|
||||
//
|
||||
// FIXME: In future, there should be a way to name I/O objects and specify it
|
||||
// to GCompiled externally (for example, when it is loaded on the target system).
|
||||
|
||||
class GAPI_EXPORTS GCompiled
|
||||
{
|
||||
public:
|
||||
class GAPI_EXPORTS Priv;
|
||||
|
||||
GCompiled();
|
||||
|
||||
void operator() (GRunArgs &&ins, GRunArgsP &&outs); // Generic arg-to-arg
|
||||
void operator() (cv::Mat in, cv::Mat &out); // Unary overload
|
||||
void operator() (cv::Mat in, cv::Scalar &out); // Unary overload (scalar)
|
||||
void operator() (cv::Mat in1, cv::Mat in2, cv::Mat &out); // Binary overload
|
||||
void operator() (cv::Mat in1, cv::Mat in2, cv::Scalar &out); // Binary overload (scalar)
|
||||
void operator() (const std::vector<cv::Mat> &ins, // Compatibility overload
|
||||
const std::vector<cv::Mat> &outs);
|
||||
|
||||
Priv& priv();
|
||||
|
||||
explicit operator bool () const; // Check if GCompiled is runnable or empty
|
||||
|
||||
const GMetaArgs& metas() const; // Meta passed to compile()
|
||||
const GMetaArgs& outMetas() const; // Inferred output metadata
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Priv> m_priv;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OPENCV_GAPI_GCOMPILED_HPP
|
||||
@@ -0,0 +1,123 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GCOMPOUNDKERNEL_HPP
|
||||
#define OPENCV_GAPI_GCOMPOUNDKERNEL_HPP
|
||||
|
||||
#include <opencv2/gapi/opencv_includes.hpp>
|
||||
#include <opencv2/gapi/gcommon.hpp>
|
||||
#include <opencv2/gapi/gkernel.hpp>
|
||||
#include <opencv2/gapi/garg.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace gapi
|
||||
{
|
||||
namespace compound
|
||||
{
|
||||
// FIXME User does not need to know about this function
|
||||
// Needs that user may define compound kernels(as cpu kernels)
|
||||
GAPI_EXPORTS cv::gapi::GBackend backend();
|
||||
} // namespace compound
|
||||
} // namespace gapi
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct GCompoundContext
|
||||
{
|
||||
explicit GCompoundContext(const GArgs& in_args);
|
||||
template<typename T>
|
||||
const T& inArg(int input) { return m_args.at(input).get<T>(); }
|
||||
|
||||
GArgs m_args;
|
||||
GArgs m_results;
|
||||
};
|
||||
|
||||
class GAPI_EXPORTS GCompoundKernel
|
||||
{
|
||||
// Compound kernel must use all of it's inputs
|
||||
public:
|
||||
using F = std::function<void(GCompoundContext& ctx)>;
|
||||
|
||||
explicit GCompoundKernel(const F& f);
|
||||
void apply(GCompoundContext& ctx);
|
||||
|
||||
protected:
|
||||
F m_f;
|
||||
};
|
||||
|
||||
template<typename T> struct get_compound_in
|
||||
{
|
||||
static T get(GCompoundContext &ctx, int idx) { return ctx.inArg<T>(idx); }
|
||||
};
|
||||
|
||||
template<typename U> struct get_compound_in<cv::GArray<U>>
|
||||
{
|
||||
static cv::GArray<U> get(GCompoundContext &ctx, int idx)
|
||||
{
|
||||
auto array = cv::GArray<U>();
|
||||
ctx.m_args[idx] = GArg(array);
|
||||
return array;
|
||||
}
|
||||
};
|
||||
|
||||
// Kernel may return one object(GMat, GScalar) or a tuple of objects.
|
||||
// This helper is needed to cast return value to the same form(tuple)
|
||||
template<typename>
|
||||
struct tuple_wrap_helper;
|
||||
|
||||
template<typename T> struct tuple_wrap_helper
|
||||
{
|
||||
static std::tuple<T> get(T&& obj) { return std::make_tuple(std::move(obj)); }
|
||||
};
|
||||
|
||||
template<typename... Objs>
|
||||
struct tuple_wrap_helper<std::tuple<Objs...>>
|
||||
{
|
||||
static std::tuple<Objs...> get(std::tuple<Objs...>&& objs) { return objs; }
|
||||
};
|
||||
|
||||
template<typename, typename, typename>
|
||||
struct GCompoundCallHelper;
|
||||
|
||||
template<typename Impl, typename... Ins, typename... Outs>
|
||||
struct GCompoundCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
|
||||
{
|
||||
template<int... IIs, int... OIs>
|
||||
static void expand_impl(GCompoundContext &ctx, detail::Seq<IIs...>, detail::Seq<OIs...>)
|
||||
{
|
||||
auto result = Impl::expand(get_compound_in<Ins>::get(ctx, IIs)...);
|
||||
auto tuple_return = tuple_wrap_helper<decltype(result)>::get(std::move(result));
|
||||
ctx.m_results = { cv::GArg(std::get<OIs>(tuple_return))... };
|
||||
}
|
||||
|
||||
static void expand(GCompoundContext &ctx)
|
||||
{
|
||||
expand_impl(ctx,
|
||||
typename detail::MkSeq<sizeof...(Ins)>::type(),
|
||||
typename detail::MkSeq<sizeof...(Outs)>::type());
|
||||
}
|
||||
};
|
||||
|
||||
template<class Impl, class K>
|
||||
class GCompoundKernelImpl: public cv::detail::GCompoundCallHelper<Impl, typename K::InArgs, typename K::OutArgs>
|
||||
{
|
||||
using P = cv::detail::GCompoundCallHelper<Impl, typename K::InArgs, typename K::OutArgs>;
|
||||
|
||||
public:
|
||||
using API = K;
|
||||
|
||||
static cv::gapi::GBackend backend() { return cv::gapi::compound::backend(); }
|
||||
static GCompoundKernel kernel() { return GCompoundKernel(&P::expand); }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
#define GAPI_COMPOUND_KERNEL(Name, API) struct Name: public cv::detail::GCompoundKernelImpl<Name, API>
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GCOMPOUNDKERNEL_HPP
|
||||
@@ -0,0 +1,135 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GCOMPUTATION_HPP
|
||||
#define OPENCV_GAPI_GCOMPUTATION_HPP
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "opencv2/gapi/util/util.hpp"
|
||||
#include "opencv2/gapi/gcommon.hpp"
|
||||
#include "opencv2/gapi/gproto.hpp"
|
||||
#include "opencv2/gapi/garg.hpp"
|
||||
#include "opencv2/gapi/gcompiled.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// FIXME: move to algorithm, cover with separate tests
|
||||
// FIXME: replace with O(1) version (both memory and compilation time)
|
||||
template<typename...>
|
||||
struct last_type;
|
||||
|
||||
template<typename T>
|
||||
struct last_type<T> { using type = T;};
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
struct last_type<T, Ts...> { using type = typename last_type<Ts...>::type; };
|
||||
|
||||
template<typename... Ts>
|
||||
using last_type_t = typename last_type<Ts...>::type;
|
||||
}
|
||||
|
||||
class GAPI_EXPORTS GComputation
|
||||
{
|
||||
public:
|
||||
class Priv;
|
||||
typedef std::function<GComputation()> Generator;
|
||||
|
||||
// Various constructors enable different ways to define a computation: /////
|
||||
// 1. Generic constructors
|
||||
GComputation(const Generator& gen); // Generator overload
|
||||
GComputation(GProtoInputArgs &&ins,
|
||||
GProtoOutputArgs &&outs); // Arg-to-arg overload
|
||||
|
||||
// 2. Syntax sugar and compatibility overloads
|
||||
GComputation(GMat in, GMat out); // Unary overload
|
||||
GComputation(GMat in, GScalar out); // Unary overload (scalar)
|
||||
GComputation(GMat in1, GMat in2, GMat out); // Binary overload
|
||||
GComputation(GMat in1, GMat in2, GScalar out); // Binary overload (scalar)
|
||||
GComputation(const std::vector<GMat> &ins, // Compatibility overload
|
||||
const std::vector<GMat> &outs);
|
||||
|
||||
// Various versions of apply(): ////////////////////////////////////////////
|
||||
// 1. Generic apply()
|
||||
void apply(GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args = {}); // Arg-to-arg overload
|
||||
|
||||
// 2. Syntax sugar and compatibility overloads
|
||||
void apply(cv::Mat in, cv::Mat &out, GCompileArgs &&args = {}); // Unary overload
|
||||
void apply(cv::Mat in, cv::Scalar &out, GCompileArgs &&args = {}); // Unary overload (scalar)
|
||||
void apply(cv::Mat in1, cv::Mat in2, cv::Mat &out, GCompileArgs &&args = {}); // Binary overload
|
||||
void apply(cv::Mat in1, cv::Mat in2, cv::Scalar &out, GCompileArgs &&args = {}); // Binary overload (scalar)
|
||||
void apply(const std::vector<cv::Mat>& ins, // Compatibility overload
|
||||
const std::vector<cv::Mat>& outs,
|
||||
GCompileArgs &&args = {});
|
||||
|
||||
// Various versions of compile(): //////////////////////////////////////////
|
||||
// 1. Generic compile() - requires metas to be passed as vector
|
||||
GCompiled compile(GMetaArgs &&in_metas, GCompileArgs &&args = {});
|
||||
|
||||
// 2. Syntax sugar - variadic list of metas, no extra compile args
|
||||
template<typename... Ts>
|
||||
auto compile(const Ts&... metas) ->
|
||||
typename std::enable_if<detail::are_meta_descrs<Ts...>::value, GCompiled>::type
|
||||
{
|
||||
return compile(GMetaArgs{GMetaArg(metas)...}, GCompileArgs());
|
||||
}
|
||||
|
||||
// 3. Syntax sugar - variadic list of metas, extra compile args
|
||||
// (seems optional parameters don't work well when there's an variadic template
|
||||
// comes first)
|
||||
//
|
||||
// Ideally it should look like:
|
||||
//
|
||||
// template<typename... Ts>
|
||||
// GCompiled compile(const Ts&... metas, GCompileArgs &&args)
|
||||
//
|
||||
// But not all compilers can hande this (and seems they shouldn't be able to).
|
||||
template<typename... Ts>
|
||||
auto compile(const Ts&... meta_and_compile_args) ->
|
||||
typename std::enable_if<detail::are_meta_descrs_but_last<Ts...>::value
|
||||
&& std::is_same<GCompileArgs, detail::last_type_t<Ts...> >::value,
|
||||
GCompiled>::type
|
||||
{
|
||||
//FIXME: wrapping meta_and_compile_args into a tuple to unwrap them inside a helper function is the overkill
|
||||
return compile(std::make_tuple(meta_and_compile_args...),
|
||||
typename detail::MkSeq<sizeof...(Ts)-1>::type());
|
||||
}
|
||||
|
||||
// Internal use only
|
||||
Priv& priv();
|
||||
const Priv& priv() const;
|
||||
|
||||
protected:
|
||||
|
||||
// 4. Helper method for (3)
|
||||
template<typename... Ts, int... IIs>
|
||||
GCompiled compile(const std::tuple<Ts...> &meta_and_compile_args, detail::Seq<IIs...>)
|
||||
{
|
||||
GMetaArgs meta_args = {GMetaArg(std::get<IIs>(meta_and_compile_args))...};
|
||||
GCompileArgs comp_args = std::get<sizeof...(Ts)-1>(meta_and_compile_args);
|
||||
return compile(std::move(meta_args), std::move(comp_args));
|
||||
}
|
||||
|
||||
std::shared_ptr<Priv> m_priv;
|
||||
};
|
||||
|
||||
namespace gapi
|
||||
{
|
||||
// Declare an Island tagged with `name` and defined from `ins` to `outs`
|
||||
// (exclusively, as ins/outs are data objects, and regioning is done on
|
||||
// operations level).
|
||||
// Throws if any operation between `ins` and `outs` are already assigned
|
||||
// to another island.
|
||||
void GAPI_EXPORTS island(const std::string &name,
|
||||
GProtoInputArgs &&ins,
|
||||
GProtoOutputArgs &&outs);
|
||||
} // namespace gapi
|
||||
|
||||
} // namespace cv
|
||||
#endif // OPENCV_GAPI_GCOMPUTATION_HPP
|
||||
@@ -0,0 +1,409 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GKERNEL_HPP
|
||||
#define OPENCV_GAPI_GKERNEL_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <unordered_map> // map (for GKernelPackage)
|
||||
#include <vector> // lookup order
|
||||
#include <string> // string
|
||||
#include <utility> // tuple
|
||||
#include <type_traits> // false_type, true_type
|
||||
|
||||
#include <opencv2/gapi/gcommon.hpp> // CompileArgTag
|
||||
#include <opencv2/gapi/util/util.hpp> // Seq
|
||||
#include <opencv2/gapi/gcall.hpp>
|
||||
#include <opencv2/gapi/garg.hpp> // GArg
|
||||
#include <opencv2/gapi/gmetaarg.hpp> // GMetaArg
|
||||
#include <opencv2/gapi/gtype_traits.hpp> // GTypeTraits
|
||||
#include <opencv2/gapi/util/compiler_hints.hpp> //suppress_unused_warning
|
||||
|
||||
|
||||
namespace cv {
|
||||
|
||||
using GShapes = std::vector<GShape>;
|
||||
|
||||
// GKernel describes kernel API to the system
|
||||
// FIXME: add attributes of a kernel, (e.g. number and types
|
||||
// of inputs, etc)
|
||||
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 M outMeta; // generic adaptor to API::outMeta(...)
|
||||
const GShapes outShapes; // types (shapes) kernel's outputs
|
||||
};
|
||||
|
||||
// GKernelImpl describes particular kernel implementation to the system
|
||||
struct GAPI_EXPORTS GKernelImpl
|
||||
{
|
||||
util::any opaque; // backend-specific opaque info
|
||||
};
|
||||
|
||||
template<typename, typename> class GKernelTypeM;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// yield() is used in graph construction time as a generic method to obtain
|
||||
// lazy "return value" of G-API operations
|
||||
//
|
||||
namespace
|
||||
{
|
||||
|
||||
template<typename T> struct Yield;
|
||||
template<> struct Yield<cv::GMat>
|
||||
{
|
||||
static inline cv::GMat yield(cv::GCall &call, int i) { return call.yield(i); }
|
||||
};
|
||||
template<> struct Yield<cv::GScalar>
|
||||
{
|
||||
static inline cv::GScalar yield(cv::GCall &call, int i) { return call.yieldScalar(i); }
|
||||
};
|
||||
template<typename U> struct Yield<cv::GArray<U> >
|
||||
{
|
||||
static inline cv::GArray<U> yield(cv::GCall &call, int i) { return call.yieldArray<U>(i); }
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Helper classes which brings outputMeta() marshalling to kernel
|
||||
// implementations
|
||||
//
|
||||
// 1. MetaType establishes G#Type -> G#Meta mapping between G-API dynamic
|
||||
// types and its metadata descriptor types.
|
||||
// This mapping is used to transform types to call outMeta() callback.
|
||||
template<typename T> struct MetaType;
|
||||
template<> struct MetaType<cv::GMat> { using type = GMatDesc; };
|
||||
template<> struct MetaType<cv::GScalar> { using type = GScalarDesc; };
|
||||
template<typename U> struct MetaType<cv::GArray<U> > { using type = GArrayDesc; };
|
||||
template<typename T> struct MetaType { using type = T; }; // opaque args passed as-is
|
||||
|
||||
// 2. Hacky test based on MetaType to check if we operate on G-* type or not
|
||||
template<typename T> using is_nongapi_type = std::is_same<T, typename MetaType<T>::type>;
|
||||
|
||||
// 3. Two ways to transform input arguments to its meta - for G-* and non-G* types:
|
||||
template<typename T>
|
||||
typename std::enable_if<!is_nongapi_type<T>::value, typename MetaType<T>::type>
|
||||
::type get_in_meta(const GMetaArgs &in_meta, const GArgs &, int idx)
|
||||
{
|
||||
return util::get<typename MetaType<T>::type>(in_meta.at(idx));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if<is_nongapi_type<T>::value, T>
|
||||
::type get_in_meta(const GMetaArgs &, const GArgs &in_args, int idx)
|
||||
{
|
||||
return in_args.at(idx).template get<T>();
|
||||
}
|
||||
|
||||
// 4. The MetaHelper itself: an entity which generates outMeta() call
|
||||
// based on kernel signature, with arguments properly substituted.
|
||||
// 4.1 - case for multiple return values
|
||||
// FIXME: probably can be simplified with std::apply or analogue.
|
||||
template<typename, typename, typename>
|
||||
struct MetaHelper;
|
||||
|
||||
template<typename K, typename... Ins, typename... Outs>
|
||||
struct MetaHelper<K, std::tuple<Ins...>, std::tuple<Outs...> >
|
||||
{
|
||||
template<int... IIs, int... OIs>
|
||||
static GMetaArgs getOutMeta_impl(const GMetaArgs &in_meta,
|
||||
const GArgs &in_args,
|
||||
detail::Seq<IIs...>,
|
||||
detail::Seq<OIs...>)
|
||||
{
|
||||
// FIXME: decay?
|
||||
using R = std::tuple<typename MetaType<Outs>::type...>;
|
||||
const R r = K::outMeta( get_in_meta<Ins>(in_meta, in_args, IIs)... );
|
||||
return GMetaArgs{ GMetaArg(std::get<OIs>(r))... };
|
||||
}
|
||||
// FIXME: help users identify how outMeta must look like (via default impl w/static_assert?)
|
||||
|
||||
static GMetaArgs getOutMeta(const GMetaArgs &in_meta,
|
||||
const GArgs &in_args)
|
||||
{
|
||||
return getOutMeta_impl(in_meta,
|
||||
in_args,
|
||||
typename detail::MkSeq<sizeof...(Ins)>::type(),
|
||||
typename detail::MkSeq<sizeof...(Outs)>::type());
|
||||
}
|
||||
};
|
||||
|
||||
// 4.1 - case for a single return value
|
||||
// FIXME: How to avoid duplication here?
|
||||
template<typename K, typename... Ins, typename Out>
|
||||
struct MetaHelper<K, std::tuple<Ins...>, Out >
|
||||
{
|
||||
template<int... IIs>
|
||||
static GMetaArgs getOutMeta_impl(const GMetaArgs &in_meta,
|
||||
const GArgs &in_args,
|
||||
detail::Seq<IIs...>)
|
||||
{
|
||||
// FIXME: decay?
|
||||
using R = typename MetaType<Out>::type;
|
||||
const R r = K::outMeta( get_in_meta<Ins>(in_meta, in_args, IIs)... );
|
||||
return GMetaArgs{ GMetaArg(r) };
|
||||
}
|
||||
// FIXME: help users identify how outMeta must look like (via default impl w/static_assert?)
|
||||
|
||||
static GMetaArgs getOutMeta(const GMetaArgs &in_meta,
|
||||
const GArgs &in_args)
|
||||
{
|
||||
return getOutMeta_impl(in_meta,
|
||||
in_args,
|
||||
typename detail::MkSeq<sizeof...(Ins)>::type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// GKernelType and GKernelTypeM are base classes which implement typed ::on()
|
||||
// method based on kernel signature. GKernelTypeM stands for multiple-return-value kernels
|
||||
//
|
||||
// G_TYPED_KERNEL and G_TYPED_KERNEK_M macros inherit user classes from GKernelType and
|
||||
// GKernelTypeM respectively.
|
||||
|
||||
template<typename K, typename... R, typename... Args>
|
||||
class GKernelTypeM<K, std::function<std::tuple<R...>(Args...)> >:
|
||||
public detail::MetaHelper<K, std::tuple<Args...>, std::tuple<R...> >
|
||||
{
|
||||
template<int... IIs>
|
||||
static std::tuple<R...> yield(cv::GCall &call, detail::Seq<IIs...>)
|
||||
{
|
||||
return std::make_tuple(detail::Yield<R>::yield(call, IIs)...);
|
||||
}
|
||||
|
||||
public:
|
||||
using InArgs = std::tuple<Args...>;
|
||||
using OutArgs = std::tuple<R...>;
|
||||
|
||||
static std::tuple<R...> on(Args... args)
|
||||
{
|
||||
cv::GCall call(GKernel{K::id(), &K::getOutMeta, {detail::GTypeTraits<R>::shape...}});
|
||||
call.pass(args...);
|
||||
return yield(call, typename detail::MkSeq<sizeof...(R)>::type());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename, typename> class GKernelType;
|
||||
|
||||
template<typename K, typename R, typename... Args>
|
||||
class GKernelType<K, std::function<R(Args...)> >:
|
||||
public detail::MetaHelper<K, std::tuple<Args...>, R >
|
||||
{
|
||||
public:
|
||||
using InArgs = std::tuple<Args...>;
|
||||
using OutArgs = std::tuple<R>;
|
||||
|
||||
static R on(Args... args)
|
||||
{
|
||||
cv::GCall call(GKernel{K::id(), &K::getOutMeta, {detail::GTypeTraits<R>::shape}});
|
||||
call.pass(args...);
|
||||
return detail::Yield<R>::yield(call, 0);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace cv
|
||||
|
||||
|
||||
// FIXME: I don't know a better way so far. Feel free to suggest one
|
||||
// The problem is that every typed kernel should have ::id() but body
|
||||
// of the class is defined by user (with outMeta, other stuff)
|
||||
|
||||
#define G_ID_HELPER_CLASS(Class) Class##IdHelper
|
||||
|
||||
#define G_ID_HELPER_BODY(Class, Id) \
|
||||
namespace detail \
|
||||
{ \
|
||||
struct G_ID_HELPER_CLASS(Class) \
|
||||
{ \
|
||||
static constexpr const char * id() {return Id;}; \
|
||||
}; \
|
||||
}
|
||||
|
||||
#define G_TYPED_KERNEL(Class, API, Id) \
|
||||
G_ID_HELPER_BODY(Class, Id) \
|
||||
struct Class final: public cv::GKernelType<Class, std::function API >, \
|
||||
public detail::G_ID_HELPER_CLASS(Class)
|
||||
// {body} is to be defined by user
|
||||
|
||||
#define G_TYPED_KERNEL_M(Class, API, Id) \
|
||||
G_ID_HELPER_BODY(Class, Id) \
|
||||
struct Class final: public cv::GKernelTypeM<Class, std::function API >, \
|
||||
public detail::G_ID_HELPER_CLASS(Class) \
|
||||
// {body} is to be defined by user
|
||||
|
||||
namespace cv
|
||||
{
|
||||
// Declare <unite> in cv:: namespace
|
||||
enum class unite_policy
|
||||
{
|
||||
REPLACE,
|
||||
KEEP
|
||||
};
|
||||
|
||||
namespace gapi
|
||||
{
|
||||
// Prework: model "Device" API before it gets to G-API headers.
|
||||
// FIXME: Don't mix with internal Backends class!
|
||||
class GAPI_EXPORTS GBackend
|
||||
{
|
||||
public:
|
||||
class Priv;
|
||||
|
||||
// TODO: make it template (call `new` within??)
|
||||
GBackend();
|
||||
explicit GBackend(std::shared_ptr<Priv> &&p);
|
||||
|
||||
Priv& priv();
|
||||
const Priv& priv() const;
|
||||
std::size_t hash() const;
|
||||
|
||||
bool operator== (const GBackend &rhs) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Priv> m_priv;
|
||||
};
|
||||
|
||||
inline bool operator != (const GBackend &lhs, const GBackend &rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
} // namespace gapi
|
||||
} // namespace cv
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<> struct hash<cv::gapi::GBackend>
|
||||
{
|
||||
std::size_t operator() (const cv::gapi::GBackend &b) const
|
||||
{
|
||||
return b.hash();
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
|
||||
namespace cv {
|
||||
namespace gapi {
|
||||
// Lookup order is in fact a vector of Backends to traverse during look-up
|
||||
using GLookupOrder = std::vector<GBackend>;
|
||||
inline GLookupOrder lookup_order(std::initializer_list<GBackend> &&list)
|
||||
{
|
||||
return GLookupOrder(std::move(list));
|
||||
}
|
||||
|
||||
// FIXME: Hide implementation
|
||||
class GAPI_EXPORTS GKernelPackage
|
||||
{
|
||||
using S = std::unordered_map<std::string, GKernelImpl>;
|
||||
using M = std::unordered_map<GBackend, S>;
|
||||
M m_backend_kernels;
|
||||
|
||||
protected:
|
||||
// Check if package contains ANY implementation of a kernel API
|
||||
// by API textual id.
|
||||
bool includesAPI(const std::string &id) const;
|
||||
|
||||
public:
|
||||
// Return total number of kernels (accross all backends)
|
||||
std::size_t size() const;
|
||||
|
||||
// Check if particular kernel implementation exist in the package.
|
||||
// The key word here is _particular_ - i.e., from the specific backend.
|
||||
template<typename KImpl>
|
||||
bool includes() const
|
||||
{
|
||||
const auto set_iter = m_backend_kernels.find(KImpl::backend());
|
||||
return (set_iter != m_backend_kernels.end())
|
||||
? (set_iter->second.count(KImpl::API::id()) > 0)
|
||||
: false;
|
||||
}
|
||||
|
||||
// Removes all the kernels related to the given backend
|
||||
void remove(const GBackend& backend);
|
||||
|
||||
// Check if package contains ANY implementation of a kernel API
|
||||
// by API type.
|
||||
template<typename KAPI>
|
||||
bool includesAPI() const
|
||||
{
|
||||
return includesAPI(KAPI::id());
|
||||
}
|
||||
|
||||
// Lookup a kernel, given the look-up order. Returns Backend which
|
||||
// hosts kernel implementation. Throws if nothing found.
|
||||
//
|
||||
// If order is empty(), returns first suitable implementation.
|
||||
template<typename KAPI>
|
||||
GBackend lookup(const GLookupOrder &order = {}) const
|
||||
{
|
||||
return lookup(KAPI::id(), order).first;
|
||||
}
|
||||
|
||||
std::pair<cv::gapi::GBackend, cv::GKernelImpl>
|
||||
lookup(const std::string &id, const GLookupOrder &order = {}) const;
|
||||
|
||||
// Put a new kernel implementation into package
|
||||
// FIXME: No overwrites allowed?
|
||||
template<typename KImpl> void include()
|
||||
{
|
||||
auto backend = KImpl::backend();
|
||||
auto kernel_id = KImpl::API::id();
|
||||
auto kernel_impl = GKernelImpl{KImpl::kernel()};
|
||||
m_backend_kernels[backend][kernel_id] = std::move(kernel_impl);
|
||||
}
|
||||
|
||||
// Lists all backends which are included into package
|
||||
std::vector<GBackend> backends() const;
|
||||
|
||||
friend GAPI_EXPORTS GKernelPackage combine(const GKernelPackage &,
|
||||
const GKernelPackage &,
|
||||
const cv::unite_policy);
|
||||
};
|
||||
|
||||
template<typename... KK> GKernelPackage kernels()
|
||||
{
|
||||
GKernelPackage pkg;
|
||||
|
||||
// For those who wonder - below is a trick to call a number of
|
||||
// methods based on parameter pack (zeroes just help hiding these
|
||||
// calls into a sequence which helps to expand this parameter pack).
|
||||
// Just note that `f(),a` always equals to `a` (with f() called!)
|
||||
// and parentheses are used to hide function call in the expanded sequence.
|
||||
// Leading 0 helps to handle case when KK is an empty list (kernels<>()).
|
||||
|
||||
int unused[] = { 0, (pkg.include<KK>(), 0)... };
|
||||
cv::util::suppress_unused_warning(unused);
|
||||
return pkg;
|
||||
};
|
||||
|
||||
// Return a new package based on `lhs` and `rhs`,
|
||||
// with unity policy defined by `policy`.
|
||||
GAPI_EXPORTS GKernelPackage combine(const GKernelPackage &lhs,
|
||||
const GKernelPackage &rhs,
|
||||
const cv::unite_policy policy);
|
||||
} // namespace gapi
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<> struct CompileArgTag<cv::gapi::GKernelPackage>
|
||||
{
|
||||
static const char* tag() { return "gapi.kernel_package"; }
|
||||
};
|
||||
template<> struct CompileArgTag<cv::gapi::GLookupOrder>
|
||||
{
|
||||
static const char* tag() { return "gapi.lookup_order"; }
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GKERNEL_HPP
|
||||
@@ -0,0 +1,131 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GMAT_HPP
|
||||
#define OPENCV_GAPI_GMAT_HPP
|
||||
|
||||
#include <ostream>
|
||||
#include <memory> // std::shared_ptr
|
||||
|
||||
#include <opencv2/gapi/opencv_includes.hpp>
|
||||
#include <opencv2/gapi/gcommon.hpp> // GShape
|
||||
|
||||
#include "opencv2/gapi/own/types.hpp" // cv::gapi::own::Size
|
||||
#include "opencv2/gapi/own/convert.hpp" // to_own
|
||||
#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;
|
||||
|
||||
class GAPI_EXPORTS GMat
|
||||
{
|
||||
public:
|
||||
GMat(); // Empty constructor
|
||||
GMat(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;
|
||||
};
|
||||
|
||||
struct GAPI_EXPORTS GMatDesc
|
||||
{
|
||||
// FIXME: Default initializers in C++14
|
||||
int depth;
|
||||
int chan;
|
||||
cv::gapi::own::Size size; // NB.: no multi-dimensional cases covered yet
|
||||
|
||||
inline bool operator== (const GMatDesc &rhs) const
|
||||
{
|
||||
return depth == rhs.depth && chan == rhs.chan && size == rhs.size;
|
||||
}
|
||||
|
||||
inline bool operator!= (const GMatDesc &rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
// Meta combinator: return a new GMatDesc which differs in size by delta
|
||||
// (all other fields are taken unchanged from this GMatDesc)
|
||||
// FIXME: a better name?
|
||||
GMatDesc withSizeDelta(cv::gapi::own::Size delta) const
|
||||
{
|
||||
GMatDesc desc(*this);
|
||||
desc.size += delta;
|
||||
return desc;
|
||||
}
|
||||
|
||||
GMatDesc withSizeDelta(cv::Size delta) const
|
||||
{
|
||||
return withSizeDelta(to_own(delta));
|
||||
}
|
||||
|
||||
// Meta combinator: return a new GMatDesc which differs in size by delta
|
||||
// (all other fields are taken unchanged from this GMatDesc)
|
||||
//
|
||||
// This is an overload.
|
||||
GMatDesc withSizeDelta(int dx, int dy) const
|
||||
{
|
||||
return withSizeDelta(cv::gapi::own::Size{dx,dy});
|
||||
}
|
||||
|
||||
GMatDesc withSize(cv::gapi::own::Size sz) const
|
||||
{
|
||||
GMatDesc desc(*this);
|
||||
desc.size = sz;
|
||||
return desc;
|
||||
}
|
||||
|
||||
GMatDesc withSize(cv::Size sz) const
|
||||
{
|
||||
return withSize(to_own(sz));
|
||||
}
|
||||
|
||||
// Meta combinator: return a new GMatDesc with specified data depth.
|
||||
// (all other fields are taken unchanged from this GMatDesc)
|
||||
GMatDesc withDepth(int ddepth) const
|
||||
{
|
||||
GAPI_Assert(CV_MAT_CN(ddepth) == 1 || ddepth == -1);
|
||||
GMatDesc desc(*this);
|
||||
if (ddepth != -1) desc.depth = ddepth;
|
||||
return desc;
|
||||
}
|
||||
|
||||
// Meta combinator: return a new GMatDesc with specified data depth
|
||||
// and number of channels.
|
||||
// (all other fields are taken unchanged from this GMatDesc)
|
||||
GMatDesc withType(int ddepth, int dchan) const
|
||||
{
|
||||
GAPI_Assert(CV_MAT_CN(ddepth) == 1 || ddepth == -1);
|
||||
GMatDesc desc = withDepth(ddepth);
|
||||
desc.chan = dchan;
|
||||
return desc;
|
||||
}
|
||||
};
|
||||
|
||||
static inline GMatDesc empty_gmat_desc() { return GMatDesc{-1,-1,{-1,-1}}; }
|
||||
|
||||
class Mat;
|
||||
GAPI_EXPORTS GMatDesc descr_of(const cv::Mat &mat);
|
||||
|
||||
namespace gapi { namespace own {
|
||||
class Mat;
|
||||
CV_EXPORTS GMatDesc descr_of(const Mat &mat);
|
||||
}}//gapi::own
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const cv::GMatDesc &desc);
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GMAT_HPP
|
||||
@@ -0,0 +1,66 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GMETAARG_HPP
|
||||
#define OPENCV_GAPI_GMETAARG_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
|
||||
#include "opencv2/gapi/util/util.hpp"
|
||||
#include "opencv2/gapi/util/variant.hpp"
|
||||
|
||||
#include "opencv2/gapi/gmat.hpp"
|
||||
#include "opencv2/gapi/gscalar.hpp"
|
||||
#include "opencv2/gapi/garray.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
// FIXME: Rename to GMeta?
|
||||
// FIXME: user shouldn't deal with it - put to detail?
|
||||
// GMetaArg is an union type over descriptions of G-types which can serve as
|
||||
// GComputation's in/output slots.
|
||||
//
|
||||
// GMetaArg objects are passed as arguments to GComputation::compile()
|
||||
// to specify which data a compiled computation should be specialized on.
|
||||
// For manual compile(), user must supply this metadata, in case of apply()
|
||||
// this metadata is taken from arguments computation should operate on.
|
||||
//
|
||||
// The first type (monostate) is equal to "uninitialized"/"unresolved" meta.
|
||||
using GMetaArg = util::variant
|
||||
< util::monostate
|
||||
, GMatDesc
|
||||
, GScalarDesc
|
||||
, GArrayDesc
|
||||
>;
|
||||
std::ostream& operator<<(std::ostream& os, const GMetaArg &);
|
||||
|
||||
using GMetaArgs = std::vector<GMetaArg>;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// These traits are used by GComputation::compile()
|
||||
|
||||
// FIXME: is_constructible<T> doesn't work as variant doesn't do any SFINAE
|
||||
// in its current template constructor
|
||||
|
||||
template<typename T> struct is_meta_descr : std::false_type {};
|
||||
template<> struct is_meta_descr<GMatDesc> : std::true_type {};
|
||||
template<> struct is_meta_descr<GScalarDesc> : std::true_type {};
|
||||
template<> struct is_meta_descr<GArrayDesc> : std::true_type {};
|
||||
|
||||
template<typename... Ts>
|
||||
using are_meta_descrs = all_satisfy<is_meta_descr, Ts...>;
|
||||
|
||||
template<typename... Ts>
|
||||
using are_meta_descrs_but_last = all_satisfy<is_meta_descr, typename all_but_last<Ts...>::type>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GMETAARG_HPP
|
||||
@@ -0,0 +1,96 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GPROTO_HPP
|
||||
#define OPENCV_GAPI_GPROTO_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
|
||||
#include "opencv2/gapi/util/variant.hpp"
|
||||
|
||||
#include "opencv2/gapi/gmat.hpp"
|
||||
#include "opencv2/gapi/gscalar.hpp"
|
||||
#include "opencv2/gapi/garray.hpp"
|
||||
#include "opencv2/gapi/garg.hpp"
|
||||
#include "opencv2/gapi/gmetaarg.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
// FIXME: user shouldn't deal with it - put to detail?
|
||||
// GProtoArg is an union type over G-types which can serve as
|
||||
// GComputation's in/output slots. In other words, GProtoArg
|
||||
// wraps any type which can serve as G-API exchange type.
|
||||
//
|
||||
// In Runtime, GProtoArgs are substituted with appropriate GRunArgs.
|
||||
//
|
||||
// GProtoArg objects are constructed in-place when user describes
|
||||
// (captures) computations, user doesn't interact with these types
|
||||
// directly.
|
||||
using GProtoArg = util::variant
|
||||
< GMat
|
||||
, GScalar
|
||||
, detail::GArrayU // instead of GArray<T>
|
||||
>;
|
||||
|
||||
using GProtoArgs = std::vector<GProtoArg>;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename... Ts> inline GProtoArgs packArgs(Ts... args)
|
||||
{
|
||||
return GProtoArgs{ GProtoArg(wrap_gapi_helper<Ts>::wrap(args))... };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<class Tag>
|
||||
struct GIOProtoArgs
|
||||
{
|
||||
public:
|
||||
explicit GIOProtoArgs(const GProtoArgs& args) : m_args(args) {}
|
||||
explicit GIOProtoArgs(GProtoArgs &&args) : m_args(std::move(args)) {}
|
||||
|
||||
GProtoArgs m_args;
|
||||
};
|
||||
|
||||
struct In_Tag{};
|
||||
struct Out_Tag{};
|
||||
|
||||
using GProtoInputArgs = GIOProtoArgs<In_Tag>;
|
||||
using GProtoOutputArgs = GIOProtoArgs<Out_Tag>;
|
||||
|
||||
// Perfect forwarding
|
||||
template<typename... Ts> inline GProtoInputArgs GIn(Ts&&... ts)
|
||||
{
|
||||
return GProtoInputArgs(detail::packArgs(std::forward<Ts>(ts)...));
|
||||
}
|
||||
|
||||
template<typename... Ts> inline GProtoOutputArgs GOut(Ts&&... ts)
|
||||
{
|
||||
return GProtoOutputArgs(detail::packArgs(std::forward<Ts>(ts)...));
|
||||
}
|
||||
|
||||
// Extract run-time arguments from node origin
|
||||
// Can be used to extract constant values associated with G-objects
|
||||
// (like GScalar) at graph construction time
|
||||
GRunArg value_of(const GOrigin &origin);
|
||||
|
||||
// Transform run-time computation arguments into a collection of metadata
|
||||
// extracted from that arguments
|
||||
GMetaArg GAPI_EXPORTS descr_of(const GRunArg &arg );
|
||||
GMetaArgs GAPI_EXPORTS descr_of(const GRunArgs &args);
|
||||
|
||||
// Transform run-time operation result argument into metadata extracted from that argument
|
||||
// Used to compare the metadata, which generated at compile time with the metadata result operation in run time
|
||||
GMetaArg GAPI_EXPORTS descr_of(const GRunArgP& argp);
|
||||
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GPROTO_HPP
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GSCALAR_HPP
|
||||
#define OPENCV_GAPI_GSCALAR_HPP
|
||||
|
||||
#include <ostream>
|
||||
|
||||
#include <opencv2/gapi/opencv_includes.hpp>
|
||||
#include <opencv2/gapi/gcommon.hpp> // GShape
|
||||
#include <opencv2/gapi/util/optional.hpp>
|
||||
#include "opencv2/gapi/own/scalar.hpp"
|
||||
#include <opencv2/core/types.hpp>
|
||||
|
||||
// TODO GAPI_EXPORTS or so
|
||||
namespace cv
|
||||
{
|
||||
// Forward declaration; GNode and GOrigin are an internal
|
||||
// (user-inaccessible) classes.
|
||||
class GNode;
|
||||
struct GOrigin;
|
||||
|
||||
class GAPI_EXPORTS GScalar
|
||||
{
|
||||
public:
|
||||
GScalar(); // Empty constructor
|
||||
explicit GScalar(const cv::gapi::own::Scalar& s); // Constant value constructor from cv::gapi::own::Scalar
|
||||
explicit GScalar(cv::gapi::own::Scalar&& s); // Constant value move-constructor from cv::gapi::own::Scalar
|
||||
explicit GScalar(const cv::Scalar& s); // Constant value constructor from cv::Scalar
|
||||
GScalar(double v0); // Constant value constructor from double
|
||||
GScalar(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;
|
||||
};
|
||||
|
||||
struct GScalarDesc
|
||||
{
|
||||
// NB.: right now it is empty
|
||||
|
||||
inline bool operator== (const GScalarDesc &) const
|
||||
{
|
||||
return true; // NB: implement this method if GScalar meta appears
|
||||
}
|
||||
|
||||
inline bool operator!= (const GScalarDesc &rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
static inline GScalarDesc empty_scalar_desc() { return GScalarDesc(); }
|
||||
|
||||
GAPI_EXPORTS GScalarDesc descr_of(const cv::gapi::own::Scalar &scalar);
|
||||
GAPI_EXPORTS GScalarDesc descr_of(const cv::Scalar &scalar);
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const cv::GScalarDesc &desc);
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GSCALAR_HPP
|
||||
@@ -0,0 +1,150 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GTYPE_TRAITS_HPP
|
||||
#define OPENCV_GAPI_GTYPE_TRAITS_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
|
||||
#include <opencv2/gapi/gmat.hpp>
|
||||
#include <opencv2/gapi/gscalar.hpp>
|
||||
#include <opencv2/gapi/garray.hpp>
|
||||
#include <opencv2/gapi/gcommon.hpp>
|
||||
#include <opencv2/gapi/own/convert.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// FIXME: These traits and enum and possible numerous switch(kind)
|
||||
// block may be replaced with a special Handler<T> object or with
|
||||
// a double dispatch
|
||||
enum class ArgKind: int
|
||||
{
|
||||
OPAQUE, // Unknown, generic, opaque-to-GAPI data type - STATIC
|
||||
GOBJREF, // <internal> reference to object
|
||||
GMAT, // a cv::GMat
|
||||
GSCALAR, // a cv::GScalar
|
||||
GARRAY, // a cv::GArrayU (note - exactly GArrayU, not GArray<T>!)
|
||||
};
|
||||
|
||||
// Describe G-API types (G-types) with traits. Mostly used by
|
||||
// cv::GArg to store meta information about types passed into
|
||||
// operation arguments. Please note that cv::GComputation is
|
||||
// defined on GProtoArgs, not GArgs!
|
||||
template<typename T> struct GTypeTraits;
|
||||
template<typename T> struct GTypeTraits
|
||||
{
|
||||
static constexpr const ArgKind kind = ArgKind::OPAQUE;
|
||||
};
|
||||
template<> struct GTypeTraits<cv::GMat>
|
||||
{
|
||||
static constexpr const ArgKind kind = ArgKind::GMAT;
|
||||
static constexpr const GShape shape = GShape::GMAT;
|
||||
};
|
||||
template<> struct GTypeTraits<cv::GScalar>
|
||||
{
|
||||
static constexpr const ArgKind kind = ArgKind::GSCALAR;
|
||||
static constexpr const GShape shape = GShape::GSCALAR;
|
||||
};
|
||||
template<class T> struct GTypeTraits<cv::GArray<T> >
|
||||
{
|
||||
static constexpr const ArgKind kind = ArgKind::GARRAY;
|
||||
static constexpr const GShape shape = GShape::GARRAY;
|
||||
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();}
|
||||
static cv::detail::VectorRef wrap_in (const std::vector<T> &t) { return detail::VectorRef(t); }
|
||||
static cv::detail::VectorRef wrap_out ( std::vector<T> &t) { return detail::VectorRef(t); }
|
||||
};
|
||||
|
||||
// Tests if Trait for type T requires extra marshalling ("custom wrap") or not.
|
||||
// If Traits<T> has wrap_value() defined, it does.
|
||||
template<class T> struct has_custom_wrap
|
||||
{
|
||||
template<class,class> class check;
|
||||
template<typename C> static std::true_type test(check<C, decltype(>ypeTraits<C>::wrap_value)> *);
|
||||
template<typename C> static std::false_type test(...);
|
||||
using type = decltype(test<T>(nullptr));
|
||||
static const constexpr bool value = std::is_same<std::true_type, decltype(test<T>(nullptr))>::value;
|
||||
};
|
||||
|
||||
// Resolve a Host type back to its associated G-Type.
|
||||
// FIXME: Probably it can be avoided
|
||||
template<typename T> struct GTypeOf;
|
||||
template<> struct GTypeOf<cv::Mat> { using type = cv::GMat; };
|
||||
template<> struct GTypeOf<cv::gapi::own::Mat> { using type = cv::GMat; };
|
||||
template<> struct GTypeOf<cv::Scalar> { using type = cv::GScalar; };
|
||||
template<> struct GTypeOf<cv::gapi::own::Scalar> { using type = cv::GScalar; };
|
||||
template<typename U> struct GTypeOf<std::vector<U> > { using type = cv::GArray<U>; };
|
||||
template<class T> using g_type_of_t = typename GTypeOf<T>::type;
|
||||
|
||||
// Marshalling helper for G-types and its Host types. Helps G-API
|
||||
// to store G types in internal generic containers for further
|
||||
// processing. Implements the following callbacks:
|
||||
//
|
||||
// * wrap() - converts user-facing G-type into an internal one
|
||||
// for internal storage.
|
||||
// Used when G-API operation is instantiated (G<Kernel>::on(),
|
||||
// etc) during expressing a pipeline. Mostly returns input
|
||||
// value "as is" except the case when G-type is a template. For
|
||||
// template G-classes, calls custom wrap() from Traits.
|
||||
// The value returned by wrap() is then wrapped into GArg() and
|
||||
// stored in G-API metadata.
|
||||
//
|
||||
// Example:
|
||||
// - cv::GMat arguments are passed as-is.
|
||||
// - integers, pointers, STL containers, user types are passed as-is.
|
||||
// - cv::GArray<T> is converted to cv::GArrayU.
|
||||
//
|
||||
// * wrap_in() / wrap_out() - convert Host type associated with
|
||||
// G-type to internal representation type.
|
||||
//
|
||||
// - For "simple" (non-template) G-types, returns value as-is.
|
||||
// Example: cv::GMat has host type cv::Mat, when user passes a
|
||||
// cv::Mat, system stores it internally as cv::Mat.
|
||||
//
|
||||
// - For "complex" (template) G-types, utilizes custom
|
||||
// wrap_in()/wrap_out() as described in Traits.
|
||||
// Example: cv::GArray<T> has host type std::vector<T>, when
|
||||
// user passes a std::vector<T>, system stores it
|
||||
// internally as VectorRef (with <T> stripped away).
|
||||
template<typename T, class Custom = void> struct WrapValue
|
||||
{
|
||||
static auto wrap(const T& t) ->
|
||||
typename std::remove_reference<T>::type
|
||||
{
|
||||
return static_cast<typename std::remove_reference<T>::type>(t);
|
||||
}
|
||||
|
||||
template<typename U> static U wrap_in (const U &u) { return u; }
|
||||
template<typename U> static U* wrap_out(U &u) { return &u; }
|
||||
};
|
||||
template<typename T> struct WrapValue<T, typename std::enable_if<has_custom_wrap<T>::value>::type>
|
||||
{
|
||||
static auto wrap(const T& t) -> decltype(GTypeTraits<T>::wrap_value(t))
|
||||
{
|
||||
return GTypeTraits<T>::wrap_value(t);
|
||||
}
|
||||
template<typename U> static auto wrap_in (const U &u) -> typename GTypeTraits<T>::strip_type
|
||||
{
|
||||
return GTypeTraits<T>::wrap_in(u);
|
||||
}
|
||||
template<typename U> static auto wrap_out(U &u) -> typename GTypeTraits<T>::strip_type
|
||||
{
|
||||
return GTypeTraits<T>::wrap_out(u);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> using wrap_gapi_helper = WrapValue<typename std::decay<T>::type>;
|
||||
template<typename T> using wrap_host_helper = WrapValue<typename std::decay<g_type_of_t<T> >::type>;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GTYPE_TRAITS_HPP
|
||||
@@ -0,0 +1,186 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GTYPED_HPP
|
||||
#define OPENCV_GAPI_GTYPED_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "opencv2/gapi/gcomputation.hpp"
|
||||
#include "opencv2/gapi/gcompiled.hpp"
|
||||
#include "opencv2/gapi/gproto.hpp"
|
||||
#include "opencv2/gapi/gcommon.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// FIXME: How to prevent coolhackers from extending it by their own types?
|
||||
// FIXME: ...Should we care?
|
||||
template<typename T> struct ProtoToParam;
|
||||
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<typename T> using ProtoToParamT = typename ProtoToParam<T>::type;
|
||||
|
||||
template<typename T> struct ProtoToMeta;
|
||||
template<> struct ProtoToMeta<cv::GMat> { using type = cv::GMatDesc; };
|
||||
template<> struct ProtoToMeta<cv::GScalar> { using type = cv::GScalarDesc; };
|
||||
template<typename U> struct ProtoToMeta<cv::GArray<U> > { using type = cv::GArrayDesc; };
|
||||
template<typename T> using ProtoToMetaT = typename ProtoToMeta<T>::type;
|
||||
|
||||
//workaround for MSVC 19.0 bug
|
||||
template <typename T>
|
||||
auto make_default()->decltype(T{}) {return {};}
|
||||
}; // detail
|
||||
|
||||
template<typename> class GComputationT;
|
||||
|
||||
// Single return value implementation
|
||||
template<typename R, typename... Args> class GComputationT<R(Args...)>
|
||||
{
|
||||
public:
|
||||
typedef std::function<R(Args...)> Gen;
|
||||
|
||||
class GCompiledT
|
||||
{
|
||||
private:
|
||||
friend class GComputationT<R(Args...)>;
|
||||
|
||||
cv::GCompiled m_comp;
|
||||
|
||||
explicit GCompiledT(const cv::GCompiled &comp) : m_comp(comp) {}
|
||||
|
||||
public:
|
||||
GCompiledT() {}
|
||||
|
||||
void operator()(detail::ProtoToParamT<Args>... inArgs,
|
||||
detail::ProtoToParamT<R> &outArg)
|
||||
{
|
||||
m_comp(cv::gin(inArgs...), cv::gout(outArg));
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return static_cast<bool>(m_comp);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
typedef std::pair<R, GProtoInputArgs > Captured;
|
||||
|
||||
Captured capture(const Gen& g, Args... args)
|
||||
{
|
||||
return Captured(g(args...), cv::GIn(args...));
|
||||
}
|
||||
|
||||
Captured m_capture;
|
||||
cv::GComputation m_comp;
|
||||
|
||||
public:
|
||||
GComputationT(const Gen &generator)
|
||||
: m_capture(capture(generator, detail::make_default<Args>()...))
|
||||
, m_comp(cv::GProtoInputArgs(std::move(m_capture.second)),
|
||||
cv::GOut(m_capture.first))
|
||||
{
|
||||
}
|
||||
|
||||
void apply(detail::ProtoToParamT<Args>... inArgs,
|
||||
detail::ProtoToParamT<R> &outArg)
|
||||
{
|
||||
m_comp.apply(cv::gin(inArgs...), cv::gout(outArg));
|
||||
}
|
||||
|
||||
GCompiledT compile(detail::ProtoToMetaT<Args>... inDescs)
|
||||
{
|
||||
GMetaArgs inMetas = { GMetaArg(inDescs)... };
|
||||
return GCompiledT(m_comp.compile(std::move(inMetas), GCompileArgs()));
|
||||
}
|
||||
|
||||
GCompiledT compile(detail::ProtoToMetaT<Args>... inDescs, GCompileArgs &&args)
|
||||
{
|
||||
GMetaArgs inMetas = { GMetaArg(inDescs)... };
|
||||
return GCompiledT(m_comp.compile(std::move(inMetas), std::move(args)));
|
||||
}
|
||||
};
|
||||
|
||||
// Multiple (fixed) return value implementation. FIXME: How to avoid copy-paste?
|
||||
template<typename... R, typename... Args> class GComputationT<std::tuple<R...>(Args...)>
|
||||
{
|
||||
public:
|
||||
typedef std::function<std::tuple<R...>(Args...)> Gen;
|
||||
|
||||
class GCompiledT
|
||||
{
|
||||
private:
|
||||
friend class GComputationT<std::tuple<R...>(Args...)>;
|
||||
|
||||
cv::GCompiled m_comp;
|
||||
explicit GCompiledT(const cv::GCompiled &comp) : m_comp(comp) {}
|
||||
|
||||
public:
|
||||
GCompiledT() {}
|
||||
|
||||
void operator()(detail::ProtoToParamT<Args>... inArgs,
|
||||
detail::ProtoToParamT<R>&... outArgs)
|
||||
{
|
||||
m_comp(cv::gin(inArgs...), cv::gout(outArgs...));
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return static_cast<bool>(m_comp);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
typedef std::pair<GProtoArgs, GProtoArgs> Captured;
|
||||
|
||||
template<int... IIs>
|
||||
Captured capture(GProtoArgs &&args, const std::tuple<R...> &rr, detail::Seq<IIs...>)
|
||||
{
|
||||
return Captured(cv::GOut(std::get<IIs>(rr)...).m_args, args);
|
||||
}
|
||||
|
||||
Captured capture(const Gen& g, Args... args)
|
||||
{
|
||||
return capture(cv::GIn(args...).m_args, g(args...), typename detail::MkSeq<sizeof...(R)>::type());
|
||||
}
|
||||
|
||||
Captured m_capture;
|
||||
cv::GComputation m_comp;
|
||||
|
||||
public:
|
||||
GComputationT(const Gen &generator)
|
||||
: m_capture(capture(generator, detail::make_default<Args>()...))
|
||||
, m_comp(cv::GProtoInputArgs(std::move(m_capture.second)),
|
||||
cv::GProtoOutputArgs(std::move(m_capture.first)))
|
||||
{
|
||||
}
|
||||
|
||||
void apply(detail::ProtoToParamT<Args>... inArgs,
|
||||
detail::ProtoToParamT<R>&... outArgs)
|
||||
{
|
||||
m_comp.apply(cv::gin(inArgs...), cv::gout(outArgs...));
|
||||
}
|
||||
|
||||
GCompiledT compile(detail::ProtoToMetaT<Args>... inDescs)
|
||||
{
|
||||
GMetaArgs inMetas = { GMetaArg(inDescs)... };
|
||||
return GCompiledT(m_comp.compile(std::move(inMetas), GCompileArgs()));
|
||||
}
|
||||
|
||||
GCompiledT compile(detail::ProtoToMetaT<Args>... inDescs, GCompileArgs &&args)
|
||||
{
|
||||
GMetaArgs inMetas = { GMetaArg(inDescs)... };
|
||||
return GCompiledT(m_comp.compile(std::move(inMetas), std::move(args)));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GTYPED_HPP
|
||||
@@ -0,0 +1,677 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_IMGPROC_HPP
|
||||
#define OPENCV_GAPI_IMGPROC_HPP
|
||||
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
#include <utility> // std::tuple
|
||||
|
||||
#include "opencv2/gapi/gkernel.hpp"
|
||||
#include "opencv2/gapi/gmat.hpp"
|
||||
#include "opencv2/gapi/gscalar.hpp"
|
||||
|
||||
|
||||
/** \defgroup gapi_imgproc G-API image processing functionality
|
||||
@{
|
||||
@defgroup gapi_filters Graph API: Image filters
|
||||
@defgroup gapi_colorconvert Graph API: Converting image from one color space to another
|
||||
@}
|
||||
*/
|
||||
|
||||
namespace cv { namespace gapi {
|
||||
|
||||
namespace imgproc {
|
||||
using GMat3 = std::tuple<GMat,GMat,GMat>; // FIXME: how to avoid this?
|
||||
|
||||
G_TYPED_KERNEL(GFilter2D, <GMat(GMat,int,Mat,Point,Scalar,int,Scalar)>,"org.opencv.imgproc.filters.filter2D") {
|
||||
static GMatDesc outMeta(GMatDesc in, int ddepth, Mat, Point, Scalar, int, Scalar) {
|
||||
return in.withDepth(ddepth);
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GSepFilter, <GMat(GMat,int,Mat,Mat,Point,Scalar,int,Scalar)>, "org.opencv.imgproc.filters.sepfilter") {
|
||||
static GMatDesc outMeta(GMatDesc in, int ddepth, Mat, Mat, Point, Scalar, int, Scalar) {
|
||||
return in.withDepth(ddepth);
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GBoxFilter, <GMat(GMat,int,Size,Point,bool,int,Scalar)>, "org.opencv.imgproc.filters.boxfilter") {
|
||||
static GMatDesc outMeta(GMatDesc in, int ddepth, Size, Point, bool, int, Scalar) {
|
||||
return in.withDepth(ddepth);
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GBlur, <GMat(GMat,Size,Point,int,Scalar)>, "org.opencv.imgproc.filters.blur"){
|
||||
static GMatDesc outMeta(GMatDesc in, Size, Point, int, Scalar) {
|
||||
return in;
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GGaussBlur, <GMat(GMat,Size,double,double,int,Scalar)>, "org.opencv.imgproc.filters.gaussianBlur") {
|
||||
static GMatDesc outMeta(GMatDesc in, Size, double, double, int, Scalar) {
|
||||
return in;
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GMedianBlur, <GMat(GMat,int)>, "org.opencv.imgproc.filters.medianBlur") {
|
||||
static GMatDesc outMeta(GMatDesc in, int) {
|
||||
return in;
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GErode, <GMat(GMat,Mat,Point,int,int,Scalar)>, "org.opencv.imgproc.filters.erode") {
|
||||
static GMatDesc outMeta(GMatDesc in, Mat, Point, int, int, Scalar) {
|
||||
return in;
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GDilate, <GMat(GMat,Mat,Point,int,int,Scalar)>, "org.opencv.imgproc.filters.dilate") {
|
||||
static GMatDesc outMeta(GMatDesc in, Mat, Point, int, int, Scalar) {
|
||||
return in;
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GSobel, <GMat(GMat,int,int,int,int,double,double,int,Scalar)>, "org.opencv.imgproc.filters.sobel") {
|
||||
static GMatDesc outMeta(GMatDesc in, int ddepth, int, int, int, double, double, int, Scalar) {
|
||||
return in.withDepth(ddepth);
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GEqHist, <GMat(GMat)>, "org.opencv.imgproc.equalizeHist"){
|
||||
static GMatDesc outMeta(GMatDesc in) {
|
||||
return in.withType(CV_8U, 1);
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GCanny, <GMat(GMat,double,double,int,bool)>, "org.opencv.imgproc.canny"){
|
||||
static GMatDesc outMeta(GMatDesc in, double, double, int, bool) {
|
||||
return in.withType(CV_8U, 1);
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GRGB2YUV, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.rgb2yuv") {
|
||||
static GMatDesc outMeta(GMatDesc in) {
|
||||
return in; // type still remains CV_8UC3;
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GYUV2RGB, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.yuv2rgb") {
|
||||
static GMatDesc outMeta(GMatDesc in) {
|
||||
return in; // type still remains CV_8UC3;
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GRGB2Lab, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.rgb2lab") {
|
||||
static GMatDesc outMeta(GMatDesc in) {
|
||||
return in; // type still remains CV_8UC3;
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GBGR2LUV, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.bgr2luv") {
|
||||
static GMatDesc outMeta(GMatDesc in) {
|
||||
return in; // type still remains CV_8UC3;
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GLUV2BGR, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.luv2bgr") {
|
||||
static GMatDesc outMeta(GMatDesc in) {
|
||||
return in; // type still remains CV_8UC3;
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GYUV2BGR, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.yuv2bgr") {
|
||||
static GMatDesc outMeta(GMatDesc in) {
|
||||
return in; // type still remains CV_8UC3;
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GBGR2YUV, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.bgr2yuv") {
|
||||
static GMatDesc outMeta(GMatDesc in) {
|
||||
return in; // type still remains CV_8UC3;
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GRGB2Gray, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.rgb2gray") {
|
||||
static GMatDesc outMeta(GMatDesc in) {
|
||||
return in.withType(CV_8U, 1);
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GRGB2GrayCustom, <GMat(GMat,float,float,float)>, "org.opencv.imgproc.colorconvert.rgb2graycustom") {
|
||||
static GMatDesc outMeta(GMatDesc in, float, float, float) {
|
||||
return in.withType(CV_8U, 1);
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GBGR2Gray, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.bgr2gray") {
|
||||
static GMatDesc outMeta(GMatDesc in) {
|
||||
return in.withType(CV_8U, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//! @addtogroup gapi_filters
|
||||
//! @{
|
||||
/** @brief Applies a separable linear filter to a matrix(image).
|
||||
|
||||
The function applies a separable linear filter to the matrix. That is, first, every row of src is
|
||||
filtered with the 1D kernel kernelX. Then, every column of the result is filtered with the 1D
|
||||
kernel kernelY. The final result is returned.
|
||||
|
||||
Supported 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.
|
||||
@note In case of floating-point computation, rounding to nearest even is procedeed
|
||||
if hardware supports it (if not - to nearest value).
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.filters.sepfilter"
|
||||
@param src Source image.
|
||||
@param ddepth desired depth of the destination image (the following combinations of src.depth() and ddepth are supported:
|
||||
|
||||
src.depth() = CV_8U, ddepth = -1/CV_16S/CV_32F/CV_64F
|
||||
src.depth() = CV_16U/CV_16S, ddepth = -1/CV_32F/CV_64F
|
||||
src.depth() = CV_32F, ddepth = -1/CV_32F/CV_64F
|
||||
src.depth() = CV_64F, ddepth = -1/CV_64F
|
||||
|
||||
when ddepth=-1, the output image will have the same depth as the source)
|
||||
@param kernelX Coefficients for filtering each row.
|
||||
@param kernelY Coefficients for filtering each column.
|
||||
@param anchor Anchor position within the kernel. The default value \f$(-1,-1)\f$ means that the anchor
|
||||
is at the kernel center.
|
||||
@param delta Value added to the filtered results before storing them.
|
||||
@param borderType Pixel extrapolation method, see cv::BorderTypes
|
||||
@param borderValue border value in case of constant border type
|
||||
@sa boxFilter, gaussianBlur, medianBlur
|
||||
*/
|
||||
GAPI_EXPORTS GMat sepFilter(const GMat& src, int ddepth, const Mat& kernelX, const Mat& kernelY, const Point& anchor /*FIXME: = Point(-1,-1)*/,
|
||||
const Scalar& delta /*FIXME = GScalar(0)*/, int borderType = BORDER_DEFAULT,
|
||||
const Scalar& borderValue = Scalar(0));
|
||||
|
||||
/** @brief Convolves an image with the kernel.
|
||||
|
||||
The function applies an arbitrary linear filter to an image. When
|
||||
the aperture is partially outside the image, the function interpolates outlier pixel values
|
||||
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]
|
||||
|
||||
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 -
|
||||
anchor.y - 1)`.
|
||||
|
||||
Supported 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 size and number of channels an input image.
|
||||
@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.filters.filter2D"
|
||||
|
||||
@param src input image.
|
||||
@param ddepth desired depth of the destination image
|
||||
@param kernel convolution kernel (or rather a correlation kernel), a single-channel floating point
|
||||
matrix; if you want to apply different kernels to different channels, split the image into
|
||||
separate color planes using split and process them individually.
|
||||
@param anchor anchor of the kernel that indicates the relative position of a filtered point within
|
||||
the kernel; the anchor should lie within the kernel; default value (-1,-1) means that the anchor
|
||||
is at the kernel center.
|
||||
@param delta optional value added to the filtered pixels before storing them in dst.
|
||||
@param borderType pixel extrapolation method, see cv::BorderTypes
|
||||
@param borderValue border value in case of constant border type
|
||||
@sa sepFilter
|
||||
*/
|
||||
GAPI_EXPORTS GMat filter2D(const GMat& src, int ddepth, const Mat& kernel, const Point& anchor = Point(-1,-1), const Scalar& delta = Scalar(0),
|
||||
int borderType = BORDER_DEFAULT, const Scalar& borderValue = Scalar(0));
|
||||
|
||||
|
||||
/** @brief Blurs an image using the box filter.
|
||||
|
||||
The function smooths an image using the kernel:
|
||||
|
||||
\f[\texttt{K} = \alpha \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]
|
||||
|
||||
where
|
||||
|
||||
\f[\alpha = \fork{\frac{1}{\texttt{ksize.width*ksize.height}}}{when \texttt{normalize=true}}{1}{otherwise}\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
|
||||
algorithms, and so on). If you need to compute pixel sums over variable-size windows, use cv::integral.
|
||||
|
||||
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.
|
||||
@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.filters.boxfilter"
|
||||
|
||||
@param src Source image.
|
||||
@param dtype the output image depth (-1 to set the input image data type).
|
||||
@param ksize blurring kernel size.
|
||||
@param anchor Anchor position within the kernel. The default value \f$(-1,-1)\f$ means that the anchor
|
||||
is at the kernel center.
|
||||
@param normalize flag, specifying whether the kernel is normalized by its area or not.
|
||||
@param borderType Pixel extrapolation method, see cv::BorderTypes
|
||||
@param borderValue border value in case of constant border type
|
||||
@sa sepFilter, gaussianBlur, medianBlur, integral
|
||||
*/
|
||||
GAPI_EXPORTS GMat boxFilter(const GMat& src, int dtype, const Size& ksize, const Point& anchor = Point(-1,-1),
|
||||
bool normalize = true, int borderType = BORDER_DEFAULT,
|
||||
const Scalar& borderValue = Scalar(0));
|
||||
|
||||
/** @brief Blurs an image using the normalized box filter.
|
||||
|
||||
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)`.
|
||||
|
||||
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.
|
||||
@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.filters.blur"
|
||||
|
||||
@param src Source image.
|
||||
@param ksize blurring kernel size.
|
||||
@param anchor anchor point; default value Point(-1,-1) means that the anchor is at the kernel
|
||||
center.
|
||||
@param borderType border mode used to extrapolate pixels outside of the image, see cv::BorderTypes
|
||||
@param borderValue border value in case of constant border type
|
||||
@sa boxFilter, bilateralFilter, GaussianBlur, medianBlur
|
||||
*/
|
||||
GAPI_EXPORTS GMat blur(const GMat& src, const Size& ksize, const Point& anchor = Point(-1,-1),
|
||||
int borderType = BORDER_DEFAULT, const Scalar& borderValue = Scalar(0));
|
||||
|
||||
|
||||
//GAPI_EXPORTS_W void blur( InputArray src, OutputArray dst,
|
||||
// Size ksize, Point anchor = Point(-1,-1),
|
||||
// int borderType = BORDER_DEFAULT );
|
||||
|
||||
|
||||
/** @brief Blurs an image using a Gaussian filter.
|
||||
|
||||
The function filter2Ds the source image with the specified Gaussian kernel.
|
||||
Output image must have the same type and number of channels an input image.
|
||||
|
||||
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.
|
||||
@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.filters.gaussianBlur"
|
||||
|
||||
@param src input image;
|
||||
@param ksize Gaussian kernel size. ksize.width and ksize.height can differ but they both must be
|
||||
positive and odd. Or, they can be zero's and then they are computed from sigma.
|
||||
@param sigmaX Gaussian kernel standard deviation in X direction.
|
||||
@param sigmaY Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be
|
||||
equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width and ksize.height,
|
||||
respectively (see cv::getGaussianKernel for details); to fully control the result regardless of
|
||||
possible future modifications of all this semantics, it is recommended to specify all of ksize,
|
||||
sigmaX, and sigmaY.
|
||||
@param borderType pixel extrapolation method, see cv::BorderTypes
|
||||
@param borderValue border value in case of constant border type
|
||||
@sa sepFilter, boxFilter, medianBlur
|
||||
*/
|
||||
GAPI_EXPORTS GMat gaussianBlur(const GMat& src, const Size& ksize, double sigmaX, double sigmaY = 0,
|
||||
int borderType = BORDER_DEFAULT, const Scalar& borderValue = Scalar(0));
|
||||
|
||||
/** @brief Blurs an image using the median filter.
|
||||
|
||||
The function smoothes an image using the median filter with the \f$\texttt{ksize} \times
|
||||
\texttt{ksize}\f$ aperture. Each channel of a multi-channel image is processed independently.
|
||||
Output image must have the same type, size, and number of channels as the input image.
|
||||
@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
|
||||
The median filter uses cv::BORDER_REPLICATE internally to cope with border pixels, see cv::BorderTypes
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.filters.medianBlur"
|
||||
|
||||
@param src input matrix (image)
|
||||
@param ksize aperture linear size; it must be odd and greater than 1, for example: 3, 5, 7 ...
|
||||
@sa boxFilter, gaussianBlur
|
||||
*/
|
||||
GAPI_EXPORTS GMat medianBlur(const GMat& src, int ksize);
|
||||
|
||||
/** @brief Erodes an image by using a specific structuring element.
|
||||
|
||||
The function erodes the source image using the specified structuring element that determines the
|
||||
shape of a pixel neighborhood over which the minimum is taken:
|
||||
|
||||
\f[\texttt{dst} (x,y) = \min _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\f]
|
||||
|
||||
Erosion can be applied several (iterations) times. In case of multi-channel images, each channel is processed independently.
|
||||
Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, and @ref CV_32FC1.
|
||||
Output image must have the same type, size, and number of channels as the input image.
|
||||
@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.filters.erode"
|
||||
|
||||
@param src input image
|
||||
@param kernel structuring element used for erosion; if `element=Mat()`, a `3 x 3` rectangular
|
||||
structuring element is used. Kernel can be created using getStructuringElement.
|
||||
@param anchor position of the anchor within the element; default value (-1, -1) means that the
|
||||
anchor is at the element center.
|
||||
@param iterations number of times erosion is applied.
|
||||
@param borderType pixel extrapolation method, see cv::BorderTypes
|
||||
@param borderValue border value in case of a constant border
|
||||
@sa dilate
|
||||
*/
|
||||
GAPI_EXPORTS GMat erode(const GMat& src, const Mat& kernel, const Point& anchor = Point(-1,-1), int iterations = 1,
|
||||
int borderType = BORDER_CONSTANT,
|
||||
const Scalar& borderValue = morphologyDefaultBorderValue());
|
||||
|
||||
/** @brief Erodes an image by using 3 by 3 rectangular structuring element.
|
||||
|
||||
The function erodes the source image using the rectangular structuring element with rectangle center as an anchor.
|
||||
Erosion can be applied several (iterations) times. In case of multi-channel images, each channel is processed independently.
|
||||
Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, and @ref CV_32FC1.
|
||||
Output image must have the same type, size, and number of channels as the input image.
|
||||
@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
|
||||
|
||||
@param src input image
|
||||
@param iterations number of times erosion is applied.
|
||||
@param borderType pixel extrapolation method, see cv::BorderTypes
|
||||
@param borderValue border value in case of a constant border
|
||||
@sa erode, dilate3x3
|
||||
*/
|
||||
GAPI_EXPORTS GMat erode3x3(const GMat& src, int iterations = 1,
|
||||
int borderType = BORDER_CONSTANT,
|
||||
const Scalar& borderValue = morphologyDefaultBorderValue());
|
||||
|
||||
/** @brief Dilates an image by using a specific structuring element.
|
||||
|
||||
The function dilates the source image using the specified structuring element that determines the
|
||||
shape of a pixel neighborhood over which the maximum is taken:
|
||||
\f[\texttt{dst} (x,y) = \max _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\f]
|
||||
|
||||
Dilation can be applied several (iterations) times. In case of multi-channel images, each channel is processed independently.
|
||||
Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, and @ref CV_32FC1.
|
||||
Output image must have the same type, size, and number of channels as the input image.
|
||||
@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.filters.dilate"
|
||||
|
||||
@param src input image.
|
||||
@param kernel structuring element used for dilation; if elemenat=Mat(), a 3 x 3 rectangular
|
||||
structuring element is used. Kernel can be created using getStructuringElement
|
||||
@param anchor position of the anchor within the element; default value (-1, -1) means that the
|
||||
anchor is at the element center.
|
||||
@param iterations number of times dilation is applied.
|
||||
@param borderType pixel extrapolation method, see cv::BorderTypes
|
||||
@param borderValue border value in case of a constant border
|
||||
@sa erode, morphologyEx, getStructuringElement
|
||||
*/
|
||||
GAPI_EXPORTS GMat dilate(const GMat& src, const Mat& kernel, const Point& anchor = Point(-1,-1), int iterations = 1,
|
||||
int borderType = BORDER_CONSTANT,
|
||||
const Scalar& borderValue = morphologyDefaultBorderValue());
|
||||
|
||||
/** @brief Dilates an image by using 3 by 3 rectangular structuring element.
|
||||
|
||||
The function dilates the source image using the specified structuring element that determines the
|
||||
shape of a pixel neighborhood over which the maximum is taken:
|
||||
\f[\texttt{dst} (x,y) = \max _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\f]
|
||||
|
||||
Dilation can be applied several (iterations) times. In case of multi-channel images, each channel is processed independently.
|
||||
Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, and @ref CV_32FC1.
|
||||
Output image must have the same type, size, and number of channels as the input image.
|
||||
@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.filters.dilate"
|
||||
|
||||
@param src input image.
|
||||
@param iterations number of times dilation is applied.
|
||||
@param borderType pixel extrapolation method, see cv::BorderTypes
|
||||
@param borderValue border value in case of a constant border
|
||||
@sa dilate, erode3x3
|
||||
*/
|
||||
|
||||
GAPI_EXPORTS GMat dilate3x3(const GMat& src, int iterations = 1,
|
||||
int borderType = BORDER_CONSTANT,
|
||||
const Scalar& borderValue = morphologyDefaultBorderValue());
|
||||
|
||||
/** @brief Calculates the first, second, third, or mixed image derivatives using an extended Sobel operator.
|
||||
|
||||
In all cases except one, the \f$\texttt{ksize} \times \texttt{ksize}\f$ separable kernel is used to
|
||||
calculate the derivative. When \f$\texttt{ksize = 1}\f$, the \f$3 \times 1\f$ or \f$1 \times 3\f$
|
||||
kernel is used (that is, no Gaussian smoothing is done). `ksize = 1` can only be used for the first
|
||||
or the second x- or y- derivatives.
|
||||
|
||||
There is also the special value `ksize = CV_SCHARR (-1)` that corresponds to the \f$3\times3\f$ Scharr
|
||||
filter that may give more accurate results than the \f$3\times3\f$ Sobel. The Scharr aperture is
|
||||
|
||||
\f[\vecthreethree{-3}{0}{3}{-10}{0}{10}{-3}{0}{3}\f]
|
||||
|
||||
for the x-derivative, or transposed for the y-derivative.
|
||||
|
||||
The function calculates an image derivative by convolving the image with the appropriate kernel:
|
||||
|
||||
\f[\texttt{dst} = \frac{\partial^{xorder+yorder} \texttt{src}}{\partial x^{xorder} \partial y^{yorder}}\f]
|
||||
|
||||
The Sobel operators combine Gaussian smoothing and differentiation, so the result is more or less
|
||||
resistant to the noise. Most often, the function is called with ( xorder = 1, yorder = 0, ksize = 3)
|
||||
or ( xorder = 0, yorder = 1, ksize = 3) to calculate the first x- or y- image derivative. The first
|
||||
case corresponds to a kernel of:
|
||||
|
||||
\f[\vecthreethree{-1}{0}{1}{-2}{0}{2}{-1}{0}{1}\f]
|
||||
|
||||
The second case corresponds to a kernel of:
|
||||
|
||||
\f[\vecthreethree{-1}{-2}{-1}{0}{0}{0}{1}{2}{1}\f]
|
||||
|
||||
@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.filters.sobel"
|
||||
|
||||
@param src input image.
|
||||
@param ddepth output image depth, see @ref filter_depths "combinations"; in the case of
|
||||
8-bit input images it will result in truncated derivatives.
|
||||
@param dx order of the derivative x.
|
||||
@param dy order of the derivative y.
|
||||
@param ksize size of the extended Sobel kernel; it must be odd.
|
||||
@param scale optional scale factor for the computed derivative values; by default, no scaling is
|
||||
applied (see cv::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 cv::BorderTypes
|
||||
@param borderValue border value in case of constant border type
|
||||
@sa filter2D, gaussianBlur, cartToPolar
|
||||
*/
|
||||
GAPI_EXPORTS GMat sobel(const GMat& src, int ddepth, int dx, int dy, int ksize = 3,
|
||||
double scale = 1, double delta = 0,
|
||||
int borderType = BORDER_DEFAULT,
|
||||
const Scalar& borderValue = Scalar(0));
|
||||
|
||||
/** @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
|
||||
Canny algorithm. The smallest value between threshold1 and threshold2 is used for edge linking. The
|
||||
largest value is used to find initial segments of strong edges. See
|
||||
<http://en.wikipedia.org/wiki/Canny_edge_detector>
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.filters.canny"
|
||||
|
||||
@param image 8-bit input image.
|
||||
@param threshold1 first threshold for the hysteresis procedure.
|
||||
@param threshold2 second threshold for the hysteresis procedure.
|
||||
@param apertureSize aperture size for the Sobel operator.
|
||||
@param L2gradient a flag, indicating whether a more accurate \f$L_2\f$ norm
|
||||
\f$=\sqrt{(dI/dx)^2 + (dI/dy)^2}\f$ should be used to calculate the image gradient magnitude (
|
||||
L2gradient=true ), or whether the default \f$L_1\f$ norm \f$=|dI/dx|+|dI/dy|\f$ is enough (
|
||||
L2gradient=false ).
|
||||
*/
|
||||
GAPI_EXPORTS GMat Canny(const GMat& image, double threshold1, double threshold2,
|
||||
int apertureSize = 3, bool L2gradient = false);
|
||||
|
||||
/** @brief Equalizes the histogram of a grayscale image.
|
||||
|
||||
The function equalizes the histogram of the input image using the following algorithm:
|
||||
|
||||
- Calculate the histogram \f$H\f$ for src .
|
||||
- Normalize the histogram so that the sum of histogram bins is 255.
|
||||
- Compute the integral of the histogram:
|
||||
\f[H'_i = \sum _{0 \le j < i} H(j)\f]
|
||||
- Transform the image using \f$H'\f$ as a look-up table: \f$\texttt{dst}(x,y) = H'(\texttt{src}(x,y))\f$
|
||||
|
||||
The algorithm normalizes the brightness and increases the contrast of the image.
|
||||
@note The returned image is of the same size and type as input.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.equalizeHist"
|
||||
|
||||
@param src Source 8-bit single channel image.
|
||||
*/
|
||||
GAPI_EXPORTS GMat equalizeHist(const GMat& src);
|
||||
|
||||
//! @} gapi_filters
|
||||
|
||||
//! @addtogroup gapi_colorconvert
|
||||
//! @{
|
||||
/** @brief Converts an image from RGB color space to gray-scaled.
|
||||
The conventional ranges for R, G, and B channel values are 0 to 255.
|
||||
Resulting gray color value computed as
|
||||
\f[\texttt{dst} (I)= \texttt{0.299} * \texttt{src}(I).R + \texttt{0.587} * \texttt{src}(I).G + \texttt{0.114} * \texttt{src}(I).B \f]
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2gray"
|
||||
|
||||
@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC1.
|
||||
@sa RGB2YUV
|
||||
*/
|
||||
GAPI_EXPORTS GMat RGB2Gray(const GMat& src);
|
||||
|
||||
/** @overload
|
||||
Resulting gray color value computed as
|
||||
\f[\texttt{dst} (I)= \texttt{rY} * \texttt{src}(I).R + \texttt{gY} * \texttt{src}(I).G + \texttt{bY} * \texttt{src}(I).B \f]
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2graycustom"
|
||||
|
||||
@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC1.
|
||||
@param rY float multiplier for R channel.
|
||||
@param gY float multiplier for G channel.
|
||||
@param bY float multiplier for B channel.
|
||||
@sa RGB2YUV
|
||||
*/
|
||||
GAPI_EXPORTS GMat RGB2Gray(const GMat& src, float rY, float gY, float bY);
|
||||
|
||||
/** @brief Converts an image from BGR color space to gray-scaled.
|
||||
The conventional ranges for B, G, and R channel values are 0 to 255.
|
||||
Resulting gray color value computed as
|
||||
\f[\texttt{dst} (I)= \texttt{0.114} * \texttt{src}(I).B + \texttt{0.587} * \texttt{src}(I).G + \texttt{0.299} * \texttt{src}(I).R \f]
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.colorconvert.bgr2gray"
|
||||
|
||||
@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC1.
|
||||
@sa BGR2LUV
|
||||
*/
|
||||
GAPI_EXPORTS GMat BGR2Gray(const GMat& src);
|
||||
|
||||
/** @brief Converts an image from RGB color space to YUV color space.
|
||||
|
||||
The function converts an input image from RGB color space to YUV.
|
||||
The conventional ranges for R, G, and B channel values are 0 to 255.
|
||||
|
||||
In case of linear transformations, the range does not matter. But in case of a non-linear
|
||||
transformation, an input RGB image should be normalized to the proper value range to get the correct
|
||||
results, like here, at RGB \f$\rightarrow\f$ Y\*u\*v\* transformation.
|
||||
Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2yuv"
|
||||
|
||||
@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
@sa YUV2RGB, RGB2Lab
|
||||
*/
|
||||
GAPI_EXPORTS GMat RGB2YUV(const GMat& src);
|
||||
|
||||
/** @brief Converts an image from BGR color space to LUV color space.
|
||||
|
||||
The function converts an input image from BGR color space to LUV.
|
||||
The conventional ranges for B, G, and R channel values are 0 to 255.
|
||||
|
||||
Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.colorconvert.bgr2luv"
|
||||
|
||||
@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
@sa RGB2Lab, RGB2LUV
|
||||
*/
|
||||
GAPI_EXPORTS GMat BGR2LUV(const GMat& src);
|
||||
|
||||
/** @brief Converts an image from LUV color space to BGR color space.
|
||||
|
||||
The function converts an input image from LUV color space to BGR.
|
||||
The conventional ranges for B, G, and R channel values are 0 to 255.
|
||||
|
||||
Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.colorconvert.luv2bgr"
|
||||
|
||||
@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
@sa BGR2LUV
|
||||
*/
|
||||
GAPI_EXPORTS GMat LUV2BGR(const GMat& src);
|
||||
|
||||
/** @brief Converts an image from YUV color space to BGR color space.
|
||||
|
||||
The function converts an input image from YUV color space to BGR.
|
||||
The conventional ranges for B, G, and R channel values are 0 to 255.
|
||||
|
||||
Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.colorconvert.yuv2bgr"
|
||||
|
||||
@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
@sa BGR2YUV
|
||||
*/
|
||||
GAPI_EXPORTS GMat YUV2BGR(const GMat& src);
|
||||
|
||||
/** @brief Converts an image from BGR color space to YUV color space.
|
||||
|
||||
The function converts an input image from BGR color space to YUV.
|
||||
The conventional ranges for B, G, and R channel values are 0 to 255.
|
||||
|
||||
Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.colorconvert.bgr2yuv"
|
||||
|
||||
@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
@sa YUV2BGR
|
||||
*/
|
||||
GAPI_EXPORTS GMat BGR2YUV(const GMat& src);
|
||||
|
||||
/** @brief Converts an image from RGB color space to Lab color space.
|
||||
|
||||
The function converts an input image from BGR color space to Lab.
|
||||
The conventional ranges for R, G, and B channel values are 0 to 255.
|
||||
|
||||
Output image must be 8-bit unsigned 3-channel image @ref CV_8UC1.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2lab"
|
||||
|
||||
@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC1.
|
||||
@sa RGB2YUV, RGB2LUV
|
||||
*/
|
||||
GAPI_EXPORTS GMat RGB2Lab(const GMat& src);
|
||||
|
||||
/** @brief Converts an image from YUV color space to RGB.
|
||||
The function converts an input image from YUV color space to RGB.
|
||||
The conventional ranges for Y, U, and V channel values are 0 to 255.
|
||||
|
||||
Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
|
||||
@note Function textual ID is "org.opencv.imgproc.colorconvert.yuv2rgb"
|
||||
|
||||
@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
|
||||
@sa RGB2Lab, RGB2YUV
|
||||
*/
|
||||
GAPI_EXPORTS GMat YUV2RGB(const GMat& src);
|
||||
|
||||
//! @} gapi_colorconvert
|
||||
} //namespace gapi
|
||||
} //namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_IMGPROC_HPP
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_OPENCV_INCLUDES_HPP
|
||||
#define OPENCV_GAPI_OPENCV_INCLUDES_HPP
|
||||
|
||||
#include <opencv2/core/mat.hpp>
|
||||
#include <opencv2/core/cvdef.h>
|
||||
#include <opencv2/core/types.hpp>
|
||||
#include <opencv2/core/base.hpp>
|
||||
|
||||
#endif // OPENCV_GAPI_OPENCV_INCLUDES_HPP
|
||||
@@ -0,0 +1,69 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_OPERATORS_HPP
|
||||
#define OPENCV_GAPI_OPERATORS_HPP
|
||||
|
||||
#include "opencv2/gapi/gmat.hpp"
|
||||
#include "opencv2/gapi/gscalar.hpp"
|
||||
|
||||
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);
|
||||
GAPI_EXPORTS cv::GMat operator+(const cv::GScalar& lhs, const cv::GMat& rhs);
|
||||
|
||||
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);
|
||||
GAPI_EXPORTS cv::GMat operator-(const cv::GScalar& lhs, const cv::GMat& rhs);
|
||||
|
||||
GAPI_EXPORTS cv::GMat operator*(const cv::GMat& lhs, float rhs);
|
||||
GAPI_EXPORTS cv::GMat operator*(float lhs, const cv::GMat& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator*(const cv::GMat& lhs, const cv::GScalar& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator*(const cv::GScalar& lhs, const cv::GMat& rhs);
|
||||
|
||||
GAPI_EXPORTS cv::GMat operator/(const cv::GMat& lhs, const cv::GScalar& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator/(const cv::GScalar& lhs, const cv::GMat& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator/(const cv::GMat& lhs, const cv::GMat& rhs);
|
||||
|
||||
GAPI_EXPORTS cv::GMat operator&(const cv::GMat& lhs, const cv::GMat& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator|(const cv::GMat& lhs, const cv::GMat& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator^(const cv::GMat& lhs, const cv::GMat& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator~(const cv::GMat& lhs);
|
||||
|
||||
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::GMat& lhs, const cv::GScalar& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator|(const cv::GMat& lhs, const cv::GScalar& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator^(const cv::GMat& lhs, const cv::GScalar& rhs);
|
||||
|
||||
GAPI_EXPORTS cv::GMat operator>(const cv::GMat& lhs, const cv::GMat& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator>=(const cv::GMat& lhs, const cv::GMat& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator<(const cv::GMat& lhs, const cv::GMat& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator<=(const cv::GMat& lhs, const cv::GMat& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator==(const cv::GMat& lhs, const cv::GMat& rhs);
|
||||
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);
|
||||
GAPI_EXPORTS cv::GMat operator>=(const cv::GMat& lhs, const cv::GScalar& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator<(const cv::GMat& lhs, const cv::GScalar& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator<=(const cv::GMat& lhs, const cv::GScalar& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator==(const cv::GMat& lhs, const cv::GScalar& rhs);
|
||||
GAPI_EXPORTS cv::GMat operator!=(const cv::GMat& lhs, const cv::GScalar& 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);
|
||||
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);
|
||||
|
||||
|
||||
|
||||
#endif // OPENCV_GAPI_OPERATORS_HPP
|
||||
@@ -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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_OWN_ASSERT_HPP
|
||||
#define OPENCV_GAPI_OWN_ASSERT_HPP
|
||||
|
||||
#if 0
|
||||
#include <opencv2/core/base.hpp>
|
||||
#define GAPI_Assert(expr) CV_Assert(expr)
|
||||
|
||||
#else
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include "opencv2/gapi/util/throw.hpp"
|
||||
|
||||
namespace detail
|
||||
{
|
||||
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";
|
||||
cv::util::throw_error(std::logic_error(ss.str()));
|
||||
}
|
||||
}
|
||||
|
||||
#define GAPI_Assert(expr) \
|
||||
{ if (!(expr)) ::detail::assert_abort(#expr, __LINE__, __FILE__, __func__); }
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
# define GAPI_DbgAssert(expr) GAPI_Assert(expr)
|
||||
#else
|
||||
# define GAPI_DbgAssert(expr)
|
||||
#endif
|
||||
|
||||
#endif // OPENCV_GAPI_OWN_ASSERT_HPP
|
||||
@@ -0,0 +1,47 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_OWN_CONVERT_HPP
|
||||
#define OPENCV_GAPI_OWN_CONVERT_HPP
|
||||
|
||||
#include <opencv2/core/types.hpp>
|
||||
#include <opencv2/core/mat.hpp>
|
||||
#include <opencv2/gapi/own/types.hpp>
|
||||
#include <opencv2/gapi/own/mat.hpp>
|
||||
#include "opencv2/gapi/own/scalar.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
inline cv::gapi::own::Mat to_own(Mat const& m) { return {m.rows, m.cols, m.type(), m.data, m.step};};
|
||||
cv::gapi::own::Mat to_own(Mat&&) = delete;
|
||||
|
||||
inline cv::gapi::own::Scalar to_own(const cv::Scalar& s) { return {s[0], s[1], s[2], s[3]}; };
|
||||
|
||||
inline cv::gapi::own::Size to_own (const Size& s) { return {s.width, s.height}; };
|
||||
|
||||
inline cv::gapi::own::Rect to_own (const Rect& r) { return {r.x, r.y, r.width, r.height}; };
|
||||
|
||||
|
||||
|
||||
namespace gapi
|
||||
{
|
||||
namespace own
|
||||
{
|
||||
inline cv::Mat to_ocv(Mat const& m) { return {m.rows, m.cols, m.type(), m.data, m.step};};
|
||||
cv::Mat to_ocv(Mat&&) = delete;
|
||||
|
||||
inline cv::Scalar to_ocv(const Scalar& s) { return {s[0], s[1], s[2], s[3]}; };
|
||||
|
||||
inline cv::Size to_ocv (const Size& s) { return cv::Size(s.width, s.height); };
|
||||
|
||||
inline cv::Rect to_ocv (const Rect& r) { return cv::Rect(r.x, r.y, r.width, r.height); };
|
||||
|
||||
} // namespace own
|
||||
} // namespace gapi
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_OWN_CONVERT_HPP
|
||||
@@ -0,0 +1,28 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_OWN_TYPES_HPP
|
||||
#define OPENCV_GAPI_OWN_TYPES_HPP
|
||||
|
||||
# if 0
|
||||
# include <opencv2/core/base.hpp>
|
||||
# define GAPI_EXPORTS CV_EXPORTS
|
||||
|
||||
# else
|
||||
# if defined _WIN32
|
||||
# define GAPI_EXPORTS __declspec(dllexport)
|
||||
# elif defined __GNUC__ && __GNUC__ >= 4
|
||||
# define GAPI_EXPORTS __attribute__ ((visibility ("default")))
|
||||
# endif
|
||||
|
||||
# ifndef GAPI_EXPORTS
|
||||
# define GAPI_EXPORTS
|
||||
# endif
|
||||
|
||||
# endif
|
||||
|
||||
#endif // OPENCV_GAPI_OWN_TYPES_HPP
|
||||
@@ -0,0 +1,142 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef INCLUDE_OPENCV2_GAPI_OWN_MAT_HPP
|
||||
#define INCLUDE_OPENCV2_GAPI_OWN_MAT_HPP
|
||||
|
||||
#include "opencv2/core/cvdef.h"
|
||||
#include "opencv2/gapi/own/types.hpp"
|
||||
#include <memory> //std::shared_ptr
|
||||
|
||||
namespace cv { namespace gapi { namespace own {
|
||||
namespace detail {
|
||||
inline size_t default_step(int type, int cols)
|
||||
{
|
||||
return CV_ELEM_SIZE(type) * cols;
|
||||
}
|
||||
//Matrix header, i.e. fields that are unique to each Mat object.
|
||||
//Devoted class is needed to implement custom behavior on move (erasing state of moved from object)
|
||||
struct MatHeader{
|
||||
enum { AUTO_STEP = 0};
|
||||
enum { TYPE_MASK = 0x00000FFF };
|
||||
|
||||
MatHeader() = default;
|
||||
|
||||
MatHeader(int _rows, int _cols, int type, void* _data, size_t _step)
|
||||
: flags((type & TYPE_MASK)), rows(_rows), cols(_cols), data((uchar*)_data), step(_step == AUTO_STEP ? detail::default_step(type, _cols) : _step)
|
||||
{}
|
||||
|
||||
MatHeader(const MatHeader& ) = default;
|
||||
MatHeader(MatHeader&& src) : MatHeader(src) // reuse copy constructor here
|
||||
{
|
||||
MatHeader empty; //give it a name to call copy(not move) assignment below
|
||||
src = empty;
|
||||
}
|
||||
MatHeader& operator=(const MatHeader& ) = default;
|
||||
MatHeader& operator=(MatHeader&& src)
|
||||
{
|
||||
*this = src; //calling a copy assignment here, not move one
|
||||
MatHeader empty; //give it a name to call copy(not move) assignment below
|
||||
src = empty;
|
||||
return *this;
|
||||
}
|
||||
/*! includes several bit-fields:
|
||||
- depth
|
||||
- number of channels
|
||||
*/
|
||||
int flags = 0;
|
||||
|
||||
//! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
|
||||
int rows = 0, cols = 0;
|
||||
//! pointer to the data
|
||||
uchar* data = nullptr;
|
||||
size_t step = 0;
|
||||
};
|
||||
}
|
||||
//concise version of cv::Mat suitable for GAPI needs (used when no dependence on OpenCV is required)
|
||||
class Mat : public detail::MatHeader{
|
||||
public:
|
||||
|
||||
Mat() = default;
|
||||
|
||||
/** @overload
|
||||
@param _rows Number of rows in a 2D array.
|
||||
@param _cols Number of columns in a 2D array.
|
||||
@param _type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or
|
||||
CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices.
|
||||
@param _data Pointer to the user data. Matrix constructors that take data and step parameters do not
|
||||
allocate matrix data. Instead, they just initialize the matrix header that points to the specified
|
||||
data, which means that no data is copied. This operation is very efficient and can be used to
|
||||
process external data using OpenCV functions. The external data is not automatically deallocated, so
|
||||
you should take care of it.
|
||||
@param _step Number of bytes each matrix row occupies. The value should include the padding bytes at
|
||||
the end of each row, if any. If the parameter is missing (set to AUTO_STEP ), no padding is assumed
|
||||
and the actual step is calculated as cols*elemSize(). See Mat::elemSize.
|
||||
*/
|
||||
Mat(int _rows, int _cols, int _type, void* _data, size_t _step = AUTO_STEP)
|
||||
: MatHeader (_rows, _cols, _type, _data, _step)
|
||||
{}
|
||||
|
||||
Mat(Mat const& src) = default;
|
||||
Mat(Mat&& src) = default;
|
||||
|
||||
Mat& operator=(Mat const& src) = default;
|
||||
Mat& operator=(Mat&& src) = default;
|
||||
|
||||
/** @brief Returns the type of a matrix element.
|
||||
|
||||
The method returns a matrix element type. This is an identifier compatible with the CvMat type
|
||||
system, like CV_16SC3 or 16-bit signed 3-channel array, and so on.
|
||||
*/
|
||||
int type() const {return CV_MAT_TYPE(flags);}
|
||||
|
||||
/** @brief Returns the depth of a matrix element.
|
||||
|
||||
The method returns the identifier of the matrix element depth (the type of each individual channel).
|
||||
For example, for a 16-bit signed element array, the method returns CV_16S . A complete list of
|
||||
matrix types contains the following values:
|
||||
- CV_8U - 8-bit unsigned integers ( 0..255 )
|
||||
- CV_8S - 8-bit signed integers ( -128..127 )
|
||||
- CV_16U - 16-bit unsigned integers ( 0..65535 )
|
||||
- CV_16S - 16-bit signed integers ( -32768..32767 )
|
||||
- CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
|
||||
- CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
|
||||
- CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
|
||||
*/
|
||||
int depth() const {return CV_MAT_DEPTH(flags);}
|
||||
|
||||
/** @brief Returns the number of matrix channels.
|
||||
|
||||
The method returns the number of matrix channels.
|
||||
*/
|
||||
int channels() const {return CV_MAT_CN(flags);}
|
||||
|
||||
/** @overload
|
||||
@param _size Alternative new matrix size specification: Size(cols, rows)
|
||||
@param _type New matrix type.
|
||||
*/
|
||||
void create(cv::gapi::own::Size _size, int _type)
|
||||
{
|
||||
if (_size != cv::gapi::own::Size{cols, rows} )
|
||||
{
|
||||
Mat tmp{_size.height, _size.width, _type, nullptr};
|
||||
tmp.memory.reset(new uchar[ tmp.step * tmp.rows], [](uchar * p){delete[] p;});
|
||||
tmp.data = tmp.memory.get();
|
||||
|
||||
*this = std::move(tmp);
|
||||
}
|
||||
}
|
||||
private:
|
||||
//actual memory allocated for storage, or nullptr if object is non owning view to over memory
|
||||
std::shared_ptr<uchar> memory;
|
||||
};
|
||||
|
||||
} //namespace own
|
||||
} //namespace gapi
|
||||
} //namespace cv
|
||||
|
||||
#endif /* INCLUDE_OPENCV2_GAPI_OWN_MAT_HPP */
|
||||
@@ -0,0 +1,45 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GAPI_OWN_SCALAR_HPP
|
||||
#define OPENCV_GAPI_GAPI_OWN_SCALAR_HPP
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace gapi
|
||||
{
|
||||
namespace own
|
||||
{
|
||||
|
||||
class CV_EXPORTS Scalar
|
||||
{
|
||||
public:
|
||||
Scalar() = default;
|
||||
explicit Scalar(double v0) { val[0] = v0; };
|
||||
Scalar(double v0, double v1, double v2 = 0, double v3 = 0)
|
||||
: val{v0, v1, v2, v3}
|
||||
{
|
||||
}
|
||||
|
||||
const double& operator[](int i) const { return val[i]; }
|
||||
double& operator[](int i) { return val[i]; }
|
||||
|
||||
static Scalar all(double v0) { return Scalar(v0, v0, v0, v0); }
|
||||
|
||||
double val[4] = {0};
|
||||
};
|
||||
|
||||
inline bool operator==(const Scalar& lhs, const Scalar& rhs)
|
||||
{
|
||||
return std::equal(std::begin(lhs.val), std::end(lhs.val), std::begin(rhs.val));
|
||||
}
|
||||
|
||||
} // namespace own
|
||||
} // namespace gapi
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GAPI_OWN_SCALAR_HPP
|
||||
@@ -0,0 +1,137 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_TYPES_HPP
|
||||
#define OPENCV_GAPI_TYPES_HPP
|
||||
|
||||
#include <algorithm> // std::max, std::min
|
||||
|
||||
#include "opencv2/core/base.hpp" //for CV_DbgAssert
|
||||
#include "opencv2/gapi/own/assert.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace gapi
|
||||
{
|
||||
namespace own
|
||||
{
|
||||
|
||||
class Point
|
||||
{
|
||||
public:
|
||||
Point() = default;
|
||||
Point(int _x, int _y) : x(_x), y(_y) {};
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
};
|
||||
|
||||
class Rect
|
||||
{
|
||||
public:
|
||||
Rect() = default;
|
||||
Rect(int _x, int _y, int _width, int _height) : x(_x), y(_y), width(_width), height(_height) {};
|
||||
#if 1
|
||||
Rect(const cv::Rect& other) : x(other.x), y(other.y), width(other.width), height(other.height) {};
|
||||
inline Rect& operator=(const cv::Rect& other)
|
||||
{
|
||||
x = other.x;
|
||||
y = other.x;
|
||||
width = other.width;
|
||||
height = other.height;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
int x = 0; //!< x coordinate of the top-left corner
|
||||
int y = 0; //!< y coordinate of the top-left corner
|
||||
int width = 0; //!< width of the rectangle
|
||||
int height = 0; //!< height of the rectangle
|
||||
};
|
||||
|
||||
inline bool operator==(const Rect& lhs, const Rect& rhs)
|
||||
{
|
||||
return lhs.x == rhs.x && lhs.y == rhs.y && lhs.width == rhs.width && lhs.height == rhs.height;
|
||||
}
|
||||
|
||||
inline bool operator!=(const Rect& lhs, const Rect& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline Rect& operator&=(Rect& lhs, const Rect& rhs)
|
||||
{
|
||||
int x1 = std::max(lhs.x, rhs.x);
|
||||
int y1 = std::max(lhs.y, rhs.y);
|
||||
lhs.width = std::min(lhs.x + lhs.width, rhs.x + rhs.width) - x1;
|
||||
lhs.height = std::min(lhs.y + lhs.height, rhs.y + rhs.height) - y1;
|
||||
lhs.x = x1;
|
||||
lhs.y = y1;
|
||||
if( lhs.width <= 0 || lhs.height <= 0 )
|
||||
lhs = Rect();
|
||||
return lhs;
|
||||
}
|
||||
|
||||
inline const Rect operator&(const Rect& lhs, const Rect& rhs)
|
||||
{
|
||||
Rect result = lhs;
|
||||
return result &= rhs;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& o, const Rect& rect)
|
||||
{
|
||||
return o << "[" << rect.width << " x " << rect.height << " from (" << rect.x << ", " << rect.y << ")]";
|
||||
}
|
||||
|
||||
class Size
|
||||
{
|
||||
public:
|
||||
Size() = default;
|
||||
Size(int _width, int _height) : width(_width), height(_height) {};
|
||||
#if 1
|
||||
Size(const cv::Size& other) : width(other.width), height(other.height) {};
|
||||
inline Size& operator=(const cv::Size& rhs)
|
||||
{
|
||||
width = rhs.width;
|
||||
height = rhs.height;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
};
|
||||
|
||||
inline Size& operator+=(Size& lhs, const Size& rhs)
|
||||
{
|
||||
lhs.width += rhs.width;
|
||||
lhs.height += rhs.height;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
inline bool operator==(const Size& lhs, const Size& rhs)
|
||||
{
|
||||
return lhs.width == rhs.width && lhs.height == rhs.height;
|
||||
}
|
||||
|
||||
inline bool operator!=(const Size& lhs, const Size& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& o, const Size& s)
|
||||
{
|
||||
o << "[" << s.width << " x " << s.height << "]";
|
||||
return o;
|
||||
}
|
||||
|
||||
} // namespace own
|
||||
} // namespace gapi
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_TYPES_HPP
|
||||
@@ -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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_UTIL_ANY_HPP
|
||||
#define OPENCV_GAPI_UTIL_ANY_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
|
||||
#include "opencv2/gapi/util/throw.hpp"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// disable MSVC warning on "multiple copy constructors specified"
|
||||
# pragma warning(disable: 4521)
|
||||
#endif
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
namespace internal
|
||||
{
|
||||
template <class T, class Source>
|
||||
T down_cast(Source operand)
|
||||
{
|
||||
#if defined(__GXX_RTTI) || defined(_CPPRTTI)
|
||||
return dynamic_cast<T>(operand);
|
||||
#else
|
||||
#warning used static cast instead of dynamic because RTTI is disabled
|
||||
return static_cast<T>(operand);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
namespace util
|
||||
{
|
||||
class bad_any_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
virtual const char* what() const noexcept override
|
||||
{
|
||||
return "Bad any cast";
|
||||
}
|
||||
};
|
||||
|
||||
//modeled against C++17 std::any
|
||||
|
||||
class any
|
||||
{
|
||||
private:
|
||||
struct holder;
|
||||
using holder_ptr = std::unique_ptr<holder>;
|
||||
struct holder
|
||||
{
|
||||
virtual holder_ptr clone() = 0;
|
||||
virtual ~holder() = default;
|
||||
};
|
||||
|
||||
template <typename value_t>
|
||||
struct holder_impl : holder
|
||||
{
|
||||
value_t v;
|
||||
template<typename arg_t>
|
||||
holder_impl(arg_t&& a) : v(std::forward<arg_t>(a)) {}
|
||||
holder_ptr clone() override { return holder_ptr(new holder_impl (v));}
|
||||
};
|
||||
|
||||
holder_ptr hldr;
|
||||
public:
|
||||
template<class value_t>
|
||||
any(value_t&& arg) : hldr(new holder_impl<typename std::decay<value_t>::type>( std::forward<value_t>(arg))) {}
|
||||
|
||||
any(any const& src) : hldr( src.hldr ? src.hldr->clone() : nullptr) {}
|
||||
//simple hack in order not to write enable_if<not any> for the template constructor
|
||||
any(any & src) : any (const_cast<any const&>(src)) {}
|
||||
|
||||
any() = default;
|
||||
any(any&& ) = default;
|
||||
|
||||
any& operator=(any&&) = default;
|
||||
|
||||
any& operator=(any const& src)
|
||||
{
|
||||
any copy(src);
|
||||
swap(*this, copy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class value_t>
|
||||
friend value_t* any_cast(any* operand);
|
||||
|
||||
template<class value_t>
|
||||
friend const value_t* any_cast(const any* operand);
|
||||
|
||||
friend void swap(any & lhs, any& rhs)
|
||||
{
|
||||
swap(lhs.hldr, rhs.hldr);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<class value_t>
|
||||
value_t* any_cast(any* operand)
|
||||
{
|
||||
auto casted = internal::down_cast<any::holder_impl<typename std::decay<value_t>::type> *>(operand->hldr.get());
|
||||
if (casted){
|
||||
return & (casted->v);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<class value_t>
|
||||
const value_t* any_cast(const any* operand)
|
||||
{
|
||||
auto casted = internal::down_cast<any::holder_impl<typename std::decay<value_t>::type> *>(operand->hldr.get());
|
||||
if (casted){
|
||||
return & (casted->v);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<class value_t>
|
||||
value_t& any_cast(any& operand)
|
||||
{
|
||||
auto ptr = any_cast<value_t>(&operand);
|
||||
if (ptr)
|
||||
{
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
throw_error(bad_any_cast());
|
||||
}
|
||||
|
||||
|
||||
template<class value_t>
|
||||
const value_t& any_cast(const any& operand)
|
||||
{
|
||||
auto ptr = any_cast<value_t>(&operand);
|
||||
if (ptr)
|
||||
{
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
throw_error(bad_any_cast());
|
||||
}
|
||||
} // namespace util
|
||||
} // namespace cv
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Enable "multiple copy constructors specified" back
|
||||
# pragma warning(default: 4521)
|
||||
#endif
|
||||
|
||||
#endif // OPENCV_GAPI_UTIL_ANY_HPP
|
||||
@@ -0,0 +1,21 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
#ifndef OPENCV_GAPI_UTIL_COMPILER_HINTS_HPP
|
||||
#define OPENCV_GAPI_UTIL_COMPILER_HINTS_HPP
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
//! Utility template function to prevent "unused" warnings by various compilers.
|
||||
template<typename T> void suppress_unused_warning( const T& ) {}
|
||||
} // namespace util
|
||||
} // namespace cv
|
||||
|
||||
#define UNUSED(x) cv::util::suppress_unused_warning(x)
|
||||
|
||||
#endif /* OPENCV_GAPI_UTIL_COMPILER_HINTS_HPP */
|
||||
@@ -0,0 +1,178 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_UTIL_OPTIONAL_HPP
|
||||
#define OPENCV_GAPI_UTIL_OPTIONAL_HPP
|
||||
|
||||
#include "opencv2/gapi/util/variant.hpp"
|
||||
|
||||
// A poor man's `optional` implementation, incompletely modeled against C++17 spec.
|
||||
namespace cv
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
class bad_optional_access: public std::exception
|
||||
{
|
||||
public:
|
||||
virtual const char *what() const noexcept override
|
||||
{
|
||||
return "Bad optional access";
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: nullopt_t
|
||||
|
||||
// Interface ///////////////////////////////////////////////////////////////
|
||||
template<typename T> class optional
|
||||
{
|
||||
public:
|
||||
// Constructors
|
||||
// NB.: there were issues with Clang 3.8 when =default() was used
|
||||
// instead {}
|
||||
optional() {};
|
||||
optional(const optional&) = default;
|
||||
explicit optional(T &&value) noexcept;
|
||||
explicit optional(const T &value) noexcept;
|
||||
optional(optional &&) noexcept;
|
||||
// TODO: optional(nullopt_t) noexcept;
|
||||
// TODO: optional(const optional<U> &)
|
||||
// TODO: optional(optional<U> &&)
|
||||
// TODO: optional(Args&&...)
|
||||
// TODO: optional(initializer_list<U>)
|
||||
// TODO: optional(U&& value);
|
||||
|
||||
// Assignment
|
||||
optional& operator=(const optional& rhs) = default;
|
||||
optional& operator=(optional&& rhs);
|
||||
|
||||
// Observers
|
||||
T* operator-> ();
|
||||
const T* operator-> () const;
|
||||
T& operator* ();
|
||||
const T& operator* () const;
|
||||
// TODO: && versions
|
||||
|
||||
operator bool() const noexcept;
|
||||
bool has_value() const noexcept;
|
||||
|
||||
T& value();
|
||||
const T& value() const;
|
||||
// TODO: && versions
|
||||
|
||||
template<class U>
|
||||
T value_or(U &&default_value) const;
|
||||
|
||||
void swap(optional &other) noexcept;
|
||||
void reset() noexcept;
|
||||
// TODO: emplace
|
||||
|
||||
// TODO: operator==, !=, <, <=, >, >=
|
||||
|
||||
private:
|
||||
struct nothing {};
|
||||
util::variant<nothing, T> m_holder;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
optional<typename std::decay<T>::type> make_optional(T&& value);
|
||||
|
||||
// TODO: Args... and initializer_list versions
|
||||
|
||||
// Implementation //////////////////////////////////////////////////////////
|
||||
template<class T> optional<T>::optional(T &&v) noexcept
|
||||
: m_holder(v)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T> optional<T>::optional(const T &v) noexcept
|
||||
: m_holder(v)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T> optional<T>::optional(optional&& rhs) noexcept
|
||||
: m_holder(std::move(rhs.m_holder))
|
||||
{
|
||||
rhs.reset();
|
||||
}
|
||||
|
||||
template<class T> optional<T>& optional<T>::operator=(optional&& rhs)
|
||||
{
|
||||
m_holder = std::move(rhs.m_holder);
|
||||
rhs.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T> T* optional<T>::operator-> ()
|
||||
{
|
||||
return & *(*this);
|
||||
}
|
||||
|
||||
template<class T> const T* optional<T>::operator-> () const
|
||||
{
|
||||
return & *(*this);
|
||||
}
|
||||
|
||||
template<class T> T& optional<T>::operator* ()
|
||||
{
|
||||
return this->value();
|
||||
}
|
||||
|
||||
template<class T> const T& optional<T>::operator* () const
|
||||
{
|
||||
return this->value();
|
||||
}
|
||||
|
||||
template<class T> optional<T>::operator bool() const noexcept
|
||||
{
|
||||
return this->has_value();
|
||||
}
|
||||
|
||||
template<class T> bool optional<T>::has_value() const noexcept
|
||||
{
|
||||
return util::holds_alternative<T>(m_holder);
|
||||
}
|
||||
|
||||
template<class T> T& optional<T>::value()
|
||||
{
|
||||
if (!this->has_value())
|
||||
throw_error(bad_optional_access());
|
||||
return util::get<T>(m_holder);
|
||||
}
|
||||
|
||||
template<class T> const T& optional<T>::value() const
|
||||
{
|
||||
if (!this->has_value())
|
||||
throw_error(bad_optional_access());
|
||||
return util::get<T>(m_holder);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<class U> T optional<T>::value_or(U &&default_value) const
|
||||
{
|
||||
return (this->has_value() ? this->value() : T(default_value));
|
||||
}
|
||||
|
||||
template<class T> void optional<T>::swap(optional<T> &other) noexcept
|
||||
{
|
||||
m_holder.swap(other.m_holder);
|
||||
}
|
||||
|
||||
template<class T> void optional<T>::reset() noexcept
|
||||
{
|
||||
if (this->has_value())
|
||||
m_holder = nothing{};
|
||||
}
|
||||
|
||||
template<class T>
|
||||
optional<typename std::decay<T>::type> make_optional(T&& value)
|
||||
{
|
||||
return optional<typename std::decay<T>::type>(std::forward<T>(value));
|
||||
}
|
||||
} // namespace util
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_UTIL_OPTIONAL_HPP
|
||||
@@ -0,0 +1,36 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_UTIL_THROW_HPP
|
||||
#define OPENCV_GAPI_UTIL_THROW_HPP
|
||||
|
||||
#include <utility> // std::forward
|
||||
|
||||
#if !defined(__EXCEPTIONS)
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
template <class ExceptionType>
|
||||
[[noreturn]] void throw_error(ExceptionType &&e)
|
||||
{
|
||||
#if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
|
||||
throw std::forward<ExceptionType>(e);
|
||||
#else
|
||||
fprintf(stderr, "An exception thrown! %s\n" , e.what());
|
||||
fflush(stderr);
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
} // namespace util
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_UTIL_THROW_HPP
|
||||
@@ -0,0 +1,92 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_UTIL_HPP
|
||||
#define OPENCV_GAPI_UTIL_HPP
|
||||
|
||||
#include <utility> // std::tuple
|
||||
|
||||
// \cond HIDDEN_SYMBOLS
|
||||
// This header file contains some generic utility functions which are
|
||||
// used in other G-API Public API headers.
|
||||
//
|
||||
// PLEASE don't put any stuff here if it is NOT used in public API headers!
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// Recursive integer sequence type, useful for enumerating elements of
|
||||
// template parameter packs.
|
||||
template<int... I> struct Seq { using next = Seq<I..., sizeof...(I)>; };
|
||||
template<int Sz> struct MkSeq { using type = typename MkSeq<Sz-1>::type::next; };
|
||||
template<> struct MkSeq<0>{ using type = Seq<>; };
|
||||
|
||||
// Checks if elements of variadic template satisfy the given Predicate.
|
||||
// Implemented via tuple, with an interface to accept plain type lists
|
||||
template<template<class> class, typename, typename...> struct all_satisfy;
|
||||
|
||||
template<template<class> class F, typename T, typename... Ts>
|
||||
struct all_satisfy<F, std::tuple<T, Ts...> >
|
||||
{
|
||||
static const constexpr bool value = F<T>::value
|
||||
&& all_satisfy<F, std::tuple<Ts...> >::value;
|
||||
};
|
||||
template<template<class> class F, typename T>
|
||||
struct all_satisfy<F, std::tuple<T> >
|
||||
{
|
||||
static const constexpr bool value = F<T>::value;
|
||||
};
|
||||
|
||||
template<template<class> class F, typename T, typename... Ts>
|
||||
struct all_satisfy: public all_satisfy<F, std::tuple<T, Ts...> > {};
|
||||
|
||||
// Permute given tuple type C with given integer sequence II
|
||||
// Sequence may be less than tuple C size.
|
||||
template<class, class> struct permute_tuple;
|
||||
|
||||
template<class C, int... IIs>
|
||||
struct permute_tuple<C, Seq<IIs...> >
|
||||
{
|
||||
using type = std::tuple< typename std::tuple_element<IIs, C>::type... >;
|
||||
};
|
||||
|
||||
// Given T..., generates a type sequence of sizeof...(T)-1 elements
|
||||
// which is T... without its last element
|
||||
// Implemented via tuple, with an interface to accept plain type lists
|
||||
template<typename T, typename... Ts> struct all_but_last;
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
struct all_but_last<std::tuple<T, Ts...> >
|
||||
{
|
||||
using C = std::tuple<T, Ts...>;
|
||||
using S = typename MkSeq<std::tuple_size<C>::value - 1>::type;
|
||||
using type = typename permute_tuple<C, S>::type;
|
||||
};
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
struct all_but_last: public all_but_last<std::tuple<T, Ts...> > {};
|
||||
|
||||
template<typename... Ts>
|
||||
using all_but_last_t = typename all_but_last<Ts...>::type;
|
||||
|
||||
// NB.: This is here because there's no constexpr std::max in C++11
|
||||
template<std::size_t S0, std::size_t... SS> struct max_of_t
|
||||
{
|
||||
static constexpr const std::size_t rest = max_of_t<SS...>::value;
|
||||
static constexpr const std::size_t value = rest > S0 ? rest : S0;
|
||||
};
|
||||
template<std::size_t S> struct max_of_t<S>
|
||||
{
|
||||
static constexpr const std::size_t value = S;
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace cv
|
||||
|
||||
// \endcond
|
||||
|
||||
#endif // OPENCV_GAPI_UTIL_HPP
|
||||
@@ -0,0 +1,377 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_UTIL_VARIANT_HPP
|
||||
#define OPENCV_GAPI_UTIL_VARIANT_HPP
|
||||
|
||||
#include <array>
|
||||
#include <type_traits>
|
||||
|
||||
#include "opencv2/gapi/util/throw.hpp"
|
||||
#include "opencv2/gapi/util/util.hpp" // max_of_t
|
||||
|
||||
// A poor man's `variant` implementation, incompletely modeled against C++17 spec.
|
||||
namespace cv
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<std::size_t I, typename Target, typename First, typename... Remaining>
|
||||
struct type_list_index_helper
|
||||
{
|
||||
static const constexpr bool is_same = std::is_same<Target, First>::value;
|
||||
static const constexpr std::size_t value =
|
||||
std::conditional<is_same, std::integral_constant<std::size_t, I>, type_list_index_helper<I + 1, Target, Remaining...>>::type::value;
|
||||
};
|
||||
|
||||
template<std::size_t I, typename Target, typename First>
|
||||
struct type_list_index_helper<I, Target, First>
|
||||
{
|
||||
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>
|
||||
struct type_list_index
|
||||
{
|
||||
static const constexpr std::size_t value = detail::type_list_index_helper<0, Target, Types...>::value;
|
||||
};
|
||||
|
||||
class bad_variant_access: public std::exception
|
||||
{
|
||||
public:
|
||||
virtual const char *what() const noexcept override
|
||||
{
|
||||
return "Bad variant access";
|
||||
}
|
||||
};
|
||||
|
||||
// Interface ///////////////////////////////////////////////////////////////
|
||||
struct monostate {};
|
||||
inline bool operator==(const util::monostate&, const util::monostate&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename... Ts> // FIXME: no references, arrays, and void
|
||||
class variant
|
||||
{
|
||||
// FIXME: Replace with std::aligned_union after gcc4.8 support is dropped
|
||||
static constexpr const std::size_t S = cv::detail::max_of_t<sizeof(Ts)...>::value;
|
||||
static constexpr const std::size_t A = cv::detail::max_of_t<alignof(Ts)...>::value;
|
||||
using Memory = typename std::aligned_storage<S, A>::type[1];
|
||||
|
||||
template<typename T> struct cctr_h {
|
||||
static void help(Memory memory, const Memory from) {
|
||||
new (memory) T(*reinterpret_cast<const T*>(from));
|
||||
}
|
||||
};
|
||||
|
||||
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)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct copy_h {
|
||||
static void help(Memory to, const Memory from) {
|
||||
*reinterpret_cast<T*>(to) = *reinterpret_cast<const T*>(from);
|
||||
}
|
||||
};
|
||||
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct swap_h {
|
||||
static void help(Memory to, Memory from) {
|
||||
std::swap(*reinterpret_cast<T*>(to), *reinterpret_cast<T*>(from));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct dtor_h {
|
||||
static void help(Memory memory) {
|
||||
(void) memory; // MSCV warning
|
||||
reinterpret_cast<T*>(memory)->~T();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct equal_h {
|
||||
static bool help(const Memory lhs, const Memory rhs) {
|
||||
const T& t_lhs = *reinterpret_cast<const T*>(lhs);
|
||||
const T& t_rhs = *reinterpret_cast<const T*>(rhs);
|
||||
return t_lhs == t_rhs;
|
||||
}
|
||||
};
|
||||
|
||||
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 (*Swap) (Memory, Memory); // Swap
|
||||
typedef void (*Dtor) (Memory); // Destructor
|
||||
|
||||
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 {{(©_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)...}};}
|
||||
|
||||
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... Us> friend bool operator==(const variant<Us...> &lhs,
|
||||
const variant<Us...> &rhs);
|
||||
Memory memory;
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
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
|
||||
// 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);
|
||||
// template<class T, class... Args> explicit variant(Args&&... args);
|
||||
// FIXME: other constructors
|
||||
|
||||
// Destructor
|
||||
~variant();
|
||||
|
||||
// Assignment
|
||||
variant& operator=(const variant& rhs);
|
||||
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;
|
||||
|
||||
// Observers
|
||||
std::size_t index() const noexcept;
|
||||
// FIXME: valueless_by_exception()
|
||||
|
||||
// Modifiers
|
||||
// FIXME: emplace()
|
||||
void swap(variant &rhs) noexcept;
|
||||
|
||||
// Non-C++17x!
|
||||
template<typename T> static constexpr std::size_t index_of();
|
||||
};
|
||||
|
||||
// FIMXE: visit
|
||||
|
||||
template<typename T, typename... Types>
|
||||
T& get(util::variant<Types...> &v);
|
||||
|
||||
template<typename T, typename... Types>
|
||||
const T& get(const util::variant<Types...> &v);
|
||||
|
||||
template<typename T, typename... Types>
|
||||
bool holds_alternative(const util::variant<Types...> &v) noexcept;
|
||||
|
||||
// FIXME: T&&, const TT&& versions.
|
||||
|
||||
// Implementation //////////////////////////////////////////////////////////
|
||||
template<typename... Ts>
|
||||
variant<Ts...>::variant() noexcept
|
||||
{
|
||||
typedef typename std::tuple_element<0, std::tuple<Ts...> >::type TFirst;
|
||||
new (memory) TFirst();
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
variant<Ts...>::variant(const variant &other)
|
||||
: m_index(other.m_index)
|
||||
{
|
||||
(cctrs()[m_index])(memory, other.memory);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
variant<Ts...>::variant(variant &&other) noexcept
|
||||
: m_index(other.m_index)
|
||||
{
|
||||
(mctrs()[m_index])(memory, other.memory);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
template<class T>
|
||||
variant<Ts...>::variant(const T& t)
|
||||
: m_index(util::type_list_index<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);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
variant<Ts...>::~variant()
|
||||
{
|
||||
(dtors()[m_index])(memory);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
variant<Ts...>& variant<Ts...>::operator=(const variant<Ts...> &rhs)
|
||||
{
|
||||
if (m_index != rhs.m_index)
|
||||
{
|
||||
(dtors()[ m_index])(memory);
|
||||
(cctrs()[rhs.m_index])(memory, rhs.memory);
|
||||
m_index = rhs.m_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
(cpyrs()[rhs.m_index])(memory, rhs.memory);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
variant<Ts...>& variant<Ts...>::operator=(variant<Ts...> &&rhs) noexcept
|
||||
{
|
||||
if (m_index != rhs.m_index)
|
||||
{
|
||||
(dtors()[ m_index])(memory);
|
||||
(mctrs()[rhs.m_index])(memory, rhs.memory);
|
||||
m_index = rhs.m_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
(mvers()[rhs.m_index])(memory, rhs.memory);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
template<class T> typename detail::are_different<variant<Ts...>, T, variant<Ts...>&>
|
||||
::type variant<Ts...>::operator=(T&& t) noexcept
|
||||
{
|
||||
// FIXME: No version with implicit type conversion available!
|
||||
static const constexpr std::size_t t_index =
|
||||
util::type_list_index<T, Ts...>::value;
|
||||
|
||||
if (t_index == m_index)
|
||||
{
|
||||
util::get<T>(*this) = std::move(t);
|
||||
return *this;
|
||||
}
|
||||
else return (*this = variant(std::move(t)));
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::size_t util::variant<Ts...>::index() const noexcept
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
void variant<Ts...>::swap(variant<Ts...> &rhs) noexcept
|
||||
{
|
||||
if (m_index == rhs.index())
|
||||
{
|
||||
(swprs()[m_index](memory, rhs.memory));
|
||||
}
|
||||
else
|
||||
{
|
||||
variant<Ts...> tmp(std::move(*this));
|
||||
*this = std::move(rhs);
|
||||
rhs = std::move(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
template<typename T>
|
||||
constexpr std::size_t variant<Ts...>::index_of()
|
||||
{
|
||||
return util::type_list_index<T, Ts...>::value; // FIXME: tests!
|
||||
}
|
||||
|
||||
template<typename T, typename... Types>
|
||||
T& get(util::variant<Types...> &v)
|
||||
{
|
||||
const constexpr std::size_t t_index =
|
||||
util::type_list_index<T, Types...>::value;
|
||||
|
||||
if (v.index() == t_index)
|
||||
return reinterpret_cast<T&>(v.memory);
|
||||
else
|
||||
throw_error(bad_variant_access());
|
||||
}
|
||||
|
||||
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 reinterpret_cast<const T&>(v.memory);
|
||||
else
|
||||
throw_error(bad_variant_access());
|
||||
}
|
||||
|
||||
template<typename T, typename... Types>
|
||||
bool holds_alternative(const util::variant<Types...> &v) noexcept
|
||||
{
|
||||
return v.index() == util::variant<Types...>::template index_of<T>();
|
||||
}
|
||||
|
||||
template<typename... Us> bool operator==(const variant<Us...> &lhs,
|
||||
const variant<Us...> &rhs)
|
||||
{
|
||||
using V = variant<Us...>;
|
||||
|
||||
// Instantiate table only here since it requires operator== for <Us...>
|
||||
// <Us...> should have operator== only if this one is used, not in general
|
||||
static const std::array<typename V::Equal, sizeof...(Us)> eqs = {
|
||||
{(&V::template equal_h<Us>::help)...}
|
||||
};
|
||||
if (lhs.index() != rhs.index())
|
||||
return false;
|
||||
return (eqs[lhs.index()])(lhs.memory, rhs.memory);
|
||||
}
|
||||
|
||||
template<typename... Us> bool operator!=(const variant<Us...> &lhs,
|
||||
const variant<Us...> &rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
} // namespace cv
|
||||
} // namespace util
|
||||
|
||||
#endif // OPENCV_GAPI_UTIL_VARIANT_HPP
|
||||
Reference in New Issue
Block a user