1 #ifndef OPENCV_TS_PERF_HPP
2 #define OPENCV_TS_PERF_HPP
4 #include "opencv2/ts.hpp"
11 #if !(defined(LOGD) || defined(LOGI) || defined(LOGW) || defined(LOGE))
12 # if defined(__ANDROID__) && defined(USE_ANDROID_LOGGING)
13 # include <android/log.h>
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__))
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)
28 // declare major namespaces to avoid errors on unknown namespace
29 namespace cv { namespace cuda {} namespace ocl {} }
35 // Tuple stuff from Google Tests
37 using testing::make_tuple;
39 using testing::tuple_size;
40 using testing::tuple_element;
44 /*****************************************************************************************\
45 * Predefined typical frame sizes and typical test parameters *
46 \*****************************************************************************************/
47 const static cv::Size szQVGA = cv::Size(320, 240);
48 const static cv::Size szVGA = cv::Size(640, 480);
49 const static cv::Size szSVGA = cv::Size(800, 600);
50 const static cv::Size szXGA = cv::Size(1024, 768);
51 const static cv::Size szSXGA = cv::Size(1280, 1024);
52 const static cv::Size szWQHD = cv::Size(2560, 1440);
54 const static cv::Size sznHD = cv::Size(640, 360);
55 const static cv::Size szqHD = cv::Size(960, 540);
56 const static cv::Size sz240p = szQVGA;
57 const static cv::Size sz720p = cv::Size(1280, 720);
58 const static cv::Size sz1080p = cv::Size(1920, 1080);
59 const static cv::Size sz1440p = szWQHD;
60 const static cv::Size sz2160p = cv::Size(3840, 2160);//UHDTV1 4K
61 const static cv::Size sz4320p = cv::Size(7680, 4320);//UHDTV2 8K
63 const static cv::Size sz3MP = cv::Size(2048, 1536);
64 const static cv::Size sz5MP = cv::Size(2592, 1944);
65 const static cv::Size sz2K = cv::Size(2048, 2048);
67 const static cv::Size szODD = cv::Size(127, 61);
69 const static cv::Size szSmall24 = cv::Size(24, 24);
70 const static cv::Size szSmall32 = cv::Size(32, 32);
71 const static cv::Size szSmall64 = cv::Size(64, 64);
72 const static cv::Size szSmall128 = cv::Size(128, 128);
74 #define SZ_ALL_VGA ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA)
75 #define SZ_ALL_GA ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA, ::perf::szXGA, ::perf::szSXGA)
76 #define SZ_ALL_HD ::testing::Values(::perf::sznHD, ::perf::szqHD, ::perf::sz720p, ::perf::sz1080p)
77 #define SZ_ALL_SMALL ::testing::Values(::perf::szSmall24, ::perf::szSmall32, ::perf::szSmall64, ::perf::szSmall128)
78 #define SZ_ALL ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA, ::perf::szXGA, ::perf::szSXGA, ::perf::sznHD, ::perf::szqHD, ::perf::sz720p, ::perf::sz1080p)
79 #define SZ_TYPICAL ::testing::Values(::perf::szVGA, ::perf::szqHD, ::perf::sz720p, ::perf::szODD)
82 #define TYPICAL_MAT_SIZES ::perf::szVGA, ::perf::sz720p, ::perf::sz1080p, ::perf::szODD
83 #define TYPICAL_MAT_TYPES CV_8UC1, CV_8UC4, CV_32FC1
84 #define TYPICAL_MATS testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( TYPICAL_MAT_TYPES ) )
85 #define TYPICAL_MATS_C1 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC1, CV_32FC1 ) )
86 #define TYPICAL_MATS_C4 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC4 ) )
89 /*****************************************************************************************\
90 * MatType - printable wrapper over integer 'type' of Mat *
91 \*****************************************************************************************/
95 MatType(int val=0) : _type(val) {}
96 operator int() const {return _type;}
102 /*****************************************************************************************\
103 * CV_ENUM and CV_FLAGS - macro to create printable wrappers for defines and enums *
104 \*****************************************************************************************/
106 #define CV_ENUM(class_name, ...) \
108 using namespace cv;using namespace cv::cuda; using namespace cv::ocl; \
109 struct class_name { \
110 class_name(int val = 0) : val_(val) {} \
111 operator int() const { return val_; } \
112 void PrintTo(std::ostream* os) const { \
113 const int vals[] = { __VA_ARGS__ }; \
114 const char* svals = #__VA_ARGS__; \
115 for(int i = 0, pos = 0; i < (int)(sizeof(vals)/sizeof(int)); ++i) { \
116 while(isspace(svals[pos]) || svals[pos] == ',') ++pos; \
118 while(!(isspace(svals[pos]) || svals[pos] == ',' || svals[pos] == 0)) \
120 if (val_ == vals[i]) { \
121 *os << std::string(svals + start, svals + pos); \
127 static ::testing::internal::ParamGenerator<class_name> all() { \
128 const class_name vals[] = { __VA_ARGS__ }; \
129 return ::testing::ValuesIn(vals); \
133 static inline void PrintTo(const class_name& t, std::ostream* os) { t.PrintTo(os); } }
135 #define CV_FLAGS(class_name, ...) \
137 struct class_name { \
138 class_name(int val = 0) : val_(val) {} \
139 operator int() const { return val_; } \
140 void PrintTo(std::ostream* os) const { \
141 using namespace cv;using namespace cv::cuda; using namespace cv::ocl; \
142 const int vals[] = { __VA_ARGS__ }; \
143 const char* svals = #__VA_ARGS__; \
146 for(int i = 0, pos = 0; i < (int)(sizeof(vals)/sizeof(int)); ++i) { \
147 while(isspace(svals[pos]) || svals[pos] == ',') ++pos; \
149 while(!(isspace(svals[pos]) || svals[pos] == ',' || svals[pos] == 0)) \
151 if ((value & vals[i]) == vals[i]) { \
153 if (first) first = false; else *os << "|"; \
154 *os << std::string(svals + start, svals + pos); \
155 if (!value) return; \
158 if (first) *os << "UNKNOWN"; \
162 static inline void PrintTo(const class_name& t, std::ostream* os) { t.PrintTo(os); } }
164 CV_ENUM(MatDepth, CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, CV_USRTYPE1)
166 /*****************************************************************************************\
167 * Regression control utility for performance testing *
168 \*****************************************************************************************/
175 class CV_EXPORTS Regression
178 static Regression& add(TestBase* test, const std::string& name, cv::InputArray array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
179 static Regression& addMoments(TestBase* test, const std::string& name, const cv::Moments & array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
180 static Regression& addKeypoints(TestBase* test, const std::string& name, const std::vector<cv::KeyPoint>& array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
181 static Regression& addMatches(TestBase* test, const std::string& name, const std::vector<cv::DMatch>& array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
182 static void Init(const std::string& testSuitName, const std::string& ext = ".xml");
184 Regression& operator() (const std::string& name, cv::InputArray array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
187 static Regression& instance();
191 Regression(const Regression&);
192 Regression& operator=(const Regression&);
194 cv::RNG regRNG;//own random numbers generator to make collection and verification work identical
195 std::string storageInPath;
196 std::string storageOutPath;
197 cv::FileStorage storageIn;
198 cv::FileStorage storageOut;
200 std::string currentTestNodeName;
201 std::string suiteName;
203 cv::FileStorage& write();
205 static std::string getCurrentTestNodeName();
206 static bool isVector(cv::InputArray a);
207 static double getElem(cv::Mat& m, int x, int y, int cn = 0);
209 void init(const std::string& testSuitName, const std::string& ext);
210 void write(cv::InputArray array);
211 void write(cv::Mat m);
212 void verify(cv::FileNode node, cv::InputArray array, double eps, ERROR_TYPE err);
213 void verify(cv::FileNode node, cv::Mat actual, double eps, std::string argname, ERROR_TYPE err);
216 #define SANITY_CHECK(array, ...) ::perf::Regression::add(this, #array, array , ## __VA_ARGS__)
217 #define SANITY_CHECK_MOMENTS(array, ...) ::perf::Regression::addMoments(this, #array, array , ## __VA_ARGS__)
218 #define SANITY_CHECK_KEYPOINTS(array, ...) ::perf::Regression::addKeypoints(this, #array, array , ## __VA_ARGS__)
219 #define SANITY_CHECK_MATCHES(array, ...) ::perf::Regression::addMatches(this, #array, array , ## __VA_ARGS__)
220 #define SANITY_CHECK_NOTHING() this->setVerified()
222 class CV_EXPORTS GpuPerf
225 static bool targetDevice();
228 #define PERF_RUN_CUDA() ::perf::GpuPerf::targetDevice()
230 /*****************************************************************************************\
231 * Container for performance metrics *
232 \*****************************************************************************************/
233 typedef struct CV_EXPORTS performance_metrics
237 unsigned int samples;
238 unsigned int outliers;
240 double gstddev;//stddev for log(time)
246 int terminationReason;
254 TERM_SKIP_TEST = 4, // there are some limitations and test should be skipped
258 performance_metrics();
260 } performance_metrics;
263 /*****************************************************************************************\
264 * Strategy for performance measuring *
265 \*****************************************************************************************/
268 PERF_STRATEGY_DEFAULT = -1,
269 PERF_STRATEGY_BASE = 0,
270 PERF_STRATEGY_SIMPLE = 1
274 /*****************************************************************************************\
275 * Base fixture for performance tests *
276 \*****************************************************************************************/
277 #ifdef CV_COLLECT_IMPL_DATA
278 // Implementation collection processing class.
279 // Accumulates and shapes implementation data.
280 typedef struct ImplData
287 std::vector<int> implCode;
288 std::vector<cv::String> funName;
298 ipp = icv = ocl = ipp_mt = false;
305 flagsToVars(cv::getImpl(implCode, funName));
308 std::vector<cv::String> GetCallsForImpl(int impl)
310 std::vector<cv::String> out;
312 for(int i = 0; i < (int)implCode.size(); i++)
314 if(impl == implCode[i])
315 out.push_back(funName[i]);
320 // Remove duplicate entries
323 std::vector<int> savedCode;
324 std::vector<cv::String> savedName;
326 for(int i = 0; i < (int)implCode.size(); i++)
329 for(int j = 0; j < (int)savedCode.size(); j++)
331 if(implCode[i] == savedCode[j] && !funName[i].compare(savedName[j]))
339 savedCode.push_back(implCode[i]);
340 savedName.push_back(funName[i]);
344 implCode = savedCode;
348 // convert flags register to more handy variables
349 void flagsToVars(int flags)
351 #if defined(HAVE_IPP_ICV)
353 icv = ((flags&CV_IMPL_IPP) > 0);
355 ipp = ((flags&CV_IMPL_IPP) > 0);
358 ipp_mt = ((flags&CV_IMPL_MT) > 0);
359 ocl = ((flags&CV_IMPL_OCL) > 0);
360 plain = (flags == 0);
366 #ifdef ENABLE_INSTRUMENTATION
370 static ::cv::String treeToString();
371 static void printTree();
375 class CV_EXPORTS TestBase: public ::testing::Test
380 static void Init(int argc, const char* const argv[]);
381 static void Init(const std::vector<std::string> & availableImpls,
382 int argc, const char* const argv[]);
383 static void RecordRunParameters();
384 static std::string getDataPath(const std::string& relativePath);
385 static std::string getSelectedImpl();
387 static enum PERF_STRATEGY getCurrentModulePerformanceStrategy();
388 static enum PERF_STRATEGY setModulePerformanceStrategy(enum PERF_STRATEGY strategy);
390 class PerfSkipTestException: public cv::Exception
393 int dummy; // workaround for MacOSX Xcode 7.3 bug (don't make class "empty")
394 PerfSkipTestException() : dummy(0) {}
398 virtual void PerfTestBody() = 0;
400 virtual void SetUp();
401 virtual void TearDown();
403 bool startTimer(); // bool is dummy for conditional loop
407 PERF_STRATEGY getCurrentPerformanceStrategy() const;
417 void reportMetrics(bool toJUnitXML = false);
418 static void warmup(cv::InputOutputArray a, WarmUpType wtype = WARMUP_READ);
420 performance_metrics& calcMetrics();
422 void RunPerfTestBody();
424 #ifdef CV_COLLECT_IMPL_DATA
427 #ifdef ENABLE_INSTRUMENTATION
428 InstumentData instrConf;
432 typedef std::vector<std::pair<int, cv::Size> > SizeVector;
433 typedef std::vector<int64> TimeVector;
435 SizeVector inputData;
436 SizeVector outputData;
437 unsigned int getTotalInputSize() const;
438 unsigned int getTotalOutputSize() const;
440 enum PERF_STRATEGY testStrategy;
446 static int64 timeLimitDefault;
447 static unsigned int iterationsLimitDefault;
449 unsigned int minIters;
451 unsigned int currentIter;
452 unsigned int runsPerIteration;
453 unsigned int perfValidationStage;
455 performance_metrics metrics;
456 void validateMetrics();
458 static int64 _timeadjustment;
459 static int64 _calibrate();
461 static void warmup_impl(cv::Mat m, WarmUpType wtype);
462 static int getSizeInBytes(cv::InputArray a);
463 static cv::Size getSize(cv::InputArray a);
464 static void declareArray(SizeVector& sizes, cv::InputOutputArray a, WarmUpType wtype);
466 class CV_EXPORTS _declareHelper
469 _declareHelper& in(cv::InputOutputArray a1, WarmUpType wtype = WARMUP_READ);
470 _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, WarmUpType wtype = WARMUP_READ);
471 _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, WarmUpType wtype = WARMUP_READ);
472 _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, WarmUpType wtype = WARMUP_READ);
474 _declareHelper& out(cv::InputOutputArray a1, WarmUpType wtype = WARMUP_WRITE);
475 _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, WarmUpType wtype = WARMUP_WRITE);
476 _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, WarmUpType wtype = WARMUP_WRITE);
477 _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, WarmUpType wtype = WARMUP_WRITE);
479 _declareHelper& iterations(unsigned int n);
480 _declareHelper& time(double timeLimitSecs);
481 _declareHelper& tbb_threads(int n = -1);
482 _declareHelper& runs(unsigned int runsNumber);
484 _declareHelper& strategy(enum PERF_STRATEGY s);
487 _declareHelper(TestBase* t);
488 _declareHelper(const _declareHelper&);
489 _declareHelper& operator=(const _declareHelper&);
490 friend class TestBase;
492 friend class _declareHelper;
497 _declareHelper declare;
499 void setVerified() { this->verified = true; }
502 template<typename T> class TestBaseWithParam: public TestBase, public ::testing::WithParamInterface<T> {};
504 typedef tuple<cv::Size, MatType> Size_MatType_t;
505 typedef TestBaseWithParam<Size_MatType_t> Size_MatType;
507 /*****************************************************************************************\
508 * Print functions for googletest *
509 \*****************************************************************************************/
510 CV_EXPORTS void PrintTo(const MatType& t, std::ostream* os);
517 CV_EXPORTS void PrintTo(const String& str, ::std::ostream* os);
518 CV_EXPORTS void PrintTo(const Size& sz, ::std::ostream* os);
523 /*****************************************************************************************\
524 * Macro definitions for performance tests *
525 \*****************************************************************************************/
527 #define CV__PERF_TEST_BODY_IMPL(name) \
529 CV__TRACE_APP_FUNCTION_NAME("PERF_TEST: " name); \
533 #define PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name) \
534 test_case_name##_##test_name##_perf_namespace_proxy
536 // Defines a performance test.
538 // The first parameter is the name of the test case, and the second
539 // parameter is the name of the test within the test case.
541 // The user should put his test code between braces after using this
544 // PERF_TEST(FooTest, InitializesCorrectly) {
546 // EXPECT_TRUE(foo.StatusIsOK());
548 #define PERF_TEST(test_case_name, test_name)\
549 namespace PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name) {\
550 class TestBase {/*compile error for this class means that you are trying to use perf::TestBase as a fixture*/};\
551 class test_case_name : public ::perf::TestBase {\
555 virtual void PerfTestBody();\
557 TEST_F(test_case_name, test_name){ CV__PERF_TEST_BODY_IMPL(#test_case_name "_" #test_name); }\
559 void PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name)::test_case_name::PerfTestBody()
561 // Defines a performance test that uses a test fixture.
563 // The first parameter is the name of the test fixture class, which
564 // also doubles as the test case name. The second parameter is the
565 // name of the test within the test case.
567 // A test fixture class must be declared earlier. The user should put
568 // his test code between braces after using this macro. Example:
570 // class FooTest : public ::perf::TestBase {
572 // virtual void SetUp() { TestBase::SetUp(); b_.AddElement(3); }
578 // PERF_TEST_F(FooTest, InitializesCorrectly) {
579 // EXPECT_TRUE(a_.StatusIsOK());
582 // PERF_TEST_F(FooTest, ReturnsElementCountCorrectly) {
583 // EXPECT_EQ(0, a_.size());
584 // EXPECT_EQ(1, b_.size());
586 #define PERF_TEST_F(fixture, testname) \
587 namespace PERF_PROXY_NAMESPACE_NAME_(fixture, testname) {\
588 class TestBase {/*compile error for this class means that you are trying to use perf::TestBase as a fixture*/};\
589 class fixture : public ::fixture {\
593 virtual void PerfTestBody();\
595 TEST_F(fixture, testname){ CV__PERF_TEST_BODY_IMPL(#fixture "_" #testname); }\
597 void PERF_PROXY_NAMESPACE_NAME_(fixture, testname)::fixture::PerfTestBody()
599 // Defines a parametrized performance test.
601 // @Note PERF_TEST_P() below violates behavior of original Google Tests - there is no tests instantiation in original TEST_P()
602 // This macro is intended for usage with separate INSTANTIATE_TEST_CASE_P macro
603 #define PERF_TEST_P_(test_case_name, test_name) CV__TEST_P(test_case_name, test_name, PerfTestBody, CV__PERF_TEST_BODY_IMPL)
605 // Defines a parametrized performance test.
607 // @Note Original TEST_P() macro doesn't instantiate tests with parameters. To keep original usage use PERF_TEST_P_() macro
609 // The first parameter is the name of the test fixture class, which
610 // also doubles as the test case name. The second parameter is the
611 // name of the test within the test case.
613 // The user should put his test code between braces after using this
616 // typedef ::perf::TestBaseWithParam<cv::Size> FooTest;
618 // PERF_TEST_P(FooTest, DoTestingRight, ::testing::Values(::perf::szVGA, ::perf::sz720p) {
619 // cv::Mat b(GetParam(), CV_8U, cv::Scalar(10));
620 // cv::Mat a(GetParam(), CV_8U, cv::Scalar(20));
621 // cv::Mat c(GetParam(), CV_8U, cv::Scalar(0));
623 // declare.in(a, b).out(c).time(0.5);
625 // TEST_CYCLE() cv::add(a, b, c);
629 #define PERF_TEST_P(fixture, name, params) \
630 class fixture##_##name : public fixture {\
632 fixture##_##name() {}\
634 virtual void PerfTestBody();\
636 CV__TEST_P(fixture##_##name, name, PerfTestBodyDummy, CV__PERF_TEST_BODY_IMPL){} \
637 INSTANTIATE_TEST_CASE_P(/*none*/, fixture##_##name, params);\
638 void fixture##_##name::PerfTestBody()
640 #ifndef __CV_TEST_EXEC_ARGS
641 #if defined(_MSC_VER) && (_MSC_VER <= 1400)
642 #define __CV_TEST_EXEC_ARGS(...) \
643 while (++argc >= (--argc,-1)) {__VA_ARGS__; break;} /*this ugly construction is needed for VS 2005*/
645 #define __CV_TEST_EXEC_ARGS(...) \
651 namespace cvtest { namespace ocl {
652 void dumpOpenCLDevice();
654 #define TEST_DUMP_OCL_INFO cvtest::ocl::dumpOpenCLDevice();
656 #define TEST_DUMP_OCL_INFO
660 #define CV_PERF_TEST_MAIN_INTERNALS(modulename, impls, ...) \
661 CV_TRACE_FUNCTION(); \
662 { CV_TRACE_REGION("INIT"); \
663 ::perf::Regression::Init(#modulename); \
664 ::perf::TestBase::Init(std::vector<std::string>(impls, impls + sizeof impls / sizeof *impls), \
666 ::testing::InitGoogleTest(&argc, argv); \
667 cvtest::printVersionInfo(); \
668 ::testing::Test::RecordProperty("cv_module_name", #modulename); \
669 ::perf::TestBase::RecordRunParameters(); \
670 __CV_TEST_EXEC_ARGS(__VA_ARGS__) \
673 return RUN_ALL_TESTS();
675 // impls must be an array, not a pointer; "plain" should always be one of the implementations
676 #define CV_PERF_TEST_MAIN_WITH_IMPLS(modulename, impls, ...) \
677 int main(int argc, char **argv)\
679 CV_PERF_TEST_MAIN_INTERNALS(modulename, impls, __VA_ARGS__)\
682 #define CV_PERF_TEST_MAIN(modulename, ...) \
683 int main(int argc, char **argv)\
685 const char * plain_only[] = { "plain" };\
686 CV_PERF_TEST_MAIN_INTERNALS(modulename, plain_only, __VA_ARGS__)\
690 #define TEST_CYCLE_N(n) for(declare.iterations(n); next() && startTimer(); stopTimer())
692 #define TEST_CYCLE() for(; next() && startTimer(); stopTimer())
694 #define TEST_CYCLE_MULTIRUN(runsNum) for(declare.runs(runsNum); next() && startTimer(); stopTimer()) for(int r = 0; r < runsNum; ++r)
696 #define PERF_SAMPLE_BEGIN() \
697 for(; next() && startTimer(); stopTimer()) \
699 CV_TRACE_REGION("iteration");
700 #define PERF_SAMPLE_END() \
705 namespace comparators
709 struct CV_EXPORTS RectLess_ :
710 public std::binary_function<cv::Rect_<T>, cv::Rect_<T>, bool>
712 bool operator()(const cv::Rect_<T>& r1, const cv::Rect_<T>& r2) const
714 return r1.x < r2.x ||
715 (r1.x == r2.x && r1.y < r2.y) ||
716 (r1.x == r2.x && r1.y == r2.y && r1.width < r2.width) ||
717 (r1.x == r2.x && r1.y == r2.y && r1.width == r2.width && r1.height < r2.height);
721 typedef RectLess_<int> RectLess;
723 struct CV_EXPORTS KeypointGreater :
724 public std::binary_function<cv::KeyPoint, cv::KeyPoint, bool>
726 bool operator()(const cv::KeyPoint& kp1, const cv::KeyPoint& kp2) const
728 if (kp1.response > kp2.response) return true;
729 if (kp1.response < kp2.response) return false;
730 if (kp1.size > kp2.size) return true;
731 if (kp1.size < kp2.size) return false;
732 if (kp1.octave > kp2.octave) return true;
733 if (kp1.octave < kp2.octave) return false;
734 if (kp1.pt.y < kp2.pt.y) return false;
735 if (kp1.pt.y > kp2.pt.y) return true;
736 return kp1.pt.x < kp2.pt.x;
740 } //namespace comparators
742 void CV_EXPORTS sort(std::vector<cv::KeyPoint>& pts, cv::InputOutputArray descriptors);
745 #endif //OPENCV_TS_PERF_HPP