Added support of vertical straightening into stitching
authorAlexey Spizhevoy <no@email>
Sat, 24 Sep 2011 08:20:13 +0000 (08:20 +0000)
committerAlexey Spizhevoy <no@email>
Sat, 24 Sep 2011 08:20:13 +0000 (08:20 +0000)
modules/stitching/include/opencv2/stitching/detail/motion_estimators.hpp
modules/stitching/include/opencv2/stitching/detail/seam_finders.hpp
modules/stitching/include/opencv2/stitching/detail/warpers.hpp
modules/stitching/include/opencv2/stitching/stitcher.hpp
modules/stitching/src/motion_estimators.cpp
modules/stitching/src/stitcher.cpp
samples/cpp/stitching_detailed.cpp

index 65f6d23..81fff1f 100644 (file)
@@ -170,7 +170,13 @@ private:
 };\r
 \r
 \r
-void CV_EXPORTS waveCorrect(std::vector<Mat> &rmats);\r
+enum CV_EXPORTS WaveCorrectKind\r
+{\r
+    WAVE_CORRECT_HORIZ,\r
+    WAVE_CORRECT_VERT\r
+};\r
+\r
+void CV_EXPORTS waveCorrect(std::vector<Mat> &rmats, WaveCorrectKind kind);\r
 \r
 \r
 //////////////////////////////////////////////////////////////////////////////\r
index 52ffd0a..4151598 100644 (file)
@@ -100,6 +100,7 @@ public:
               std::vector<Mat> &masks);\r
 \r
 private:\r
+    // To avoid GCGraph dependency\r
     class Impl;\r
     Ptr<Impl> impl_;\r
 };\r
index 97e6a0a..12600a6 100644 (file)
@@ -129,6 +129,7 @@ protected:
     void detectResultRoi(Point &dst_tl, Point &dst_br);\r
 };\r
 \r
+\r
 #ifndef ANDROID\r
 class CV_EXPORTS PlaneWarperGpu : public PlaneWarper\r
 {\r
index 072e96f..db1bb33 100644 (file)
@@ -96,6 +96,9 @@ public:
     void setBundleAdjuster(Ptr<detail::BundleAdjusterBase> 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_; }
     const Ptr<WarperCreator> warper() const { return warper_; }
     void setWarper(Ptr<WarperCreator> warper) { warper_ = warper; }
@@ -124,6 +127,7 @@ private:
     Ptr<detail::FeaturesFinder> features_finder_;
     Ptr<detail::FeaturesMatcher> features_matcher_;
     Ptr<detail::BundleAdjusterBase> bundle_adjuster_;
+    detail::WaveCorrectKind wave_correct_kind_;
     Ptr<WarperCreator> warper_;
     Ptr<detail::ExposureCompensator> exposure_comp_;
     Ptr<detail::SeamFinder> seam_finder_;
index ea85f07..74ff579 100644 (file)
@@ -567,7 +567,7 @@ void BundleAdjusterRay::calcJacobian(Mat &jac)
 \r
 //////////////////////////////////////////////////////////////////////////////\r
 \r
-void waveCorrect(vector<Mat> &rmats)\r
+void waveCorrect(vector<Mat> &rmats, WaveCorrectKind kind)\r
 {\r
     LOGLN("Wave correcting...");\r
     int64 t = getTickCount();\r
@@ -580,7 +580,14 @@ void waveCorrect(vector<Mat> &rmats)
     }\r
     Mat eigen_vals, eigen_vecs;\r
     eigen(moment, eigen_vals, eigen_vecs);\r
-    Mat rg1 = eigen_vecs.row(2).t();\r
+\r
+    Mat rg1;\r
+    if (kind == WAVE_CORRECT_HORIZ)\r
+        rg1 = eigen_vecs.row(2).t();\r
+    else if (kind == WAVE_CORRECT_VERT)\r
+        rg1 = eigen_vecs.row(0).t();\r
+    else\r
+        CV_Error(CV_StsBadArg, "unsupported kind of wave correction");\r
 \r
     Mat img_k = Mat::zeros(3, 1, CV_32F);\r
     for (size_t i = 0; i < rmats.size(); ++i)\r
@@ -590,6 +597,29 @@ void waveCorrect(vector<Mat> &rmats)
 \r
     Mat rg2 = rg0.cross(rg1);\r
 \r
+    double conf = 0;\r
+    if (kind == WAVE_CORRECT_HORIZ)\r
+    {\r
+        for (size_t i = 0; i < rmats.size(); ++i)\r
+            conf += rg0.dot(rmats[i].col(0));\r
+        if (conf < 0)\r
+        {\r
+            rg0 *= -1;\r
+            rg1 *= -1;\r
+        }\r
+    }\r
+    else if (kind == WAVE_CORRECT_VERT)\r
+    {\r
+        for (size_t i = 0; i < rmats.size(); ++i)\r
+            conf -= rg1.dot(rmats[i].col(0));\r
+        cout << conf << endl;\r
+        if (conf < 0)\r
+        {\r
+            rg0 *= -1;\r
+            rg1 *= -1;\r
+        }\r
+    }\r
+\r
     Mat R = Mat::zeros(3, 3, CV_32F);\r
     Mat tmp = R.row(0);\r
     Mat(rg0.t()).copyTo(tmp);\r
index 38a26c5..fd45f07 100644 (file)
@@ -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<Mat> 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];
     }
index 8e780ca..7016155 100644 (file)
@@ -88,8 +88,8 @@ void printUsage()
         "      <fx><skew><ppx><aspect><ppy>. 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 <file_name>\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"
@@ -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<float>(focals[focals.size() / 2]);
 
-    if (wave_correct)
+    if (do_wave_correct)
     {
         vector<Mat> 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];
     }