Refactored warpers in the stitching module, added buildMaps function into the Rotatio...
authorAlexey Spizhevoy <no@email>
Mon, 3 Oct 2011 06:31:24 +0000 (06:31 +0000)
committerAlexey Spizhevoy <no@email>
Mon, 3 Oct 2011 06:31:24 +0000 (06:31 +0000)
modules/stitching/include/opencv2/stitching/detail/warpers.hpp
modules/stitching/include/opencv2/stitching/detail/warpers_inl.hpp
modules/stitching/include/opencv2/stitching/warpers.hpp
modules/stitching/src/stitcher.cpp
modules/stitching/src/warpers.cpp
samples/cpp/stitching_detailed.cpp

index 12600a6..6efcee6 100644 (file)
 namespace cv {\r
 namespace detail {\r
 \r
-class CV_EXPORTS Warper\r
+class CV_EXPORTS RotationWarper\r
 {\r
 public:\r
-    virtual ~Warper() {}\r
-    virtual Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,\r
-                       int interp_mode, int border_mode) = 0;\r
-    virtual void warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Size dstSize,\r
-                       int interp_mode, int border_mode) = 0;\r
-    virtual Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst,\r
-                       int interp_mode, int border_mode) = 0;\r
-    virtual Rect warpRoi(const Size &sz, const Mat &K, const Mat &R) = 0;\r
-    virtual Rect warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T) = 0;\r
+    virtual ~RotationWarper() {}\r
+\r
+    virtual Rect buildMaps(Size src_size, const Mat &K, const Mat &R, Mat &xmap, Mat &ymap) = 0;\r
+\r
+    virtual Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,\r
+                       Mat &dst) = 0;\r
+\r
+    virtual void warpBackward(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,\r
+                              Size dst_size, Mat &dst) = 0;\r
+\r
+    virtual Rect warpRoi(Size src_size, const Mat &K, const Mat &R) = 0;\r
 };\r
 \r
 \r
@@ -83,27 +85,28 @@ struct CV_EXPORTS ProjectorBase
 \r
 \r
 template <class P>\r
-class CV_EXPORTS WarperBase : public Warper\r
+class CV_EXPORTS RotationWarperBase : public RotationWarper\r
 {   \r
 public:\r
-    Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,\r
-               int interp_mode, int border_mode);\r
-    void warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Size dstSize,\r
-               int interp_mode, int border_mode);\r
-    Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst,\r
-               int interp_mode, int border_mode);\r
-    Rect warpRoi(const Size &sz, const Mat &K, const Mat &R);\r
-    Rect warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T);\r
+    Rect buildMaps(Size src_size, const Mat &K, const Mat &R, Mat &xmap, Mat &ymap);\r
+\r
+    Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,\r
+               Mat &dst);\r
+\r
+    void warpBackward(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,\r
+                      Size dst_size, Mat &dst);\r
+\r
+    Rect warpRoi(Size src_size, const Mat &K, const Mat &R);\r
 \r
 protected:\r
+\r
     // Detects ROI of the destination image. It's correct for any projection.\r
-    virtual void detectResultRoi(Point &dst_tl, Point &dst_br);\r
+    virtual void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br);\r
 \r
     // Detects ROI of the destination image by walking over image border.\r
     // Correctness for any projection isn't guaranteed.\r
-    void detectResultRoiByBorder(Point &dst_tl, Point &dst_br);\r
+    void detectResultRoiByBorder(Size src_size, Point &dst_tl, Point &dst_br);\r
 \r
-    Size src_size_;\r
     P projector_;\r
 };\r
 \r
@@ -116,17 +119,22 @@ struct CV_EXPORTS PlaneProjector : ProjectorBase
 \r
 \r
 // Projects image onto z = plane_dist plane\r
-class CV_EXPORTS PlaneWarper : public WarperBase<PlaneProjector>\r
+class CV_EXPORTS PlaneWarper : public RotationWarperBase<PlaneProjector>\r
 {\r
 public:\r
     PlaneWarper(float scale = 1.f) { projector_.scale = scale; }\r
+\r
     void setScale(float scale) { projector_.scale = scale; }\r
-    Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst,\r
-               int interp_mode, int border_mode);\r
-    Rect warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T);\r
+\r
+    Rect buildMaps(Size src_size, const Mat &K, const Mat &R, const Mat &T, Mat &xmap, Mat &ymap);\r
+\r
+    Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, int interp_mode, int border_mode,\r
+               Mat &dst);\r
+\r
+    Rect warpRoi(Size src_size, const Mat &K, const Mat &R, const Mat &T);\r
 \r
 protected:\r
-    void detectResultRoi(Point &dst_tl, Point &dst_br);\r
+    void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br);\r
 };\r
 \r
 \r
@@ -135,10 +143,12 @@ class CV_EXPORTS PlaneWarperGpu : public PlaneWarper
 {\r
 public:\r
     PlaneWarperGpu(float scale = 1.f) : PlaneWarper(scale) {}\r
-    Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,\r
-               int interp_mode, int border_mode);\r
-    Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst,\r
-               int interp_mode, int border_mode);\r
+\r
+    Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,\r
+               Mat &dst);\r
+\r
+    Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, int interp_mode, int border_mode,\r
+               Mat &dst);\r
 \r
 private:\r
     gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_;\r
@@ -155,13 +165,13 @@ struct CV_EXPORTS SphericalProjector : ProjectorBase
 \r
 // Projects image onto unit sphere with origin at (0, 0, 0).\r
 // Poles are located at (0, -1, 0) and (0, 1, 0) points.\r
-class CV_EXPORTS SphericalWarper : public WarperBase<SphericalProjector>\r
+class CV_EXPORTS SphericalWarper : public RotationWarperBase<SphericalProjector>\r
 {\r
 public:\r
     SphericalWarper(float scale) { projector_.scale = scale; }\r
 \r
 protected:\r
-    void detectResultRoi(Point &dst_tl, Point &dst_br);\r
+    void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br);\r
 };\r
 \r
 \r
@@ -170,8 +180,9 @@ class CV_EXPORTS SphericalWarperGpu : public SphericalWarper
 {\r
 public:\r
     SphericalWarperGpu(float scale) : SphericalWarper(scale) {}\r
-    Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,\r
-               int interp_mode, int border_mode);\r
+\r
+    Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,\r
+               Mat &dst);\r
 \r
 private:\r
     gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_;\r
@@ -187,14 +198,16 @@ struct CV_EXPORTS CylindricalProjector : ProjectorBase
 \r
 \r
 // Projects image onto x * x + z * z = 1 cylinder\r
-class CV_EXPORTS CylindricalWarper : public WarperBase<CylindricalProjector>\r
+class CV_EXPORTS CylindricalWarper : public RotationWarperBase<CylindricalProjector>\r
 {\r
 public:\r
     CylindricalWarper(float scale) { projector_.scale = scale; }\r
 \r
 protected:\r
-    void detectResultRoi(Point &dst_tl, Point &dst_br)\r
-        { WarperBase<CylindricalProjector>::detectResultRoiByBorder(dst_tl, dst_br); }\r
+    void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)\r
+    { \r
+        RotationWarperBase<CylindricalProjector>::detectResultRoiByBorder(src_size, dst_tl, dst_br); \r
+    }\r
 };\r
 \r
 \r
@@ -203,8 +216,9 @@ class CV_EXPORTS CylindricalWarperGpu : public CylindricalWarper
 {\r
 public:\r
     CylindricalWarperGpu(float scale) : CylindricalWarper(scale) {}\r
-    Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,\r
-               int interp_mode, int border_mode);\r
+\r
+    Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,\r
+               Mat &dst);\r
 \r
 private:\r
     gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_;\r
index 3d44269..389deda 100644 (file)
@@ -50,17 +50,15 @@ namespace cv {
 namespace detail {\r
 \r
 template <class P>\r
-Point WarperBase<P>::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,\r
-                          int interp_mode, int border_mode)\r
+Rect RotationWarperBase<P>::buildMaps(Size src_size, const Mat &K, const Mat &R, Mat &xmap, Mat &ymap)\r
 {\r
-    src_size_ = src.size();\r
     projector_.setCameraParams(K, R);\r
 \r
     Point dst_tl, dst_br;\r
-    detectResultRoi(dst_tl, dst_br);\r
+    detectResultRoi(src_size, dst_tl, dst_br);\r
 \r
-    Mat xmap(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);\r
-    Mat ymap(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);\r
+    xmap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);\r
+    ymap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);\r
 \r
     float x, y;\r
     for (int v = dst_tl.y; v <= dst_br.y; ++v)\r
@@ -73,30 +71,41 @@ Point WarperBase<P>::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
         }\r
     }\r
 \r
-    dst.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, src.type());\r
+    return Rect(dst_tl, dst_br);\r
+}\r
+\r
+\r
+template <class P>\r
+Point RotationWarperBase<P>::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,\r
+                                  Mat &dst)\r
+{    \r
+    Mat xmap, ymap;\r
+    Rect dst_roi = buildMaps(src.size(), K, R, xmap, ymap);    \r
+\r
+    dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());\r
     remap(src, dst, xmap, ymap, interp_mode, border_mode);\r
 \r
-    return dst_tl;\r
+    return dst_roi.tl();\r
 }\r
 \r
+\r
 template <class P>\r
-void WarperBase<P>::warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Size dstSize,\r
-                          int interp_mode, int border_mode)\r
+void RotationWarperBase<P>::warpBackward(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,\r
+                                         Size dst_size, Mat &dst)\r
 {\r
-    src_size_ = dstSize;\r
     projector_.setCameraParams(K, R);\r
 \r
     Point src_tl, src_br;\r
-    detectResultRoi(src_tl, src_br);\r
+    detectResultRoi(dst_size, src_tl, src_br);\r
     CV_Assert(src_br.x - src_tl.x + 1 == src.cols && src_br.y - src_tl.y + 1 == src.rows);\r
 \r
-    Mat xmap(dstSize, CV_32F);\r
-    Mat ymap(dstSize, CV_32F);\r
+    Mat xmap(dst_size, CV_32F);\r
+    Mat ymap(dst_size, CV_32F);\r
 \r
     float u, v;\r
-    for (int y = 0; y < dstSize.height; ++y)\r
+    for (int y = 0; y < dst_size.height; ++y)\r
     {\r
-        for (int x = 0; x < dstSize.width; ++x)\r
+        for (int x = 0; x < dst_size.width; ++x)\r
         {\r
             projector_.mapForward(static_cast<float>(x), static_cast<float>(y), u, v);\r
             xmap.at<float>(y, x) = u - src_tl.x;\r
@@ -104,43 +113,25 @@ void WarperBase<P>::warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat
         }\r
     }\r
 \r
-    dst.create(dstSize, src.type());\r
+    dst.create(dst_size, src.type());\r
     remap(src, dst, xmap, ymap, interp_mode, border_mode);\r
 }\r
 \r
 \r
 template <class P>\r
-Point WarperBase<P>::warp(const Mat &/*src*/, const Mat &/*K*/, const Mat &/*R*/, const Mat &/*T*/, Mat &/*dst*/,\r
-                          int /*interp_mode*/, int /*border_mode*/)\r
+Rect RotationWarperBase<P>::warpRoi(Size src_size, const Mat &K, const Mat &R)\r
 {\r
-    CV_Error(CV_StsNotImplemented, "translation support isn't implemented");\r
-    return Point();\r
-}\r
-\r
-\r
-template <class P>\r
-Rect WarperBase<P>::warpRoi(const Size &sz, const Mat &K, const Mat &R)\r
-{\r
-    src_size_ = sz;\r
     projector_.setCameraParams(K, R);\r
 \r
     Point dst_tl, dst_br;\r
-    detectResultRoi(dst_tl, dst_br);\r
+    detectResultRoi(src_size, dst_tl, dst_br);\r
 \r
     return Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1));\r
 }\r
 \r
 \r
 template <class P>\r
-Rect WarperBase<P>::warpRoi(const Size &/*sz*/, const Mat &/*K*/, const Mat &/*R*/, const Mat &/*T*/)\r
-{\r
-    CV_Error(CV_StsNotImplemented, "translation support isn't implemented");\r
-    return Rect();\r
-}\r
-\r
-\r
-template <class P>\r
-void WarperBase<P>::detectResultRoi(Point &dst_tl, Point &dst_br)\r
+void RotationWarperBase<P>::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)\r
 {\r
     float tl_uf = std::numeric_limits<float>::max();\r
     float tl_vf = std::numeric_limits<float>::max();\r
@@ -148,9 +139,9 @@ void WarperBase<P>::detectResultRoi(Point &dst_tl, Point &dst_br)
     float br_vf = -std::numeric_limits<float>::max();\r
 \r
     float u, v;\r
-    for (int y = 0; y < src_size_.height; ++y)\r
+    for (int y = 0; y < src_size.height; ++y)\r
     {\r
-        for (int x = 0; x < src_size_.width; ++x)\r
+        for (int x = 0; x < src_size.width; ++x)\r
         {\r
             projector_.mapForward(static_cast<float>(x), static_cast<float>(y), u, v);\r
             tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);\r
@@ -166,7 +157,7 @@ void WarperBase<P>::detectResultRoi(Point &dst_tl, Point &dst_br)
 \r
 \r
 template <class P>\r
-void WarperBase<P>::detectResultRoiByBorder(Point &dst_tl, Point &dst_br)\r
+void RotationWarperBase<P>::detectResultRoiByBorder(Size src_size, Point &dst_tl, Point &dst_br)\r
 {\r
     float tl_uf = std::numeric_limits<float>::max();\r
     float tl_vf = std::numeric_limits<float>::max();\r
@@ -174,23 +165,23 @@ void WarperBase<P>::detectResultRoiByBorder(Point &dst_tl, Point &dst_br)
     float br_vf = -std::numeric_limits<float>::max();\r
 \r
     float u, v;\r
-    for (float x = 0; x < src_size_.width; ++x)\r
+    for (float x = 0; x < src_size.width; ++x)\r
     {\r
         projector_.mapForward(static_cast<float>(x), 0, u, v);\r
         tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);\r
         br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);\r
 \r
-        projector_.mapForward(static_cast<float>(x), static_cast<float>(src_size_.height - 1), u, v);\r
+        projector_.mapForward(static_cast<float>(x), static_cast<float>(src_size.height - 1), u, v);\r
         tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);\r
         br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);\r
     }\r
-    for (int y = 0; y < src_size_.height; ++y)\r
+    for (int y = 0; y < src_size.height; ++y)\r
     {\r
         projector_.mapForward(0, static_cast<float>(y), u, v);\r
         tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);\r
         br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);\r
 \r
-        projector_.mapForward(static_cast<float>(src_size_.width - 1), static_cast<float>(y), u, v);\r
+        projector_.mapForward(static_cast<float>(src_size.width - 1), static_cast<float>(y), u, v);\r
         tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);\r
         br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);\r
     }\r
index 6f3c944..b612de6 100644 (file)
@@ -51,28 +51,28 @@ class WarperCreator
 {
 public:
     virtual ~WarperCreator() {}
-    virtual Ptr<detail::Warper> create(float scale) const = 0;
+    virtual Ptr<detail::RotationWarper> create(float scale) const = 0;
 };
 
 
 class PlaneWarper : public WarperCreator
 {
 public:
-    Ptr<detail::Warper> create(float scale) const { return new detail::PlaneWarper(scale); }
+    Ptr<detail::RotationWarper> create(float scale) const { return new detail::PlaneWarper(scale); }
 };
 
 
 class CylindricalWarper: public WarperCreator
 {
 public:
-    Ptr<detail::Warper> create(float scale) const { return new detail::CylindricalWarper(scale); }
+    Ptr<detail::RotationWarper> create(float scale) const { return new detail::CylindricalWarper(scale); }
 };
 
 
 class SphericalWarper: public WarperCreator
 {
 public:
-    Ptr<detail::Warper> create(float scale) const { return new detail::SphericalWarper(scale); }
+    Ptr<detail::RotationWarper> create(float scale) const { return new detail::SphericalWarper(scale); }
 };
 
 
@@ -80,21 +80,21 @@ public:
 class PlaneWarperGpu: public WarperCreator
 {
 public:
-    Ptr<detail::Warper> create(float scale) const { return new detail::PlaneWarperGpu(scale); }
+    Ptr<detail::RotationWarper> create(float scale) const { return new detail::PlaneWarperGpu(scale); }
 };
 
 
 class CylindricalWarperGpu: public WarperCreator
 {
 public:
-    Ptr<detail::Warper> create(float scale) const { return new detail::CylindricalWarperGpu(scale); }
+    Ptr<detail::RotationWarper> create(float scale) const { return new detail::CylindricalWarperGpu(scale); }
 };
 
 
 class SphericalWarperGpu: public WarperCreator
 {
 public:
-    Ptr<detail::Warper> create(float scale) const { return new detail::SphericalWarperGpu(scale); }
+    Ptr<detail::RotationWarper> create(float scale) const { return new detail::SphericalWarperGpu(scale); }
 };
 #endif
 
index 47e3c43..9887fc1 100644 (file)
@@ -261,7 +261,7 @@ Stitcher::Status Stitcher::composePanorama(Mat &pano)
     }
 
     // Warp images and their masks
-    Ptr<detail::Warper> warper = warper_->create(float(warped_image_scale_ * seam_work_aspect_));
+    Ptr<detail::RotationWarper> warper = warper_->create(float(warped_image_scale_ * seam_work_aspect_));
     for (size_t i = 0; i < imgs_.size(); ++i)
     {
         Mat_<float> 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<Mat> 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);
index 68938c1..652de12 100644 (file)
@@ -78,17 +78,15 @@ void ProjectorBase::setCameraParams(const Mat &K, const Mat &R, const Mat &T)
 }\r
 \r
 \r
-Point PlaneWarper::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst,\r
-                        int interp_mode, int border_mode)\r
+Rect PlaneWarper::buildMaps(Size src_size, const Mat &K, const Mat &R, const Mat &T, Mat &xmap, Mat &ymap)\r
 {\r
-    src_size_ = src.size();\r
     projector_.setCameraParams(K, R, T);\r
 \r
     Point dst_tl, dst_br;\r
-    detectResultRoi(dst_tl, dst_br);\r
+    detectResultRoi(src_size, dst_tl, dst_br);\r
 \r
-    Mat xmap(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);\r
-    Mat ymap(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);\r
+    xmap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);\r
+    ymap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);\r
 \r
     float x, y;\r
     for (int v = dst_tl.y; v <= dst_br.y; ++v)\r
@@ -101,26 +99,35 @@ Point PlaneWarper::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T
         }\r
     }\r
 \r
-    dst.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, src.type());\r
+    return Rect(dst_tl, dst_br);\r
+}\r
+\r
+\r
+Point PlaneWarper::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, int interp_mode, int border_mode,\r
+                        Mat &dst)\r
+{\r
+    Mat xmap, ymap;\r
+    Rect dst_roi = buildMaps(src.size(), K, R, T, xmap, ymap);\r
+\r
+    dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());\r
     remap(src, dst, xmap, ymap, interp_mode, border_mode);\r
 \r
-    return dst_tl;\r
+    return dst_roi.tl();\r
 }\r
 \r
 \r
-Rect PlaneWarper::warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T)\r
+Rect PlaneWarper::warpRoi(Size src_size, const Mat &K, const Mat &R, const Mat &T)\r
 {\r
-    src_size_ = sz;\r
     projector_.setCameraParams(K, R, T);\r
 \r
     Point dst_tl, dst_br;\r
-    detectResultRoi(dst_tl, dst_br);\r
+    detectResultRoi(src_size, dst_tl, dst_br);\r
 \r
     return Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1));\r
 }\r
 \r
 \r
-void PlaneWarper::detectResultRoi(Point &dst_tl, Point &dst_br)\r
+void PlaneWarper::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)\r
 {\r
     float tl_uf = numeric_limits<float>::max();\r
     float tl_vf = numeric_limits<float>::max();\r
@@ -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);\r
     br_uf = max(br_uf, u); br_vf = max(br_vf, v);\r
 \r
-    projector_.mapForward(0, static_cast<float>(src_size_.height - 1), u, v);\r
+    projector_.mapForward(0, static_cast<float>(src_size.height - 1), u, v);\r
     tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v);\r
     br_uf = max(br_uf, u); br_vf = max(br_vf, v);\r
 \r
-    projector_.mapForward(static_cast<float>(src_size_.width - 1), 0, u, v);\r
+    projector_.mapForward(static_cast<float>(src_size.width - 1), 0, u, v);\r
     tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v);\r
     br_uf = max(br_uf, u); br_vf = max(br_vf, v);\r
 \r
-    projector_.mapForward(static_cast<float>(src_size_.width - 1), static_cast<float>(src_size_.height - 1), u, v);\r
+    projector_.mapForward(static_cast<float>(src_size.width - 1), static_cast<float>(src_size.height - 1), u, v);\r
     tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v);\r
     br_uf = max(br_uf, u); br_vf = max(br_vf, v);\r
 \r
@@ -153,21 +160,20 @@ void PlaneWarper::detectResultRoi(Point &dst_tl, Point &dst_br)
 \r
 \r
 #ifndef ANDROID\r
-Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, \r
-                           int interp_mode, int border_mode)\r
+Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,\r
+                           Mat &dst)\r
 {\r
-    return warp(src, K, R, Mat::zeros(3, 1, CV_32F), dst, interp_mode, border_mode);\r
+    return warp(src, K, R, Mat::zeros(3, 1, CV_32F), interp_mode, border_mode, dst);\r
 }\r
 \r
 \r
-Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst, \r
-                           int interp_mode, int border_mode)\r
+Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, int interp_mode, int border_mode,\r
+                           Mat &dst)\r
 {\r
-    src_size_ = src.size();\r
     projector_.setCameraParams(K, R, T);\r
 \r
     Point dst_tl, dst_br;\r
-    detectResultRoi(dst_tl, dst_br);\r
+    detectResultRoi(src.size(), dst_tl, dst_br);\r
 \r
     gpu::buildWarpPlaneMaps(src.size(), Rect(dst_tl, Point(dst_br.x+1, dst_br.y+1)),\r
                             K, R, projector_.scale, d_xmap_, d_ymap_);\r
@@ -186,9 +192,9 @@ Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, const Mat
 #endif\r
 \r
 \r
-void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br)\r
+void SphericalWarper::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)\r
 {\r
-    detectResultRoiByBorder(dst_tl, dst_br);\r
+    detectResultRoiByBorder(src_size, dst_tl, dst_br);\r
 \r
     float tl_uf = static_cast<float>(dst_tl.x);\r
     float tl_vf = static_cast<float>(dst_tl.y);\r
@@ -202,7 +208,7 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br)
     {\r
         float x_ = (projector_.k[0] * x + projector_.k[1] * y) / z + projector_.k[2];\r
         float y_ = projector_.k[4] * y / z + projector_.k[5];\r
-        if (x_ > 0.f && x_ < src_size_.width && y_ > 0.f && y_ < src_size_.height)\r
+        if (x_ > 0.f && x_ < src_size.width && y_ > 0.f && y_ < src_size.height)\r
         {\r
             tl_uf = min(tl_uf, 0.f); tl_vf = min(tl_vf, static_cast<float>(CV_PI * projector_.scale));\r
             br_uf = max(br_uf, 0.f); br_vf = max(br_vf, static_cast<float>(CV_PI * projector_.scale));\r
@@ -216,7 +222,7 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br)
     {\r
         float x_ = (projector_.k[0] * x + projector_.k[1] * y) / z + projector_.k[2];\r
         float y_ = projector_.k[4] * y / z + projector_.k[5];\r
-        if (x_ > 0.f && x_ < src_size_.width && y_ > 0.f && y_ < src_size_.height)\r
+        if (x_ > 0.f && x_ < src_size.width && y_ > 0.f && y_ < src_size.height)\r
         {\r
             tl_uf = min(tl_uf, 0.f); tl_vf = min(tl_vf, static_cast<float>(0));\r
             br_uf = max(br_uf, 0.f); br_vf = max(br_vf, static_cast<float>(0));\r
@@ -231,14 +237,13 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br)
 \r
 \r
 #ifndef ANDROID\r
-Point SphericalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,\r
-                               int interp_mode, int border_mode)\r
+Point SphericalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,\r
+                               Mat &dst)\r
 {\r
-    src_size_ = src.size();\r
     projector_.setCameraParams(K, R);\r
 \r
     Point dst_tl, dst_br;\r
-    detectResultRoi(dst_tl, dst_br);\r
+    detectResultRoi(src.size(), dst_tl, dst_br);\r
 \r
     gpu::buildWarpSphericalMaps(src.size(), Rect(dst_tl, Point(dst_br.x+1, dst_br.y+1)),\r
                                 K, R, projector_.scale, d_xmap_, d_ymap_);\r
@@ -256,14 +261,13 @@ Point SphericalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &
 }\r
 \r
 \r
-Point CylindricalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,\r
-                                 int interp_mode, int border_mode)\r
+Point CylindricalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,\r
+                                 Mat &dst)\r
 {\r
-    src_size_ = src.size();\r
     projector_.setCameraParams(K, R);\r
 \r
     Point dst_tl, dst_br;\r
-    detectResultRoi(dst_tl, dst_br);\r
+    detectResultRoi(src.size(), dst_tl, dst_br);\r
 \r
     gpu::buildWarpCylindricalMaps(src.size(), Rect(dst_tl, Point(dst_br.x+1, dst_br.y+1)),\r
                                   K, R, projector_.scale, d_xmap_, d_ymap_);\r
index 71e51d6..6e10007 100644 (file)
@@ -523,7 +523,7 @@ int main(int argc, char* argv[])
         return 1;
     }
     
-    Ptr<Warper> warper = warper_creator->create(static_cast<float>(warped_image_scale * seam_work_aspect));
+    Ptr<RotationWarper> warper = warper_creator->create(static_cast<float>(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<Mat> 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);