Merge pull request #1704 from SpecLad:merge-2.4
[profile/ivi/opencv.git] / samples / ocl / stereo_match.cpp
1 #include <iostream>
2 #include <string>
3 #include <sstream>
4 #include <iomanip>
5 #include <stdexcept>
6
7 #include "opencv2/core/utility.hpp"
8 #include "opencv2/ocl/ocl.hpp"
9 #include "opencv2/highgui/highgui.hpp"
10
11 using namespace cv;
12 using namespace std;
13 using namespace ocl;
14
15
16 struct App
17 {
18     App(CommandLineParser& cmd);
19     void run();
20     void handleKey(char key);
21     void printParams() const;
22
23     void workBegin()
24     {
25         work_begin = getTickCount();
26     }
27     void workEnd()
28     {
29         int64 d = getTickCount() - work_begin;
30         double f = getTickFrequency();
31         work_fps = f / d;
32     }
33     string method_str() const
34     {
35         switch (method)
36         {
37         case BM:
38             return "BM";
39         case BP:
40             return "BP";
41         case CSBP:
42             return "CSBP";
43         }
44         return "";
45     }
46     string text() const
47     {
48         stringstream ss;
49         ss << "(" << method_str() << ") FPS: " << setiosflags(ios::left)
50            << setprecision(4) << work_fps;
51         return ss.str();
52     }
53 private:
54     bool running, write_once;
55
56     Mat left_src, right_src;
57     Mat left, right;
58     oclMat d_left, d_right;
59
60     StereoBM_OCL bm;
61     StereoBeliefPropagation bp;
62     StereoConstantSpaceBP csbp;
63
64     int64 work_begin;
65     double work_fps;
66
67     string l_img, r_img;
68     string out_img;
69     enum {BM, BP, CSBP} method;
70     int ndisp; // Max disparity + 1
71     enum {GPU, CPU} type;
72 };
73
74 int main(int argc, char** argv)
75 {
76     const char* keys =
77         "{ h | help     | false                     | print help message }"
78         "{ l | left     |                           | specify left image }"
79         "{ r | right    |                           | specify right image }"
80         "{ m | method   | BM                        | specify match method(BM/BP/CSBP) }"
81         "{ n | ndisp    | 64                        | specify number of disparity levels }"
82         "{ o | output   | stereo_match_output.jpg   | specify output path when input is images}";
83
84     CommandLineParser cmd(argc, argv, keys);
85     if (cmd.get<bool>("help"))
86     {
87         cout << "Available options:" << endl;
88         cmd.printMessage();
89         return 0;
90     }
91
92     try
93     {
94         App app(cmd);
95         cout << "Device name:" << cv::ocl::Context::getContext()->getDeviceInfo().deviceName << endl;
96
97         app.run();
98     }
99     catch (const exception& e)
100     {
101         cout << "error: " << e.what() << endl;
102     }
103
104     return EXIT_SUCCESS;
105 }
106
107 App::App(CommandLineParser& cmd)
108     : running(false),method(BM)
109 {
110     cout << "stereo_match_ocl sample\n";
111     cout << "\nControls:\n"
112          << "\tesc - exit\n"
113          << "\to - save output image once\n"
114          << "\tp - print current parameters\n"
115          << "\tg - convert source images into gray\n"
116          << "\tm - change stereo match method\n"
117          << "\ts - change Sobel prefiltering flag (for BM only)\n"
118          << "\t1/q - increase/decrease maximum disparity\n"
119          << "\t2/w - increase/decrease window size (for BM only)\n"
120          << "\t3/e - increase/decrease iteration count (for BP and CSBP only)\n"
121          << "\t4/r - increase/decrease level count (for BP and CSBP only)\n";
122
123     l_img = cmd.get<string>("l");
124     r_img = cmd.get<string>("r");
125     string mstr = cmd.get<string>("m");
126     if(mstr == "BM") method = BM;
127     else if(mstr == "BP") method = BP;
128     else if(mstr == "CSBP") method = CSBP;
129     else cout << "unknown method!\n";
130     ndisp = cmd.get<int>("n");
131     out_img = cmd.get<string>("o");
132     write_once = false;
133 }
134
135
136 void App::run()
137 {
138     // Load images
139     left_src = imread(l_img);
140     right_src = imread(r_img);
141     if (left_src.empty()) throw runtime_error("can't open file \"" + l_img + "\"");
142     if (right_src.empty()) throw runtime_error("can't open file \"" + r_img + "\"");
143
144     cvtColor(left_src, left, COLOR_BGR2GRAY);
145     cvtColor(right_src, right, COLOR_BGR2GRAY);
146
147     d_left.upload(left);
148     d_right.upload(right);
149
150     imshow("left", left);
151     imshow("right", right);
152
153     // Set common parameters
154     bm.ndisp = ndisp;
155     bp.ndisp = ndisp;
156     csbp.ndisp = ndisp;
157
158     cout << endl;
159     printParams();
160
161     running = true;
162     while (running)
163     {
164         // Prepare disparity map of specified type
165         Mat disp;
166         oclMat d_disp;
167         workBegin();
168         switch (method)
169         {
170         case BM:
171             if (d_left.channels() > 1 || d_right.channels() > 1)
172             {
173                 cout << "BM doesn't support color images\n";
174                 cvtColor(left_src, left, COLOR_BGR2GRAY);
175                 cvtColor(right_src, right, COLOR_BGR2GRAY);
176                 cout << "image_channels: " << left.channels() << endl;
177                 d_left.upload(left);
178                 d_right.upload(right);
179                 imshow("left", left);
180                 imshow("right", right);
181             }
182             bm(d_left, d_right, d_disp);
183             break;
184         case BP:
185             bp(d_left, d_right, d_disp);
186             break;
187         case CSBP:
188             csbp(d_left, d_right, d_disp);
189             break;
190         }
191
192         // Show results
193         d_disp.download(disp);
194         workEnd();
195
196         if (method != BM)
197         {
198             disp.convertTo(disp, 0);
199         }
200         putText(disp, text(), Point(5, 25), FONT_HERSHEY_SIMPLEX, 1.0, Scalar::all(255));
201         imshow("disparity", disp);
202         if(write_once)
203         {
204             imwrite(out_img, disp);
205             write_once = false;
206         }
207         handleKey((char)waitKey(3));
208     }
209 }
210
211
212 void App::printParams() const
213 {
214     cout << "--- Parameters ---\n";
215     cout << "image_size: (" << left.cols << ", " << left.rows << ")\n";
216     cout << "image_channels: " << left.channels() << endl;
217     cout << "method: " << method_str() << endl
218          << "ndisp: " << ndisp << endl;
219     switch (method)
220     {
221     case BM:
222         cout << "win_size: " << bm.winSize << endl;
223         cout << "prefilter_sobel: " << bm.preset << endl;
224         break;
225     case BP:
226         cout << "iter_count: " << bp.iters << endl;
227         cout << "level_count: " << bp.levels << endl;
228         break;
229     case CSBP:
230         cout << "iter_count: " << csbp.iters << endl;
231         cout << "level_count: " << csbp.levels << endl;
232         break;
233     }
234     cout << endl;
235 }
236
237
238 void App::handleKey(char key)
239 {
240     switch (key)
241     {
242     case 27:
243         running = false;
244         break;
245     case 'p':
246     case 'P':
247         printParams();
248         break;
249     case 'g':
250     case 'G':
251         if (left.channels() == 1 && method != BM)
252         {
253             left = left_src;
254             right = right_src;
255         }
256         else
257         {
258             cvtColor(left_src, left, COLOR_BGR2GRAY);
259             cvtColor(right_src, right, COLOR_BGR2GRAY);
260         }
261         d_left.upload(left);
262         d_right.upload(right);
263         cout << "image_channels: " << left.channels() << endl;
264         imshow("left", left);
265         imshow("right", right);
266         break;
267     case 'm':
268     case 'M':
269         switch (method)
270         {
271         case BM:
272             method = BP;
273             break;
274         case BP:
275             method = CSBP;
276             break;
277         case CSBP:
278             method = BM;
279             break;
280         }
281         cout << "method: " << method_str() << endl;
282         break;
283     case 's':
284     case 'S':
285         if (method == BM)
286         {
287             switch (bm.preset)
288             {
289             case StereoBM_OCL::BASIC_PRESET:
290                 bm.preset = StereoBM_OCL::PREFILTER_XSOBEL;
291                 break;
292             case StereoBM_OCL::PREFILTER_XSOBEL:
293                 bm.preset = StereoBM_OCL::BASIC_PRESET;
294                 break;
295             }
296             cout << "prefilter_sobel: " << bm.preset << endl;
297         }
298         break;
299     case '1':
300         ndisp == 1 ? ndisp = 8 : ndisp += 8;
301         cout << "ndisp: " << ndisp << endl;
302         bm.ndisp = ndisp;
303         bp.ndisp = ndisp;
304         csbp.ndisp = ndisp;
305         break;
306     case 'q':
307     case 'Q':
308         ndisp = max(ndisp - 8, 1);
309         cout << "ndisp: " << ndisp << endl;
310         bm.ndisp = ndisp;
311         bp.ndisp = ndisp;
312         csbp.ndisp = ndisp;
313         break;
314     case '2':
315         if (method == BM)
316         {
317             bm.winSize = min(bm.winSize + 1, 51);
318             cout << "win_size: " << bm.winSize << endl;
319         }
320         break;
321     case 'w':
322     case 'W':
323         if (method == BM)
324         {
325             bm.winSize = max(bm.winSize - 1, 2);
326             cout << "win_size: " << bm.winSize << endl;
327         }
328         break;
329     case '3':
330         if (method == BP)
331         {
332             bp.iters += 1;
333             cout << "iter_count: " << bp.iters << endl;
334         }
335         else if (method == CSBP)
336         {
337             csbp.iters += 1;
338             cout << "iter_count: " << csbp.iters << endl;
339         }
340         break;
341     case 'e':
342     case 'E':
343         if (method == BP)
344         {
345             bp.iters = max(bp.iters - 1, 1);
346             cout << "iter_count: " << bp.iters << endl;
347         }
348         else if (method == CSBP)
349         {
350             csbp.iters = max(csbp.iters - 1, 1);
351             cout << "iter_count: " << csbp.iters << endl;
352         }
353         break;
354     case '4':
355         if (method == BP)
356         {
357             bp.levels += 1;
358             cout << "level_count: " << bp.levels << endl;
359         }
360         else if (method == CSBP)
361         {
362             csbp.levels += 1;
363             cout << "level_count: " << csbp.levels << endl;
364         }
365         break;
366     case 'r':
367     case 'R':
368         if (method == BP)
369         {
370             bp.levels = max(bp.levels - 1, 1);
371             cout << "level_count: " << bp.levels << endl;
372         }
373         else if (method == CSBP)
374         {
375             csbp.levels = max(csbp.levels - 1, 1);
376             cout << "level_count: " << csbp.levels << endl;
377         }
378         break;
379     case 'o':
380     case 'O':
381         write_once = true;
382         break;
383     }
384 }