Refactored warpers in the stitching module, added buildMaps function into the RotationWarper interface
This commit is contained in:
parent
b7a3d36729
commit
404e9cb9d5
@ -52,18 +52,20 @@
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
|
||||
class CV_EXPORTS Warper
|
||||
class CV_EXPORTS RotationWarper
|
||||
{
|
||||
public:
|
||||
virtual ~Warper() {}
|
||||
virtual Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
|
||||
int interp_mode, int border_mode) = 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, const Mat &T, Mat &dst,
|
||||
int interp_mode, int border_mode) = 0;
|
||||
virtual Rect warpRoi(const Size &sz, const Mat &K, const Mat &R) = 0;
|
||||
virtual Rect warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T) = 0;
|
||||
virtual ~RotationWarper() {}
|
||||
|
||||
virtual Rect buildMaps(Size src_size, const Mat &K, const Mat &R, Mat &xmap, Mat &ymap) = 0;
|
||||
|
||||
virtual Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
|
||||
Mat &dst) = 0;
|
||||
|
||||
virtual void warpBackward(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
|
||||
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
|
||||
|
||||
|
||||
template <class P>
|
||||
class CV_EXPORTS WarperBase : public Warper
|
||||
class CV_EXPORTS RotationWarperBase : public RotationWarper
|
||||
{
|
||||
public:
|
||||
Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
|
||||
int interp_mode, int border_mode);
|
||||
void warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Size dstSize,
|
||||
int interp_mode, int border_mode);
|
||||
Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst,
|
||||
int interp_mode, int border_mode);
|
||||
Rect warpRoi(const Size &sz, const Mat &K, const Mat &R);
|
||||
Rect warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T);
|
||||
Rect buildMaps(Size src_size, const Mat &K, const Mat &R, Mat &xmap, Mat &ymap);
|
||||
|
||||
Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
|
||||
Mat &dst);
|
||||
|
||||
void warpBackward(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
|
||||
Size dst_size, Mat &dst);
|
||||
|
||||
Rect warpRoi(Size src_size, const Mat &K, const Mat &R);
|
||||
|
||||
protected:
|
||||
|
||||
// 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.
|
||||
// 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_;
|
||||
};
|
||||
|
||||
@ -116,17 +119,22 @@ struct CV_EXPORTS PlaneProjector : ProjectorBase
|
||||
|
||||
|
||||
// Projects image onto z = plane_dist plane
|
||||
class CV_EXPORTS PlaneWarper : public WarperBase<PlaneProjector>
|
||||
class CV_EXPORTS PlaneWarper : public RotationWarperBase<PlaneProjector>
|
||||
{
|
||||
public:
|
||||
PlaneWarper(float scale = 1.f) { 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 warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T);
|
||||
|
||||
Rect buildMaps(Size src_size, const Mat &K, const Mat &R, const Mat &T, Mat &xmap, Mat &ymap);
|
||||
|
||||
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:
|
||||
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
|
||||
{
|
||||
public:
|
||||
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, const Mat &T, 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);
|
||||
|
||||
Point warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, int interp_mode, int border_mode,
|
||||
Mat &dst);
|
||||
|
||||
private:
|
||||
gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_;
|
||||
@ -155,13 +165,13 @@ struct CV_EXPORTS SphericalProjector : ProjectorBase
|
||||
|
||||
// Projects image onto unit sphere with origin at (0, 0, 0).
|
||||
// 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:
|
||||
SphericalWarper(float scale) { projector_.scale = scale; }
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
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:
|
||||
gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_;
|
||||
@ -187,14 +198,16 @@ struct CV_EXPORTS CylindricalProjector : ProjectorBase
|
||||
|
||||
|
||||
// Projects image onto x * x + z * z = 1 cylinder
|
||||
class CV_EXPORTS CylindricalWarper : public WarperBase<CylindricalProjector>
|
||||
class CV_EXPORTS CylindricalWarper : public RotationWarperBase<CylindricalProjector>
|
||||
{
|
||||
public:
|
||||
CylindricalWarper(float scale) { projector_.scale = scale; }
|
||||
|
||||
protected:
|
||||
void detectResultRoi(Point &dst_tl, Point &dst_br)
|
||||
{ WarperBase<CylindricalProjector>::detectResultRoiByBorder(dst_tl, dst_br); }
|
||||
void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)
|
||||
{
|
||||
RotationWarperBase<CylindricalProjector>::detectResultRoiByBorder(src_size, dst_tl, dst_br);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -203,8 +216,9 @@ class CV_EXPORTS CylindricalWarperGpu : public CylindricalWarper
|
||||
{
|
||||
public:
|
||||
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:
|
||||
gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_;
|
||||
|
@ -50,17 +50,15 @@ namespace cv {
|
||||
namespace detail {
|
||||
|
||||
template <class P>
|
||||
Point WarperBase<P>::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
|
||||
int interp_mode, int border_mode)
|
||||
Rect RotationWarperBase<P>::buildMaps(Size src_size, const Mat &K, const Mat &R, Mat &xmap, Mat &ymap)
|
||||
{
|
||||
src_size_ = src.size();
|
||||
projector_.setCameraParams(K, R);
|
||||
|
||||
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);
|
||||
Mat ymap(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);
|
||||
ymap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);
|
||||
|
||||
float x, y;
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
dst.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, src.type());
|
||||
remap(src, dst, xmap, ymap, interp_mode, border_mode);
|
||||
|
||||
return dst_tl;
|
||||
return Rect(dst_tl, dst_br);
|
||||
}
|
||||
|
||||
|
||||
template <class P>
|
||||
void WarperBase<P>::warpBackward(const Mat &src, const Mat &K, const Mat &R, Mat &dst, Size dstSize,
|
||||
int interp_mode, int border_mode)
|
||||
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);
|
||||
|
||||
return dst_roi.tl();
|
||||
}
|
||||
|
||||
|
||||
template <class P>
|
||||
void RotationWarperBase<P>::warpBackward(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
|
||||
Size dst_size, Mat &dst)
|
||||
{
|
||||
src_size_ = dstSize;
|
||||
projector_.setCameraParams(K, R);
|
||||
|
||||
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);
|
||||
|
||||
Mat xmap(dstSize, CV_32F);
|
||||
Mat ymap(dstSize, CV_32F);
|
||||
Mat xmap(dst_size, CV_32F);
|
||||
Mat ymap(dst_size, CV_32F);
|
||||
|
||||
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);
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
dst.create(dstSize, src.type());
|
||||
dst.create(dst_size, src.type());
|
||||
remap(src, dst, xmap, ymap, interp_mode, border_mode);
|
||||
}
|
||||
|
||||
|
||||
template <class P>
|
||||
Point WarperBase<P>::warp(const Mat &/*src*/, const Mat &/*K*/, const Mat &/*R*/, const Mat &/*T*/, Mat &/*dst*/,
|
||||
int /*interp_mode*/, int /*border_mode*/)
|
||||
Rect RotationWarperBase<P>::warpRoi(Size src_size, const Mat &K, const Mat &R)
|
||||
{
|
||||
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);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
template <class P>
|
||||
Rect WarperBase<P>::warpRoi(const Size &/*sz*/, const Mat &/*K*/, const Mat &/*R*/, const Mat &/*T*/)
|
||||
{
|
||||
CV_Error(CV_StsNotImplemented, "translation support isn't implemented");
|
||||
return Rect();
|
||||
}
|
||||
|
||||
|
||||
template <class P>
|
||||
void WarperBase<P>::detectResultRoi(Point &dst_tl, Point &dst_br)
|
||||
void RotationWarperBase<P>::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)
|
||||
{
|
||||
float tl_uf = 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)
|
||||
float br_vf = -std::numeric_limits<float>::max();
|
||||
|
||||
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);
|
||||
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)
|
||||
|
||||
|
||||
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_vf = std::numeric_limits<float>::max();
|
||||
@ -174,23 +165,23 @@ void WarperBase<P>::detectResultRoiByBorder(Point &dst_tl, Point &dst_br)
|
||||
float br_vf = -std::numeric_limits<float>::max();
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
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);
|
||||
br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
|
||||
}
|
||||
|
@ -51,28 +51,28 @@ class WarperCreator
|
||||
{
|
||||
public:
|
||||
virtual ~WarperCreator() {}
|
||||
virtual Ptr<detail::Warper> create(float scale) const = 0;
|
||||
virtual Ptr<detail::RotationWarper> create(float scale) const = 0;
|
||||
};
|
||||
|
||||
|
||||
class PlaneWarper : public WarperCreator
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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:
|
||||
class PlaneWarperGpu: public WarperCreator
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
|
||||
|
@ -261,7 +261,7 @@ Stitcher::Status Stitcher::composePanorama(Mat &pano)
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
Mat_<float> K;
|
||||
@ -271,10 +271,10 @@ Stitcher::Status Stitcher::composePanorama(Mat &pano)
|
||||
K(1,1) *= (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();
|
||||
|
||||
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());
|
||||
@ -361,12 +361,12 @@ Stitcher::Status Stitcher::composePanorama(Mat &pano)
|
||||
cameras_[img_idx].K().convertTo(K, CV_32F);
|
||||
|
||||
// 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
|
||||
mask.create(img_size, CV_8U);
|
||||
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
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
Point PlaneWarper::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst,
|
||||
int interp_mode, int border_mode)
|
||||
Rect PlaneWarper::buildMaps(Size src_size, const Mat &K, const Mat &R, const Mat &T, Mat &xmap, Mat &ymap)
|
||||
{
|
||||
src_size_ = src.size();
|
||||
projector_.setCameraParams(K, R, T);
|
||||
|
||||
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);
|
||||
Mat ymap(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);
|
||||
ymap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);
|
||||
|
||||
float x, y;
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
dst.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, src.type());
|
||||
remap(src, dst, xmap, ymap, interp_mode, border_mode);
|
||||
|
||||
return dst_tl;
|
||||
return Rect(dst_tl, dst_br);
|
||||
}
|
||||
|
||||
|
||||
Rect PlaneWarper::warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T)
|
||||
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);
|
||||
|
||||
return dst_roi.tl();
|
||||
}
|
||||
|
||||
|
||||
Rect PlaneWarper::warpRoi(Size src_size, const Mat &K, const Mat &R, const Mat &T)
|
||||
{
|
||||
src_size_ = sz;
|
||||
projector_.setCameraParams(K, R, T);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
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_vf = numeric_limits<float>::max();
|
||||
@ -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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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)
|
||||
|
||||
|
||||
#ifndef ANDROID
|
||||
Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
|
||||
int interp_mode, int border_mode)
|
||||
Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, 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,
|
||||
int interp_mode, int border_mode)
|
||||
Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, int interp_mode, int border_mode,
|
||||
Mat &dst)
|
||||
{
|
||||
src_size_ = src.size();
|
||||
projector_.setCameraParams(K, R, T);
|
||||
|
||||
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)),
|
||||
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
|
||||
#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_vf = static_cast<float>(dst_tl.y);
|
||||
@ -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 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));
|
||||
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)
|
||||
{
|
||||
float x_ = (projector_.k[0] * x + projector_.k[1] * y) / z + projector_.k[2];
|
||||
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));
|
||||
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)
|
||||
|
||||
|
||||
#ifndef ANDROID
|
||||
Point SphericalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
|
||||
int interp_mode, int border_mode)
|
||||
Point SphericalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
|
||||
Mat &dst)
|
||||
{
|
||||
src_size_ = src.size();
|
||||
projector_.setCameraParams(K, R);
|
||||
|
||||
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)),
|
||||
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 &
|
||||
}
|
||||
|
||||
|
||||
Point CylindricalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
|
||||
int interp_mode, int border_mode)
|
||||
Point CylindricalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
|
||||
Mat &dst)
|
||||
{
|
||||
src_size_ = src.size();
|
||||
projector_.setCameraParams(K, R);
|
||||
|
||||
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)),
|
||||
K, R, projector_.scale, d_xmap_, d_ymap_);
|
||||
|
@ -523,7 +523,7 @@ int main(int argc, char* argv[])
|
||||
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)
|
||||
{
|
||||
@ -532,10 +532,10 @@ int main(int argc, char* argv[])
|
||||
K(0,0) *= seam_work_aspect; K(0,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();
|
||||
|
||||
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);
|
||||
@ -647,12 +647,12 @@ int main(int argc, char* argv[])
|
||||
cameras[img_idx].K().convertTo(K, CV_32F);
|
||||
|
||||
// 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
|
||||
mask.create(img_size, CV_8U);
|
||||
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
|
||||
compensator->apply(img_idx, corners[img_idx], img_warped, mask_warped);
|
||||
|
Loading…
x
Reference in New Issue
Block a user