[PP GAPI] - Generic precision conversion kernel (#1897)
authorAnton Potapov <anton.potapov@intel.com>
Fri, 4 Sep 2020 12:24:36 +0000 (15:24 +0300)
committerGitHub <noreply@github.com>
Fri, 4 Sep 2020 12:24:36 +0000 (15:24 +0300)
- 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

inference-engine/src/preprocessing/ie_preprocess_gapi_kernels.cpp
inference-engine/src/preprocessing/ie_preprocess_gapi_kernels.hpp
inference-engine/src/preprocessing/ie_preprocess_gapi_kernels_impl.hpp
inference-engine/tests_deprecated/fluid_preproc/common/fluid_tests.cpp
inference-engine/tests_deprecated/fluid_preproc/common/fluid_tests.hpp
inference-engine/tests_deprecated/fluid_preproc/cpu/fluid_tests_cpu.cpp
inference-engine/tests_deprecated/fluid_preproc/fluid_test_computations/fluid_test_computations.cpp
inference-engine/tests_deprecated/fluid_preproc/fluid_test_computations/fluid_test_computations.hpp

index 53c1fee..654b625 100644 (file)
@@ -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
         >();
 }
 
index 8caacd2..7b6acdb 100644 (file)
@@ -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);
         }
     };
 
index d34942e..6d5161f 100644 (file)
@@ -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); }
 
 //------------------------------------------------------------------------------
index 479c3e5..8f5a2f0 100644 (file)
@@ -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);
+
+    const int out_type = CV_MAKETYPE(out_depth,1);
 
-    initMatrixRandU(CV_16UC1, sz, CV_32FC1);
+    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 //////////////////////////////////////////////////////////////
     {
index fb4535a..012a281 100644 (file)
@@ -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>> {};
index 1a41fcc..954bff9 100644 (file)
@@ -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),
index f4afb49..5192cf0 100644 (file)
@@ -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)}
                                })
 {}
 
index 39d06a3..e7d071e 100644 (file)
@@ -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