Home | History | Annotate | Download | only in detail
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                          License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
     14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
     15 // Third party copyrights are property of their respective owners.
     16 //
     17 // Redistribution and use in source and binary forms, with or without modification,
     18 // are permitted provided that the following conditions are met:
     19 //
     20 //   * Redistribution's of source code must retain the above copyright notice,
     21 //     this list of conditions and the following disclaimer.
     22 //
     23 //   * Redistribution's in binary form must reproduce the above copyright notice,
     24 //     this list of conditions and the following disclaimer in the documentation
     25 //     and/or other materials provided with the distribution.
     26 //
     27 //   * The name of the copyright holders may not be used to endorse or promote products
     28 //     derived from this software without specific prior written permission.
     29 //
     30 // This software is provided by the copyright holders and contributors "as is" and
     31 // any express or implied warranties, including, but not limited to, the implied
     32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     33 // In no event shall the Intel Corporation or contributors be liable for any direct,
     34 // indirect, incidental, special, exemplary, or consequential damages
     35 // (including, but not limited to, procurement of substitute goods or services;
     36 // loss of use, data, or profits; or business interruption) however caused
     37 // and on any theory of liability, whether in contract, strict liability,
     38 // or tort (including negligence or otherwise) arising in any way out of
     39 // the use of this software, even if advised of the possibility of such damage.
     40 //
     41 //M*/
     42 
     43 #ifndef __OPENCV_STITCHING_WARPERS_INL_HPP__
     44 #define __OPENCV_STITCHING_WARPERS_INL_HPP__
     45 
     46 #include "opencv2/core.hpp"
     47 #include "warpers.hpp" // Make your IDE see declarations
     48 #include <limits>
     49 
     50 //! @cond IGNORED
     51 
     52 namespace cv {
     53 namespace detail {
     54 
     55 template <class P>
     56 Point2f RotationWarperBase<P>::warpPoint(const Point2f &pt, InputArray K, InputArray R)
     57 {
     58     projector_.setCameraParams(K, R);
     59     Point2f uv;
     60     projector_.mapForward(pt.x, pt.y, uv.x, uv.y);
     61     return uv;
     62 }
     63 
     64 
     65 template <class P>
     66 Rect RotationWarperBase<P>::buildMaps(Size src_size, InputArray K, InputArray R, OutputArray _xmap, OutputArray _ymap)
     67 {
     68     projector_.setCameraParams(K, R);
     69 
     70     Point dst_tl, dst_br;
     71     detectResultRoi(src_size, dst_tl, dst_br);
     72 
     73     _xmap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);
     74     _ymap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);
     75 
     76     Mat xmap = _xmap.getMat(), ymap = _ymap.getMat();
     77 
     78     float x, y;
     79     for (int v = dst_tl.y; v <= dst_br.y; ++v)
     80     {
     81         for (int u = dst_tl.x; u <= dst_br.x; ++u)
     82         {
     83             projector_.mapBackward(static_cast<float>(u), static_cast<float>(v), x, y);
     84             xmap.at<float>(v - dst_tl.y, u - dst_tl.x) = x;
     85             ymap.at<float>(v - dst_tl.y, u - dst_tl.x) = y;
     86         }
     87     }
     88 
     89     return Rect(dst_tl, dst_br);
     90 }
     91 
     92 
     93 template <class P>
     94 Point RotationWarperBase<P>::warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
     95                                   OutputArray dst)
     96 {
     97     UMat xmap, ymap;
     98     Rect dst_roi = buildMaps(src.size(), K, R, xmap, ymap);
     99 
    100     dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());
    101     remap(src, dst, xmap, ymap, interp_mode, border_mode);
    102 
    103     return dst_roi.tl();
    104 }
    105 
    106 
    107 template <class P>
    108 void RotationWarperBase<P>::warpBackward(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
    109                                          Size dst_size, OutputArray dst)
    110 {
    111     projector_.setCameraParams(K, R);
    112 
    113     Point src_tl, src_br;
    114     detectResultRoi(dst_size, src_tl, src_br);
    115 
    116     Size size = src.size();
    117     CV_Assert(src_br.x - src_tl.x + 1 == size.width && src_br.y - src_tl.y + 1 == size.height);
    118 
    119     Mat xmap(dst_size, CV_32F);
    120     Mat ymap(dst_size, CV_32F);
    121 
    122     float u, v;
    123     for (int y = 0; y < dst_size.height; ++y)
    124     {
    125         for (int x = 0; x < dst_size.width; ++x)
    126         {
    127             projector_.mapForward(static_cast<float>(x), static_cast<float>(y), u, v);
    128             xmap.at<float>(y, x) = u - src_tl.x;
    129             ymap.at<float>(y, x) = v - src_tl.y;
    130         }
    131     }
    132 
    133     dst.create(dst_size, src.type());
    134     remap(src, dst, xmap, ymap, interp_mode, border_mode);
    135 }
    136 
    137 
    138 template <class P>
    139 Rect RotationWarperBase<P>::warpRoi(Size src_size, InputArray K, InputArray R)
    140 {
    141     projector_.setCameraParams(K, R);
    142 
    143     Point dst_tl, dst_br;
    144     detectResultRoi(src_size, dst_tl, dst_br);
    145 
    146     return Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1));
    147 }
    148 
    149 
    150 template <class P>
    151 void RotationWarperBase<P>::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)
    152 {
    153     float tl_uf = std::numeric_limits<float>::max();
    154     float tl_vf = std::numeric_limits<float>::max();
    155     float br_uf = -std::numeric_limits<float>::max();
    156     float br_vf = -std::numeric_limits<float>::max();
    157 
    158     float u, v;
    159     for (int y = 0; y < src_size.height; ++y)
    160     {
    161         for (int x = 0; x < src_size.width; ++x)
    162         {
    163             projector_.mapForward(static_cast<float>(x), static_cast<float>(y), u, v);
    164             tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
    165             br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
    166         }
    167     }
    168 
    169     dst_tl.x = static_cast<int>(tl_uf);
    170     dst_tl.y = static_cast<int>(tl_vf);
    171     dst_br.x = static_cast<int>(br_uf);
    172     dst_br.y = static_cast<int>(br_vf);
    173 }
    174 
    175 
    176 template <class P>
    177 void RotationWarperBase<P>::detectResultRoiByBorder(Size src_size, Point &dst_tl, Point &dst_br)
    178 {
    179     float tl_uf = std::numeric_limits<float>::max();
    180     float tl_vf = std::numeric_limits<float>::max();
    181     float br_uf = -std::numeric_limits<float>::max();
    182     float br_vf = -std::numeric_limits<float>::max();
    183 
    184     float u, v;
    185     for (float x = 0; x < src_size.width; ++x)
    186     {
    187         projector_.mapForward(static_cast<float>(x), 0, u, v);
    188         tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
    189         br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
    190 
    191         projector_.mapForward(static_cast<float>(x), static_cast<float>(src_size.height - 1), u, v);
    192         tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
    193         br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
    194     }
    195     for (int y = 0; y < src_size.height; ++y)
    196     {
    197         projector_.mapForward(0, static_cast<float>(y), u, v);
    198         tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
    199         br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
    200 
    201         projector_.mapForward(static_cast<float>(src_size.width - 1), static_cast<float>(y), u, v);
    202         tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
    203         br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
    204     }
    205 
    206     dst_tl.x = static_cast<int>(tl_uf);
    207     dst_tl.y = static_cast<int>(tl_vf);
    208     dst_br.x = static_cast<int>(br_uf);
    209     dst_br.y = static_cast<int>(br_vf);
    210 }
    211 
    212 
    213 inline
    214 void PlaneProjector::mapForward(float x, float y, float &u, float &v)
    215 {
    216     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
    217     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
    218     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
    219 
    220     x_ = t[0] + x_ / z_ * (1 - t[2]);
    221     y_ = t[1] + y_ / z_ * (1 - t[2]);
    222 
    223     u = scale * x_;
    224     v = scale * y_;
    225 }
    226 
    227 
    228 inline
    229 void PlaneProjector::mapBackward(float u, float v, float &x, float &y)
    230 {
    231     u = u / scale - t[0];
    232     v = v / scale - t[1];
    233 
    234     float z;
    235     x = k_rinv[0] * u + k_rinv[1] * v + k_rinv[2] * (1 - t[2]);
    236     y = k_rinv[3] * u + k_rinv[4] * v + k_rinv[5] * (1 - t[2]);
    237     z = k_rinv[6] * u + k_rinv[7] * v + k_rinv[8] * (1 - t[2]);
    238 
    239     x /= z;
    240     y /= z;
    241 }
    242 
    243 
    244 inline
    245 void SphericalProjector::mapForward(float x, float y, float &u, float &v)
    246 {
    247     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
    248     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
    249     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
    250 
    251     u = scale * atan2f(x_, z_);
    252     float w = y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_);
    253     v = scale * (static_cast<float>(CV_PI) - acosf(w == w ? w : 0));
    254 }
    255 
    256 
    257 inline
    258 void SphericalProjector::mapBackward(float u, float v, float &x, float &y)
    259 {
    260     u /= scale;
    261     v /= scale;
    262 
    263     float sinv = sinf(static_cast<float>(CV_PI) - v);
    264     float x_ = sinv * sinf(u);
    265     float y_ = cosf(static_cast<float>(CV_PI) - v);
    266     float z_ = sinv * cosf(u);
    267 
    268     float z;
    269     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
    270     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
    271     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
    272 
    273     if (z > 0) { x /= z; y /= z; }
    274     else x = y = -1;
    275 }
    276 
    277 
    278 inline
    279 void CylindricalProjector::mapForward(float x, float y, float &u, float &v)
    280 {
    281     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
    282     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
    283     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
    284 
    285     u = scale * atan2f(x_, z_);
    286     v = scale * y_ / sqrtf(x_ * x_ + z_ * z_);
    287 }
    288 
    289 
    290 inline
    291 void CylindricalProjector::mapBackward(float u, float v, float &x, float &y)
    292 {
    293     u /= scale;
    294     v /= scale;
    295 
    296     float x_ = sinf(u);
    297     float y_ = v;
    298     float z_ = cosf(u);
    299 
    300     float z;
    301     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
    302     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
    303     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
    304 
    305     if (z > 0) { x /= z; y /= z; }
    306     else x = y = -1;
    307 }
    308 
    309 inline
    310 void FisheyeProjector::mapForward(float x, float y, float &u, float &v)
    311 {
    312     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
    313     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
    314     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
    315 
    316     float u_ = atan2f(x_, z_);
    317     float v_ = (float)CV_PI - acosf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
    318 
    319     u = scale * v_ * cosf(u_);
    320     v = scale * v_ * sinf(u_);
    321 }
    322 
    323 inline
    324 void FisheyeProjector::mapBackward(float u, float v, float &x, float &y)
    325 {
    326     u /= scale;
    327     v /= scale;
    328 
    329     float u_ = atan2f(v, u);
    330     float v_ = sqrtf(u*u + v*v);
    331 
    332     float sinv = sinf((float)CV_PI - v_);
    333     float x_ = sinv * sinf(u_);
    334     float y_ = cosf((float)CV_PI - v_);
    335     float z_ = sinv * cosf(u_);
    336 
    337     float z;
    338     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
    339     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
    340     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
    341 
    342     if (z > 0) { x /= z; y /= z; }
    343     else x = y = -1;
    344 }
    345 
    346 inline
    347 void StereographicProjector::mapForward(float x, float y, float &u, float &v)
    348 {
    349     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
    350     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
    351     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
    352 
    353     float u_ = atan2f(x_, z_);
    354     float v_ = (float)CV_PI - acosf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
    355 
    356     float r = sinf(v_) / (1 - cosf(v_));
    357 
    358     u = scale * r * cos(u_);
    359     v = scale * r * sin(u_);
    360 }
    361 
    362 inline
    363 void StereographicProjector::mapBackward(float u, float v, float &x, float &y)
    364 {
    365     u /= scale;
    366     v /= scale;
    367 
    368     float u_ = atan2f(v, u);
    369     float r = sqrtf(u*u + v*v);
    370     float v_ = 2 * atanf(1.f / r);
    371 
    372     float sinv = sinf((float)CV_PI - v_);
    373     float x_ = sinv * sinf(u_);
    374     float y_ = cosf((float)CV_PI - v_);
    375     float z_ = sinv * cosf(u_);
    376 
    377     float z;
    378     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
    379     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
    380     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
    381 
    382     if (z > 0) { x /= z; y /= z; }
    383     else x = y = -1;
    384 }
    385 
    386 inline
    387 void CompressedRectilinearProjector::mapForward(float x, float y, float &u, float &v)
    388 {
    389     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
    390     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
    391     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
    392 
    393     float u_ = atan2f(x_, z_);
    394     float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
    395 
    396     u = scale * a * tanf(u_ / a);
    397     v = scale * b * tanf(v_) / cosf(u_);
    398 }
    399 
    400 inline
    401 void CompressedRectilinearProjector::mapBackward(float u, float v, float &x, float &y)
    402 {
    403     u /= scale;
    404     v /= scale;
    405 
    406     float aatg = a * atanf(u / a);
    407     float u_ = aatg;
    408     float v_ = atanf(v * cosf(aatg) / b);
    409 
    410     float cosv = cosf(v_);
    411     float x_ = cosv * sinf(u_);
    412     float y_ = sinf(v_);
    413     float z_ = cosv * cosf(u_);
    414 
    415     float z;
    416     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
    417     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
    418     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
    419 
    420     if (z > 0) { x /= z; y /= z; }
    421     else x = y = -1;
    422 }
    423 
    424 inline
    425 void CompressedRectilinearPortraitProjector::mapForward(float x, float y, float &u, float &v)
    426 {
    427     float y_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
    428     float x_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
    429     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
    430 
    431     float u_ = atan2f(x_, z_);
    432     float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
    433 
    434     u = - scale * a * tanf(u_ / a);
    435     v = scale * b * tanf(v_) / cosf(u_);
    436 }
    437 
    438 inline
    439 void CompressedRectilinearPortraitProjector::mapBackward(float u, float v, float &x, float &y)
    440 {
    441     u /= - scale;
    442     v /= scale;
    443 
    444     float aatg = a * atanf(u / a);
    445     float u_ = aatg;
    446     float v_ = atanf(v * cosf( aatg ) / b);
    447 
    448     float cosv = cosf(v_);
    449     float y_ = cosv * sinf(u_);
    450     float x_ = sinf(v_);
    451     float z_ = cosv * cosf(u_);
    452 
    453     float z;
    454     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
    455     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
    456     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
    457 
    458     if (z > 0) { x /= z; y /= z; }
    459     else x = y = -1;
    460 }
    461 
    462 inline
    463 void PaniniProjector::mapForward(float x, float y, float &u, float &v)
    464 {
    465     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
    466     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
    467     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
    468 
    469     float u_ = atan2f(x_, z_);
    470     float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
    471 
    472     float tg = a * tanf(u_ / a);
    473     u = scale * tg;
    474 
    475     float sinu = sinf(u_);
    476     if ( fabs(sinu) < 1E-7 )
    477         v = scale * b * tanf(v_);
    478     else
    479         v = scale * b * tg * tanf(v_) / sinu;
    480 }
    481 
    482 inline
    483 void PaniniProjector::mapBackward(float u, float v, float &x, float &y)
    484 {
    485     u /= scale;
    486     v /= scale;
    487 
    488     float lamda = a * atanf(u / a);
    489     float u_ = lamda;
    490 
    491     float v_;
    492     if ( fabs(lamda) > 1E-7)
    493         v_ = atanf(v * sinf(lamda) / (b * a * tanf(lamda / a)));
    494     else
    495         v_ = atanf(v / b);
    496 
    497     float cosv = cosf(v_);
    498     float x_ = cosv * sinf(u_);
    499     float y_ = sinf(v_);
    500     float z_ = cosv * cosf(u_);
    501 
    502     float z;
    503     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
    504     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
    505     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
    506 
    507     if (z > 0) { x /= z; y /= z; }
    508     else x = y = -1;
    509 }
    510 
    511 inline
    512 void PaniniPortraitProjector::mapForward(float x, float y, float &u, float &v)
    513 {
    514     float y_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
    515     float x_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
    516     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
    517 
    518     float u_ = atan2f(x_, z_);
    519     float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
    520 
    521     float tg = a * tanf(u_ / a);
    522     u = - scale * tg;
    523 
    524     float sinu = sinf( u_ );
    525     if ( fabs(sinu) < 1E-7 )
    526         v = scale * b * tanf(v_);
    527     else
    528         v = scale * b * tg * tanf(v_) / sinu;
    529 }
    530 
    531 inline
    532 void PaniniPortraitProjector::mapBackward(float u, float v, float &x, float &y)
    533 {
    534     u /= - scale;
    535     v /= scale;
    536 
    537     float lamda = a * atanf(u / a);
    538     float u_ = lamda;
    539 
    540     float v_;
    541     if ( fabs(lamda) > 1E-7)
    542         v_ = atanf(v * sinf(lamda) / (b * a * tanf(lamda/a)));
    543     else
    544         v_ = atanf(v / b);
    545 
    546     float cosv = cosf(v_);
    547     float y_ = cosv * sinf(u_);
    548     float x_ = sinf(v_);
    549     float z_ = cosv * cosf(u_);
    550 
    551     float z;
    552     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
    553     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
    554     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
    555 
    556     if (z > 0) { x /= z; y /= z; }
    557     else x = y = -1;
    558 }
    559 
    560 inline
    561 void MercatorProjector::mapForward(float x, float y, float &u, float &v)
    562 {
    563     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
    564     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
    565     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
    566 
    567     float u_ = atan2f(x_, z_);
    568     float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
    569 
    570     u = scale * u_;
    571     v = scale * logf( tanf( (float)(CV_PI/4) + v_/2 ) );
    572 }
    573 
    574 inline
    575 void MercatorProjector::mapBackward(float u, float v, float &x, float &y)
    576 {
    577     u /= scale;
    578     v /= scale;
    579 
    580     float v_ = atanf( sinhf(v) );
    581     float u_ = u;
    582 
    583     float cosv = cosf(v_);
    584     float x_ = cosv * sinf(u_);
    585     float y_ = sinf(v_);
    586     float z_ = cosv * cosf(u_);
    587 
    588     float z;
    589     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
    590     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
    591     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
    592 
    593     if (z > 0) { x /= z; y /= z; }
    594     else x = y = -1;
    595 }
    596 
    597 inline
    598 void TransverseMercatorProjector::mapForward(float x, float y, float &u, float &v)
    599 {
    600     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
    601     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
    602     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
    603 
    604     float u_ = atan2f(x_, z_);
    605     float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
    606 
    607     float B = cosf(v_) * sinf(u_);
    608 
    609     u = scale / 2 * logf( (1+B) / (1-B) );
    610     v = scale * atan2f(tanf(v_), cosf(u_));
    611 }
    612 
    613 inline
    614 void TransverseMercatorProjector::mapBackward(float u, float v, float &x, float &y)
    615 {
    616     u /= scale;
    617     v /= scale;
    618 
    619     float v_ = asinf( sinf(v) / coshf(u) );
    620     float u_ = atan2f( sinhf(u), cos(v) );
    621 
    622     float cosv = cosf(v_);
    623     float x_ = cosv * sinf(u_);
    624     float y_ = sinf(v_);
    625     float z_ = cosv * cosf(u_);
    626 
    627     float z;
    628     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
    629     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
    630     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
    631 
    632     if (z > 0) { x /= z; y /= z; }
    633     else x = y = -1;
    634 }
    635 
    636 inline
    637 void SphericalPortraitProjector::mapForward(float x, float y, float &u0, float &v0)
    638 {
    639     float x0_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
    640     float y0_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
    641     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
    642 
    643     float x_ = y0_;
    644     float y_ = x0_;
    645     float u, v;
    646 
    647     u = scale * atan2f(x_, z_);
    648     v = scale * (static_cast<float>(CV_PI) - acosf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_)));
    649 
    650     u0 = -u;//v;
    651     v0 = v;//u;
    652 }
    653 
    654 
    655 inline
    656 void SphericalPortraitProjector::mapBackward(float u0, float v0, float &x, float &y)
    657 {
    658     float u, v;
    659     u = -u0;//v0;
    660     v = v0;//u0;
    661 
    662     u /= scale;
    663     v /= scale;
    664 
    665     float sinv = sinf(static_cast<float>(CV_PI) - v);
    666     float x0_ = sinv * sinf(u);
    667     float y0_ = cosf(static_cast<float>(CV_PI) - v);
    668     float z_ = sinv * cosf(u);
    669 
    670     float x_ = y0_;
    671     float y_ = x0_;
    672 
    673     float z;
    674     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
    675     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
    676     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
    677 
    678     if (z > 0) { x /= z; y /= z; }
    679     else x = y = -1;
    680 }
    681 
    682 inline
    683 void CylindricalPortraitProjector::mapForward(float x, float y, float &u0, float &v0)
    684 {
    685     float x0_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
    686     float y0_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
    687     float z_  = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
    688 
    689     float x_ = y0_;
    690     float y_ = x0_;
    691     float u, v;
    692 
    693     u = scale * atan2f(x_, z_);
    694     v = scale * y_ / sqrtf(x_ * x_ + z_ * z_);
    695 
    696     u0 = -u;//v;
    697     v0 = v;//u;
    698 }
    699 
    700 
    701 inline
    702 void CylindricalPortraitProjector::mapBackward(float u0, float v0, float &x, float &y)
    703 {
    704     float u, v;
    705     u = -u0;//v0;
    706     v = v0;//u0;
    707 
    708     u /= scale;
    709     v /= scale;
    710 
    711     float x0_ = sinf(u);
    712     float y0_ = v;
    713     float z_  = cosf(u);
    714 
    715     float x_ = y0_;
    716     float y_ = x0_;
    717 
    718     float z;
    719     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
    720     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
    721     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
    722 
    723     if (z > 0) { x /= z; y /= z; }
    724     else x = y = -1;
    725 }
    726 
    727 inline
    728 void PlanePortraitProjector::mapForward(float x, float y, float &u0, float &v0)
    729 {
    730     float x0_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
    731     float y0_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
    732     float z_  = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
    733 
    734     float x_ = y0_;
    735     float y_ = x0_;
    736 
    737     x_ = t[0] + x_ / z_ * (1 - t[2]);
    738     y_ = t[1] + y_ / z_ * (1 - t[2]);
    739 
    740     float u,v;
    741     u = scale * x_;
    742     v = scale * y_;
    743 
    744     u0 = -u;
    745     v0 = v;
    746 }
    747 
    748 
    749 inline
    750 void PlanePortraitProjector::mapBackward(float u0, float v0, float &x, float &y)
    751 {
    752     float u, v;
    753     u = -u0;
    754     v = v0;
    755 
    756     u = u / scale - t[0];
    757     v = v / scale - t[1];
    758 
    759     float z;
    760     x = k_rinv[0] * v + k_rinv[1] * u + k_rinv[2] * (1 - t[2]);
    761     y = k_rinv[3] * v + k_rinv[4] * u + k_rinv[5] * (1 - t[2]);
    762     z = k_rinv[6] * v + k_rinv[7] * u + k_rinv[8] * (1 - t[2]);
    763 
    764     x /= z;
    765     y /= z;
    766 }
    767 
    768 
    769 } // namespace detail
    770 } // namespace cv
    771 
    772 //! @endcond
    773 
    774 #endif // __OPENCV_STITCHING_WARPERS_INL_HPP__
    775