mirror of
https://github.com/opencv/opencv.git
synced 2025-06-08 01:53:19 +08:00
added handling of camera parameters estimation errors (#3122)
This commit is contained in:
parent
70deda354a
commit
37ea872204
@ -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:
|
|||||||
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
|
|||||||
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:
|
|||||||
: 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:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
|||||||
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> ¢ers);
|
int num_images, const std::vector<MatchesInfo> &pairwise_matches,
|
||||||
|
Graph &span_tree, std::vector<int> ¢ers);
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cv
|
} // namespace cv
|
||||||
|
@ -101,8 +101,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 +166,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,7 +248,21 @@ 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);
|
||||||
|
|
||||||
obtainRefinedCameraParams(cameras);
|
// 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)) ||
|
||||||
|
isinf(cam_params_.at<double>(i,0)))
|
||||||
|
{
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
obtainRefinedCameraParams(cameras);
|
||||||
|
|
||||||
// Normalize motion to center image
|
// Normalize motion to center image
|
||||||
Graph span_tree;
|
Graph span_tree;
|
||||||
@ -256,6 +273,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
|
|||||||
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()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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()
|
|||||||
}
|
}
|
||||||
|
|
||||||
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()
|
|||||||
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[])
|
|||||||
|
|
||||||
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[])
|
|||||||
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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user