diff --git a/modules/stitching/include/opencv2/stitching/detail/warpers.hpp b/modules/stitching/include/opencv2/stitching/detail/warpers.hpp index 12600a6c8f..6efcee6068 100644 --- a/modules/stitching/include/opencv2/stitching/detail/warpers.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/warpers.hpp @@ -52,18 +52,20 @@ namespace cv { namespace detail { -class CV_EXPORTS Warper +class CV_EXPORTS RotationWarper { public: - virtual ~Warper() {} - virtual Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, - int interp_mode, int border_mode) = 0; - virtual void warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Size dstSize, - int interp_mode, int border_mode) = 0; - virtual Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst, - int interp_mode, int border_mode) = 0; - virtual Rect warpRoi(const Size &sz, const Mat &K, const Mat &R) = 0; - virtual Rect warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T) = 0; + virtual ~RotationWarper() {} + + virtual Rect buildMaps(Size src_size, const Mat &K, const Mat &R, Mat &xmap, Mat &ymap) = 0; + + virtual Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode, + Mat &dst) = 0; + + virtual void warpBackward(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode, + Size dst_size, Mat &dst) = 0; + + virtual Rect warpRoi(Size src_size, const Mat &K, const Mat &R) = 0; }; @@ -83,27 +85,28 @@ struct CV_EXPORTS ProjectorBase template -class CV_EXPORTS WarperBase : public Warper +class CV_EXPORTS RotationWarperBase : public RotationWarper { public: - Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, - int interp_mode, int border_mode); - void warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Size dstSize, - int interp_mode, int border_mode); - Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst, - int interp_mode, int border_mode); - Rect warpRoi(const Size &sz, const Mat &K, const Mat &R); - Rect warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T); + Rect buildMaps(Size src_size, const Mat &K, const Mat &R, Mat &xmap, Mat &ymap); + + Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode, + Mat &dst); + + void warpBackward(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode, + Size dst_size, Mat &dst); + + Rect warpRoi(Size src_size, const Mat &K, const Mat &R); protected: + // Detects ROI of the destination image. It's correct for any projection. - virtual void detectResultRoi(Point &dst_tl, Point &dst_br); + virtual void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br); // Detects ROI of the destination image by walking over image border. // Correctness for any projection isn't guaranteed. - void detectResultRoiByBorder(Point &dst_tl, Point &dst_br); + void detectResultRoiByBorder(Size src_size, Point &dst_tl, Point &dst_br); - Size src_size_; P projector_; }; @@ -116,17 +119,22 @@ struct CV_EXPORTS PlaneProjector : ProjectorBase // Projects image onto z = plane_dist plane -class CV_EXPORTS PlaneWarper : public WarperBase +class CV_EXPORTS PlaneWarper : public RotationWarperBase { public: PlaneWarper(float scale = 1.f) { projector_.scale = scale; } + void setScale(float scale) { projector_.scale = scale; } - Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst, - int interp_mode, int border_mode); - Rect warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T); + + Rect buildMaps(Size src_size, const Mat &K, const Mat &R, const Mat &T, Mat &xmap, Mat &ymap); + + Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, int interp_mode, int border_mode, + Mat &dst); + + Rect warpRoi(Size src_size, const Mat &K, const Mat &R, const Mat &T); protected: - void detectResultRoi(Point &dst_tl, Point &dst_br); + void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br); }; @@ -135,10 +143,12 @@ class CV_EXPORTS PlaneWarperGpu : public PlaneWarper { public: PlaneWarperGpu(float scale = 1.f) : PlaneWarper(scale) {} - Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, - int interp_mode, int border_mode); - Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst, - int interp_mode, int border_mode); + + Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode, + Mat &dst); + + Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, int interp_mode, int border_mode, + Mat &dst); private: gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_; @@ -155,13 +165,13 @@ struct CV_EXPORTS SphericalProjector : ProjectorBase // Projects image onto unit sphere with origin at (0, 0, 0). // Poles are located at (0, -1, 0) and (0, 1, 0) points. -class CV_EXPORTS SphericalWarper : public WarperBase +class CV_EXPORTS SphericalWarper : public RotationWarperBase { public: SphericalWarper(float scale) { projector_.scale = scale; } protected: - void detectResultRoi(Point &dst_tl, Point &dst_br); + void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br); }; @@ -170,8 +180,9 @@ class CV_EXPORTS SphericalWarperGpu : public SphericalWarper { public: SphericalWarperGpu(float scale) : SphericalWarper(scale) {} - Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, - int interp_mode, int border_mode); + + Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode, + Mat &dst); private: gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_; @@ -187,14 +198,16 @@ struct CV_EXPORTS CylindricalProjector : ProjectorBase // Projects image onto x * x + z * z = 1 cylinder -class CV_EXPORTS CylindricalWarper : public WarperBase +class CV_EXPORTS CylindricalWarper : public RotationWarperBase { public: CylindricalWarper(float scale) { projector_.scale = scale; } protected: - void detectResultRoi(Point &dst_tl, Point &dst_br) - { WarperBase::detectResultRoiByBorder(dst_tl, dst_br); } + void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) + { + RotationWarperBase::detectResultRoiByBorder(src_size, dst_tl, dst_br); + } }; @@ -203,8 +216,9 @@ class CV_EXPORTS CylindricalWarperGpu : public CylindricalWarper { public: CylindricalWarperGpu(float scale) : CylindricalWarper(scale) {} - Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, - int interp_mode, int border_mode); + + Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode, + Mat &dst); private: gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_; diff --git a/modules/stitching/include/opencv2/stitching/detail/warpers_inl.hpp b/modules/stitching/include/opencv2/stitching/detail/warpers_inl.hpp index 3d44269cb5..389deda140 100644 --- a/modules/stitching/include/opencv2/stitching/detail/warpers_inl.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/warpers_inl.hpp @@ -50,17 +50,15 @@ namespace cv { namespace detail { template -Point WarperBase

::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, - int interp_mode, int border_mode) +Rect RotationWarperBase

::buildMaps(Size src_size, const Mat &K, const Mat &R, Mat &xmap, Mat &ymap) { - src_size_ = src.size(); projector_.setCameraParams(K, R); Point dst_tl, dst_br; - detectResultRoi(dst_tl, dst_br); + detectResultRoi(src_size, dst_tl, dst_br); - Mat xmap(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F); - Mat ymap(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F); + xmap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F); + ymap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F); float x, y; for (int v = dst_tl.y; v <= dst_br.y; ++v) @@ -73,30 +71,41 @@ Point WarperBase

::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, } } - dst.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, src.type()); + return Rect(dst_tl, dst_br); +} + + +template +Point RotationWarperBase

::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode, + Mat &dst) +{ + Mat xmap, ymap; + Rect dst_roi = buildMaps(src.size(), K, R, xmap, ymap); + + dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type()); remap(src, dst, xmap, ymap, interp_mode, border_mode); - return dst_tl; + return dst_roi.tl(); } + template -void WarperBase

::warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Size dstSize, - int interp_mode, int border_mode) +void RotationWarperBase

::warpBackward(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode, + Size dst_size, Mat &dst) { - src_size_ = dstSize; projector_.setCameraParams(K, R); Point src_tl, src_br; - detectResultRoi(src_tl, src_br); + detectResultRoi(dst_size, src_tl, src_br); CV_Assert(src_br.x - src_tl.x + 1 == src.cols && src_br.y - src_tl.y + 1 == src.rows); - Mat xmap(dstSize, CV_32F); - Mat ymap(dstSize, CV_32F); + Mat xmap(dst_size, CV_32F); + Mat ymap(dst_size, CV_32F); float u, v; - for (int y = 0; y < dstSize.height; ++y) + for (int y = 0; y < dst_size.height; ++y) { - for (int x = 0; x < dstSize.width; ++x) + for (int x = 0; x < dst_size.width; ++x) { projector_.mapForward(static_cast(x), static_cast(y), u, v); xmap.at(y, x) = u - src_tl.x; @@ -104,43 +113,25 @@ void WarperBase

::warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat } } - dst.create(dstSize, src.type()); + dst.create(dst_size, src.type()); remap(src, dst, xmap, ymap, interp_mode, border_mode); } template -Point WarperBase

::warp(const Mat &/*src*/, const Mat &/*K*/, const Mat &/*R*/, const Mat &/*T*/, Mat &/*dst*/, - int /*interp_mode*/, int /*border_mode*/) +Rect RotationWarperBase

::warpRoi(Size src_size, const Mat &K, const Mat &R) { - CV_Error(CV_StsNotImplemented, "translation support isn't implemented"); - return Point(); -} - - -template -Rect WarperBase

::warpRoi(const Size &sz, const Mat &K, const Mat &R) -{ - src_size_ = sz; projector_.setCameraParams(K, R); Point dst_tl, dst_br; - detectResultRoi(dst_tl, dst_br); + detectResultRoi(src_size, dst_tl, dst_br); return Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1)); } template -Rect WarperBase

::warpRoi(const Size &/*sz*/, const Mat &/*K*/, const Mat &/*R*/, const Mat &/*T*/) -{ - CV_Error(CV_StsNotImplemented, "translation support isn't implemented"); - return Rect(); -} - - -template -void WarperBase

::detectResultRoi(Point &dst_tl, Point &dst_br) +void RotationWarperBase

::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) { float tl_uf = std::numeric_limits::max(); float tl_vf = std::numeric_limits::max(); @@ -148,9 +139,9 @@ void WarperBase

::detectResultRoi(Point &dst_tl, Point &dst_br) float br_vf = -std::numeric_limits::max(); float u, v; - for (int y = 0; y < src_size_.height; ++y) + for (int y = 0; y < src_size.height; ++y) { - for (int x = 0; x < src_size_.width; ++x) + for (int x = 0; x < src_size.width; ++x) { projector_.mapForward(static_cast(x), static_cast(y), u, v); tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); @@ -166,7 +157,7 @@ void WarperBase

::detectResultRoi(Point &dst_tl, Point &dst_br) template -void WarperBase

::detectResultRoiByBorder(Point &dst_tl, Point &dst_br) +void RotationWarperBase

::detectResultRoiByBorder(Size src_size, Point &dst_tl, Point &dst_br) { float tl_uf = std::numeric_limits::max(); float tl_vf = std::numeric_limits::max(); @@ -174,23 +165,23 @@ void WarperBase

::detectResultRoiByBorder(Point &dst_tl, Point &dst_br) float br_vf = -std::numeric_limits::max(); float u, v; - for (float x = 0; x < src_size_.width; ++x) + for (float x = 0; x < src_size.width; ++x) { projector_.mapForward(static_cast(x), 0, u, v); tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); - projector_.mapForward(static_cast(x), static_cast(src_size_.height - 1), u, v); + projector_.mapForward(static_cast(x), static_cast(src_size.height - 1), u, v); tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); } - for (int y = 0; y < src_size_.height; ++y) + for (int y = 0; y < src_size.height; ++y) { projector_.mapForward(0, static_cast(y), u, v); tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); - projector_.mapForward(static_cast(src_size_.width - 1), static_cast(y), u, v); + projector_.mapForward(static_cast(src_size.width - 1), static_cast(y), u, v); tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); } diff --git a/modules/stitching/include/opencv2/stitching/warpers.hpp b/modules/stitching/include/opencv2/stitching/warpers.hpp index 6f3c94472b..b612de6e07 100644 --- a/modules/stitching/include/opencv2/stitching/warpers.hpp +++ b/modules/stitching/include/opencv2/stitching/warpers.hpp @@ -51,28 +51,28 @@ class WarperCreator { public: virtual ~WarperCreator() {} - virtual Ptr create(float scale) const = 0; + virtual Ptr create(float scale) const = 0; }; class PlaneWarper : public WarperCreator { public: - Ptr create(float scale) const { return new detail::PlaneWarper(scale); } + Ptr create(float scale) const { return new detail::PlaneWarper(scale); } }; class CylindricalWarper: public WarperCreator { public: - Ptr create(float scale) const { return new detail::CylindricalWarper(scale); } + Ptr create(float scale) const { return new detail::CylindricalWarper(scale); } }; class SphericalWarper: public WarperCreator { public: - Ptr create(float scale) const { return new detail::SphericalWarper(scale); } + Ptr create(float scale) const { return new detail::SphericalWarper(scale); } }; @@ -80,21 +80,21 @@ public: class PlaneWarperGpu: public WarperCreator { public: - Ptr create(float scale) const { return new detail::PlaneWarperGpu(scale); } + Ptr create(float scale) const { return new detail::PlaneWarperGpu(scale); } }; class CylindricalWarperGpu: public WarperCreator { public: - Ptr create(float scale) const { return new detail::CylindricalWarperGpu(scale); } + Ptr create(float scale) const { return new detail::CylindricalWarperGpu(scale); } }; class SphericalWarperGpu: public WarperCreator { public: - Ptr create(float scale) const { return new detail::SphericalWarperGpu(scale); } + Ptr create(float scale) const { return new detail::SphericalWarperGpu(scale); } }; #endif diff --git a/modules/stitching/src/stitcher.cpp b/modules/stitching/src/stitcher.cpp index 47e3c437ba..9887fc10d8 100644 --- a/modules/stitching/src/stitcher.cpp +++ b/modules/stitching/src/stitcher.cpp @@ -261,7 +261,7 @@ Stitcher::Status Stitcher::composePanorama(Mat &pano) } // Warp images and their masks - Ptr warper = warper_->create(float(warped_image_scale_ * seam_work_aspect_)); + Ptr warper = warper_->create(float(warped_image_scale_ * seam_work_aspect_)); for (size_t i = 0; i < imgs_.size(); ++i) { Mat_ K; @@ -271,10 +271,10 @@ Stitcher::Status Stitcher::composePanorama(Mat &pano) K(1,1) *= (float)seam_work_aspect_; K(1,2) *= (float)seam_work_aspect_; - corners[i] = warper->warp(seam_est_imgs_[i], K, cameras_[i].R, images_warped[i], INTER_LINEAR, BORDER_REFLECT); + corners[i] = warper->warp(seam_est_imgs_[i], K, cameras_[i].R, INTER_LINEAR, BORDER_REFLECT, images_warped[i]); sizes[i] = images_warped[i].size(); - warper->warp(masks[i], K, cameras_[i].R, masks_warped[i], INTER_NEAREST, BORDER_CONSTANT); + warper->warp(masks[i], K, cameras_[i].R, INTER_NEAREST, BORDER_CONSTANT, masks_warped[i]); } vector images_warped_f(imgs_.size()); @@ -361,12 +361,12 @@ Stitcher::Status Stitcher::composePanorama(Mat &pano) cameras_[img_idx].K().convertTo(K, CV_32F); // Warp the current image - warper->warp(img, K, cameras_[img_idx].R, img_warped, INTER_LINEAR, BORDER_REFLECT); + warper->warp(img, K, cameras_[img_idx].R, INTER_LINEAR, BORDER_REFLECT, img_warped); // Warp the current image mask mask.create(img_size, CV_8U); mask.setTo(Scalar::all(255)); - warper->warp(mask, K, cameras_[img_idx].R, mask_warped, INTER_NEAREST, BORDER_CONSTANT); + warper->warp(mask, K, cameras_[img_idx].R, INTER_NEAREST, BORDER_CONSTANT, mask_warped); // Compensate exposure exposure_comp_->apply(img_idx, corners[img_idx], img_warped, mask_warped); diff --git a/modules/stitching/src/warpers.cpp b/modules/stitching/src/warpers.cpp index 68938c1aa7..652de128d1 100644 --- a/modules/stitching/src/warpers.cpp +++ b/modules/stitching/src/warpers.cpp @@ -78,17 +78,15 @@ void ProjectorBase::setCameraParams(const Mat &K, const Mat &R, const Mat &T) } -Point PlaneWarper::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst, - int interp_mode, int border_mode) +Rect PlaneWarper::buildMaps(Size src_size, const Mat &K, const Mat &R, const Mat &T, Mat &xmap, Mat &ymap) { - src_size_ = src.size(); projector_.setCameraParams(K, R, T); Point dst_tl, dst_br; - detectResultRoi(dst_tl, dst_br); + detectResultRoi(src_size, dst_tl, dst_br); - Mat xmap(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F); - Mat ymap(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F); + xmap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F); + ymap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F); float x, y; for (int v = dst_tl.y; v <= dst_br.y; ++v) @@ -101,26 +99,35 @@ Point PlaneWarper::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T } } - dst.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, src.type()); + return Rect(dst_tl, dst_br); +} + + +Point PlaneWarper::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, int interp_mode, int border_mode, + Mat &dst) +{ + Mat xmap, ymap; + Rect dst_roi = buildMaps(src.size(), K, R, T, xmap, ymap); + + dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type()); remap(src, dst, xmap, ymap, interp_mode, border_mode); - return dst_tl; + return dst_roi.tl(); } -Rect PlaneWarper::warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T) +Rect PlaneWarper::warpRoi(Size src_size, const Mat &K, const Mat &R, const Mat &T) { - src_size_ = sz; projector_.setCameraParams(K, R, T); Point dst_tl, dst_br; - detectResultRoi(dst_tl, dst_br); + detectResultRoi(src_size, dst_tl, dst_br); return Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1)); } -void PlaneWarper::detectResultRoi(Point &dst_tl, Point &dst_br) +void PlaneWarper::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) { float tl_uf = numeric_limits::max(); float tl_vf = numeric_limits::max(); @@ -133,15 +140,15 @@ void PlaneWarper::detectResultRoi(Point &dst_tl, Point &dst_br) tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v); br_uf = max(br_uf, u); br_vf = max(br_vf, v); - projector_.mapForward(0, static_cast(src_size_.height - 1), u, v); + projector_.mapForward(0, static_cast(src_size.height - 1), u, v); tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v); br_uf = max(br_uf, u); br_vf = max(br_vf, v); - projector_.mapForward(static_cast(src_size_.width - 1), 0, u, v); + projector_.mapForward(static_cast(src_size.width - 1), 0, u, v); tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v); br_uf = max(br_uf, u); br_vf = max(br_vf, v); - projector_.mapForward(static_cast(src_size_.width - 1), static_cast(src_size_.height - 1), u, v); + projector_.mapForward(static_cast(src_size.width - 1), static_cast(src_size.height - 1), u, v); tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v); br_uf = max(br_uf, u); br_vf = max(br_vf, v); @@ -153,21 +160,20 @@ void PlaneWarper::detectResultRoi(Point &dst_tl, Point &dst_br) #ifndef ANDROID -Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, - int interp_mode, int border_mode) +Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode, + Mat &dst) { - return warp(src, K, R, Mat::zeros(3, 1, CV_32F), dst, interp_mode, border_mode); + return warp(src, K, R, Mat::zeros(3, 1, CV_32F), interp_mode, border_mode, dst); } -Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst, - int interp_mode, int border_mode) +Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, int interp_mode, int border_mode, + Mat &dst) { - src_size_ = src.size(); projector_.setCameraParams(K, R, T); Point dst_tl, dst_br; - detectResultRoi(dst_tl, dst_br); + detectResultRoi(src.size(), dst_tl, dst_br); gpu::buildWarpPlaneMaps(src.size(), Rect(dst_tl, Point(dst_br.x+1, dst_br.y+1)), K, R, projector_.scale, d_xmap_, d_ymap_); @@ -186,9 +192,9 @@ Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, const Mat #endif -void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br) +void SphericalWarper::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) { - detectResultRoiByBorder(dst_tl, dst_br); + detectResultRoiByBorder(src_size, dst_tl, dst_br); float tl_uf = static_cast(dst_tl.x); float tl_vf = static_cast(dst_tl.y); @@ -202,7 +208,7 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br) { float x_ = (projector_.k[0] * x + projector_.k[1] * y) / z + projector_.k[2]; float y_ = projector_.k[4] * y / z + projector_.k[5]; - if (x_ > 0.f && x_ < src_size_.width && y_ > 0.f && y_ < src_size_.height) + if (x_ > 0.f && x_ < src_size.width && y_ > 0.f && y_ < src_size.height) { tl_uf = min(tl_uf, 0.f); tl_vf = min(tl_vf, static_cast(CV_PI * projector_.scale)); br_uf = max(br_uf, 0.f); br_vf = max(br_vf, static_cast(CV_PI * projector_.scale)); @@ -216,7 +222,7 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br) { float x_ = (projector_.k[0] * x + projector_.k[1] * y) / z + projector_.k[2]; float y_ = projector_.k[4] * y / z + projector_.k[5]; - if (x_ > 0.f && x_ < src_size_.width && y_ > 0.f && y_ < src_size_.height) + if (x_ > 0.f && x_ < src_size.width && y_ > 0.f && y_ < src_size.height) { tl_uf = min(tl_uf, 0.f); tl_vf = min(tl_vf, static_cast(0)); br_uf = max(br_uf, 0.f); br_vf = max(br_vf, static_cast(0)); @@ -231,14 +237,13 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br) #ifndef ANDROID -Point SphericalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, - int interp_mode, int border_mode) +Point SphericalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode, + Mat &dst) { - src_size_ = src.size(); projector_.setCameraParams(K, R); Point dst_tl, dst_br; - detectResultRoi(dst_tl, dst_br); + detectResultRoi(src.size(), dst_tl, dst_br); gpu::buildWarpSphericalMaps(src.size(), Rect(dst_tl, Point(dst_br.x+1, dst_br.y+1)), K, R, projector_.scale, d_xmap_, d_ymap_); @@ -256,14 +261,13 @@ Point SphericalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat & } -Point CylindricalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, - int interp_mode, int border_mode) +Point CylindricalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode, + Mat &dst) { - src_size_ = src.size(); projector_.setCameraParams(K, R); Point dst_tl, dst_br; - detectResultRoi(dst_tl, dst_br); + detectResultRoi(src.size(), dst_tl, dst_br); gpu::buildWarpCylindricalMaps(src.size(), Rect(dst_tl, Point(dst_br.x+1, dst_br.y+1)), K, R, projector_.scale, d_xmap_, d_ymap_); diff --git a/samples/cpp/stitching_detailed.cpp b/samples/cpp/stitching_detailed.cpp index 71e51d6372..6e1000716d 100644 --- a/samples/cpp/stitching_detailed.cpp +++ b/samples/cpp/stitching_detailed.cpp @@ -523,7 +523,7 @@ int main(int argc, char* argv[]) return 1; } - Ptr warper = warper_creator->create(static_cast(warped_image_scale * seam_work_aspect)); + Ptr warper = warper_creator->create(static_cast(warped_image_scale * seam_work_aspect)); for (int i = 0; i < num_images; ++i) { @@ -532,10 +532,10 @@ int main(int argc, char* argv[]) K(0,0) *= seam_work_aspect; K(0,2) *= seam_work_aspect; K(1,1) *= seam_work_aspect; K(1,2) *= seam_work_aspect; - corners[i] = warper->warp(images[i], K, cameras[i].R, images_warped[i], INTER_LINEAR, BORDER_REFLECT); + corners[i] = warper->warp(images[i], K, cameras[i].R, INTER_LINEAR, BORDER_REFLECT, images_warped[i]); sizes[i] = images_warped[i].size(); - warper->warp(masks[i], K, cameras[i].R, masks_warped[i], INTER_NEAREST, BORDER_CONSTANT); + warper->warp(masks[i], K, cameras[i].R, INTER_NEAREST, BORDER_CONSTANT, masks_warped[i]); } vector images_warped_f(num_images); @@ -647,12 +647,12 @@ int main(int argc, char* argv[]) cameras[img_idx].K().convertTo(K, CV_32F); // Warp the current image - warper->warp(img, K, cameras[img_idx].R, img_warped, INTER_LINEAR, BORDER_REFLECT); + warper->warp(img, K, cameras[img_idx].R, INTER_LINEAR, BORDER_REFLECT, img_warped); // Warp the current image mask mask.create(img_size, CV_8U); mask.setTo(Scalar::all(255)); - warper->warp(mask, K, cameras[img_idx].R, mask_warped, INTER_NEAREST, BORDER_CONSTANT); + warper->warp(mask, K, cameras[img_idx].R, INTER_NEAREST, BORDER_CONSTANT, mask_warped); // Compensate exposure compensator->apply(img_idx, corners[img_idx], img_warped, mask_warped);