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_TEMPLATE RotationWarperBase : public RotationWarper
142 {
143 public:
144     Point2f warpPoint(const Point2f &pt, InputArray K, InputArray R) CV_OVERRIDE;
145 
146     Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap) CV_OVERRIDE;
147 
148     Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
149                OutputArray dst) CV_OVERRIDE;
150 
151     void warpBackward(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
152                       Size dst_size, OutputArray dst) CV_OVERRIDE;
153 
154     Rect warpRoi(Size src_size, InputArray K, InputArray R) CV_OVERRIDE;
155 
getScale() const156     float getScale() const  CV_OVERRIDE{ return projector_.scale; }
setScale(float val)157     void setScale(float val) CV_OVERRIDE { 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) CV_OVERRIDE;
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) CV_OVERRIDE;
194 
195     Point warp(InputArray src, InputArray K, InputArray R,
196                int interp_mode, int border_mode, OutputArray dst) CV_OVERRIDE;
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) CV_OVERRIDE;
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) CV_OVERRIDE;
205 };
206 
207 
208 /** @brief Affine warper that uses rotations and translations
209 
210  Uses affine transformation in homogeneous coordinates to represent both rotation and
211  translation in camera rotation matrix.
212  */
213 class CV_EXPORTS AffineWarper : public PlaneWarper
214 {
215 public:
216     /** @brief Construct an instance of the affine warper class.
217 
218     @param scale Projected image scale multiplier
219      */
AffineWarper(float scale=1.f)220     AffineWarper(float scale = 1.f) : PlaneWarper(scale) {}
221 
222     Point2f warpPoint(const Point2f &pt, InputArray K, InputArray R) CV_OVERRIDE;
223     Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap) CV_OVERRIDE;
224     Point warp(InputArray src, InputArray K, InputArray R,
225                int interp_mode, int border_mode, OutputArray dst) CV_OVERRIDE;
226     Rect warpRoi(Size src_size, InputArray K, InputArray R) CV_OVERRIDE;
227 
228 protected:
229     /** @brief Extracts rotation and translation matrices from matrix H representing
230         affine transformation in homogeneous coordinates
231      */
232     void getRTfromHomogeneous(InputArray H, Mat &R, Mat &T);
233 };
234 
235 
236 struct CV_EXPORTS SphericalProjector : 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 unit sphere located at the origin.
244 
245  Projects image onto unit sphere with origin at (0, 0, 0) and radius scale, measured in pixels.
246  A 360 panorama would therefore have a resulting width of 2 * scale * PI pixels.
247  Poles are located at (0, -1, 0) and (0, 1, 0) points.
248 */
249 class CV_EXPORTS SphericalWarper : public RotationWarperBase<SphericalProjector>
250 {
251 public:
252     /** @brief Construct an instance of the spherical warper class.
253 
254     @param scale Radius of the projected sphere, in pixels. An image spanning the
255                  whole sphere will have a width of 2 * scale * PI pixels.
256      */
SphericalWarper(float scale)257     SphericalWarper(float scale) { projector_.scale = scale; }
258 
259     Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap) CV_OVERRIDE;
260     Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst) CV_OVERRIDE;
261 protected:
262     void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) CV_OVERRIDE;
263 };
264 
265 
266 struct CV_EXPORTS CylindricalProjector : ProjectorBase
267 {
268     void mapForward(float x, float y, float &u, float &v);
269     void mapBackward(float u, float v, float &x, float &y);
270 };
271 
272 
273 /** @brief Warper that maps an image onto the x\*x + z\*z = 1 cylinder.
274  */
275 class CV_EXPORTS CylindricalWarper : public RotationWarperBase<CylindricalProjector>
276 {
277 public:
278     /** @brief Construct an instance of the cylindrical warper class.
279 
280     @param scale Projected image scale multiplier
281      */
CylindricalWarper(float scale)282     CylindricalWarper(float scale) { projector_.scale = scale; }
283 
284     Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap) CV_OVERRIDE;
285     Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst) CV_OVERRIDE;
286 protected:
detectResultRoi(Size src_size,Point & dst_tl,Point & dst_br)287     void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) CV_OVERRIDE
288     {
289         RotationWarperBase<CylindricalProjector>::detectResultRoiByBorder(src_size, dst_tl, dst_br);
290     }
291 };
292 
293 
294 struct CV_EXPORTS FisheyeProjector : ProjectorBase
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 FisheyeWarper : public RotationWarperBase<FisheyeProjector>
302 {
303 public:
FisheyeWarper(float scale)304     FisheyeWarper(float scale) { projector_.scale = scale; }
305 };
306 
307 
308 struct CV_EXPORTS StereographicProjector : ProjectorBase
309 {
310     void mapForward(float x, float y, float &u, float &v);
311     void mapBackward(float u, float v, float &x, float &y);
312 };
313 
314 
315 class CV_EXPORTS StereographicWarper : public RotationWarperBase<StereographicProjector>
316 {
317 public:
StereographicWarper(float scale)318     StereographicWarper(float scale) { projector_.scale = scale; }
319 };
320 
321 
322 struct CV_EXPORTS CompressedRectilinearProjector : ProjectorBase
323 {
324     float a, b;
325 
326     void mapForward(float x, float y, float &u, float &v);
327     void mapBackward(float u, float v, float &x, float &y);
328 };
329 
330 
331 class CV_EXPORTS CompressedRectilinearWarper : public RotationWarperBase<CompressedRectilinearProjector>
332 {
333 public:
CompressedRectilinearWarper(float scale,float A=1,float B=1)334     CompressedRectilinearWarper(float scale, float A = 1, float B = 1)
335     {
336         projector_.a = A;
337         projector_.b = B;
338         projector_.scale = scale;
339     }
340 };
341 
342 
343 struct CV_EXPORTS CompressedRectilinearPortraitProjector : ProjectorBase
344 {
345     float a, b;
346 
347     void mapForward(float x, float y, float &u, float &v);
348     void mapBackward(float u, float v, float &x, float &y);
349 };
350 
351 
352 class CV_EXPORTS CompressedRectilinearPortraitWarper : public RotationWarperBase<CompressedRectilinearPortraitProjector>
353 {
354 public:
CompressedRectilinearPortraitWarper(float scale,float A=1,float B=1)355    CompressedRectilinearPortraitWarper(float scale, float A = 1, float B = 1)
356    {
357        projector_.a = A;
358        projector_.b = B;
359        projector_.scale = scale;
360    }
361 };
362 
363 
364 struct CV_EXPORTS PaniniProjector : ProjectorBase
365 {
366     float a, b;
367 
368     void mapForward(float x, float y, float &u, float &v);
369     void mapBackward(float u, float v, float &x, float &y);
370 };
371 
372 
373 class CV_EXPORTS PaniniWarper : public RotationWarperBase<PaniniProjector>
374 {
375 public:
PaniniWarper(float scale,float A=1,float B=1)376    PaniniWarper(float scale, float A = 1, float B = 1)
377    {
378        projector_.a = A;
379        projector_.b = B;
380        projector_.scale = scale;
381    }
382 };
383 
384 
385 struct CV_EXPORTS PaniniPortraitProjector : ProjectorBase
386 {
387     float a, b;
388 
389     void mapForward(float x, float y, float &u, float &v);
390     void mapBackward(float u, float v, float &x, float &y);
391 };
392 
393 
394 class CV_EXPORTS PaniniPortraitWarper : public RotationWarperBase<PaniniPortraitProjector>
395 {
396 public:
PaniniPortraitWarper(float scale,float A=1,float B=1)397    PaniniPortraitWarper(float scale, float A = 1, float B = 1)
398    {
399        projector_.a = A;
400        projector_.b = B;
401        projector_.scale = scale;
402    }
403 
404 };
405 
406 
407 struct CV_EXPORTS MercatorProjector : ProjectorBase
408 {
409     void mapForward(float x, float y, float &u, float &v);
410     void mapBackward(float u, float v, float &x, float &y);
411 };
412 
413 
414 class CV_EXPORTS MercatorWarper : public RotationWarperBase<MercatorProjector>
415 {
416 public:
MercatorWarper(float scale)417     MercatorWarper(float scale) { projector_.scale = scale; }
418 };
419 
420 
421 struct CV_EXPORTS TransverseMercatorProjector : ProjectorBase
422 {
423     void mapForward(float x, float y, float &u, float &v);
424     void mapBackward(float u, float v, float &x, float &y);
425 };
426 
427 
428 class CV_EXPORTS TransverseMercatorWarper : public RotationWarperBase<TransverseMercatorProjector>
429 {
430 public:
TransverseMercatorWarper(float scale)431     TransverseMercatorWarper(float scale) { projector_.scale = scale; }
432 };
433 
434 
435 class CV_EXPORTS PlaneWarperGpu : public PlaneWarper
436 {
437 public:
PlaneWarperGpu(float scale=1.f)438     PlaneWarperGpu(float scale = 1.f) : PlaneWarper(scale) {}
439 
buildMaps(Size src_size,InputArray K,InputArray R,OutputArray xmap,OutputArray ymap)440     Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap) CV_OVERRIDE
441     {
442         Rect result = buildMaps(src_size, K, R, d_xmap_, d_ymap_);
443         d_xmap_.download(xmap);
444         d_ymap_.download(ymap);
445         return result;
446     }
447 
buildMaps(Size src_size,InputArray K,InputArray R,InputArray T,OutputArray xmap,OutputArray ymap)448     Rect buildMaps(Size src_size, InputArray K, InputArray R, InputArray T, OutputArray xmap, OutputArray ymap) CV_OVERRIDE
449     {
450         Rect result = buildMaps(src_size, K, R, T, d_xmap_, d_ymap_);
451         d_xmap_.download(xmap);
452         d_ymap_.download(ymap);
453         return result;
454     }
455 
warp(InputArray src,InputArray K,InputArray R,int interp_mode,int border_mode,OutputArray dst)456     Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
457                OutputArray dst) CV_OVERRIDE
458     {
459         d_src_.upload(src);
460         Point result = warp(d_src_, K, R, interp_mode, border_mode, d_dst_);
461         d_dst_.download(dst);
462         return result;
463     }
464 
warp(InputArray src,InputArray K,InputArray R,InputArray T,int interp_mode,int border_mode,OutputArray dst)465     Point warp(InputArray src, InputArray K, InputArray R, InputArray T, int interp_mode, int border_mode,
466                OutputArray dst) CV_OVERRIDE
467     {
468         d_src_.upload(src);
469         Point result = warp(d_src_, K, R, T, interp_mode, border_mode, d_dst_);
470         d_dst_.download(dst);
471         return result;
472     }
473 
474     Rect buildMaps(Size src_size, InputArray K, InputArray R, cuda::GpuMat & xmap, cuda::GpuMat & ymap);
475 
476     Rect buildMaps(Size src_size, InputArray K, InputArray R, InputArray T, cuda::GpuMat & xmap, cuda::GpuMat & ymap);
477 
478     Point warp(const cuda::GpuMat & src, InputArray K, InputArray R, int interp_mode, int border_mode,
479                cuda::GpuMat & dst);
480 
481     Point warp(const cuda::GpuMat & src, InputArray K, InputArray R, InputArray T, int interp_mode, int border_mode,
482                cuda::GpuMat & dst);
483 
484 private:
485     cuda::GpuMat d_xmap_, d_ymap_, d_src_, d_dst_;
486 };
487 
488 
489 class CV_EXPORTS SphericalWarperGpu : public SphericalWarper
490 {
491 public:
SphericalWarperGpu(float scale)492     SphericalWarperGpu(float scale) : SphericalWarper(scale) {}
493 
buildMaps(Size src_size,InputArray K,InputArray R,OutputArray xmap,OutputArray ymap)494     Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap) CV_OVERRIDE
495     {
496         Rect result = buildMaps(src_size, K, R, d_xmap_, d_ymap_);
497         d_xmap_.download(xmap);
498         d_ymap_.download(ymap);
499         return result;
500     }
501 
warp(InputArray src,InputArray K,InputArray R,int interp_mode,int border_mode,OutputArray dst)502     Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
503                OutputArray dst) CV_OVERRIDE
504     {
505         d_src_.upload(src);
506         Point result = warp(d_src_, K, R, interp_mode, border_mode, d_dst_);
507         d_dst_.download(dst);
508         return result;
509     }
510 
511     Rect buildMaps(Size src_size, InputArray K, InputArray R, cuda::GpuMat & xmap, cuda::GpuMat & ymap);
512 
513     Point warp(const cuda::GpuMat & src, InputArray K, InputArray R, int interp_mode, int border_mode,
514                cuda::GpuMat & dst);
515 
516 private:
517     cuda::GpuMat d_xmap_, d_ymap_, d_src_, d_dst_;
518 };
519 
520 
521 class CV_EXPORTS CylindricalWarperGpu : public CylindricalWarper
522 {
523 public:
CylindricalWarperGpu(float scale)524     CylindricalWarperGpu(float scale) : CylindricalWarper(scale) {}
525 
buildMaps(Size src_size,InputArray K,InputArray R,OutputArray xmap,OutputArray ymap)526     Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap) CV_OVERRIDE
527     {
528         Rect result = buildMaps(src_size, K, R, d_xmap_, d_ymap_);
529         d_xmap_.download(xmap);
530         d_ymap_.download(ymap);
531         return result;
532     }
533 
warp(InputArray src,InputArray K,InputArray R,int interp_mode,int border_mode,OutputArray dst)534     Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
535                OutputArray dst) CV_OVERRIDE
536     {
537         d_src_.upload(src);
538         Point result = warp(d_src_, K, R, interp_mode, border_mode, d_dst_);
539         d_dst_.download(dst);
540         return result;
541     }
542 
543     Rect buildMaps(Size src_size, InputArray K, InputArray R, cuda::GpuMat & xmap, cuda::GpuMat & ymap);
544 
545     Point warp(const cuda::GpuMat & src, InputArray K, InputArray R, int interp_mode, int border_mode,
546                cuda::GpuMat & dst);
547 
548 private:
549     cuda::GpuMat d_xmap_, d_ymap_, d_src_, d_dst_;
550 };
551 
552 
553 struct CV_EXPORTS SphericalPortraitProjector : ProjectorBase
554 {
555     void mapForward(float x, float y, float &u, float &v);
556     void mapBackward(float u, float v, float &x, float &y);
557 };
558 
559 
560 // Projects image onto unit sphere with origin at (0, 0, 0).
561 // Poles are located NOT at (0, -1, 0) and (0, 1, 0) points, BUT at (1, 0, 0) and (-1, 0, 0) points.
562 class CV_EXPORTS SphericalPortraitWarper : public RotationWarperBase<SphericalPortraitProjector>
563 {
564 public:
SphericalPortraitWarper(float scale)565     SphericalPortraitWarper(float scale) { projector_.scale = scale; }
566 
567 protected:
568     void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) CV_OVERRIDE;
569 };
570 
571 struct CV_EXPORTS CylindricalPortraitProjector : ProjectorBase
572 {
573     void mapForward(float x, float y, float &u, float &v);
574     void mapBackward(float u, float v, float &x, float &y);
575 };
576 
577 
578 class CV_EXPORTS CylindricalPortraitWarper : public RotationWarperBase<CylindricalPortraitProjector>
579 {
580 public:
CylindricalPortraitWarper(float scale)581     CylindricalPortraitWarper(float scale) { projector_.scale = scale; }
582 
583 protected:
detectResultRoi(Size src_size,Point & dst_tl,Point & dst_br)584     void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) CV_OVERRIDE
585     {
586         RotationWarperBase<CylindricalPortraitProjector>::detectResultRoiByBorder(src_size, dst_tl, dst_br);
587     }
588 };
589 
590 struct CV_EXPORTS PlanePortraitProjector : ProjectorBase
591 {
592     void mapForward(float x, float y, float &u, float &v);
593     void mapBackward(float u, float v, float &x, float &y);
594 };
595 
596 
597 class CV_EXPORTS PlanePortraitWarper : public RotationWarperBase<PlanePortraitProjector>
598 {
599 public:
PlanePortraitWarper(float scale)600     PlanePortraitWarper(float scale) { projector_.scale = scale; }
601 
602 protected:
detectResultRoi(Size src_size,Point & dst_tl,Point & dst_br)603     void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) CV_OVERRIDE
604     {
605         RotationWarperBase<PlanePortraitProjector>::detectResultRoiByBorder(src_size, dst_tl, dst_br);
606     }
607 };
608 
609 //! @} stitching_warp
610 
611 } // namespace detail
612 } // namespace cv
613 
614 #include "warpers_inl.hpp"
615 
616 #endif // OPENCV_STITCHING_WARPERS_HPP
617