From ecee388236cdfd737def724c3f9fca6ad6e0a4aa Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Wed, 24 Dec 2014 16:06:09 +0300 Subject: [PATCH] move buildWarp*Maps to stitching --- .../include/opencv2/cudawarping.hpp | 15 - modules/cudawarping/perf/perf_warping.cpp | 82 ----- modules/cudawarping/src/warp.cpp | 122 -------- modules/stitching/CMakeLists.txt | 5 + .../opencv2/stitching/detail/warpers.hpp | 2 - .../src/cuda/build_warp_maps.cu | 0 modules/stitching/src/warpers.cpp | 85 ------ modules/stitching/src/warpers_cuda.cpp | 283 ++++++++++++++++++ 8 files changed, 288 insertions(+), 306 deletions(-) rename modules/{cudawarping => stitching}/src/cuda/build_warp_maps.cu (100%) create mode 100644 modules/stitching/src/warpers_cuda.cpp diff --git a/modules/cudawarping/include/opencv2/cudawarping.hpp b/modules/cudawarping/include/opencv2/cudawarping.hpp index fbd63873bc..66c41ccefb 100644 --- a/modules/cudawarping/include/opencv2/cudawarping.hpp +++ b/modules/cudawarping/include/opencv2/cudawarping.hpp @@ -171,21 +171,6 @@ CV_EXPORTS void warpPerspective(InputArray src, OutputArray dst, InputArray M, S */ CV_EXPORTS void buildWarpPerspectiveMaps(InputArray M, bool inverse, Size dsize, OutputArray xmap, OutputArray ymap, Stream& stream = Stream::Null()); -/** @brief Builds plane warping maps. - */ -CV_EXPORTS void buildWarpPlaneMaps(Size src_size, Rect dst_roi, InputArray K, InputArray R, InputArray T, float scale, - OutputArray map_x, OutputArray map_y, Stream& stream = Stream::Null()); - -/** @brief Builds cylindrical warping maps. - */ -CV_EXPORTS void buildWarpCylindricalMaps(Size src_size, Rect dst_roi, InputArray K, InputArray R, float scale, - OutputArray map_x, OutputArray map_y, Stream& stream = Stream::Null()); - -/** @brief Builds spherical warping maps. - */ -CV_EXPORTS void buildWarpSphericalMaps(Size src_size, Rect dst_roi, InputArray K, InputArray R, float scale, - OutputArray map_x, OutputArray map_y, Stream& stream = Stream::Null()); - /** @brief Rotates an image around the origin (0,0) and then shifts it. @param src Source image. Supports 1, 3 or 4 channels images with CV_8U , CV_16U or CV_32F diff --git a/modules/cudawarping/perf/perf_warping.cpp b/modules/cudawarping/perf/perf_warping.cpp index 1096d3f441..36662418c3 100644 --- a/modules/cudawarping/perf/perf_warping.cpp +++ b/modules/cudawarping/perf/perf_warping.cpp @@ -325,88 +325,6 @@ PERF_TEST_P(Sz_Depth_Cn_Inter_Border, WarpPerspective, } } -////////////////////////////////////////////////////////////////////// -// BuildWarpPlaneMaps - -PERF_TEST_P(Sz, BuildWarpPlaneMaps, - CUDA_TYPICAL_MAT_SIZES) -{ - const cv::Size size = GetParam(); - - const cv::Mat K = cv::Mat::eye(3, 3, CV_32FC1); - const cv::Mat R = cv::Mat::ones(3, 3, CV_32FC1); - const cv::Mat T = cv::Mat::zeros(1, 3, CV_32F); - - if (PERF_RUN_CUDA()) - { - cv::cuda::GpuMat map_x; - cv::cuda::GpuMat map_y; - - TEST_CYCLE() cv::cuda::buildWarpPlaneMaps(size, cv::Rect(0, 0, size.width, size.height), K, R, T, 1.0, map_x, map_y); - - CUDA_SANITY_CHECK(map_x); - CUDA_SANITY_CHECK(map_y); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// BuildWarpCylindricalMaps - -PERF_TEST_P(Sz, BuildWarpCylindricalMaps, - CUDA_TYPICAL_MAT_SIZES) -{ - const cv::Size size = GetParam(); - - const cv::Mat K = cv::Mat::eye(3, 3, CV_32FC1); - const cv::Mat R = cv::Mat::ones(3, 3, CV_32FC1); - - if (PERF_RUN_CUDA()) - { - cv::cuda::GpuMat map_x; - cv::cuda::GpuMat map_y; - - TEST_CYCLE() cv::cuda::buildWarpCylindricalMaps(size, cv::Rect(0, 0, size.width, size.height), K, R, 1.0, map_x, map_y); - - CUDA_SANITY_CHECK(map_x); - CUDA_SANITY_CHECK(map_y); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// BuildWarpSphericalMaps - -PERF_TEST_P(Sz, BuildWarpSphericalMaps, - CUDA_TYPICAL_MAT_SIZES) -{ - const cv::Size size = GetParam(); - - const cv::Mat K = cv::Mat::eye(3, 3, CV_32FC1); - const cv::Mat R = cv::Mat::ones(3, 3, CV_32FC1); - - if (PERF_RUN_CUDA()) - { - cv::cuda::GpuMat map_x; - cv::cuda::GpuMat map_y; - - TEST_CYCLE() cv::cuda::buildWarpSphericalMaps(size, cv::Rect(0, 0, size.width, size.height), K, R, 1.0, map_x, map_y); - - CUDA_SANITY_CHECK(map_x); - CUDA_SANITY_CHECK(map_y); - } - else - { - FAIL_NO_CPU(); - } -} - ////////////////////////////////////////////////////////////////////// // Rotate diff --git a/modules/cudawarping/src/warp.cpp b/modules/cudawarping/src/warp.cpp index 121ea5c018..99554e3122 100644 --- a/modules/cudawarping/src/warp.cpp +++ b/modules/cudawarping/src/warp.cpp @@ -53,10 +53,6 @@ void cv::cuda::buildWarpAffineMaps(InputArray, bool, Size, OutputArray, OutputAr void cv::cuda::warpPerspective(InputArray, OutputArray, InputArray, Size, int, int, Scalar, Stream&) { throw_no_cuda(); } void cv::cuda::buildWarpPerspectiveMaps(InputArray, bool, Size, OutputArray, OutputArray, Stream&) { throw_no_cuda(); } -void cv::cuda::buildWarpPlaneMaps(Size, Rect, InputArray, InputArray, InputArray, float, OutputArray, OutputArray, Stream&) { throw_no_cuda(); } -void cv::cuda::buildWarpCylindricalMaps(Size, Rect, InputArray, InputArray, float, OutputArray, OutputArray, Stream&) { throw_no_cuda(); } -void cv::cuda::buildWarpSphericalMaps(Size, Rect, InputArray, InputArray, float, OutputArray, OutputArray, Stream&) { throw_no_cuda(); } - void cv::cuda::rotate(InputArray, OutputArray, Size, double, double, double, int, Stream&) { throw_no_cuda(); } #else // HAVE_CUDA @@ -462,124 +458,6 @@ void cv::cuda::warpPerspective(InputArray _src, OutputArray _dst, InputArray _M, } } -////////////////////////////////////////////////////////////////////////////// -// buildWarpPlaneMaps - -namespace cv { namespace cuda { namespace device -{ - namespace imgproc - { - void buildWarpPlaneMaps(int tl_u, int tl_v, PtrStepSzf map_x, PtrStepSzf map_y, - const float k_rinv[9], const float r_kinv[9], const float t[3], float scale, - cudaStream_t stream); - } -}}} - -void cv::cuda::buildWarpPlaneMaps(Size src_size, Rect dst_roi, InputArray _K, InputArray _R, InputArray _T, - float scale, OutputArray _map_x, OutputArray _map_y, Stream& stream) -{ - (void) src_size; - - Mat K = _K.getMat(); - Mat R = _R.getMat(); - Mat T = _T.getMat(); - - CV_Assert( K.size() == Size(3,3) && K.type() == CV_32FC1 ); - CV_Assert( R.size() == Size(3,3) && R.type() == CV_32FC1 ); - CV_Assert( (T.size() == Size(3,1) || T.size() == Size(1,3)) && T.type() == CV_32FC1 && T.isContinuous() ); - - Mat K_Rinv = K * R.t(); - Mat R_Kinv = R * K.inv(); - CV_Assert( K_Rinv.isContinuous() ); - CV_Assert( R_Kinv.isContinuous() ); - - _map_x.create(dst_roi.size(), CV_32FC1); - _map_y.create(dst_roi.size(), CV_32FC1); - - GpuMat map_x = _map_x.getGpuMat(); - GpuMat map_y = _map_y.getGpuMat(); - - device::imgproc::buildWarpPlaneMaps(dst_roi.tl().x, dst_roi.tl().y, map_x, map_y, K_Rinv.ptr(), R_Kinv.ptr(), - T.ptr(), scale, StreamAccessor::getStream(stream)); -} - -////////////////////////////////////////////////////////////////////////////// -// buildWarpCylyndricalMaps - -namespace cv { namespace cuda { namespace device -{ - namespace imgproc - { - void buildWarpCylindricalMaps(int tl_u, int tl_v, PtrStepSzf map_x, PtrStepSzf map_y, - const float k_rinv[9], const float r_kinv[9], float scale, - cudaStream_t stream); - } -}}} - -void cv::cuda::buildWarpCylindricalMaps(Size src_size, Rect dst_roi, InputArray _K, InputArray _R, float scale, - OutputArray _map_x, OutputArray _map_y, Stream& stream) -{ - (void) src_size; - - Mat K = _K.getMat(); - Mat R = _R.getMat(); - - CV_Assert( K.size() == Size(3,3) && K.type() == CV_32FC1 ); - CV_Assert( R.size() == Size(3,3) && R.type() == CV_32FC1 ); - - Mat K_Rinv = K * R.t(); - Mat R_Kinv = R * K.inv(); - CV_Assert( K_Rinv.isContinuous() ); - CV_Assert( R_Kinv.isContinuous() ); - - _map_x.create(dst_roi.size(), CV_32FC1); - _map_y.create(dst_roi.size(), CV_32FC1); - - GpuMat map_x = _map_x.getGpuMat(); - GpuMat map_y = _map_y.getGpuMat(); - - device::imgproc::buildWarpCylindricalMaps(dst_roi.tl().x, dst_roi.tl().y, map_x, map_y, K_Rinv.ptr(), R_Kinv.ptr(), scale, StreamAccessor::getStream(stream)); -} - - -////////////////////////////////////////////////////////////////////////////// -// buildWarpSphericalMaps - -namespace cv { namespace cuda { namespace device -{ - namespace imgproc - { - void buildWarpSphericalMaps(int tl_u, int tl_v, PtrStepSzf map_x, PtrStepSzf map_y, - const float k_rinv[9], const float r_kinv[9], float scale, - cudaStream_t stream); - } -}}} - -void cv::cuda::buildWarpSphericalMaps(Size src_size, Rect dst_roi, InputArray _K, InputArray _R, float scale, - OutputArray _map_x, OutputArray _map_y, Stream& stream) -{ - (void) src_size; - - Mat K = _K.getMat(); - Mat R = _R.getMat(); - - CV_Assert( K.size() == Size(3,3) && K.type() == CV_32FC1 ); - CV_Assert( R.size() == Size(3,3) && R.type() == CV_32FC1 ); - - Mat K_Rinv = K * R.t(); - Mat R_Kinv = R * K.inv(); - CV_Assert( K_Rinv.isContinuous() ); - CV_Assert( R_Kinv.isContinuous() ); - - _map_x.create(dst_roi.size(), CV_32FC1); - _map_y.create(dst_roi.size(), CV_32FC1); - - GpuMat map_x = _map_x.getGpuMat(); - GpuMat map_y = _map_y.getGpuMat(); - - device::imgproc::buildWarpSphericalMaps(dst_roi.tl().x, dst_roi.tl().y, map_x, map_y, K_Rinv.ptr(), R_Kinv.ptr(), scale, StreamAccessor::getStream(stream)); -} - //////////////////////////////////////////////////////////////////////// // rotate diff --git a/modules/stitching/CMakeLists.txt b/modules/stitching/CMakeLists.txt index 73db4a0310..8d11491be2 100644 --- a/modules/stitching/CMakeLists.txt +++ b/modules/stitching/CMakeLists.txt @@ -1,3 +1,8 @@ set(the_description "Images stitching") + +if(HAVE_CUDA) + ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef -Wmissing-declarations) +endif() + ocv_define_module(stitching opencv_imgproc opencv_features2d opencv_calib3d opencv_objdetect OPTIONAL opencv_cuda opencv_cudaarithm opencv_cudafilters opencv_cudafeatures2d opencv_xfeatures2d) diff --git a/modules/stitching/include/opencv2/stitching/detail/warpers.hpp b/modules/stitching/include/opencv2/stitching/detail/warpers.hpp index 79f387cc2f..19dff8e1f0 100644 --- a/modules/stitching/include/opencv2/stitching/detail/warpers.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/warpers.hpp @@ -398,7 +398,6 @@ public: }; -#ifdef HAVE_OPENCV_CUDAWARPING class CV_EXPORTS PlaneWarperGpu : public PlaneWarper { public: @@ -515,7 +514,6 @@ public: private: cuda::GpuMat d_xmap_, d_ymap_, d_src_, d_dst_; }; -#endif struct SphericalPortraitProjector : ProjectorBase diff --git a/modules/cudawarping/src/cuda/build_warp_maps.cu b/modules/stitching/src/cuda/build_warp_maps.cu similarity index 100% rename from modules/cudawarping/src/cuda/build_warp_maps.cu rename to modules/stitching/src/cuda/build_warp_maps.cu diff --git a/modules/stitching/src/warpers.cpp b/modules/stitching/src/warpers.cpp index 744474ba6e..4b6185f4e6 100644 --- a/modules/stitching/src/warpers.cpp +++ b/modules/stitching/src/warpers.cpp @@ -242,91 +242,6 @@ void SphericalWarper::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_b dst_br.y = static_cast(br_vf); } - -#ifdef HAVE_OPENCV_CUDAWARPING -Rect PlaneWarperGpu::buildMaps(Size src_size, InputArray K, InputArray R, cuda::GpuMat & xmap, cuda::GpuMat & ymap) -{ - return buildMaps(src_size, K, R, Mat::zeros(3, 1, CV_32F), xmap, ymap); -} - -Rect PlaneWarperGpu::buildMaps(Size src_size, InputArray K, InputArray R, InputArray T, cuda::GpuMat & xmap, cuda::GpuMat & ymap) -{ - projector_.setCameraParams(K, R, T); - - Point dst_tl, dst_br; - detectResultRoi(src_size, dst_tl, dst_br); - - cuda::buildWarpPlaneMaps(src_size, Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1)), - K, R, T, projector_.scale, xmap, ymap); - - return Rect(dst_tl, dst_br); -} - -Point PlaneWarperGpu::warp(const cuda::GpuMat & src, InputArray K, InputArray R, int interp_mode, int border_mode, - cuda::GpuMat & dst) -{ - return warp(src, K, R, Mat::zeros(3, 1, CV_32F), interp_mode, border_mode, dst); -} - - -Point PlaneWarperGpu::warp(const cuda::GpuMat & src, InputArray K, InputArray R, InputArray T, int interp_mode, int border_mode, - cuda::GpuMat & dst) -{ - Rect dst_roi = buildMaps(src.size(), K, R, T, d_xmap_, d_ymap_); - dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type()); - cuda::remap(src, dst, d_xmap_, d_ymap_, interp_mode, border_mode); - return dst_roi.tl(); -} - - -Rect SphericalWarperGpu::buildMaps(Size src_size, InputArray K, InputArray R, cuda::GpuMat & xmap, cuda::GpuMat & ymap) -{ - projector_.setCameraParams(K, R); - - Point dst_tl, dst_br; - detectResultRoi(src_size, dst_tl, dst_br); - - cuda::buildWarpSphericalMaps(src_size, Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1)), - K, R, projector_.scale, xmap, ymap); - - return Rect(dst_tl, dst_br); -} - - -Point SphericalWarperGpu::warp(const cuda::GpuMat & src, InputArray K, InputArray R, int interp_mode, int border_mode, - cuda::GpuMat & dst) -{ - Rect dst_roi = buildMaps(src.size(), K, R, d_xmap_, d_ymap_); - dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type()); - cuda::remap(src, dst, d_xmap_, d_ymap_, interp_mode, border_mode); - return dst_roi.tl(); -} - - -Rect CylindricalWarperGpu::buildMaps(Size src_size, InputArray K, InputArray R, cuda::GpuMat & xmap, cuda::GpuMat & ymap) -{ - projector_.setCameraParams(K, R); - - Point dst_tl, dst_br; - detectResultRoi(src_size, dst_tl, dst_br); - - cuda::buildWarpCylindricalMaps(src_size, Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1)), - K, R, projector_.scale, xmap, ymap); - - return Rect(dst_tl, dst_br); -} - - -Point CylindricalWarperGpu::warp(const cuda::GpuMat & src, InputArray K, InputArray R, int interp_mode, int border_mode, - cuda::GpuMat & dst) -{ - Rect dst_roi = buildMaps(src.size(), K, R, d_xmap_, d_ymap_); - dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type()); - cuda::remap(src, dst, d_xmap_, d_ymap_, interp_mode, border_mode); - return dst_roi.tl(); -} -#endif - void SphericalPortraitWarper::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) { detectResultRoiByBorder(src_size, dst_tl, dst_br); diff --git a/modules/stitching/src/warpers_cuda.cpp b/modules/stitching/src/warpers_cuda.cpp new file mode 100644 index 0000000000..0593e6d9e1 --- /dev/null +++ b/modules/stitching/src/warpers_cuda.cpp @@ -0,0 +1,283 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "precomp.hpp" +#include "opencv2/core/private.cuda.hpp" + +using namespace cv; +using namespace cv::cuda; + +Rect cv::detail::PlaneWarperGpu::buildMaps(Size src_size, InputArray K, InputArray R, + cuda::GpuMat & xmap, cuda::GpuMat & ymap) +{ + return buildMaps(src_size, K, R, Mat::zeros(3, 1, CV_32F), xmap, ymap); +} + +#ifdef HAVE_CUDA + +namespace cv { namespace cuda { namespace device +{ + namespace imgproc + { + void buildWarpPlaneMaps(int tl_u, int tl_v, PtrStepSzf map_x, PtrStepSzf map_y, + const float k_rinv[9], const float r_kinv[9], const float t[3], float scale, + cudaStream_t stream); + } +}}} + +static void buildWarpPlaneMaps(Size src_size, Rect dst_roi, InputArray _K, InputArray _R, InputArray _T, + float scale, OutputArray _map_x, OutputArray _map_y, Stream& stream = Stream::Null()) +{ + (void) src_size; + + Mat K = _K.getMat(); + Mat R = _R.getMat(); + Mat T = _T.getMat(); + + CV_Assert( K.size() == Size(3,3) && K.type() == CV_32FC1 ); + CV_Assert( R.size() == Size(3,3) && R.type() == CV_32FC1 ); + CV_Assert( (T.size() == Size(3,1) || T.size() == Size(1,3)) && T.type() == CV_32FC1 && T.isContinuous() ); + + Mat K_Rinv = K * R.t(); + Mat R_Kinv = R * K.inv(); + CV_Assert( K_Rinv.isContinuous() ); + CV_Assert( R_Kinv.isContinuous() ); + + _map_x.create(dst_roi.size(), CV_32FC1); + _map_y.create(dst_roi.size(), CV_32FC1); + + GpuMat map_x = _map_x.getGpuMat(); + GpuMat map_y = _map_y.getGpuMat(); + + device::imgproc::buildWarpPlaneMaps(dst_roi.tl().x, dst_roi.tl().y, map_x, map_y, K_Rinv.ptr(), R_Kinv.ptr(), + T.ptr(), scale, StreamAccessor::getStream(stream)); +} + +#endif + +Rect cv::detail::PlaneWarperGpu::buildMaps(Size src_size, InputArray K, InputArray R, InputArray T, + cuda::GpuMat & xmap, cuda::GpuMat & ymap) +{ +#ifndef HAVE_CUDA + (void)src_size; + (void)K; + (void)R; + (void)T; + (void)xmap; + (void)ymap; + throw_no_cuda(); + return Rect(); +#else + projector_.setCameraParams(K, R, T); + + Point dst_tl, dst_br; + detectResultRoi(src_size, dst_tl, dst_br); + + ::buildWarpPlaneMaps(src_size, Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1)), + K, R, T, projector_.scale, xmap, ymap); + + return Rect(dst_tl, dst_br); +#endif +} + +Point cv::detail::PlaneWarperGpu::warp(const cuda::GpuMat & src, InputArray K, InputArray R, + int interp_mode, int border_mode, + cuda::GpuMat & dst) +{ + return warp(src, K, R, Mat::zeros(3, 1, CV_32F), interp_mode, border_mode, dst); +} + + +Point cv::detail::PlaneWarperGpu::warp(const cuda::GpuMat & src, InputArray K, InputArray R, InputArray T, + int interp_mode, int border_mode, + cuda::GpuMat & dst) +{ + Rect dst_roi = buildMaps(src.size(), K, R, T, d_xmap_, d_ymap_); + dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type()); + cuda::remap(src, dst, d_xmap_, d_ymap_, interp_mode, border_mode); + return dst_roi.tl(); +} + +#ifdef HAVE_CUDA + +namespace cv { namespace cuda { namespace device +{ + namespace imgproc + { + void buildWarpSphericalMaps(int tl_u, int tl_v, PtrStepSzf map_x, PtrStepSzf map_y, + const float k_rinv[9], const float r_kinv[9], float scale, + cudaStream_t stream); + } +}}} + +static void buildWarpSphericalMaps(Size src_size, Rect dst_roi, InputArray _K, InputArray _R, float scale, + OutputArray _map_x, OutputArray _map_y, Stream& stream = Stream::Null()) +{ + (void) src_size; + + Mat K = _K.getMat(); + Mat R = _R.getMat(); + + CV_Assert( K.size() == Size(3,3) && K.type() == CV_32FC1 ); + CV_Assert( R.size() == Size(3,3) && R.type() == CV_32FC1 ); + + Mat K_Rinv = K * R.t(); + Mat R_Kinv = R * K.inv(); + CV_Assert( K_Rinv.isContinuous() ); + CV_Assert( R_Kinv.isContinuous() ); + + _map_x.create(dst_roi.size(), CV_32FC1); + _map_y.create(dst_roi.size(), CV_32FC1); + + GpuMat map_x = _map_x.getGpuMat(); + GpuMat map_y = _map_y.getGpuMat(); + + device::imgproc::buildWarpSphericalMaps(dst_roi.tl().x, dst_roi.tl().y, map_x, map_y, K_Rinv.ptr(), R_Kinv.ptr(), scale, StreamAccessor::getStream(stream)); +} + +#endif + +Rect cv::detail::SphericalWarperGpu::buildMaps(Size src_size, InputArray K, InputArray R, cuda::GpuMat & xmap, cuda::GpuMat & ymap) +{ +#ifndef HAVE_CUDA + (void)src_size; + (void)K; + (void)R; + (void)xmap; + (void)ymap; + throw_no_cuda(); + return Rect(); +#else + projector_.setCameraParams(K, R); + + Point dst_tl, dst_br; + detectResultRoi(src_size, dst_tl, dst_br); + + ::buildWarpSphericalMaps(src_size, Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1)), + K, R, projector_.scale, xmap, ymap); + + return Rect(dst_tl, dst_br); +#endif +} + +Point cv::detail::SphericalWarperGpu::warp(const cuda::GpuMat & src, InputArray K, InputArray R, + int interp_mode, int border_mode, + cuda::GpuMat & dst) +{ + Rect dst_roi = buildMaps(src.size(), K, R, d_xmap_, d_ymap_); + dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type()); + cuda::remap(src, dst, d_xmap_, d_ymap_, interp_mode, border_mode); + return dst_roi.tl(); +} + +#ifdef HAVE_CUDA + +namespace cv { namespace cuda { namespace device +{ + namespace imgproc + { + void buildWarpCylindricalMaps(int tl_u, int tl_v, PtrStepSzf map_x, PtrStepSzf map_y, + const float k_rinv[9], const float r_kinv[9], float scale, + cudaStream_t stream); + } +}}} + +static void buildWarpCylindricalMaps(Size src_size, Rect dst_roi, InputArray _K, InputArray _R, float scale, + OutputArray _map_x, OutputArray _map_y, Stream& stream = Stream::Null()) +{ + (void) src_size; + + Mat K = _K.getMat(); + Mat R = _R.getMat(); + + CV_Assert( K.size() == Size(3,3) && K.type() == CV_32FC1 ); + CV_Assert( R.size() == Size(3,3) && R.type() == CV_32FC1 ); + + Mat K_Rinv = K * R.t(); + Mat R_Kinv = R * K.inv(); + CV_Assert( K_Rinv.isContinuous() ); + CV_Assert( R_Kinv.isContinuous() ); + + _map_x.create(dst_roi.size(), CV_32FC1); + _map_y.create(dst_roi.size(), CV_32FC1); + + GpuMat map_x = _map_x.getGpuMat(); + GpuMat map_y = _map_y.getGpuMat(); + + device::imgproc::buildWarpCylindricalMaps(dst_roi.tl().x, dst_roi.tl().y, map_x, map_y, K_Rinv.ptr(), R_Kinv.ptr(), scale, StreamAccessor::getStream(stream)); +} + +#endif + +Rect cv::detail::CylindricalWarperGpu::buildMaps(Size src_size, InputArray K, InputArray R, + cuda::GpuMat & xmap, cuda::GpuMat & ymap) +{ +#ifndef HAVE_CUDA + (void)src_size; + (void)K; + (void)R; + (void)xmap; + (void)ymap; + throw_no_cuda(); + return Rect(); +#else + projector_.setCameraParams(K, R); + + Point dst_tl, dst_br; + detectResultRoi(src_size, dst_tl, dst_br); + + ::buildWarpCylindricalMaps(src_size, Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1)), + K, R, projector_.scale, xmap, ymap); + + return Rect(dst_tl, dst_br); +#endif +} + +Point cv::detail::CylindricalWarperGpu::warp(const cuda::GpuMat & src, InputArray K, InputArray R, + int interp_mode, int border_mode, + cuda::GpuMat & dst) +{ + Rect dst_roi = buildMaps(src.size(), K, R, d_xmap_, d_ymap_); + dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type()); + cuda::remap(src, dst, d_xmap_, d_ymap_, interp_mode, border_mode); + return dst_roi.tl(); +}