OpenCV 2.4.8 components for OpenCVgrabber.
[mmanager-3rdparty.git] / OpenCV2.4.8 / build / include / opencv2 / stitching / detail / warpers_inl.hpp
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/core.hpp"
47 #include "warpers.hpp" // Make your IDE see declarations
48
49 namespace cv {
50 namespace detail {
51
52 template <class P>
53 Point2f RotationWarperBase<P>::warpPoint(const Point2f &pt, const Mat &K, const Mat &R)
54 {
55     projector_.setCameraParams(K, R);
56     Point2f uv;
57     projector_.mapForward(pt.x, pt.y, uv.x, uv.y);
58     return uv;
59 }
60
61
62 template <class P>
63 Rect RotationWarperBase<P>::buildMaps(Size src_size, const Mat &K, const Mat &R, Mat &xmap, Mat &ymap)
64 {
65     projector_.setCameraParams(K, R);
66
67     Point dst_tl, dst_br;
68     detectResultRoi(src_size, dst_tl, dst_br);
69
70     xmap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);
71     ymap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);
72
73     float x, y;
74     for (int v = dst_tl.y; v <= dst_br.y; ++v)
75     {
76         for (int u = dst_tl.x; u <= dst_br.x; ++u)
77         {
78             projector_.mapBackward(static_cast<float>(u), static_cast<float>(v), x, y);
79             xmap.at<float>(v - dst_tl.y, u - dst_tl.x) = x;
80             ymap.at<float>(v - dst_tl.y, u - dst_tl.x) = y;
81         }
82     }
83
84     return Rect(dst_tl, dst_br);
85 }
86
87
88 template <class P>
89 Point RotationWarperBase<P>::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
90                                   Mat &dst)
91 {
92     Mat xmap, ymap;
93     Rect dst_roi = buildMaps(src.size(), K, R, xmap, ymap);
94
95     dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());
96     remap(src, dst, xmap, ymap, interp_mode, border_mode);
97
98     return dst_roi.tl();
99 }
100
101
102 template <class P>
103 void RotationWarperBase<P>::warpBackward(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
104                                          Size dst_size, Mat &dst)
105 {
106     projector_.setCameraParams(K, R);
107
108     Point src_tl, src_br;
109     detectResultRoi(dst_size, src_tl, src_br);
110     CV_Assert(src_br.x - src_tl.x + 1 == src.cols && src_br.y - src_tl.y + 1 == src.rows);
111
112     Mat xmap(dst_size, CV_32F);
113     Mat ymap(dst_size, CV_32F);
114
115     float u, v;
116     for (int y = 0; y < dst_size.height; ++y)
117     {
118         for (int x = 0; x < dst_size.width; ++x)
119         {
120             projector_.mapForward(static_cast<float>(x), static_cast<float>(y), u, v);
121             xmap.at<float>(y, x) = u - src_tl.x;
122             ymap.at<float>(y, x) = v - src_tl.y;
123         }
124     }
125
126     dst.create(dst_size, src.type());
127     remap(src, dst, xmap, ymap, interp_mode, border_mode);
128 }
129
130
131 template <class P>
132 Rect RotationWarperBase<P>::warpRoi(Size src_size, const Mat &K, const Mat &R)
133 {
134     projector_.setCameraParams(K, R);
135
136     Point dst_tl, dst_br;
137     detectResultRoi(src_size, dst_tl, dst_br);
138
139     return Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1));
140 }
141
142
143 template <class P>
144 void RotationWarperBase<P>::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)
145 {
146     float tl_uf = std::numeric_limits<float>::max();
147     float tl_vf = std::numeric_limits<float>::max();
148     float br_uf = -std::numeric_limits<float>::max();
149     float br_vf = -std::numeric_limits<float>::max();
150
151     float u, v;
152     for (int y = 0; y < src_size.height; ++y)
153     {
154         for (int x = 0; x < src_size.width; ++x)
155         {
156             projector_.mapForward(static_cast<float>(x), static_cast<float>(y), u, v);
157             tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
158             br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
159         }
160     }
161
162     dst_tl.x = static_cast<int>(tl_uf);
163     dst_tl.y = static_cast<int>(tl_vf);
164     dst_br.x = static_cast<int>(br_uf);
165     dst_br.y = static_cast<int>(br_vf);
166 }
167
168
169 template <class P>
170 void RotationWarperBase<P>::detectResultRoiByBorder(Size src_size, Point &dst_tl, Point &dst_br)
171 {
172     float tl_uf = std::numeric_limits<float>::max();
173     float tl_vf = std::numeric_limits<float>::max();
174     float br_uf = -std::numeric_limits<float>::max();
175     float br_vf = -std::numeric_limits<float>::max();
176
177     float u, v;
178     for (float x = 0; x < src_size.width; ++x)
179     {
180         projector_.mapForward(static_cast<float>(x), 0, u, v);
181         tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
182         br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
183
184         projector_.mapForward(static_cast<float>(x), static_cast<float>(src_size.height - 1), u, v);
185         tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
186         br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
187     }
188     for (int y = 0; y < src_size.height; ++y)
189     {
190         projector_.mapForward(0, static_cast<float>(y), u, v);
191         tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
192         br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
193
194         projector_.mapForward(static_cast<float>(src_size.width - 1), static_cast<float>(y), u, v);
195         tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
196         br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
197     }
198
199     dst_tl.x = static_cast<int>(tl_uf);
200     dst_tl.y = static_cast<int>(tl_vf);
201     dst_br.x = static_cast<int>(br_uf);
202     dst_br.y = static_cast<int>(br_vf);
203 }
204
205
206 inline
207 void PlaneProjector::mapForward(float x, float y, float &u, float &v)
208 {
209     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
210     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
211     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
212
213     x_ = t[0] + x_ / z_ * (1 - t[2]);
214     y_ = t[1] + y_ / z_ * (1 - t[2]);
215
216     u = scale * x_;
217     v = scale * y_;
218 }
219
220
221 inline
222 void PlaneProjector::mapBackward(float u, float v, float &x, float &y)
223 {
224     u = u / scale - t[0];
225     v = v / scale - t[1];
226
227     float z;
228     x = k_rinv[0] * u + k_rinv[1] * v + k_rinv[2] * (1 - t[2]);
229     y = k_rinv[3] * u + k_rinv[4] * v + k_rinv[5] * (1 - t[2]);
230     z = k_rinv[6] * u + k_rinv[7] * v + k_rinv[8] * (1 - t[2]);
231
232     x /= z;
233     y /= z;
234 }
235
236
237 inline
238 void SphericalProjector::mapForward(float x, float y, float &u, float &v)
239 {
240     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
241     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
242     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
243
244     u = scale * atan2f(x_, z_);
245     float w = y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_);
246     v = scale * (static_cast<float>(CV_PI) - acosf(w == w ? w : 0));
247 }
248
249
250 inline
251 void SphericalProjector::mapBackward(float u, float v, float &x, float &y)
252 {
253     u /= scale;
254     v /= scale;
255
256     float sinv = sinf(static_cast<float>(CV_PI) - v);
257     float x_ = sinv * sinf(u);
258     float y_ = cosf(static_cast<float>(CV_PI) - v);
259     float z_ = sinv * cosf(u);
260
261     float z;
262     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
263     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
264     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
265
266     if (z > 0) { x /= z; y /= z; }
267     else x = y = -1;
268 }
269
270
271 inline
272 void CylindricalProjector::mapForward(float x, float y, float &u, float &v)
273 {
274     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
275     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
276     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
277
278     u = scale * atan2f(x_, z_);
279     v = scale * y_ / sqrtf(x_ * x_ + z_ * z_);
280 }
281
282
283 inline
284 void CylindricalProjector::mapBackward(float u, float v, float &x, float &y)
285 {
286     u /= scale;
287     v /= scale;
288
289     float x_ = sinf(u);
290     float y_ = v;
291     float z_ = cosf(u);
292
293     float z;
294     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
295     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
296     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
297
298     if (z > 0) { x /= z; y /= z; }
299     else x = y = -1;
300 }
301
302 inline
303 void FisheyeProjector::mapForward(float x, float y, float &u, float &v)
304 {
305     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
306     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
307     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
308
309     float u_ = atan2f(x_, z_);
310     float v_ = (float)CV_PI - acosf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
311
312     u = scale * v_ * cosf(u_);
313     v = scale * v_ * sinf(u_);
314 }
315
316 inline
317 void FisheyeProjector::mapBackward(float u, float v, float &x, float &y)
318 {
319     u /= scale;
320     v /= scale;
321
322     float u_ = atan2f(v, u);
323     float v_ = sqrtf(u*u + v*v);
324
325     float sinv = sinf((float)CV_PI - v_);
326     float x_ = sinv * sinf(u_);
327     float y_ = cosf((float)CV_PI - v_);
328     float z_ = sinv * cosf(u_);
329
330     float z;
331     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
332     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
333     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
334
335     if (z > 0) { x /= z; y /= z; }
336     else x = y = -1;
337 }
338
339 inline
340 void StereographicProjector::mapForward(float x, float y, float &u, float &v)
341 {
342     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
343     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
344     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
345
346     float u_ = atan2f(x_, z_);
347     float v_ = (float)CV_PI - acosf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
348
349     float r = sinf(v_) / (1 - cosf(v_));
350
351     u = scale * r * cos(u_);
352     v = scale * r * sin(u_);
353 }
354
355 inline
356 void StereographicProjector::mapBackward(float u, float v, float &x, float &y)
357 {
358     u /= scale;
359     v /= scale;
360
361     float u_ = atan2f(v, u);
362     float r = sqrtf(u*u + v*v);
363     float v_ = 2 * atanf(1.f / r);
364
365     float sinv = sinf((float)CV_PI - v_);
366     float x_ = sinv * sinf(u_);
367     float y_ = cosf((float)CV_PI - v_);
368     float z_ = sinv * cosf(u_);
369
370     float z;
371     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
372     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
373     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
374
375     if (z > 0) { x /= z; y /= z; }
376     else x = y = -1;
377 }
378
379 inline
380 void CompressedRectilinearProjector::mapForward(float x, float y, float &u, float &v)
381 {
382     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
383     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
384     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
385
386     float u_ = atan2f(x_, z_);
387     float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
388
389     u = scale * a * tanf(u_ / a);
390     v = scale * b * tanf(v_) / cosf(u_);
391 }
392
393 inline
394 void CompressedRectilinearProjector::mapBackward(float u, float v, float &x, float &y)
395 {
396     u /= scale;
397     v /= scale;
398
399     float aatg = a * atanf(u / a);
400     float u_ = aatg;
401     float v_ = atanf(v * cosf(aatg) / b);
402
403     float cosv = cosf(v_);
404     float x_ = cosv * sinf(u_);
405     float y_ = sinf(v_);
406     float z_ = cosv * cosf(u_);
407
408     float z;
409     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
410     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
411     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
412
413     if (z > 0) { x /= z; y /= z; }
414     else x = y = -1;
415 }
416
417 inline
418 void CompressedRectilinearPortraitProjector::mapForward(float x, float y, float &u, float &v)
419 {
420     float y_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
421     float x_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
422     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
423
424     float u_ = atan2f(x_, z_);
425     float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
426
427     u = - scale * a * tanf(u_ / a);
428     v = scale * b * tanf(v_) / cosf(u_);
429 }
430
431 inline
432 void CompressedRectilinearPortraitProjector::mapBackward(float u, float v, float &x, float &y)
433 {
434     u /= - scale;
435     v /= scale;
436
437     float aatg = a * atanf(u / a);
438     float u_ = aatg;
439     float v_ = atanf(v * cosf( aatg ) / b);
440
441     float cosv = cosf(v_);
442     float y_ = cosv * sinf(u_);
443     float x_ = sinf(v_);
444     float z_ = cosv * cosf(u_);
445
446     float z;
447     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
448     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
449     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
450
451     if (z > 0) { x /= z; y /= z; }
452     else x = y = -1;
453 }
454
455 inline
456 void PaniniProjector::mapForward(float x, float y, float &u, float &v)
457 {
458     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
459     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
460     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
461
462     float u_ = atan2f(x_, z_);
463     float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
464
465     float tg = a * tanf(u_ / a);
466     u = scale * tg;
467
468     float sinu = sinf(u_);
469     if ( fabs(sinu) < 1E-7 )
470         v = scale * b * tanf(v_);
471     else
472         v = scale * b * tg * tanf(v_) / sinu;
473 }
474
475 inline
476 void PaniniProjector::mapBackward(float u, float v, float &x, float &y)
477 {
478     u /= scale;
479     v /= scale;
480
481     float lamda = a * atanf(u / a);
482     float u_ = lamda;
483
484     float v_;
485     if ( fabs(lamda) > 1E-7)
486         v_ = atanf(v * sinf(lamda) / (b * a * tanf(lamda / a)));
487     else
488         v_ = atanf(v / b);
489
490     float cosv = cosf(v_);
491     float x_ = cosv * sinf(u_);
492     float y_ = sinf(v_);
493     float z_ = cosv * cosf(u_);
494
495     float z;
496     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
497     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
498     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
499
500     if (z > 0) { x /= z; y /= z; }
501     else x = y = -1;
502 }
503
504 inline
505 void PaniniPortraitProjector::mapForward(float x, float y, float &u, float &v)
506 {
507     float y_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
508     float x_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
509     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
510
511     float u_ = atan2f(x_, z_);
512     float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
513
514     float tg = a * tanf(u_ / a);
515     u = - scale * tg;
516
517     float sinu = sinf( u_ );
518     if ( fabs(sinu) < 1E-7 )
519         v = scale * b * tanf(v_);
520     else
521         v = scale * b * tg * tanf(v_) / sinu;
522 }
523
524 inline
525 void PaniniPortraitProjector::mapBackward(float u, float v, float &x, float &y)
526 {
527     u /= - scale;
528     v /= scale;
529
530     float lamda = a * atanf(u / a);
531     float u_ = lamda;
532
533     float v_;
534     if ( fabs(lamda) > 1E-7)
535         v_ = atanf(v * sinf(lamda) / (b * a * tanf(lamda/a)));
536     else
537         v_ = atanf(v / b);
538
539     float cosv = cosf(v_);
540     float y_ = cosv * sinf(u_);
541     float x_ = sinf(v_);
542     float z_ = cosv * cosf(u_);
543
544     float z;
545     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
546     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
547     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
548
549     if (z > 0) { x /= z; y /= z; }
550     else x = y = -1;
551 }
552
553 inline
554 void MercatorProjector::mapForward(float x, float y, float &u, float &v)
555 {
556     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
557     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
558     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
559
560     float u_ = atan2f(x_, z_);
561     float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
562
563     u = scale * u_;
564     v = scale * logf( tanf( (float)(CV_PI/4) + v_/2 ) );
565 }
566
567 inline
568 void MercatorProjector::mapBackward(float u, float v, float &x, float &y)
569 {
570     u /= scale;
571     v /= scale;
572
573     float v_ = atanf( sinhf(v) );
574     float u_ = u;
575
576     float cosv = cosf(v_);
577     float x_ = cosv * sinf(u_);
578     float y_ = sinf(v_);
579     float z_ = cosv * cosf(u_);
580
581     float z;
582     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
583     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
584     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
585
586     if (z > 0) { x /= z; y /= z; }
587     else x = y = -1;
588 }
589
590 inline
591 void TransverseMercatorProjector::mapForward(float x, float y, float &u, float &v)
592 {
593     float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
594     float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
595     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
596
597     float u_ = atan2f(x_, z_);
598     float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_));
599
600     float B = cosf(v_) * sinf(u_);
601
602     u = scale / 2 * logf( (1+B) / (1-B) );
603     v = scale * atan2f(tanf(v_), cosf(u_));
604 }
605
606 inline
607 void TransverseMercatorProjector::mapBackward(float u, float v, float &x, float &y)
608 {
609     u /= scale;
610     v /= scale;
611
612     float v_ = asinf( sinf(v) / coshf(u) );
613     float u_ = atan2f( sinhf(u), cos(v) );
614
615     float cosv = cosf(v_);
616     float x_ = cosv * sinf(u_);
617     float y_ = sinf(v_);
618     float z_ = cosv * cosf(u_);
619
620     float z;
621     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
622     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
623     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
624
625     if (z > 0) { x /= z; y /= z; }
626     else x = y = -1;
627 }
628
629 inline
630 void SphericalPortraitProjector::mapForward(float x, float y, float &u0, float &v0)
631 {
632     float x0_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
633     float y0_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
634     float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
635
636     float x_ = y0_;
637     float y_ = x0_;
638     float u, v;
639
640     u = scale * atan2f(x_, z_);
641     v = scale * (static_cast<float>(CV_PI) - acosf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_)));
642
643     u0 = -u;//v;
644     v0 = v;//u;
645 }
646
647
648 inline
649 void SphericalPortraitProjector::mapBackward(float u0, float v0, float &x, float &y)
650 {
651     float u, v;
652     u = -u0;//v0;
653     v = v0;//u0;
654
655     u /= scale;
656     v /= scale;
657
658     float sinv = sinf(static_cast<float>(CV_PI) - v);
659     float x0_ = sinv * sinf(u);
660     float y0_ = cosf(static_cast<float>(CV_PI) - v);
661     float z_ = sinv * cosf(u);
662
663     float x_ = y0_;
664     float y_ = x0_;
665
666     float z;
667     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
668     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
669     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
670
671     if (z > 0) { x /= z; y /= z; }
672     else x = y = -1;
673 }
674
675 inline
676 void CylindricalPortraitProjector::mapForward(float x, float y, float &u0, float &v0)
677 {
678     float x0_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
679     float y0_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
680     float z_  = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
681
682     float x_ = y0_;
683     float y_ = x0_;
684     float u, v;
685
686     u = scale * atan2f(x_, z_);
687     v = scale * y_ / sqrtf(x_ * x_ + z_ * z_);
688
689     u0 = -u;//v;
690     v0 = v;//u;
691 }
692
693
694 inline
695 void CylindricalPortraitProjector::mapBackward(float u0, float v0, float &x, float &y)
696 {
697     float u, v;
698     u = -u0;//v0;
699     v = v0;//u0;
700
701     u /= scale;
702     v /= scale;
703
704     float x0_ = sinf(u);
705     float y0_ = v;
706     float z_  = cosf(u);
707
708     float x_ = y0_;
709     float y_ = x0_;
710
711     float z;
712     x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
713     y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
714     z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
715
716     if (z > 0) { x /= z; y /= z; }
717     else x = y = -1;
718 }
719
720 inline
721 void PlanePortraitProjector::mapForward(float x, float y, float &u0, float &v0)
722 {
723     float x0_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
724     float y0_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
725     float z_  = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
726
727     float x_ = y0_;
728     float y_ = x0_;
729
730     x_ = t[0] + x_ / z_ * (1 - t[2]);
731     y_ = t[1] + y_ / z_ * (1 - t[2]);
732
733     float u,v;
734     u = scale * x_;
735     v = scale * y_;
736
737     u0 = -u;
738     v0 = v;
739 }
740
741
742 inline
743 void PlanePortraitProjector::mapBackward(float u0, float v0, float &x, float &y)
744 {
745     float u, v;
746     u = -u0;
747     v = v0;
748
749     u = u / scale - t[0];
750     v = v / scale - t[1];
751
752     float z;
753     x = k_rinv[0] * v + k_rinv[1] * u + k_rinv[2] * (1 - t[2]);
754     y = k_rinv[3] * v + k_rinv[4] * u + k_rinv[5] * (1 - t[2]);
755     z = k_rinv[6] * v + k_rinv[7] * u + k_rinv[8] * (1 - t[2]);
756
757     x /= z;
758     y /= z;
759 }
760
761
762 } // namespace detail
763 } // namespace cv
764
765 #endif // __OPENCV_STITCHING_WARPERS_INL_HPP__