mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 15:53:03 +04:00
Merge pull request #13008 from dbudniko:dbudniko/gpu_opencl_backend
G-API GPU-OpenCL backend (#13008) * gpu/ocl backend core * accuracy tests added and adjusted + license headers * GPU perf. tests added; almost all adjusted to pass * all tests adjusted and passed - ready for pull request * missing license headers * fix warning (workaround RGB2Gray) * fix c++ magic * precompiled header * white spaces * try to fix warning and blur test * try to fix Blur perf tests * more alignments with the latest cpu backend * more gapi tests refactoring + 1 more UB issue fix + more informative tolerance exceed reports * white space fix * try workaround for SumTest * GAPI_EXPORTS instead CV_EXPORTS
This commit is contained in:
committed by
Alexander Alekhin
parent
ebc8015638
commit
5087ff0814
@@ -45,18 +45,21 @@ namespace magazine {
|
||||
};
|
||||
|
||||
} // namespace magazine
|
||||
|
||||
#if !defined(GAPI_STANDALONE)
|
||||
using Mag = magazine::Class<cv::gapi::own::Mat, cv::UMat, cv::gapi::own::Scalar, cv::detail::VectorRef>;
|
||||
#else
|
||||
using Mag = magazine::Class<cv::gapi::own::Mat, cv::gapi::own::Scalar, cv::detail::VectorRef>;
|
||||
#endif
|
||||
|
||||
namespace magazine
|
||||
{
|
||||
void bindInArg (Mag& mag, const RcDesc &rc, const GRunArg &arg);
|
||||
void bindOutArg(Mag& mag, const RcDesc &rc, const GRunArgP &arg);
|
||||
void bindInArg (Mag& mag, const RcDesc &rc, const GRunArg &arg, bool is_umat = false);
|
||||
void bindOutArg(Mag& mag, const RcDesc &rc, const GRunArgP &arg, bool is_umat = false);
|
||||
|
||||
void resetInternalData(Mag& mag, const Data &d);
|
||||
cv::GRunArg getArg (const Mag& mag, const RcDesc &ref);
|
||||
cv::GRunArgP getObjPtr ( Mag& mag, const RcDesc &rc);
|
||||
void writeBack (const Mag& mag, const RcDesc &rc, GRunArgP &g_arg);
|
||||
cv::GRunArgP getObjPtr ( Mag& mag, const RcDesc &rc, bool is_umat = false);
|
||||
void writeBack (const Mag& mag, const RcDesc &rc, GRunArgP &g_arg, bool is_umat = false);
|
||||
} // namespace magazine
|
||||
|
||||
namespace detail
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
// 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
|
||||
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <ade/util/algorithm.hpp>
|
||||
|
||||
#include <ade/util/range.hpp>
|
||||
#include <ade/util/zip_range.hpp>
|
||||
#include <ade/util/chain_range.hpp>
|
||||
|
||||
#include <ade/typed_graph.hpp>
|
||||
|
||||
#include "opencv2/gapi/gcommon.hpp"
|
||||
#include "opencv2/gapi/util/any.hpp"
|
||||
#include "opencv2/gapi/gtype_traits.hpp"
|
||||
|
||||
#include "compiler/gobjref.hpp"
|
||||
#include "compiler/gmodel.hpp"
|
||||
|
||||
#include "backends/gpu/ggpubackend.hpp"
|
||||
#include "backends/gpu/ggpuimgproc.hpp"
|
||||
#include "backends/gpu/ggpucore.hpp"
|
||||
|
||||
#include "api/gbackend_priv.hpp" // FIXME: Make it part of Backend SDK!
|
||||
|
||||
// FIXME: Is there a way to take a typed graph (our GModel),
|
||||
// and create a new typed graph _ATOP_ of that (by extending with a couple of
|
||||
// new types?).
|
||||
// Alternatively, is there a way to compose types graphs?
|
||||
//
|
||||
// If not, we need to introduce that!
|
||||
using GGPUModel = ade::TypedGraph
|
||||
< cv::gimpl::Unit
|
||||
, cv::gimpl::Protocol
|
||||
>;
|
||||
|
||||
// FIXME: Same issue with Typed and ConstTyped
|
||||
using GConstGGPUModel = ade::ConstTypedGraph
|
||||
< cv::gimpl::Unit
|
||||
, cv::gimpl::Protocol
|
||||
>;
|
||||
|
||||
namespace
|
||||
{
|
||||
class GGPUBackendImpl final: public cv::gapi::GBackend::Priv
|
||||
{
|
||||
virtual void unpackKernel(ade::Graph &graph,
|
||||
const ade::NodeHandle &op_node,
|
||||
const cv::GKernelImpl &impl) override
|
||||
{
|
||||
GGPUModel gm(graph);
|
||||
auto gpu_impl = cv::util::any_cast<cv::GGPUKernel>(impl.opaque);
|
||||
gm.metadata(op_node).set(cv::gimpl::Unit{gpu_impl});
|
||||
}
|
||||
|
||||
virtual EPtr compile(const ade::Graph &graph,
|
||||
const cv::GCompileArgs &,
|
||||
const std::vector<ade::NodeHandle> &nodes) const override
|
||||
{
|
||||
return EPtr{new cv::gimpl::GGPUExecutable(graph, nodes)};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
cv::gapi::GBackend cv::gapi::gpu::backend()
|
||||
{
|
||||
static cv::gapi::GBackend this_backend(std::make_shared<GGPUBackendImpl>());
|
||||
return this_backend;
|
||||
}
|
||||
|
||||
// GGPUExcecutable implementation //////////////////////////////////////////////
|
||||
cv::gimpl::GGPUExecutable::GGPUExecutable(const ade::Graph &g,
|
||||
const std::vector<ade::NodeHandle> &nodes)
|
||||
: m_g(g), m_gm(m_g)
|
||||
{
|
||||
// Convert list of operations (which is topologically sorted already)
|
||||
// into an execution script.
|
||||
for (auto &nh : nodes)
|
||||
{
|
||||
switch (m_gm.metadata(nh).get<NodeType>().t)
|
||||
{
|
||||
case NodeType::OP: m_script.push_back({nh, GModel::collectOutputMeta(m_gm, nh)}); break;
|
||||
case NodeType::DATA:
|
||||
{
|
||||
m_dataNodes.push_back(nh);
|
||||
const auto &desc = m_gm.metadata(nh).get<Data>();
|
||||
if (desc.storage == Data::Storage::CONST)
|
||||
{
|
||||
auto rc = RcDesc{desc.rc, desc.shape, desc.ctor};
|
||||
magazine::bindInArg(m_res, rc, m_gm.metadata(nh).get<ConstValue>().arg);
|
||||
}
|
||||
//preallocate internal Mats in advance
|
||||
if (desc.storage == Data::Storage::INTERNAL && desc.shape == GShape::GMAT)
|
||||
{
|
||||
const auto mat_desc = util::get<cv::GMatDesc>(desc.meta);
|
||||
const auto type = CV_MAKETYPE(mat_desc.depth, mat_desc.chan);
|
||||
m_res.slot<cv::UMat>()[desc.rc].create(mat_desc.size.width, mat_desc.size.height, type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: util::throw_error(std::logic_error("Unsupported NodeType type"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Document what it does
|
||||
cv::GArg cv::gimpl::GGPUExecutable::packArg(const GArg &arg)
|
||||
{
|
||||
// No API placeholders allowed at this point
|
||||
// FIXME: this check has to be done somewhere in compilation stage.
|
||||
GAPI_Assert( arg.kind != cv::detail::ArgKind::GMAT
|
||||
&& arg.kind != cv::detail::ArgKind::GSCALAR
|
||||
&& arg.kind != cv::detail::ArgKind::GARRAY);
|
||||
|
||||
if (arg.kind != cv::detail::ArgKind::GOBJREF)
|
||||
{
|
||||
// All other cases - pass as-is, with no transformations to GArg contents.
|
||||
return arg;
|
||||
}
|
||||
GAPI_Assert(arg.kind == cv::detail::ArgKind::GOBJREF);
|
||||
|
||||
// Wrap associated CPU object (either host or an internal one)
|
||||
// FIXME: object can be moved out!!! GExecutor faced that.
|
||||
const cv::gimpl::RcDesc &ref = arg.get<cv::gimpl::RcDesc>();
|
||||
switch (ref.shape)
|
||||
{
|
||||
case GShape::GMAT: return GArg(m_res.slot<cv::UMat>()[ref.id]);
|
||||
case GShape::GSCALAR: return GArg(m_res.slot<cv::gapi::own::Scalar>()[ref.id]);
|
||||
// Note: .at() is intentional for GArray as object MUST be already there
|
||||
// (and constructed by either bindIn/Out or resetInternal)
|
||||
case GShape::GARRAY: return GArg(m_res.slot<cv::detail::VectorRef>().at(ref.id));
|
||||
default:
|
||||
util::throw_error(std::logic_error("Unsupported GShape type"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void cv::gimpl::GGPUExecutable::run(std::vector<InObj> &&input_objs,
|
||||
std::vector<OutObj> &&output_objs)
|
||||
{
|
||||
// Update resources with run-time information - what this Island
|
||||
// has received from user (or from another Island, or mix...)
|
||||
// FIXME: Check input/output objects against GIsland protocol
|
||||
|
||||
for (auto& it : input_objs) magazine::bindInArg (m_res, it.first, it.second, true);
|
||||
for (auto& it : output_objs) magazine::bindOutArg(m_res, it.first, it.second, true);
|
||||
|
||||
// Initialize (reset) internal data nodes with user structures
|
||||
// before processing a frame (no need to do it for external data structures)
|
||||
GModel::ConstGraph gm(m_g);
|
||||
for (auto nh : m_dataNodes)
|
||||
{
|
||||
const auto &desc = gm.metadata(nh).get<Data>();
|
||||
|
||||
if ( desc.storage == Data::Storage::INTERNAL
|
||||
&& !util::holds_alternative<util::monostate>(desc.ctor))
|
||||
{
|
||||
// FIXME: Note that compile-time constant data objects (like
|
||||
// a value-initialized GArray<T>) also satisfy this condition
|
||||
// and should be excluded, but now we just don't support it
|
||||
magazine::resetInternalData(m_res, desc);
|
||||
}
|
||||
}
|
||||
|
||||
// OpenCV backend execution is not a rocket science at all.
|
||||
// Simply invoke our kernels in the proper order.
|
||||
GConstGGPUModel gcm(m_g);
|
||||
for (auto &op_info : m_script)
|
||||
{
|
||||
const auto &op = m_gm.metadata(op_info.nh).get<Op>();
|
||||
|
||||
// Obtain our real execution unit
|
||||
// TODO: Should kernels be copyable?
|
||||
GGPUKernel k = gcm.metadata(op_info.nh).get<Unit>().k;
|
||||
|
||||
// Initialize kernel's execution context:
|
||||
// - Input parameters
|
||||
GGPUContext context;
|
||||
context.m_args.reserve(op.args.size());
|
||||
|
||||
using namespace std::placeholders;
|
||||
ade::util::transform(op.args,
|
||||
std::back_inserter(context.m_args),
|
||||
std::bind(&GGPUExecutable::packArg, this, _1));
|
||||
|
||||
// - Output parameters.
|
||||
// FIXME: pre-allocate internal Mats, etc, according to the known meta
|
||||
for (const auto &out_it : ade::util::indexed(op.outs))
|
||||
{
|
||||
// FIXME: Can the same GArg type resolution mechanism be reused here?
|
||||
const auto out_port = ade::util::index(out_it);
|
||||
const auto out_desc = ade::util::value(out_it);
|
||||
context.m_results[out_port] = magazine::getObjPtr(m_res, out_desc, true);
|
||||
}
|
||||
|
||||
// Now trigger the executable unit
|
||||
k.apply(context);
|
||||
|
||||
for (const auto &out_it : ade::util::indexed(op_info.expected_out_metas))
|
||||
{
|
||||
const auto out_index = ade::util::index(out_it);
|
||||
const auto expected_meta = ade::util::value(out_it);
|
||||
const auto out_meta = descr_of(context.m_results[out_index]);
|
||||
|
||||
if (expected_meta != out_meta)
|
||||
{
|
||||
util::throw_error
|
||||
(std::logic_error
|
||||
("Output meta doesn't "
|
||||
"coincide with the generated meta\n"
|
||||
"Expected: " + ade::util::to_string(expected_meta) + "\n"
|
||||
"Actual : " + ade::util::to_string(out_meta)));
|
||||
}
|
||||
}
|
||||
} // for(m_script)
|
||||
|
||||
for (auto &it : output_objs) magazine::writeBack(m_res, it.first, it.second, true);
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// 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_GGPUBACKEND_HPP
|
||||
#define OPENCV_GAPI_GGPUBACKEND_HPP
|
||||
|
||||
#include <map> // map
|
||||
#include <unordered_map> // unordered_map
|
||||
#include <tuple> // tuple
|
||||
#include <ade/util/algorithm.hpp> // type_list_index
|
||||
|
||||
#include "opencv2/gapi/garg.hpp"
|
||||
#include "opencv2/gapi/gproto.hpp"
|
||||
#include "opencv2/gapi/gpu/ggpukernel.hpp"
|
||||
|
||||
|
||||
#include "api/gapi_priv.hpp"
|
||||
#include "backends/common/gbackend.hpp"
|
||||
#include "compiler/gislandmodel.hpp"
|
||||
|
||||
namespace cv { namespace gimpl {
|
||||
|
||||
struct Unit
|
||||
{
|
||||
static const char *name() { return "GPUKernel"; }
|
||||
GGPUKernel k;
|
||||
};
|
||||
|
||||
class GGPUExecutable final: public GIslandExecutable
|
||||
{
|
||||
const ade::Graph &m_g;
|
||||
GModel::ConstGraph m_gm;
|
||||
|
||||
struct OperationInfo
|
||||
{
|
||||
ade::NodeHandle nh;
|
||||
GMetaArgs expected_out_metas;
|
||||
};
|
||||
|
||||
// Execution script, currently absolutely naive
|
||||
std::vector<OperationInfo> m_script;
|
||||
// List of all resources in graph (both internal and external)
|
||||
std::vector<ade::NodeHandle> m_dataNodes;
|
||||
|
||||
// Actual data of all resources in graph (both internal and external)
|
||||
Mag m_res;
|
||||
GArg packArg(const GArg &arg);
|
||||
|
||||
public:
|
||||
GGPUExecutable(const ade::Graph &graph,
|
||||
const std::vector<ade::NodeHandle> &nodes);
|
||||
|
||||
virtual inline bool canReshape() const override { return false; }
|
||||
virtual inline void reshape(ade::Graph&, const GCompileArgs&) override
|
||||
{
|
||||
// FIXME: GPU plugin is in fact reshapeable (as it was initially,
|
||||
// even before outMeta() has been introduced), so this limitation
|
||||
// should be dropped.
|
||||
util::throw_error(std::logic_error("GGPUExecutable::reshape() should never be called"));
|
||||
}
|
||||
|
||||
virtual void run(std::vector<InObj> &&input_objs,
|
||||
std::vector<OutObj> &&output_objs) override;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif // OPENCV_GAPI_GGPUBACKEND_HPP
|
||||
@@ -0,0 +1,582 @@
|
||||
// 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
|
||||
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#include "opencv2/gapi/core.hpp"
|
||||
#include "opencv2/gapi/gpu/core.hpp"
|
||||
#include "backends/gpu/ggpucore.hpp"
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUAdd, cv::gapi::core::GAdd)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::UMat& b, int dtype, cv::UMat& out)
|
||||
{
|
||||
cv::add(a, b, out, cv::noArray(), dtype);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUAddC, cv::gapi::core::GAddC)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::Scalar& b, int dtype, cv::UMat& out)
|
||||
{
|
||||
cv::add(a, b, out, cv::noArray(), dtype);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUSub, cv::gapi::core::GSub)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::UMat& b, int dtype, cv::UMat& out)
|
||||
{
|
||||
cv::subtract(a, b, out, cv::noArray(), dtype);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUSubC, cv::gapi::core::GSubC)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::Scalar& b, int dtype, cv::UMat& out)
|
||||
{
|
||||
cv::subtract(a, b, out, cv::noArray(), dtype);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUSubRC, cv::gapi::core::GSubRC)
|
||||
{
|
||||
static void run(const cv::Scalar& a, const cv::UMat& b, int dtype, cv::UMat& out)
|
||||
{
|
||||
cv::subtract(a, b, out, cv::noArray(), dtype);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUMul, cv::gapi::core::GMul)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::UMat& b, double scale, int dtype, cv::UMat& out)
|
||||
{
|
||||
cv::multiply(a, b, out, scale, dtype);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUMulCOld, cv::gapi::core::GMulCOld)
|
||||
{
|
||||
static void run(const cv::UMat& a, double b, int dtype, cv::UMat& out)
|
||||
{
|
||||
cv::multiply(a, b, out, 1, dtype);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUMulC, cv::gapi::core::GMulC)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::Scalar& b, int dtype, cv::UMat& out)
|
||||
{
|
||||
cv::multiply(a, b, out, 1, dtype);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUDiv, cv::gapi::core::GDiv)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::UMat& b, double scale, int dtype, cv::UMat& out)
|
||||
{
|
||||
cv::divide(a, b, out, scale, dtype);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUDivC, cv::gapi::core::GDivC)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::Scalar& b, double scale, int dtype, cv::UMat& out)
|
||||
{
|
||||
cv::divide(a, b, out, scale, dtype);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUDivRC, cv::gapi::core::GDivRC)
|
||||
{
|
||||
static void run(const cv::Scalar& a, const cv::UMat& b, double scale, int dtype, cv::UMat& out)
|
||||
{
|
||||
cv::divide(a, b, out, scale, dtype);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUMask, cv::gapi::core::GMask)
|
||||
{
|
||||
static void run(const cv::UMat& in, const cv::UMat& mask, cv::UMat& out)
|
||||
{
|
||||
out = cv::UMat::zeros(in.size(), in.type());
|
||||
in.copyTo(out, mask);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUMean, cv::gapi::core::GMean)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::Scalar& out)
|
||||
{
|
||||
out = cv::mean(in);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUPolarToCart, cv::gapi::core::GPolarToCart)
|
||||
{
|
||||
static void run(const cv::UMat& magn, const cv::UMat& angle, bool angleInDegrees, cv::UMat& outx, cv::UMat& outy)
|
||||
{
|
||||
cv::polarToCart(magn, angle, outx, outy, angleInDegrees);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCartToPolar, cv::gapi::core::GCartToPolar)
|
||||
{
|
||||
static void run(const cv::UMat& x, const cv::UMat& y, bool angleInDegrees, cv::UMat& outmagn, cv::UMat& outangle)
|
||||
{
|
||||
cv::cartToPolar(x, y, outmagn, outangle, angleInDegrees);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCmpGT, cv::gapi::core::GCmpGT)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
|
||||
{
|
||||
cv::compare(a, b, out, cv::CMP_GT);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCmpGE, cv::gapi::core::GCmpGE)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
|
||||
{
|
||||
cv::compare(a, b, out, cv::CMP_GE);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCmpLE, cv::gapi::core::GCmpLE)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
|
||||
{
|
||||
cv::compare(a, b, out, cv::CMP_LE);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCmpLT, cv::gapi::core::GCmpLT)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
|
||||
{
|
||||
cv::compare(a, b, out, cv::CMP_LT);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCmpEQ, cv::gapi::core::GCmpEQ)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
|
||||
{
|
||||
cv::compare(a, b, out, cv::CMP_EQ);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCmpNE, cv::gapi::core::GCmpNE)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
|
||||
{
|
||||
cv::compare(a, b, out, cv::CMP_NE);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCmpGTScalar, cv::gapi::core::GCmpGTScalar)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
|
||||
{
|
||||
cv::compare(a, b, out, cv::CMP_GT);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCmpGEScalar, cv::gapi::core::GCmpGEScalar)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
|
||||
{
|
||||
cv::compare(a, b, out, cv::CMP_GE);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCmpLEScalar, cv::gapi::core::GCmpLEScalar)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
|
||||
{
|
||||
cv::compare(a, b, out, cv::CMP_LE);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCmpLTScalar, cv::gapi::core::GCmpLTScalar)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
|
||||
{
|
||||
cv::compare(a, b, out, cv::CMP_LT);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCmpEQScalar, cv::gapi::core::GCmpEQScalar)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
|
||||
{
|
||||
cv::compare(a, b, out, cv::CMP_EQ);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCmpNEScalar, cv::gapi::core::GCmpNEScalar)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
|
||||
{
|
||||
cv::compare(a, b, out, cv::CMP_NE);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUAnd, cv::gapi::core::GAnd)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
|
||||
{
|
||||
cv::bitwise_and(a, b, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUAndS, cv::gapi::core::GAndS)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
|
||||
{
|
||||
cv::bitwise_and(a, b, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUOr, cv::gapi::core::GOr)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
|
||||
{
|
||||
cv::bitwise_or(a, b, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUOrS, cv::gapi::core::GOrS)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
|
||||
{
|
||||
cv::bitwise_or(a, b, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUXor, cv::gapi::core::GXor)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
|
||||
{
|
||||
cv::bitwise_xor(a, b, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUXorS, cv::gapi::core::GXorS)
|
||||
{
|
||||
static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
|
||||
{
|
||||
cv::bitwise_xor(a, b, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUNot, cv::gapi::core::GNot)
|
||||
{
|
||||
static void run(const cv::UMat& a, cv::UMat& out)
|
||||
{
|
||||
cv::bitwise_not(a, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUSelect, cv::gapi::core::GSelect)
|
||||
{
|
||||
static void run(const cv::UMat& src1, const cv::UMat& src2, const cv::UMat& mask, cv::UMat& out)
|
||||
{
|
||||
src2.copyTo(out);
|
||||
src1.copyTo(out, mask);
|
||||
}
|
||||
};
|
||||
|
||||
////TODO: doesn't compiled with UMat
|
||||
//GAPI_GPU_KERNEL(GGPUMin, cv::gapi::core::GMin)
|
||||
//{
|
||||
// static void run(const cv::UMat& in1, const cv::UMat& in2, cv::UMat& out)
|
||||
// {
|
||||
// out = cv::min(in1, in2);
|
||||
// }
|
||||
//};
|
||||
//
|
||||
////TODO: doesn't compiled with UMat
|
||||
//GAPI_GPU_KERNEL(GGPUMax, cv::gapi::core::GMax)
|
||||
//{
|
||||
// static void run(const cv::UMat& in1, const cv::UMat& in2, cv::UMat& out)
|
||||
// {
|
||||
// out = cv::max(in1, in2);
|
||||
// }
|
||||
//};
|
||||
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUAbsDiff, cv::gapi::core::GAbsDiff)
|
||||
{
|
||||
static void run(const cv::UMat& in1, const cv::UMat& in2, cv::UMat& out)
|
||||
{
|
||||
cv::absdiff(in1, in2, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUAbsDiffC, cv::gapi::core::GAbsDiffC)
|
||||
{
|
||||
static void run(const cv::UMat& in1, const cv::Scalar& in2, cv::UMat& out)
|
||||
{
|
||||
cv::absdiff(in1, in2, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUSum, cv::gapi::core::GSum)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::Scalar& out)
|
||||
{
|
||||
out = cv::sum(in);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUAddW, cv::gapi::core::GAddW)
|
||||
{
|
||||
static void run(const cv::UMat& in1, double alpha, const cv::UMat& in2, double beta, double gamma, int dtype, cv::UMat& out)
|
||||
{
|
||||
cv::addWeighted(in1, alpha, in2, beta, gamma, out, dtype);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUNormL1, cv::gapi::core::GNormL1)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::Scalar& out)
|
||||
{
|
||||
out = cv::norm(in, cv::NORM_L1);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUNormL2, cv::gapi::core::GNormL2)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::Scalar& out)
|
||||
{
|
||||
out = cv::norm(in, cv::NORM_L2);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUNormInf, cv::gapi::core::GNormInf)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::Scalar& out)
|
||||
{
|
||||
out = cv::norm(in, cv::NORM_INF);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUIntegral, cv::gapi::core::GIntegral)
|
||||
{
|
||||
static void run(const cv::UMat& in, int sdepth, int sqdepth, cv::UMat& out, cv::UMat& outSq)
|
||||
{
|
||||
cv::integral(in, out, outSq, sdepth, sqdepth);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUThreshold, cv::gapi::core::GThreshold)
|
||||
{
|
||||
static void run(const cv::UMat& in, const cv::Scalar& a, const cv::Scalar& b, int type, cv::UMat& out)
|
||||
{
|
||||
cv::threshold(in, out, a.val[0], b.val[0], type);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUThresholdOT, cv::gapi::core::GThresholdOT)
|
||||
{
|
||||
static void run(const cv::UMat& in, const cv::Scalar& b, int type, cv::UMat& out, cv::Scalar& outScalar)
|
||||
{
|
||||
outScalar = cv::threshold(in, out, b.val[0], b.val[0], type);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUInRange, cv::gapi::core::GInRange)
|
||||
{
|
||||
static void run(const cv::UMat& in, const cv::Scalar& low, const cv::Scalar& up, cv::UMat& out)
|
||||
{
|
||||
cv::inRange(in, low, up, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUSplit3, cv::gapi::core::GSplit3)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::UMat &m1, cv::UMat &m2, cv::UMat &m3)
|
||||
{
|
||||
std::vector<cv::UMat> outMats = {m1, m2, m3};
|
||||
cv::split(in, outMats);
|
||||
|
||||
// Write back FIXME: Write a helper or avoid this nonsence completely!
|
||||
m1 = outMats[0];
|
||||
m2 = outMats[1];
|
||||
m3 = outMats[2];
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUSplit4, cv::gapi::core::GSplit4)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::UMat &m1, cv::UMat &m2, cv::UMat &m3, cv::UMat &m4)
|
||||
{
|
||||
std::vector<cv::UMat> outMats = {m1, m2, m3, m4};
|
||||
cv::split(in, outMats);
|
||||
|
||||
// Write back FIXME: Write a helper or avoid this nonsence completely!
|
||||
m1 = outMats[0];
|
||||
m2 = outMats[1];
|
||||
m3 = outMats[2];
|
||||
m4 = outMats[3];
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUMerge3, cv::gapi::core::GMerge3)
|
||||
{
|
||||
static void run(const cv::UMat& in1, const cv::UMat& in2, const cv::UMat& in3, cv::UMat &out)
|
||||
{
|
||||
std::vector<cv::UMat> inMats = {in1, in2, in3};
|
||||
cv::merge(inMats, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUMerge4, cv::gapi::core::GMerge4)
|
||||
{
|
||||
static void run(const cv::UMat& in1, const cv::UMat& in2, const cv::UMat& in3, const cv::UMat& in4, cv::UMat &out)
|
||||
{
|
||||
std::vector<cv::UMat> inMats = {in1, in2, in3, in4};
|
||||
cv::merge(inMats, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUResize, cv::gapi::core::GResize)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::Size sz, double fx, double fy, int interp, cv::UMat &out)
|
||||
{
|
||||
cv::resize(in, out, sz, fx, fy, interp);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPURemap, cv::gapi::core::GRemap)
|
||||
{
|
||||
static void run(const cv::UMat& in, const cv::Mat& x, const cv::Mat& y, int a, int b, cv::Scalar s, cv::UMat& out)
|
||||
{
|
||||
cv::remap(in, out, x, y, a, b, s);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUFlip, cv::gapi::core::GFlip)
|
||||
{
|
||||
static void run(const cv::UMat& in, int code, cv::UMat& out)
|
||||
{
|
||||
cv::flip(in, out, code);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCrop, cv::gapi::core::GCrop)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::Rect rect, cv::UMat& out)
|
||||
{
|
||||
cv::UMat(in, rect).copyTo(out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUConcatHor, cv::gapi::core::GConcatHor)
|
||||
{
|
||||
static void run(const cv::UMat& in1, const cv::UMat& in2, cv::UMat& out)
|
||||
{
|
||||
cv::hconcat(in1, in2, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUConcatVert, cv::gapi::core::GConcatVert)
|
||||
{
|
||||
static void run(const cv::UMat& in1, const cv::UMat& in2, cv::UMat& out)
|
||||
{
|
||||
cv::vconcat(in1, in2, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPULUT, cv::gapi::core::GLUT)
|
||||
{
|
||||
static void run(const cv::UMat& in, const cv::Mat& lut, cv::UMat& out)
|
||||
{
|
||||
cv::LUT(in, lut, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUConvertTo, cv::gapi::core::GConvertTo)
|
||||
{
|
||||
static void run(const cv::UMat& in, int rtype, double alpha, double beta, cv::UMat& out)
|
||||
{
|
||||
in.convertTo(out, rtype, alpha, beta);
|
||||
}
|
||||
};
|
||||
|
||||
cv::gapi::GKernelPackage cv::gapi::core::gpu::kernels()
|
||||
{
|
||||
static auto pkg = cv::gapi::kernels
|
||||
< GGPUAdd
|
||||
, GGPUAddC
|
||||
, GGPUSub
|
||||
, GGPUSubC
|
||||
, GGPUSubRC
|
||||
, GGPUMul
|
||||
, GGPUMulC
|
||||
, GGPUMulCOld
|
||||
, GGPUDiv
|
||||
, GGPUDivC
|
||||
, GGPUDivRC
|
||||
, GGPUMean
|
||||
, GGPUMask
|
||||
, GGPUPolarToCart
|
||||
, GGPUCartToPolar
|
||||
, GGPUCmpGT
|
||||
, GGPUCmpGE
|
||||
, GGPUCmpLE
|
||||
, GGPUCmpLT
|
||||
, GGPUCmpEQ
|
||||
, GGPUCmpNE
|
||||
, GGPUCmpGTScalar
|
||||
, GGPUCmpGEScalar
|
||||
, GGPUCmpLEScalar
|
||||
, GGPUCmpLTScalar
|
||||
, GGPUCmpEQScalar
|
||||
, GGPUCmpNEScalar
|
||||
, GGPUAnd
|
||||
, GGPUAndS
|
||||
, GGPUOr
|
||||
, GGPUOrS
|
||||
, GGPUXor
|
||||
, GGPUXorS
|
||||
, GGPUNot
|
||||
, GGPUSelect
|
||||
//, GGPUMin
|
||||
//, GGPUMax
|
||||
, GGPUAbsDiff
|
||||
, GGPUAbsDiffC
|
||||
, GGPUSum
|
||||
, GGPUAddW
|
||||
, GGPUNormL1
|
||||
, GGPUNormL2
|
||||
, GGPUNormInf
|
||||
, GGPUIntegral
|
||||
, GGPUThreshold
|
||||
, GGPUThresholdOT
|
||||
, GGPUInRange
|
||||
, GGPUSplit3
|
||||
, GGPUSplit4
|
||||
, GGPUResize
|
||||
, GGPUMerge3
|
||||
, GGPUMerge4
|
||||
, GGPURemap
|
||||
, GGPUFlip
|
||||
, GGPUCrop
|
||||
, GGPUConcatHor
|
||||
, GGPUConcatVert
|
||||
, GGPULUT
|
||||
, GGPUConvertTo
|
||||
>();
|
||||
return pkg;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// 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_GGPUCORE_HPP
|
||||
#define OPENCV_GAPI_GGPUCORE_HPP
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "opencv2/gapi/gpu/ggpukernel.hpp"
|
||||
|
||||
namespace cv { namespace gimpl {
|
||||
|
||||
// NB: This is what a "Kernel Package" from the original Wiki doc should be.
|
||||
void loadGPUCore(std::map<std::string, cv::GGPUKernel> &kmap);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENCV_GAPI_GGPUCORE_HPP
|
||||
@@ -0,0 +1,277 @@
|
||||
// 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
|
||||
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#include "opencv2/gapi/imgproc.hpp"
|
||||
#include "opencv2/gapi/gpu/imgproc.hpp"
|
||||
#include "backends/gpu/ggpuimgproc.hpp"
|
||||
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUSepFilter, cv::gapi::imgproc::GSepFilter)
|
||||
{
|
||||
static void run(const cv::UMat& in, int ddepth, const cv::Mat& kernX, const cv::Mat& kernY, const cv::Point& anchor, const cv::Scalar& delta,
|
||||
int border, const cv::Scalar& bordVal, cv::UMat &out)
|
||||
{
|
||||
if( border == cv::BORDER_CONSTANT )
|
||||
{
|
||||
cv::UMat temp_in;
|
||||
int width_add = (kernY.cols - 1) / 2;
|
||||
int height_add = (kernX.rows - 1) / 2;
|
||||
cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, border, bordVal);
|
||||
cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
|
||||
cv::sepFilter2D(temp_in(rect), out, ddepth, kernX, kernY, anchor, delta.val[0], border);
|
||||
}
|
||||
else
|
||||
cv::sepFilter2D(in, out, ddepth, kernX, kernY, anchor, delta.val[0], border);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUBoxFilter, cv::gapi::imgproc::GBoxFilter)
|
||||
{
|
||||
static void run(const cv::UMat& in, int ddepth, const cv::Size& ksize, const cv::Point& anchor, bool normalize, int borderType, const cv::Scalar& bordVal, cv::UMat &out)
|
||||
{
|
||||
if( borderType == cv::BORDER_CONSTANT )
|
||||
{
|
||||
cv::UMat temp_in;
|
||||
int width_add = (ksize.width - 1) / 2;
|
||||
int height_add = (ksize.height - 1) / 2;
|
||||
cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, borderType, bordVal);
|
||||
cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
|
||||
cv::boxFilter(temp_in(rect), out, ddepth, ksize, anchor, normalize, borderType);
|
||||
}
|
||||
else
|
||||
cv::boxFilter(in, out, ddepth, ksize, anchor, normalize, borderType);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUBlur, cv::gapi::imgproc::GBlur)
|
||||
{
|
||||
static void run(const cv::UMat& in, const cv::Size& ksize, const cv::Point& anchor, int borderType, const cv::Scalar& bordVal, cv::UMat &out)
|
||||
{
|
||||
if( borderType == cv::BORDER_CONSTANT )
|
||||
{
|
||||
cv::UMat temp_in;
|
||||
int width_add = (ksize.width - 1) / 2;
|
||||
int height_add = (ksize.height - 1) / 2;
|
||||
cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, borderType, bordVal);
|
||||
cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
|
||||
cv::blur(temp_in(rect), out, ksize, anchor, borderType);
|
||||
}
|
||||
else
|
||||
cv::blur(in, out, ksize, anchor, borderType);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUFilter2D, cv::gapi::imgproc::GFilter2D)
|
||||
{
|
||||
static void run(const cv::UMat& in, int ddepth, const cv::Mat& k, const cv::Point& anchor, const cv::Scalar& delta, int border,
|
||||
const cv::Scalar& bordVal, cv::UMat &out)
|
||||
{
|
||||
if( border == cv::BORDER_CONSTANT )
|
||||
{
|
||||
cv::UMat temp_in;
|
||||
int width_add = (k.cols - 1) / 2;
|
||||
int height_add = (k.rows - 1) / 2;
|
||||
cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, border, bordVal );
|
||||
cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
|
||||
cv::filter2D(temp_in(rect), out, ddepth, k, anchor, delta.val[0], border);
|
||||
}
|
||||
else
|
||||
cv::filter2D(in, out, ddepth, k, anchor, delta.val[0], border);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUGaussBlur, cv::gapi::imgproc::GGaussBlur)
|
||||
{
|
||||
static void run(const cv::UMat& in, const cv::Size& ksize, double sigmaX, double sigmaY, int borderType, const cv::Scalar& bordVal, cv::UMat &out)
|
||||
{
|
||||
if( borderType == cv::BORDER_CONSTANT )
|
||||
{
|
||||
cv::UMat temp_in;
|
||||
int width_add = (ksize.width - 1) / 2;
|
||||
int height_add = (ksize.height - 1) / 2;
|
||||
cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, borderType, bordVal );
|
||||
cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
|
||||
cv::GaussianBlur(temp_in(rect), out, ksize, sigmaX, sigmaY, borderType);
|
||||
}
|
||||
else
|
||||
cv::GaussianBlur(in, out, ksize, sigmaX, sigmaY, borderType);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUMedianBlur, cv::gapi::imgproc::GMedianBlur)
|
||||
{
|
||||
static void run(const cv::UMat& in, int ksize, cv::UMat &out)
|
||||
{
|
||||
cv::medianBlur(in, out, ksize);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUErode, cv::gapi::imgproc::GErode)
|
||||
{
|
||||
static void run(const cv::UMat& in, const cv::Mat& kernel, const cv::Point& anchor, int iterations, int borderType, const cv::Scalar& borderValue, cv::UMat &out)
|
||||
{
|
||||
cv::erode(in, out, kernel, anchor, iterations, borderType, borderValue);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUDilate, cv::gapi::imgproc::GDilate)
|
||||
{
|
||||
static void run(const cv::UMat& in, const cv::Mat& kernel, const cv::Point& anchor, int iterations, int borderType, const cv::Scalar& borderValue, cv::UMat &out)
|
||||
{
|
||||
cv::dilate(in, out, kernel, anchor, iterations, borderType, borderValue);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUSobel, cv::gapi::imgproc::GSobel)
|
||||
{
|
||||
static void run(const cv::UMat& in, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType,
|
||||
const cv::Scalar& bordVal, cv::UMat &out)
|
||||
{
|
||||
if( borderType == cv::BORDER_CONSTANT )
|
||||
{
|
||||
cv::UMat temp_in;
|
||||
int add = (ksize - 1) / 2;
|
||||
cv::copyMakeBorder(in, temp_in, add, add, add, add, borderType, bordVal );
|
||||
cv::Rect rect = cv::Rect(add, add, in.cols, in.rows);
|
||||
cv::Sobel(temp_in(rect), out, ddepth, dx, dy, ksize, scale, delta, borderType);
|
||||
}
|
||||
else
|
||||
cv::Sobel(in, out, ddepth, dx, dy, ksize, scale, delta, borderType);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUEqualizeHist, cv::gapi::imgproc::GEqHist)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::UMat &out)
|
||||
{
|
||||
cv::equalizeHist(in, out);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUCanny, cv::gapi::imgproc::GCanny)
|
||||
{
|
||||
static void run(const cv::UMat& in, double thr1, double thr2, int apSize, bool l2gradient, cv::UMat &out)
|
||||
{
|
||||
cv::Canny(in, out, thr1, thr2, apSize, l2gradient);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPURGB2YUV, cv::gapi::imgproc::GRGB2YUV)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::UMat &out)
|
||||
{
|
||||
cv::cvtColor(in, out, cv::COLOR_RGB2YUV);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUYUV2RGB, cv::gapi::imgproc::GYUV2RGB)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::UMat &out)
|
||||
{
|
||||
cv::cvtColor(in, out, cv::COLOR_YUV2RGB);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPURGB2Lab, cv::gapi::imgproc::GRGB2Lab)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::UMat &out)
|
||||
{
|
||||
cv::cvtColor(in, out, cv::COLOR_RGB2Lab);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUBGR2LUV, cv::gapi::imgproc::GBGR2LUV)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::UMat &out)
|
||||
{
|
||||
cv::cvtColor(in, out, cv::COLOR_BGR2Luv);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUBGR2YUV, cv::gapi::imgproc::GBGR2YUV)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::UMat &out)
|
||||
{
|
||||
cv::cvtColor(in, out, cv::COLOR_BGR2YUV);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPULUV2BGR, cv::gapi::imgproc::GLUV2BGR)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::UMat &out)
|
||||
{
|
||||
cv::cvtColor(in, out, cv::COLOR_Luv2BGR);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUYUV2BGR, cv::gapi::imgproc::GYUV2BGR)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::UMat &out)
|
||||
{
|
||||
cv::cvtColor(in, out, cv::COLOR_YUV2BGR);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPURGB2Gray, cv::gapi::imgproc::GRGB2Gray)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::UMat &out)
|
||||
{
|
||||
cv::cvtColor(in, out, cv::COLOR_RGB2GRAY);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPUBGR2Gray, cv::gapi::imgproc::GBGR2Gray)
|
||||
{
|
||||
static void run(const cv::UMat& in, cv::UMat &out)
|
||||
{
|
||||
cv::cvtColor(in, out, cv::COLOR_BGR2GRAY);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_GPU_KERNEL(GGPURGB2GrayCustom, cv::gapi::imgproc::GRGB2GrayCustom)
|
||||
{
|
||||
//TODO: avoid copy
|
||||
static void run(const cv::UMat& in, float rY, float bY, float gY, cv::UMat &out)
|
||||
{
|
||||
cv::Mat planes[3];
|
||||
cv::split(in.getMat(cv::ACCESS_READ), planes);
|
||||
cv::Mat tmp_out = (planes[0]*rY + planes[1]*bY + planes[2]*gY);
|
||||
tmp_out.copyTo(out);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
cv::gapi::GKernelPackage cv::gapi::imgproc::gpu::kernels()
|
||||
{
|
||||
static auto pkg = cv::gapi::kernels
|
||||
< GGPUFilter2D
|
||||
, GGPUSepFilter
|
||||
, GGPUBoxFilter
|
||||
, GGPUBlur
|
||||
, GGPUGaussBlur
|
||||
, GGPUMedianBlur
|
||||
, GGPUErode
|
||||
, GGPUDilate
|
||||
, GGPUSobel
|
||||
, GGPUCanny
|
||||
, GGPUEqualizeHist
|
||||
, GGPURGB2YUV
|
||||
, GGPUYUV2RGB
|
||||
, GGPURGB2Lab
|
||||
, GGPUBGR2LUV
|
||||
, GGPUBGR2YUV
|
||||
, GGPUYUV2BGR
|
||||
, GGPULUV2BGR
|
||||
, GGPUBGR2Gray
|
||||
, GGPURGB2Gray
|
||||
, GGPURGB2GrayCustom
|
||||
>();
|
||||
return pkg;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// 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_GGPUIMGPROC_HPP
|
||||
#define OPENCV_GAPI_GGPUIMGPROC_HPP
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "opencv2/gapi/gpu/ggpukernel.hpp"
|
||||
|
||||
namespace cv { namespace gimpl {
|
||||
|
||||
// NB: This is what a "Kernel Package" from the origianl Wiki doc should be.
|
||||
void loadGPUImgProc(std::map<std::string, cv::GGPUKernel> &kmap);
|
||||
|
||||
}}
|
||||
|
||||
#endif // OPENCV_GAPI_GGPUIMGPROC_HPP
|
||||
@@ -0,0 +1,50 @@
|
||||
// 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
|
||||
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "opencv2/gapi/gpu/ggpukernel.hpp"
|
||||
|
||||
const cv::UMat& cv::GGPUContext::inMat(int input)
|
||||
{
|
||||
return (inArg<cv::UMat>(input));
|
||||
}
|
||||
|
||||
cv::UMat& cv::GGPUContext::outMatR(int output)
|
||||
{
|
||||
return (*(util::get<cv::UMat*>(m_results.at(output))));
|
||||
}
|
||||
|
||||
const cv::gapi::own::Scalar& cv::GGPUContext::inVal(int input)
|
||||
{
|
||||
return inArg<cv::gapi::own::Scalar>(input);
|
||||
}
|
||||
|
||||
cv::gapi::own::Scalar& cv::GGPUContext::outValR(int output)
|
||||
{
|
||||
return *util::get<cv::gapi::own::Scalar*>(m_results.at(output));
|
||||
}
|
||||
|
||||
cv::detail::VectorRef& cv::GGPUContext::outVecRef(int output)
|
||||
{
|
||||
return util::get<cv::detail::VectorRef>(m_results.at(output));
|
||||
}
|
||||
|
||||
cv::GGPUKernel::GGPUKernel()
|
||||
{
|
||||
}
|
||||
|
||||
cv::GGPUKernel::GGPUKernel(const GGPUKernel::F &f)
|
||||
: m_f(f)
|
||||
{
|
||||
}
|
||||
|
||||
void cv::GGPUKernel::apply(GGPUContext &ctx)
|
||||
{
|
||||
CV_Assert(m_f);
|
||||
m_f(ctx);
|
||||
}
|
||||
Reference in New Issue
Block a user