reduced memory requirements in opencv_stitching
authorAlexey Spizhevoy <no@email>
Wed, 18 May 2011 14:52:23 +0000 (14:52 +0000)
committerAlexey Spizhevoy <no@email>
Wed, 18 May 2011 14:52:23 +0000 (14:52 +0000)
modules/stitching/autocalib.cpp
modules/stitching/blenders.cpp
modules/stitching/blenders.hpp
modules/stitching/main.cpp
modules/stitching/motion_estimators.cpp
modules/stitching/motion_estimators.hpp

index ad1ac0a..ecededd 100644 (file)
@@ -56,7 +56,7 @@ double estimateFocal(const vector<Mat> &images, const vector<ImageFeatures> &/*f
         }
     }
 
-    if (focals.size() + 1 >= images.size())
+    if (focals.size() >= 2 * (num_images - 1))
     {
         nth_element(focals.begin(), focals.end(), focals.begin() + focals.size()/2);
         return focals[focals.size()/2];
index 4ca8fc3..04cc7b9 100644 (file)
@@ -133,19 +133,20 @@ Point MultiBandBlender::blend(const vector<Mat> &src, const vector<Point> &corne
         int left = corners[img_idx].x - dst_roi.x;
         int right = dst_roi.br().x - corners[img_idx].x - src[img_idx].cols;
 
-        Mat big_src;
-        copyMakeBorder(src[img_idx], big_src, top, bottom, left, right, BORDER_REFLECT);
-        vector<Mat> src_pyr_gauss;
+        vector<Mat> src_pyr_gauss(num_bands_ + 1);
+        copyMakeBorder(src[img_idx], src_pyr_gauss[0], top, bottom, left, right, BORDER_REFLECT);
+        for (int i = 0; i < num_bands_; ++i)
+            pyrDown(src_pyr_gauss[i], src_pyr_gauss[i + 1]);
+
         vector<Mat> src_pyr_laplace;
-        createGaussPyr(big_src, num_bands_, src_pyr_gauss);
         createLaplacePyr(src_pyr_gauss, src_pyr_laplace);
 
-        Mat big_mask;
-        copyMakeBorder(masks[img_idx], big_mask, top, bottom, left, right, BORDER_CONSTANT);
-        Mat weight_map;
-        big_mask.convertTo(weight_map, CV_32F, 1./255.);
-        vector<Mat> weight_pyr_gauss;
-        createGaussPyr(weight_map, num_bands_, weight_pyr_gauss);
+        vector<Mat> weight_pyr_gauss(num_bands_ + 1);
+        Mat mask_f;
+        masks[img_idx].convertTo(mask_f, CV_32F, 1./255.);
+        copyMakeBorder(mask_f, weight_pyr_gauss[0], top, bottom, left, right, BORDER_CONSTANT);
+        for (int i = 0; i < num_bands_; ++i)
+            pyrDown(weight_pyr_gauss[i], weight_pyr_gauss[i + 1]);
 
         for (int band_idx = 0; band_idx <= num_bands_; ++band_idx)
         {
@@ -286,15 +287,6 @@ void createWeightMap(const Mat &mask, float sharpness, Mat &weight)
 }
 
 
-void createGaussPyr(const Mat &img, int num_layers, vector<Mat> &pyr)
-{
-    pyr.resize(num_layers + 1);
-    pyr[0] = img.clone();
-    for (int i = 0; i < num_layers; ++i)
-        pyrDown(pyr[i], pyr[i + 1]);
-}
-
-
 void createLaplacePyr(const vector<Mat> &pyr_gauss, vector<Mat> &pyr_laplace)
 {
     if (pyr_gauss.size() == 0)
index a2151b6..ae1b6b3 100644 (file)
@@ -63,8 +63,6 @@ void normalize(const cv::Mat& weight, cv::Mat& src);
 
 void createWeightMap(const cv::Mat& mask, float sharpness, cv::Mat& weight);
 
-void createGaussPyr(const cv::Mat& img, int num_layers, std::vector<cv::Mat>& pyr);
-
 void createLaplacePyr(const std::vector<cv::Mat>& pyr_gauss, std::vector<cv::Mat>& pyr_laplace);
 
 // Restores source image in-place. Result will be stored in pyr[0].
index 83d01a6..bbdf701 100644 (file)
@@ -35,8 +35,8 @@ int main(int argc, char* argv[])
     vector<string> img_names;\r
     vector<Mat> images;\r
     bool trygpu = true;\r
-    double work_megapix = -1;\r
-    double compose_megapix = -1;\r
+    double work_megapix = 1;\r
+    double compose_megapix = 1;\r
     int ba_space = BundleAdjuster::FOCAL_RAY_SPACE;\r
     float conf_thresh = 1.f;\r
     bool wave_correct = true;\r
@@ -47,8 +47,8 @@ int main(int argc, char* argv[])
     int blend_type = Blender::MULTI_BAND;\r
     string result_name = "result.png";\r
 \r
-    double work_scale = 1, compose_scale = 1;\r
-    bool is_work_scale_set = false, is_compose_scale_set = true;\r
+    double work_scale, compose_scale;\r
+    bool is_work_scale_set = false, is_compose_scale_set = false;\r
 \r
     if (argc == 1)\r
     {\r
@@ -85,7 +85,6 @@ int main(int argc, char* argv[])
         else if (string(argv[i]) == "--compose_megapix") \r
         {\r
             compose_megapix = atof(argv[i + 1]);\r
-            is_compose_scale_set = false;\r
             i++; \r
         }\r
         else if (string(argv[i]) == "--result")\r
@@ -195,7 +194,7 @@ int main(int argc, char* argv[])
             {\r
                 if (!is_work_scale_set)\r
                 {\r
-                    work_scale = min(1.0, sqrt(work_megapix * 1000000 / full_img.size().area()));                    \r
+                    work_scale = min(1.0, sqrt(work_megapix * 1e6 / full_img.size().area()));                    \r
                     is_work_scale_set = true;\r
                 }\r
                 Mat img;\r
@@ -224,7 +223,11 @@ int main(int argc, char* argv[])
         matcher = BestOf2NearestMatcher(true, match_conf);\r
     matcher(images, features, pairwise_matches);\r
 \r
-    leaveBiggestComponent(images, features, pairwise_matches, conf_thresh);\r
+    vector<int> indices = leaveBiggestComponent(images, features, pairwise_matches, conf_thresh);\r
+    vector<string> img_names_subset;\r
+    for (size_t i = 0; i < indices.size(); ++i)\r
+        img_names_subset.push_back(img_names[indices[i]]);\r
+    img_names = img_names_subset;\r
 \r
     num_images = static_cast<int>(images.size());\r
     if (num_images < 2)\r
@@ -271,14 +274,15 @@ int main(int argc, char* argv[])
     nth_element(focals.begin(), focals.end(), focals.begin() + focals.size() / 2);\r
     float camera_focal = static_cast<float>(focals[focals.size() / 2]);\r
 \r
-    if (work_megapix > 0 || compose_megapix > 0)\r
+    if ((work_megapix > 0 || compose_megapix > 0) \r
+        && abs(work_megapix - compose_megapix) > 1e-3)\r
     {\r
         for (int i = 0; i < num_images; ++i)\r
         {\r
             Mat full_img = imread(img_names[i]);\r
             if (!is_compose_scale_set)\r
             {\r
-                compose_scale = min(1.0, sqrt(compose_megapix * 1000000 / full_img.size().area()));                    \r
+                compose_scale = min(1.0, sqrt(compose_megapix * 1e6 / full_img.size().area()));                    \r
                 is_compose_scale_set = true;\r
             }\r
             Mat img;\r
index 90638fd..ae72b71 100644 (file)
@@ -328,8 +328,7 @@ void waveCorrect(vector<Mat> &rmats)
     SVD svd;
     svd(cov, SVD::FULL_UV);
     svd.vt.row(2).copyTo(r1);
-    if (determinant(svd.vt) < 0)
-        r1 *= -1;
+    if (determinant(svd.vt) < 0) r1 *= -1;
 
     Mat avgz = Mat::zeros(3, 1, CV_32F);
     for (size_t i = 0; i < rmats.size(); ++i)
@@ -338,8 +337,7 @@ void waveCorrect(vector<Mat> &rmats)
     normalize(r0, r0);
 
     r1.cross(r0).copyTo(r2);
-    if (determinant(R) < 0)
-        R *= -1;
+    if (determinant(R) < 0) R *= -1;
 
     for (size_t i = 0; i < rmats.size(); ++i)
         rmats[i] = R * rmats[i];
@@ -348,8 +346,8 @@ void waveCorrect(vector<Mat> &rmats)
 
 //////////////////////////////////////////////////////////////////////////////
 
-void leaveBiggestComponent(vector<Mat> &images, vector<ImageFeatures> &features, 
-                           vector<MatchesInfo> &pairwise_matches, float conf_threshold)
+vector<int> leaveBiggestComponent(vector<Mat> &images, vector<ImageFeatures> &features, 
+                                  vector<MatchesInfo> &pairwise_matches, float conf_threshold)
 {
     const int num_images = static_cast<int>(images.size());
 
@@ -393,7 +391,7 @@ void leaveBiggestComponent(vector<Mat> &images, vector<ImageFeatures> &features,
     }
 
     if (static_cast<int>(images_subset.size()) == num_images)
-        return;
+        return indices;
 
     LOG("Removed some images, because can't match them: (");
     LOG(indices_removed[0]);
@@ -403,6 +401,8 @@ void leaveBiggestComponent(vector<Mat> &images, vector<ImageFeatures> &features,
     images = images_subset;
     features = features_subset;
     pairwise_matches = pairwise_matches_subset;
+
+    return indices;
 }
 
 
index 3a782a2..3bc3f74 100644 (file)
@@ -83,8 +83,8 @@ void waveCorrect(std::vector<cv::Mat> &rmats);
 //////////////////////////////////////////////////////////////////////////////
 // Auxiliary functions
 
-void leaveBiggestComponent(std::vector<cv::Mat> &images, std::vector<ImageFeatures> &features, 
-                           std::vector<MatchesInfo> &pairwise_matches, float conf_threshold);
+std::vector<int> leaveBiggestComponent(std::vector<cv::Mat> &images, std::vector<ImageFeatures> &features, 
+                                       std::vector<MatchesInfo> &pairwise_matches, float conf_threshold);
 
 void findMaxSpanningTree(int num_images, const std::vector<MatchesInfo> &pairwise_matches, 
                          Graph &span_tree, std::vector<int> &centers);