Added spherical and cylindrical warpers, which work in the portrait mode -- when...
authorLeonid Beynenson <no@email>
Wed, 22 Feb 2012 15:44:39 +0000 (15:44 +0000)
committerLeonid Beynenson <no@email>
Wed, 22 Feb 2012 15:44:39 +0000 (15:44 +0000)
modules/stitching/include/opencv2/stitching/detail/warpers.hpp
modules/stitching/include/opencv2/stitching/detail/warpers_inl.hpp
modules/stitching/src/warpers.cpp

index 7061411..4a9bafe 100644 (file)
@@ -304,6 +304,45 @@ private:
 };\r
 #endif\r
 \r
+\r
+struct SphericalPortraitProjector : ProjectorBase\r
+{\r
+    void mapForward(float x, float y, float &u, float &v);\r
+    void mapBackward(float u, float v, float &x, float &y);\r
+};\r
+\r
+\r
+// Projects image onto unit sphere with origin at (0, 0, 0).\r
+// Poles are located NOT at (0, -1, 0) and (0, 1, 0) points, BUT at (1, 0, 0) and (-1, 0, 0) points.\r
+class SphericalPortraitWarper : public RotationWarperBase<SphericalPortraitProjector>\r
+{\r
+public:\r
+    SphericalPortraitWarper(float scale) { projector_.scale = scale; }\r
+\r
+protected:\r
+    void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br);\r
+};\r
+\r
+struct CylindricalPortraitProjector : ProjectorBase\r
+{\r
+    void mapForward(float x, float y, float &u, float &v);\r
+    void mapBackward(float u, float v, float &x, float &y);\r
+};\r
+\r
+\r
+class CylindricalPortraitWarper : public RotationWarperBase<CylindricalPortraitProjector>\r
+{\r
+public:\r
+    CylindricalPortraitWarper(float scale) { projector_.scale = scale; }\r
+\r
+protected:\r
+    void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)\r
+    { \r
+        RotationWarperBase<CylindricalPortraitProjector>::detectResultRoiByBorder(src_size, dst_tl, dst_br); \r
+    }\r
+};\r
+\r
+\r
 } // namespace detail\r
 } // namespace cv\r
 \r
index e925c63..d1ff56d 100644 (file)
@@ -298,6 +298,97 @@ void CylindricalProjector::mapBackward(float u, float v, float &x, float &y)
     else x = y = -1;\r
 }\r
 \r
+inline\r
+void SphericalPortraitProjector::mapForward(float x, float y, float &u0, float &v0)\r
+{    \r
+    float x0_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];\r
+    float y0_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];\r
+    float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];\r
+\r
+    float x_ = y0_;\r
+    float y_ = x0_;\r
+    float u, v;\r
+\r
+    u = scale * atan2f(x_, z_);\r
+    v = scale * (static_cast<float>(CV_PI) - acosf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_)));\r
+\r
+    u0 = -u;//v;\r
+    v0 = v;//u;\r
+}\r
+\r
+\r
+inline\r
+void SphericalPortraitProjector::mapBackward(float u0, float v0, float &x, float &y)\r
+{\r
+    float u, v;\r
+    u = -u0;//v0;\r
+    v = v0;//u0;\r
+\r
+    u /= scale;\r
+    v /= scale;\r
+\r
+    float sinv = sinf(static_cast<float>(CV_PI) - v);\r
+    float x0_ = sinv * sinf(u);\r
+    float y0_ = cosf(static_cast<float>(CV_PI) - v);\r
+    float z_ = sinv * cosf(u);\r
+\r
+    float x_ = y0_;\r
+    float y_ = x0_;\r
+\r
+    float z;\r
+    x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;\r
+    y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;\r
+    z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;\r
+\r
+    if (z > 0) { x /= z; y /= z; }\r
+    else x = y = -1;\r
+}\r
+\r
+inline\r
+void CylindricalPortraitProjector::mapForward(float x, float y, float &u0, float &v0)\r
+{    \r
+    float x0_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];\r
+    float y0_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];\r
+    float z_  = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];\r
+\r
+    float x_ = y0_;\r
+    float y_ = x0_;\r
+    float u, v;\r
+\r
+    u = scale * atan2f(x_, z_);\r
+    v = scale * y_ / sqrtf(x_ * x_ + z_ * z_);\r
+\r
+    u0 = -u;//v;\r
+    v0 = v;//u;\r
+}\r
+\r
+\r
+inline\r
+void CylindricalPortraitProjector::mapBackward(float u0, float v0, float &x, float &y)\r
+{\r
+    float u, v;\r
+    u = -u0;//v0;\r
+    v = v0;//u0;\r
+\r
+    u /= scale;\r
+    v /= scale;\r
+\r
+    float x0_ = sinf(u);\r
+    float y0_ = v;\r
+    float z_  = cosf(u);\r
+\r
+    float x_ = y0_;\r
+    float y_ = x0_;\r
+\r
+    float z;\r
+    x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;\r
+    y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;\r
+    z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;\r
+\r
+    if (z > 0) { x /= z; y /= z; }\r
+    else x = y = -1;\r
+}\r
+\r
 } // namespace detail\r
 } // namespace cv\r
 \r
index 235656e..f3bb480 100644 (file)
@@ -296,5 +296,48 @@ Point CylindricalWarperGpu::warp(const gpu::GpuMat &src, const Mat &K, const Mat
 }\r
 #endif\r
 \r
+void SphericalPortraitWarper::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)\r
+{\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
+    float br_uf = static_cast<float>(dst_br.x);\r
+    float br_vf = static_cast<float>(dst_br.y);\r
+\r
+    float x = projector_.rinv[0];\r
+    float y = projector_.rinv[3];\r
+    float z = projector_.rinv[6];\r
+    if (y > 0.f)\r
+    {\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
+        {\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
+        }\r
+    }\r
+\r
+    x = projector_.rinv[0];\r
+    y = -projector_.rinv[3];\r
+    z = projector_.rinv[6];\r
+    if (y > 0.f)\r
+    {\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
+        {\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
+        }\r
+    }\r
+\r
+    dst_tl.x = static_cast<int>(tl_uf);\r
+    dst_tl.y = static_cast<int>(tl_vf);\r
+    dst_br.x = static_cast<int>(br_uf);\r
+    dst_br.y = static_cast<int>(br_vf);\r
+}\r
+\r
 } // namespace detail\r
 } // namespace cv\r