Added support of vertical straightening into stitching
This commit is contained in:
parent
48dec9c03a
commit
16f5c67914
@ -170,7 +170,13 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void CV_EXPORTS waveCorrect(std::vector<Mat> &rmats);
|
enum CV_EXPORTS WaveCorrectKind
|
||||||
|
{
|
||||||
|
WAVE_CORRECT_HORIZ,
|
||||||
|
WAVE_CORRECT_VERT
|
||||||
|
};
|
||||||
|
|
||||||
|
void CV_EXPORTS waveCorrect(std::vector<Mat> &rmats, WaveCorrectKind kind);
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -100,6 +100,7 @@ public:
|
|||||||
std::vector<Mat> &masks);
|
std::vector<Mat> &masks);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// To avoid GCGraph dependency
|
||||||
class Impl;
|
class Impl;
|
||||||
Ptr<Impl> impl_;
|
Ptr<Impl> impl_;
|
||||||
};
|
};
|
||||||
|
@ -129,6 +129,7 @@ protected:
|
|||||||
void detectResultRoi(Point &dst_tl, Point &dst_br);
|
void detectResultRoi(Point &dst_tl, Point &dst_br);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
class CV_EXPORTS PlaneWarperGpu : public PlaneWarper
|
class CV_EXPORTS PlaneWarperGpu : public PlaneWarper
|
||||||
{
|
{
|
||||||
|
@ -96,6 +96,9 @@ public:
|
|||||||
void setBundleAdjuster(Ptr<detail::BundleAdjusterBase> bundle_adjuster)
|
void setBundleAdjuster(Ptr<detail::BundleAdjusterBase> bundle_adjuster)
|
||||||
{ bundle_adjuster_ = bundle_adjuster; }
|
{ bundle_adjuster_ = bundle_adjuster; }
|
||||||
|
|
||||||
|
detail::WaveCorrectKind waveCorrectKind() const { return wave_correct_kind_; }
|
||||||
|
void setWaveCorrectKind(detail::WaveCorrectKind kind) { wave_correct_kind_ = kind; }
|
||||||
|
|
||||||
Ptr<WarperCreator> warper() { return warper_; }
|
Ptr<WarperCreator> warper() { return warper_; }
|
||||||
const Ptr<WarperCreator> warper() const { return warper_; }
|
const Ptr<WarperCreator> warper() const { return warper_; }
|
||||||
void setWarper(Ptr<WarperCreator> warper) { warper_ = warper; }
|
void setWarper(Ptr<WarperCreator> warper) { warper_ = warper; }
|
||||||
@ -124,6 +127,7 @@ private:
|
|||||||
Ptr<detail::FeaturesFinder> features_finder_;
|
Ptr<detail::FeaturesFinder> features_finder_;
|
||||||
Ptr<detail::FeaturesMatcher> features_matcher_;
|
Ptr<detail::FeaturesMatcher> features_matcher_;
|
||||||
Ptr<detail::BundleAdjusterBase> bundle_adjuster_;
|
Ptr<detail::BundleAdjusterBase> bundle_adjuster_;
|
||||||
|
detail::WaveCorrectKind wave_correct_kind_;
|
||||||
Ptr<WarperCreator> warper_;
|
Ptr<WarperCreator> warper_;
|
||||||
Ptr<detail::ExposureCompensator> exposure_comp_;
|
Ptr<detail::ExposureCompensator> exposure_comp_;
|
||||||
Ptr<detail::SeamFinder> seam_finder_;
|
Ptr<detail::SeamFinder> seam_finder_;
|
||||||
|
@ -567,7 +567,7 @@ void BundleAdjusterRay::calcJacobian(Mat &jac)
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void waveCorrect(vector<Mat> &rmats)
|
void waveCorrect(vector<Mat> &rmats, WaveCorrectKind kind)
|
||||||
{
|
{
|
||||||
LOGLN("Wave correcting...");
|
LOGLN("Wave correcting...");
|
||||||
int64 t = getTickCount();
|
int64 t = getTickCount();
|
||||||
@ -580,7 +580,14 @@ void waveCorrect(vector<Mat> &rmats)
|
|||||||
}
|
}
|
||||||
Mat eigen_vals, eigen_vecs;
|
Mat eigen_vals, eigen_vecs;
|
||||||
eigen(moment, eigen_vals, eigen_vecs);
|
eigen(moment, eigen_vals, eigen_vecs);
|
||||||
Mat rg1 = eigen_vecs.row(2).t();
|
|
||||||
|
Mat rg1;
|
||||||
|
if (kind == WAVE_CORRECT_HORIZ)
|
||||||
|
rg1 = eigen_vecs.row(2).t();
|
||||||
|
else if (kind == WAVE_CORRECT_VERT)
|
||||||
|
rg1 = eigen_vecs.row(0).t();
|
||||||
|
else
|
||||||
|
CV_Error(CV_StsBadArg, "unsupported kind of wave correction");
|
||||||
|
|
||||||
Mat img_k = Mat::zeros(3, 1, CV_32F);
|
Mat img_k = Mat::zeros(3, 1, CV_32F);
|
||||||
for (size_t i = 0; i < rmats.size(); ++i)
|
for (size_t i = 0; i < rmats.size(); ++i)
|
||||||
@ -590,6 +597,29 @@ void waveCorrect(vector<Mat> &rmats)
|
|||||||
|
|
||||||
Mat rg2 = rg0.cross(rg1);
|
Mat rg2 = rg0.cross(rg1);
|
||||||
|
|
||||||
|
double conf = 0;
|
||||||
|
if (kind == WAVE_CORRECT_HORIZ)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < rmats.size(); ++i)
|
||||||
|
conf += rg0.dot(rmats[i].col(0));
|
||||||
|
if (conf < 0)
|
||||||
|
{
|
||||||
|
rg0 *= -1;
|
||||||
|
rg1 *= -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (kind == WAVE_CORRECT_VERT)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < rmats.size(); ++i)
|
||||||
|
conf -= rg1.dot(rmats[i].col(0));
|
||||||
|
cout << conf << endl;
|
||||||
|
if (conf < 0)
|
||||||
|
{
|
||||||
|
rg0 *= -1;
|
||||||
|
rg1 *= -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Mat R = Mat::zeros(3, 3, CV_32F);
|
Mat R = Mat::zeros(3, 3, CV_32F);
|
||||||
Mat tmp = R.row(0);
|
Mat tmp = R.row(0);
|
||||||
Mat(rg0.t()).copyTo(tmp);
|
Mat(rg0.t()).copyTo(tmp);
|
||||||
|
@ -56,6 +56,7 @@ Stitcher Stitcher::createDefault(bool try_use_gpu)
|
|||||||
stitcher.setHorizontalStrightening(true);
|
stitcher.setHorizontalStrightening(true);
|
||||||
stitcher.setFeaturesMatcher(new detail::BestOf2NearestMatcher(try_use_gpu));
|
stitcher.setFeaturesMatcher(new detail::BestOf2NearestMatcher(try_use_gpu));
|
||||||
stitcher.setBundleAdjuster(new detail::BundleAdjusterRay());
|
stitcher.setBundleAdjuster(new detail::BundleAdjusterRay());
|
||||||
|
stitcher.setWaveCorrectKind(detail::WAVE_CORRECT_HORIZ);
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
if (try_use_gpu && gpu::getCudaEnabledDeviceCount() > 0)
|
if (try_use_gpu && gpu::getCudaEnabledDeviceCount() > 0)
|
||||||
@ -208,7 +209,7 @@ Stitcher::Status Stitcher::stitch(InputArray imgs_, OutputArray pano_)
|
|||||||
vector<Mat> rmats;
|
vector<Mat> rmats;
|
||||||
for (size_t i = 0; i < cameras.size(); ++i)
|
for (size_t i = 0; i < cameras.size(); ++i)
|
||||||
rmats.push_back(cameras[i].R);
|
rmats.push_back(cameras[i].R);
|
||||||
detail::waveCorrect(rmats);
|
detail::waveCorrect(rmats, wave_correct_kind_);
|
||||||
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];
|
||||||
}
|
}
|
||||||
|
@ -88,8 +88,8 @@ void printUsage()
|
|||||||
" <fx><skew><ppx><aspect><ppy>. The default mask is 'xxxxx'. If bundle\n"
|
" <fx><skew><ppx><aspect><ppy>. The default mask is 'xxxxx'. If bundle\n"
|
||||||
" adjustment doesn't support estimation of selected parameter then\n"
|
" adjustment doesn't support estimation of selected parameter then\n"
|
||||||
" the respective flag is ignored.\n"
|
" the respective flag is ignored.\n"
|
||||||
" --wave_correct (no|yes)\n"
|
" --wave_correct (no|horiz|vert)\n"
|
||||||
" Perform wave effect correction. The default is 'yes'.\n"
|
" Perform wave effect correction. The default is 'horiz'.\n"
|
||||||
" --save_graph <file_name>\n"
|
" --save_graph <file_name>\n"
|
||||||
" Save matches graph represented in DOT language to <file_name> file.\n"
|
" Save matches graph represented in DOT language to <file_name> file.\n"
|
||||||
" Labels description: Nm is number of matches, Ni is number of inliers,\n"
|
" Labels description: Nm is number of matches, Ni is number of inliers,\n"
|
||||||
@ -125,7 +125,8 @@ double compose_megapix = -1;
|
|||||||
float conf_thresh = 1.f;
|
float conf_thresh = 1.f;
|
||||||
string ba_cost_func = "ray";
|
string ba_cost_func = "ray";
|
||||||
string ba_refine_mask = "xxxxx";
|
string ba_refine_mask = "xxxxx";
|
||||||
bool wave_correct = true;
|
bool do_wave_correct = true;
|
||||||
|
WaveCorrectKind wave_correct = detail::WAVE_CORRECT_HORIZ;
|
||||||
bool save_graph = false;
|
bool save_graph = false;
|
||||||
std::string save_graph_to;
|
std::string save_graph_to;
|
||||||
string warp_type = "spherical";
|
string warp_type = "spherical";
|
||||||
@ -215,9 +216,17 @@ int parseCmdArgs(int argc, char** argv)
|
|||||||
else if (string(argv[i]) == "--wave_correct")
|
else if (string(argv[i]) == "--wave_correct")
|
||||||
{
|
{
|
||||||
if (string(argv[i + 1]) == "no")
|
if (string(argv[i + 1]) == "no")
|
||||||
wave_correct = false;
|
do_wave_correct = false;
|
||||||
else if (string(argv[i + 1]) == "yes")
|
else if (string(argv[i + 1]) == "horiz")
|
||||||
wave_correct = true;
|
{
|
||||||
|
do_wave_correct = true;
|
||||||
|
wave_correct = detail::WAVE_CORRECT_HORIZ;
|
||||||
|
}
|
||||||
|
else if (string(argv[i + 1]) == "vert")
|
||||||
|
{
|
||||||
|
do_wave_correct = true;
|
||||||
|
wave_correct = detail::WAVE_CORRECT_VERT;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cout << "Bad --wave_correct flag value\n";
|
cout << "Bad --wave_correct flag value\n";
|
||||||
@ -467,12 +476,12 @@ int main(int argc, char* argv[])
|
|||||||
nth_element(focals.begin(), focals.begin() + focals.size()/2, focals.end());
|
nth_element(focals.begin(), focals.begin() + focals.size()/2, focals.end());
|
||||||
float warped_image_scale = static_cast<float>(focals[focals.size() / 2]);
|
float warped_image_scale = static_cast<float>(focals[focals.size() / 2]);
|
||||||
|
|
||||||
if (wave_correct)
|
if (do_wave_correct)
|
||||||
{
|
{
|
||||||
vector<Mat> rmats;
|
vector<Mat> rmats;
|
||||||
for (size_t i = 0; i < cameras.size(); ++i)
|
for (size_t i = 0; i < cameras.size(); ++i)
|
||||||
rmats.push_back(cameras[i].R);
|
rmats.push_back(cameras[i].R);
|
||||||
waveCorrect(rmats);
|
waveCorrect(rmats, wave_correct);
|
||||||
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];
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user