Commit 404e9cb9 authored by Alexey Spizhevoy's avatar Alexey Spizhevoy

Refactored warpers in the stitching module, added buildMaps function into the…

Refactored warpers in the stitching module, added buildMaps function into the RotationWarper interface
parent b7a3d367
...@@ -52,18 +52,20 @@ ...@@ -52,18 +52,20 @@
namespace cv { namespace cv {
namespace detail { namespace detail {
class CV_EXPORTS Warper class CV_EXPORTS RotationWarper
{ {
public: public:
virtual ~Warper() {} virtual ~RotationWarper() {}
virtual Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
int interp_mode, int border_mode) = 0; virtual Rect buildMaps(Size src_size, const Mat &K, const Mat &R, Mat &xmap, Mat &ymap) = 0;
virtual void warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Size dstSize,
int interp_mode, int border_mode) = 0; virtual Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
virtual Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst, Mat &dst) = 0;
int interp_mode, int border_mode) = 0;
virtual Rect warpRoi(const Size &sz, const Mat &K, const Mat &R) = 0; virtual void warpBackward(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
virtual Rect warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T) = 0; Size dst_size, Mat &dst) = 0;
virtual Rect warpRoi(Size src_size, const Mat &K, const Mat &R) = 0;
}; };
...@@ -83,27 +85,28 @@ struct CV_EXPORTS ProjectorBase ...@@ -83,27 +85,28 @@ struct CV_EXPORTS ProjectorBase
template <class P> template <class P>
class CV_EXPORTS WarperBase : public Warper class CV_EXPORTS RotationWarperBase : public RotationWarper
{ {
public: public:
Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Rect buildMaps(Size src_size, const Mat &K, const Mat &R, Mat &xmap, Mat &ymap);
int interp_mode, int border_mode);
void warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Size dstSize, Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
int interp_mode, int border_mode); Mat &dst);
Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst,
int interp_mode, int border_mode); void warpBackward(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
Rect warpRoi(const Size &sz, const Mat &K, const Mat &R); Size dst_size, Mat &dst);
Rect warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T);
Rect warpRoi(Size src_size, const Mat &K, const Mat &R);
protected: protected:
// Detects ROI of the destination image. It's correct for any projection. // Detects ROI of the destination image. It's correct for any projection.
virtual void detectResultRoi(Point &dst_tl, Point &dst_br); virtual void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br);
// Detects ROI of the destination image by walking over image border. // Detects ROI of the destination image by walking over image border.
// Correctness for any projection isn't guaranteed. // Correctness for any projection isn't guaranteed.
void detectResultRoiByBorder(Point &dst_tl, Point &dst_br); void detectResultRoiByBorder(Size src_size, Point &dst_tl, Point &dst_br);
Size src_size_;
P projector_; P projector_;
}; };
...@@ -116,17 +119,22 @@ struct CV_EXPORTS PlaneProjector : ProjectorBase ...@@ -116,17 +119,22 @@ struct CV_EXPORTS PlaneProjector : ProjectorBase
// Projects image onto z = plane_dist plane // Projects image onto z = plane_dist plane
class CV_EXPORTS PlaneWarper : public WarperBase<PlaneProjector> class CV_EXPORTS PlaneWarper : public RotationWarperBase<PlaneProjector>
{ {
public: public:
PlaneWarper(float scale = 1.f) { projector_.scale = scale; } PlaneWarper(float scale = 1.f) { projector_.scale = scale; }
void setScale(float scale) { projector_.scale = scale; } void setScale(float scale) { projector_.scale = scale; }
Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst,
int interp_mode, int border_mode); Rect buildMaps(Size src_size, const Mat &K, const Mat &R, const Mat &T, Mat &xmap, Mat &ymap);
Rect warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T);
Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, int interp_mode, int border_mode,
Mat &dst);
Rect warpRoi(Size src_size, const Mat &K, const Mat &R, const Mat &T);
protected: protected:
void detectResultRoi(Point &dst_tl, Point &dst_br); void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br);
}; };
...@@ -135,10 +143,12 @@ class CV_EXPORTS PlaneWarperGpu : public PlaneWarper ...@@ -135,10 +143,12 @@ class CV_EXPORTS PlaneWarperGpu : public PlaneWarper
{ {
public: public:
PlaneWarperGpu(float scale = 1.f) : PlaneWarper(scale) {} PlaneWarperGpu(float scale = 1.f) : PlaneWarper(scale) {}
Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
int interp_mode, int border_mode); Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst, Mat &dst);
int interp_mode, int border_mode);
Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, int interp_mode, int border_mode,
Mat &dst);
private: private:
gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_; gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_;
...@@ -155,13 +165,13 @@ struct CV_EXPORTS SphericalProjector : ProjectorBase ...@@ -155,13 +165,13 @@ struct CV_EXPORTS SphericalProjector : ProjectorBase
// Projects image onto unit sphere with origin at (0, 0, 0). // Projects image onto unit sphere with origin at (0, 0, 0).
// Poles are located at (0, -1, 0) and (0, 1, 0) points. // Poles are located at (0, -1, 0) and (0, 1, 0) points.
class CV_EXPORTS SphericalWarper : public WarperBase<SphericalProjector> class CV_EXPORTS SphericalWarper : public RotationWarperBase<SphericalProjector>
{ {
public: public:
SphericalWarper(float scale) { projector_.scale = scale; } SphericalWarper(float scale) { projector_.scale = scale; }
protected: protected:
void detectResultRoi(Point &dst_tl, Point &dst_br); void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br);
}; };
...@@ -170,8 +180,9 @@ class CV_EXPORTS SphericalWarperGpu : public SphericalWarper ...@@ -170,8 +180,9 @@ class CV_EXPORTS SphericalWarperGpu : public SphericalWarper
{ {
public: public:
SphericalWarperGpu(float scale) : SphericalWarper(scale) {} SphericalWarperGpu(float scale) : SphericalWarper(scale) {}
Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
int interp_mode, int border_mode); Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
Mat &dst);
private: private:
gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_; gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_;
...@@ -187,14 +198,16 @@ struct CV_EXPORTS CylindricalProjector : ProjectorBase ...@@ -187,14 +198,16 @@ struct CV_EXPORTS CylindricalProjector : ProjectorBase
// Projects image onto x * x + z * z = 1 cylinder // Projects image onto x * x + z * z = 1 cylinder
class CV_EXPORTS CylindricalWarper : public WarperBase<CylindricalProjector> class CV_EXPORTS CylindricalWarper : public RotationWarperBase<CylindricalProjector>
{ {
public: public:
CylindricalWarper(float scale) { projector_.scale = scale; } CylindricalWarper(float scale) { projector_.scale = scale; }
protected: protected:
void detectResultRoi(Point &dst_tl, Point &dst_br) void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)
{ WarperBase<CylindricalProjector>::detectResultRoiByBorder(dst_tl, dst_br); } {
RotationWarperBase<CylindricalProjector>::detectResultRoiByBorder(src_size, dst_tl, dst_br);
}
}; };
...@@ -203,8 +216,9 @@ class CV_EXPORTS CylindricalWarperGpu : public CylindricalWarper ...@@ -203,8 +216,9 @@ class CV_EXPORTS CylindricalWarperGpu : public CylindricalWarper
{ {
public: public:
CylindricalWarperGpu(float scale) : CylindricalWarper(scale) {} CylindricalWarperGpu(float scale) : CylindricalWarper(scale) {}
Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
int interp_mode, int border_mode); Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
Mat &dst);
private: private:
gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_; gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_;
......
...@@ -50,17 +50,15 @@ namespace cv { ...@@ -50,17 +50,15 @@ namespace cv {
namespace detail { namespace detail {
template <class P> template <class P>
Point WarperBase<P>::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Rect RotationWarperBase<P>::buildMaps(Size src_size, const Mat &K, const Mat &R, Mat &xmap, Mat &ymap)
int interp_mode, int border_mode)
{ {
src_size_ = src.size();
projector_.setCameraParams(K, R); projector_.setCameraParams(K, R);
Point dst_tl, dst_br; Point dst_tl, dst_br;
detectResultRoi(dst_tl, dst_br); detectResultRoi(src_size, dst_tl, dst_br);
Mat xmap(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F); xmap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);
Mat ymap(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F); ymap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);
float x, y; float x, y;
for (int v = dst_tl.y; v <= dst_br.y; ++v) for (int v = dst_tl.y; v <= dst_br.y; ++v)
...@@ -73,30 +71,41 @@ Point WarperBase<P>::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, ...@@ -73,30 +71,41 @@ Point WarperBase<P>::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
} }
} }
dst.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, src.type()); return Rect(dst_tl, dst_br);
}
template <class P>
Point RotationWarperBase<P>::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
Mat &dst)
{
Mat xmap, ymap;
Rect dst_roi = buildMaps(src.size(), K, R, xmap, ymap);
dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());
remap(src, dst, xmap, ymap, interp_mode, border_mode); remap(src, dst, xmap, ymap, interp_mode, border_mode);
return dst_tl; return dst_roi.tl();
} }
template <class P> template <class P>
void WarperBase<P>::warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Size dstSize, void RotationWarperBase<P>::warpBackward(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
int interp_mode, int border_mode) Size dst_size, Mat &dst)
{ {
src_size_ = dstSize;
projector_.setCameraParams(K, R); projector_.setCameraParams(K, R);
Point src_tl, src_br; Point src_tl, src_br;
detectResultRoi(src_tl, src_br); detectResultRoi(dst_size, src_tl, src_br);
CV_Assert(src_br.x - src_tl.x + 1 == src.cols && src_br.y - src_tl.y + 1 == src.rows); CV_Assert(src_br.x - src_tl.x + 1 == src.cols && src_br.y - src_tl.y + 1 == src.rows);
Mat xmap(dstSize, CV_32F); Mat xmap(dst_size, CV_32F);
Mat ymap(dstSize, CV_32F); Mat ymap(dst_size, CV_32F);
float u, v; float u, v;
for (int y = 0; y < dstSize.height; ++y) for (int y = 0; y < dst_size.height; ++y)
{ {
for (int x = 0; x < dstSize.width; ++x) for (int x = 0; x < dst_size.width; ++x)
{ {
projector_.mapForward(static_cast<float>(x), static_cast<float>(y), u, v); projector_.mapForward(static_cast<float>(x), static_cast<float>(y), u, v);
xmap.at<float>(y, x) = u - src_tl.x; xmap.at<float>(y, x) = u - src_tl.x;
...@@ -104,43 +113,25 @@ void WarperBase<P>::warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat ...@@ -104,43 +113,25 @@ void WarperBase<P>::warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat
} }
} }
dst.create(dstSize, src.type()); dst.create(dst_size, src.type());
remap(src, dst, xmap, ymap, interp_mode, border_mode); remap(src, dst, xmap, ymap, interp_mode, border_mode);
} }
template <class P> template <class P>
Point WarperBase<P>::warp(const Mat &/*src*/, const Mat &/*K*/, const Mat &/*R*/, const Mat &/*T*/, Mat &/*dst*/, Rect RotationWarperBase<P>::warpRoi(Size src_size, const Mat &K, const Mat &R)
int /*interp_mode*/, int /*border_mode*/)
{ {
CV_Error(CV_StsNotImplemented, "translation support isn't implemented");
return Point();
}
template <class P>
Rect WarperBase<P>::warpRoi(const Size &sz, const Mat &K, const Mat &R)
{
src_size_ = sz;
projector_.setCameraParams(K, R); projector_.setCameraParams(K, R);
Point dst_tl, dst_br; Point dst_tl, dst_br;
detectResultRoi(dst_tl, dst_br); detectResultRoi(src_size, dst_tl, dst_br);
return Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1)); return Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1));
} }
template <class P> template <class P>
Rect WarperBase<P>::warpRoi(const Size &/*sz*/, const Mat &/*K*/, const Mat &/*R*/, const Mat &/*T*/) void RotationWarperBase<P>::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)
{
CV_Error(CV_StsNotImplemented, "translation support isn't implemented");
return Rect();
}
template <class P>
void WarperBase<P>::detectResultRoi(Point &dst_tl, Point &dst_br)
{ {
float tl_uf = std::numeric_limits<float>::max(); float tl_uf = std::numeric_limits<float>::max();
float tl_vf = std::numeric_limits<float>::max(); float tl_vf = std::numeric_limits<float>::max();
...@@ -148,9 +139,9 @@ void WarperBase<P>::detectResultRoi(Point &dst_tl, Point &dst_br) ...@@ -148,9 +139,9 @@ void WarperBase<P>::detectResultRoi(Point &dst_tl, Point &dst_br)
float br_vf = -std::numeric_limits<float>::max(); float br_vf = -std::numeric_limits<float>::max();
float u, v; float u, v;
for (int y = 0; y < src_size_.height; ++y) for (int y = 0; y < src_size.height; ++y)
{ {
for (int x = 0; x < src_size_.width; ++x) for (int x = 0; x < src_size.width; ++x)
{ {
projector_.mapForward(static_cast<float>(x), static_cast<float>(y), u, v); projector_.mapForward(static_cast<float>(x), static_cast<float>(y), u, v);
tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
...@@ -166,7 +157,7 @@ void WarperBase<P>::detectResultRoi(Point &dst_tl, Point &dst_br) ...@@ -166,7 +157,7 @@ void WarperBase<P>::detectResultRoi(Point &dst_tl, Point &dst_br)
template <class P> template <class P>
void WarperBase<P>::detectResultRoiByBorder(Point &dst_tl, Point &dst_br) void RotationWarperBase<P>::detectResultRoiByBorder(Size src_size, Point &dst_tl, Point &dst_br)
{ {
float tl_uf = std::numeric_limits<float>::max(); float tl_uf = std::numeric_limits<float>::max();
float tl_vf = std::numeric_limits<float>::max(); float tl_vf = std::numeric_limits<float>::max();
...@@ -174,23 +165,23 @@ void WarperBase<P>::detectResultRoiByBorder(Point &dst_tl, Point &dst_br) ...@@ -174,23 +165,23 @@ void WarperBase<P>::detectResultRoiByBorder(Point &dst_tl, Point &dst_br)
float br_vf = -std::numeric_limits<float>::max(); float br_vf = -std::numeric_limits<float>::max();
float u, v; float u, v;
for (float x = 0; x < src_size_.width; ++x) for (float x = 0; x < src_size.width; ++x)
{ {
projector_.mapForward(static_cast<float>(x), 0, u, v); projector_.mapForward(static_cast<float>(x), 0, u, v);
tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
projector_.mapForward(static_cast<float>(x), static_cast<float>(src_size_.height - 1), u, v); projector_.mapForward(static_cast<float>(x), static_cast<float>(src_size.height - 1), u, v);
tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
} }
for (int y = 0; y < src_size_.height; ++y) for (int y = 0; y < src_size.height; ++y)
{ {
projector_.mapForward(0, static_cast<float>(y), u, v); projector_.mapForward(0, static_cast<float>(y), u, v);
tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
projector_.mapForward(static_cast<float>(src_size_.width - 1), static_cast<float>(y), u, v); projector_.mapForward(static_cast<float>(src_size.width - 1), static_cast<float>(y), u, v);
tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
} }
......
...@@ -51,28 +51,28 @@ class WarperCreator ...@@ -51,28 +51,28 @@ class WarperCreator
{ {
public: public:
virtual ~WarperCreator() {} virtual ~WarperCreator() {}
virtual Ptr<detail::Warper> create(float scale) const = 0; virtual Ptr<detail::RotationWarper> create(float scale) const = 0;
}; };
class PlaneWarper : public WarperCreator class PlaneWarper : public WarperCreator
{ {
public: public:
Ptr<detail::Warper> create(float scale) const { return new detail::PlaneWarper(scale); } Ptr<detail::RotationWarper> create(float scale) const { return new detail::PlaneWarper(scale); }
}; };
class CylindricalWarper: public WarperCreator class CylindricalWarper: public WarperCreator
{ {
public: public:
Ptr<detail::Warper> create(float scale) const { return new detail::CylindricalWarper(scale); } Ptr<detail::RotationWarper> create(float scale) const { return new detail::CylindricalWarper(scale); }
}; };
class SphericalWarper: public WarperCreator class SphericalWarper: public WarperCreator
{ {
public: public:
Ptr<detail::Warper> create(float scale) const { return new detail::SphericalWarper(scale); } Ptr<detail::RotationWarper> create(float scale) const { return new detail::SphericalWarper(scale); }
}; };
...@@ -80,21 +80,21 @@ public: ...@@ -80,21 +80,21 @@ public:
class PlaneWarperGpu: public WarperCreator class PlaneWarperGpu: public WarperCreator
{ {
public: public:
Ptr<detail::Warper> create(float scale) const { return new detail::PlaneWarperGpu(scale); } Ptr<detail::RotationWarper> create(float scale) const { return new detail::PlaneWarperGpu(scale); }
}; };
class CylindricalWarperGpu: public WarperCreator class CylindricalWarperGpu: public WarperCreator
{ {
public: public:
Ptr<detail::Warper> create(float scale) const { return new detail::CylindricalWarperGpu(scale); } Ptr<detail::RotationWarper> create(float scale) const { return new detail::CylindricalWarperGpu(scale); }
}; };
class SphericalWarperGpu: public WarperCreator class SphericalWarperGpu: public WarperCreator
{ {
public: public:
Ptr<detail::Warper> create(float scale) const { return new detail::SphericalWarperGpu(scale); } Ptr<detail::RotationWarper> create(float scale) const { return new detail::SphericalWarperGpu(scale); }
}; };
#endif #endif
......
...@@ -261,7 +261,7 @@ Stitcher::Status Stitcher::composePanorama(Mat &pano) ...@@ -261,7 +261,7 @@ Stitcher::Status Stitcher::composePanorama(Mat &pano)
} }
// Warp images and their masks // Warp images and their masks
Ptr<detail::Warper> warper = warper_->create(float(warped_image_scale_ * seam_work_aspect_)); Ptr<detail::RotationWarper> warper = warper_->create(float(warped_image_scale_ * seam_work_aspect_));
for (size_t i = 0; i < imgs_.size(); ++i) for (size_t i = 0; i < imgs_.size(); ++i)
{ {
Mat_<float> K; Mat_<float> K;
...@@ -271,10 +271,10 @@ Stitcher::Status Stitcher::composePanorama(Mat &pano) ...@@ -271,10 +271,10 @@ Stitcher::Status Stitcher::composePanorama(Mat &pano)
K(1,1) *= (float)seam_work_aspect_; K(1,1) *= (float)seam_work_aspect_;
K(1,2) *= (float)seam_work_aspect_; K(1,2) *= (float)seam_work_aspect_;
corners[i] = warper->warp(seam_est_imgs_[i], K, cameras_[i].R, images_warped[i], INTER_LINEAR, BORDER_REFLECT); corners[i] = warper->warp(seam_est_imgs_[i], K, cameras_[i].R, INTER_LINEAR, BORDER_REFLECT, images_warped[i]);
sizes[i] = images_warped[i].size(); sizes[i] = images_warped[i].size();
warper->warp(masks[i], K, cameras_[i].R, masks_warped[i], INTER_NEAREST, BORDER_CONSTANT); warper->warp(masks[i], K, cameras_[i].R, INTER_NEAREST, BORDER_CONSTANT, masks_warped[i]);
} }
vector<Mat> images_warped_f(imgs_.size()); vector<Mat> images_warped_f(imgs_.size());
...@@ -361,12 +361,12 @@ Stitcher::Status Stitcher::composePanorama(Mat &pano) ...@@ -361,12 +361,12 @@ Stitcher::Status Stitcher::composePanorama(Mat &pano)
cameras_[img_idx].K().convertTo(K, CV_32F); cameras_[img_idx].K().convertTo(K, CV_32F);
// Warp the current image // Warp the current image
warper->warp(img, K, cameras_[img_idx].R, img_warped, INTER_LINEAR, BORDER_REFLECT); warper->warp(img, K, cameras_[img_idx].R, INTER_LINEAR, BORDER_REFLECT, img_warped);
// Warp the current image mask // Warp the current image mask
mask.create(img_size, CV_8U); mask.create(img_size, CV_8U);
mask.setTo(Scalar::all(255)); mask.setTo(Scalar::all(255));
warper->warp(mask, K, cameras_[img_idx].R, mask_warped, INTER_NEAREST, BORDER_CONSTANT); warper->warp(mask, K, cameras_[img_idx].R, INTER_NEAREST, BORDER_CONSTANT, mask_warped);
// Compensate exposure // Compensate exposure
exposure_comp_->apply(img_idx, corners[img_idx], img_warped, mask_warped); exposure_comp_->apply(img_idx, corners[img_idx], img_warped, mask_warped);
......
...@@ -78,17 +78,15 @@ void ProjectorBase::setCameraParams(const Mat &K, const Mat &R, const Mat &T) ...@@ -78,17 +78,15 @@ void ProjectorBase::setCameraParams(const Mat &K, const Mat &R, const Mat &T)
} }
Point PlaneWarper::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst, Rect PlaneWarper::buildMaps(Size src_size, const Mat &K, const Mat &R, const Mat &T, Mat &xmap, Mat &ymap)
int interp_mode, int border_mode)
{ {
src_size_ = src.size();
projector_.setCameraParams(K, R, T); projector_.setCameraParams(K, R, T);
Point dst_tl, dst_br; Point dst_tl, dst_br;
detectResultRoi(dst_tl, dst_br); detectResultRoi(src_size, dst_tl, dst_br);
Mat xmap(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F); xmap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);
Mat ymap(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F); ymap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);
float x, y; float x, y;
for (int v = dst_tl.y; v <= dst_br.y; ++v) for (int v = dst_tl.y; v <= dst_br.y; ++v)
...@@ -101,26 +99,35 @@ Point PlaneWarper::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T ...@@ -101,26 +99,35 @@ Point PlaneWarper::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T
} }
} }
dst.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, src.type()); return Rect(dst_tl, dst_br);
}
Point PlaneWarper::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, int interp_mode, int border_mode,
Mat &dst)
{
Mat xmap, ymap;
Rect dst_roi = buildMaps(src.size(), K, R, T, xmap, ymap);
dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());
remap(src, dst, xmap, ymap, interp_mode, border_mode); remap(src, dst, xmap, ymap, interp_mode, border_mode);
return dst_tl; return dst_roi.tl();
} }
Rect PlaneWarper::warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T) Rect PlaneWarper::warpRoi(Size src_size, const Mat &K, const Mat &R, const Mat &T)
{ {
src_size_ = sz;
projector_.setCameraParams(K, R, T); projector_.setCameraParams(K, R, T);
Point dst_tl, dst_br; Point dst_tl, dst_br;
detectResultRoi(dst_tl, dst_br); detectResultRoi(src_size, dst_tl, dst_br);
return Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1)); return Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1));
} }
void PlaneWarper::detectResultRoi(Point &dst_tl, Point &dst_br) void PlaneWarper::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)
{ {
float tl_uf = numeric_limits<float>::max(); float tl_uf = numeric_limits<float>::max();
float tl_vf = numeric_limits<float>::max(); float tl_vf = numeric_limits<float>::max();
...@@ -133,15 +140,15 @@ void PlaneWarper::detectResultRoi(Point &dst_tl, Point &dst_br) ...@@ -133,15 +140,15 @@ void PlaneWarper::detectResultRoi(Point &dst_tl, Point &dst_br)
tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v); tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v);
br_uf = max(br_uf, u); br_vf = max(br_vf, v); br_uf = max(br_uf, u); br_vf = max(br_vf, v);
projector_.mapForward(0, static_cast<float>(src_size_.height - 1), u, v); projector_.mapForward(0, static_cast<float>(src_size.height - 1), u, v);
tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v); tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v);
br_uf = max(br_uf, u); br_vf = max(br_vf, v); br_uf = max(br_uf, u); br_vf = max(br_vf, v);
projector_.mapForward(static_cast<float>(src_size_.width - 1), 0, u, v); projector_.mapForward(static_cast<float>(src_size.width - 1), 0, u, v);
tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v); tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v);
br_uf = max(br_uf, u); br_vf = max(br_vf, v); br_uf = max(br_uf, u); br_vf = max(br_vf, v);
projector_.mapForward(static_cast<float>(src_size_.width - 1), static_cast<float>(src_size_.height - 1), u, v); projector_.mapForward(static_cast<float>(src_size.width - 1), static_cast<float>(src_size.height - 1), u, v);
tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v); tl_uf = min(tl_uf, u); tl_vf = min(tl_vf, v);
br_uf = max(br_uf, u); br_vf = max(br_vf, v); br_uf = max(br_uf, u); br_vf = max(br_vf, v);
...@@ -153,21 +160,20 @@ void PlaneWarper::detectResultRoi(Point &dst_tl, Point &dst_br) ...@@ -153,21 +160,20 @@ void PlaneWarper::detectResultRoi(Point &dst_tl, Point &dst_br)
#ifndef ANDROID #ifndef ANDROID
Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
int interp_mode, int border_mode) Mat &dst)
{ {
return warp(src, K, R, Mat::zeros(3, 1, CV_32F), dst, interp_mode, border_mode); return warp(src, K, R, Mat::zeros(3, 1, CV_32F), interp_mode, border_mode, dst);
} }
Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst, Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, int interp_mode, int border_mode,
int interp_mode, int border_mode) Mat &dst)
{ {
src_size_ = src.size();
projector_.setCameraParams(K, R, T); projector_.setCameraParams(K, R, T);
Point dst_tl, dst_br; Point dst_tl, dst_br;
detectResultRoi(dst_tl, dst_br); detectResultRoi(src.size(), dst_tl, dst_br);
gpu::buildWarpPlaneMaps(src.size(), Rect(dst_tl, Point(dst_br.x+1, dst_br.y+1)), gpu::buildWarpPlaneMaps(src.size(), Rect(dst_tl, Point(dst_br.x+1, dst_br.y+1)),
K, R, projector_.scale, d_xmap_, d_ymap_); K, R, projector_.scale, d_xmap_, d_ymap_);
...@@ -186,9 +192,9 @@ Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, const Mat ...@@ -186,9 +192,9 @@ Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, const Mat
#endif #endif
void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br) void SphericalWarper::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)
{ {
detectResultRoiByBorder(dst_tl, dst_br); detectResultRoiByBorder(src_size, dst_tl, dst_br);
float tl_uf = static_cast<float>(dst_tl.x); float tl_uf = static_cast<float>(dst_tl.x);
float tl_vf = static_cast<float>(dst_tl.y); float tl_vf = static_cast<float>(dst_tl.y);
...@@ -202,7 +208,7 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br) ...@@ -202,7 +208,7 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br)
{ {
float x_ = (projector_.k[0] * x + projector_.k[1] * y) / z + projector_.k[2]; float x_ = (projector_.k[0] * x + projector_.k[1] * y) / z + projector_.k[2];
float y_ = projector_.k[4] * y / z + projector_.k[5]; float y_ = projector_.k[4] * y / z + projector_.k[5];
if (x_ > 0.f && x_ < src_size_.width && y_ > 0.f && y_ < src_size_.height) if (x_ > 0.f && x_ < src_size.width && y_ > 0.f && y_ < src_size.height)
{ {
tl_uf = min(tl_uf, 0.f); tl_vf = min(tl_vf, static_cast<float>(CV_PI * projector_.scale)); tl_uf = min(tl_uf, 0.f); tl_vf = min(tl_vf, static_cast<float>(CV_PI * projector_.scale));
br_uf = max(br_uf, 0.f); br_vf = max(br_vf, static_cast<float>(CV_PI * projector_.scale)); br_uf = max(br_uf, 0.f); br_vf = max(br_vf, static_cast<float>(CV_PI * projector_.scale));
...@@ -216,7 +222,7 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br) ...@@ -216,7 +222,7 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br)
{ {
float x_ = (projector_.k[0] * x + projector_.k[1] * y) / z + projector_.k[2]; float x_ = (projector_.k[0] * x + projector_.k[1] * y) / z + projector_.k[2];
float y_ = projector_.k[4] * y / z + projector_.k[5]; float y_ = projector_.k[4] * y / z + projector_.k[5];
if (x_ > 0.f && x_ < src_size_.width && y_ > 0.f && y_ < src_size_.height) if (x_ > 0.f && x_ < src_size.width && y_ > 0.f && y_ < src_size.height)
{ {
tl_uf = min(tl_uf, 0.f); tl_vf = min(tl_vf, static_cast<float>(0)); tl_uf = min(tl_uf, 0.f); tl_vf = min(tl_vf, static_cast<float>(0));
br_uf = max(br_uf, 0.f); br_vf = max(br_vf, static_cast<float>(0)); br_uf = max(br_uf, 0.f); br_vf = max(br_vf, static_cast<float>(0));
...@@ -231,14 +237,13 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br) ...@@ -231,14 +237,13 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br)
#ifndef ANDROID #ifndef ANDROID
Point SphericalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Point SphericalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
int interp_mode, int border_mode) Mat &dst)
{ {
src_size_ = src.size();
projector_.setCameraParams(K, R); projector_.setCameraParams(K, R);
Point dst_tl, dst_br; Point dst_tl, dst_br;
detectResultRoi(dst_tl, dst_br); detectResultRoi(src.size(), dst_tl, dst_br);
gpu::buildWarpSphericalMaps(src.size(), Rect(dst_tl, Point(dst_br.x+1, dst_br.y+1)), gpu::buildWarpSphericalMaps(src.size(), Rect(dst_tl, Point(dst_br.x+1, dst_br.y+1)),
K, R, projector_.scale, d_xmap_, d_ymap_); K, R, projector_.scale, d_xmap_, d_ymap_);
...@@ -256,14 +261,13 @@ Point SphericalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat & ...@@ -256,14 +261,13 @@ Point SphericalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &
} }
Point CylindricalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Point CylindricalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
int interp_mode, int border_mode) Mat &dst)
{ {
src_size_ = src.size();
projector_.setCameraParams(K, R); projector_.setCameraParams(K, R);
Point dst_tl, dst_br; Point dst_tl, dst_br;
detectResultRoi(dst_tl, dst_br); detectResultRoi(src.size(), dst_tl, dst_br);
gpu::buildWarpCylindricalMaps(src.size(), Rect(dst_tl, Point(dst_br.x+1, dst_br.y+1)), gpu::buildWarpCylindricalMaps(src.size(), Rect(dst_tl, Point(dst_br.x+1, dst_br.y+1)),
K, R, projector_.scale, d_xmap_, d_ymap_); K, R, projector_.scale, d_xmap_, d_ymap_);
......
...@@ -523,7 +523,7 @@ int main(int argc, char* argv[]) ...@@ -523,7 +523,7 @@ int main(int argc, char* argv[])
return 1; return 1;
} }
Ptr<Warper> warper = warper_creator->create(static_cast<float>(warped_image_scale * seam_work_aspect)); Ptr<RotationWarper> warper = warper_creator->create(static_cast<float>(warped_image_scale * seam_work_aspect));
for (int i = 0; i < num_images; ++i) for (int i = 0; i < num_images; ++i)
{ {
...@@ -532,10 +532,10 @@ int main(int argc, char* argv[]) ...@@ -532,10 +532,10 @@ int main(int argc, char* argv[])
K(0,0) *= seam_work_aspect; K(0,2) *= seam_work_aspect; K(0,0) *= seam_work_aspect; K(0,2) *= seam_work_aspect;
K(1,1) *= seam_work_aspect; K(1,2) *= seam_work_aspect; K(1,1) *= seam_work_aspect; K(1,2) *= seam_work_aspect;
corners[i] = warper->warp(images[i], K, cameras[i].R, images_warped[i], INTER_LINEAR, BORDER_REFLECT); corners[i] = warper->warp(images[i], K, cameras[i].R, INTER_LINEAR, BORDER_REFLECT, images_warped[i]);
sizes[i] = images_warped[i].size(); sizes[i] = images_warped[i].size();
warper->warp(masks[i], K, cameras[i].R, masks_warped[i], INTER_NEAREST, BORDER_CONSTANT); warper->warp(masks[i], K, cameras[i].R, INTER_NEAREST, BORDER_CONSTANT, masks_warped[i]);
} }
vector<Mat> images_warped_f(num_images); vector<Mat> images_warped_f(num_images);
...@@ -647,12 +647,12 @@ int main(int argc, char* argv[]) ...@@ -647,12 +647,12 @@ int main(int argc, char* argv[])
cameras[img_idx].K().convertTo(K, CV_32F); cameras[img_idx].K().convertTo(K, CV_32F);
// Warp the current image // Warp the current image
warper->warp(img, K, cameras[img_idx].R, img_warped, INTER_LINEAR, BORDER_REFLECT); warper->warp(img, K, cameras[img_idx].R, INTER_LINEAR, BORDER_REFLECT, img_warped);
// Warp the current image mask // Warp the current image mask
mask.create(img_size, CV_8U); mask.create(img_size, CV_8U);
mask.setTo(Scalar::all(255)); mask.setTo(Scalar::all(255));
warper->warp(mask, K, cameras[img_idx].R, mask_warped, INTER_NEAREST, BORDER_CONSTANT); warper->warp(mask, K, cameras[img_idx].R, INTER_NEAREST, BORDER_CONSTANT, mask_warped);
// Compensate exposure // Compensate exposure
compensator->apply(img_idx, corners[img_idx], img_warped, mask_warped); compensator->apply(img_idx, corners[img_idx], img_warped, mask_warped);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment