Commit 8a7e7467 authored by Alexey Smirnov's avatar Alexey Smirnov Committed by Alexander Alekhin

Merge pull request #15312 from smirnov-alexey:gapi_fluid_garray

* Support GArray as input in fluid kernels

* Create tests on GArray input in fluid

* Some fixes to fully support GArray

* Refactor code and change the kernel according to review

* Add histogram calculation as a G-API kernel

Add assert that input GArgs in fluid contain at least one GMat
parent e98e58c6
...@@ -154,6 +154,15 @@ template<> struct fluid_get_in<cv::GScalar> ...@@ -154,6 +154,15 @@ template<> struct fluid_get_in<cv::GScalar>
} }
#endif // !defined(GAPI_STANDALONE) #endif // !defined(GAPI_STANDALONE)
}; };
template<typename U> struct fluid_get_in<cv::GArray<U>>
{
static const std::vector<U>& get(const cv::GArgs &in_args, int idx)
{
return in_args.at(idx).unsafe_get<cv::detail::VectorRef>().rref<U>();
}
};
template<class T> struct fluid_get_in template<class T> struct fluid_get_in
{ {
static const T& get(const cv::GArgs &in_args, int idx) static const T& get(const cv::GArgs &in_args, int idx)
...@@ -250,6 +259,7 @@ template<typename Impl, typename... Ins, typename... Outs, bool UseScratch> ...@@ -250,6 +259,7 @@ template<typename Impl, typename... Ins, typename... Outs, bool UseScratch>
struct FluidCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>, UseScratch> struct FluidCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>, UseScratch>
{ {
static_assert(all_satisfy<is_gmat_type, Outs...>::value, "return type must be GMat"); static_assert(all_satisfy<is_gmat_type, Outs...>::value, "return type must be GMat");
static_assert(contains<GMat, Ins...>::value, "input must contain at least one GMat");
// Execution dispatcher //////////////////////////////////////////////////// // Execution dispatcher ////////////////////////////////////////////////////
template<int... IIs, int... OIs> template<int... IIs, int... OIs>
......
...@@ -1229,6 +1229,7 @@ void cv::gimpl::GFluidExecutable::bindInArg(const cv::gimpl::RcDesc &rc, const G ...@@ -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<cv::gapi::own::Mat>(arg), true); break; case GShape::GMAT: m_buffers[m_id_map.at(rc.id)].priv().bindTo(util::get<cv::gapi::own::Mat>(arg), true); break;
case GShape::GSCALAR: m_res.slot<cv::gapi::own::Scalar>()[rc.id] = util::get<cv::gapi::own::Scalar>(arg); break; case GShape::GSCALAR: m_res.slot<cv::gapi::own::Scalar>()[rc.id] = util::get<cv::gapi::own::Scalar>(arg); break;
case GShape::GARRAY: m_res.slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg); break;
default: util::throw_error(std::logic_error("Unsupported GShape type")); 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 ...@@ -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) void cv::gimpl::GFluidExecutable::packArg(cv::GArg &in_arg, const cv::GArg &op_arg)
{ {
GAPI_Assert(op_arg.kind != cv::detail::ArgKind::GMAT 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) 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 ...@@ -1263,6 +1265,10 @@ void cv::gimpl::GFluidExecutable::packArg(cv::GArg &in_arg, const cv::GArg &op_a
{ {
in_arg = GArg(m_res.slot<cv::gapi::own::Scalar>()[ref.id]); in_arg = GArg(m_res.slot<cv::gapi::own::Scalar>()[ref.id]);
} }
else if (ref.shape == GShape::GARRAY)
{
in_arg = GArg(m_res.slot<cv::detail::VectorRef>()[ref.id]);
}
} }
} }
......
...@@ -128,7 +128,7 @@ class GFluidExecutable final: public GIslandExecutable ...@@ -128,7 +128,7 @@ class GFluidExecutable final: public GIslandExecutable
std::vector<FluidAgent*> m_script; std::vector<FluidAgent*> m_script;
using Magazine = detail::magazine<cv::gapi::own::Scalar>; using Magazine = detail::magazine<cv::gapi::own::Scalar, cv::detail::VectorRef>;
Magazine m_res; Magazine m_res;
std::size_t m_num_int_buffers; // internal buffers counter (m_buffers - num_scratch) std::size_t m_num_int_buffers; // internal buffers counter (m_buffers - num_scratch)
......
...@@ -244,6 +244,26 @@ TEST(Fluid, Sum_2_Mats_And_Scalar) ...@@ -244,6 +244,26 @@ TEST(Fluid, Sum_2_Mats_And_Scalar)
EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat)); 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) TEST(Fluid, Split3)
{ {
cv::GMat bgr; cv::GMat bgr;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "test_precomp.hpp" #include "test_precomp.hpp"
#include <iomanip> #include <iomanip>
#include <vector>
#include "gapi_fluid_test_kernels.hpp" #include "gapi_fluid_test_kernels.hpp"
#include <opencv2/gapi/core.hpp> #include <opencv2/gapi/core.hpp>
#include <opencv2/gapi/own/saturate.hpp> #include <opencv2/gapi/own/saturate.hpp>
...@@ -448,6 +449,56 @@ GAPI_FLUID_KERNEL(FSum2MatsAndScalar, TSum2MatsAndScalar, false) ...@@ -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<int> &arr,
cv::gapi::fluid::Buffer &out)
{
for (int l = 0, lpi = out.lpi(); l < lpi; l++)
{
const uint8_t* in_row = mat.InLine <uint8_t>(l);
uint8_t* out_row = out.OutLine<uint8_t>(l);
for (int i = 0, w = mat.length(); i < w; i++)
{
out_row[i] = static_cast<uint8_t>(arr[in_row[i]]);
}
}
}
};
GAPI_OCV_KERNEL(OCVCalcHist, TCalcHist)
{
static void run(const cv::Mat& in, std::vector<int>& out)
{
out = std::vector<int>(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<uint8_t>(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_CY = 1220542;
static const int ITUR_BT_601_CUB = 2116026; static const int ITUR_BT_601_CUB = 2116026;
static const int ITUR_BT_601_CUG = -409993; static const int ITUR_BT_601_CUG = -409993;
...@@ -569,6 +620,8 @@ cv::gapi::GKernelPackage fluidTestPackage = cv::gapi::kernels ...@@ -569,6 +620,8 @@ cv::gapi::GKernelPackage fluidTestPackage = cv::gapi::kernels
,FSum2MatsAndScalar ,FSum2MatsAndScalar
,FTestSplit3 ,FTestSplit3
,FTestSplit3_4lpi ,FTestSplit3_4lpi
,FEqualizeHist
,OCVCalcHist
>(); >();
} // namespace gapi_test_kernels } // namespace gapi_test_kernels
} // namespace cv } // namespace cv
...@@ -15,6 +15,7 @@ namespace cv ...@@ -15,6 +15,7 @@ namespace cv
namespace gapi_test_kernels namespace gapi_test_kernels
{ {
using cv::gapi::core::GMat3; using cv::gapi::core::GMat3;
using GMat2 = std::tuple<GMat, GMat>;
G_TYPED_KERNEL(TAddSimple, <GMat(GMat, GMat)>, "test.fluid.add_simple") { G_TYPED_KERNEL(TAddSimple, <GMat(GMat, GMat)>, "test.fluid.add_simple") {
static cv::GMatDesc outMeta(cv::GMatDesc a, cv::GMatDesc) { static cv::GMatDesc outMeta(cv::GMatDesc a, cv::GMatDesc) {
...@@ -112,6 +113,20 @@ G_TYPED_KERNEL_M(TSplit3_4lpi, <GMat3(GMat)>, "test.fluid.split3_4lpi") { ...@@ -112,6 +113,20 @@ G_TYPED_KERNEL_M(TSplit3_4lpi, <GMat3(GMat)>, "test.fluid.split3_4lpi") {
} }
}; };
G_TYPED_KERNEL(TEqualizeHist, <GMat(GMat, GArray<int>)>, "test.fluid.equalize_hist")
{
static GMatDesc outMeta(GMatDesc in, const cv::GArrayDesc&) {
return in;
}
};
G_TYPED_KERNEL(TCalcHist, <GArray<int>(GMat)>, "test.ocv.calc_hist")
{
static GArrayDesc outMeta(GMatDesc) {
return {};
}
};
GMat merge3_4lpi(const GMat& src1, const GMat& src2, const GMat& src3); GMat merge3_4lpi(const GMat& src1, const GMat& src2, const GMat& src3);
std::tuple<GMat, GMat, GMat> split3_4lpi(const GMat& src); std::tuple<GMat, GMat, GMat> split3_4lpi(const GMat& src);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment