[PP GAPI] - Generic precision conversion kernel (#1897)

- U16toF32 conversion kernel converted to more generic ConvDepth one
- U16 <-> F32 conversion only are supported for now
- kernel is not used in the preprocessing graph yet
- tests are extended
This commit is contained in:
Anton Potapov authored and GitHub committed 2020-09-04 15:24:36 +03:00
1 parent 2d606e35c5
commit 74b77a4c97
8 files changed
+78 -34

No files matched your search

@@ -2231,23 +2231,52 @@ GAPI_FLUID_KERNEL(FI420toRGB, I420toRGB, false) {
}
};
GAPI_FLUID_KERNEL(FU16toF32, U16toF32, false) {
namespace {
template <typename src_t, typename dst_t>
void convert_precision(const uint8_t* src, uint8_t* dst, const int width) {
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]);
}
}
}
GAPI_FLUID_KERNEL(FConvertDepth, ConvertDepth, false) {
static const int Window = 1;
static void run(const cv::gapi::fluid::View& src, cv::gapi::fluid::Buffer& dst) {
GAPI_Assert(src.meta().depth == CV_16U);
GAPI_Assert(dst.meta().depth == CV_32F);
static void run(const cv::gapi::fluid::View& src, int depth, cv::gapi::fluid::Buffer& dst) {
GAPI_Assert(src.meta().depth == CV_16U || src.meta().depth == CV_32F);
GAPI_Assert(dst.meta().depth == CV_32F || dst.meta().depth == CV_16U);
GAPI_Assert(src.meta().chan == 1);
GAPI_Assert(dst.meta().chan == 1);
GAPI_Assert(src.length() == dst.length());
const auto *in = src.InLine<uint16_t>(0);
auto *out = dst.OutLine<float>();
constexpr unsigned supported_types_n = 2;
using p_f = void (*)( const uint8_t* src, uint8_t* dst, const int width);
using table_string_t = std::array<p_f, supported_types_n>;
constexpr std::array<table_string_t, supported_types_n> func_table = {
table_string_t{convert_precision<uint16_t, uint16_t>, convert_precision<uint16_t, float>},
table_string_t{convert_precision<float, uint16_t>, convert_precision<float, float>}
};
auto depth_to_index = [](int depth){
switch (depth) {
case CV_16U: return 0;
case CV_32F: return 1;
default: GAPI_Assert(!"not supported depth"); return -1;
}
};
const auto *in = src.InLineB(0);
auto *out = dst.OutLineB();
auto const width = dst.length();
for (int i = 0; i < width; i++) {
out[i] = in[i];
}
auto const src_index = depth_to_index(src.meta().depth);
auto const dst_index = depth_to_index(dst.meta().depth);
(func_table[src_index][dst_index])(in, out, width);
}
};
@@ -2277,7 +2306,7 @@ cv::gapi::GKernelPackage preprocKernels() {
, FSplit4
, FNV12toRGB
, FI420toRGB
, FU16toF32
, FConvertDepth
>();
}
@@ -143,11 +143,12 @@ namespace gapi {
}
};
G_TYPED_KERNEL(U16toF32, <cv::GMat(cv::GMat)>, "com.intel.ie.u16tof32") {
static cv::GMatDesc outMeta(const cv::GMatDesc& in) {
GAPI_Assert(in.depth == CV_16U);
G_TYPED_KERNEL(ConvertDepth, <cv::GMat(cv::GMat, int depth)>, "com.intel.ie.ConvertDepth") {
static cv::GMatDesc outMeta(const cv::GMatDesc& in, int depth) {
GAPI_Assert(in.depth == CV_16U || in.depth == CV_32F);
GAPI_Assert(depth == CV_32F || depth == CV_16U);
return in.withDepth(CV_32F);
return in.withDepth(depth);
}
};
@@ -38,7 +38,10 @@ template<> inline short saturate_cast(int x) { return (std::min)(SHRT_MAX, (std:
template<> inline short saturate_cast(float x) { return saturate_cast<short>(static_cast<int>(std::rint(x))); }
template<> inline float saturate_cast(float x) { return x; }
template<> inline short saturate_cast(short x) { return x; }
template<> inline uint16_t saturate_cast(uint16_t x) { return x; }
template<> inline float saturate_cast(uint16_t x) { return x; }
template<> inline uint16_t saturate_cast(int x) { return (std::min)(USHRT_MAX, (std::max)(0, x)); }
template<> inline uint16_t saturate_cast(float x) { return saturate_cast<uint16_t>(static_cast<int>(std::rint(x))); }
template<> inline uchar saturate_cast<uchar>(int v) { return (uchar)((unsigned)v <= UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0); }
//------------------------------------------------------------------------------
@@ -625,27 +625,31 @@ TEST_P(I420toRGBTestGAPI, AccuracyTest)
}
}
TEST_P(U16toF32TestGAPI, AccuracyTest)
TEST_P(ConvertDepthTestGAPI, AccuracyTest)
{
const auto params = GetParam();
cv::Size sz = std::get<0>(params);
double tolerance = std::get<1>(params);
int in_depth = std::get<0>(params);
int out_depth = std::get<1>(params);
cv::Size sz = std::get<2>(params);
double tolerance = std::get<3>(params);
initMatrixRandU(CV_16UC1, sz, CV_32FC1);
const int out_type = CV_MAKETYPE(out_depth,1);
initMatrixRandU(CV_MAKETYPE(in_depth,1), sz, out_type);
// G-API code //////////////////////////////////////////////////////////////
FluidU16ToF32Computation cc(to_test(in_mat1), to_test(out_mat_gapi));
ConvertDepthComputation cc(to_test(in_mat1), to_test(out_mat_gapi), out_mat_gapi.depth());
cc.warmUp();
#if PERF_TEST
// iterate testing, and print performance
test_ms([&](){ cc.apply(); },
400, "U16ToF32 GAPI %s %dx%d", typeToString(CV_16UC1).c_str(), sz.width, sz.height);
400, "ConvDepth GAPI %s to %s %dx%d", depthToString(in_mat1.depth()).c_str(), depthToString(out_mat_gapi.depth()).c_str(), sz.width, sz.height);
#endif
// OpenCV code /////////////////////////////////////////////////////////////
{
in_mat1.convertTo(out_mat_ocv, CV_32FC1);
in_mat1.convertTo(out_mat_ocv, out_type);
}
// Comparison //////////////////////////////////////////////////////////////
{
@@ -19,7 +19,12 @@ struct NV12toRGBTestGAPI: public TestParams<std::tuple<cv::Size, double>> {};
struct I420toRGBTestGAPI: public TestParams<std::tuple<cv::Size, double>> {};
struct ResizeRoiTestGAPI: public testing::TestWithParam<std::tuple<int, int, std::pair<cv::Size, cv::Size>, cv::Rect, double>> {};
struct ResizeRGB8URoiTestGAPI: public testing::TestWithParam<std::tuple<int, int, std::pair<cv::Size, cv::Size>, cv::Rect, double>> {};
struct U16toF32TestGAPI: public TestParams<std::tuple<cv::Size, double>> {};
struct ConvertDepthTestGAPI: public TestParams<std::tuple<
int, // input matrix depth
int, // output matrix depth
cv::Size,
double>> // tolerance
{};
//------------------------------------------------------------------------------
struct ResizeTestIE: public testing::TestWithParam<std::tuple<int, int, std::pair<cv::Size, cv::Size>, double>> {};
@@ -170,8 +170,10 @@ INSTANTIATE_TEST_CASE_P(I420toRGBTestFluid, I420toRGBTestGAPI,
cv::Size( 320, 200)),
Values(0)));
INSTANTIATE_TEST_CASE_P(U16toF32TestGAPIFluid, U16toF32TestGAPI,
Combine(Values(cv::Size(3840, 2160),
INSTANTIATE_TEST_CASE_P(ConvertDepthFluid, ConvertDepthTestGAPI,
Combine(Values(CV_16U, CV_32F),
Values(CV_32F, CV_16U),
Values(cv::Size(3840, 2160),
cv::Size(1920, 1080),
cv::Size(1280, 720),
cv::Size(1280, 960),
@@ -179,7 +181,7 @@ INSTANTIATE_TEST_CASE_P(U16toF32TestGAPIFluid, U16toF32TestGAPI,
cv::Size( 640, 480),
cv::Size( 300, 300),
cv::Size( 320, 200)),
Values(0)));
Values(1)));
INSTANTIATE_TEST_CASE_P(ResizeRoiTestFluid, ResizeRoiTestGAPI,
Combine(Values(CV_8UC1, CV_8UC3),
@@ -214,14 +214,14 @@ FluidI420toRGBComputation::FluidI420toRGBComputation(test::Mat inMat_y, test::Ma
})
{}
FluidU16ToF32Computation::FluidU16ToF32Computation(test::Mat inMatU16, test::Mat outMatF32)
: FluidComputation(new Priv{ []()-> cv::GComputation {
cv::GMat in_U16;
cv::GMat outf32 = InferenceEngine::gapi::U16toF32::on(in_U16);
return cv::GComputation(cv::GIn(in_U16), cv::GOut(outf32));
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(inMatU16)}
, {to_own(outMatF32)}
, {to_own(inMat)}
, {to_own(outMat)}
})
{}
@@ -98,10 +98,10 @@ public:
FluidI420toRGBComputation(test::Mat inMat_y, test::Mat inMat_u, test::Mat inMat_v, test::Mat outMat);
};
class FLUID_COMPUTATION_VISIBILITY FluidU16ToF32Computation : public FluidComputation
class FLUID_COMPUTATION_VISIBILITY ConvertDepthComputation : public FluidComputation
{
public:
FluidU16ToF32Computation(test::Mat inMatU16, test::Mat outMatF32);
ConvertDepthComputation(test::Mat inMat, test::Mat outMat, int depth);
};
#endif // FLUID_TEST_COMPUTATIONS_HPP