Adding stereo operation and tests
authoraDanPin <danil.pinaev@intel.com>
Wed, 31 Mar 2021 17:09:10 +0000 (20:09 +0300)
committeraDanPin <danil.pinaev@intel.com>
Wed, 31 Mar 2021 17:09:10 +0000 (20:09 +0300)
modules/gapi/CMakeLists.txt
modules/gapi/include/opencv2/gapi/cpu/stereo.hpp [new file with mode: 0644]
modules/gapi/include/opencv2/gapi/stereo.hpp [new file with mode: 0644]
modules/gapi/src/api/kernels_stereo.cpp [new file with mode: 0644]
modules/gapi/src/backends/cpu/gcpustereo.cpp [new file with mode: 0644]
modules/gapi/test/common/gapi_stereo_tests.cpp [new file with mode: 0644]
modules/gapi/test/common/gapi_stereo_tests.hpp [new file with mode: 0644]
modules/gapi/test/common/gapi_stereo_tests_inl.hpp [new file with mode: 0644]
modules/gapi/test/cpu/gapi_stereo_tests_cpu.cpp [new file with mode: 0644]

index 9dc393fb8acb91c291dedd5df1c9113302668d3e..6753c93b7d8580c8b3a38b2c9839f6a3e5e43f91 100644 (file)
@@ -23,7 +23,7 @@ ocv_add_module(gapi
     REQUIRED
       opencv_imgproc
     OPTIONAL
-      opencv_video
+      opencv_video opencv_calib3d
     WRAP
       python
 )
@@ -76,6 +76,7 @@ set(gapi_srcs
     src/api/kernels_video.cpp
     src/api/kernels_nnparsers.cpp
     src/api/kernels_streaming.cpp
+    src/api/kernels_stereo.cpp
     src/api/render.cpp
     src/api/render_ocv.cpp
     src/api/ginfer.cpp
@@ -111,6 +112,7 @@ set(gapi_srcs
     src/backends/cpu/gcpubackend.cpp
     src/backends/cpu/gcpukernel.cpp
     src/backends/cpu/gcpuimgproc.cpp
+    src/backends/cpu/gcpustereo.cpp
     src/backends/cpu/gcpuvideo.cpp
     src/backends/cpu/gcpucore.cpp
     src/backends/cpu/gnnparsers.cpp
diff --git a/modules/gapi/include/opencv2/gapi/cpu/stereo.hpp b/modules/gapi/include/opencv2/gapi/cpu/stereo.hpp
new file mode 100644 (file)
index 0000000..f7d79e9
--- /dev/null
@@ -0,0 +1,48 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2021 Intel Corporation
+
+#ifndef OPENCV_GAPI_CPU_STEREO_API_HPP
+#define OPENCV_GAPI_CPU_STEREO_API_HPP
+
+#include <opencv2/gapi/gkernel.hpp> // GKernelPackage
+
+namespace cv {
+namespace gapi {
+namespace calib3d {
+namespace cpu {
+
+GAPI_EXPORTS GKernelPackage kernels();
+
+/** @brief Structure for the Stereo operation initialization parameters.*/
+struct GAPI_EXPORTS StereoInitParam {
+    StereoInitParam(int nD, int bS, double bL, double f):
+        numDisparities(nD), blockSize(bS), baseline(bL), focus(f) {}
+
+    StereoInitParam() = default;
+
+    int numDisparities = 0;
+    int blockSize = 21;
+    double baseline = 70.;
+    double focus = 1000.;
+};
+
+} // namespace cpu
+} // namespace calib3d
+} // namespace gapi
+
+namespace detail {
+
+    template<> struct CompileArgTag<cv::gapi::calib3d::cpu::StereoInitParam> {
+    static const char* tag() {
+        return "org.opencv.stereoInit";
+    }
+};
+
+} // namespace detail
+} // namespace cv
+
+
+#endif // OPENCV_GAPI_CPU_STEREO_API_HPP
diff --git a/modules/gapi/include/opencv2/gapi/stereo.hpp b/modules/gapi/include/opencv2/gapi/stereo.hpp
new file mode 100644 (file)
index 0000000..908045d
--- /dev/null
@@ -0,0 +1,64 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distereoibution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2021 Intel Corporation
+
+#ifndef OPENCV_GAPI_STEREO_HPP
+#define OPENCV_GAPI_STEREO_HPP
+
+#include <opencv2/gapi/gmat.hpp>
+#include <opencv2/gapi/gscalar.hpp>
+#include <opencv2/gapi/gkernel.hpp>
+
+namespace cv {
+namespace gapi {
+
+enum class StereoOutputFormat {
+    DEPTH_FLOAT16,
+    DEPTH_FLOAT32,
+    DISPARITY_FIXED16_11_5,
+    DISPARITY_FIXED16_12_4
+};
+
+namespace calib3d {
+
+G_TYPED_KERNEL(GStereo, <GMat(GMat, GMat, const StereoOutputFormat)>, "org.opencv.stereo") {
+    static GMatDesc outMeta(const GMatDesc &left, const GMatDesc &right, const StereoOutputFormat of) {
+        GAPI_Assert(left.chan == 1);
+        GAPI_Assert(left.depth == CV_8U);
+
+        GAPI_Assert(right.chan == 1);
+        GAPI_Assert(right.depth == CV_8U);
+
+        switch(of) {
+            case StereoOutputFormat::DEPTH_FLOAT16:
+                return left.withDepth(CV_16FC1);
+            case StereoOutputFormat::DEPTH_FLOAT32:
+                return left.withDepth(CV_32FC1);
+            case StereoOutputFormat::DISPARITY_FIXED16_11_5:
+            case StereoOutputFormat::DISPARITY_FIXED16_12_4:
+                return left.withDepth(CV_16SC1);
+            default:
+                GAPI_Assert(false && "Unknown output format!");
+        }
+    }
+};
+
+} // namespace calib3d
+
+/** @brief Extract disparity/depth information depending on passed StereoOutputFormat argument.
+The function extracts disparity/depth information depending on passed StereoOutputFormat argument from
+given stereo-pair.
+
+@param left left 8-bit unsigned 1-channel image of @ref CV_8UC1 type
+@param right right 8-bit unsigned 1-channel image of @ref CV_8UC1 type
+@param of enum to specify output kind: depth or disparity and corresponding type
+*/
+GAPI_EXPORTS GMat stereo(const GMat& left,
+                         const GMat& right,
+                         const StereoOutputFormat of = StereoOutputFormat::DEPTH_FLOAT32);
+} // namespace gapi
+} // namespace cv
+
+#endif // OPENCV_GAPI_STEREO_HPP
diff --git a/modules/gapi/src/api/kernels_stereo.cpp b/modules/gapi/src/api/kernels_stereo.cpp
new file mode 100644 (file)
index 0000000..f336e8b
--- /dev/null
@@ -0,0 +1,18 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2021 Intel Corporation
+
+#include <opencv2/gapi/stereo.hpp>
+
+namespace cv { namespace gapi {
+
+GMat stereo(const GMat& left, const GMat& right,
+            const cv::gapi::StereoOutputFormat of)
+{
+    return calib3d::GStereo::on(left, right, of);
+}
+
+} // namespace cv
+} // namespace gapi
diff --git a/modules/gapi/src/backends/cpu/gcpustereo.cpp b/modules/gapi/src/backends/cpu/gcpustereo.cpp
new file mode 100644 (file)
index 0000000..9b51d23
--- /dev/null
@@ -0,0 +1,85 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2021 Intel Corporation
+
+#include <opencv2/gapi/stereo.hpp>
+#include <opencv2/gapi/cpu/stereo.hpp>
+#include <opencv2/gapi/cpu/gcpukernel.hpp>
+
+#ifdef HAVE_OPENCV_CALIB3D
+#include <opencv2/calib3d.hpp>
+#endif // HAVE_OPENCV_CALIB3D
+
+#ifdef HAVE_OPENCV_CALIB3D
+
+/** @brief Structure for the Stereo operation setup parameters.*/
+struct GAPI_EXPORTS StereoSetup {
+    double baseline;
+    double focus;
+    cv::Ptr<cv::StereoBM> stereoBM;
+};
+
+namespace {
+cv::Mat calcDepth(const cv::Mat &left, const cv::Mat &right,
+                  const StereoSetup &ss) {
+    constexpr int DISPARITY_SHIFT_16S = 4;
+    cv::Mat disp;
+    ss.stereoBM->compute(left, right, disp);
+    disp.convertTo(disp, CV_32FC1, 1./(1 << DISPARITY_SHIFT_16S), 0);
+    return (ss.focus * ss.baseline) / disp;
+}
+} // anonymous namespace
+
+GAPI_OCV_KERNEL_ST(GCPUStereo, cv::gapi::calib3d::GStereo, StereoSetup)
+{
+    static void setup(const cv::GMatDesc&, const cv::GMatDesc&,
+                      const cv::gapi::StereoOutputFormat,
+                      std::shared_ptr<StereoSetup> &stereoSetup,
+                      const cv::GCompileArgs &compileArgs) {
+        auto stereoInit = cv::gapi::getCompileArg<cv::gapi::calib3d::cpu::StereoInitParam>(compileArgs)
+            .value_or(cv::gapi::calib3d::cpu::StereoInitParam{});
+
+        StereoSetup ss{stereoInit.baseline,
+                       stereoInit.focus,
+                       cv::StereoBM::create(stereoInit.numDisparities,
+                       stereoInit.blockSize)};
+        stereoSetup = std::make_shared<StereoSetup>(ss);
+    }
+    static void run(const cv::Mat& left,
+                    const cv::Mat& right,
+                    const cv::gapi::StereoOutputFormat oF,
+                    cv::Mat& out_mat,
+                    const StereoSetup &stereoSetup) {
+        switch(oF){
+            case cv::gapi::StereoOutputFormat::DEPTH_FLOAT16:
+                calcDepth(left, right, stereoSetup).convertTo(out_mat, CV_16FC1);
+                break;
+            case cv::gapi::StereoOutputFormat::DEPTH_FLOAT32:
+                calcDepth(left, right, stereoSetup).copyTo(out_mat);
+                break;
+            case cv::gapi::StereoOutputFormat::DISPARITY_FIXED16_12_4:
+                stereoSetup.stereoBM->compute(left, right, out_mat);
+                break;
+            case cv::gapi::StereoOutputFormat::DISPARITY_FIXED16_11_5:
+                GAPI_Assert(false && "This case may be supported in future.");
+            default:
+                GAPI_Assert(false && "Unknown output format!");
+        }
+    }
+};
+
+cv::gapi::GKernelPackage cv::gapi::calib3d::cpu::kernels() {
+    static auto pkg = cv::gapi::kernels<GCPUStereo>();
+    return pkg;
+}
+
+#else
+
+cv::gapi::GKernelPackage cv::gapi::calib3d::cpu::kernels()
+{
+    return GKernelPackage();
+}
+
+#endif // HAVE_OPENCV_CALIB3D
diff --git a/modules/gapi/test/common/gapi_stereo_tests.cpp b/modules/gapi/test/common/gapi_stereo_tests.cpp
new file mode 100644 (file)
index 0000000..1211422
--- /dev/null
@@ -0,0 +1,8 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2021 Intel Corporation
+
+#include "../test_precomp.hpp"
+#include "gapi_stereo_tests_inl.hpp"
diff --git a/modules/gapi/test/common/gapi_stereo_tests.hpp b/modules/gapi/test/common/gapi_stereo_tests.hpp
new file mode 100644 (file)
index 0000000..576f230
--- /dev/null
@@ -0,0 +1,26 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2021 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_STEREO_TESTS_HPP
+#define OPENCV_GAPI_STEREO_TESTS_HPP
+
+
+#include <opencv2/gapi/stereo.hpp> // fore cv::gapi::StereoOutputFormat
+
+#include "gapi_tests_common.hpp"
+#include "gapi_parsers_tests_common.hpp"
+
+namespace opencv_test
+{
+
+GAPI_TEST_FIXTURE(TestGAPIStereo, initMatsRandU, FIXTURE_API(cv::gapi::StereoOutputFormat, int, int, double, double, CompareMats), 6,
+                                                             oF, numDisparities, blockSize, baseline,
+                                                             focus, cmpF)
+
+} // namespace opencv_test
+
+#endif // OPENCV_GAPI_STEREO_TESTS_HPP
diff --git a/modules/gapi/test/common/gapi_stereo_tests_inl.hpp b/modules/gapi/test/common/gapi_stereo_tests_inl.hpp
new file mode 100644 (file)
index 0000000..7950531
--- /dev/null
@@ -0,0 +1,74 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2021 Intel Corporation
+
+#ifndef OPENCV_GAPI_STEREO_TESTS_INL_HPP
+#define OPENCV_GAPI_STEREO_TESTS_INL_HPP
+
+
+#include <opencv2/gapi/stereo.hpp>
+#include <opencv2/gapi/cpu/stereo.hpp>
+#include "gapi_stereo_tests.hpp"
+
+#ifdef HAVE_OPENCV_CALIB3D
+
+#include <opencv2/calib3d.hpp>
+
+namespace opencv_test {
+
+TEST_P(TestGAPIStereo, DisparityDepthTest)
+{
+    using format = cv::gapi::StereoOutputFormat;
+    switch(oF) {
+        case format::DEPTH_FLOAT16: dtype = CV_16FC1; break;
+        case format::DEPTH_FLOAT32: dtype = CV_32FC1; break;
+        case format::DISPARITY_FIXED16_12_4: dtype = CV_16SC1; break;
+        default: GAPI_Assert(false && "Unsupported format in test");
+    }
+    initOutMats(sz, dtype);
+
+    // G-API
+    cv::GMat inL, inR;
+    cv::GMat out = cv::gapi::stereo(inL, inR, oF);
+
+    cv::GComputation(cv::GIn(inL, inR), cv::GOut(out))
+        .apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat_gapi),
+        cv::compile_args(cv::gapi::calib3d::cpu::kernels(),
+                         cv::gapi::calib3d::cpu::StereoInitParam {
+                             numDisparities,
+                             blockSize,
+                             baseline,
+                             focus}));
+
+    // OpenCV
+    cv::StereoBM::create(numDisparities, blockSize)->compute(in_mat1,
+                                                             in_mat2,
+                                                             out_mat_ocv);
+
+    static const int DISPARITY_SHIFT_16S = 4;
+    switch(oF) {
+        case format::DEPTH_FLOAT16:
+            out_mat_ocv.convertTo(out_mat_ocv, CV_32FC1, 1./(1 << DISPARITY_SHIFT_16S), 0);
+            out_mat_ocv = (focus * baseline) / out_mat_ocv;
+            out_mat_ocv.convertTo(out_mat_ocv, CV_16FC1);
+            break;
+        case format::DEPTH_FLOAT32:
+            out_mat_ocv.convertTo(out_mat_ocv, CV_32FC1, 1./(1 << DISPARITY_SHIFT_16S), 0);
+            out_mat_ocv = (focus * baseline) / out_mat_ocv;
+            break;
+        case format::DISPARITY_FIXED16_12_4:
+            break;
+        default:
+            GAPI_Assert(false && "Unsupported format in test");
+    }
+
+    EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+}
+
+} // namespace opencv_test
+
+#endif // HAVE_OPENCV_CALIB3D
+
+#endif // OPENCV_GAPI_STEREO_TESTS_INL_HPP
diff --git a/modules/gapi/test/cpu/gapi_stereo_tests_cpu.cpp b/modules/gapi/test/cpu/gapi_stereo_tests_cpu.cpp
new file mode 100644 (file)
index 0000000..5a70b5f
--- /dev/null
@@ -0,0 +1,36 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2021 Intel Corporation
+
+
+#include "../test_precomp.hpp"
+#include "../common/gapi_stereo_tests.hpp"
+
+#include <opencv2/gapi/stereo.hpp> // For ::gapi::stereo::disparity/depth
+#include <opencv2/gapi/cpu/stereo.hpp>
+
+namespace
+{
+#define STEREO_CPU [] () { return cv::compile_args(cv::gapi::use_only{cv::gapi::calib3d::cpu::kernels()}); }
+}  // anonymous namespace
+
+namespace opencv_test
+{
+
+INSTANTIATE_TEST_CASE_P(CPU_Tests, TestGAPIStereo,
+                        Combine(Values(CV_8UC1),
+                                Values(cv::Size(1280, 720)),
+                                Values(CV_32FC1),
+                                Values(STEREO_CPU),
+                                Values(cv::gapi::StereoOutputFormat::DEPTH_FLOAT16,
+                                       cv::gapi::StereoOutputFormat::DEPTH_FLOAT32,
+                                       cv::gapi::StereoOutputFormat::DISPARITY_FIXED16_12_4),
+                                Values(16),
+                                Values(43),
+                                Values(10.),
+                                Values(100.),
+                                Values(AbsExact().to_compare_obj())));
+
+} // opencv_test