1 #ifndef __OPENCV_TS_PERF_HPP__ 2 #define __OPENCV_TS_PERF_HPP__ 3 4 #include "opencv2/core.hpp" 5 #include "ts_gtest.h" 6 #include "ts_ext.hpp" 7 8 #include <functional> 9 10 #if !(defined(LOGD) || defined(LOGI) || defined(LOGW) || defined(LOGE)) 11 # if defined(ANDROID) && defined(USE_ANDROID_LOGGING) 12 # include <android/log.h> 13 14 # define PERF_TESTS_LOG_TAG "OpenCV_perf" 15 # define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, PERF_TESTS_LOG_TAG, __VA_ARGS__)) 16 # define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, PERF_TESTS_LOG_TAG, __VA_ARGS__)) 17 # define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, PERF_TESTS_LOG_TAG, __VA_ARGS__)) 18 # define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, PERF_TESTS_LOG_TAG, __VA_ARGS__)) 19 # else 20 # define LOGD(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0) 21 # define LOGI(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0) 22 # define LOGW(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0) 23 # define LOGE(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0) 24 # endif 25 #endif 26 27 // declare major namespaces to avoid errors on unknown namespace 28 namespace cv { namespace cuda {} namespace ocl {} } 29 30 namespace perf 31 { 32 class TestBase; 33 34 /*****************************************************************************************\ 35 * Predefined typical frame sizes and typical test parameters * 36 \*****************************************************************************************/ 37 const cv::Size szQVGA = cv::Size(320, 240); 38 const cv::Size szVGA = cv::Size(640, 480); 39 const cv::Size szSVGA = cv::Size(800, 600); 40 const cv::Size szXGA = cv::Size(1024, 768); 41 const cv::Size szSXGA = cv::Size(1280, 1024); 42 const cv::Size szWQHD = cv::Size(2560, 1440); 43 44 const cv::Size sznHD = cv::Size(640, 360); 45 const cv::Size szqHD = cv::Size(960, 540); 46 const cv::Size sz240p = szQVGA; 47 const cv::Size sz720p = cv::Size(1280, 720); 48 const cv::Size sz1080p = cv::Size(1920, 1080); 49 const cv::Size sz1440p = szWQHD; 50 const cv::Size sz2160p = cv::Size(3840, 2160);//UHDTV1 4K 51 const cv::Size sz4320p = cv::Size(7680, 4320);//UHDTV2 8K 52 53 const cv::Size sz3MP = cv::Size(2048, 1536); 54 const cv::Size sz5MP = cv::Size(2592, 1944); 55 const cv::Size sz2K = cv::Size(2048, 2048); 56 57 const cv::Size szODD = cv::Size(127, 61); 58 59 const cv::Size szSmall24 = cv::Size(24, 24); 60 const cv::Size szSmall32 = cv::Size(32, 32); 61 const cv::Size szSmall64 = cv::Size(64, 64); 62 const cv::Size szSmall128 = cv::Size(128, 128); 63 64 #define SZ_ALL_VGA ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA) 65 #define SZ_ALL_GA ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA, ::perf::szXGA, ::perf::szSXGA) 66 #define SZ_ALL_HD ::testing::Values(::perf::sznHD, ::perf::szqHD, ::perf::sz720p, ::perf::sz1080p) 67 #define SZ_ALL_SMALL ::testing::Values(::perf::szSmall24, ::perf::szSmall32, ::perf::szSmall64, ::perf::szSmall128) 68 #define SZ_ALL ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA, ::perf::szXGA, ::perf::szSXGA, ::perf::sznHD, ::perf::szqHD, ::perf::sz720p, ::perf::sz1080p) 69 #define SZ_TYPICAL ::testing::Values(::perf::szVGA, ::perf::szqHD, ::perf::sz720p, ::perf::szODD) 70 71 72 #define TYPICAL_MAT_SIZES ::perf::szVGA, ::perf::sz720p, ::perf::sz1080p, ::perf::szODD 73 #define TYPICAL_MAT_TYPES CV_8UC1, CV_8UC4, CV_32FC1 74 #define TYPICAL_MATS testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( TYPICAL_MAT_TYPES ) ) 75 #define TYPICAL_MATS_C1 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC1, CV_32FC1 ) ) 76 #define TYPICAL_MATS_C4 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC4 ) ) 77 78 79 /*****************************************************************************************\ 80 * MatType - printable wrapper over integer 'type' of Mat * 81 \*****************************************************************************************/ 82 class MatType 83 { 84 public: MatType(int val=0)85 MatType(int val=0) : _type(val) {} operator int() const86 operator int() const {return _type;} 87 88 private: 89 int _type; 90 }; 91 92 /*****************************************************************************************\ 93 * CV_ENUM and CV_FLAGS - macro to create printable wrappers for defines and enums * 94 \*****************************************************************************************/ 95 96 #define CV_ENUM(class_name, ...) \ 97 namespace { \ 98 struct class_name { \ 99 class_name(int val = 0) : val_(val) {} \ 100 operator int() const { return val_; } \ 101 void PrintTo(std::ostream* os) const { \ 102 using namespace cv;using namespace cv::cuda; using namespace cv::ocl; \ 103 const int vals[] = { __VA_ARGS__ }; \ 104 const char* svals = #__VA_ARGS__; \ 105 for(int i = 0, pos = 0; i < (int)(sizeof(vals)/sizeof(int)); ++i) { \ 106 while(isspace(svals[pos]) || svals[pos] == ',') ++pos; \ 107 int start = pos; \ 108 while(!(isspace(svals[pos]) || svals[pos] == ',' || svals[pos] == 0)) \ 109 ++pos; \ 110 if (val_ == vals[i]) { \ 111 *os << std::string(svals + start, svals + pos); \ 112 return; \ 113 } \ 114 } \ 115 *os << "UNKNOWN"; \ 116 } \ 117 static ::testing::internal::ParamGenerator<class_name> all() { \ 118 using namespace cv;using namespace cv::cuda; using namespace cv::ocl; \ 119 static class_name vals[] = { __VA_ARGS__ }; \ 120 return ::testing::ValuesIn(vals); \ 121 } \ 122 private: int val_; \ 123 }; \ 124 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 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 ImplDataperf::ImplData281 ImplData() 282 { 283 Reset(); 284 } 285 Resetperf::ImplData286 void Reset() 287 { 288 cv::setImpl(0); 289 ipp = icv = ocl = ipp_mt = false; 290 implCode.clear(); 291 funName.clear(); 292 } 293 GetImplperf::ImplData294 void GetImpl() 295 { 296 flagsToVars(cv::getImpl(implCode, funName)); 297 } 298 GetCallsForImplperf::ImplData299 std::vector<cv::String> GetCallsForImpl(int impl) 300 { 301 std::vector<cv::String> out; 302 303 for(int i = 0; i < 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 ShapeUpperf::ImplData312 void ShapeUp() 313 { 314 std::vector<int> savedCode; 315 std::vector<cv::String> savedName; 316 317 for(int i = 0; i < implCode.size(); i++) 318 { 319 bool match = false; 320 for(int j = 0; j < 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 flagsToVarsperf::ImplData340 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 class CV_EXPORTS TestBase: public ::testing::Test 358 { 359 public: 360 TestBase(); 361 362 static void Init(int argc, const char* const argv[]); 363 static void Init(const std::vector<std::string> & availableImpls, 364 int argc, const char* const argv[]); 365 static void RecordRunParameters(); 366 static std::string getDataPath(const std::string& relativePath); 367 static std::string getSelectedImpl(); 368 369 static enum PERF_STRATEGY getCurrentModulePerformanceStrategy(); 370 static enum PERF_STRATEGY setModulePerformanceStrategy(enum PERF_STRATEGY strategy); 371 372 class PerfSkipTestException: public cv::Exception {}; 373 374 protected: 375 virtual void PerfTestBody() = 0; 376 377 virtual void SetUp(); 378 virtual void TearDown(); 379 380 void startTimer(); 381 void stopTimer(); 382 bool next(); 383 384 PERF_STRATEGY getCurrentPerformanceStrategy() const; 385 386 enum WarmUpType 387 { 388 WARMUP_READ, 389 WARMUP_WRITE, 390 WARMUP_RNG, 391 WARMUP_NONE 392 }; 393 394 void reportMetrics(bool toJUnitXML = false); 395 static void warmup(cv::InputOutputArray a, WarmUpType wtype = WARMUP_READ); 396 397 performance_metrics& calcMetrics(); 398 399 void RunPerfTestBody(); 400 401 #ifdef CV_COLLECT_IMPL_DATA 402 ImplData implConf; 403 #endif 404 private: 405 typedef std::vector<std::pair<int, cv::Size> > SizeVector; 406 typedef std::vector<int64> TimeVector; 407 408 SizeVector inputData; 409 SizeVector outputData; 410 unsigned int getTotalInputSize() const; 411 unsigned int getTotalOutputSize() const; 412 413 enum PERF_STRATEGY testStrategy; 414 415 TimeVector times; 416 int64 lastTime; 417 int64 totalTime; 418 int64 timeLimit; 419 static int64 timeLimitDefault; 420 static unsigned int iterationsLimitDefault; 421 422 unsigned int minIters; 423 unsigned int nIters; 424 unsigned int currentIter; 425 unsigned int runsPerIteration; 426 unsigned int perfValidationStage; 427 428 performance_metrics metrics; 429 void validateMetrics(); 430 431 static int64 _timeadjustment; 432 static int64 _calibrate(); 433 434 static void warmup_impl(cv::Mat m, WarmUpType wtype); 435 static int getSizeInBytes(cv::InputArray a); 436 static cv::Size getSize(cv::InputArray a); 437 static void declareArray(SizeVector& sizes, cv::InputOutputArray a, WarmUpType wtype); 438 439 class CV_EXPORTS _declareHelper 440 { 441 public: 442 _declareHelper& in(cv::InputOutputArray a1, WarmUpType wtype = WARMUP_READ); 443 _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, WarmUpType wtype = WARMUP_READ); 444 _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, WarmUpType wtype = WARMUP_READ); 445 _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, WarmUpType wtype = WARMUP_READ); 446 447 _declareHelper& out(cv::InputOutputArray a1, WarmUpType wtype = WARMUP_WRITE); 448 _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, WarmUpType wtype = WARMUP_WRITE); 449 _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, WarmUpType wtype = WARMUP_WRITE); 450 _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, WarmUpType wtype = WARMUP_WRITE); 451 452 _declareHelper& iterations(unsigned int n); 453 _declareHelper& time(double timeLimitSecs); 454 _declareHelper& tbb_threads(int n = -1); 455 _declareHelper& runs(unsigned int runsNumber); 456 457 _declareHelper& strategy(enum PERF_STRATEGY s); 458 private: 459 TestBase* test; 460 _declareHelper(TestBase* t); 461 _declareHelper(const _declareHelper&); 462 _declareHelper& operator=(const _declareHelper&); 463 friend class TestBase; 464 }; 465 friend class _declareHelper; 466 467 bool verified; 468 469 public: 470 _declareHelper declare; 471 setVerified()472 void setVerified() { this->verified = true; } 473 }; 474 475 template<typename T> class TestBaseWithParam: public TestBase, public ::testing::WithParamInterface<T> {}; 476 477 typedef std::tr1::tuple<cv::Size, MatType> Size_MatType_t; 478 typedef TestBaseWithParam<Size_MatType_t> Size_MatType; 479 480 typedef std::tr1::tuple<cv::Size, MatDepth> Size_MatDepth_t; 481 typedef TestBaseWithParam<Size_MatDepth_t> Size_MatDepth; 482 483 /*****************************************************************************************\ 484 * Print functions for googletest * 485 \*****************************************************************************************/ 486 CV_EXPORTS void PrintTo(const MatType& t, std::ostream* os); 487 488 } //namespace perf 489 490 namespace cv 491 { 492 493 CV_EXPORTS void PrintTo(const String& str, ::std::ostream* os); 494 CV_EXPORTS void PrintTo(const Size& sz, ::std::ostream* os); 495 496 } //namespace cv 497 498 499 /*****************************************************************************************\ 500 * Macro definitions for performance tests * 501 \*****************************************************************************************/ 502 #define PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name) \ 503 test_case_name##_##test_name##_perf_namespace_proxy 504 505 // Defines a performance test. 506 // 507 // The first parameter is the name of the test case, and the second 508 // parameter is the name of the test within the test case. 509 // 510 // The user should put his test code between braces after using this 511 // macro. Example: 512 // 513 // PERF_TEST(FooTest, InitializesCorrectly) { 514 // Foo foo; 515 // EXPECT_TRUE(foo.StatusIsOK()); 516 // } 517 #define PERF_TEST(test_case_name, test_name)\ 518 namespace PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name) {\ 519 class TestBase {/*compile error for this class means that you are trying to use perf::TestBase as a fixture*/};\ 520 class test_case_name : public ::perf::TestBase {\ 521 public:\ 522 test_case_name() {}\ 523 protected:\ 524 virtual void PerfTestBody();\ 525 };\ 526 TEST_F(test_case_name, test_name){ RunPerfTestBody(); }\ 527 }\ 528 void PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name)::test_case_name::PerfTestBody() 529 530 // Defines a performance test that uses a test fixture. 531 // 532 // The first parameter is the name of the test fixture class, which 533 // also doubles as the test case name. The second parameter is the 534 // name of the test within the test case. 535 // 536 // A test fixture class must be declared earlier. The user should put 537 // his test code between braces after using this macro. Example: 538 // 539 // class FooTest : public ::perf::TestBase { 540 // protected: 541 // virtual void SetUp() { TestBase::SetUp(); b_.AddElement(3); } 542 // 543 // Foo a_; 544 // Foo b_; 545 // }; 546 // 547 // PERF_TEST_F(FooTest, InitializesCorrectly) { 548 // EXPECT_TRUE(a_.StatusIsOK()); 549 // } 550 // 551 // PERF_TEST_F(FooTest, ReturnsElementCountCorrectly) { 552 // EXPECT_EQ(0, a_.size()); 553 // EXPECT_EQ(1, b_.size()); 554 // } 555 #define PERF_TEST_F(fixture, testname) \ 556 namespace PERF_PROXY_NAMESPACE_NAME_(fixture, testname) {\ 557 class TestBase {/*compile error for this class means that you are trying to use perf::TestBase as a fixture*/};\ 558 class fixture : public ::fixture {\ 559 public:\ 560 fixture() {}\ 561 protected:\ 562 virtual void PerfTestBody();\ 563 };\ 564 TEST_F(fixture, testname){ RunPerfTestBody(); }\ 565 }\ 566 void PERF_PROXY_NAMESPACE_NAME_(fixture, testname)::fixture::PerfTestBody() 567 568 // Defines a parametrized performance test. 569 // 570 // The first parameter is the name of the test fixture class, which 571 // also doubles as the test case name. The second parameter is the 572 // name of the test within the test case. 573 // 574 // The user should put his test code between braces after using this 575 // macro. Example: 576 // 577 // typedef ::perf::TestBaseWithParam<cv::Size> FooTest; 578 // 579 // PERF_TEST_P(FooTest, DoTestingRight, ::testing::Values(::perf::szVGA, ::perf::sz720p) { 580 // cv::Mat b(GetParam(), CV_8U, cv::Scalar(10)); 581 // cv::Mat a(GetParam(), CV_8U, cv::Scalar(20)); 582 // cv::Mat c(GetParam(), CV_8U, cv::Scalar(0)); 583 // 584 // declare.in(a, b).out(c).time(0.5); 585 // 586 // TEST_CYCLE() cv::add(a, b, c); 587 // 588 // SANITY_CHECK(c); 589 // } 590 #define PERF_TEST_P(fixture, name, params) \ 591 class fixture##_##name : public fixture {\ 592 public:\ 593 fixture##_##name() {}\ 594 protected:\ 595 virtual void PerfTestBody();\ 596 };\ 597 TEST_P(fixture##_##name, name /*perf*/){ RunPerfTestBody(); }\ 598 INSTANTIATE_TEST_CASE_P(/*none*/, fixture##_##name, params);\ 599 void fixture##_##name::PerfTestBody() 600 601 #ifndef __CV_TEST_EXEC_ARGS 602 #if defined(_MSC_VER) && (_MSC_VER <= 1400) 603 #define __CV_TEST_EXEC_ARGS(...) \ 604 while (++argc >= (--argc,-1)) {__VA_ARGS__; break;} /*this ugly construction is needed for VS 2005*/ 605 #else 606 #define __CV_TEST_EXEC_ARGS(...) \ 607 __VA_ARGS__; 608 #endif 609 #endif 610 611 #ifdef HAVE_OPENCL 612 namespace cvtest { namespace ocl { 613 void dumpOpenCLDevice(); 614 }} 615 #define TEST_DUMP_OCL_INFO cvtest::ocl::dumpOpenCLDevice(); 616 #else 617 #define TEST_DUMP_OCL_INFO 618 #endif 619 620 #define CV_PERF_TEST_MAIN_INTERNALS(modulename, impls, ...) \ 621 ::perf::Regression::Init(#modulename); \ 622 ::perf::TestBase::Init(std::vector<std::string>(impls, impls + sizeof impls / sizeof *impls), \ 623 argc, argv); \ 624 ::testing::InitGoogleTest(&argc, argv); \ 625 cvtest::printVersionInfo(); \ 626 ::testing::Test::RecordProperty("cv_module_name", #modulename); \ 627 ::perf::TestBase::RecordRunParameters(); \ 628 __CV_TEST_EXEC_ARGS(__VA_ARGS__) \ 629 TEST_DUMP_OCL_INFO \ 630 return RUN_ALL_TESTS(); 631 632 // impls must be an array, not a pointer; "plain" should always be one of the implementations 633 #define CV_PERF_TEST_MAIN_WITH_IMPLS(modulename, impls, ...) \ 634 int main(int argc, char **argv)\ 635 {\ 636 CV_PERF_TEST_MAIN_INTERNALS(modulename, impls, __VA_ARGS__)\ 637 } 638 639 #define CV_PERF_TEST_MAIN(modulename, ...) \ 640 int main(int argc, char **argv)\ 641 {\ 642 const char * plain_only[] = { "plain" };\ 643 CV_PERF_TEST_MAIN_INTERNALS(modulename, plain_only, __VA_ARGS__)\ 644 } 645 646 #define TEST_CYCLE_N(n) for(declare.iterations(n); startTimer(), next(); stopTimer()) 647 #define TEST_CYCLE() for(; startTimer(), next(); stopTimer()) 648 #define TEST_CYCLE_MULTIRUN(runsNum) for(declare.runs(runsNum); startTimer(), next(); stopTimer()) for(int r = 0; r < runsNum; ++r) 649 650 namespace perf 651 { 652 namespace comparators 653 { 654 655 template<typename T> 656 struct CV_EXPORTS RectLess_ : 657 public std::binary_function<cv::Rect_<T>, cv::Rect_<T>, bool> 658 { operator ()perf::comparators::RectLess_659 bool operator()(const cv::Rect_<T>& r1, const cv::Rect_<T>& r2) const 660 { 661 return r1.x < r2.x || 662 (r1.x == r2.x && r1.y < r2.y) || 663 (r1.x == r2.x && r1.y == r2.y && r1.width < r2.width) || 664 (r1.x == r2.x && r1.y == r2.y && r1.width == r2.width && r1.height < r2.height); 665 } 666 }; 667 668 typedef RectLess_<int> RectLess; 669 670 struct CV_EXPORTS KeypointGreater : 671 public std::binary_function<cv::KeyPoint, cv::KeyPoint, bool> 672 { operator ()perf::comparators::KeypointGreater673 bool operator()(const cv::KeyPoint& kp1, const cv::KeyPoint& kp2) const 674 { 675 if (kp1.response > kp2.response) return true; 676 if (kp1.response < kp2.response) return false; 677 if (kp1.size > kp2.size) return true; 678 if (kp1.size < kp2.size) return false; 679 if (kp1.octave > kp2.octave) return true; 680 if (kp1.octave < kp2.octave) return false; 681 if (kp1.pt.y < kp2.pt.y) return false; 682 if (kp1.pt.y > kp2.pt.y) return true; 683 return kp1.pt.x < kp2.pt.x; 684 } 685 }; 686 687 } //namespace comparators 688 689 void CV_EXPORTS sort(std::vector<cv::KeyPoint>& pts, cv::InputOutputArray descriptors); 690 } //namespace perf 691 692 #endif //__OPENCV_TS_PERF_HPP__ 693