diff --git a/modules/gapi/CMakeLists.txt b/modules/gapi/CMakeLists.txt index 137894cb8f..82b719ad4e 100644 --- a/modules/gapi/CMakeLists.txt +++ b/modules/gapi/CMakeLists.txt @@ -77,7 +77,6 @@ set(gapi_srcs src/api/render.cpp src/api/render_ocv.cpp src/api/ginfer.cpp - src/api/ft_render.cpp src/api/media.cpp src/api/rmat.cpp @@ -131,8 +130,8 @@ set(gapi_srcs src/backends/ie/giebackend/giewrapper.cpp # Render Backend. - src/backends/render/grenderocvbackend.cpp src/backends/render/grenderocv.cpp + src/backends/render/ft_render.cpp #PlaidML Backend src/backends/plaidml/gplaidmlcore.cpp diff --git a/modules/gapi/src/api/render_ocv.cpp b/modules/gapi/src/api/render_ocv.cpp index a298a958bd..5ab2e1dd07 100644 --- a/modules/gapi/src/api/render_ocv.cpp +++ b/modules/gapi/src/api/render_ocv.cpp @@ -2,7 +2,7 @@ #include // Kernel API's #include "api/render_ocv.hpp" -#include "api/ft_render.hpp" +#include "backends/render/ft_render.hpp" namespace cv { @@ -146,12 +146,8 @@ struct EmptyConverter template void drawPrimitivesOCV(cv::Mat& in, const cv::gapi::wip::draw::Prims& prims, - cv::gapi::wip::draw::FTTextRender* ftpr) + std::shared_ptr& ftpr) { -#ifndef HAVE_FREETYPE - cv::util::suppress_unused_warning(ftpr); -#endif - using namespace cv::gapi::wip::draw; ColorConverter converter; @@ -177,7 +173,6 @@ void drawPrimitivesOCV(cv::Mat& in, case Prim::index_of(): { -#ifdef HAVE_FREETYPE const auto& ftp = cv::util::get(p); const auto color = converter.cvtColor(ftp.color); @@ -196,9 +191,6 @@ void drawPrimitivesOCV(cv::Mat& in, cv::Point tl(ftp.org.x, ftp.org.y - mask.size().height + baseline); blendTextMask(in, mask, tl, color); -#else - cv::util::throw_error(std::runtime_error("FreeType not found !")); -#endif break; } @@ -251,16 +243,16 @@ void drawPrimitivesOCV(cv::Mat& in, } } -void drawPrimitivesOCVBGR(cv::Mat &in, - const cv::gapi::wip::draw::Prims &prims, - cv::gapi::wip::draw::FTTextRender* ftpr) +void drawPrimitivesOCVBGR(cv::Mat &in, + const cv::gapi::wip::draw::Prims &prims, + std::shared_ptr &ftpr) { drawPrimitivesOCV(in, prims, ftpr); } -void drawPrimitivesOCVYUV(cv::Mat &in, - const cv::gapi::wip::draw::Prims &prims, - cv::gapi::wip::draw::FTTextRender* ftpr) +void drawPrimitivesOCVYUV(cv::Mat &in, + const cv::gapi::wip::draw::Prims &prims, + std::shared_ptr &ftpr) { drawPrimitivesOCV(in, prims, ftpr); } diff --git a/modules/gapi/src/api/render_ocv.hpp b/modules/gapi/src/api/render_ocv.hpp index 91194dcdc1..a9a98f93fb 100644 --- a/modules/gapi/src/api/render_ocv.hpp +++ b/modules/gapi/src/api/render_ocv.hpp @@ -1,6 +1,6 @@ #include #include "render_priv.hpp" -#include "ft_render.hpp" +#include "backends/render/ft_render.hpp" #ifndef OPENCV_RENDER_OCV_HPP #define OPENCV_RENDER_OCV_HPP @@ -15,8 +15,8 @@ namespace draw { // FIXME only for tests -void GAPI_EXPORTS drawPrimitivesOCVYUV(cv::Mat& yuv, const Prims& prims, cv::gapi::wip::draw::FTTextRender* mc); -void GAPI_EXPORTS drawPrimitivesOCVBGR(cv::Mat& bgr, const Prims& prims, cv::gapi::wip::draw::FTTextRender* mc); +void GAPI_EXPORTS drawPrimitivesOCVYUV(cv::Mat& yuv, const Prims& prims, std::shared_ptr& mc); +void GAPI_EXPORTS drawPrimitivesOCVBGR(cv::Mat& bgr, const Prims& prims, std::shared_ptr& mc); } // namespace draw } // namespace wip diff --git a/modules/gapi/src/api/ft_render.cpp b/modules/gapi/src/backends/render/ft_render.cpp similarity index 92% rename from modules/gapi/src/api/ft_render.cpp rename to modules/gapi/src/backends/render/ft_render.cpp index 7561dff833..fcf84713ff 100644 --- a/modules/gapi/src/api/ft_render.cpp +++ b/modules/gapi/src/backends/render/ft_render.cpp @@ -5,11 +5,11 @@ // Copyright (C) 2019 Intel Corporation #include "precomp.hpp" +#include "ft_render.hpp" #ifdef HAVE_FREETYPE -#include "api/ft_render.hpp" -#include "api/ft_render_priv.hpp" +#include "ft_render_priv.hpp" #include #include @@ -166,6 +166,11 @@ void cv::gapi::wip::draw::FTTextRender::Priv::putText(cv::Mat& mat, "Failed to load char"); FT_Bitmap *bitmap = &(m_face->glyph->bitmap); + // FIXME: Skip glyph, if size is 0 + if (bitmap->rows == 0 || bitmap->width == 0) { + continue; + } + cv::Mat glyph(bitmap->rows, bitmap->width, CV_8UC1, bitmap->buffer, bitmap->pitch); int left = m_face->glyph->bitmap_left; @@ -211,4 +216,21 @@ void cv::gapi::wip::draw::FTTextRender::putText(cv::Mat& mat, m_priv->putText(mat, text, org, fh); } +#else + +cv::Size cv::gapi::wip::draw::FTTextRender::getTextSize(const std::wstring&, int, int*) +{ + cv::util::throw_error(std::runtime_error("Freetype not found")); +} + +void cv::gapi::wip::draw::FTTextRender::putText(cv::Mat&, const std::wstring&, const cv::Point&, int) +{ + cv::util::throw_error(std::runtime_error("Freetype not found")); +} + +cv::gapi::wip::draw::FTTextRender::FTTextRender(const std::string&) +{ + cv::util::throw_error(std::runtime_error("Freetype not found")); +} + #endif // HAVE_FREETYPE diff --git a/modules/gapi/src/api/ft_render.hpp b/modules/gapi/src/backends/render/ft_render.hpp similarity index 91% rename from modules/gapi/src/api/ft_render.hpp rename to modules/gapi/src/backends/render/ft_render.hpp index 2556c7269c..068c0d4d3f 100644 --- a/modules/gapi/src/api/ft_render.hpp +++ b/modules/gapi/src/backends/render/ft_render.hpp @@ -23,8 +23,6 @@ namespace wip namespace draw { -#ifdef HAVE_FREETYPE - class GAPI_EXPORTS FTTextRender { public: @@ -38,12 +36,6 @@ private: std::shared_ptr m_priv; }; -#else - -class GAPI_EXPORTS FTTextRender {}; - -#endif // HAVE_FREETYPE - } // namespace draw } // namespace wip } // namespace gapi diff --git a/modules/gapi/src/api/ft_render_priv.hpp b/modules/gapi/src/backends/render/ft_render_priv.hpp similarity index 96% rename from modules/gapi/src/api/ft_render_priv.hpp rename to modules/gapi/src/backends/render/ft_render_priv.hpp index 5a0679dd99..903f439b96 100644 --- a/modules/gapi/src/api/ft_render_priv.hpp +++ b/modules/gapi/src/backends/render/ft_render_priv.hpp @@ -10,7 +10,7 @@ #ifndef OPENCV_FT_RENDER_PRIV_HPP #define OPENCV_FT_RENDER_PRIV_HPP -#include "api/ft_render.hpp" +#include "ft_render.hpp" #include #include FT_FREETYPE_H diff --git a/modules/gapi/src/backends/render/grenderocv.cpp b/modules/gapi/src/backends/render/grenderocv.cpp index cb4fd1be3a..71be889d79 100644 --- a/modules/gapi/src/backends/render/grenderocv.cpp +++ b/modules/gapi/src/backends/render/grenderocv.cpp @@ -1,16 +1,21 @@ #include #include "api/render_ocv.hpp" -#include "backends/render/grenderocv.hpp" #include +#include -GAPI_RENDER_OCV_KERNEL(RenderBGROCVImpl, cv::gapi::wip::draw::GRenderBGR) +struct RenderOCVState +{ + std::shared_ptr ftpr; +}; + +GAPI_OCV_KERNEL_ST(RenderBGROCVImpl, cv::gapi::wip::draw::GRenderBGR, RenderOCVState) { static void run(const cv::Mat& in, const cv::gapi::wip::draw::Prims& prims, - cv::gapi::wip::draw::FTTextRender* ftpr, - cv::Mat& out) + cv::Mat& out, + RenderOCVState& state) { // NB: If in and out cv::Mats are the same object // we can avoid copy and render on out cv::Mat @@ -19,18 +24,33 @@ GAPI_RENDER_OCV_KERNEL(RenderBGROCVImpl, cv::gapi::wip::draw::GRenderBGR) in.copyTo(out); } - cv::gapi::wip::draw::drawPrimitivesOCVBGR(out, prims, ftpr); + cv::gapi::wip::draw::drawPrimitivesOCVBGR(out, prims, state.ftpr); + } + + static void setup(const cv::GMatDesc& /* in */, + const cv::GArrayDesc& /* prims */, + std::shared_ptr& state, + const cv::GCompileArgs& args) + { + using namespace cv::gapi::wip::draw; + auto opt_freetype_font = cv::gapi::getCompileArg(args); + state = std::make_shared(); + + if (opt_freetype_font.has_value()) + { + state->ftpr = std::make_shared(opt_freetype_font->path); + } } }; -GAPI_RENDER_OCV_KERNEL(RenderNV12OCVImpl, cv::gapi::wip::draw::GRenderNV12) +GAPI_OCV_KERNEL_ST(RenderNV12OCVImpl, cv::gapi::wip::draw::GRenderNV12, RenderOCVState) { static void run(const cv::Mat& in_y, const cv::Mat& in_uv, const cv::gapi::wip::draw::Prims& prims, - cv::gapi::wip::draw::FTTextRender* ftpr, cv::Mat& out_y, - cv::Mat& out_uv) + cv::Mat& out_uv, + RenderOCVState& state) { // NB: If in and out cv::Mats are the same object // we can avoid copy and render on out cv::Mat @@ -67,7 +87,7 @@ GAPI_RENDER_OCV_KERNEL(RenderNV12OCVImpl, cv::gapi::wip::draw::GRenderNV12) cv::resize(in_uv, upsample_uv, in_uv.size() * 2, cv::INTER_LINEAR); cv::merge(std::vector{in_y, upsample_uv}, yuv); - cv::gapi::wip::draw::drawPrimitivesOCVYUV(yuv, prims, ftpr); + cv::gapi::wip::draw::drawPrimitivesOCVYUV(yuv, prims, state.ftpr); // YUV -> NV12 cv::Mat out_u, out_v, uv_plane; @@ -76,6 +96,22 @@ GAPI_RENDER_OCV_KERNEL(RenderNV12OCVImpl, cv::gapi::wip::draw::GRenderNV12) cv::merge(std::vector{chs[1], chs[2]}, uv_plane); cv::resize(uv_plane, out_uv, uv_plane.size() / 2, cv::INTER_LINEAR); } + + static void setup(const cv::GMatDesc& /* in_y */, + const cv::GMatDesc& /* in_uv */, + const cv::GArrayDesc& /* prims */, + std::shared_ptr& state, + const cv::GCompileArgs& args) + { + using namespace cv::gapi::wip::draw; + auto has_freetype_font = cv::gapi::getCompileArg(args); + state = std::make_shared(); + + if (has_freetype_font) + { + state->ftpr = std::make_shared(has_freetype_font->path); + } + } }; cv::gapi::GKernelPackage cv::gapi::render::ocv::kernels() diff --git a/modules/gapi/src/backends/render/grenderocv.hpp b/modules/gapi/src/backends/render/grenderocv.hpp deleted file mode 100644 index e5091042b2..0000000000 --- a/modules/gapi/src/backends/render/grenderocv.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// 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 -#include "api/render_priv.hpp" -#include "api/ft_render.hpp" - -namespace cv -{ -namespace gapi -{ -namespace render -{ -namespace ocv -{ - -GAPI_EXPORTS cv::gapi::GBackend backend(); - -template -struct add_type_to_tuple; - -template -struct add_type_to_tuple> -{ - using type = std::tuple; -}; - -template -class GRenderKernelImpl: public cv::detail::OCVCallHelper, - public cv::detail::KernelTag -{ - using InArgs = typename add_type_to_tuple::type; - using P = detail::OCVCallHelper; - -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 - -} // namespace ocv -} // namespace render -} // namespace gapi -} // namespace cv - -#endif // OPENCV_GAPI_GRENDEROCV_HPP diff --git a/modules/gapi/src/backends/render/grenderocvbackend.cpp b/modules/gapi/src/backends/render/grenderocvbackend.cpp deleted file mode 100644 index 413d0c3f9c..0000000000 --- a/modules/gapi/src/backends/render/grenderocvbackend.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// 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-2020 Intel Corporation - -#include "precomp.hpp" - -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#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" - -#include -#include "api/ocv_mask_creator.hpp" -#include "api/ft_render.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 &nodes, - std::unique_ptr&& ftpr) - : m_g(g), m_gm(m_g), m_ftpr(std::move(ftpr)) { - GConstRenderModel gcm(m_g); - - auto is_op = [&](ade::NodeHandle nh) { - return m_gm.metadata(nh).get().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 &&input_objs, - std::vector &&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(); - - // 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().k; - - context.m_args.emplace_back(m_ftpr.get()); - - k.m_runF(context); - - for (auto &it : output_objs) magazine::writeBack(m_res, it.first, it.second); - - // In/Out args clean-up is mandatory now with RMat - for (auto &it : input_objs) magazine::unbind(m_res, it.first); - for (auto &it : output_objs) magazine::unbind(m_res, it.first); -} - -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(); - switch (ref.shape) - { - case GShape::GMAT: return GArg(m_res.slot()[ref.id]); - case GShape::GARRAY: return GArg(m_res.slot().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(impl.opaque); - rm.metadata(op_node).set(cv::gimpl::render::ocv::RenderUnit{render_impl}); - } - - virtual EPtr compile(const ade::Graph &graph, - const cv::GCompileArgs& args, - const std::vector &nodes) const override { - - using namespace cv::gapi::wip::draw; - auto has_freetype_font = cv::gapi::getCompileArg(args); - std::unique_ptr ftpr; - if (has_freetype_font) - { -#ifndef HAVE_FREETYPE - throw std::runtime_error("Freetype not found"); -#else - ftpr.reset(new FTTextRender(has_freetype_font.value().path)); -#endif - } - return EPtr{new cv::gimpl::render::ocv::GRenderExecutable(graph, nodes, std::move(ftpr))}; - } - }; -} - -cv::gapi::GBackend cv::gapi::render::ocv::backend() { - static cv::gapi::GBackend this_backend(std::make_shared()); - return this_backend; -} diff --git a/modules/gapi/src/backends/render/grenderocvbackend.hpp b/modules/gapi/src/backends/render/grenderocvbackend.hpp deleted file mode 100644 index 69d388ffe6..0000000000 --- a/modules/gapi/src/backends/render/grenderocvbackend.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// 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 -#include -#include - -#include "api/gorigin.hpp" -#include "backends/common/gbackend.hpp" -#include "compiler/gislandmodel.hpp" - -#include "backends/render/grenderocv.hpp" - -#include - -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; - std::unique_ptr m_ftpr; - - // 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 &nodes, - std::unique_ptr&& ftpr); - - 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 &&input_objs, - std::vector &&output_objs) override; -}; - -} // namespace ocv -} // namespace render -} // namespace gimpl -} // namespace cv - -#endif // OPENCV_GAPI_GRENDEROCVBACKEND_HPP diff --git a/modules/gapi/test/render/ftp_render_test.cpp b/modules/gapi/test/render/ftp_render_test.cpp index 5bdbb74e30..af9c5c6f13 100644 --- a/modules/gapi/test/render/ftp_render_test.cpp +++ b/modules/gapi/test/render/ftp_render_test.cpp @@ -13,7 +13,7 @@ #include -#include "api/ft_render.hpp" +#include "backends/render/ft_render.hpp" namespace opencv_test { diff --git a/modules/gapi/test/render/gapi_render_tests_ocv.cpp b/modules/gapi/test/render/gapi_render_tests_ocv.cpp index f727d977aa..88b5d88075 100644 --- a/modules/gapi/test/render/gapi_render_tests_ocv.cpp +++ b/modules/gapi/test/render/gapi_render_tests_ocv.cpp @@ -95,7 +95,6 @@ TEST_P(RenderNV12OCVTestFTexts, AccuracyTest) cv::compile_args(cv::gapi::wip::draw::freetype_font{ "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc" }))); - } static std::wstring to_wstring(const char* bytes)