Pre-processing: Adding DivC and SubC kernels. (#5364)
* [PP] FLuid level tests for mean value preprocessing * PP] Fluid operations for mean value preprocessing * * Relaxed tolerance and fix for issue. * * Fix for issue. * * Applied comments. Co-authored-by: Anton Potapov <anton.potapov@intel.com>
This commit is contained in:
parent
768aec9d92
commit
b1a4a73328
@ -2461,6 +2461,58 @@ GAPI_FLUID_KERNEL(FConvertDepth, ConvertDepth, false) {
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
template <typename src_t, typename dst_t>
|
||||
void sub(const uint8_t* src, uint8_t* dst, const int width, double c) {
|
||||
const auto *in = reinterpret_cast<const src_t *>(src);
|
||||
auto *out = reinterpret_cast<dst_t *>(dst);
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
out[i] = saturate_cast<dst_t>(in[i] - c);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename src_t, typename dst_t>
|
||||
void div(const uint8_t* src, uint8_t* dst, const int width, double c) {
|
||||
const auto *in = reinterpret_cast<const src_t *>(src);
|
||||
auto *out = reinterpret_cast<dst_t *>(dst);
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
out[i] = saturate_cast<dst_t>(in[i] / c);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
GAPI_FLUID_KERNEL(FSubC, GSubC, false) {
|
||||
static const int Window = 1;
|
||||
|
||||
static void run(const cv::gapi::fluid::View& src, const cv::Scalar &scalar, int depth, cv::gapi::fluid::Buffer& dst) {
|
||||
GAPI_Assert(src.meta().depth == CV_32F && src.meta().chan == 1);
|
||||
|
||||
const auto *in = src.InLineB(0);
|
||||
auto *out = dst.OutLineB();
|
||||
|
||||
auto const width = dst.length();
|
||||
|
||||
sub<float, float>(in, out, width, scalar[0]);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_FLUID_KERNEL(FDivC, GDivC, false) {
|
||||
static const int Window = 1;
|
||||
|
||||
static void run(const cv::gapi::fluid::View &src, const cv::Scalar &scalar, double _scale, int /*dtype*/,
|
||||
cv::gapi::fluid::Buffer &dst) {
|
||||
GAPI_Assert(src.meta().depth == CV_32F && src.meta().chan == 1);
|
||||
|
||||
const auto *in = src.InLineB(0);
|
||||
auto *out = dst.OutLineB();
|
||||
|
||||
auto const width = dst.length();
|
||||
|
||||
div<float, float>(in, out, width, scalar[0]);
|
||||
}
|
||||
};
|
||||
} // namespace kernels
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@ -2488,6 +2540,8 @@ cv::gapi::GKernelPackage preprocKernels() {
|
||||
, FNV12toRGB
|
||||
, FI420toRGB
|
||||
, FConvertDepth
|
||||
, FSubC
|
||||
, FDivC
|
||||
>();
|
||||
}
|
||||
|
||||
|
@ -152,8 +152,17 @@ namespace gapi {
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GSubC, <cv::GMat(cv::GMat, cv::GScalar, int)>, "com.intel.ie.math.subC") {
|
||||
static cv::GMatDesc outMeta(cv::GMatDesc a, cv::GScalarDesc, int ddepth) {
|
||||
return a.withDepth(ddepth);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
G_TYPED_KERNEL(GDivC, <cv::GMat(cv::GMat, cv::GScalar, double, int)>, "com.intel.ie.math.divC") {
|
||||
static cv::GMatDesc outMeta(cv::GMatDesc a, cv::GScalarDesc, double, int ddepth) {
|
||||
return a.withDepth(ddepth);
|
||||
}
|
||||
};
|
||||
cv::gapi::GKernelPackage preprocKernels();
|
||||
|
||||
} // namespace gapi
|
||||
|
@ -57,6 +57,8 @@ template<> inline uint8_t saturate_cast(uint16_t x) {
|
||||
std::max(static_cast<uint16_t>(lim::min()), x));
|
||||
}
|
||||
template<> inline uint8_t saturate_cast(float x) { return saturate_cast<uint8_t>(static_cast<int>(std::rint(x))); }
|
||||
|
||||
template<> inline float saturate_cast(double x) { return x; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
constexpr static const int ONE = 1 << 15;
|
||||
|
@ -142,6 +142,7 @@ std::vector<test::Mat> to_test(std::vector<cv::Mat>& mats)
|
||||
}
|
||||
|
||||
test::Rect to_test(cv::Rect& rect) { return {rect.x, rect.y, rect.width, rect.height}; }
|
||||
test::Scalar to_test(cv::Scalar const& sc) { return {sc[0], sc[1], sc[2], sc[3]}; }
|
||||
|
||||
cv::ColorConversionCodes toCvtColorCode(InferenceEngine::ColorFormat in,
|
||||
InferenceEngine::ColorFormat out) {
|
||||
@ -678,6 +679,61 @@ TEST_P(ConvertDepthTestGAPI, AccuracyTest)
|
||||
EXPECT_LE(cv::norm(out_mat_ocv, out_mat_gapi, cv::NORM_INF), tolerance);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(DivCTestGAPI, AccuracyTest)
|
||||
{
|
||||
const auto params = GetParam();
|
||||
const int in_depth = std::get<0>(params);
|
||||
const int in_channels = std::get<1>(params);
|
||||
const cv::Size sz = std::get<2>(params);
|
||||
const cv::Scalar C = std::get<3>(params);
|
||||
double tolerance = std::get<4>(params);
|
||||
|
||||
const int in_type = CV_MAKETYPE(in_depth,in_channels);
|
||||
|
||||
initMatrixRandU(in_type, sz, in_type);
|
||||
|
||||
// G-API code
|
||||
DivCComputation cc(to_test(in_mat1), to_test(out_mat_gapi), to_test(C));
|
||||
cc.warmUp();
|
||||
|
||||
// OpenCV code /////////////////////////////////////////////////////////////
|
||||
{
|
||||
out_mat_ocv = in_mat1 / C;
|
||||
}
|
||||
// Comparison //////////////////////////////////////////////////////////////
|
||||
{
|
||||
EXPECT_LE(cv::norm(out_mat_ocv, out_mat_gapi, cv::NORM_INF), tolerance);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(SubCTestGAPI, AccuracyTest)
|
||||
{
|
||||
const auto params = GetParam();
|
||||
const int in_depth = std::get<0>(params);
|
||||
const int in_channels = std::get<1>(params);
|
||||
const cv::Size sz = std::get<2>(params);
|
||||
const cv::Scalar C = std::get<3>(params);
|
||||
const double tolerance = std::get<4>(params);
|
||||
|
||||
const int in_type = CV_MAKETYPE(in_depth,in_channels);
|
||||
|
||||
initMatrixRandU(in_type, sz, in_type);
|
||||
|
||||
// G-API code
|
||||
SubCComputation cc(to_test(in_mat1), to_test(out_mat_gapi), to_test(C));
|
||||
cc.warmUp();
|
||||
|
||||
// OpenCV code /////////////////////////////////////////////////////////////
|
||||
{
|
||||
out_mat_ocv = in_mat1 - C;
|
||||
}
|
||||
// Comparison //////////////////////////////////////////////////////////////
|
||||
{
|
||||
EXPECT_LE(cv::norm(out_mat_ocv, out_mat_gapi, cv::NORM_INF), tolerance);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
TEST_P(ResizeTestIE, AccuracyTest)
|
||||
@ -1268,5 +1324,31 @@ TEST_P(PreprocTest, Performance)
|
||||
out_layout_str.c_str(), out_size.width, out_size.height,
|
||||
colorFormatToString(in_fmt).c_str(), colorFormatToString(out_fmt).c_str());
|
||||
#endif // PERF_TEST
|
||||
}
|
||||
|
||||
TEST_P(MeanValueGAPI, AccuracyTest)
|
||||
{
|
||||
const auto params = GetParam();
|
||||
cv::Size sz = std::get<0>(params);
|
||||
double tolerance = std::get<1>(params);
|
||||
|
||||
initMatrixRandU(CV_32FC1, sz, CV_32FC1);
|
||||
|
||||
const cv::Scalar mean = { 0.485, 0.456, 0.406 };
|
||||
const cv::Scalar std = { 0.229, 0.224, 0.225 };
|
||||
|
||||
// G-API code
|
||||
MeanValueSubtractComputation cc(to_test(in_mat1), to_test(out_mat_gapi), to_test(mean), to_test(std));
|
||||
cc.warmUp();
|
||||
|
||||
// OpenCV code /////////////////////////////////////////////////////////////
|
||||
{
|
||||
out_mat_ocv = (in_mat1 - mean) / std;
|
||||
}
|
||||
// Comparison //////////////////////////////////////////////////////////////
|
||||
{
|
||||
EXPECT_LE(cv::norm(out_mat_ocv, out_mat_gapi, cv::NORM_INF), tolerance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,18 @@ struct ConvertDepthTestGAPI: public TestParams<std::tuple<
|
||||
cv::Size,
|
||||
double>> // tolerance
|
||||
{};
|
||||
struct DivCTestGAPI: public TestParams<std::tuple<
|
||||
int, // input matrix depth
|
||||
int, // input matrix channels number
|
||||
cv::Size,
|
||||
cv::Scalar, // second operarnd
|
||||
double>> // tolerance
|
||||
{};
|
||||
|
||||
struct SubCTestGAPI : public DivCTestGAPI
|
||||
{};
|
||||
|
||||
struct MeanValueGAPI: public TestParams<std::tuple<cv::Size, double>> {};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct ResizeTestIE: public testing::TestWithParam<std::tuple<int, int, std::pair<cv::Size, cv::Size>, double>> {};
|
||||
|
@ -183,6 +183,20 @@ INSTANTIATE_TEST_CASE_P(ConvertDepthFluid, ConvertDepthTestGAPI,
|
||||
cv::Size( 320, 200)),
|
||||
Values(1)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(DivCFluid, DivCTestGAPI,
|
||||
Combine(Values(CV_32F),
|
||||
Values(1), //channels
|
||||
Values(TEST_SIZES),
|
||||
Values(cv::Scalar{0.229}),
|
||||
Values(0)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(SubCFluid, SubCTestGAPI,
|
||||
Combine(Values(CV_32F),
|
||||
Values(1), //channels
|
||||
Values(TEST_SIZES),
|
||||
Values(cv::Scalar{0.229}),
|
||||
Values(0.00001)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ResizeRoiTestFluid, ResizeRoiTestGAPI,
|
||||
Combine(Values(CV_8UC1, CV_8UC3),
|
||||
Values(cv::INTER_LINEAR),
|
||||
@ -284,6 +298,10 @@ INSTANTIATE_TEST_CASE_P(Reorder_CHW2HWC, ColorConvertTestIE,
|
||||
Values(TEST_SIZES),
|
||||
Values(0)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(MeanValueGAPI32F, MeanValueGAPI,
|
||||
Combine(Values(TEST_SIZES),
|
||||
Values(0.00001)));
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace IE = InferenceEngine;
|
||||
|
@ -12,8 +12,42 @@
|
||||
struct FluidComputation::Priv
|
||||
{
|
||||
cv::GComputation m_c;
|
||||
std::vector<cv::gapi::own::Mat> m_v_in;
|
||||
cv::GRunArgs m_v_in;
|
||||
std::vector<cv::gapi::own::Mat> m_v_out;
|
||||
|
||||
Priv(cv::GComputation && c, std::vector<cv::gapi::own::Mat>&& v_in, std::vector<cv::gapi::own::Mat>&& v_out)
|
||||
: m_c(std::move(c)),
|
||||
m_v_in(v_in.begin(), v_in.end()),
|
||||
m_v_out(std::move(v_out))
|
||||
{}
|
||||
|
||||
Priv(cv::GComputation && c, cv::gapi::own::Mat&& v_in, cv::gapi::own::Mat&& v_out)
|
||||
: m_c(std::move(c)),
|
||||
m_v_in{std::move(v_in)},
|
||||
m_v_out{std::move(v_out)}
|
||||
{}
|
||||
|
||||
Priv(cv::GComputation && c, cv::gapi::own::Mat&& v_in, std::vector<cv::gapi::own::Mat>&& v_out)
|
||||
: m_c(std::move(c)),
|
||||
m_v_in{std::move(v_in)},
|
||||
m_v_out(std::move(v_out))
|
||||
{}
|
||||
|
||||
Priv(cv::GComputation && c, cv::GRunArgs&& v_in, std::vector<cv::gapi::own::Mat>&& v_out)
|
||||
: m_c(std::move(c)),
|
||||
m_v_in(std::move(v_in)),
|
||||
m_v_out(std::move(v_out))
|
||||
{}
|
||||
|
||||
cv::GRunArgs ins() { return m_v_in;}
|
||||
cv::GRunArgsP outs() {
|
||||
cv::GRunArgsP call_outs;
|
||||
|
||||
for (auto &m : m_v_out) { call_outs.emplace_back(&m); }
|
||||
|
||||
return call_outs;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
FluidComputation::FluidComputation(Priv *priv)
|
||||
@ -27,19 +61,24 @@ namespace
|
||||
|
||||
void FluidComputation::warmUp(test::Rect roi)
|
||||
{
|
||||
if (roi.empty())
|
||||
m_priv->m_c.apply(m_priv->m_v_in, m_priv->m_v_out, cv::compile_args(InferenceEngine::gapi::preprocKernels()));
|
||||
else
|
||||
m_priv->m_c.apply(m_priv->m_v_in, m_priv->m_v_out, cv::compile_args(InferenceEngine::gapi::preprocKernels(), cv::GFluidOutputRois{{to_own(roi)}}));
|
||||
auto compile_args = roi.empty() ? cv::compile_args(InferenceEngine::gapi::preprocKernels())
|
||||
: cv::compile_args(InferenceEngine::gapi::preprocKernels(),
|
||||
cv::GFluidOutputRois{{to_own(roi)}});
|
||||
|
||||
m_priv->m_c.apply(m_priv->ins(), m_priv->outs(), std::move(compile_args));
|
||||
}
|
||||
|
||||
void FluidComputation::apply()
|
||||
{
|
||||
m_priv->m_c.apply(m_priv->m_v_in, m_priv->m_v_out);
|
||||
m_priv->m_c.apply(m_priv->ins(), m_priv->outs());
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
cv::gapi::own::Scalar to_own(test::Scalar const& s) {
|
||||
return {s.v[0], s.v[1], s.v[2], s.v[3]};
|
||||
}
|
||||
|
||||
cv::gapi::own::Mat to_own(test::Mat mat) {
|
||||
return {mat.rows, mat.cols, mat.type, mat.data, mat.step};
|
||||
}
|
||||
@ -94,8 +133,8 @@ static cv::GComputation buildResizeComputation(test::Mat inMat, test::Mat outMat
|
||||
|
||||
FluidResizeComputation::FluidResizeComputation(test::Mat inMat, test::Mat outMat, int interp)
|
||||
: FluidComputation(new Priv{buildResizeComputation(inMat, outMat, interp)
|
||||
,{to_own(inMat)}
|
||||
,{to_own(outMat)}
|
||||
,to_own(inMat)
|
||||
,to_own(outMat)
|
||||
})
|
||||
{}
|
||||
|
||||
@ -122,8 +161,8 @@ static cv::GComputation buildResizeRGB8UComputation(test::Mat inMat, test::Mat o
|
||||
|
||||
FluidResizeRGB8UComputation::FluidResizeRGB8UComputation(test::Mat inMat, test::Mat outMat, int interp)
|
||||
: FluidComputation(new Priv{buildResizeRGB8UComputation(inMat, outMat, interp)
|
||||
,{to_own(inMat)}
|
||||
,{to_own(outMat)}
|
||||
,to_own(inMat)
|
||||
,to_own(outMat)
|
||||
})
|
||||
{}
|
||||
|
||||
@ -144,7 +183,7 @@ static cv::GComputation buildSplitComputation(int planes)
|
||||
|
||||
FluidSplitComputation::FluidSplitComputation(test::Mat inMat, std::vector<test::Mat> outMats)
|
||||
: FluidComputation(new Priv{buildSplitComputation(outMats.size())
|
||||
,{to_own(inMat)}
|
||||
,to_own(inMat)
|
||||
,to_own(outMats)
|
||||
})
|
||||
{}
|
||||
@ -158,8 +197,8 @@ static cv::GComputation buildChanToPlaneComputation(int chan)
|
||||
|
||||
FluidChanToPlaneComputation::FluidChanToPlaneComputation(test::Mat inMat, test::Mat outMat, int chan)
|
||||
: FluidComputation(new Priv{buildChanToPlaneComputation(chan)
|
||||
,{to_own(inMat)}
|
||||
,{to_own(outMat)}
|
||||
,to_own(inMat)
|
||||
,to_own(outMat)
|
||||
})
|
||||
{}
|
||||
|
||||
@ -216,12 +255,60 @@ FluidI420toRGBComputation::FluidI420toRGBComputation(test::Mat inMat_y, test::Ma
|
||||
|
||||
ConvertDepthComputation::ConvertDepthComputation(test::Mat inMat, test::Mat outMat, int depth)
|
||||
: FluidComputation(new Priv{ [depth]()-> cv::GComputation {
|
||||
cv::GMat in;
|
||||
cv::GMat out = InferenceEngine::gapi::ConvertDepth::on(in, depth);
|
||||
return cv::GComputation(cv::GIn(in), cv::GOut(out));
|
||||
}()
|
||||
, {to_own(inMat)}
|
||||
, {to_own(outMat)}
|
||||
cv::GMat in;
|
||||
cv::GMat out = InferenceEngine::gapi::ConvertDepth::on(in, depth);
|
||||
return cv::GComputation(cv::GIn(in), cv::GOut(out));
|
||||
}()
|
||||
, to_own(inMat)
|
||||
, to_own(outMat)
|
||||
})
|
||||
{}
|
||||
|
||||
DivCComputation::DivCComputation(test::Mat inMat, test::Mat outMat, test::Scalar const& c)
|
||||
: FluidComputation(new Priv{ []()-> cv::GComputation {
|
||||
cv::GMat in;
|
||||
cv::GScalar C;
|
||||
cv::GMat out = in / C;
|
||||
return cv::GComputation(cv::GIn(in, C), cv::GOut(out));
|
||||
}()
|
||||
, cv::GRunArgs{cv::GRunArg{to_own(inMat)}, cv::GRunArg{to_own(c)}}
|
||||
, {to_own(outMat)}
|
||||
})
|
||||
{}
|
||||
|
||||
SubCComputation::SubCComputation(test::Mat inMat, test::Mat outMat, test::Scalar const& c)
|
||||
: FluidComputation(new Priv{ []()-> cv::GComputation{
|
||||
cv::GMat in;
|
||||
cv::GScalar C;
|
||||
cv::GMat out = in - C;
|
||||
return cv::GComputation(cv::GIn(in, C), cv::GOut(out));
|
||||
}()
|
||||
, cv::GRunArgs{cv::GRunArg{to_own(inMat)}, cv::GRunArg{to_own(c)}}
|
||||
, {to_own(outMat)}
|
||||
})
|
||||
{}
|
||||
|
||||
MeanValueSubtractComputation::MeanValueSubtractComputation(test::Mat inMat, test::Mat outMat, test::Scalar const& mean, test::Scalar const& std)
|
||||
: FluidComputation(new Priv{ []()-> cv::GComputation{
|
||||
cv::GMat in;
|
||||
cv::GScalar _mean;
|
||||
cv::GScalar _std;
|
||||
cv::GMat out = (in - _mean) / _std;
|
||||
return cv::GComputation(cv::GIn(in, _mean, _std), cv::GOut(out));
|
||||
}()
|
||||
, cv::GRunArgs{cv::GRunArg{to_own(inMat)}, cv::GRunArg{to_own(mean)}, cv::GRunArg{to_own(std)}}
|
||||
, {to_own(outMat)}
|
||||
})
|
||||
{}
|
||||
|
||||
namespace cv {
|
||||
cv::GMat operator-(const cv::GMat& lhs, const cv::GScalar& rhs)
|
||||
{
|
||||
return InferenceEngine::gapi::GSubC::on(lhs, rhs, -1);
|
||||
}
|
||||
cv::GMat operator/(const cv::GMat& lhs, const cv::GScalar& rhs)
|
||||
{
|
||||
return InferenceEngine::gapi::GDivC::on(lhs, rhs, 1.0, -1);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifdef IMPLEMENT_FLUID_COMPUTATION_API
|
||||
@ -43,6 +44,11 @@ struct Rect{
|
||||
return width == 0 && height == 0;
|
||||
};
|
||||
};
|
||||
struct Scalar
|
||||
{
|
||||
std::array<double, 4> v;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class FLUID_COMPUTATION_VISIBILITY FluidComputation
|
||||
@ -104,4 +110,22 @@ public:
|
||||
ConvertDepthComputation(test::Mat inMat, test::Mat outMat, int depth);
|
||||
};
|
||||
|
||||
class FLUID_COMPUTATION_VISIBILITY DivCComputation : public FluidComputation
|
||||
{
|
||||
public:
|
||||
DivCComputation(test::Mat inMat, test::Mat outMat, test::Scalar const& c);
|
||||
};
|
||||
|
||||
class FLUID_COMPUTATION_VISIBILITY SubCComputation : public FluidComputation
|
||||
{
|
||||
public:
|
||||
SubCComputation(test::Mat inMat, test::Mat outMat, test::Scalar const& c);
|
||||
};
|
||||
|
||||
class FLUID_COMPUTATION_VISIBILITY MeanValueSubtractComputation : public FluidComputation
|
||||
{
|
||||
public:
|
||||
MeanValueSubtractComputation(test::Mat inMat, test::Mat outMat, test::Scalar const& mean, test::Scalar const& std);
|
||||
};
|
||||
|
||||
#endif // FLUID_TEST_COMPUTATIONS_HPP
|
||||
|
Loading…
Reference in New Issue
Block a user