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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user