f448b1c0dd096839a107c54671fe5cbb893c98e0
[profile/ivi/opencv.git] / modules / ts / include / opencv2 / ts / ts_perf.hpp
1 #ifndef __OPENCV_TS_PERF_HPP__\r
2 #define __OPENCV_TS_PERF_HPP__\r
3 \r
4 #include "opencv2/core/core.hpp"\r
5 #include "ts_gtest.h"\r
6 \r
7 #ifdef HAVE_TBB\r
8 #include "tbb/task_scheduler_init.h"\r
9 #endif\r
10 \r
11 #if defined(ANDROID) && defined(USE_ANDROID_LOGGING)\r
12 #include <android/log.h>\r
13 \r
14 #define PERF_TESTS_LOG_TAG "OpenCV_perf"\r
15 #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, PERF_TESTS_LOG_TAG, __VA_ARGS__))\r
16 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, PERF_TESTS_LOG_TAG, __VA_ARGS__))\r
17 #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, PERF_TESTS_LOG_TAG, __VA_ARGS__))\r
18 #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, PERF_TESTS_LOG_TAG, __VA_ARGS__))\r
19 #else\r
20 #define LOGD(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)\r
21 #define LOGI(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)\r
22 #define LOGW(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)\r
23 #define LOGE(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)\r
24 #endif\r
25 \r
26 \r
27 namespace perf\r
28 {\r
29 \r
30 /*****************************************************************************************\\r
31 *                Predefined typical frame sizes and typical test parameters               *\r
32 \*****************************************************************************************/\r
33 const cv::Size szQVGA = cv::Size(320, 240);\r
34 const cv::Size szVGA = cv::Size(640, 480);\r
35 const cv::Size szSVGA = cv::Size(800, 600);\r
36 const cv::Size szXGA = cv::Size(1024, 768);\r
37 const cv::Size szSXGA = cv::Size(1280, 1024);\r
38 \r
39 const cv::Size sznHD = cv::Size(640, 360);\r
40 const cv::Size szqHD = cv::Size(960, 540);\r
41 const cv::Size sz720p = cv::Size(1280, 720);\r
42 const cv::Size sz1080p = cv::Size(1920, 1080);\r
43 \r
44 const cv::Size sz2K = cv::Size(2048, 2048);\r
45 \r
46 const cv::Size szODD = cv::Size(127, 61);\r
47 \r
48 const cv::Size szSmall24 = cv::Size(24, 24);\r
49 const cv::Size szSmall32 = cv::Size(32, 32);\r
50 const cv::Size szSmall64 = cv::Size(64, 64);\r
51 const cv::Size szSmall128 = cv::Size(128, 128);\r
52 \r
53 #define SZ_ALL_VGA ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA)\r
54 #define SZ_ALL_GA  ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA, ::perf::szXGA, ::perf::szSXGA)\r
55 #define SZ_ALL_HD  ::testing::Values(::perf::sznHD, ::perf::szqHD, ::perf::sz720p, ::perf::sz1080p)\r
56 #define SZ_ALL_SMALL ::testing::Values(::perf::szSmall24, ::perf::szSmall32, ::perf::szSmall64, ::perf::szSmall128)\r
57 #define SZ_ALL  ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA, ::perf::szXGA, ::perf::szSXGA, ::perf::sznHD, ::perf::szqHD, ::perf::sz720p, ::perf::sz1080p)\r
58 #define SZ_TYPICAL  ::testing::Values(::perf::szVGA, ::perf::szqHD, ::perf::sz720p, ::perf::szODD)\r
59 \r
60 \r
61 #define TYPICAL_MAT_SIZES ::perf::szVGA, ::perf::sz720p, ::perf::sz1080p, ::perf::szODD\r
62 #define TYPICAL_MAT_TYPES CV_8UC1, CV_8UC4, CV_32FC1\r
63 #define TYPICAL_MATS testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( TYPICAL_MAT_TYPES ) )\r
64 #define TYPICAL_MATS_C1 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC1, CV_32FC1 ) )\r
65 #define TYPICAL_MATS_C4 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC4 ) )\r
66 \r
67 \r
68 /*****************************************************************************************\\r
69 *                MatType - printable wrapper over integer 'type' of Mat                   *\r
70 \*****************************************************************************************/\r
71 class MatType\r
72 {\r
73 public:\r
74     MatType(int val=0) : _type(val) {}\r
75     operator int() const {return _type;}\r
76 \r
77 private:\r
78     int _type;\r
79 };\r
80 \r
81 /*****************************************************************************************\\r
82 *     CV_ENUM and CV_FLAGS - macro to create printable wrappers for defines and enums     *\r
83 \*****************************************************************************************/\r
84 \r
85 #define CV_ENUM(class_name, ...) \\r
86 class CV_EXPORTS class_name {\\r
87 public:\\r
88   class_name(int val = 0) : _val(val) {}\\r
89   operator int() const {return _val;}\\r
90   void PrintTo(std::ostream* os) const {\\r
91     const int vals[] = {__VA_ARGS__};\\r
92     const char* svals = #__VA_ARGS__;\\r
93     for(int i = 0, pos = 0; i < (int)(sizeof(vals)/sizeof(int)); ++i){\\r
94       while(isspace(svals[pos]) || svals[pos] == ',') ++pos;\\r
95       int start = pos;\\r
96       while(!(isspace(svals[pos]) || svals[pos] == ',' || svals[pos] == 0)) ++pos;\\r
97       if (_val == vals[i]) {\\r
98         *os << std::string(svals + start, svals + pos);\\r
99         return;\\r
100       }\\r
101     }\\r
102     *os << "UNKNOWN";\\r
103   }\\r
104   struct Container{\\r
105     typedef class_name value_type;\\r
106       Container(class_name* first, size_t len): _begin(first), _end(first+len){}\\r
107       const class_name* begin() const {return _begin;}\\r
108       const class_name* end() const {return _end;}\\r
109     private: class_name *_begin, *_end;\\r
110   };\\r
111   static Container all(){\\r
112     static class_name vals[] = {__VA_ARGS__};\\r
113     return Container(vals, sizeof(vals)/sizeof(vals[0]));\\r
114   }\\r
115 private: int _val;\\r
116 };\\r
117 inline void PrintTo(const class_name& t, std::ostream* os) { t.PrintTo(os); }\r
118 \r
119 #define CV_FLAGS(class_name, ...) \\r
120 class CV_EXPORTS class_name {\\r
121 public:\\r
122   class_name(int val = 0) : _val(val) {}\\r
123   operator int() const {return _val;}\\r
124   void PrintTo(std::ostream* os) const {\\r
125     const int vals[] = {__VA_ARGS__};\\r
126     const char* svals = #__VA_ARGS__;\\r
127     int value = _val;\\r
128     bool first = true;\\r
129     for(int i = 0, pos = 0; i < (int)(sizeof(vals)/sizeof(int)); ++i){\\r
130       while(isspace(svals[pos]) || svals[pos] == ',') ++pos;\\r
131       int start = pos;\\r
132       while(!(isspace(svals[pos]) || svals[pos] == ',' || svals[pos] == 0)) ++pos;\\r
133       if ((value & vals[i]) == vals[i]) {\\r
134         value &= ~vals[i]; \\r
135         if (first) first = false; else *os << "|"; \\r
136         *os << std::string(svals + start, svals + pos);\\r
137         if (!value) return;\\r
138       }\\r
139     }\\r
140     if (first) *os << "UNKNOWN";\\r
141   }\\r
142 private: int _val;\\r
143 };\\r
144 inline void PrintTo(const class_name& t, std::ostream* os) { t.PrintTo(os); }\r
145 \r
146 CV_ENUM(MatDepth, CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, CV_USRTYPE1)\r
147 \r
148 /*****************************************************************************************\\r
149 *                 Regression control utility for performance testing                      *\r
150 \*****************************************************************************************/\r
151 class CV_EXPORTS Regression\r
152 {\r
153 public:\r
154     static Regression& add(const std::string& name, cv::InputArray array, double eps = DBL_EPSILON);\r
155     static void Init(const std::string& testSuitName, const std::string& ext = ".xml");\r
156 \r
157     Regression& operator() (const std::string& name, cv::InputArray array, double eps = DBL_EPSILON);\r
158 \r
159 private:\r
160     static Regression& instance();\r
161     Regression();\r
162     ~Regression();\r
163 \r
164     Regression(const Regression&);\r
165     Regression& operator=(const Regression&);\r
166 \r
167     cv::RNG regRNG;//own random numbers generator to make collection and verification work identical\r
168     std::string storageInPath;\r
169     std::string storageOutPath;\r
170     cv::FileStorage storageIn;\r
171     cv::FileStorage storageOut;\r
172     cv::FileNode rootIn;\r
173     std::string currentTestNodeName;\r
174     cv::FileStorage& write();\r
175 \r
176     static std::string getCurrentTestNodeName();\r
177     static bool isVector(cv::InputArray a);\r
178     static double getElem(cv::Mat& m, int x, int y, int cn = 0);\r
179 \r
180     void init(const std::string& testSuitName, const std::string& ext);\r
181     void write(cv::InputArray array);\r
182     void write(cv::Mat m);\r
183     void verify(cv::FileNode node, cv::InputArray array, double eps);\r
184     void verify(cv::FileNode node, cv::Mat actual, double eps, std::string argname);\r
185 };\r
186 \r
187 #define SANITY_CHECK(array, ...) ::perf::Regression::add(#array, array , ## __VA_ARGS__)\r
188 \r
189 \r
190 /*****************************************************************************************\\r
191 *                            Container for performance metrics                            *\r
192 \*****************************************************************************************/\r
193 typedef struct CV_EXPORTS performance_metrics\r
194 {\r
195     size_t bytesIn;\r
196     size_t bytesOut;\r
197     unsigned int samples;\r
198     unsigned int outliers;\r
199     double gmean;\r
200     double gstddev;//stddev for log(time)\r
201     double mean;\r
202     double stddev;\r
203     double median;\r
204     double min;\r
205     double frequency;\r
206     int terminationReason;\r
207 \r
208     enum\r
209     {\r
210         TERM_ITERATIONS = 0,\r
211         TERM_TIME = 1,\r
212         TERM_INTERRUPT = 2,\r
213         TERM_EXCEPTION = 3,\r
214         TERM_UNKNOWN = -1\r
215     };\r
216 \r
217     performance_metrics();\r
218 } performance_metrics;\r
219 \r
220 \r
221 /*****************************************************************************************\\r
222 *                           Base fixture for performance tests                            *\r
223 \*****************************************************************************************/\r
224 class CV_EXPORTS TestBase: public ::testing::Test\r
225 {\r
226 public:\r
227     TestBase();\r
228 \r
229     static void Init(int argc, const char* const argv[]);\r
230     static std::string getDataPath(const std::string& relativePath);\r
231 \r
232 protected:\r
233     virtual void PerfTestBody() = 0;\r
234 \r
235     virtual void SetUp();\r
236     virtual void TearDown();\r
237 \r
238     void startTimer();\r
239     void stopTimer();\r
240     bool next();\r
241 \r
242     //_declareHelper declare;\r
243 \r
244     enum\r
245     {\r
246         WARMUP_READ,\r
247         WARMUP_WRITE,\r
248         WARMUP_RNG,\r
249         WARMUP_NONE\r
250     };\r
251 \r
252     void reportMetrics(bool toJUnitXML = false);\r
253     static void warmup(cv::InputOutputArray a, int wtype = WARMUP_READ);\r
254 \r
255     performance_metrics& calcMetrics();\r
256     void RunPerfTestBody();\r
257 private:\r
258     typedef std::vector<std::pair<int, cv::Size> > SizeVector;\r
259     typedef std::vector<int64> TimeVector;\r
260 \r
261     SizeVector inputData;\r
262     SizeVector outputData;\r
263     unsigned int getTotalInputSize() const;\r
264     unsigned int getTotalOutputSize() const;\r
265 \r
266     TimeVector times;\r
267     int64 lastTime;\r
268     int64 totalTime;\r
269     int64 timeLimit;\r
270     static int64 timeLimitDefault;\r
271 \r
272     unsigned int nIters;\r
273     unsigned int currentIter;\r
274 \r
275     performance_metrics metrics;\r
276     void validateMetrics();\r
277 \r
278     static int64 _timeadjustment;\r
279     static int64 _calibrate();\r
280 \r
281     static void warmup_impl(cv::Mat m, int wtype);\r
282     static int getSizeInBytes(cv::InputArray a);\r
283     static cv::Size getSize(cv::InputArray a);\r
284     static void declareArray(SizeVector& sizes, cv::InputOutputArray a, int wtype = 0);\r
285 \r
286     class CV_EXPORTS _declareHelper\r
287     {\r
288     public:\r
289         _declareHelper& in(cv::InputOutputArray a1, int wtype = WARMUP_READ);\r
290         _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, int wtype = WARMUP_READ);\r
291         _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, int wtype = WARMUP_READ);\r
292         _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, int wtype = WARMUP_READ);\r
293 \r
294         _declareHelper& out(cv::InputOutputArray a1, int wtype = WARMUP_WRITE);\r
295         _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, int wtype = WARMUP_WRITE);\r
296         _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, int wtype = WARMUP_WRITE);\r
297         _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, int wtype = WARMUP_WRITE);\r
298 \r
299         _declareHelper& iterations(int n);\r
300         _declareHelper& time(double timeLimitSecs);\r
301         _declareHelper& tbb_threads(int n = -1);\r
302     private:\r
303         TestBase* test;\r
304         _declareHelper(TestBase* t);\r
305         _declareHelper(const _declareHelper&);\r
306         _declareHelper& operator=(const _declareHelper&);\r
307         friend class TestBase;\r
308     };\r
309     friend class _declareHelper;\r
310 \r
311 #ifdef HAVE_TBB\r
312     cv::Ptr<tbb::task_scheduler_init> p_tbb_initializer;\r
313 #endif\r
314 \r
315 public:\r
316     _declareHelper declare;\r
317 };\r
318 \r
319 template<typename T> class TestBaseWithParam: public TestBase, public ::testing::WithParamInterface<T> {};\r
320 \r
321 typedef std::tr1::tuple<cv::Size, MatType> Size_MatType_t;\r
322 typedef TestBaseWithParam<Size_MatType_t> Size_MatType;\r
323 \r
324 /*****************************************************************************************\\r
325 *                              Print functions for googletest                             *\r
326 \*****************************************************************************************/\r
327 CV_EXPORTS void PrintTo(const MatType& t, std::ostream* os);\r
328 \r
329 } //namespace perf\r
330 \r
331 namespace cv\r
332 {\r
333 \r
334 CV_EXPORTS void PrintTo(const Size& sz, ::std::ostream* os);\r
335 \r
336 } //namespace cv\r
337 \r
338 \r
339 /*****************************************************************************************\\r
340 *                        Macro definitions for performance tests                          *\r
341 \*****************************************************************************************/\r
342 #define PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name) \\r
343   test_case_name##_##test_name##_perf_namespace_proxy\r
344 \r
345 // Defines a performance test.\r
346 //\r
347 // The first parameter is the name of the test case, and the second\r
348 // parameter is the name of the test within the test case.\r
349 //\r
350 // The user should put his test code between braces after using this\r
351 // macro.  Example:\r
352 //\r
353 //   PERF_TEST(FooTest, InitializesCorrectly) {\r
354 //     Foo foo;\r
355 //     EXPECT_TRUE(foo.StatusIsOK());\r
356 //   }\r
357 #define PERF_TEST(test_case_name, test_name)\\r
358     namespace PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name) {\\r
359      class TestBase {/*compile error for this class means that you are trying to use perf::TestBase as a fixture*/};\\r
360      class test_case_name : public ::perf::TestBase {\\r
361       public:\\r
362        test_case_name() {}\\r
363       protected:\\r
364        virtual void PerfTestBody();\\r
365      };\\r
366      TEST_F(test_case_name, test_name){ RunPerfTestBody(); }\\r
367     }\\r
368     void PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name)::test_case_name::PerfTestBody()\r
369 \r
370 // Defines a performance test that uses a test fixture.\r
371 //\r
372 // The first parameter is the name of the test fixture class, which\r
373 // also doubles as the test case name.  The second parameter is the\r
374 // name of the test within the test case.\r
375 //\r
376 // A test fixture class must be declared earlier.  The user should put\r
377 // his test code between braces after using this macro.  Example:\r
378 //\r
379 //   class FooTest : public ::perf::TestBase {\r
380 //    protected:\r
381 //     virtual void SetUp() { TestBase::SetUp(); b_.AddElement(3); }\r
382 //\r
383 //     Foo a_;\r
384 //     Foo b_;\r
385 //   };\r
386 //\r
387 //   PERF_TEST_F(FooTest, InitializesCorrectly) {\r
388 //     EXPECT_TRUE(a_.StatusIsOK());\r
389 //   }\r
390 //\r
391 //   PERF_TEST_F(FooTest, ReturnsElementCountCorrectly) {\r
392 //     EXPECT_EQ(0, a_.size());\r
393 //     EXPECT_EQ(1, b_.size());\r
394 //   }\r
395 #define PERF_TEST_F(fixture, testname) \\r
396     namespace PERF_PROXY_NAMESPACE_NAME_(fixture, testname) {\\r
397      class TestBase {/*compile error for this class means that you are trying to use perf::TestBase as a fixture*/};\\r
398      class fixture : public ::fixture {\\r
399       public:\\r
400        fixture() {}\\r
401       protected:\\r
402        virtual void PerfTestBody();\\r
403      };\\r
404      TEST_F(fixture, testname){ RunPerfTestBody(); }\\r
405     }\\r
406     void PERF_PROXY_NAMESPACE_NAME_(fixture, testname)::fixture::PerfTestBody()\r
407 \r
408 // Defines a parametrized performance test.\r
409 //\r
410 // The first parameter is the name of the test fixture class, which\r
411 // also doubles as the test case name.  The second parameter is the\r
412 // name of the test within the test case.\r
413 //\r
414 // The user should put his test code between braces after using this\r
415 // macro.  Example:\r
416 //\r
417 //   typedef ::perf::TestBaseWithParam<cv::Size> FooTest;\r
418 //\r
419 //   PERF_TEST_P(FooTest, DoTestingRight, ::testing::Values(::perf::szVGA, ::perf::sz720p) {\r
420 //     cv::Mat b(GetParam(), CV_8U, cv::Scalar(10));\r
421 //     cv::Mat a(GetParam(), CV_8U, cv::Scalar(20));\r
422 //     cv::Mat c(GetParam(), CV_8U, cv::Scalar(0));\r
423 //\r
424 //     declare.in(a, b).out(c).time(0.5);\r
425 //\r
426 //     SIMPLE_TEST_CYCLE() cv::add(a, b, c);\r
427 //\r
428 //     SANITY_CHECK(c);\r
429 //   }\r
430 #define PERF_TEST_P(fixture, name, params)  \\r
431     class fixture##_##name : public ::fixture {\\r
432      public:\\r
433       fixture##_##name() {}\\r
434      protected:\\r
435       virtual void PerfTestBody();\\r
436     };\\r
437     TEST_P(fixture##_##name, name /*perf*/){ RunPerfTestBody(); }\\r
438     INSTANTIATE_TEST_CASE_P(/*none*/, fixture##_##name, params);\\r
439     void fixture##_##name::PerfTestBody()\r
440 \r
441 \r
442 #define CV_PERF_TEST_MAIN(testsuitname) \\r
443 int main(int argc, char **argv)\\r
444 {\\r
445     ::perf::Regression::Init(#testsuitname);\\r
446     ::perf::TestBase::Init(argc, argv);\\r
447     ::testing::InitGoogleTest(&argc, argv);\\r
448     return RUN_ALL_TESTS();\\r
449 }\r
450 \r
451 #define TEST_CYCLE(n) for(declare.iterations(n); startTimer(), next(); stopTimer())\r
452 #define SIMPLE_TEST_CYCLE() for(; startTimer(), next(); stopTimer())\r
453 \r
454 //flags\r
455 namespace perf\r
456 {\r
457 //GTEST_DECLARE_int32_(allowed_outliers);\r
458 } //namespace perf\r
459 \r
460 #endif //__OPENCV_TS_PERF_HPP__\r