diff --git a/modules/stitching/include/opencv2/stitching/detail/motion_estimators.hpp b/modules/stitching/include/opencv2/stitching/detail/motion_estimators.hpp index 65f6d235d5..81fff1f699 100644 --- a/modules/stitching/include/opencv2/stitching/detail/motion_estimators.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/motion_estimators.hpp @@ -170,7 +170,13 @@ private: }; -void CV_EXPORTS waveCorrect(std::vector &rmats); +enum CV_EXPORTS WaveCorrectKind +{ + WAVE_CORRECT_HORIZ, + WAVE_CORRECT_VERT +}; + +void CV_EXPORTS waveCorrect(std::vector &rmats, WaveCorrectKind kind); ////////////////////////////////////////////////////////////////////////////// diff --git a/modules/stitching/include/opencv2/stitching/detail/seam_finders.hpp b/modules/stitching/include/opencv2/stitching/detail/seam_finders.hpp index 52ffd0a655..4151598745 100644 --- a/modules/stitching/include/opencv2/stitching/detail/seam_finders.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/seam_finders.hpp @@ -100,6 +100,7 @@ public: std::vector &masks); private: + // To avoid GCGraph dependency class Impl; Ptr impl_; }; diff --git a/modules/stitching/include/opencv2/stitching/detail/warpers.hpp b/modules/stitching/include/opencv2/stitching/detail/warpers.hpp index 97e6a0a402..12600a6c8f 100644 --- a/modules/stitching/include/opencv2/stitching/detail/warpers.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/warpers.hpp @@ -129,6 +129,7 @@ protected: void detectResultRoi(Point &dst_tl, Point &dst_br); }; + #ifndef ANDROID class CV_EXPORTS PlaneWarperGpu : public PlaneWarper { diff --git a/modules/stitching/include/opencv2/stitching/stitcher.hpp b/modules/stitching/include/opencv2/stitching/stitcher.hpp index 072e96f864..db1bb337db 100644 --- a/modules/stitching/include/opencv2/stitching/stitcher.hpp +++ b/modules/stitching/include/opencv2/stitching/stitcher.hpp @@ -96,6 +96,9 @@ public: void setBundleAdjuster(Ptr bundle_adjuster) { bundle_adjuster_ = bundle_adjuster; } + detail::WaveCorrectKind waveCorrectKind() const { return wave_correct_kind_; } + void setWaveCorrectKind(detail::WaveCorrectKind kind) { wave_correct_kind_ = kind; } + Ptr warper() { return warper_; } const Ptr warper() const { return warper_; } void setWarper(Ptr warper) { warper_ = warper; } @@ -124,6 +127,7 @@ private: Ptr features_finder_; Ptr features_matcher_; Ptr bundle_adjuster_; + detail::WaveCorrectKind wave_correct_kind_; Ptr warper_; Ptr exposure_comp_; Ptr seam_finder_; diff --git a/modules/stitching/src/motion_estimators.cpp b/modules/stitching/src/motion_estimators.cpp index ea85f070af..74ff579543 100644 --- a/modules/stitching/src/motion_estimators.cpp +++ b/modules/stitching/src/motion_estimators.cpp @@ -567,7 +567,7 @@ void BundleAdjusterRay::calcJacobian(Mat &jac) ////////////////////////////////////////////////////////////////////////////// -void waveCorrect(vector &rmats) +void waveCorrect(vector &rmats, WaveCorrectKind kind) { LOGLN("Wave correcting..."); int64 t = getTickCount(); @@ -580,7 +580,14 @@ void waveCorrect(vector &rmats) } Mat 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); for (size_t i = 0; i < rmats.size(); ++i) @@ -590,6 +597,29 @@ void waveCorrect(vector &rmats) 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 tmp = R.row(0); Mat(rg0.t()).copyTo(tmp); diff --git a/modules/stitching/src/stitcher.cpp b/modules/stitching/src/stitcher.cpp index 38a26c5bed..fd45f07212 100644 --- a/modules/stitching/src/stitcher.cpp +++ b/modules/stitching/src/stitcher.cpp @@ -56,6 +56,7 @@ Stitcher Stitcher::createDefault(bool try_use_gpu) stitcher.setHorizontalStrightening(true); stitcher.setFeaturesMatcher(new detail::BestOf2NearestMatcher(try_use_gpu)); stitcher.setBundleAdjuster(new detail::BundleAdjusterRay()); + stitcher.setWaveCorrectKind(detail::WAVE_CORRECT_HORIZ); #ifndef ANDROID if (try_use_gpu && gpu::getCudaEnabledDeviceCount() > 0) @@ -208,7 +209,7 @@ Stitcher::Status Stitcher::stitch(InputArray imgs_, OutputArray pano_) vector rmats; for (size_t i = 0; i < cameras.size(); ++i) rmats.push_back(cameras[i].R); - detail::waveCorrect(rmats); + detail::waveCorrect(rmats, wave_correct_kind_); for (size_t i = 0; i < cameras.size(); ++i) cameras[i].R = rmats[i]; } diff --git a/samples/cpp/stitching_detailed.cpp b/samples/cpp/stitching_detailed.cpp index 8e780caf43..7016155634 100644 --- a/samples/cpp/stitching_detailed.cpp +++ b/samples/cpp/stitching_detailed.cpp @@ -88,8 +88,8 @@ void printUsage() " . The default mask is 'xxxxx'. If bundle\n" " adjustment doesn't support estimation of selected parameter then\n" " the respective flag is ignored.\n" - " --wave_correct (no|yes)\n" - " Perform wave effect correction. The default is 'yes'.\n" + " --wave_correct (no|horiz|vert)\n" + " Perform wave effect correction. The default is 'horiz'.\n" " --save_graph \n" " Save matches graph represented in DOT language to file.\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; string ba_cost_func = "ray"; 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; std::string save_graph_to; string warp_type = "spherical"; @@ -215,9 +216,17 @@ int parseCmdArgs(int argc, char** argv) else if (string(argv[i]) == "--wave_correct") { if (string(argv[i + 1]) == "no") - wave_correct = false; - else if (string(argv[i + 1]) == "yes") - wave_correct = true; + do_wave_correct = false; + else if (string(argv[i + 1]) == "horiz") + { + 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 { 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()); float warped_image_scale = static_cast(focals[focals.size() / 2]); - if (wave_correct) + if (do_wave_correct) { vector rmats; for (size_t i = 0; i < cameras.size(); ++i) rmats.push_back(cameras[i].R); - waveCorrect(rmats); + waveCorrect(rmats, wave_correct); for (size_t i = 0; i < cameras.size(); ++i) cameras[i].R = rmats[i]; }