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