Updated bundle adjustment in stitching module: 1) it minimizes reprojection error now, 2) it minimizes error over focal, aspect, p.p.x, p.p.y parameters. Refactored and updated warpers.
This commit is contained in:
@@ -53,8 +53,12 @@ struct CV_EXPORTS CameraParams
|
||||
CameraParams();
|
||||
CameraParams(const CameraParams& other);
|
||||
const CameraParams& operator =(const CameraParams& other);
|
||||
Mat K() const;
|
||||
|
||||
double focal; // Focal length
|
||||
double aspect; // Aspect ratio
|
||||
double ppx; // Principal point X
|
||||
double ppy; // Principal point Y
|
||||
Mat R; // Rotation
|
||||
Mat t; // Translation
|
||||
};
|
||||
|
@@ -58,9 +58,7 @@ public:
|
||||
|
||||
void operator ()(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches,
|
||||
std::vector<CameraParams> &cameras)
|
||||
{
|
||||
estimate(features, pairwise_matches, cameras);
|
||||
}
|
||||
{ estimate(features, pairwise_matches, cameras); }
|
||||
|
||||
protected:
|
||||
virtual void estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches,
|
||||
@@ -90,6 +88,8 @@ public:
|
||||
BundleAdjuster(int cost_space = FOCAL_RAY_SPACE, float conf_thresh = 1.f)
|
||||
: cost_space_(cost_space), conf_thresh_(conf_thresh) {}
|
||||
|
||||
Mat K;
|
||||
|
||||
private:
|
||||
void estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches,
|
||||
std::vector<CameraParams> &cameras);
|
||||
|
@@ -55,27 +55,22 @@ namespace detail {
|
||||
class CV_EXPORTS Warper
|
||||
{
|
||||
public:
|
||||
enum { PLANE, CYLINDRICAL, SPHERICAL };
|
||||
|
||||
// TODO remove this method
|
||||
static Ptr<Warper> createByCameraFocal(float focal, int type, bool try_gpu = false);
|
||||
|
||||
virtual ~Warper() {}
|
||||
virtual Point warp(const Mat &src, float focal, const Mat& R, Mat &dst,
|
||||
virtual Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
|
||||
int interp_mode = INTER_LINEAR, int border_mode = BORDER_REFLECT) = 0;
|
||||
virtual Rect warpRoi(const Size &sz, float focal, const Mat &R) = 0;
|
||||
virtual Rect warpRoi(const Size &sz, const Mat &K, const Mat &R) = 0;
|
||||
};
|
||||
|
||||
|
||||
struct CV_EXPORTS ProjectorBase
|
||||
{
|
||||
void setTransformation(const Mat& R);
|
||||
void setCameraParams(const Mat &K, const Mat &R);
|
||||
|
||||
Size size;
|
||||
float focal;
|
||||
float r[9];
|
||||
float rinv[9];
|
||||
float scale;
|
||||
float k[9];
|
||||
float rinv[9];
|
||||
float r_kinv[9];
|
||||
float k_rinv[9];
|
||||
};
|
||||
|
||||
|
||||
@@ -83,10 +78,10 @@ template <class P>
|
||||
class CV_EXPORTS WarperBase : public Warper
|
||||
{
|
||||
public:
|
||||
virtual Point warp(const Mat &src, float focal, const Mat &R, Mat &dst,
|
||||
virtual Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
|
||||
int interp_mode, int border_mode);
|
||||
|
||||
virtual Rect warpRoi(const Size &sz, float focal, const Mat &R);
|
||||
virtual Rect warpRoi(const Size &sz, const Mat &K, const Mat &R);
|
||||
|
||||
protected:
|
||||
// Detects ROI of the destination image. It's correct for any projection.
|
||||
@@ -105,7 +100,6 @@ struct CV_EXPORTS PlaneProjector : ProjectorBase
|
||||
{
|
||||
void mapForward(float x, float y, float &u, float &v);
|
||||
void mapBackward(float u, float v, float &x, float &y);
|
||||
float plane_dist;
|
||||
};
|
||||
|
||||
|
||||
@@ -113,11 +107,7 @@ struct CV_EXPORTS PlaneProjector : ProjectorBase
|
||||
class CV_EXPORTS PlaneWarper : public WarperBase<PlaneProjector>
|
||||
{
|
||||
public:
|
||||
PlaneWarper(float plane_dist = 1.f, float scale = 1.f)
|
||||
{
|
||||
projector_.plane_dist = plane_dist;
|
||||
projector_.scale = scale;
|
||||
}
|
||||
PlaneWarper(float scale = 1.f) { projector_.scale = scale; }
|
||||
|
||||
protected:
|
||||
void detectResultRoi(Point &dst_tl, Point &dst_br);
|
||||
@@ -127,8 +117,8 @@ protected:
|
||||
class CV_EXPORTS PlaneWarperGpu : public PlaneWarper
|
||||
{
|
||||
public:
|
||||
PlaneWarperGpu(float plane_dist = 1.f, float scale = 1.f) : PlaneWarper(plane_dist, scale) {}
|
||||
Point warp(const Mat &src, float focal, const Mat &R, Mat &dst,
|
||||
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);
|
||||
|
||||
private:
|
||||
@@ -149,7 +139,7 @@ struct CV_EXPORTS SphericalProjector : ProjectorBase
|
||||
class CV_EXPORTS SphericalWarper : public WarperBase<SphericalProjector>
|
||||
{
|
||||
public:
|
||||
SphericalWarper(float scale = 300.f) { projector_.scale = scale; }
|
||||
SphericalWarper(float scale) { projector_.scale = scale; }
|
||||
|
||||
protected:
|
||||
void detectResultRoi(Point &dst_tl, Point &dst_br);
|
||||
@@ -160,9 +150,9 @@ protected:
|
||||
class CV_EXPORTS SphericalWarperGpu : public SphericalWarper
|
||||
{
|
||||
public:
|
||||
SphericalWarperGpu(float scale = 300.f) : SphericalWarper(scale) {}
|
||||
Point warp(const Mat &src, float focal, const Mat &R, Mat &dst,
|
||||
int interp_mode, int border_mode);
|
||||
SphericalWarperGpu(float scale) : SphericalWarper(scale) {}
|
||||
Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
|
||||
int interp_mode, int border_mode);
|
||||
|
||||
private:
|
||||
gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_;
|
||||
@@ -181,13 +171,11 @@ struct CV_EXPORTS CylindricalProjector : ProjectorBase
|
||||
class CV_EXPORTS CylindricalWarper : public WarperBase<CylindricalProjector>
|
||||
{
|
||||
public:
|
||||
CylindricalWarper(float scale = 300.f) { projector_.scale = scale; }
|
||||
CylindricalWarper(float scale) { projector_.scale = scale; }
|
||||
|
||||
protected:
|
||||
void detectResultRoi(Point &dst_tl, Point &dst_br)
|
||||
{
|
||||
WarperBase<CylindricalProjector>::detectResultRoiByBorder(dst_tl, dst_br);
|
||||
}
|
||||
{ WarperBase<CylindricalProjector>::detectResultRoiByBorder(dst_tl, dst_br); }
|
||||
};
|
||||
|
||||
|
||||
@@ -195,9 +183,9 @@ protected:
|
||||
class CV_EXPORTS CylindricalWarperGpu : public CylindricalWarper
|
||||
{
|
||||
public:
|
||||
CylindricalWarperGpu(float scale = 300.f) : CylindricalWarper(scale) {}
|
||||
Point warp(const Mat &src, float focal, const Mat &R, Mat &dst,
|
||||
int interp_mode, int border_mode);
|
||||
CylindricalWarperGpu(float scale) : CylindricalWarper(scale) {}
|
||||
Point warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
|
||||
int interp_mode, int border_mode);
|
||||
|
||||
private:
|
||||
gpu::GpuMat d_xmap_, d_ymap_, d_dst_, d_src_;
|
||||
|
@@ -50,14 +50,11 @@ namespace cv {
|
||||
namespace detail {
|
||||
|
||||
template <class P>
|
||||
Point WarperBase<P>::warp(const Mat &src, float focal, const Mat &R, Mat &dst,
|
||||
Point WarperBase<P>::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
|
||||
int interp_mode, int border_mode)
|
||||
{
|
||||
src_size_ = src.size();
|
||||
|
||||
projector_.size = src.size();
|
||||
projector_.focal = focal;
|
||||
projector_.setTransformation(R);
|
||||
projector_.setCameraParams(K, R);
|
||||
|
||||
Point dst_tl, dst_br;
|
||||
detectResultRoi(dst_tl, dst_br);
|
||||
@@ -84,13 +81,10 @@ Point WarperBase<P>::warp(const Mat &src, float focal, const Mat &R, Mat &dst,
|
||||
|
||||
|
||||
template <class P>
|
||||
Rect WarperBase<P>::warpRoi(const Size &sz, float focal, const Mat &R)
|
||||
Rect WarperBase<P>::warpRoi(const Size &sz, const Mat &K, const Mat &R)
|
||||
{
|
||||
src_size_ = sz;
|
||||
|
||||
projector_.size = sz;
|
||||
projector_.focal = focal;
|
||||
projector_.setTransformation(R);
|
||||
projector_.setCameraParams(K, R);
|
||||
|
||||
Point dst_tl, dst_br;
|
||||
detectResultRoi(dst_tl, dst_br);
|
||||
@@ -165,43 +159,37 @@ void WarperBase<P>::detectResultRoiByBorder(Point &dst_tl, Point &dst_br)
|
||||
inline
|
||||
void PlaneProjector::mapForward(float x, float y, float &u, float &v)
|
||||
{
|
||||
x -= size.width * 0.5f;
|
||||
y -= size.height * 0.5f;
|
||||
float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
|
||||
float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
|
||||
float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
|
||||
|
||||
float x_ = r[0] * x + r[1] * y + r[2] * focal;
|
||||
float y_ = r[3] * x + r[4] * y + r[5] * focal;
|
||||
float z_ = r[6] * x + r[7] * y + r[8] * focal;
|
||||
|
||||
u = scale * x_ / z_ * plane_dist;
|
||||
v = scale * y_ / z_ * plane_dist;
|
||||
u = scale * x_ / z_;
|
||||
v = scale * y_ / z_;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
void PlaneProjector::mapBackward(float u, float v, float &x, float &y)
|
||||
{
|
||||
float x_ = u / scale;
|
||||
float y_ = v / scale;
|
||||
u /= scale;
|
||||
v /= scale;
|
||||
|
||||
float z;
|
||||
x = rinv[0] * x_ + rinv[1] * y_ + rinv[2] * plane_dist;
|
||||
y = rinv[3] * x_ + rinv[4] * y_ + rinv[5] * plane_dist;
|
||||
z = rinv[6] * x_ + rinv[7] * y_ + rinv[8] * plane_dist;
|
||||
x = k_rinv[0] * u + k_rinv[1] * v + k_rinv[2];
|
||||
y = k_rinv[3] * u + k_rinv[4] * v + k_rinv[5];
|
||||
z = k_rinv[6] * u + k_rinv[7] * v + k_rinv[8];
|
||||
|
||||
x = focal * x / z + size.width * 0.5f;
|
||||
y = focal * y / z + size.height * 0.5f;
|
||||
x /= z;
|
||||
y /= z;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
void SphericalProjector::mapForward(float x, float y, float &u, float &v)
|
||||
{
|
||||
x -= size.width * 0.5f;
|
||||
y -= size.height * 0.5f;
|
||||
|
||||
float x_ = r[0] * x + r[1] * y + r[2] * focal;
|
||||
float y_ = r[3] * x + r[4] * y + r[5] * focal;
|
||||
float z_ = r[6] * x + r[7] * y + r[8] * focal;
|
||||
{
|
||||
float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
|
||||
float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
|
||||
float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
|
||||
|
||||
u = scale * atan2f(x_, z_);
|
||||
v = scale * (static_cast<float>(CV_PI) - acosf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_)));
|
||||
@@ -211,30 +199,30 @@ void SphericalProjector::mapForward(float x, float y, float &u, float &v)
|
||||
inline
|
||||
void SphericalProjector::mapBackward(float u, float v, float &x, float &y)
|
||||
{
|
||||
float sinv = sinf(static_cast<float>(CV_PI) - v / scale);
|
||||
float x_ = sinv * sinf(u / scale);
|
||||
float y_ = cosf(static_cast<float>(CV_PI) - v / scale);
|
||||
float z_ = sinv * cosf(u / scale);
|
||||
u /= scale;
|
||||
v /= scale;
|
||||
|
||||
float sinv = sinf(static_cast<float>(CV_PI) - v);
|
||||
float x_ = sinv * sinf(u);
|
||||
float y_ = cosf(static_cast<float>(CV_PI) - v);
|
||||
float z_ = sinv * cosf(u);
|
||||
|
||||
float z;
|
||||
x = rinv[0] * x_ + rinv[1] * y_ + rinv[2] * z_;
|
||||
y = rinv[3] * x_ + rinv[4] * y_ + rinv[5] * z_;
|
||||
z = rinv[6] * x_ + rinv[7] * y_ + rinv[8] * z_;
|
||||
x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
|
||||
y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
|
||||
z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
|
||||
|
||||
x = focal * x / z + size.width * 0.5f;
|
||||
y = focal * y / z + size.height * 0.5f;
|
||||
x /= z;
|
||||
y /= z;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
void CylindricalProjector::mapForward(float x, float y, float &u, float &v)
|
||||
{
|
||||
x -= size.width * 0.5f;
|
||||
y -= size.height * 0.5f;
|
||||
|
||||
float x_ = r[0] * x + r[1] * y + r[2] * focal;
|
||||
float y_ = r[3] * x + r[4] * y + r[5] * focal;
|
||||
float z_ = r[6] * x + r[7] * y + r[8] * focal;
|
||||
float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2];
|
||||
float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5];
|
||||
float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8];
|
||||
|
||||
u = scale * atan2f(x_, z_);
|
||||
v = scale * y_ / sqrtf(x_ * x_ + z_ * z_);
|
||||
@@ -244,17 +232,20 @@ void CylindricalProjector::mapForward(float x, float y, float &u, float &v)
|
||||
inline
|
||||
void CylindricalProjector::mapBackward(float u, float v, float &x, float &y)
|
||||
{
|
||||
float x_ = sinf(u / scale);
|
||||
float y_ = v / scale;
|
||||
float z_ = cosf(u / scale);
|
||||
u /= scale;
|
||||
v /= scale;
|
||||
|
||||
float x_ = sinf(u);
|
||||
float y_ = v;
|
||||
float z_ = cosf(u);
|
||||
|
||||
float z;
|
||||
x = rinv[0] * x_ + rinv[1] * y_ + rinv[2] * z_;
|
||||
y = rinv[3] * x_ + rinv[4] * y_ + rinv[5] * z_;
|
||||
z = rinv[6] * x_ + rinv[7] * y_ + rinv[8] * z_;
|
||||
x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_;
|
||||
y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_;
|
||||
z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_;
|
||||
|
||||
x = focal * x / z + size.width * 0.5f;
|
||||
y = focal * y / z + size.height * 0.5f;
|
||||
x /= z;
|
||||
y /= z;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
@@ -51,28 +51,28 @@ class WarperCreator
|
||||
{
|
||||
public:
|
||||
virtual ~WarperCreator() {}
|
||||
virtual Ptr<detail::Warper> createByFocalLength(double f) const = 0;
|
||||
virtual Ptr<detail::Warper> create(float scale) const = 0;
|
||||
};
|
||||
|
||||
|
||||
class PlaneWarper : public WarperCreator
|
||||
{
|
||||
public:
|
||||
Ptr<detail::Warper> createByFocalLength(double f) const { return new detail::PlaneWarper(f); }
|
||||
Ptr<detail::Warper> create(float scale) const { return new detail::PlaneWarper(scale); }
|
||||
};
|
||||
|
||||
|
||||
class CylindricalWarper: public WarperCreator
|
||||
{
|
||||
public:
|
||||
Ptr<detail::Warper> createByFocalLength(double f) const { return new detail::CylindricalWarper(f); }
|
||||
Ptr<detail::Warper> create(float scale) const { return new detail::CylindricalWarper(scale); }
|
||||
};
|
||||
|
||||
|
||||
class SphericalWarper: public WarperCreator
|
||||
{
|
||||
public:
|
||||
Ptr<detail::Warper> createByFocalLength(double f) const { return new detail::SphericalWarper(f); }
|
||||
Ptr<detail::Warper> create(float scale) const { return new detail::SphericalWarper(scale); }
|
||||
};
|
||||
|
||||
|
||||
@@ -80,21 +80,21 @@ public:
|
||||
class PlaneWarperGpu: public WarperCreator
|
||||
{
|
||||
public:
|
||||
Ptr<detail::Warper> createByFocalLength(double f) const { return new detail::PlaneWarperGpu(f); }
|
||||
Ptr<detail::Warper> create(float scale) const { return new detail::PlaneWarperGpu(scale); }
|
||||
};
|
||||
|
||||
|
||||
class CylindricalWarperGpu: public WarperCreator
|
||||
{
|
||||
public:
|
||||
Ptr<detail::Warper> createByFocalLength(double f) const { return new detail::CylindricalWarperGpu(f); }
|
||||
Ptr<detail::Warper> create(float scale) const { return new detail::CylindricalWarperGpu(scale); }
|
||||
};
|
||||
|
||||
|
||||
class SphericalWarperGpu: public WarperCreator
|
||||
{
|
||||
public:
|
||||
Ptr<detail::Warper> createByFocalLength(double f) const { return new detail::SphericalWarperGpu(f); }
|
||||
Ptr<detail::Warper> create(float scale) const { return new detail::SphericalWarperGpu(scale); }
|
||||
};
|
||||
#endif
|
||||
|
||||
|
Reference in New Issue
Block a user