1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 00:03:03 +04:00

Merge pull request #19112 from rgarnov:rg/generic_copy_kernel

Generic copy kernel

* Moved RMat wrapping of cv::Mats to StreamingInput

* Generalized GCopy kernel

* Generic GCopy kernel: applied review comments
This commit is contained in:
Ruslan Garnov
2020-12-16 14:18:08 +03:00
committed by GitHub
parent 50baf76cc2
commit f7cab121fe
19 changed files with 161 additions and 180 deletions
-5
View File
@@ -328,11 +328,6 @@ GMat crop(const GMat& src, const Rect& rect)
return core::GCrop::on(src, rect);
}
GMat copy(const GMat& src)
{
return core::GCopy::on(src);
}
GMat concatHor(const GMat& src1, const GMat& src2)
{
return core::GConcatHor::on(src1, src2);
@@ -75,10 +75,6 @@ cv::GMat cv::gapi::streaming::desync(const cv::GMat &g) {
// object will feed both branches of the streaming executable.
}
cv::GFrame cv::gapi::streaming::copy(const cv::GFrame& in) {
return cv::gapi::streaming::GCopy::on(in);
}
cv::GMat cv::gapi::streaming::BGR(const cv::GFrame& in) {
return cv::gapi::streaming::GBGR::on(in);
}
@@ -510,14 +510,6 @@ GAPI_OCV_KERNEL(GCPUCrop, cv::gapi::core::GCrop)
}
};
GAPI_OCV_KERNEL(GCPUCopy, cv::gapi::core::GCopy)
{
static void run(const cv::Mat& in, cv::Mat& out)
{
in.copyTo(out);
}
};
GAPI_OCV_KERNEL(GCPUConcatHor, cv::gapi::core::GConcatHor)
{
static void run(const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out)
@@ -762,7 +754,6 @@ cv::gapi::GKernelPackage cv::gapi::core::cpu::kernels()
, GCPURemap
, GCPUFlip
, GCPUCrop
, GCPUCopy
, GCPUConcatHor
, GCPUConcatVert
, GCPULUT
@@ -2675,40 +2675,6 @@ GAPI_FLUID_KERNEL(GFluidSqrt, cv::gapi::core::GSqrt, false)
}
};
GAPI_FLUID_KERNEL(GFluidCopy, cv::gapi::core::GCopy, false)
{
static const int Window = 1;
static void run(const View &src, Buffer &dst)
{
const auto *in = src.InLine<uchar>(0);
auto *out = dst.OutLine<uchar>();
GAPI_DbgAssert(dst.length() == src.length());
GAPI_DbgAssert(dst.meta().chan == src.meta().chan);
GAPI_DbgAssert(dst.meta().depth == src.meta().depth);
int width = src.length();
int elem_size = CV_ELEM_SIZE(CV_MAKETYPE(src.meta().depth, src.meta().chan));
int w = 0; // cycle counter
#if CV_SIMD128
for (; w <= width*elem_size-16; w+=16)
{
v_uint8x16 a;
a = v_load(&in[w]);
v_store(&out[w], a);
}
#endif
for (; w < width*elem_size; w++)
{
out[w] = in[w];
}
}
};
} // namespace fliud
} // namespace gapi
} // namespace cv
@@ -2768,7 +2734,6 @@ cv::gapi::GKernelPackage cv::gapi::core::fluid::kernels()
,GFluidInRange
,GFluidResize
,GFluidSqrt
,GFluidCopy
#if 0
,GFluidMean -- not fluid
,GFluidSum -- not fluid
@@ -490,14 +490,6 @@ GAPI_OCL_KERNEL(GOCLCrop, cv::gapi::core::GCrop)
}
};
GAPI_OCL_KERNEL(GOCLCopy, cv::gapi::core::GCopy)
{
static void run(const cv::UMat& in, cv::UMat& out)
{
in.copyTo(out);
}
};
GAPI_OCL_KERNEL(GOCLConcatHor, cv::gapi::core::GConcatHor)
{
static void run(const cv::UMat& in1, const cv::UMat& in2, cv::UMat& out)
@@ -590,7 +582,6 @@ cv::gapi::GKernelPackage cv::gapi::core::ocl::kernels()
, GOCLRemap
, GOCLFlip
, GOCLCrop
, GOCLCopy
, GOCLConcatHor
, GOCLConcatVert
, GOCLLUT
@@ -137,7 +137,12 @@ cv::gapi::GBackend cv::gapi::streaming::backend()
cv::gapi::GKernelPackage cv::gapi::streaming::kernels()
{
return cv::gapi::kernels<cv::gimpl::Copy, cv::gimpl::BGR>();
return cv::gapi::kernels<cv::gimpl::BGR>();
}
cv::gapi::GKernelPackage cv::gimpl::streaming::kernels()
{
return cv::gapi::kernels<cv::gimpl::Copy>();
}
void cv::gimpl::Copy::Actor::run(cv::gimpl::GIslandExecutable::IInput &in,
@@ -153,8 +158,21 @@ void cv::gimpl::Copy::Actor::run(cv::gimpl::GIslandExecutable::IInput &in,
const cv::GRunArgs &in_args = cv::util::get<cv::GRunArgs>(in_msg);
GAPI_Assert(in_args.size() == 1u);
cv::GRunArgP out_arg = out.get(0);
*cv::util::get<cv::MediaFrame*>(out_arg) = cv::util::get<cv::MediaFrame>(in_args[0]);
const auto& in_arg = in_args[0];
auto out_arg = out.get(0);
using cv::util::get;
switch (in_arg.index()) {
case cv::GRunArg::index_of<cv::RMat>():
*get<cv::RMat*>(out_arg) = get<cv::RMat>(in_arg);
break;
case cv::GRunArg::index_of<cv::MediaFrame>():
*get<cv::MediaFrame*>(out_arg) = get<cv::MediaFrame>(in_arg);
break;
// FIXME: Add support for remaining types
default:
GAPI_Assert(false && "Copy: unsupported data type");
}
out.meta(out_arg, in_arg.meta);
out.post(std::move(out_arg));
}
@@ -197,3 +215,11 @@ void cv::gimpl::BGR::Actor::run(cv::gimpl::GIslandExecutable::IInput &in,
}
out.post(std::move(out_arg));
}
cv::GMat cv::gapi::copy(const cv::GMat& in) {
return cv::gimpl::streaming::GCopy::on<cv::GMat>(in);
}
cv::GFrame cv::gapi::copy(const cv::GFrame& in) {
return cv::gimpl::streaming::GCopy::on<cv::GFrame>(in);
}
@@ -12,11 +12,37 @@
#include "gstreamingkernel.hpp"
namespace cv {
namespace gapi {
namespace streaming {
cv::gapi::GBackend backend();
}} // namespace gapi::streaming
namespace gimpl {
namespace streaming {
cv::gapi::GKernelPackage kernels();
struct GCopy final : public cv::detail::NoTag
{
static constexpr const char* id() { return "org.opencv.streaming.copy"; }
static GMetaArgs getOutMeta(const GMetaArgs &in_meta, const GArgs&) {
GAPI_Assert(in_meta.size() == 1u);
return in_meta;
}
template<typename T> static T on(const T& arg) {
return cv::GKernelType<GCopy, std::function<T(T)>>::on(arg);
}
};
} // namespace streaming
struct Copy: public cv::detail::KernelTag
{
using API = cv::gapi::streaming::GCopy;
using API = streaming::GCopy;
static gapi::GBackend backend() { return cv::gapi::streaming::backend(); }
+6 -2
View File
@@ -36,6 +36,7 @@
#include "executor/gstreamingexecutor.hpp"
#include "backends/common/gbackend.hpp"
#include "backends/common/gmetabackend.hpp"
#include "backends/streaming/gstreamingbackend.hpp"
// <FIXME:>
#if !defined(GAPI_STANDALONE)
@@ -60,8 +61,11 @@ namespace
for (const auto &b : pkg.backends()) {
aux_pkg = combine(aux_pkg, b.priv().auxiliaryKernels());
}
// Always include built-in meta<> implementation
return combine(pkg, aux_pkg, cv::gimpl::meta::kernels());
// Always include built-in meta<> and copy implementation
return combine(pkg,
aux_pkg,
cv::gimpl::meta::kernels(),
cv::gimpl::streaming::kernels());
};
auto has_use_only = cv::gapi::getCompileArg<cv::gapi::use_only>(args);
+1 -17
View File
@@ -18,7 +18,6 @@
#include "compiler/gmodel.hpp"
#include "compiler/gislandmodel.hpp"
#include "compiler/gmodel.hpp"
#include "backends/common/gbackend.hpp" // RMatAdapter
#include "logger.hpp" // GAPI_LOG
@@ -357,22 +356,7 @@ void GIslandExecutable::run(GIslandExecutable::IInput &in, GIslandExecutable::IO
for (auto &&it: ade::util::zip(ade::util::toRange(in_desc),
ade::util::toRange(in_vector)))
{
const cv::GRunArg& in_data_orig = std::get<1>(it);
cv::GRunArg in_data;
switch (in_data_orig.index())
{
case cv::GRunArg::index_of<cv::Mat>():
// FIXME: This whole construct is ugly, from
// its writing to a need in this in general
in_data = cv::GRunArg{ cv::make_rmat<cv::gimpl::RMatAdapter>(cv::util::get<cv::Mat>(in_data_orig))
, in_data_orig.meta
};
break;
default:
in_data = in_data_orig;
break;
}
in_objs.emplace_back(std::get<0>(it), std::move(in_data));
in_objs.emplace_back(std::get<0>(it), std::get<1>(it));
}
for (auto &&it: ade::util::indexed(ade::util::toRange(out_desc)))
{
+17 -7
View File
@@ -146,16 +146,26 @@ void writeBackExec(const Mag& mag, const RcDesc &rc, GRunArgP &g_arg)
writeBack(mag, rc, g_arg);
return;
}
auto checkOutArgData = [&](const uchar* out_arg_data) {
//simply check that memory was not reallocated, i.e.
//both Mat and View pointing to the same memory
auto mag_data = mag.template slot<cv::RMat>().at(rc.id).get<RMatAdapter>()->data();
GAPI_Assert((out_arg_data == mag_data) && " data for output parameters was reallocated ?");
};
switch (g_arg.index())
{
case GRunArgP::index_of<cv::Mat*>() : checkOutArgData(util::get<cv::Mat*>(g_arg)->data); break;
case GRunArgP::index_of<cv::Mat*>() : {
// If there is a copy intrinsic at the end of the graph
// we need to actualy copy the data to the user buffer
// since output runarg was optimized to simply point
// to the input of the copy kernel
// FIXME:
// Rework, find a better way to check if there should be
// a real copy (add a pass to StreamingBackend?)
auto& out_mat = *util::get<cv::Mat*>(g_arg);
const auto& rmat = mag.template slot<cv::RMat>().at(rc.id);
auto mag_data = rmat.get<RMatAdapter>()->data();
if (out_mat.data != mag_data) {
auto view = rmat.access(RMat::Access::R);
asMat(view).copyTo(out_mat);
}
break;
}
case GRunArgP::index_of<cv::RMat*>() : /* do nothing */ break;
default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
}
@@ -20,6 +20,7 @@
#include "api/gproto_priv.hpp" // ptr(GRunArgP)
#include "compiler/passes/passes.hpp"
#include "backends/common/gbackend.hpp" // createMat
#include "backends/streaming/gstreamingbackend.hpp" // GCopy
#include "compiler/gcompiler.hpp" // for compileIslands
#include "executor/gstreamingexecutor.hpp"
@@ -535,6 +536,14 @@ class StreamingInput final: public cv::gimpl::GIslandExecutable::IInput
// Stop case
return cv::gimpl::StreamMsg{cv::gimpl::EndOfStream{}};
}
// Wrap all input cv::Mats with RMats
for (auto& arg : isl_input_args) {
if (arg.index() == cv::GRunArg::index_of<cv::Mat>()) {
arg = cv::GRunArg{ cv::make_rmat<cv::gimpl::RMatAdapter>(cv::util::get<cv::Mat>(arg))
, arg.meta
};
}
}
return cv::gimpl::StreamMsg{std::move(isl_input_args)};
}
virtual cv::gimpl::StreamMsg try_get() override
@@ -1000,7 +1009,7 @@ cv::gimpl::GStreamingExecutor::GStreamingExecutor(std::unique_ptr<ade::Graph> &&
GAPI_Assert(GModel::Graph(*m_orig_graph)
.metadata(*isl->in_ops().begin())
.get<cv::gimpl::Op>()
.k.name == cv::gapi::core::GCopy::id());
.k.name == cv::gimpl::streaming::GCopy::id());
#endif // GAPI_STANDALONE
for (auto out_nh : nh->outNodes()) {
for (auto out_eh : out_nh->outEdges()) {