mirror of
https://github.com/opencv/opencv.git
synced 2025-06-11 11:45:30 +08:00
Merge pull request #15699 from TolyaTalamanov:at/graph-ocv-render-backend-skeleton
G-API: Implement OpenCV render backend * Implement render opencv backend * Fix comment to review * Add comment * Add wrappers for kernels * Fix comments to review * Fix comment to review
This commit is contained in:
parent
cc9b199ecb
commit
2ff12c4981
@ -94,6 +94,10 @@ set(gapi_srcs
|
||||
# if and only if IE support is enabled
|
||||
src/backends/ie/giebackend.cpp
|
||||
|
||||
# Render Backend.
|
||||
src/backends/render/grenderocvbackend.cpp
|
||||
src/backends/render/grenderocv.cpp
|
||||
|
||||
# Compound
|
||||
src/backends/common/gcompoundbackend.cpp
|
||||
src/backends/common/gcompoundkernel.cpp
|
||||
|
@ -28,6 +28,14 @@ namespace gimpl
|
||||
{
|
||||
// Forward-declare an internal class
|
||||
class GCPUExecutable;
|
||||
|
||||
namespace render
|
||||
{
|
||||
namespace ocv
|
||||
{
|
||||
class GRenderExecutable;
|
||||
}
|
||||
}
|
||||
} // namespace gimpl
|
||||
|
||||
namespace gapi
|
||||
@ -98,6 +106,7 @@ protected:
|
||||
std::unordered_map<std::size_t, GRunArgP> m_results;
|
||||
|
||||
friend class gimpl::GCPUExecutable;
|
||||
friend class gimpl::render::ocv::GRenderExecutable;
|
||||
};
|
||||
|
||||
class GAPI_EXPORTS GCPUKernel
|
||||
|
@ -23,13 +23,21 @@ namespace cv
|
||||
namespace gapi
|
||||
{
|
||||
|
||||
namespace ocv { GAPI_EXPORTS cv::gapi::GKernelPackage kernels(); }
|
||||
|
||||
namespace wip
|
||||
{
|
||||
namespace draw
|
||||
{
|
||||
|
||||
/**
|
||||
* A structure allows using freetype library for text rendering
|
||||
*/
|
||||
struct use_freetype
|
||||
{
|
||||
/*@{*/
|
||||
std::string path; //!< The path to font file (.ttf)
|
||||
/*@{*/
|
||||
};
|
||||
|
||||
/**
|
||||
* A structure to represent parameters for drawing a text string.
|
||||
*/
|
||||
@ -131,6 +139,28 @@ using Prims = std::vector<Prim>;
|
||||
using GMat2 = std::tuple<cv::GMat,cv::GMat>;
|
||||
using GMatDesc2 = std::tuple<cv::GMatDesc,cv::GMatDesc>;
|
||||
|
||||
/** @brief The function renders on the input image passed drawing primitivies
|
||||
|
||||
@param bgr input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
@param prims vector of drawing primitivies
|
||||
@param args graph compile time parameters
|
||||
*/
|
||||
void GAPI_EXPORTS render(cv::Mat& bgr,
|
||||
const Prims& prims,
|
||||
cv::GCompileArgs&& args = {});
|
||||
|
||||
/** @brief The function renders on two NV12 planes passed drawing primitivies
|
||||
|
||||
@param y_plane input image: 8-bit unsigned 1-channel image @ref CV_8UC1.
|
||||
@param uv_plane input image: 8-bit unsigned 2-channel image @ref CV_8UC2.
|
||||
@param prims vector of drawing primitivies
|
||||
@param args graph compile time parameters
|
||||
*/
|
||||
void GAPI_EXPORTS render(cv::Mat& y_plane,
|
||||
cv::Mat& uv_plane,
|
||||
const Prims& prims,
|
||||
cv::GCompileArgs&& args = {});
|
||||
|
||||
G_TYPED_KERNEL_M(GRenderNV12, <GMat2(cv::GMat,cv::GMat,cv::GArray<wip::draw::Prim>)>, "org.opencv.render.nv12")
|
||||
{
|
||||
static GMatDesc2 outMeta(GMatDesc y_plane, GMatDesc uv_plane, GArrayDesc)
|
||||
@ -147,31 +177,39 @@ G_TYPED_KERNEL(GRenderBGR, <cv::GMat(cv::GMat,cv::GArray<wip::draw::Prim>)>, "or
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief The function renders on the input image passed drawing primitivies
|
||||
/** @brief Renders on 3 channels input
|
||||
|
||||
@param bgr input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
@param prims vector of drawing primitivies
|
||||
@param pkg contains render kernel implementation
|
||||
Output image must be 8-bit unsigned planar 3-channel image
|
||||
|
||||
@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3
|
||||
@param prims draw primitives
|
||||
*/
|
||||
GAPI_EXPORTS void render(cv::Mat& bgr,
|
||||
const Prims& prims,
|
||||
const cv::gapi::GKernelPackage& pkg = ocv::kernels());
|
||||
GAPI_EXPORTS GMat render3ch(const GMat& src, const GArray<Prim>& prims);
|
||||
|
||||
/** @brief The function renders on two NV12 planes passed drawing primitivies
|
||||
/** @brief Renders on two planes
|
||||
|
||||
@param y_plane input image: 8-bit unsigned 1-channel image @ref CV_8UC1.
|
||||
@param uv_plane input image: 8-bit unsigned 2-channel image @ref CV_8UC2.
|
||||
@param prims vector of drawing primitivies
|
||||
@param pkg contains render kernel implementation
|
||||
Output y image must be 8-bit unsigned planar 1-channel image @ref CV_8UC1
|
||||
uv image must be 8-bit unsigned planar 2-channel image @ref CV_8UC2
|
||||
|
||||
@param y input image: 8-bit unsigned 1-channel image @ref CV_8UC1
|
||||
@param uv input image: 8-bit unsigned 2-channel image @ref CV_8UC2
|
||||
@param prims draw primitives
|
||||
*/
|
||||
GAPI_EXPORTS void render(cv::Mat& y_plane,
|
||||
cv::Mat& uv_plane,
|
||||
const Prims& prims,
|
||||
const cv::gapi::GKernelPackage& pkg = ocv::kernels());
|
||||
GAPI_EXPORTS GMat2 renderNV12(const GMat& y,
|
||||
const GMat& uv,
|
||||
const GArray<Prim>& prims);
|
||||
|
||||
} // namespace draw
|
||||
} // namespace wip
|
||||
|
||||
namespace render
|
||||
{
|
||||
namespace ocv
|
||||
{
|
||||
GAPI_EXPORTS cv::gapi::GKernelPackage kernels();
|
||||
|
||||
} // namespace ocv
|
||||
} // namespace render
|
||||
} // namespace gapi
|
||||
} // namespace cv
|
||||
|
@ -1,34 +1,33 @@
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/gapi/render.hpp>
|
||||
#include <opencv2/gapi/render/render.hpp>
|
||||
#include <opencv2/gapi/own/assert.hpp>
|
||||
|
||||
#include "api/render_priv.hpp"
|
||||
|
||||
void cv::gapi::wip::draw::render(cv::Mat &bgr,
|
||||
const cv::gapi::wip::draw::Prims &prims,
|
||||
const cv::gapi::GKernelPackage& pkg)
|
||||
cv::GCompileArgs&& args)
|
||||
{
|
||||
cv::GMat in;
|
||||
cv::GArray<Prim> arr;
|
||||
|
||||
cv::GComputation comp(cv::GIn(in, arr),
|
||||
cv::GOut(cv::gapi::wip::draw::GRenderBGR::on(in, arr)));
|
||||
comp.apply(cv::gin(bgr, prims), cv::gout(bgr), cv::compile_args(pkg));
|
||||
cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
|
||||
comp.apply(cv::gin(bgr, prims), cv::gout(bgr), std::move(args));
|
||||
}
|
||||
|
||||
void cv::gapi::wip::draw::render(cv::Mat &y_plane,
|
||||
cv::Mat &uv_plane,
|
||||
const Prims &prims,
|
||||
const GKernelPackage& pkg)
|
||||
cv::GCompileArgs&& args)
|
||||
{
|
||||
cv::GMat y_in, uv_in, y_out, uv_out;
|
||||
cv::GArray<Prim> arr;
|
||||
std::tie(y_out, uv_out) = cv::gapi::wip::draw::GRenderNV12::on(y_in, uv_in, arr);
|
||||
std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
|
||||
|
||||
cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
|
||||
comp.apply(cv::gin(y_plane, uv_plane, prims),
|
||||
cv::gout(y_plane, uv_plane),
|
||||
cv::compile_args(pkg));
|
||||
cv::gout(y_plane, uv_plane), std::move(args));
|
||||
}
|
||||
|
||||
void cv::gapi::wip::draw::BGR2NV12(const cv::Mat &bgr,
|
||||
@ -48,3 +47,28 @@ void cv::gapi::wip::draw::BGR2NV12(const cv::Mat &bgr,
|
||||
cv::merge(std::vector<cv::Mat>{chs[1], chs[2]}, uv_plane);
|
||||
cv::resize(uv_plane, uv_plane, uv_plane.size() / 2, cv::INTER_LINEAR);
|
||||
}
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<> struct CompileArgTag<cv::gapi::wip::draw::use_freetype>
|
||||
{
|
||||
static const char* tag() { return "gapi.use_freetype"; }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
GMat cv::gapi::wip::draw::render3ch(const GMat& src, const GArray<Prim>& prims)
|
||||
{
|
||||
return cv::gapi::wip::draw::GRenderBGR::on(src, prims);
|
||||
}
|
||||
|
||||
std::tuple<GMat, GMat> cv::gapi::wip::draw::renderNV12(const GMat& y,
|
||||
const GMat& uv,
|
||||
const GArray<cv::gapi::wip::draw::Prim>& prims)
|
||||
{
|
||||
return cv::gapi::wip::draw::GRenderNV12::on(y, uv, prims);
|
||||
}
|
||||
|
||||
} // namespace cv
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <opencv2/gapi/cpu/gcpukernel.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/gapi/render.hpp> // Kernel API's
|
||||
#include <opencv2/gapi/render/render.hpp> // Kernel API's
|
||||
|
||||
#include "api/render_ocv.hpp"
|
||||
|
||||
@ -11,61 +10,6 @@ namespace gapi
|
||||
|
||||
namespace ocv
|
||||
{
|
||||
|
||||
GAPI_OCV_KERNEL(GOCVRenderNV12, cv::gapi::wip::draw::GRenderNV12)
|
||||
{
|
||||
static void run(const cv::Mat& y, const cv::Mat& uv, const cv::gapi::wip::draw::Prims& prims,
|
||||
cv::Mat& out_y, cv::Mat& out_uv)
|
||||
{
|
||||
/* FIXME How to render correctly on NV12 format ?
|
||||
*
|
||||
* Rendering on NV12 via OpenCV looks like this:
|
||||
*
|
||||
* y --------> 1)(NV12 -> YUV) -> yuv -> 2)draw -> yuv -> 3)split -------> out_y
|
||||
* ^ |
|
||||
* | |
|
||||
* uv -------------- `----------> out_uv
|
||||
*
|
||||
*
|
||||
* 1) Collect yuv mat from two planes, uv plain in two times less than y plane
|
||||
* so, upsample uv in tow times, with bilinear interpolation
|
||||
*
|
||||
* 2) Render primitives on YUV
|
||||
*
|
||||
* 3) Convert yuv to NV12 (using bilinear interpolation)
|
||||
*
|
||||
*/
|
||||
|
||||
// NV12 -> YUV
|
||||
cv::Mat upsample_uv, yuv;
|
||||
cv::resize(uv, upsample_uv, uv.size() * 2, cv::INTER_LINEAR);
|
||||
cv::merge(std::vector<cv::Mat>{y, upsample_uv}, yuv);
|
||||
|
||||
cv::gapi::wip::draw::drawPrimitivesOCVYUV(yuv, prims);
|
||||
|
||||
// YUV -> NV12
|
||||
cv::Mat out_u, out_v, uv_plane;
|
||||
std::vector<cv::Mat> chs = {out_y, out_u, out_v};
|
||||
cv::split(yuv, chs);
|
||||
cv::merge(std::vector<cv::Mat>{chs[1], chs[2]}, uv_plane);
|
||||
cv::resize(uv_plane, out_uv, uv_plane.size() / 2, cv::INTER_LINEAR);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_OCV_KERNEL(GOCVRenderBGR, cv::gapi::wip::draw::GRenderBGR)
|
||||
{
|
||||
static void run(const cv::Mat&, const cv::gapi::wip::draw::Prims& prims, cv::Mat& out)
|
||||
{
|
||||
cv::gapi::wip::draw::drawPrimitivesOCVBGR(out, prims);
|
||||
}
|
||||
};
|
||||
|
||||
cv::gapi::GKernelPackage kernels()
|
||||
{
|
||||
static const auto pkg = cv::gapi::kernels<GOCVRenderNV12, GOCVRenderBGR>();
|
||||
return pkg;
|
||||
}
|
||||
|
||||
} // namespace ocv
|
||||
|
||||
namespace wip
|
||||
|
@ -8,7 +8,7 @@
|
||||
#ifndef OPENCV_RENDER_PRIV_HPP
|
||||
#define OPENCV_RENDER_PRIV_HPP
|
||||
|
||||
#include <opencv2/gapi/render.hpp>
|
||||
#include <opencv2/gapi/render/render.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
81
modules/gapi/src/backends/render/grenderocv.cpp
Normal file
81
modules/gapi/src/backends/render/grenderocv.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include <opencv2/imgproc.hpp>
|
||||
|
||||
#include "api/render_ocv.hpp"
|
||||
#include "backends/render/grenderocv.hpp"
|
||||
|
||||
#include <opencv2/gapi/cpu/gcpukernel.hpp>
|
||||
|
||||
GAPI_RENDER_OCV_KERNEL(RenderBGRImpl, cv::gapi::wip::draw::GRenderBGR)
|
||||
{
|
||||
static void run(const cv::Mat& in, const cv::gapi::wip::draw::Prims& prims, cv::Mat& out)
|
||||
{
|
||||
// NB: If in and out cv::Mats are the same object
|
||||
// we can avoid copy and render on out cv::Mat
|
||||
// It's work if this kernel is last operation in the graph
|
||||
if (in.data != out.data) {
|
||||
in.copyTo(out);
|
||||
}
|
||||
|
||||
cv::gapi::wip::draw::drawPrimitivesOCVBGR(out, prims);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_RENDER_OCV_KERNEL(RenderNV12Impl, cv::gapi::wip::draw::GRenderNV12)
|
||||
{
|
||||
static void run(const cv::Mat& in_y,
|
||||
const cv::Mat& in_uv,
|
||||
const cv::gapi::wip::draw::Prims& prims,
|
||||
cv::Mat& out_y,
|
||||
cv::Mat& out_uv)
|
||||
{
|
||||
// NB: If in and out cv::Mats are the same object
|
||||
// we can avoid copy and render on out cv::Mat
|
||||
// It's work if this kernel is last operation in the graph
|
||||
if (in_y.data != out_y.data) {
|
||||
in_y.copyTo(out_y);
|
||||
}
|
||||
|
||||
if (in_uv.data != out_uv.data) {
|
||||
in_uv.copyTo(out_uv);
|
||||
}
|
||||
|
||||
/* FIXME How to render correctly on NV12 format ?
|
||||
*
|
||||
* Rendering on NV12 via OpenCV looks like this:
|
||||
*
|
||||
* y --------> 1)(NV12 -> YUV) -> yuv -> 2)draw -> yuv -> 3)split -------> out_y
|
||||
* ^ |
|
||||
* | |
|
||||
* uv -------------- `----------> out_uv
|
||||
*
|
||||
*
|
||||
* 1) Collect yuv mat from two planes, uv plain in two times less than y plane
|
||||
* so, upsample uv in tow times, with bilinear interpolation
|
||||
*
|
||||
* 2) Render primitives on YUV
|
||||
*
|
||||
* 3) Convert yuv to NV12 (using bilinear interpolation)
|
||||
*
|
||||
*/
|
||||
|
||||
// NV12 -> YUV
|
||||
cv::Mat upsample_uv, yuv;
|
||||
cv::resize(in_uv, upsample_uv, in_uv.size() * 2, cv::INTER_LINEAR);
|
||||
cv::merge(std::vector<cv::Mat>{in_y, upsample_uv}, yuv);
|
||||
|
||||
cv::gapi::wip::draw::drawPrimitivesOCVYUV(yuv, prims);
|
||||
|
||||
// YUV -> NV12
|
||||
cv::Mat out_u, out_v, uv_plane;
|
||||
std::vector<cv::Mat> chs = {out_y, out_u, out_v};
|
||||
cv::split(yuv, chs);
|
||||
cv::merge(std::vector<cv::Mat>{chs[1], chs[2]}, uv_plane);
|
||||
cv::resize(uv_plane, out_uv, uv_plane.size() / 2, cv::INTER_LINEAR);
|
||||
}
|
||||
};
|
||||
|
||||
cv::gapi::GKernelPackage cv::gapi::render::ocv::kernels()
|
||||
{
|
||||
const static auto pkg = cv::gapi::kernels<RenderBGRImpl, RenderNV12Impl>();
|
||||
return pkg;
|
||||
}
|
55
modules/gapi/src/backends/render/grenderocv.hpp
Normal file
55
modules/gapi/src/backends/render/grenderocv.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2019 Intel Corporation
|
||||
|
||||
#ifndef OPENCV_GAPI_GRENDEROCV_HPP
|
||||
#define OPENCV_GAPI_GRENDEROCV_HPP
|
||||
|
||||
#include <opencv2/gapi/cpu/gcpukernel.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace gapi
|
||||
{
|
||||
namespace render
|
||||
{
|
||||
namespace ocv
|
||||
{
|
||||
|
||||
GAPI_EXPORTS cv::gapi::GBackend backend();
|
||||
|
||||
template<typename, typename>
|
||||
struct add_type_to_tuple;
|
||||
|
||||
template<typename P, typename ...Ts>
|
||||
struct add_type_to_tuple<P, std::tuple<Ts...>>
|
||||
{
|
||||
using type = std::tuple<Ts..., P>;
|
||||
};
|
||||
|
||||
template<class Impl, class K>
|
||||
class GRenderKernelImpl: public cv::detail::OCVCallHelper<Impl, typename K::InArgs, typename K::OutArgs>,
|
||||
public cv::detail::KernelTag
|
||||
{
|
||||
// TODO Use this mechanism for adding new parameter to run method
|
||||
// using InArgs = typename add_type_to_tuple<IBitMaskCreator, typename K::InArgs>::type;
|
||||
using InArgs = typename K::InArgs;
|
||||
using P = detail::OCVCallHelper<Impl, InArgs, typename K::OutArgs>;
|
||||
|
||||
public:
|
||||
using API = K;
|
||||
|
||||
static cv::gapi::GBackend backend() { return cv::gapi::render::ocv::backend(); }
|
||||
static cv::GCPUKernel kernel() { return GCPUKernel(&P::call); }
|
||||
};
|
||||
|
||||
#define GAPI_RENDER_OCV_KERNEL(Name, API) struct Name: public cv::gapi::render::ocv::GRenderKernelImpl<Name, API>
|
||||
|
||||
} // namespace ocv
|
||||
} // namespace render
|
||||
} // namespace gapi
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GRENDEROCV_HPP
|
141
modules/gapi/src/backends/render/grenderocvbackend.cpp
Normal file
141
modules/gapi/src/backends/render/grenderocvbackend.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
// 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/garray.hpp>
|
||||
#include <opencv2/gapi/util/any.hpp>
|
||||
#include <opencv2/gapi/gtype_traits.hpp>
|
||||
|
||||
#include "compiler/gobjref.hpp"
|
||||
#include "compiler/gmodel.hpp"
|
||||
|
||||
#include "api/gbackend_priv.hpp" // FIXME: Make it part of Backend SDK!
|
||||
#include "api/render_ocv.hpp"
|
||||
|
||||
#include "backends/render/grenderocvbackend.hpp"
|
||||
|
||||
|
||||
using GRenderModel = ade::TypedGraph
|
||||
< cv::gimpl::render::ocv::RenderUnit
|
||||
>;
|
||||
|
||||
// FIXME: Same issue with Typed and ConstTyped
|
||||
using GConstRenderModel = ade::ConstTypedGraph
|
||||
< cv::gimpl::render::ocv::RenderUnit
|
||||
>;
|
||||
|
||||
cv::gimpl::render::ocv::GRenderExecutable::GRenderExecutable(const ade::Graph &g,
|
||||
const std::vector<ade::NodeHandle> &nodes)
|
||||
: m_g(g), m_gm(m_g) {
|
||||
GConstRenderModel gcm(m_g);
|
||||
|
||||
auto is_op = [&](ade::NodeHandle nh) {
|
||||
return m_gm.metadata(nh).get<NodeType>().t == NodeType::OP;
|
||||
};
|
||||
|
||||
auto it = ade::util::find_if(nodes, is_op);
|
||||
|
||||
GAPI_Assert(it != nodes.end());
|
||||
this_nh = *it;
|
||||
|
||||
if (!std::none_of(std::next(it), nodes.end(), is_op)) {
|
||||
util::throw_error(std::logic_error("Multi-node rendering is not supported!"));
|
||||
}
|
||||
}
|
||||
|
||||
void cv::gimpl::render::ocv::GRenderExecutable::run(std::vector<InObj> &&input_objs,
|
||||
std::vector<OutObj> &&output_objs) {
|
||||
GConstRenderModel gcm(m_g);
|
||||
|
||||
for (auto& it : input_objs) magazine::bindInArg (m_res, it.first, it.second);
|
||||
for (auto& it : output_objs) magazine::bindOutArg(m_res, it.first, it.second);
|
||||
|
||||
const auto &op = m_gm.metadata(this_nh).get<Op>();
|
||||
|
||||
// Initialize kernel's execution context:
|
||||
// - Input parameters
|
||||
GCPUContext 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(&GRenderExecutable::packArg, this, _1));
|
||||
|
||||
// - Output parameters.
|
||||
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);
|
||||
}
|
||||
|
||||
auto k = gcm.metadata(this_nh).get<RenderUnit>().k;
|
||||
|
||||
k.apply(context);
|
||||
|
||||
for (auto &it : output_objs) magazine::writeBack(m_res, it.first, it.second);
|
||||
}
|
||||
|
||||
cv::GArg cv::gimpl::render::ocv::GRenderExecutable::packArg(const cv::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) {
|
||||
util::throw_error(std::logic_error("Render supports G-types ONLY!"));
|
||||
}
|
||||
GAPI_Assert(arg.kind == cv::detail::ArgKind::GOBJREF);
|
||||
|
||||
const cv::gimpl::RcDesc &ref = arg.get<cv::gimpl::RcDesc>();
|
||||
switch (ref.shape)
|
||||
{
|
||||
case GShape::GMAT: return GArg(m_res.slot<cv::gapi::own::Mat>()[ref.id]);
|
||||
case GShape::GARRAY: return GArg(m_res.slot<cv::detail::VectorRef>().at(ref.id));
|
||||
default:
|
||||
util::throw_error(std::logic_error("Unsupported GShape type"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
class GRenderBackendImpl final: public cv::gapi::GBackend::Priv {
|
||||
virtual void unpackKernel(ade::Graph &gr,
|
||||
const ade::NodeHandle &op_node,
|
||||
const cv::GKernelImpl &impl) override {
|
||||
GRenderModel rm(gr);
|
||||
//auto render_impl = cv::util::any_cast<cv::gapi::render::ocv::KImpl>(impl.opaque);
|
||||
auto render_impl = cv::util::any_cast<cv::GCPUKernel>(impl.opaque);
|
||||
rm.metadata(op_node).set(cv::gimpl::render::ocv::RenderUnit{render_impl});
|
||||
}
|
||||
|
||||
virtual EPtr compile(const ade::Graph &graph,
|
||||
const cv::GCompileArgs&,
|
||||
const std::vector<ade::NodeHandle> &nodes) const override {
|
||||
|
||||
return EPtr{new cv::gimpl::render::ocv::GRenderExecutable(graph, nodes)};
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
cv::gapi::GBackend cv::gapi::render::ocv::backend() {
|
||||
static cv::gapi::GBackend this_backend(std::make_shared<GRenderBackendImpl>());
|
||||
return this_backend;
|
||||
}
|
71
modules/gapi/src/backends/render/grenderocvbackend.hpp
Normal file
71
modules/gapi/src/backends/render/grenderocvbackend.hpp
Normal file
@ -0,0 +1,71 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2019 Intel Corporation
|
||||
|
||||
#ifndef OPENCV_GAPI_GRENDEROCVBACKEND_HPP
|
||||
#define OPENCV_GAPI_GRENDEROCVBACKEND_HPP
|
||||
|
||||
#include <opencv2/gapi/garg.hpp>
|
||||
#include <opencv2/gapi/gproto.hpp>
|
||||
#include <opencv2/gapi/render/render.hpp>
|
||||
|
||||
#include "api/gorigin.hpp"
|
||||
#include "backends/common/gbackend.hpp"
|
||||
#include "compiler/gislandmodel.hpp"
|
||||
|
||||
#include "backends/render/grenderocv.hpp"
|
||||
|
||||
#include <opencv2/gapi/cpu/gcpukernel.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace gimpl
|
||||
{
|
||||
namespace render
|
||||
{
|
||||
namespace ocv
|
||||
{
|
||||
|
||||
struct RenderUnit
|
||||
{
|
||||
static const char *name() { return "RenderUnit"; }
|
||||
GCPUKernel k;
|
||||
};
|
||||
|
||||
class GRenderExecutable final: public GIslandExecutable
|
||||
{
|
||||
const ade::Graph &m_g;
|
||||
GModel::ConstGraph m_gm;
|
||||
|
||||
// The only executable stuff in this graph
|
||||
// (assuming it is always single-op)
|
||||
ade::NodeHandle this_nh;
|
||||
|
||||
//// Actual data of all resources in graph (both internal and external)
|
||||
Mag m_res;
|
||||
|
||||
//// Execution helpers
|
||||
GArg packArg(const GArg &arg);
|
||||
|
||||
public:
|
||||
GRenderExecutable(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 {
|
||||
GAPI_Assert(false); // Not implemented yet
|
||||
}
|
||||
|
||||
virtual void run(std::vector<InObj> &&input_objs,
|
||||
std::vector<OutObj> &&output_objs) override;
|
||||
};
|
||||
|
||||
} // namespace ocv
|
||||
} // namespace render
|
||||
} // namespace gimpl
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GRENDEROCVBACKEND_HPP
|
@ -42,6 +42,7 @@
|
||||
// </FIXME:>
|
||||
|
||||
#include <opencv2/gapi/gcompoundkernel.hpp> // compound::backend()
|
||||
#include <opencv2/gapi/render/render.hpp> // render::ocv::backend()
|
||||
|
||||
#include "logger.hpp"
|
||||
|
||||
@ -63,11 +64,14 @@ namespace
|
||||
|
||||
static auto ocv_pkg =
|
||||
#if !defined(GAPI_STANDALONE)
|
||||
combine(cv::gapi::core::cpu::kernels(),
|
||||
cv::gapi::imgproc::cpu::kernels());
|
||||
// FIXME add N-arg version combine
|
||||
combine(combine(cv::gapi::core::cpu::kernels(),
|
||||
cv::gapi::imgproc::cpu::kernels()),
|
||||
cv::gapi::render::ocv::kernels());
|
||||
#else
|
||||
cv::gapi::GKernelPackage();
|
||||
#endif // !defined(GAPI_STANDALONE)
|
||||
|
||||
auto user_pkg = cv::gimpl::getCompileArg<cv::gapi::GKernelPackage>(args);
|
||||
auto user_pkg_with_aux = withAuxKernels(user_pkg.value_or(cv::gapi::GKernelPackage{}));
|
||||
return combine(ocv_pkg, user_pkg_with_aux);
|
||||
@ -202,8 +206,9 @@ cv::gimpl::GCompiler::GCompiler(const cv::GComputation &c,
|
||||
};
|
||||
take(kernels_to_use.backends());
|
||||
take(networks_to_use.backends());
|
||||
m_all_kernels = cv::gapi::combine(kernels_to_use,
|
||||
auxKernelsFrom(all_backends));
|
||||
|
||||
m_all_kernels = cv::gapi::combine(kernels_to_use,
|
||||
auxKernelsFrom(all_backends));
|
||||
// NB: The expectation in the line above is that
|
||||
// NN backends (present here via network package) always add their
|
||||
// inference kernels via auxiliary...()
|
||||
|
@ -78,7 +78,7 @@ protected:
|
||||
cv::Mat y_mat_ocv, uv_mat_ocv, y_mat_gapi, uv_mat_gapi, mat_ocv, mat_gapi;
|
||||
};
|
||||
|
||||
using TestArgs = std::tuple<cv::Size,cv::gapi::wip::draw::Prims,cv::gapi::GKernelPackage>;
|
||||
using TestArgs = std::tuple<cv::Size,cv::gapi::wip::draw::Prims>;
|
||||
|
||||
struct RenderNV12 : public RenderWithParam<TestArgs>
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
#ifndef OPENCV_GAPI_RENDER_TESTS_INL_HPP
|
||||
#define OPENCV_GAPI_RENDER_TESTS_INL_HPP
|
||||
|
||||
#include <opencv2/gapi/render.hpp>
|
||||
#include <opencv2/gapi/render/render.hpp>
|
||||
#include "gapi_render_tests.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
@ -16,11 +16,11 @@ namespace opencv_test
|
||||
|
||||
TEST_P(RenderNV12, AccuracyTest)
|
||||
{
|
||||
std::tie(sz, prims, pkg) = GetParam();
|
||||
std::tie(sz, prims) = GetParam();
|
||||
Init();
|
||||
|
||||
cv::gapi::wip::draw::BGR2NV12(mat_gapi, y_mat_gapi, uv_mat_gapi);
|
||||
cv::gapi::wip::draw::render(y_mat_gapi, uv_mat_gapi, prims, pkg);
|
||||
cv::gapi::wip::draw::render(y_mat_gapi, uv_mat_gapi, prims);
|
||||
|
||||
ComputeRef();
|
||||
|
||||
@ -30,10 +30,10 @@ TEST_P(RenderNV12, AccuracyTest)
|
||||
|
||||
TEST_P(RenderBGR, AccuracyTest)
|
||||
{
|
||||
std::tie(sz, prims, pkg) = GetParam();
|
||||
std::tie(sz, prims) = GetParam();
|
||||
Init();
|
||||
|
||||
cv::gapi::wip::draw::render(mat_gapi, prims, pkg);
|
||||
cv::gapi::wip::draw::render(mat_gapi, prims);
|
||||
ComputeRef();
|
||||
|
||||
EXPECT_EQ(0, cv::norm(mat_gapi, mat_ocv));
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <opencv2/gapi/util/util.hpp>
|
||||
|
||||
#include "gapi_tests_helpers.hpp"
|
||||
#include <opencv2/gapi/render.hpp>
|
||||
#include <opencv2/gapi/render/render.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -11,92 +11,76 @@
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
#define OCV cv::gapi::ocv::kernels()
|
||||
|
||||
/* NV12 test cases */
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVRects, RenderNV12,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(rects),
|
||||
Values(OCV)));
|
||||
Values(rects)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVCircles, RenderNV12,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(circles),
|
||||
Values(OCV)));
|
||||
Values(circles)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVLines, RenderNV12,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(lines),
|
||||
Values(OCV)));
|
||||
Values(lines)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVMosaics, RenderNV12,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(mosaics),
|
||||
Values(OCV)));
|
||||
Values(mosaics)));
|
||||
|
||||
// FIXME difference in color
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVImages, RenderNV12,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(images),
|
||||
Values(OCV)));
|
||||
Values(images)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVPolygons, RenderNV12,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(polygons),
|
||||
Values(OCV)));
|
||||
Values(polygons)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVTexts, RenderNV12,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(texts),
|
||||
Values(OCV)));
|
||||
Values(texts)));
|
||||
|
||||
/* BGR test cases */
|
||||
INSTANTIATE_TEST_CASE_P(RenderBGROCVRects, RenderBGR,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(rects),
|
||||
Values(OCV)));
|
||||
Values(rects)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderBGROCVCircles, RenderBGR,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(circles),
|
||||
Values(OCV)));
|
||||
Values(circles)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderBGROCVLines, RenderBGR,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(lines),
|
||||
Values(OCV)));
|
||||
Values(lines)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderBGROCVMosaics, RenderBGR,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(mosaics),
|
||||
Values(OCV)));
|
||||
Values(mosaics)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderBGROCVImages, RenderBGR,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(images),
|
||||
Values(OCV)));
|
||||
Values(images)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderBGROCVPolygons, RenderBGR,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(polygons),
|
||||
Values(OCV)));
|
||||
Values(polygons)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderBGROCVTexts, RenderBGR,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(texts),
|
||||
Values(OCV)));
|
||||
Values(texts)));
|
||||
}
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <ade/util/iota_range.hpp>
|
||||
#include "logger.hpp"
|
||||
|
||||
#include <opencv2/gapi/render/render.hpp>
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
@ -313,5 +315,4 @@ TEST(GAPI_Pipeline, CanUseOwnMatAsOutput)
|
||||
// FIXME add overload for apply(cv::gapi::own::Mat in, cv::gapi::own::Mat& out)
|
||||
EXPECT_NO_THROW(comp.apply({in_own_mat}, {out_own_mat}));
|
||||
}
|
||||
|
||||
} // namespace opencv_test
|
||||
|
Loading…
Reference in New Issue
Block a user