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_HPP__
44 #define __OPENCV_STITCHING_WARPERS_HPP__
45 
46 #include "opencv2/core.hpp"
47 #include "opencv2/core/cuda.hpp"
48 #include "opencv2/imgproc.hpp"
49 #include "opencv2/opencv_modules.hpp"
50 
51 namespace cv {
52 namespace detail {
53 
54 //! @addtogroup stitching_warp
55 //! @{
56 
57 /** @brief Rotation-only model image warper interface.
58  */
59 class CV_EXPORTS RotationWarper
60 {
61 public:
~RotationWarper()62     virtual ~RotationWarper() {}
63 
64     /** @brief Projects the image point.
65 
66     @param pt Source point
67     @param K Camera intrinsic parameters
68     @param R Camera rotation matrix
69     @return Projected point
70      */
71     virtual Point2f warpPoint(const Point2f &pt, InputArray K, InputArray R) = 0;
72 
73     /** @brief Builds the projection maps according to the given camera data.
74 
75     @param src_size Source image size
76     @param K Camera intrinsic parameters
77     @param R Camera rotation matrix
78     @param xmap Projection map for the x axis
79     @param ymap Projection map for the y axis
80     @return Projected image minimum bounding box
81      */
82     virtual Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap) = 0;
83 
84     /** @brief Projects the image.
85 
86     @param src Source image
87     @param K Camera intrinsic parameters
88     @param R Camera rotation matrix
89     @param interp_mode Interpolation mode
90     @param border_mode Border extrapolation mode
91     @param dst Projected image
92     @return Project image top-left corner
93      */
94     virtual Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
95                        OutputArray dst) = 0;
96 
97     /** @brief Projects the image backward.
98 
99     @param src Projected image
100     @param K Camera intrinsic parameters
101     @param R Camera rotation matrix
102     @param interp_mode Interpolation mode
103     @param border_mode Border extrapolation mode
104     @param dst_size Backward-projected image size
105     @param dst Backward-projected image
106      */
107     virtual void warpBackward(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
108                               Size dst_size, OutputArray dst) = 0;
109 
110     /**
111     @param src_size Source image bounding box
112     @param K Camera intrinsic parameters
113     @param R Camera rotation matrix
114     @return Projected image minimum bounding box
115      */
116     virtual Rect warpRoi(Size src_size, InputArray K, InputArray R) = 0;
117 
getScale() const118     virtual float getScale() const { return 1.f; }
setScale(float)119     virtual void setScale(float) {}
120 };
121 
122 /** @brief Base class for warping logic implementation.
123  */
124 struct CV_EXPORTS ProjectorBase
125 {
126     void setCameraParams(InputArray K = Mat::eye(3, 3, CV_32F),
127                          InputArray R = Mat::eye(3, 3, CV_32F),
128                          InputArray T = Mat::zeros(3, 1, CV_32F));
129 
130     float scale;
131     float k[9];
132     float rinv[9];
133     float r_kinv[9];
134     float k_rinv[9];
135     float t[3];
136 };
137 
138 /** @brief Base class for rotation-based warper using a detail::ProjectorBase_ derived class.
139  */
140 template <class P>
141 class CV_EXPORTS RotationWarperBase : public RotationWarper
142 {
143 public:
144     Point2f warpPoint(const Point2f &pt, InputArray K, InputArray R);
145 
146     Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap);
147 
148     Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
149                OutputArray dst);
150 
151     void warpBackward(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
152                       Size dst_size, OutputArray dst);
153 
154     Rect warpRoi(Size src_size, InputArray K, InputArray R);
155 
getScale() const156     float getScale() const { return projector_.scale; }
setScale(float val)157     void setScale(float val) { projector_.scale = val; }
158 
159 protected:
160 
161     // Detects ROI of the destination image. It's correct for any projection.
162     virtual void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br);
163 
164     // Detects ROI of the destination image by walking over image border.
165     // Correctness for any projection isn't guaranteed.
166     void detectResultRoiByBorder(Size src_size, Point &dst_tl, Point &dst_br);
167 
168     P projector_;
169 };
170 
171 
172 struct CV_EXPORTS PlaneProjector : ProjectorBase
173 {
174     void mapForward(float x, float y, float &u, float &v);
175     void mapBackward(float u, float v, float &x, float &y);
176 };
177 
178 /** @brief Warper that maps an image onto the z = 1 plane.
179  */
180 class CV_EXPORTS PlaneWarper : public RotationWarperBase<PlaneProjector>
181 {
182 public:
183     /** @brief Construct an instance of the plane warper class.
184 
185     @param scale Projected image scale multiplier
186      */
PlaneWarper(float scale=1.f)187     PlaneWarper(float scale = 1.f) { projector_.scale = scale; }
188 
189     Point2f warpPoint(const Point2f &pt, InputArray K, InputArray R);
190     Point2f warpPoint(const Point2f &pt, InputArray K, InputArray R, InputArray T);
191 
192     virtual Rect buildMaps(Size src_size, InputArray K, InputArray R, InputArray T, OutputArray xmap, OutputArray ymap);
193     Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap);
194 
195     Point warp(InputArray src, InputArray K, InputArray R,
196                int interp_mode, int border_mode, OutputArray dst);
197     virtual Point warp(InputArray src, InputArray K, InputArray R, InputArray T, int interp_mode, int border_mode,
198                OutputArray dst);
199 
200     Rect warpRoi(Size src_size, InputArray K, InputArray R);
201     Rect warpRoi(Size src_size, InputArray K, InputArray R, InputArray T);
202 
203 protected:
204     void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br);
205 };
206 
207 
208 struct CV_EXPORTS SphericalProjector : ProjectorBase
209 {
210     void mapForward(float x, float y, float &u, float &v);
211     void mapBackward(float u, float v, float &x, float &y);
212 };
213 
214 
215 /** @brief Warper that maps an image onto the unit sphere located at the origin.
216 
217  Projects image onto unit sphere with origin at (0, 0, 0).
218  Poles are located at (0, -1, 0) and (0, 1, 0) points.
219 */
220 class CV_EXPORTS SphericalWarper : public RotationWarperBase<SphericalProjector>
221 {
222 public:
223     /** @brief Construct an instance of the spherical warper class.
224 
225     @param scale Projected image scale multiplier
226      */
SphericalWarper(float scale)227     SphericalWarper(float scale) { projector_.scale = scale; }
228 
229     Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap);
230     Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst);
231 protected:
232     void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br);
233 };
234 
235 
236 struct CV_EXPORTS CylindricalProjector : ProjectorBase
237 {
238     void mapForward(float x, float y, float &u, float &v);
239     void mapBackward(float u, float v, float &x, float &y);
240 };
241 
242 
243 /** @brief Warper that maps an image onto the x\*x + z\*z = 1 cylinder.
244  */
245 class CV_EXPORTS CylindricalWarper : public RotationWarperBase<CylindricalProjector>
246 {
247 public:
248     /** @brief Construct an instance of the cylindrical warper class.
249 
250     @param scale Projected image scale multiplier
251      */
CylindricalWarper(float scale)252     CylindricalWarper(float scale) { projector_.scale = scale; }
253 
254     Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap);
255     Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst);
256 protected:
detectResultRoi(Size src_size,Point & dst_tl,Point & dst_br)257     void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)
258     {
259         RotationWarperBase<CylindricalProjector>::detectResultRoiByBorder(src_size, dst_tl, dst_br);
260     }
261 };
262 
263 
264 struct CV_EXPORTS FisheyeProjector : ProjectorBase
265 {
266     void mapForward(float x, float y, float &u, float &v);
267     void mapBackward(float u, float v, float &x, float &y);
268 };
269 
270 
271 class CV_EXPORTS FisheyeWarper : public RotationWarperBase<FisheyeProjector>
272 {
273 public:
FisheyeWarper(float scale)274     FisheyeWarper(float scale) { projector_.scale = scale; }
275 };
276 
277 
278 struct CV_EXPORTS StereographicProjector : ProjectorBase
279 {
280     void mapForward(float x, float y, float &u, float &v);
281     void mapBackward(float u, float v, float &x, float &y);
282 };
283 
284 
285 class CV_EXPORTS StereographicWarper : public RotationWarperBase<StereographicProjector>
286 {
287 public:
StereographicWarper(float scale)288     StereographicWarper(float scale) { projector_.scale = scale; }
289 };
290 
291 
292 struct CV_EXPORTS CompressedRectilinearProjector : ProjectorBase
293 {
294     float a, b;
295 
296     void mapForward(float x, float y, float &u, float &v);
297     void mapBackward(float u, float v, float &x, float &y);
298 };
299 
300 
301 class CV_EXPORTS CompressedRectilinearWarper : public RotationWarperBase<CompressedRectilinearProjector>
302 {
303 public:
CompressedRectilinearWarper(float scale,float A=1,float B=1)304     CompressedRectilinearWarper(float scale, float A = 1, float B = 1)
305     {
306         projector_.a = A;
307         projector_.b = B;
308         projector_.scale = scale;
309     }
310 };
311 
312 
313 struct CV_EXPORTS CompressedRectilinearPortraitProjector : ProjectorBase
314 {
315     float a, b;
316 
317     void mapForward(float x, float y, float &u, float &v);
318     void mapBackward(float u, float v, float &x, float &y);
319 };
320 
321 
322 class CV_EXPORTS CompressedRectilinearPortraitWarper : public RotationWarperBase<CompressedRectilinearPortraitProjector>
323 {
324 public:
CompressedRectilinearPortraitWarper(float scale,float A=1,float B=1)325    CompressedRectilinearPortraitWarper(float scale, float A = 1, float B = 1)
326    {
327        projector_.a = A;
328        projector_.b = B;
329        projector_.scale = scale;
330    }
331 };
332 
333 
334 struct CV_EXPORTS PaniniProjector : ProjectorBase
335 {
336     float a, b;
337 
338     void mapForward(float x, float y, float &u, float &v);
339     void mapBackward(float u, float v, float &x, float &y);
340 };
341 
342 
343 class CV_EXPORTS PaniniWarper : public RotationWarperBase<PaniniProjector>
344 {
345 public:
PaniniWarper(float scale,float A=1,float B=1)346    PaniniWarper(float scale, float A = 1, float B = 1)
347    {
348        projector_.a = A;
349        projector_.b = B;
350        projector_.scale = scale;
351    }
352 };
353 
354 
355 struct CV_EXPORTS PaniniPortraitProjector : ProjectorBase
356 {
357     float a, b;
358 
359     void mapForward(float x, float y, float &u, float &v);
360     void mapBackward(float u, float v, float &x, float &y);
361 };
362 
363 
364 class CV_EXPORTS PaniniPortraitWarper : public RotationWarperBase<PaniniPortraitProjector>
365 {
366 public:
PaniniPortraitWarper(float scale,float A=1,float B=1)367    PaniniPortraitWarper(float scale, float A = 1, float B = 1)
368    {
369        projector_.a = A;
370        projector_.b = B;
371        projector_.scale = scale;
372    }
373 
374 };
375 
376 
377 struct CV_EXPORTS MercatorProjector : ProjectorBase
378 {
379     void mapForward(float x, float y, float &u, float &v);
380     void mapBackward(float u, float v, float &x, float &y);
381 };
382 
383 
384 class CV_EXPORTS MercatorWarper : public RotationWarperBase<MercatorProjector>
385 {
386 public:
MercatorWarper(float scale)387     MercatorWarper(float scale) { projector_.scale = scale; }
388 };
389 
390 
391 struct CV_EXPORTS TransverseMercatorProjector : ProjectorBase
392 {
393     void mapForward(float x, float y, float &u, float &v);
394     void mapBackward(float u, float v, float &x, float &y);
395 };
396 
397 
398 class CV_EXPORTS TransverseMercatorWarper : public RotationWarperBase<TransverseMercatorProjector>
399 {
400 public:
TransverseMercatorWarper(float scale)401     TransverseMercatorWarper(float scale) { projector_.scale = scale; }
402 };
403 
404 
405 class CV_EXPORTS PlaneWarperGpu : public PlaneWarper
406 {
407 public:
PlaneWarperGpu(float scale=1.f)408     PlaneWarperGpu(float scale = 1.f) : PlaneWarper(scale) {}
409 
buildMaps(Size src_size,InputArray K,InputArray R,OutputArray xmap,OutputArray ymap)410     Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap)
411     {
412         Rect result = buildMaps(src_size, K, R, d_xmap_, d_ymap_);
413         d_xmap_.download(xmap);
414         d_ymap_.download(ymap);
415         return result;
416     }
417 
buildMaps(Size src_size,InputArray K,InputArray R,InputArray T,OutputArray xmap,OutputArray ymap)418     Rect buildMaps(Size src_size, InputArray K, InputArray R, InputArray T, OutputArray xmap, OutputArray ymap)
419     {
420         Rect result = buildMaps(src_size, K, R, T, d_xmap_, d_ymap_);
421         d_xmap_.download(xmap);
422         d_ymap_.download(ymap);
423         return result;
424     }
425 
warp(InputArray src,InputArray K,InputArray R,int interp_mode,int border_mode,OutputArray dst)426     Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
427                OutputArray dst)
428     {
429         d_src_.upload(src);
430         Point result = warp(d_src_, K, R, interp_mode, border_mode, d_dst_);
431         d_dst_.download(dst);
432         return result;
433     }
434 
warp(InputArray src,InputArray K,InputArray R,InputArray T,int interp_mode,int border_mode,OutputArray dst)435     Point warp(InputArray src, InputArray K, InputArray R, InputArray T, int interp_mode, int border_mode,
436                OutputArray dst)
437     {
438         d_src_.upload(src);
439         Point result = warp(d_src_, K, R, T, interp_mode, border_mode, d_dst_);
440         d_dst_.download(dst);
441         return result;
442     }
443 
444     Rect buildMaps(Size src_size, InputArray K, InputArray R, cuda::GpuMat & xmap, cuda::GpuMat & ymap);
445 
446     Rect buildMaps(Size src_size, InputArray K, InputArray R, InputArray T, cuda::GpuMat & xmap, cuda::GpuMat & ymap);
447 
448     Point warp(const cuda::GpuMat & src, InputArray K, InputArray R, int interp_mode, int border_mode,
449                cuda::GpuMat & dst);
450 
451     Point warp(const cuda::GpuMat & src, InputArray K, InputArray R, InputArray T, int interp_mode, int border_mode,
452                cuda::GpuMat & dst);
453 
454 private:
455     cuda::GpuMat d_xmap_, d_ymap_, d_src_, d_dst_;
456 };
457 
458 
459 class CV_EXPORTS SphericalWarperGpu : public SphericalWarper
460 {
461 public:
SphericalWarperGpu(float scale)462     SphericalWarperGpu(float scale) : SphericalWarper(scale) {}
463 
buildMaps(Size src_size,InputArray K,InputArray R,OutputArray xmap,OutputArray ymap)464     Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap)
465     {
466         Rect result = buildMaps(src_size, K, R, d_xmap_, d_ymap_);
467         d_xmap_.download(xmap);
468         d_ymap_.download(ymap);
469         return result;
470     }
471 
warp(InputArray src,InputArray K,InputArray R,int interp_mode,int border_mode,OutputArray dst)472     Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
473                OutputArray dst)
474     {
475         d_src_.upload(src);
476         Point result = warp(d_src_, K, R, interp_mode, border_mode, d_dst_);
477         d_dst_.download(dst);
478         return result;
479     }
480 
481     Rect buildMaps(Size src_size, InputArray K, InputArray R, cuda::GpuMat & xmap, cuda::GpuMat & ymap);
482 
483     Point warp(const cuda::GpuMat & src, InputArray K, InputArray R, int interp_mode, int border_mode,
484                cuda::GpuMat & dst);
485 
486 private:
487     cuda::GpuMat d_xmap_, d_ymap_, d_src_, d_dst_;
488 };
489 
490 
491 class CV_EXPORTS CylindricalWarperGpu : public CylindricalWarper
492 {
493 public:
CylindricalWarperGpu(float scale)494     CylindricalWarperGpu(float scale) : CylindricalWarper(scale) {}
495 
buildMaps(Size src_size,InputArray K,InputArray R,OutputArray xmap,OutputArray ymap)496     Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap)
497     {
498         Rect result = buildMaps(src_size, K, R, d_xmap_, d_ymap_);
499         d_xmap_.download(xmap);
500         d_ymap_.download(ymap);
501         return result;
502     }
503 
warp(InputArray src,InputArray K,InputArray R,int interp_mode,int border_mode,OutputArray dst)504     Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
505                OutputArray dst)
506     {
507         d_src_.upload(src);
508         Point result = warp(d_src_, K, R, interp_mode, border_mode, d_dst_);
509         d_dst_.download(dst);
510         return result;
511     }
512 
513     Rect buildMaps(Size src_size, InputArray K, InputArray R, cuda::GpuMat & xmap, cuda::GpuMat & ymap);
514 
515     Point warp(const cuda::GpuMat & src, InputArray K, InputArray R, int interp_mode, int border_mode,
516                cuda::GpuMat & dst);
517 
518 private:
519     cuda::GpuMat d_xmap_, d_ymap_, d_src_, d_dst_;
520 };
521 
522 
523 struct SphericalPortraitProjector : ProjectorBase
524 {
525     void mapForward(float x, float y, float &u, float &v);
526     void mapBackward(float u, float v, float &x, float &y);
527 };
528 
529 
530 // Projects image onto unit sphere with origin at (0, 0, 0).
531 // Poles are located NOT at (0, -1, 0) and (0, 1, 0) points, BUT at (1, 0, 0) and (-1, 0, 0) points.
532 class CV_EXPORTS SphericalPortraitWarper : public RotationWarperBase<SphericalPortraitProjector>
533 {
534 public:
SphericalPortraitWarper(float scale)535     SphericalPortraitWarper(float scale) { projector_.scale = scale; }
536 
537 protected:
538     void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br);
539 };
540 
541 struct CylindricalPortraitProjector : ProjectorBase
542 {
543     void mapForward(float x, float y, float &u, float &v);
544     void mapBackward(float u, float v, float &x, float &y);
545 };
546 
547 
548 class CV_EXPORTS CylindricalPortraitWarper : public RotationWarperBase<CylindricalPortraitProjector>
549 {
550 public:
CylindricalPortraitWarper(float scale)551     CylindricalPortraitWarper(float scale) { projector_.scale = scale; }
552 
553 protected:
detectResultRoi(Size src_size,Point & dst_tl,Point & dst_br)554     void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)
555     {
556         RotationWarperBase<CylindricalPortraitProjector>::detectResultRoiByBorder(src_size, dst_tl, dst_br);
557     }
558 };
559 
560 struct PlanePortraitProjector : ProjectorBase
561 {
562     void mapForward(float x, float y, float &u, float &v);
563     void mapBackward(float u, float v, float &x, float &y);
564 };
565 
566 
567 class CV_EXPORTS PlanePortraitWarper : public RotationWarperBase<PlanePortraitProjector>
568 {
569 public:
PlanePortraitWarper(float scale)570     PlanePortraitWarper(float scale) { projector_.scale = scale; }
571 
572 protected:
detectResultRoi(Size src_size,Point & dst_tl,Point & dst_br)573     void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)
574     {
575         RotationWarperBase<PlanePortraitProjector>::detectResultRoiByBorder(src_size, dst_tl, dst_br);
576     }
577 };
578 
579 //! @} stitching_warp
580 
581 } // namespace detail
582 } // namespace cv
583 
584 #include "warpers_inl.hpp"
585 
586 #endif // __OPENCV_STITCHING_WARPERS_HPP__
587