Commit 4c03afe0 authored by Andrey Pavlenko's avatar Andrey Pavlenko Committed by OpenCV Buildbot

Merge pull request #1079 from AlexeySpizhevoy:master

parents 8a3aa1f5 dcb049df
...@@ -18,12 +18,11 @@ Rotation estimator base class. It takes features of all images, pairwise matches ...@@ -18,12 +18,11 @@ Rotation estimator base class. It takes features of all images, pairwise matches
public: public:
virtual ~Estimator() {} virtual ~Estimator() {}
void operator ()(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches, bool operator ()(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches,
std::vector<CameraParams> &cameras) std::vector<CameraParams> &cameras);
{ estimate(features, pairwise_matches, cameras); }
protected: protected:
virtual void estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches, virtual bool estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches,
std::vector<CameraParams> &cameras) = 0; std::vector<CameraParams> &cameras) = 0;
}; };
...@@ -32,7 +31,7 @@ detail::Estimator::operator() ...@@ -32,7 +31,7 @@ detail::Estimator::operator()
Estimates camera parameters. Estimates camera parameters.
.. ocv:function:: detail::Estimator::operator ()(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches, std::vector<CameraParams> &cameras) .. ocv:function:: bool detail::Estimator::operator ()(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches, std::vector<CameraParams> &cameras)
:param features: Features of images :param features: Features of images
...@@ -40,12 +39,14 @@ Estimates camera parameters. ...@@ -40,12 +39,14 @@ Estimates camera parameters.
:param cameras: Estimated camera parameters :param cameras: Estimated camera parameters
:return: True in case of success, false otherwise
detail::Estimator::estimate detail::Estimator::estimate
--------------------------- ---------------------------
This method must implement camera parameters estimation logic in order to make the wrapper `detail::Estimator::operator()`_ work. This method must implement camera parameters estimation logic in order to make the wrapper `detail::Estimator::operator()`_ work.
.. ocv:function:: void detail::Estimator::estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches, std::vector<CameraParams> &cameras) .. ocv:function:: bool detail::Estimator::estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches, std::vector<CameraParams> &cameras)
:param features: Features of images :param features: Features of images
...@@ -53,6 +54,8 @@ This method must implement camera parameters estimation logic in order to make t ...@@ -53,6 +54,8 @@ This method must implement camera parameters estimation logic in order to make t
:param cameras: Estimated camera parameters :param cameras: Estimated camera parameters
:return: True in case of success, false otherwise
detail::HomographyBasedEstimator detail::HomographyBasedEstimator
-------------------------------- --------------------------------
.. ocv:class:: detail::HomographyBasedEstimator : public detail::Estimator .. ocv:class:: detail::HomographyBasedEstimator : public detail::Estimator
......
...@@ -59,7 +59,13 @@ class CV_EXPORTS Stitcher ...@@ -59,7 +59,13 @@ class CV_EXPORTS Stitcher
{ {
public: public:
enum { ORIG_RESOL = -1 }; enum { ORIG_RESOL = -1 };
enum Status { OK, ERR_NEED_MORE_IMGS }; enum Status
{
OK = 0,
ERR_NEED_MORE_IMGS = 1,
ERR_HOMOGRAPHY_EST_FAIL = 2,
ERR_CAMERA_PARAMS_ADJUST_FAIL = 3
};
// Creates stitcher with default parameters // Creates stitcher with default parameters
static Stitcher createDefault(bool try_use_gpu = false); static Stitcher createDefault(bool try_use_gpu = false);
...@@ -138,7 +144,7 @@ private: ...@@ -138,7 +144,7 @@ private:
Stitcher() {} Stitcher() {}
Status matchImages(); Status matchImages();
void estimateCameraParams(); Status estimateCameraParams();
double registr_resol_; double registr_resol_;
double seam_est_resol_; double seam_est_resol_;
......
...@@ -56,12 +56,14 @@ class CV_EXPORTS Estimator ...@@ -56,12 +56,14 @@ class CV_EXPORTS Estimator
public: public:
virtual ~Estimator() {} virtual ~Estimator() {}
void operator ()(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches, bool operator ()(const std::vector<ImageFeatures> &features,
const std::vector<MatchesInfo> &pairwise_matches,
std::vector<CameraParams> &cameras) std::vector<CameraParams> &cameras)
{ estimate(features, pairwise_matches, cameras); } { return estimate(features, pairwise_matches, cameras); }
protected: protected:
virtual void estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches, virtual bool estimate(const std::vector<ImageFeatures> &features,
const std::vector<MatchesInfo> &pairwise_matches,
std::vector<CameraParams> &cameras) = 0; std::vector<CameraParams> &cameras) = 0;
}; };
...@@ -73,8 +75,9 @@ public: ...@@ -73,8 +75,9 @@ public:
: is_focals_estimated_(is_focals_estimated) {} : is_focals_estimated_(is_focals_estimated) {}
private: private:
void estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches, virtual bool estimate(const std::vector<ImageFeatures> &features,
std::vector<CameraParams> &cameras); const std::vector<MatchesInfo> &pairwise_matches,
std::vector<CameraParams> &cameras);
bool is_focals_estimated_; bool is_focals_estimated_;
}; };
...@@ -107,7 +110,7 @@ protected: ...@@ -107,7 +110,7 @@ protected:
} }
// Runs bundle adjustment // Runs bundle adjustment
virtual void estimate(const std::vector<ImageFeatures> &features, virtual bool estimate(const std::vector<ImageFeatures> &features,
const std::vector<MatchesInfo> &pairwise_matches, const std::vector<MatchesInfo> &pairwise_matches,
std::vector<CameraParams> &cameras); std::vector<CameraParams> &cameras);
...@@ -193,11 +196,14 @@ void CV_EXPORTS waveCorrect(std::vector<Mat> &rmats, WaveCorrectKind kind); ...@@ -193,11 +196,14 @@ void CV_EXPORTS waveCorrect(std::vector<Mat> &rmats, WaveCorrectKind kind);
String CV_EXPORTS matchesGraphAsString(std::vector<String> &pathes, std::vector<MatchesInfo> &pairwise_matches, String CV_EXPORTS matchesGraphAsString(std::vector<String> &pathes, std::vector<MatchesInfo> &pairwise_matches,
float conf_threshold); float conf_threshold);
std::vector<int> CV_EXPORTS leaveBiggestComponent(std::vector<ImageFeatures> &features, std::vector<MatchesInfo> &pairwise_matches, std::vector<int> CV_EXPORTS leaveBiggestComponent(
float conf_threshold); std::vector<ImageFeatures> &features,
std::vector<MatchesInfo> &pairwise_matches,
float conf_threshold);
void CV_EXPORTS findMaxSpanningTree(int num_images, const std::vector<MatchesInfo> &pairwise_matches, void CV_EXPORTS findMaxSpanningTree(
Graph &span_tree, std::vector<int> &centers); int num_images, const std::vector<MatchesInfo> &pairwise_matches,
Graph &span_tree, std::vector<int> &centers);
} // namespace detail } // namespace detail
} // namespace cv } // namespace cv
......
...@@ -43,6 +43,13 @@ ...@@ -43,6 +43,13 @@
#include "precomp.hpp" #include "precomp.hpp"
#include "opencv2/calib3d/calib3d_c.h" #include "opencv2/calib3d/calib3d_c.h"
#ifdef _MSC_VER
#include <float.h>
#define isnan(x) _isnan(x)
#else
#include <math.h>
#endif
using namespace cv; using namespace cv;
using namespace cv::detail; using namespace cv::detail;
...@@ -101,8 +108,10 @@ void calcDeriv(const Mat &err1, const Mat &err2, double h, Mat res) ...@@ -101,8 +108,10 @@ void calcDeriv(const Mat &err1, const Mat &err2, double h, Mat res)
namespace cv { namespace cv {
namespace detail { namespace detail {
void HomographyBasedEstimator::estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches, bool HomographyBasedEstimator::estimate(
std::vector<CameraParams> &cameras) const std::vector<ImageFeatures> &features,
const std::vector<MatchesInfo> &pairwise_matches,
std::vector<CameraParams> &cameras)
{ {
LOGLN("Estimating rotations..."); LOGLN("Estimating rotations...");
#if ENABLE_LOG #if ENABLE_LOG
...@@ -164,12 +173,13 @@ void HomographyBasedEstimator::estimate(const std::vector<ImageFeatures> &featur ...@@ -164,12 +173,13 @@ void HomographyBasedEstimator::estimate(const std::vector<ImageFeatures> &featur
} }
LOGLN("Estimating rotations, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec"); LOGLN("Estimating rotations, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
return true;
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
void BundleAdjusterBase::estimate(const std::vector<ImageFeatures> &features, bool BundleAdjusterBase::estimate(const std::vector<ImageFeatures> &features,
const std::vector<MatchesInfo> &pairwise_matches, const std::vector<MatchesInfo> &pairwise_matches,
std::vector<CameraParams> &cameras) std::vector<CameraParams> &cameras)
{ {
...@@ -245,6 +255,19 @@ void BundleAdjusterBase::estimate(const std::vector<ImageFeatures> &features, ...@@ -245,6 +255,19 @@ void BundleAdjusterBase::estimate(const std::vector<ImageFeatures> &features,
LOGLN_CHAT("Bundle adjustment, final RMS error: " << std::sqrt(err.dot(err) / total_num_matches_)); LOGLN_CHAT("Bundle adjustment, final RMS error: " << std::sqrt(err.dot(err) / total_num_matches_));
LOGLN_CHAT("Bundle adjustment, iterations done: " << iter); LOGLN_CHAT("Bundle adjustment, iterations done: " << iter);
// Check if all camera parameters are valid
bool ok = true;
for (int i = 0; i < cam_params_.rows; ++i)
{
if (isnan(cam_params_.at<double>(i,0)))
{
ok = false;
break;
}
}
if (!ok)
return false;
obtainRefinedCameraParams(cameras); obtainRefinedCameraParams(cameras);
// Normalize motion to center image // Normalize motion to center image
...@@ -256,6 +279,7 @@ void BundleAdjusterBase::estimate(const std::vector<ImageFeatures> &features, ...@@ -256,6 +279,7 @@ void BundleAdjusterBase::estimate(const std::vector<ImageFeatures> &features,
cameras[i].R = R_inv * cameras[i].R; cameras[i].R = R_inv * cameras[i].R;
LOGLN_CHAT("Bundle adjustment, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec"); LOGLN_CHAT("Bundle adjustment, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
return true;
} }
......
...@@ -102,7 +102,8 @@ Stitcher::Status Stitcher::estimateTransform(InputArray images, const std::vecto ...@@ -102,7 +102,8 @@ Stitcher::Status Stitcher::estimateTransform(InputArray images, const std::vecto
if ((status = matchImages()) != OK) if ((status = matchImages()) != OK)
return status; return status;
estimateCameraParams(); if ((status = estimateCameraParams()) != OK)
return status;
return OK; return OK;
} }
...@@ -442,10 +443,11 @@ Stitcher::Status Stitcher::matchImages() ...@@ -442,10 +443,11 @@ Stitcher::Status Stitcher::matchImages()
} }
void Stitcher::estimateCameraParams() Stitcher::Status Stitcher::estimateCameraParams()
{ {
detail::HomographyBasedEstimator estimator; detail::HomographyBasedEstimator estimator;
estimator(features_, pairwise_matches_, cameras_); if (!estimator(features_, pairwise_matches_, cameras_))
return ERR_HOMOGRAPHY_EST_FAIL;
for (size_t i = 0; i < cameras_.size(); ++i) for (size_t i = 0; i < cameras_.size(); ++i)
{ {
...@@ -456,7 +458,8 @@ void Stitcher::estimateCameraParams() ...@@ -456,7 +458,8 @@ void Stitcher::estimateCameraParams()
} }
bundle_adjuster_->setConfThresh(conf_thresh_); bundle_adjuster_->setConfThresh(conf_thresh_);
(*bundle_adjuster_)(features_, pairwise_matches_, cameras_); if (!(*bundle_adjuster_)(features_, pairwise_matches_, cameras_))
return ERR_CAMERA_PARAMS_ADJUST_FAIL;
// Find median focal length and use it as final image scale // Find median focal length and use it as final image scale
std::vector<double> focals; std::vector<double> focals;
...@@ -481,6 +484,8 @@ void Stitcher::estimateCameraParams() ...@@ -481,6 +484,8 @@ void Stitcher::estimateCameraParams()
for (size_t i = 0; i < cameras_.size(); ++i) for (size_t i = 0; i < cameras_.size(); ++i)
cameras_[i].R = rmats[i]; cameras_[i].R = rmats[i];
} }
return OK;
} }
} // namespace cv } // namespace cv
...@@ -469,7 +469,11 @@ int main(int argc, char* argv[]) ...@@ -469,7 +469,11 @@ int main(int argc, char* argv[])
HomographyBasedEstimator estimator; HomographyBasedEstimator estimator;
vector<CameraParams> cameras; vector<CameraParams> cameras;
estimator(features, pairwise_matches, cameras); if (!estimator(features, pairwise_matches, cameras))
{
cout << "Homography estimation failed.\n";
return -1;
}
for (size_t i = 0; i < cameras.size(); ++i) for (size_t i = 0; i < cameras.size(); ++i)
{ {
...@@ -495,7 +499,11 @@ int main(int argc, char* argv[]) ...@@ -495,7 +499,11 @@ int main(int argc, char* argv[])
if (ba_refine_mask[3] == 'x') refine_mask(1,1) = 1; if (ba_refine_mask[3] == 'x') refine_mask(1,1) = 1;
if (ba_refine_mask[4] == 'x') refine_mask(1,2) = 1; if (ba_refine_mask[4] == 'x') refine_mask(1,2) = 1;
adjuster->setRefinementMask(refine_mask); adjuster->setRefinementMask(refine_mask);
(*adjuster)(features, pairwise_matches, cameras); if (!(*adjuster)(features, pairwise_matches, cameras))
{
cout << "Camera parameters adjusting failed.\n";
return -1;
}
// Find median focal length // Find median focal length
......
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