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