CLAHE Python bindings
[profile/ivi/opencv.git] / modules / ocl / perf / precomp.hpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
14 // Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 //   * Redistribution's of source code must retain the above copyright notice,
21 //     this list of conditions and the following disclaimer.
22 //
23 //   * Redistribution's in binary form must reproduce the above copyright notice,
24 //     this list of conditions and the following disclaimer in the documentation
25 //     and/or other oclMaterials provided with the distribution.
26 //
27 //   * The name of the copyright holders may not be used to endorse or promote products
28 //     derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors as is and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42
43 #include <iomanip>
44 #include <stdexcept>
45 #include <string>
46 #include <iostream>
47 #include <cstdio>
48 #include <vector>
49 #include <numeric>
50 #include "opencv2/core/core.hpp"
51 #include "opencv2/imgproc/imgproc.hpp"
52 #include "opencv2/highgui/highgui.hpp"
53 #include "opencv2/calib3d/calib3d.hpp"
54 #include "opencv2/video/video.hpp"
55 #include "opencv2/objdetect/objdetect.hpp"
56 #include "opencv2/features2d/features2d.hpp"
57 #include "opencv2/ocl/ocl.hpp"
58 #include "opencv2/ts/ts.hpp"
59 #include "opencv2/ts/ts_perf.hpp"
60 #include "opencv2/ts/ts_gtest.h"
61
62
63 #define Min_Size 1000
64 #define Max_Size 4000
65 #define Multiple 2
66 #define TAB "    "
67
68 using namespace std;
69 using namespace cv;
70
71 void gen(Mat &mat, int rows, int cols, int type, Scalar low, Scalar high);
72 void gen(Mat &mat, int rows, int cols, int type, int low, int high, int n);
73
74 string abspath(const string &relpath);
75 int CV_CDECL cvErrorCallback(int, const char *, const char *, const char *, int, void *);
76 typedef struct
77 {
78     short x;
79     short y;
80 } COOR;
81 COOR do_meanShift(int x0, int y0, uchar *sptr, uchar *dptr, int sstep,
82                   cv::Size size, int sp, int sr, int maxIter, float eps, int *tab);
83 void meanShiftProc_(const Mat &src_roi, Mat &dst_roi, Mat &dstCoor_roi,
84                     int sp, int sr, cv::TermCriteria crit);
85
86
87 template<class T1, class T2>
88 int ExpectedEQ(T1 expected, T2 actual)
89 {
90     if(expected == actual)
91         return 1;
92
93     return 0;
94 }
95
96 template<class T1>
97 int EeceptDoubleEQ(T1 expected, T1 actual)
98 {
99     testing::internal::Double lhs(expected);
100     testing::internal::Double rhs(actual);
101
102     if (lhs.AlmostEquals(rhs)) 
103     {
104         return 1;
105     }
106
107     return 0;
108 }
109
110 template<class T>
111 int AssertEQ(T expected, T actual)
112 {
113     if(expected == actual)
114     {
115         return 1;
116     }
117     return 0;
118 }
119
120 int ExceptDoubleNear(double val1, double val2, double abs_error);
121 bool match_rect(cv::Rect r1, cv::Rect r2, int threshold);
122
123 double checkNorm(const cv::Mat &m);
124 double checkNorm(const cv::Mat &m1, const cv::Mat &m2);
125 double checkSimilarity(const cv::Mat &m1, const cv::Mat &m2);
126
127 int ExpectedMatNear(cv::Mat dst, cv::Mat cpu_dst, double eps);
128 int ExceptedMatSimilar(cv::Mat dst, cv::Mat cpu_dst, double eps);
129
130 class Runnable
131 {
132 public:
133     explicit Runnable(const std::string &runname): name_(runname) {}
134     virtual ~Runnable() {}
135
136     const std::string &name() const
137     {
138         return name_;
139     }
140
141     virtual void run() = 0;
142
143 private:
144     std::string name_;
145 };
146
147 class TestSystem
148 {
149 public:
150     static TestSystem &instance()
151     {
152         static TestSystem me;
153         return me;
154     }
155
156     void setWorkingDir(const std::string &val)
157     {
158         working_dir_ = val;
159     }
160     const std::string &workingDir() const
161     {
162         return working_dir_;
163     }
164
165     void setTestFilter(const std::string &val)
166     {
167         test_filter_ = val;
168     }
169     const std::string &testFilter() const
170     {
171         return test_filter_;
172     }
173
174     void setNumIters(int num_iters)
175     {
176         num_iters_ = num_iters;
177     }
178     void setGPUWarmupIters(int num_iters)
179     {
180         gpu_warmup_iters_ = num_iters;
181     }
182     void setCPUIters(int num_iters)
183     {
184         cpu_num_iters_ = num_iters;
185     }
186
187     void setTopThreshold(double top)
188     {
189         top_ = top;
190     }
191     void setBottomThreshold(double bottom)
192     {
193         bottom_ = bottom;
194     }
195
196     void addInit(Runnable *init)
197     {
198         inits_.push_back(init);
199     }
200     void addTest(Runnable *test)
201     {
202         tests_.push_back(test);
203     }
204     void run();
205
206     // It's public because OpenCV callback uses it
207     void printError(const std::string &msg);
208
209     std::stringstream &startNewSubtest()
210     {
211         finishCurrentSubtest();
212         return cur_subtest_description_;
213     }
214
215     bool stop() const
216     {
217         return cur_iter_idx_ >= num_iters_;
218     }
219
220     bool cpu_stop() const
221     {
222         return cur_iter_idx_ >= cpu_num_iters_;
223     }
224
225     int get_cur_iter_idx()
226     {
227         return cur_iter_idx_;
228     }
229
230     int get_cpu_num_iters()
231     {
232         return cpu_num_iters_;
233     }
234
235     bool warmupStop()
236     {
237         return cur_warmup_idx_++ >= gpu_warmup_iters_;
238     }
239
240     void warmupComplete()
241     {
242         cur_warmup_idx_ = 0;
243     }
244
245     void cpuOn()
246     {
247         cpu_started_ = cv::getTickCount();
248     }
249     void cpuOff()
250     {
251         int64 delta = cv::getTickCount() - cpu_started_;
252         cpu_times_.push_back(delta);
253         ++cur_iter_idx_;
254     }
255     void cpuComplete()
256     {
257         cpu_elapsed_ += meanTime(cpu_times_);
258         cur_subtest_is_empty_ = false;
259         cur_iter_idx_ = 0;
260     }
261
262     void gpuOn()
263     {
264         gpu_started_ = cv::getTickCount();
265     }
266     void gpuOff()
267     {
268         int64 delta = cv::getTickCount() - gpu_started_;
269         gpu_times_.push_back(delta);
270         ++cur_iter_idx_;
271     }
272     void gpuComplete()
273     {
274         gpu_elapsed_ += meanTime(gpu_times_);
275         cur_subtest_is_empty_ = false;
276         cur_iter_idx_ = 0;
277     }
278
279     void gpufullOn()
280     {
281         gpu_full_started_ = cv::getTickCount();
282     }
283     void gpufullOff()
284     {
285         int64 delta = cv::getTickCount() - gpu_full_started_;
286         gpu_full_times_.push_back(delta);
287         ++cur_iter_idx_;
288     }
289     void gpufullComplete()
290     {
291         gpu_full_elapsed_ += meanTime(gpu_full_times_);
292         cur_subtest_is_empty_ = false;
293         cur_iter_idx_ = 0;
294     }
295
296     bool isListMode() const
297     {
298         return is_list_mode_;
299     }
300     void setListMode(bool value)
301     {
302         is_list_mode_ = value;
303     }
304
305     void setRecordName(const std::string &name)
306     {
307         recordname_ = name;
308     }
309
310     void setCurrentTest(const std::string &name)
311     {
312         itname_ = name;
313         itname_changed_ = true;
314     }
315
316     void setAccurate(int accurate, double diff)
317     {
318         is_accurate_ = accurate;
319         accurate_diff_ = diff;
320     }
321
322     void ExpectMatsNear(vector<Mat>& dst, vector<Mat>& cpu_dst, vector<double>& eps)
323     {
324         assert(dst.size() == cpu_dst.size());
325         assert(cpu_dst.size() == eps.size());
326         is_accurate_ = 1;
327         for(size_t i=0; i<dst.size(); i++)
328         {
329             double cur_diff = checkNorm(dst[i], cpu_dst[i]);
330             accurate_diff_ = max(accurate_diff_, cur_diff);
331             if(cur_diff > eps[i])
332                 is_accurate_ = 0;
333         }
334     }
335
336     void ExpectedMatNear(cv::Mat& dst, cv::Mat& cpu_dst, double eps)
337     {
338         assert(dst.type() == cpu_dst.type());
339         assert(dst.size() == cpu_dst.size());
340         accurate_diff_ = checkNorm(dst, cpu_dst);
341         if(accurate_diff_ <= eps)
342             is_accurate_ = 1;
343         else
344             is_accurate_ = 0;
345     }
346
347     void ExceptedMatSimilar(cv::Mat& dst, cv::Mat& cpu_dst, double eps)
348     {
349         assert(dst.type() == cpu_dst.type());
350         assert(dst.size() == cpu_dst.size());
351         accurate_diff_ = checkSimilarity(cpu_dst, dst);
352         if(accurate_diff_ <= eps)
353             is_accurate_ = 1;
354         else
355             is_accurate_ = 0;    
356     }
357
358     std::stringstream &getCurSubtestDescription()
359     {
360         return cur_subtest_description_;
361     }
362
363 private:
364     TestSystem():
365         cur_subtest_is_empty_(true), cpu_elapsed_(0),
366         gpu_elapsed_(0), gpu_full_elapsed_(0), speedup_total_(0.0),
367         num_subtests_called_(0),
368         speedup_faster_count_(0), speedup_slower_count_(0), speedup_equal_count_(0),
369         speedup_full_faster_count_(0), speedup_full_slower_count_(0), speedup_full_equal_count_(0), is_list_mode_(false),
370         num_iters_(10), cpu_num_iters_(2),
371         gpu_warmup_iters_(1), cur_iter_idx_(0), cur_warmup_idx_(0),
372         record_(0), recordname_("performance"), itname_changed_(true), 
373         is_accurate_(-1), accurate_diff_(0.)
374     {
375         cpu_times_.reserve(num_iters_);
376         gpu_times_.reserve(num_iters_);
377         gpu_full_times_.reserve(num_iters_);
378     }
379
380     void finishCurrentSubtest();
381     void resetCurrentSubtest()
382     {
383         cpu_elapsed_ = 0;
384         gpu_elapsed_ = 0;
385         gpu_full_elapsed_ = 0;
386         cur_subtest_description_.str("");
387         cur_subtest_is_empty_ = true;
388         cur_iter_idx_ = 0;
389         cur_warmup_idx_ = 0;
390         cpu_times_.clear();
391         gpu_times_.clear();
392         gpu_full_times_.clear();
393         is_accurate_ = -1;
394         accurate_diff_ = 0.;
395     }
396
397     double meanTime(const std::vector<int64> &samples);
398
399     void printHeading();
400     void printSummary();
401     void printMetrics(int is_accurate, double cpu_time, double gpu_time = 0.0f, double gpu_full_time = 0.0f, double speedup = 0.0f, double fullspeedup = 0.0f);
402
403     void writeHeading();
404     void writeSummary();
405     void writeMetrics(double cpu_time, double gpu_time = 0.0f, double gpu_full_time = 0.0f,
406                       double speedup = 0.0f, double fullspeedup = 0.0f,
407                       double gpu_min = 0.0f, double gpu_max = 0.0f, double std_dev = 0.0f);
408
409     std::string working_dir_;
410     std::string test_filter_;
411
412     std::vector<Runnable *> inits_;
413     std::vector<Runnable *> tests_;
414
415     std::stringstream cur_subtest_description_;
416     bool cur_subtest_is_empty_;
417
418     int64 cpu_started_;
419     int64 gpu_started_;
420     int64 gpu_full_started_;
421     double cpu_elapsed_;
422     double gpu_elapsed_;
423     double gpu_full_elapsed_;
424
425     double speedup_total_;
426     double speedup_full_total_;
427     int num_subtests_called_;
428
429     int speedup_faster_count_;
430     int speedup_slower_count_;
431     int speedup_equal_count_;
432
433     int speedup_full_faster_count_;
434     int speedup_full_slower_count_;
435     int speedup_full_equal_count_;
436
437     bool is_list_mode_;
438
439     double top_;
440     double bottom_;
441
442     int num_iters_;
443     int cpu_num_iters_;         //there's no need to set cpu running same times with gpu
444     int gpu_warmup_iters_;      //gpu warm up times, default is 1
445     int cur_iter_idx_;
446     int cur_warmup_idx_;        //current gpu warm up times
447     std::vector<int64> cpu_times_;
448     std::vector<int64> gpu_times_;
449     std::vector<int64> gpu_full_times_;
450
451     FILE *record_;
452     std::string recordname_;
453     std::string itname_;
454     bool itname_changed_;
455
456     int is_accurate_;
457     double accurate_diff_;
458 };
459
460
461 #define GLOBAL_INIT(name) \
462 struct name##_init: Runnable { \
463         name##_init(): Runnable(#name) { \
464         TestSystem::instance().addInit(this); \
465 } \
466         void run(); \
467 } name##_init_instance; \
468         void name##_init::run()
469
470
471 #define PERFTEST(name) \
472 struct name##_test: Runnable { \
473         name##_test(): Runnable(#name) { \
474         TestSystem::instance().addTest(this); \
475 } \
476         void run(); \
477 } name##_test_instance; \
478         void name##_test::run()
479
480 #define SUBTEST TestSystem::instance().startNewSubtest()
481
482 #define CPU_ON \
483         while (!TestSystem::instance().cpu_stop()) { \
484         TestSystem::instance().cpuOn()
485 #define CPU_OFF \
486         TestSystem::instance().cpuOff(); \
487         } TestSystem::instance().cpuComplete()
488
489 #define GPU_ON \
490         while (!TestSystem::instance().stop()) { \
491         TestSystem::instance().gpuOn()
492 #define GPU_OFF \
493         ocl::finish();\
494         TestSystem::instance().gpuOff(); \
495         } TestSystem::instance().gpuComplete()
496
497 #define GPU_FULL_ON \
498         while (!TestSystem::instance().stop()) { \
499         TestSystem::instance().gpufullOn()
500 #define GPU_FULL_OFF \
501         TestSystem::instance().gpufullOff(); \
502         } TestSystem::instance().gpufullComplete()
503
504 #define WARMUP_ON \
505         while (!TestSystem::instance().warmupStop()) {
506 #define WARMUP_OFF \
507         ocl::finish();\
508         } TestSystem::instance().warmupComplete()