1 
2 #include "opencv2/imgcodecs.hpp"
3 #include "opencv2/highgui.hpp"
4 #include "opencv2/stitching.hpp"
5 
6 #include <iostream>
7 
8 using namespace std;
9 using namespace cv;
10 
11 bool divide_images = false;
12 Stitcher::Mode mode = Stitcher::PANORAMA;
13 vector<Mat> imgs;
14 string result_name = "result.jpg";
15 
16 void printUsage(char** argv);
17 int parseCmdArgs(int argc, char** argv);
18 
main(int argc,char * argv[])19 int main(int argc, char* argv[])
20 {
21     int retval = parseCmdArgs(argc, argv);
22     if (retval) return EXIT_FAILURE;
23 
24     //![stitching]
25     Mat pano;
26     Ptr<Stitcher> stitcher = Stitcher::create(mode);
27     Stitcher::Status status = stitcher->stitch(imgs, pano);
28 
29     if (status != Stitcher::OK)
30     {
31         cout << "Can't stitch images, error code = " << int(status) << endl;
32         return EXIT_FAILURE;
33     }
34     //![stitching]
35 
36     imwrite(result_name, pano);
37     cout << "stitching completed successfully\n" << result_name << " saved!";
38     return EXIT_SUCCESS;
39 }
40 
41 
printUsage(char ** argv)42 void printUsage(char** argv)
43 {
44     cout <<
45          "Images stitcher.\n\n" << "Usage :\n" << argv[0] <<" [Flags] img1 img2 [...imgN]\n\n"
46          "Flags:\n"
47          "  --d3\n"
48          "      internally creates three chunks of each image to increase stitching success\n"
49          "  --mode (panorama|scans)\n"
50          "      Determines configuration of stitcher. The default is 'panorama',\n"
51          "      mode suitable for creating photo panoramas. Option 'scans' is suitable\n"
52          "      for stitching materials under affine transformation, such as scans.\n"
53          "  --output <result_img>\n"
54          "      The default is 'result.jpg'.\n\n"
55          "Example usage :\n" << argv[0] << " --d3 --mode scans img1.jpg img2.jpg\n";
56 }
57 
58 
parseCmdArgs(int argc,char ** argv)59 int parseCmdArgs(int argc, char** argv)
60 {
61     if (argc == 1)
62     {
63         printUsage(argv);
64         return EXIT_FAILURE;
65     }
66 
67     for (int i = 1; i < argc; ++i)
68     {
69         if (string(argv[i]) == "--help" || string(argv[i]) == "/?")
70         {
71             printUsage(argv);
72             return EXIT_FAILURE;
73         }
74         else if (string(argv[i]) == "--d3")
75         {
76             divide_images = true;
77         }
78         else if (string(argv[i]) == "--output")
79         {
80             result_name = argv[i + 1];
81             i++;
82         }
83         else if (string(argv[i]) == "--mode")
84         {
85             if (string(argv[i + 1]) == "panorama")
86                 mode = Stitcher::PANORAMA;
87             else if (string(argv[i + 1]) == "scans")
88                 mode = Stitcher::SCANS;
89             else
90             {
91                 cout << "Bad --mode flag value\n";
92                 return EXIT_FAILURE;
93             }
94             i++;
95         }
96         else
97         {
98             Mat img = imread(samples::findFile(argv[i]));
99             if (img.empty())
100             {
101                 cout << "Can't read image '" << argv[i] << "'\n";
102                 return EXIT_FAILURE;
103             }
104 
105             if (divide_images)
106             {
107                 Rect rect(0, 0, img.cols / 2, img.rows);
108                 imgs.push_back(img(rect).clone());
109                 rect.x = img.cols / 3;
110                 imgs.push_back(img(rect).clone());
111                 rect.x = img.cols / 2;
112                 imgs.push_back(img(rect).clone());
113             }
114             else
115                 imgs.push_back(img);
116         }
117     }
118     return EXIT_SUCCESS;
119 }
120