implemented rotating-only cameras calibration
This commit is contained in:
parent
4c289dc166
commit
aba2008711
@ -115,3 +115,70 @@ void estimateFocal(const vector<ImageFeatures> &features, const vector<MatchesIn
|
||||
focals[i] = focals_sum / num_images;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
template<typename _Tp> static inline bool
|
||||
decomposeCholesky(_Tp* A, size_t astep, int m)
|
||||
{
|
||||
if (!Cholesky(A, astep, m, 0, 0, 0))
|
||||
return false;
|
||||
astep /= sizeof(A[0]);
|
||||
for (int i = 0; i < m; ++i)
|
||||
A[i*astep + i] = (_Tp)(1./A[i*astep + i]);
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
bool calibrateRotatingCamera(const vector<Mat> &Hs, Mat &K)
|
||||
{
|
||||
int m = static_cast<int>(Hs.size());
|
||||
CV_Assert(m >= 1);
|
||||
|
||||
vector<Mat> Hs_(m);
|
||||
for (int i = 0; i < m; ++i)
|
||||
{
|
||||
CV_Assert(Hs[i].size() == Size(3, 3) && Hs[i].type() == CV_64F);
|
||||
Hs_[i] = Hs[i] / pow(determinant(Hs[i]), 1./3.);
|
||||
}
|
||||
|
||||
const int idx_map[3][3] = {{0, 1, 2}, {1, 3, 4}, {2, 4, 5}};
|
||||
Mat_<double> A(6*m, 6);
|
||||
A.setTo(0);
|
||||
|
||||
int eq_idx = 0;
|
||||
for (int k = 0; k < m; ++k)
|
||||
{
|
||||
Mat_<double> H(Hs_[k]);
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
for (int j = i; j < 3; ++j, ++eq_idx)
|
||||
{
|
||||
for (int l = 0; l < 3; ++l)
|
||||
{
|
||||
for (int s = 0; s < 3; ++s)
|
||||
{
|
||||
int idx = idx_map[l][s];
|
||||
A(eq_idx, idx) += H(i,l) * H(j,s);
|
||||
}
|
||||
}
|
||||
A(eq_idx, idx_map[i][j]) -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Mat_<double> wcoef;
|
||||
SVD::solveZ(A, wcoef);
|
||||
|
||||
Mat_<double> W(3,3);
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = i; j < 3; ++j)
|
||||
W(i,j) = W(j,i) = wcoef(idx_map[i][j], 0) / wcoef(5,0);
|
||||
if (!decomposeCholesky(W.ptr<double>(), W.step, 3))
|
||||
return false;
|
||||
W(0,1) = W(0,2) = W(1,2) = 0;
|
||||
K = W.t();
|
||||
return true;
|
||||
}
|
||||
|
@ -52,4 +52,6 @@ void focalsFromHomography(const cv::Mat &H, double &f0, double &f1, bool &f0_ok,
|
||||
void estimateFocal(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches,
|
||||
std::vector<double> &focals);
|
||||
|
||||
bool calibrateRotatingCamera(const std::vector<cv::Mat> &Hs, cv::Mat &K);
|
||||
|
||||
#endif // __OPENCV_AUTOCALIB_HPP__
|
||||
|
@ -100,7 +100,7 @@ void printUsage()
|
||||
" --blend_strength <float>\n"
|
||||
" Blending strength from [0,100] range. The default is 5.\n"
|
||||
" --output <result_img>\n"
|
||||
" The default is 'result.png'.\n";
|
||||
" The default is 'result.jpg'.\n";
|
||||
}
|
||||
|
||||
|
||||
@ -120,7 +120,7 @@ float match_conf = 0.65f;
|
||||
int seam_find_type = SeamFinder::GC_COLOR;
|
||||
int blend_type = Blender::MULTI_BAND;
|
||||
float blend_strength = 5;
|
||||
string result_name = "result.png";
|
||||
string result_name = "result.jpg";
|
||||
|
||||
int parseCmdArgs(int argc, char** argv)
|
||||
{
|
||||
|
@ -108,6 +108,27 @@ void HomographyBasedEstimator::estimate(const vector<ImageFeatures> &features, c
|
||||
{
|
||||
const int num_images = static_cast<int>(features.size());
|
||||
|
||||
#if 0
|
||||
// Robustly estimate focal length from rotating cameras
|
||||
vector<Mat> Hs;
|
||||
for (int iter = 0; iter < 100; ++iter)
|
||||
{
|
||||
int len = 2 + rand()%(pairwise_matches.size() - 1);
|
||||
vector<int> subset;
|
||||
selectRandomSubset(len, pairwise_matches.size(), subset);
|
||||
Hs.clear();
|
||||
for (size_t i = 0; i < subset.size(); ++i)
|
||||
if (!pairwise_matches[subset[i]].H.empty())
|
||||
Hs.push_back(pairwise_matches[subset[i]].H);
|
||||
Mat_<double> K;
|
||||
if (Hs.size() >= 2)
|
||||
{
|
||||
if (calibrateRotatingCamera(Hs, K))
|
||||
cin.get();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Estimate focal length and set it for all cameras
|
||||
vector<double> focals;
|
||||
estimateFocal(features, pairwise_matches, focals);
|
||||
|
@ -148,3 +148,16 @@ Point resultTl(const vector<Point> &corners)
|
||||
return tl;
|
||||
}
|
||||
|
||||
|
||||
void selectRandomSubset(int count, int size, vector<int> &subset)
|
||||
{
|
||||
subset.clear();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
if (randu<int>() % (size - i) < count)
|
||||
{
|
||||
subset.push_back(i);
|
||||
count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -108,6 +108,7 @@ bool overlapRoi(cv::Point tl1, cv::Point tl2, cv::Size sz1, cv::Size sz2, cv::Re
|
||||
cv::Rect resultRoi(const std::vector<cv::Point> &corners, const std::vector<cv::Mat> &images);
|
||||
cv::Rect resultRoi(const std::vector<cv::Point> &corners, const std::vector<cv::Size> &sizes);
|
||||
cv::Point resultTl(const std::vector<cv::Point> &corners);
|
||||
void selectRandomSubset(int count, int size, std::vector<int> &subset);
|
||||
|
||||
|
||||
#include "util_inl.hpp"
|
||||
|
Loading…
Reference in New Issue
Block a user