Merge pull request #18257 from OrestChura:oc/fluid_operator_bitwise_and_scalar

[G-API]: Add Fluid bitwise operations implementation for (GMat, GScalar)

* Added Fluid `bitwise` with `Scalar` + acc.tests
 - simple loop implementation for Fluid used (no `hal`);
   - `Scalar` is casted to `int` in the beginning
 - tests just modified to work with `Scalar`
 - expected output in operators' tests fixed (operators can't change Mat's depth)
 - `float` `Scalar` `RNG` added, `RNG` reworked (`time` is used now), initialization of test fixtures reworked
   - if input or output is `float` Scalar is initialized by `float`
 - some problems with Fluid/OCV floating-point comparison difference stashed by `AbsSimilarPoints()` usage, FIXME added
 - divide-by-zero is now fixed differently and everywhere

* - Added perf_tests for bitwise_Scalar operations
 - due to errors of Fluid floating-point comparison operations, added support of different validation in Cmp perf_tests; added FIXME

 - reworked integral initialization of Scalar

* Addressing comments
 - NULL -> nullptr
 - Scalar convertion moved to the function
 - avoid -> avoiding

* Addressing comments

* CV_assert -> GAPI_assert

* Addressed DM comments
 - refactored convertScalarForBitwise()
 - removed unnecessary braces for switch

* Changed the operators tests
 - switch via `enum` implemented
 - infrastructure for that refactored
This commit is contained in:
Orest Chura
2020-09-18 16:44:47 +03:00
committed by GitHub
parent 7163781639
commit d1cdef596c
17 changed files with 606 additions and 284 deletions
+134 -4
View File
@@ -806,7 +806,7 @@ GAPI_FLUID_KERNEL(GFluidDivRC, cv::gapi::core::GDivRC, false)
enum Bitwise { BW_AND, BW_OR, BW_XOR, BW_NOT };
template<typename DST, typename SRC1, typename SRC2>
static void run_bitwise2(Buffer &dst, const View &src1, const View &src2, Bitwise bitwise)
static void run_bitwise2(Buffer &dst, const View &src1, const View &src2, Bitwise bitwise_op)
{
static_assert(std::is_same<DST, SRC1>::value, "wrong types");
static_assert(std::is_same<DST, SRC2>::value, "wrong types");
@@ -819,7 +819,7 @@ static void run_bitwise2(Buffer &dst, const View &src1, const View &src2, Bitwis
int chan = dst.meta().chan;
int length = width * chan;
switch (bitwise)
switch (bitwise_op)
{
case BW_AND:
for (int l=0; l < length; l++)
@@ -838,7 +838,7 @@ static void run_bitwise2(Buffer &dst, const View &src1, const View &src2, Bitwis
}
template<typename DST, typename SRC>
static void run_bitwise1(Buffer &dst, const View &src, Bitwise bitwise)
static void run_bitwise1(Buffer &dst, const View &src, Bitwise bitwise_op)
{
static_assert(std::is_same<DST, SRC>::value, "wrong types");
@@ -849,7 +849,7 @@ static void run_bitwise1(Buffer &dst, const View &src, Bitwise bitwise)
int chan = dst.meta().chan;
int length = width * chan;
switch (bitwise)
switch (bitwise_op)
{
case BW_NOT:
for (int l=0; l < length; l++)
@@ -922,6 +922,133 @@ GAPI_FLUID_KERNEL(GFluidNot, cv::gapi::core::GNot, false)
}
};
//--------------------------------------
//
// Fluid math kernels: bitwise with Scalar
//
//--------------------------------------
static std::array<int,4> convertScalarForBitwise(const cv::Scalar &_scalar)
{
std::array<int,4> scalarI = {
static_cast<int>(_scalar[0]),
static_cast<int>(_scalar[1]),
static_cast<int>(_scalar[2]),
static_cast<int>(_scalar[3])
};
if (!((_scalar[0] == scalarI[0]) && (_scalar[1] == scalarI[1]) &&
(_scalar[2] == scalarI[2]) && (_scalar[3] == scalarI[3])))
{
CV_Error(cv::Error::StsBadArg, "Bitwise operations make sense with integral types only");
}
return scalarI;
}
template<typename DST>
static inline DST bw_andS(DST x, int y)
{
return x & saturate<DST>(y);
}
template<typename DST>
static inline DST bw_orS(DST x, int y)
{
return x | saturate<DST>(y);
}
template<typename DST>
static inline DST bw_xorS(DST x, int y)
{
return x ^ saturate<DST>(y);
}
// manually unroll the inner cycle by channels
// (reuse arithmetic function above of the same purpose)
template<typename DST, typename FUNC>
static inline void run_bitwise_s(DST out[], const DST in[], int width, int chan,
const int scalar[4], FUNC func)
{
run_arithm_s(out, in, width, chan, scalar, func);
}
template<typename DST, typename SRC>
static void run_bitwise_s(Buffer &dst, const View &src, const int scalar[4], Bitwise bitwise_op)
{
static_assert(std::is_same<DST, SRC>::value, "wrong types");
const auto *in = src.InLine<SRC>(0);
auto *out = dst.OutLine<DST>();
int width = dst.length();
int chan = dst.meta().chan;
switch (bitwise_op)
{
case BW_AND:
run_bitwise_s(out, in, width, chan, scalar, bw_andS<DST>);
break;
case BW_OR:
run_bitwise_s(out, in, width, chan, scalar, bw_orS<DST>);
break;
case BW_XOR:
run_bitwise_s(out, in, width, chan, scalar, bw_xorS<DST>);
break;
default: CV_Error(cv::Error::StsBadArg, "unsupported bitwise operation");
}
}
GAPI_FLUID_KERNEL(GFluidAndS, cv::gapi::core::GAndS, false)
{
static const int Window = 1;
static void run(const View &src, const cv::Scalar &_scalar, Buffer &dst)
{
std::array<int,4> scalar = convertScalarForBitwise(_scalar);
// DST SRC OP __VA_ARGS__
UNARY_(uchar , uchar , run_bitwise_s, dst, src, scalar.data(), BW_AND);
UNARY_(ushort, ushort, run_bitwise_s, dst, src, scalar.data(), BW_AND);
UNARY_( short, short, run_bitwise_s, dst, src, scalar.data(), BW_AND);
CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
}
};
GAPI_FLUID_KERNEL(GFluidOrS, cv::gapi::core::GOrS, false)
{
static const int Window = 1;
static void run(const View &src, const cv::Scalar &_scalar, Buffer &dst)
{
std::array<int,4> scalar = convertScalarForBitwise(_scalar);
// DST SRC OP __VA_ARGS__
UNARY_(uchar , uchar , run_bitwise_s, dst, src, scalar.data(), BW_OR);
UNARY_(ushort, ushort, run_bitwise_s, dst, src, scalar.data(), BW_OR);
UNARY_( short, short, run_bitwise_s, dst, src, scalar.data(), BW_OR);
CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
}
};
GAPI_FLUID_KERNEL(GFluidXorS, cv::gapi::core::GXorS, false)
{
static const int Window = 1;
static void run(const View &src, const cv::Scalar &_scalar, Buffer &dst)
{
std::array<int,4> scalar = convertScalarForBitwise(_scalar);
// DST SRC OP __VA_ARGS__
UNARY_(uchar , uchar , run_bitwise_s, dst, src, scalar.data(), BW_XOR);
UNARY_(ushort, ushort, run_bitwise_s, dst, src, scalar.data(), BW_XOR);
UNARY_( short, short, run_bitwise_s, dst, src, scalar.data(), BW_XOR);
CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
}
};
//-------------------
//
// Fluid kernels: LUT
@@ -2175,6 +2302,9 @@ cv::gapi::GKernelPackage cv::gapi::core::fluid::kernels()
,GFluidAnd
,GFluidOr
,GFluidXor
,GFluidAndS
,GFluidOrS
,GFluidXorS
,GFluidMin
,GFluidMax
,GFluidCmpGT