diff --git a/modules/gapi/include/opencv2/gapi/fluid/gfluidkernel.hpp b/modules/gapi/include/opencv2/gapi/fluid/gfluidkernel.hpp index 79c5c5f347..b454e854f9 100644 --- a/modules/gapi/include/opencv2/gapi/fluid/gfluidkernel.hpp +++ b/modules/gapi/include/opencv2/gapi/fluid/gfluidkernel.hpp @@ -154,6 +154,15 @@ template<> struct fluid_get_in } #endif // !defined(GAPI_STANDALONE) }; + +template struct fluid_get_in> +{ + static const std::vector& get(const cv::GArgs &in_args, int idx) + { + return in_args.at(idx).unsafe_get().rref(); + } +}; + template struct fluid_get_in { static const T& get(const cv::GArgs &in_args, int idx) @@ -250,6 +259,7 @@ template struct FluidCallHelper, std::tuple, UseScratch> { static_assert(all_satisfy::value, "return type must be GMat"); + static_assert(contains::value, "input must contain at least one GMat"); // Execution dispatcher //////////////////////////////////////////////////// template diff --git a/modules/gapi/src/backends/fluid/gfluidbackend.cpp b/modules/gapi/src/backends/fluid/gfluidbackend.cpp index 6e2f1aa589..283db59296 100644 --- a/modules/gapi/src/backends/fluid/gfluidbackend.cpp +++ b/modules/gapi/src/backends/fluid/gfluidbackend.cpp @@ -1229,6 +1229,7 @@ void cv::gimpl::GFluidExecutable::bindInArg(const cv::gimpl::RcDesc &rc, const G { case GShape::GMAT: m_buffers[m_id_map.at(rc.id)].priv().bindTo(util::get(arg), true); break; case GShape::GSCALAR: m_res.slot()[rc.id] = util::get(arg); break; + case GShape::GARRAY: m_res.slot()[rc.id] = util::get(arg); break; default: util::throw_error(std::logic_error("Unsupported GShape type")); } } @@ -1254,7 +1255,8 @@ void cv::gimpl::GFluidExecutable::bindOutArg(const cv::gimpl::RcDesc &rc, const void cv::gimpl::GFluidExecutable::packArg(cv::GArg &in_arg, const cv::GArg &op_arg) { GAPI_Assert(op_arg.kind != cv::detail::ArgKind::GMAT - && op_arg.kind != cv::detail::ArgKind::GSCALAR); + && op_arg.kind != cv::detail::ArgKind::GSCALAR + && op_arg.kind != cv::detail::ArgKind::GARRAY); if (op_arg.kind == cv::detail::ArgKind::GOBJREF) { @@ -1263,6 +1265,10 @@ void cv::gimpl::GFluidExecutable::packArg(cv::GArg &in_arg, const cv::GArg &op_a { in_arg = GArg(m_res.slot()[ref.id]); } + else if (ref.shape == GShape::GARRAY) + { + in_arg = GArg(m_res.slot()[ref.id]); + } } } diff --git a/modules/gapi/src/backends/fluid/gfluidbackend.hpp b/modules/gapi/src/backends/fluid/gfluidbackend.hpp index 7923f0c003..a2c853a961 100644 --- a/modules/gapi/src/backends/fluid/gfluidbackend.hpp +++ b/modules/gapi/src/backends/fluid/gfluidbackend.hpp @@ -128,7 +128,7 @@ class GFluidExecutable final: public GIslandExecutable std::vector m_script; - using Magazine = detail::magazine; + using Magazine = detail::magazine; Magazine m_res; std::size_t m_num_int_buffers; // internal buffers counter (m_buffers - num_scratch) diff --git a/modules/gapi/test/gapi_fluid_test.cpp b/modules/gapi/test/gapi_fluid_test.cpp index baccb5802d..faca309ba4 100644 --- a/modules/gapi/test/gapi_fluid_test.cpp +++ b/modules/gapi/test/gapi_fluid_test.cpp @@ -244,6 +244,26 @@ TEST(Fluid, Sum_2_Mats_And_Scalar) EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat)); } +TEST(Fluid, EqualizeHist) +{ + cv::GMat in, out; + cv::GComputation c(cv::GIn(in), cv::GOut(TEqualizeHist::on(in, TCalcHist::on(in)))); + + cv::Mat in_mat(320, 480, CV_8UC1), + out_mat(320, 480, CV_8UC1), + ref_mat(320, 480, CV_8UC1); + + cv::randu(in_mat, 200, 240); + + auto cc = c.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage)); + + cc(cv::gin(in_mat), cv::gout(out_mat)); + + cv::equalizeHist(in_mat, ref_mat); + + EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat)); +} + TEST(Fluid, Split3) { cv::GMat bgr; diff --git a/modules/gapi/test/gapi_fluid_test_kernels.cpp b/modules/gapi/test/gapi_fluid_test_kernels.cpp index 7c4904cc5e..83813842eb 100644 --- a/modules/gapi/test/gapi_fluid_test_kernels.cpp +++ b/modules/gapi/test/gapi_fluid_test_kernels.cpp @@ -7,6 +7,7 @@ #include "test_precomp.hpp" #include +#include #include "gapi_fluid_test_kernels.hpp" #include #include @@ -448,6 +449,56 @@ GAPI_FLUID_KERNEL(FSum2MatsAndScalar, TSum2MatsAndScalar, false) } }; +GAPI_FLUID_KERNEL(FEqualizeHist, TEqualizeHist, false) +{ + static const int Window = 1; + static const int LPI = 2; + + static void run(const cv::gapi::fluid::View &mat, + const std::vector &arr, + cv::gapi::fluid::Buffer &out) + { + for (int l = 0, lpi = out.lpi(); l < lpi; l++) + { + const uint8_t* in_row = mat.InLine (l); + uint8_t* out_row = out.OutLine(l); + + for (int i = 0, w = mat.length(); i < w; i++) + { + out_row[i] = static_cast(arr[in_row[i]]); + } + } + } +}; + +GAPI_OCV_KERNEL(OCVCalcHist, TCalcHist) +{ + static void run(const cv::Mat& in, std::vector& out) + { + out = std::vector(256, 0); + + // Calculate normalized accumulated integral transformation array for gapi + for(int i = 0; i < in.rows; ++i) + for(int j = 0; j < in.cols; ++j) + ++out[in.at(i, j)]; + + for(unsigned int i = 1; i < out.size(); ++i) + out[i] += out[i-1]; + + int size = in.size().width * in.size().height; + int min = size; + for(unsigned int i = 0; i < out.size(); ++i) + if(out[i] != 0 && out[i] < min) + min = out[i]; + + for(auto & el : out) + { + // General histogram equalization formula + el = cvRound(((float)(el - min) / (float)(size - min))*255); + } + } +}; + static const int ITUR_BT_601_CY = 1220542; static const int ITUR_BT_601_CUB = 2116026; static const int ITUR_BT_601_CUG = -409993; @@ -569,6 +620,8 @@ cv::gapi::GKernelPackage fluidTestPackage = cv::gapi::kernels ,FSum2MatsAndScalar ,FTestSplit3 ,FTestSplit3_4lpi + ,FEqualizeHist + ,OCVCalcHist >(); } // namespace gapi_test_kernels } // namespace cv diff --git a/modules/gapi/test/gapi_fluid_test_kernels.hpp b/modules/gapi/test/gapi_fluid_test_kernels.hpp index dfb88225bb..ba55e12d21 100644 --- a/modules/gapi/test/gapi_fluid_test_kernels.hpp +++ b/modules/gapi/test/gapi_fluid_test_kernels.hpp @@ -15,6 +15,7 @@ namespace cv namespace gapi_test_kernels { using cv::gapi::core::GMat3; +using GMat2 = std::tuple; G_TYPED_KERNEL(TAddSimple, , "test.fluid.add_simple") { static cv::GMatDesc outMeta(cv::GMatDesc a, cv::GMatDesc) { @@ -112,6 +113,20 @@ G_TYPED_KERNEL_M(TSplit3_4lpi, , "test.fluid.split3_4lpi") { } }; +G_TYPED_KERNEL(TEqualizeHist, )>, "test.fluid.equalize_hist") +{ + static GMatDesc outMeta(GMatDesc in, const cv::GArrayDesc&) { + return in; + } +}; + +G_TYPED_KERNEL(TCalcHist, (GMat)>, "test.ocv.calc_hist") +{ + static GArrayDesc outMeta(GMatDesc) { + return {}; + } +}; + GMat merge3_4lpi(const GMat& src1, const GMat& src2, const GMat& src3); std::tuple split3_4lpi(const GMat& src);