github.com/kaydxh/golang@v0.0.131/pkg/gocv/cgo/third_path/opencv2/include/opencv2/ts/ts_perf.hpp (about)

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