Merge pull request #1263 from abidrahmank:pyCLAHE_24
[profile/ivi/opencv.git] / modules / ocl / perf / 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 #ifndef __OPENCV_PERF_PRECOMP_HPP__
44 #define __OPENCV_PERF_PRECOMP_HPP__
45
46 #include <iomanip>
47 #include <stdexcept>
48 #include <string>
49 #include <iostream>
50 #include <cstdio>
51 #include <vector>
52 #include <numeric>
53 #include "opencv2/core/core.hpp"
54 #include "opencv2/imgproc/imgproc.hpp"
55 #include "opencv2/highgui/highgui.hpp"
56 #include "opencv2/calib3d/calib3d.hpp"
57 #include "opencv2/video/video.hpp"
58 #include "opencv2/objdetect/objdetect.hpp"
59 #include "opencv2/features2d/features2d.hpp"
60 #include "opencv2/ocl/ocl.hpp"
61 #include "opencv2/ts/ts.hpp"
62 #include "opencv2/ts/ts_perf.hpp"
63 #include "opencv2/ts/ts_gtest.h"
64
65
66 #define Min_Size 1000
67 #define Max_Size 4000
68 #define Multiple 2
69 #define TAB "    "
70
71 using namespace std;
72 using namespace cv;
73
74 void gen(Mat &mat, int rows, int cols, int type, Scalar low, Scalar high);
75 void gen(Mat &mat, int rows, int cols, int type, int low, int high, int n);
76
77 string abspath(const string &relpath);
78 int CV_CDECL cvErrorCallback(int, const char *, const char *, const char *, int, void *);
79 typedef struct
80 {
81     short x;
82     short y;
83 } COOR;
84 COOR do_meanShift(int x0, int y0, uchar *sptr, uchar *dptr, int sstep,
85                   cv::Size size, int sp, int sr, int maxIter, float eps, int *tab);
86 void meanShiftProc_(const Mat &src_roi, Mat &dst_roi, Mat &dstCoor_roi,
87                     int sp, int sr, cv::TermCriteria crit);
88
89
90 template<class T1, class T2>
91 int ExpectedEQ(T1 expected, T2 actual)
92 {
93     if(expected == actual)
94         return 1;
95
96     return 0;
97 }
98
99 template<class T1>
100 int EeceptDoubleEQ(T1 expected, T1 actual)
101 {
102     testing::internal::Double lhs(expected);
103     testing::internal::Double rhs(actual);
104
105     if (lhs.AlmostEquals(rhs))
106     {
107         return 1;
108     }
109
110     return 0;
111 }
112
113 template<class T>
114 int AssertEQ(T expected, T actual)
115 {
116     if(expected == actual)
117     {
118         return 1;
119     }
120     return 0;
121 }
122
123 int ExceptDoubleNear(double val1, double val2, double abs_error);
124 bool match_rect(cv::Rect r1, cv::Rect r2, int threshold);
125
126 double checkNorm(const cv::Mat &m);
127 double checkNorm(const cv::Mat &m1, const cv::Mat &m2);
128 double checkSimilarity(const cv::Mat &m1, const cv::Mat &m2);
129
130 int ExpectedMatNear(cv::Mat dst, cv::Mat cpu_dst, double eps);
131 int ExceptedMatSimilar(cv::Mat dst, cv::Mat cpu_dst, double eps);
132
133 class Runnable
134 {
135 public:
136     explicit Runnable(const std::string &runname): name_(runname) {}
137     virtual ~Runnable() {}
138
139     const std::string &name() const
140     {
141         return name_;
142     }
143
144     virtual void run() = 0;
145
146 private:
147     std::string name_;
148 };
149
150 class TestSystem
151 {
152 public:
153     static TestSystem &instance()
154     {
155         static TestSystem me;
156         return me;
157     }
158
159     void setWorkingDir(const std::string &val)
160     {
161         working_dir_ = val;
162     }
163     const std::string &workingDir() const
164     {
165         return working_dir_;
166     }
167
168     void setTestFilter(const std::string &val)
169     {
170         test_filter_ = val;
171     }
172     const std::string &testFilter() const
173     {
174         return test_filter_;
175     }
176
177     void setNumIters(int num_iters)
178     {
179         num_iters_ = num_iters;
180     }
181     void setGPUWarmupIters(int num_iters)
182     {
183         gpu_warmup_iters_ = num_iters;
184     }
185     void setCPUIters(int num_iters)
186     {
187         cpu_num_iters_ = num_iters;
188     }
189
190     void setTopThreshold(double top)
191     {
192         top_ = top;
193     }
194     void setBottomThreshold(double bottom)
195     {
196         bottom_ = bottom;
197     }
198
199     void addInit(Runnable *init)
200     {
201         inits_.push_back(init);
202     }
203     void addTest(Runnable *test)
204     {
205         tests_.push_back(test);
206     }
207     void run();
208
209     // It's public because OpenCV callback uses it
210     void printError(const std::string &msg);
211
212     std::stringstream &startNewSubtest()
213     {
214         finishCurrentSubtest();
215         return cur_subtest_description_;
216     }
217
218     bool stop() const
219     {
220         return cur_iter_idx_ >= num_iters_;
221     }
222
223     bool cpu_stop() const
224     {
225         return cur_iter_idx_ >= cpu_num_iters_;
226     }
227
228     int get_cur_iter_idx()
229     {
230         return cur_iter_idx_;
231     }
232
233     int get_cpu_num_iters()
234     {
235         return cpu_num_iters_;
236     }
237
238     bool warmupStop()
239     {
240         return cur_warmup_idx_++ >= gpu_warmup_iters_;
241     }
242
243     void warmupComplete()
244     {
245         cur_warmup_idx_ = 0;
246     }
247
248     void cpuOn()
249     {
250         cpu_started_ = cv::getTickCount();
251     }
252     void cpuOff()
253     {
254         int64 delta = cv::getTickCount() - cpu_started_;
255         cpu_times_.push_back(delta);
256         ++cur_iter_idx_;
257     }
258     void cpuComplete()
259     {
260         cpu_elapsed_ += meanTime(cpu_times_);
261         cur_subtest_is_empty_ = false;
262         cur_iter_idx_ = 0;
263     }
264
265     void gpuOn()
266     {
267         gpu_started_ = cv::getTickCount();
268     }
269     void gpuOff()
270     {
271         int64 delta = cv::getTickCount() - gpu_started_;
272         gpu_times_.push_back(delta);
273         ++cur_iter_idx_;
274     }
275     void gpuComplete()
276     {
277         gpu_elapsed_ += meanTime(gpu_times_);
278         cur_subtest_is_empty_ = false;
279         cur_iter_idx_ = 0;
280     }
281
282     void gpufullOn()
283     {
284         gpu_full_started_ = cv::getTickCount();
285     }
286     void gpufullOff()
287     {
288         int64 delta = cv::getTickCount() - gpu_full_started_;
289         gpu_full_times_.push_back(delta);
290         ++cur_iter_idx_;
291     }
292     void gpufullComplete()
293     {
294         gpu_full_elapsed_ += meanTime(gpu_full_times_);
295         cur_subtest_is_empty_ = false;
296         cur_iter_idx_ = 0;
297     }
298
299     bool isListMode() const
300     {
301         return is_list_mode_;
302     }
303     void setListMode(bool value)
304     {
305         is_list_mode_ = value;
306     }
307
308     void setRecordName(const std::string &name)
309     {
310         recordname_ = name;
311     }
312
313     void setCurrentTest(const std::string &name)
314     {
315         itname_ = name;
316         itname_changed_ = true;
317     }
318
319     void setAccurate(int accurate, double diff)
320     {
321         is_accurate_ = accurate;
322         accurate_diff_ = diff;
323     }
324
325     void ExpectMatsNear(vector<Mat>& dst, vector<Mat>& cpu_dst, vector<double>& eps)
326     {
327         assert(dst.size() == cpu_dst.size());
328         assert(cpu_dst.size() == eps.size());
329         is_accurate_ = 1;
330         for(size_t i=0; i<dst.size(); i++)
331         {
332             double cur_diff = checkNorm(dst[i], cpu_dst[i]);
333             accurate_diff_ = max(accurate_diff_, cur_diff);
334             if(cur_diff > eps[i])
335                 is_accurate_ = 0;
336         }
337     }
338
339     void ExpectedMatNear(cv::Mat& dst, cv::Mat& cpu_dst, double eps)
340     {
341         assert(dst.type() == cpu_dst.type());
342         assert(dst.size() == cpu_dst.size());
343         accurate_diff_ = checkNorm(dst, cpu_dst);
344         if(accurate_diff_ <= eps)
345             is_accurate_ = 1;
346         else
347             is_accurate_ = 0;
348     }
349
350     void ExceptedMatSimilar(cv::Mat& dst, cv::Mat& cpu_dst, double eps)
351     {
352         assert(dst.type() == cpu_dst.type());
353         assert(dst.size() == cpu_dst.size());
354         accurate_diff_ = checkSimilarity(cpu_dst, dst);
355         if(accurate_diff_ <= eps)
356             is_accurate_ = 1;
357         else
358             is_accurate_ = 0;
359     }
360
361     std::stringstream &getCurSubtestDescription()
362     {
363         return cur_subtest_description_;
364     }
365
366 private:
367     TestSystem():
368         cur_subtest_is_empty_(true), cpu_elapsed_(0),
369         gpu_elapsed_(0), gpu_full_elapsed_(0), speedup_total_(0.0),
370         num_subtests_called_(0),
371         speedup_faster_count_(0), speedup_slower_count_(0), speedup_equal_count_(0),
372         speedup_full_faster_count_(0), speedup_full_slower_count_(0), speedup_full_equal_count_(0), is_list_mode_(false),
373         num_iters_(10), cpu_num_iters_(2),
374         gpu_warmup_iters_(1), cur_iter_idx_(0), cur_warmup_idx_(0),
375         record_(0), recordname_("performance"), itname_changed_(true),
376         is_accurate_(-1), accurate_diff_(0.)
377     {
378         cpu_times_.reserve(num_iters_);
379         gpu_times_.reserve(num_iters_);
380         gpu_full_times_.reserve(num_iters_);
381     }
382
383     void finishCurrentSubtest();
384     void resetCurrentSubtest()
385     {
386         cpu_elapsed_ = 0;
387         gpu_elapsed_ = 0;
388         gpu_full_elapsed_ = 0;
389         cur_subtest_description_.str("");
390         cur_subtest_is_empty_ = true;
391         cur_iter_idx_ = 0;
392         cur_warmup_idx_ = 0;
393         cpu_times_.clear();
394         gpu_times_.clear();
395         gpu_full_times_.clear();
396         is_accurate_ = -1;
397         accurate_diff_ = 0.;
398     }
399
400     double meanTime(const std::vector<int64> &samples);
401
402     void printHeading();
403     void printSummary();
404     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);
405
406     void writeHeading();
407     void writeSummary();
408     void writeMetrics(double cpu_time, double gpu_time = 0.0f, double gpu_full_time = 0.0f,
409                       double speedup = 0.0f, double fullspeedup = 0.0f,
410                       double gpu_min = 0.0f, double gpu_max = 0.0f, double std_dev = 0.0f);
411
412     std::string working_dir_;
413     std::string test_filter_;
414
415     std::vector<Runnable *> inits_;
416     std::vector<Runnable *> tests_;
417
418     std::stringstream cur_subtest_description_;
419     bool cur_subtest_is_empty_;
420
421     int64 cpu_started_;
422     int64 gpu_started_;
423     int64 gpu_full_started_;
424     double cpu_elapsed_;
425     double gpu_elapsed_;
426     double gpu_full_elapsed_;
427
428     double speedup_total_;
429     double speedup_full_total_;
430     int num_subtests_called_;
431
432     int speedup_faster_count_;
433     int speedup_slower_count_;
434     int speedup_equal_count_;
435
436     int speedup_full_faster_count_;
437     int speedup_full_slower_count_;
438     int speedup_full_equal_count_;
439
440     bool is_list_mode_;
441
442     double top_;
443     double bottom_;
444
445     int num_iters_;
446     int cpu_num_iters_;         //there's no need to set cpu running same times with gpu
447     int gpu_warmup_iters_;      //gpu warm up times, default is 1
448     int cur_iter_idx_;
449     int cur_warmup_idx_;        //current gpu warm up times
450     std::vector<int64> cpu_times_;
451     std::vector<int64> gpu_times_;
452     std::vector<int64> gpu_full_times_;
453
454     FILE *record_;
455     std::string recordname_;
456     std::string itname_;
457     bool itname_changed_;
458
459     int is_accurate_;
460     double accurate_diff_;
461 };
462
463
464 #define GLOBAL_INIT(name) \
465 struct name##_init: Runnable { \
466         name##_init(): Runnable(#name) { \
467         TestSystem::instance().addInit(this); \
468 } \
469         void run(); \
470 } name##_init_instance; \
471         void name##_init::run()
472
473
474 #define PERFTEST(name) \
475 struct name##_test: Runnable { \
476         name##_test(): Runnable(#name) { \
477         TestSystem::instance().addTest(this); \
478 } \
479         void run(); \
480 } name##_test_instance; \
481         void name##_test::run()
482
483 #define SUBTEST TestSystem::instance().startNewSubtest()
484
485 #define CPU_ON \
486         while (!TestSystem::instance().cpu_stop()) { \
487         TestSystem::instance().cpuOn()
488 #define CPU_OFF \
489         TestSystem::instance().cpuOff(); \
490         } TestSystem::instance().cpuComplete()
491
492 #define GPU_ON \
493         while (!TestSystem::instance().stop()) { \
494         TestSystem::instance().gpuOn()
495 #define GPU_OFF \
496         ocl::finish();\
497         TestSystem::instance().gpuOff(); \
498         } TestSystem::instance().gpuComplete()
499
500 #define GPU_FULL_ON \
501         while (!TestSystem::instance().stop()) { \
502         TestSystem::instance().gpufullOn()
503 #define GPU_FULL_OFF \
504         TestSystem::instance().gpufullOff(); \
505         } TestSystem::instance().gpufullComplete()
506
507 #define WARMUP_ON \
508         while (!TestSystem::instance().warmupStop()) {
509 #define WARMUP_OFF \
510         ocl::finish();\
511         } TestSystem::instance().warmupComplete()
512
513 #endif