Merge pull request #9024 from tomoaki0705:featureDispatchAccumulate
[platform/upstream/opencv.git] / modules / ts / include / opencv2 / ts / ts_perf.hpp
1 #ifndef OPENCV_TS_PERF_HPP
2 #define OPENCV_TS_PERF_HPP
3
4 #include "opencv2/ts.hpp"
5
6 #include "ts_gtest.h"
7 #include "ts_ext.hpp"
8
9 #include <functional>
10
11 #if !(defined(LOGD) || defined(LOGI) || defined(LOGW) || defined(LOGE))
12 # if defined(ANDROID) && defined(USE_ANDROID_LOGGING)
13 #  include <android/log.h>
14
15 #  define PERF_TESTS_LOG_TAG "OpenCV_perf"
16 #  define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, PERF_TESTS_LOG_TAG, __VA_ARGS__))
17 #  define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, PERF_TESTS_LOG_TAG, __VA_ARGS__))
18 #  define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, PERF_TESTS_LOG_TAG, __VA_ARGS__))
19 #  define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, PERF_TESTS_LOG_TAG, __VA_ARGS__))
20 # else
21 #  define LOGD(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)
22 #  define LOGI(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)
23 #  define LOGW(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)
24 #  define LOGE(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)
25 # endif
26 #endif
27
28 // declare major namespaces to avoid errors on unknown namespace
29 namespace cv { namespace cuda {} namespace ocl {} }
30
31 namespace perf
32 {
33 class TestBase;
34
35 /*****************************************************************************************\
36 *                Predefined typical frame sizes and typical test parameters               *
37 \*****************************************************************************************/
38 const cv::Size szQVGA = cv::Size(320, 240);
39 const cv::Size szVGA = cv::Size(640, 480);
40 const cv::Size szSVGA = cv::Size(800, 600);
41 const cv::Size szXGA = cv::Size(1024, 768);
42 const cv::Size szSXGA = cv::Size(1280, 1024);
43 const cv::Size szWQHD = cv::Size(2560, 1440);
44
45 const cv::Size sznHD = cv::Size(640, 360);
46 const cv::Size szqHD = cv::Size(960, 540);
47 const cv::Size sz240p = szQVGA;
48 const cv::Size sz720p = cv::Size(1280, 720);
49 const cv::Size sz1080p = cv::Size(1920, 1080);
50 const cv::Size sz1440p = szWQHD;
51 const cv::Size sz2160p = cv::Size(3840, 2160);//UHDTV1 4K
52 const cv::Size sz4320p = cv::Size(7680, 4320);//UHDTV2 8K
53
54 const cv::Size sz3MP = cv::Size(2048, 1536);
55 const cv::Size sz5MP = cv::Size(2592, 1944);
56 const cv::Size sz2K = cv::Size(2048, 2048);
57
58 const cv::Size szODD = cv::Size(127, 61);
59
60 const cv::Size szSmall24 = cv::Size(24, 24);
61 const cv::Size szSmall32 = cv::Size(32, 32);
62 const cv::Size szSmall64 = cv::Size(64, 64);
63 const cv::Size szSmall128 = cv::Size(128, 128);
64
65 #define SZ_ALL_VGA ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA)
66 #define SZ_ALL_GA  ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA, ::perf::szXGA, ::perf::szSXGA)
67 #define SZ_ALL_HD  ::testing::Values(::perf::sznHD, ::perf::szqHD, ::perf::sz720p, ::perf::sz1080p)
68 #define SZ_ALL_SMALL ::testing::Values(::perf::szSmall24, ::perf::szSmall32, ::perf::szSmall64, ::perf::szSmall128)
69 #define SZ_ALL  ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA, ::perf::szXGA, ::perf::szSXGA, ::perf::sznHD, ::perf::szqHD, ::perf::sz720p, ::perf::sz1080p)
70 #define SZ_TYPICAL  ::testing::Values(::perf::szVGA, ::perf::szqHD, ::perf::sz720p, ::perf::szODD)
71
72
73 #define TYPICAL_MAT_SIZES ::perf::szVGA, ::perf::sz720p, ::perf::sz1080p, ::perf::szODD
74 #define TYPICAL_MAT_TYPES CV_8UC1, CV_8UC4, CV_32FC1
75 #define TYPICAL_MATS testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( TYPICAL_MAT_TYPES ) )
76 #define TYPICAL_MATS_C1 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC1, CV_32FC1 ) )
77 #define TYPICAL_MATS_C4 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC4 ) )
78
79
80 /*****************************************************************************************\
81 *                MatType - printable wrapper over integer 'type' of Mat                   *
82 \*****************************************************************************************/
83 class MatType
84 {
85 public:
86     MatType(int val=0) : _type(val) {}
87     operator int() const {return _type;}
88
89 private:
90     int _type;
91 };
92
93 /*****************************************************************************************\
94 *     CV_ENUM and CV_FLAGS - macro to create printable wrappers for defines and enums     *
95 \*****************************************************************************************/
96
97 #define CV_ENUM(class_name, ...)                                                        \
98     namespace {                                                                         \
99     using namespace cv;using namespace cv::cuda; using namespace cv::ocl;               \
100     struct class_name {                                                                 \
101         class_name(int val = 0) : val_(val) {}                                          \
102         operator int() const { return val_; }                                           \
103         void PrintTo(std::ostream* os) const {                                          \
104             const int vals[] = { __VA_ARGS__ };                                         \
105             const char* svals = #__VA_ARGS__;                                           \
106             for(int i = 0, pos = 0; i < (int)(sizeof(vals)/sizeof(int)); ++i) {         \
107                 while(isspace(svals[pos]) || svals[pos] == ',') ++pos;                  \
108                 int start = pos;                                                        \
109                 while(!(isspace(svals[pos]) || svals[pos] == ',' || svals[pos] == 0))   \
110                     ++pos;                                                              \
111                 if (val_ == vals[i]) {                                                  \
112                     *os << std::string(svals + start, svals + pos);                     \
113                     return;                                                             \
114                 }                                                                       \
115             }                                                                           \
116             *os << "UNKNOWN";                                                           \
117         }                                                                               \
118         static ::testing::internal::ParamGenerator<class_name> all() {                  \
119             const class_name vals[] = { __VA_ARGS__ };                                  \
120             return ::testing::ValuesIn(vals);                                           \
121         }                                                                               \
122     private: int val_;                                                                  \
123     };                                                                                  \
124     static inline void PrintTo(const class_name& t, std::ostream* os) { t.PrintTo(os); } }
125
126 #define CV_FLAGS(class_name, ...)                                                       \
127     namespace {                                                                         \
128     struct class_name {                                                                 \
129         class_name(int val = 0) : val_(val) {}                                          \
130         operator int() const { return val_; }                                           \
131         void PrintTo(std::ostream* os) const {                                          \
132             using namespace cv;using namespace cv::cuda; using namespace cv::ocl;        \
133             const int vals[] = { __VA_ARGS__ };                                         \
134             const char* svals = #__VA_ARGS__;                                           \
135             int value = val_;                                                           \
136             bool first = true;                                                          \
137             for(int i = 0, pos = 0; i < (int)(sizeof(vals)/sizeof(int)); ++i) {         \
138                 while(isspace(svals[pos]) || svals[pos] == ',') ++pos;                  \
139                 int start = pos;                                                        \
140                 while(!(isspace(svals[pos]) || svals[pos] == ',' || svals[pos] == 0))   \
141                     ++pos;                                                              \
142                 if ((value & vals[i]) == vals[i]) {                                     \
143                     value &= ~vals[i];                                                  \
144                     if (first) first = false; else *os << "|";                          \
145                     *os << std::string(svals + start, svals + pos);                     \
146                     if (!value) return;                                                 \
147                 }                                                                       \
148             }                                                                           \
149             if (first) *os << "UNKNOWN";                                                \
150         }                                                                               \
151     private: int val_;                                                                  \
152     };                                                                                  \
153     static inline void PrintTo(const class_name& t, std::ostream* os) { t.PrintTo(os); } }
154
155 CV_ENUM(MatDepth, CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, CV_USRTYPE1)
156
157 /*****************************************************************************************\
158 *                 Regression control utility for performance testing                      *
159 \*****************************************************************************************/
160 enum ERROR_TYPE
161 {
162     ERROR_ABSOLUTE = 0,
163     ERROR_RELATIVE = 1
164 };
165
166 class CV_EXPORTS Regression
167 {
168 public:
169     static Regression& add(TestBase* test, const std::string& name, cv::InputArray array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
170     static Regression& addMoments(TestBase* test, const std::string& name, const cv::Moments & array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
171     static Regression& addKeypoints(TestBase* test, const std::string& name, const std::vector<cv::KeyPoint>& array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
172     static Regression& addMatches(TestBase* test, const std::string& name, const std::vector<cv::DMatch>& array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
173     static void Init(const std::string& testSuitName, const std::string& ext = ".xml");
174
175     Regression& operator() (const std::string& name, cv::InputArray array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
176
177 private:
178     static Regression& instance();
179     Regression();
180     ~Regression();
181
182     Regression(const Regression&);
183     Regression& operator=(const Regression&);
184
185     cv::RNG regRNG;//own random numbers generator to make collection and verification work identical
186     std::string storageInPath;
187     std::string storageOutPath;
188     cv::FileStorage storageIn;
189     cv::FileStorage storageOut;
190     cv::FileNode rootIn;
191     std::string currentTestNodeName;
192     std::string suiteName;
193
194     cv::FileStorage& write();
195
196     static std::string getCurrentTestNodeName();
197     static bool isVector(cv::InputArray a);
198     static double getElem(cv::Mat& m, int x, int y, int cn = 0);
199
200     void init(const std::string& testSuitName, const std::string& ext);
201     void write(cv::InputArray array);
202     void write(cv::Mat m);
203     void verify(cv::FileNode node, cv::InputArray array, double eps, ERROR_TYPE err);
204     void verify(cv::FileNode node, cv::Mat actual, double eps, std::string argname, ERROR_TYPE err);
205 };
206
207 #define SANITY_CHECK(array, ...) ::perf::Regression::add(this, #array, array , ## __VA_ARGS__)
208 #define SANITY_CHECK_MOMENTS(array, ...) ::perf::Regression::addMoments(this, #array, array , ## __VA_ARGS__)
209 #define SANITY_CHECK_KEYPOINTS(array, ...) ::perf::Regression::addKeypoints(this, #array, array , ## __VA_ARGS__)
210 #define SANITY_CHECK_MATCHES(array, ...) ::perf::Regression::addMatches(this, #array, array , ## __VA_ARGS__)
211 #define SANITY_CHECK_NOTHING() this->setVerified()
212
213 class CV_EXPORTS GpuPerf
214 {
215 public:
216   static bool targetDevice();
217 };
218
219 #define PERF_RUN_CUDA()  ::perf::GpuPerf::targetDevice()
220
221 /*****************************************************************************************\
222 *                            Container for performance metrics                            *
223 \*****************************************************************************************/
224 typedef struct CV_EXPORTS performance_metrics
225 {
226     size_t bytesIn;
227     size_t bytesOut;
228     unsigned int samples;
229     unsigned int outliers;
230     double gmean;
231     double gstddev;//stddev for log(time)
232     double mean;
233     double stddev;
234     double median;
235     double min;
236     double frequency;
237     int terminationReason;
238
239     enum
240     {
241         TERM_ITERATIONS = 0,
242         TERM_TIME = 1,
243         TERM_INTERRUPT = 2,
244         TERM_EXCEPTION = 3,
245         TERM_SKIP_TEST = 4, // there are some limitations and test should be skipped
246         TERM_UNKNOWN = -1
247     };
248
249     performance_metrics();
250     void clear();
251 } performance_metrics;
252
253
254 /*****************************************************************************************\
255 *                           Strategy for performance measuring                            *
256 \*****************************************************************************************/
257 enum PERF_STRATEGY
258 {
259     PERF_STRATEGY_DEFAULT = -1,
260     PERF_STRATEGY_BASE = 0,
261     PERF_STRATEGY_SIMPLE = 1
262 };
263
264
265 /*****************************************************************************************\
266 *                           Base fixture for performance tests                            *
267 \*****************************************************************************************/
268 #ifdef CV_COLLECT_IMPL_DATA
269 // Implementation collection processing class.
270 // Accumulates and shapes implementation data.
271 typedef struct ImplData
272 {
273     bool ipp;
274     bool icv;
275     bool ipp_mt;
276     bool ocl;
277     bool plain;
278     std::vector<int> implCode;
279     std::vector<cv::String> funName;
280
281     ImplData()
282     {
283         Reset();
284     }
285
286     void Reset()
287     {
288         cv::setImpl(0);
289         ipp = icv = ocl = ipp_mt = false;
290         implCode.clear();
291         funName.clear();
292     }
293
294     void GetImpl()
295     {
296         flagsToVars(cv::getImpl(implCode, funName));
297     }
298
299     std::vector<cv::String> GetCallsForImpl(int impl)
300     {
301         std::vector<cv::String> out;
302
303         for(int i = 0; i < (int)implCode.size(); i++)
304         {
305             if(impl == implCode[i])
306                 out.push_back(funName[i]);
307         }
308         return out;
309     }
310
311     // Remove duplicate entries
312     void ShapeUp()
313     {
314         std::vector<int> savedCode;
315         std::vector<cv::String> savedName;
316
317         for(int i = 0; i < (int)implCode.size(); i++)
318         {
319             bool match = false;
320             for(int j = 0; j < (int)savedCode.size(); j++)
321             {
322                 if(implCode[i] == savedCode[j] && !funName[i].compare(savedName[j]))
323                 {
324                     match = true;
325                     break;
326                 }
327             }
328             if(!match)
329             {
330                 savedCode.push_back(implCode[i]);
331                 savedName.push_back(funName[i]);
332             }
333         }
334
335         implCode = savedCode;
336         funName = savedName;
337     }
338
339     // convert flags register to more handy variables
340     void flagsToVars(int flags)
341     {
342 #if defined(HAVE_IPP_ICV_ONLY)
343         ipp    = 0;
344         icv    = ((flags&CV_IMPL_IPP) > 0);
345 #else
346         ipp    = ((flags&CV_IMPL_IPP) > 0);
347         icv    = 0;
348 #endif
349         ipp_mt = ((flags&CV_IMPL_MT) > 0);
350         ocl    = ((flags&CV_IMPL_OCL) > 0);
351         plain  = (flags == 0);
352     }
353
354 } ImplData;
355 #endif
356
357 #ifdef ENABLE_INSTRUMENTATION
358 class InstumentData
359 {
360 public:
361     static ::cv::String treeToString();
362     static void         printTree();
363 };
364 #endif
365
366 class CV_EXPORTS TestBase: public ::testing::Test
367 {
368 public:
369     TestBase();
370
371     static void Init(int argc, const char* const argv[]);
372     static void Init(const std::vector<std::string> & availableImpls,
373                      int argc, const char* const argv[]);
374     static void RecordRunParameters();
375     static std::string getDataPath(const std::string& relativePath);
376     static std::string getSelectedImpl();
377
378     static enum PERF_STRATEGY getCurrentModulePerformanceStrategy();
379     static enum PERF_STRATEGY setModulePerformanceStrategy(enum PERF_STRATEGY strategy);
380
381     class PerfSkipTestException: public cv::Exception
382     {
383     public:
384         int dummy; // workaround for MacOSX Xcode 7.3 bug (don't make class "empty")
385         PerfSkipTestException() : dummy(0) {}
386     };
387
388 protected:
389     virtual void PerfTestBody() = 0;
390
391     virtual void SetUp();
392     virtual void TearDown();
393
394     bool startTimer(); // bool is dummy for conditional loop
395     void stopTimer();
396     bool next();
397
398     PERF_STRATEGY getCurrentPerformanceStrategy() const;
399
400     enum WarmUpType
401     {
402         WARMUP_READ,
403         WARMUP_WRITE,
404         WARMUP_RNG,
405         WARMUP_NONE
406     };
407
408     void reportMetrics(bool toJUnitXML = false);
409     static void warmup(cv::InputOutputArray a, WarmUpType wtype = WARMUP_READ);
410
411     performance_metrics& calcMetrics();
412
413     void RunPerfTestBody();
414
415 #ifdef CV_COLLECT_IMPL_DATA
416     ImplData implConf;
417 #endif
418 #ifdef ENABLE_INSTRUMENTATION
419     InstumentData instrConf;
420 #endif
421
422 private:
423     typedef std::vector<std::pair<int, cv::Size> > SizeVector;
424     typedef std::vector<int64> TimeVector;
425
426     SizeVector inputData;
427     SizeVector outputData;
428     unsigned int getTotalInputSize() const;
429     unsigned int getTotalOutputSize() const;
430
431     enum PERF_STRATEGY testStrategy;
432
433     TimeVector times;
434     int64 lastTime;
435     int64 totalTime;
436     int64 timeLimit;
437     static int64 timeLimitDefault;
438     static unsigned int iterationsLimitDefault;
439
440     unsigned int minIters;
441     unsigned int nIters;
442     unsigned int currentIter;
443     unsigned int runsPerIteration;
444     unsigned int perfValidationStage;
445
446     performance_metrics metrics;
447     void validateMetrics();
448
449     static int64 _timeadjustment;
450     static int64 _calibrate();
451
452     static void warmup_impl(cv::Mat m, WarmUpType wtype);
453     static int getSizeInBytes(cv::InputArray a);
454     static cv::Size getSize(cv::InputArray a);
455     static void declareArray(SizeVector& sizes, cv::InputOutputArray a, WarmUpType wtype);
456
457     class CV_EXPORTS _declareHelper
458     {
459     public:
460         _declareHelper& in(cv::InputOutputArray a1, WarmUpType wtype = WARMUP_READ);
461         _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, WarmUpType wtype = WARMUP_READ);
462         _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, WarmUpType wtype = WARMUP_READ);
463         _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, WarmUpType wtype = WARMUP_READ);
464
465         _declareHelper& out(cv::InputOutputArray a1, WarmUpType wtype = WARMUP_WRITE);
466         _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, WarmUpType wtype = WARMUP_WRITE);
467         _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, WarmUpType wtype = WARMUP_WRITE);
468         _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, WarmUpType wtype = WARMUP_WRITE);
469
470         _declareHelper& iterations(unsigned int n);
471         _declareHelper& time(double timeLimitSecs);
472         _declareHelper& tbb_threads(int n = -1);
473         _declareHelper& runs(unsigned int runsNumber);
474
475         _declareHelper& strategy(enum PERF_STRATEGY s);
476     private:
477         TestBase* test;
478         _declareHelper(TestBase* t);
479         _declareHelper(const _declareHelper&);
480         _declareHelper& operator=(const _declareHelper&);
481         friend class TestBase;
482     };
483     friend class _declareHelper;
484
485     bool verified;
486
487 public:
488     _declareHelper declare;
489
490     void setVerified() { this->verified = true; }
491 };
492
493 template<typename T> class TestBaseWithParam: public TestBase, public ::testing::WithParamInterface<T> {};
494
495 typedef std::tr1::tuple<cv::Size, MatType> Size_MatType_t;
496 typedef TestBaseWithParam<Size_MatType_t> Size_MatType;
497
498 /*****************************************************************************************\
499 *                              Print functions for googletest                             *
500 \*****************************************************************************************/
501 CV_EXPORTS void PrintTo(const MatType& t, std::ostream* os);
502
503 } //namespace perf
504
505 namespace cv
506 {
507
508 CV_EXPORTS void PrintTo(const String& str, ::std::ostream* os);
509 CV_EXPORTS void PrintTo(const Size& sz, ::std::ostream* os);
510
511 } //namespace cv
512
513
514 /*****************************************************************************************\
515 *                        Macro definitions for performance tests                          *
516 \*****************************************************************************************/
517 #define PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name) \
518   test_case_name##_##test_name##_perf_namespace_proxy
519
520 // Defines a performance test.
521 //
522 // The first parameter is the name of the test case, and the second
523 // parameter is the name of the test within the test case.
524 //
525 // The user should put his test code between braces after using this
526 // macro.  Example:
527 //
528 //   PERF_TEST(FooTest, InitializesCorrectly) {
529 //     Foo foo;
530 //     EXPECT_TRUE(foo.StatusIsOK());
531 //   }
532 #define PERF_TEST(test_case_name, test_name)\
533     namespace PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name) {\
534      class TestBase {/*compile error for this class means that you are trying to use perf::TestBase as a fixture*/};\
535      class test_case_name : public ::perf::TestBase {\
536       public:\
537        test_case_name() {}\
538       protected:\
539        virtual void PerfTestBody();\
540      };\
541      TEST_F(test_case_name, test_name){ CV_TRACE_REGION("PERF_TEST: " #test_case_name "_" #test_name); RunPerfTestBody(); }\
542     }\
543     void PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name)::test_case_name::PerfTestBody()
544
545 // Defines a performance test that uses a test fixture.
546 //
547 // The first parameter is the name of the test fixture class, which
548 // also doubles as the test case name.  The second parameter is the
549 // name of the test within the test case.
550 //
551 // A test fixture class must be declared earlier.  The user should put
552 // his test code between braces after using this macro.  Example:
553 //
554 //   class FooTest : public ::perf::TestBase {
555 //    protected:
556 //     virtual void SetUp() { TestBase::SetUp(); b_.AddElement(3); }
557 //
558 //     Foo a_;
559 //     Foo b_;
560 //   };
561 //
562 //   PERF_TEST_F(FooTest, InitializesCorrectly) {
563 //     EXPECT_TRUE(a_.StatusIsOK());
564 //   }
565 //
566 //   PERF_TEST_F(FooTest, ReturnsElementCountCorrectly) {
567 //     EXPECT_EQ(0, a_.size());
568 //     EXPECT_EQ(1, b_.size());
569 //   }
570 #define PERF_TEST_F(fixture, testname) \
571     namespace PERF_PROXY_NAMESPACE_NAME_(fixture, testname) {\
572      class TestBase {/*compile error for this class means that you are trying to use perf::TestBase as a fixture*/};\
573      class fixture : public ::fixture {\
574       public:\
575        fixture() {}\
576       protected:\
577        virtual void PerfTestBody();\
578      };\
579      TEST_F(fixture, testname){ CV_TRACE_REGION("PERF_TEST: " #fixture "_" #testname); RunPerfTestBody(); }\
580     }\
581     void PERF_PROXY_NAMESPACE_NAME_(fixture, testname)::fixture::PerfTestBody()
582
583 // Defines a parametrized performance test.
584 //
585 // The first parameter is the name of the test fixture class, which
586 // also doubles as the test case name.  The second parameter is the
587 // name of the test within the test case.
588 //
589 // The user should put his test code between braces after using this
590 // macro.  Example:
591 //
592 //   typedef ::perf::TestBaseWithParam<cv::Size> FooTest;
593 //
594 //   PERF_TEST_P(FooTest, DoTestingRight, ::testing::Values(::perf::szVGA, ::perf::sz720p) {
595 //     cv::Mat b(GetParam(), CV_8U, cv::Scalar(10));
596 //     cv::Mat a(GetParam(), CV_8U, cv::Scalar(20));
597 //     cv::Mat c(GetParam(), CV_8U, cv::Scalar(0));
598 //
599 //     declare.in(a, b).out(c).time(0.5);
600 //
601 //     TEST_CYCLE() cv::add(a, b, c);
602 //
603 //     SANITY_CHECK(c);
604 //   }
605 #define PERF_TEST_P(fixture, name, params)  \
606     class fixture##_##name : public fixture {\
607      public:\
608       fixture##_##name() {}\
609      protected:\
610       virtual void PerfTestBody();\
611     };\
612     TEST_P(fixture##_##name, name /*perf*/){ CV_TRACE_REGION("PERF_TEST: " #fixture "_" #name); RunPerfTestBody(); }\
613     INSTANTIATE_TEST_CASE_P(/*none*/, fixture##_##name, params);\
614     void fixture##_##name::PerfTestBody()
615
616 #ifndef __CV_TEST_EXEC_ARGS
617 #if defined(_MSC_VER) && (_MSC_VER <= 1400)
618 #define __CV_TEST_EXEC_ARGS(...)    \
619     while (++argc >= (--argc,-1)) {__VA_ARGS__; break;} /*this ugly construction is needed for VS 2005*/
620 #else
621 #define __CV_TEST_EXEC_ARGS(...)    \
622     __VA_ARGS__;
623 #endif
624 #endif
625
626 #ifdef HAVE_OPENCL
627 namespace cvtest { namespace ocl {
628 void dumpOpenCLDevice();
629 }}
630 #define TEST_DUMP_OCL_INFO cvtest::ocl::dumpOpenCLDevice();
631 #else
632 #define TEST_DUMP_OCL_INFO
633 #endif
634
635
636 #define CV_PERF_TEST_MAIN_INTERNALS(modulename, impls, ...)     \
637     CV_TRACE_FUNCTION(); \
638     { CV_TRACE_REGION("INIT"); \
639     ::perf::Regression::Init(#modulename); \
640     ::perf::TestBase::Init(std::vector<std::string>(impls, impls + sizeof impls / sizeof *impls), \
641                            argc, argv); \
642     ::testing::InitGoogleTest(&argc, argv); \
643     cvtest::printVersionInfo(); \
644     ::testing::Test::RecordProperty("cv_module_name", #modulename); \
645     ::perf::TestBase::RecordRunParameters(); \
646     __CV_TEST_EXEC_ARGS(__VA_ARGS__) \
647     TEST_DUMP_OCL_INFO \
648     } \
649     return RUN_ALL_TESTS();
650
651 // impls must be an array, not a pointer; "plain" should always be one of the implementations
652 #define CV_PERF_TEST_MAIN_WITH_IMPLS(modulename, impls, ...) \
653 int main(int argc, char **argv)\
654 {\
655     CV_PERF_TEST_MAIN_INTERNALS(modulename, impls, __VA_ARGS__)\
656 }
657
658 #define CV_PERF_TEST_MAIN(modulename, ...) \
659 int main(int argc, char **argv)\
660 {\
661     const char * plain_only[] = { "plain" };\
662     CV_PERF_TEST_MAIN_INTERNALS(modulename, plain_only, __VA_ARGS__)\
663 }
664
665 //! deprecated
666 #define TEST_CYCLE_N(n) for(declare.iterations(n); next() && startTimer(); stopTimer())
667 //! deprecated
668 #define TEST_CYCLE() for(; next() && startTimer(); stopTimer())
669 //! deprecated
670 #define TEST_CYCLE_MULTIRUN(runsNum) for(declare.runs(runsNum); next() && startTimer(); stopTimer()) for(int r = 0; r < runsNum; ++r)
671
672 #define PERF_SAMPLE_BEGIN() \
673     for(; next() && startTimer(); stopTimer()) \
674     { \
675         CV_TRACE_REGION("iteration");
676 #define PERF_SAMPLE_END() \
677     }
678
679 namespace perf
680 {
681 namespace comparators
682 {
683
684 template<typename T>
685 struct CV_EXPORTS RectLess_ :
686         public std::binary_function<cv::Rect_<T>, cv::Rect_<T>, bool>
687 {
688   bool operator()(const cv::Rect_<T>& r1, const cv::Rect_<T>& r2) const
689   {
690     return r1.x < r2.x ||
691             (r1.x == r2.x && r1.y < r2.y) ||
692             (r1.x == r2.x && r1.y == r2.y && r1.width < r2.width) ||
693             (r1.x == r2.x && r1.y == r2.y && r1.width == r2.width && r1.height < r2.height);
694   }
695 };
696
697 typedef RectLess_<int> RectLess;
698
699 struct CV_EXPORTS KeypointGreater :
700         public std::binary_function<cv::KeyPoint, cv::KeyPoint, bool>
701 {
702     bool operator()(const cv::KeyPoint& kp1, const cv::KeyPoint& kp2) const
703     {
704         if (kp1.response > kp2.response) return true;
705         if (kp1.response < kp2.response) return false;
706         if (kp1.size > kp2.size) return true;
707         if (kp1.size < kp2.size) return false;
708         if (kp1.octave > kp2.octave) return true;
709         if (kp1.octave < kp2.octave) return false;
710         if (kp1.pt.y < kp2.pt.y) return false;
711         if (kp1.pt.y > kp2.pt.y) return true;
712         return kp1.pt.x < kp2.pt.x;
713     }
714 };
715
716 } //namespace comparators
717
718 void CV_EXPORTS sort(std::vector<cv::KeyPoint>& pts, cv::InputOutputArray descriptors);
719 } //namespace perf
720
721 #endif //OPENCV_TS_PERF_HPP