added parameters controlling resolution into opencv_stitching
authorAlexey Spizhevoy <no@email>
Wed, 18 May 2011 13:21:45 +0000 (13:21 +0000)
committerAlexey Spizhevoy <no@email>
Wed, 18 May 2011 13:21:45 +0000 (13:21 +0000)
modules/stitching/main.cpp
modules/stitching/matchers.cpp
modules/stitching/matchers.hpp

index 4916503..83d01a6 100644 (file)
@@ -13,6 +13,9 @@ void printUsage()
 {\r
     cout << "Rotation model images stitcher.\n\n";\r
     cout << "Usage: opencv_stitching img1 img2 [...imgN]\n" \r
+        << "\t[--trygpu (yes|no)]\n"\r
+        << "\t[--work_megapix <float>]\n"\r
+        << "\t[--compose_megapix <float>]\n"\r
         << "\t[--matchconf <float>]\n"\r
         << "\t[--ba (ray|focal_ray)]\n"\r
         << "\t[--conf_thresh <float>]\n"\r
@@ -23,16 +26,17 @@ void printUsage()
         << "\t[--output <result_img>]\n\n";\r
     cout << "--matchconf\n"\r
         << "\tGood values are in [0.2, 0.8] range usually.\n\n";\r
-    cout << "--conf_thresh\n"\r
-        << "\tGood values are in [0.3, 1.0] range usually.\n";\r
 }\r
 \r
 int main(int argc, char* argv[])\r
 {\r
     cv::setBreakOnError(true);\r
 \r
+    vector<string> img_names;\r
     vector<Mat> images;\r
-    string result_name = "result.png";\r
+    bool trygpu = true;\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
@@ -41,6 +45,10 @@ int main(int argc, char* argv[])
     float match_conf = 0.55f;\r
     int seam_find_type = SeamFinder::VORONOI;\r
     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
 \r
     if (argc == 1)\r
     {\r
@@ -50,7 +58,37 @@ int main(int argc, char* argv[])
 \r
     for (int i = 1; i < argc; ++i)\r
     {\r
-        if (string(argv[i]) == "--result")\r
+        if (string(argv[i]) == "--work_megapix")\r
+        {\r
+            work_megapix = atof(argv[i + 1]);\r
+            break;\r
+        }\r
+    }\r
+\r
+    for (int i = 1; i < argc; ++i)\r
+    {\r
+        if (string(argv[i]) == "--trygpu")\r
+        {\r
+            if (string(argv[i + 1]) == "no")\r
+                trygpu = false;\r
+            else if (string(argv[i + 1]) == "yes")\r
+                trygpu = true;\r
+            else\r
+            {\r
+                cout << "Bad --trygpu flag value\n";\r
+                return -1;\r
+            }\r
+            i++;\r
+        }\r
+        else if (string(argv[i]) == "--work_megapix") \r
+            i++; \r
+        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
         {\r
             result_name = argv[i + 1];\r
             i++;\r
@@ -87,7 +125,7 @@ int main(int argc, char* argv[])
                 wave_correct = true;\r
             else\r
             {\r
-                cout << "Bad wave correct flag value\n";\r
+                cout << "Bad --wavecorrect flag value\n";\r
                 return -1;\r
             }\r
             i++;\r
@@ -144,13 +182,26 @@ int main(int argc, char* argv[])
         }\r
         else\r
         {\r
-            Mat img = imread(argv[i]);\r
-            if (img.empty())\r
+            img_names.push_back(argv[i]);\r
+            Mat full_img = imread(argv[i]);\r
+            if (full_img.empty())\r
             {\r
                 cout << "Can't open image " << argv[i] << endl;\r
                 return -1;\r
             }\r
-            images.push_back(img);\r
+            if (work_megapix < 0)\r
+                images.push_back(full_img);\r
+            else\r
+            {\r
+                if (!is_work_scale_set)\r
+                {\r
+                    work_scale = min(1.0, sqrt(work_megapix * 1000000 / full_img.size().area()));                    \r
+                    is_work_scale_set = true;\r
+                }\r
+                Mat img;\r
+                resize(full_img, img, Size(), work_scale, work_scale);\r
+                images.push_back(img);\r
+            }\r
         }\r
     }\r
 \r
@@ -163,18 +214,24 @@ int main(int argc, char* argv[])
 \r
     LOGLN("Finding features...");\r
     vector<ImageFeatures> features;\r
-    SurfFeaturesFinder finder;\r
+    SurfFeaturesFinder finder(trygpu);\r
     finder(images, features);\r
 \r
     LOGLN("Pairwise matching...");\r
     vector<MatchesInfo> pairwise_matches;\r
-    BestOf2NearestMatcher matcher;\r
+    BestOf2NearestMatcher matcher(trygpu);\r
     if (user_match_conf)\r
         matcher = BestOf2NearestMatcher(true, match_conf);\r
     matcher(images, features, pairwise_matches);\r
 \r
     leaveBiggestComponent(images, features, pairwise_matches, conf_thresh);\r
+\r
     num_images = static_cast<int>(images.size());\r
+    if (num_images < 2)\r
+    {\r
+        cout << "Need more images\n";\r
+        return -1;\r
+    }\r
 \r
     LOGLN("Estimating rotations...");\r
     HomographyBasedEstimator estimator;\r
@@ -214,6 +271,24 @@ 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
+    {\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
+                is_compose_scale_set = true;\r
+            }\r
+            Mat img;\r
+            resize(full_img, img, Size(), compose_scale, compose_scale);\r
+            images[i] = img;\r
+            cameras[i].focal *= compose_scale / work_scale;\r
+        }\r
+        camera_focal *= static_cast<float>(compose_scale / work_scale);\r
+    }\r
+\r
     vector<Mat> masks(num_images);\r
     for (int i = 0; i < num_images; ++i)\r
     {\r
@@ -250,3 +325,4 @@ int main(int argc, char* argv[])
     LOGLN("Finished");\r
     return 0;\r
 }\r
+\r
index b17ea45..0aaa163 100644 (file)
@@ -105,10 +105,10 @@ namespace
     }
 }
 
-SurfFeaturesFinder::SurfFeaturesFinder(bool gpu_hint, double hess_thresh, int num_octaves, int num_layers, 
+SurfFeaturesFinder::SurfFeaturesFinder(bool try_use_gpu, double hess_thresh, int num_octaves, int num_layers, 
                                        int num_octaves_descr, int num_layers_descr)
 {
-    if (gpu_hint && getCudaEnabledDeviceCount() > 0)
+    if (try_use_gpu && getCudaEnabledDeviceCount() > 0)
         impl_ = new GpuSurfFeaturesFinder(hess_thresh, num_octaves, num_layers, num_octaves_descr, num_layers_descr);
     else
         impl_ = new CpuSurfFeaturesFinder(hess_thresh, num_octaves, num_layers, num_octaves_descr, num_layers_descr);
@@ -274,9 +274,9 @@ namespace
     }
 }
 
-BestOf2NearestMatcher::BestOf2NearestMatcher(bool gpu_hint, float match_conf, int num_matches_thresh1, int num_matches_thresh2)
+BestOf2NearestMatcher::BestOf2NearestMatcher(bool try_use_gpu, float match_conf, int num_matches_thresh1, int num_matches_thresh2)
 {
-    if (gpu_hint && getCudaEnabledDeviceCount() > 0)
+    if (try_use_gpu && getCudaEnabledDeviceCount() > 0)
         impl_ = new GpuMatcher(match_conf);
     else
         impl_ = new CpuMatcher(match_conf);
index c3788d0..9ebc5f2 100644 (file)
@@ -26,7 +26,7 @@ protected:
 class SurfFeaturesFinder : public FeaturesFinder
 {
 public:
-    explicit SurfFeaturesFinder(bool gpu_hint = true, double hess_thresh = 500.0, 
+    explicit SurfFeaturesFinder(bool try_use_gpu = true, double hess_thresh = 500.0, 
                                 int num_octaves = 3, int num_layers = 4, 
                                 int num_octaves_descr = 4, int num_layers_descr = 2);
 
@@ -70,7 +70,7 @@ protected:
 class BestOf2NearestMatcher : public FeaturesMatcher
 {
 public:
-    explicit BestOf2NearestMatcher(bool gpu_hint = true, float match_conf = 0.55f, int num_matches_thresh1 = 5, int num_matches_thresh2 = 5);
+    explicit BestOf2NearestMatcher(bool try_use_gpu = true, float match_conf = 0.55f, int num_matches_thresh1 = 5, int num_matches_thresh2 = 5);
 
 protected:
     void match(const cv::Mat &img1, const ImageFeatures &features1, const cv::Mat &img2, const ImageFeatures &features2,