include/opencv2/ts/ts_perf.hpp
Go to the documentation of this file.
00001 #ifndef __OPENCV_TS_PERF_HPP__
00002 #define __OPENCV_TS_PERF_HPP__
00003 
00004 #include "opencv2/core/core.hpp"
00005 #include "opencv2/features2d/features2d.hpp"
00006 #include "ts_gtest.h"
00007 
00008 #ifdef HAVE_TBB
00009 #include "tbb/task_scheduler_init.h"
00010 #endif
00011 
00012 #if !(defined(LOGD) || defined(LOGI) || defined(LOGW) || defined(LOGE))
00013 # if defined(ANDROID) && defined(USE_ANDROID_LOGGING)
00014 #  include <android/log.h>
00015 
00016 #  define PERF_TESTS_LOG_TAG "OpenCV_perf"
00017 #  define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, PERF_TESTS_LOG_TAG, __VA_ARGS__))
00018 #  define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, PERF_TESTS_LOG_TAG, __VA_ARGS__))
00019 #  define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, PERF_TESTS_LOG_TAG, __VA_ARGS__))
00020 #  define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, PERF_TESTS_LOG_TAG, __VA_ARGS__))
00021 # else
00022 #  define LOGD(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)
00023 #  define LOGI(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)
00024 #  define LOGW(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)
00025 #  define LOGE(_str, ...) do{printf(_str , ## __VA_ARGS__); printf("\n");fflush(stdout);} while(0)
00026 # endif
00027 #endif
00028 
00029 namespace perf
00030 {
00031 class TestBase;
00032 
00033 /*****************************************************************************************\
00034 *                Predefined typical frame sizes and typical test parameters               *
00035 \*****************************************************************************************/
00036 const cv::Size szQVGA = cv::Size(320, 240);
00037 const cv::Size szVGA = cv::Size(640, 480);
00038 const cv::Size szSVGA = cv::Size(800, 600);
00039 const cv::Size szXGA = cv::Size(1024, 768);
00040 const cv::Size szSXGA = cv::Size(1280, 1024);
00041 const cv::Size szWQHD = cv::Size(2560, 1440);
00042 
00043 const cv::Size sznHD = cv::Size(640, 360);
00044 const cv::Size szqHD = cv::Size(960, 540);
00045 const cv::Size sz240p = szQVGA;
00046 const cv::Size sz720p = cv::Size(1280, 720);
00047 const cv::Size sz1080p = cv::Size(1920, 1080);
00048 const cv::Size sz1440p = szWQHD;
00049 const cv::Size sz2160p = cv::Size(3840, 2160);//UHDTV1 4K
00050 const cv::Size sz4320p = cv::Size(7680, 4320);//UHDTV2 8K
00051 
00052 const cv::Size sz3MP = cv::Size(2048, 1536);
00053 const cv::Size sz5MP = cv::Size(2592, 1944);
00054 const cv::Size sz2K = cv::Size(2048, 2048);
00055 
00056 const cv::Size szODD = cv::Size(127, 61);
00057 
00058 const cv::Size szSmall24 = cv::Size(24, 24);
00059 const cv::Size szSmall32 = cv::Size(32, 32);
00060 const cv::Size szSmall64 = cv::Size(64, 64);
00061 const cv::Size szSmall128 = cv::Size(128, 128);
00062 
00063 #define SZ_ALL_VGA ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA)
00064 #define SZ_ALL_GA  ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA, ::perf::szXGA, ::perf::szSXGA)
00065 #define SZ_ALL_HD  ::testing::Values(::perf::sznHD, ::perf::szqHD, ::perf::sz720p, ::perf::sz1080p)
00066 #define SZ_ALL_SMALL ::testing::Values(::perf::szSmall24, ::perf::szSmall32, ::perf::szSmall64, ::perf::szSmall128)
00067 #define SZ_ALL  ::testing::Values(::perf::szQVGA, ::perf::szVGA, ::perf::szSVGA, ::perf::szXGA, ::perf::szSXGA, ::perf::sznHD, ::perf::szqHD, ::perf::sz720p, ::perf::sz1080p)
00068 #define SZ_TYPICAL  ::testing::Values(::perf::szVGA, ::perf::szqHD, ::perf::sz720p, ::perf::szODD)
00069 
00070 
00071 #define TYPICAL_MAT_SIZES ::perf::szVGA, ::perf::sz720p, ::perf::sz1080p, ::perf::szODD
00072 #define TYPICAL_MAT_TYPES CV_8UC1, CV_8UC4, CV_32FC1
00073 #define TYPICAL_MATS testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( TYPICAL_MAT_TYPES ) )
00074 #define TYPICAL_MATS_C1 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC1, CV_32FC1 ) )
00075 #define TYPICAL_MATS_C4 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC4 ) )
00076 
00077 
00078 /*****************************************************************************************\
00079 *                MatType - printable wrapper over integer 'type' of Mat                   *
00080 \*****************************************************************************************/
00081 class MatType
00082 {
00083 public:
00084     MatType(int val=0) : _type(val) {}
00085     operator int() const {return _type;}
00086 
00087 private:
00088     int _type;
00089 };
00090 
00091 /*****************************************************************************************\
00092 *     CV_ENUM and CV_FLAGS - macro to create printable wrappers for defines and enums     *
00093 \*****************************************************************************************/
00094 
00095 #define CV_ENUM(class_name, ...) \
00096 namespace { class CV_EXPORTS class_name {\
00097 public:\
00098   class_name(int val = 0) : _val(val) {}\
00099   operator int() const {return _val;}\
00100   void PrintTo(std::ostream* os) const {\
00101     const int vals[] = {__VA_ARGS__};\
00102     const char* svals = #__VA_ARGS__;\
00103     for(int i = 0, pos = 0; i < (int)(sizeof(vals)/sizeof(int)); ++i){\
00104       while(isspace(svals[pos]) || svals[pos] == ',') ++pos;\
00105       int start = pos;\
00106       while(!(isspace(svals[pos]) || svals[pos] == ',' || svals[pos] == 0)) ++pos;\
00107       if (_val == vals[i]) {\
00108         *os << std::string(svals + start, svals + pos);\
00109         return;\
00110       }\
00111     }\
00112     *os << "UNKNOWN";\
00113   }\
00114   struct Container{\
00115     typedef class_name value_type;\
00116       Container(class_name* first, size_t len): _begin(first), _end(first+len){}\
00117       const class_name* begin() const {return _begin;}\
00118       const class_name* end() const {return _end;}\
00119     private: class_name *_begin, *_end;\
00120   };\
00121   static Container all(){\
00122     static int vals[] = {__VA_ARGS__};\
00123     return Container((class_name*)vals, sizeof(vals)/sizeof(vals[0]));\
00124   }\
00125 private: int _val;\
00126 };\
00127 inline void PrintTo(const class_name& t, std::ostream* os) { t.PrintTo(os); } }
00128 
00129 #define CV_FLAGS(class_name, ...) \
00130 class CV_EXPORTS class_name {\
00131 public:\
00132   class_name(int val = 0) : _val(val) {}\
00133   operator int() const {return _val;}\
00134   void PrintTo(std::ostream* os) const {\
00135     const int vals[] = {__VA_ARGS__};\
00136     const char* svals = #__VA_ARGS__;\
00137     int value = _val;\
00138     bool first = true;\
00139     for(int i = 0, pos = 0; i < (int)(sizeof(vals)/sizeof(int)); ++i){\
00140       while(isspace(svals[pos]) || svals[pos] == ',') ++pos;\
00141       int start = pos;\
00142       while(!(isspace(svals[pos]) || svals[pos] == ',' || svals[pos] == 0)) ++pos;\
00143       if ((value & vals[i]) == vals[i]) {\
00144         value &= ~vals[i]; \
00145         if (first) first = false; else *os << "|"; \
00146         *os << std::string(svals + start, svals + pos);\
00147         if (!value) return;\
00148       }\
00149     }\
00150     if (first) *os << "UNKNOWN";\
00151   }\
00152 private: int _val;\
00153 };\
00154 inline void PrintTo(const class_name& t, std::ostream* os) { t.PrintTo(os); }
00155 
00156 CV_ENUM(MatDepth, CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, CV_USRTYPE1)
00157 
00158 /*****************************************************************************************\
00159 *                 Regression control utility for performance testing                      *
00160 \*****************************************************************************************/
00161 enum ERROR_TYPE
00162 {
00163     ERROR_ABSOLUTE = 0,
00164     ERROR_RELATIVE = 1
00165 };
00166 
00167 class CV_EXPORTS Regression
00168 {
00169 public:
00170     static Regression& add(TestBase* test, const std::string& name, cv::InputArray array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
00171     static Regression& addKeypoints(TestBase* test, const std::string& name, const std::vector<cv::KeyPoint>& array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
00172     static Regression& addMatches(TestBase* test, const std::string& name, const std::vector<cv::DMatch>& array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
00173     static void Init(const std::string& testSuitName, const std::string& ext = ".xml");
00174 
00175     Regression& operator() (const std::string& name, cv::InputArray array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE);
00176 
00177 private:
00178     static Regression& instance();
00179     Regression();
00180     ~Regression();
00181 
00182     Regression(const Regression&);
00183     Regression& operator=(const Regression&);
00184 
00185     cv::RNG regRNG;//own random numbers generator to make collection and verification work identical
00186     std::string storageInPath;
00187     std::string storageOutPath;
00188     cv::FileStorage storageIn;
00189     cv::FileStorage storageOut;
00190     cv::FileNode rootIn;
00191     std::string currentTestNodeName;
00192     std::string suiteName;
00193 
00194     cv::FileStorage& write();
00195 
00196     static std::string getCurrentTestNodeName();
00197     static bool isVector(cv::InputArray a);
00198     static double getElem(cv::Mat& m, int x, int y, int cn = 0);
00199 
00200     void init(const std::string& testSuitName, const std::string& ext);
00201     void write(cv::InputArray array);
00202     void write(cv::Mat m);
00203     void verify(cv::FileNode node, cv::InputArray array, double eps, ERROR_TYPE err);
00204     void verify(cv::FileNode node, cv::Mat actual, double eps, std::string argname, ERROR_TYPE err);
00205 };
00206 
00207 #define SANITY_CHECK(array, ...) ::perf::Regression::add(this, #array, array , ## __VA_ARGS__)
00208 #define SANITY_CHECK_KEYPOINTS(array, ...) ::perf::Regression::addKeypoints(this, #array, array , ## __VA_ARGS__)
00209 #define SANITY_CHECK_MATCHES(array, ...) ::perf::Regression::addMatches(this, #array, array , ## __VA_ARGS__)
00210 
00211 #ifdef HAVE_CUDA
00212 class CV_EXPORTS GpuPerf
00213 {
00214 public:
00215   static bool targetDevice();
00216 };
00217 
00218 # define PERF_RUN_GPU()  ::perf::GpuPerf::targetDevice()
00219 #else
00220 # define PERF_RUN_GPU()  false
00221 #endif
00222 
00223 
00224 /*****************************************************************************************\
00225 *                            Container for performance metrics                            *
00226 \*****************************************************************************************/
00227 typedef struct CV_EXPORTS performance_metrics
00228 {
00229     size_t bytesIn;
00230     size_t bytesOut;
00231     unsigned int samples;
00232     unsigned int outliers;
00233     double gmean;
00234     double gstddev;//stddev for log(time)
00235     double mean;
00236     double stddev;
00237     double median;
00238     double min;
00239     double frequency;
00240     int terminationReason;
00241 
00242     enum
00243     {
00244         TERM_ITERATIONS = 0,
00245         TERM_TIME = 1,
00246         TERM_INTERRUPT = 2,
00247         TERM_EXCEPTION = 3,
00248         TERM_UNKNOWN = -1
00249     };
00250 
00251     performance_metrics();
00252 } performance_metrics;
00253 
00254 
00255 /*****************************************************************************************\
00256 *                           Base fixture for performance tests                            *
00257 \*****************************************************************************************/
00258 class CV_EXPORTS TestBase: public ::testing::Test
00259 {
00260 public:
00261     TestBase();
00262 
00263     static void Init(int argc, const char* const argv[]);
00264     static std::string getDataPath(const std::string& relativePath);
00265 
00266 protected:
00267     virtual void PerfTestBody() = 0;
00268 
00269     virtual void SetUp();
00270     virtual void TearDown();
00271 
00272     void startTimer();
00273     void stopTimer();
00274     bool next();
00275 
00276     //_declareHelper declare;
00277 
00278     enum
00279     {
00280         WARMUP_READ,
00281         WARMUP_WRITE,
00282         WARMUP_RNG,
00283         WARMUP_NONE
00284     };
00285 
00286     void reportMetrics(bool toJUnitXML = false);
00287     static void warmup(cv::InputOutputArray a, int wtype = WARMUP_READ);
00288 
00289     performance_metrics& calcMetrics();
00290     void RunPerfTestBody();
00291 private:
00292     typedef std::vector<std::pair<int, cv::Size> > SizeVector;
00293     typedef std::vector<int64> TimeVector;
00294 
00295     SizeVector inputData;
00296     SizeVector outputData;
00297     unsigned int getTotalInputSize() const;
00298     unsigned int getTotalOutputSize() const;
00299 
00300     TimeVector times;
00301     int64 lastTime;
00302     int64 totalTime;
00303     int64 timeLimit;
00304     static int64 timeLimitDefault;
00305     static unsigned int iterationsLimitDefault;
00306 
00307     unsigned int nIters;
00308     unsigned int currentIter;
00309     unsigned int runsPerIteration;
00310 
00311     performance_metrics metrics;
00312     void validateMetrics();
00313 
00314     static int64 _timeadjustment;
00315     static int64 _calibrate();
00316 
00317     static void warmup_impl(cv::Mat m, int wtype);
00318     static int getSizeInBytes(cv::InputArray a);
00319     static cv::Size getSize(cv::InputArray a);
00320     static void declareArray(SizeVector& sizes, cv::InputOutputArray a, int wtype = 0);
00321 
00322     class CV_EXPORTS _declareHelper
00323     {
00324     public:
00325         _declareHelper& in(cv::InputOutputArray a1, int wtype = WARMUP_READ);
00326         _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, int wtype = WARMUP_READ);
00327         _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, int wtype = WARMUP_READ);
00328         _declareHelper& in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, int wtype = WARMUP_READ);
00329 
00330         _declareHelper& out(cv::InputOutputArray a1, int wtype = WARMUP_WRITE);
00331         _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, int wtype = WARMUP_WRITE);
00332         _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, int wtype = WARMUP_WRITE);
00333         _declareHelper& out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, int wtype = WARMUP_WRITE);
00334 
00335         _declareHelper& iterations(unsigned int n);
00336         _declareHelper& time(double timeLimitSecs);
00337         _declareHelper& tbb_threads(int n = -1);
00338         _declareHelper& runs(unsigned int runsNumber);
00339     private:
00340         TestBase* test;
00341         _declareHelper(TestBase* t);
00342         _declareHelper(const _declareHelper&);
00343         _declareHelper& operator=(const _declareHelper&);
00344         friend class TestBase;
00345     };
00346     friend class _declareHelper;
00347     friend class Regression;
00348 
00349     bool verified;
00350 
00351 public:
00352     _declareHelper declare;
00353 };
00354 
00355 template<typename T> class TestBaseWithParam: public TestBase, public ::testing::WithParamInterface<T> {};
00356 
00357 typedef std::tr1::tuple<cv::Size, MatType> Size_MatType_t;
00358 typedef TestBaseWithParam<Size_MatType_t> Size_MatType;
00359 
00360 /*****************************************************************************************\
00361 *                              Print functions for googletest                             *
00362 \*****************************************************************************************/
00363 CV_EXPORTS void PrintTo(const MatType& t, std::ostream* os);
00364 
00365 } //namespace perf
00366 
00367 namespace cv
00368 {
00369 
00370 CV_EXPORTS void PrintTo(const Size& sz, ::std::ostream* os);
00371 
00372 } //namespace cv
00373 
00374 
00375 /*****************************************************************************************\
00376 *                        Macro definitions for performance tests                          *
00377 \*****************************************************************************************/
00378 #define PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name) \
00379   test_case_name##_##test_name##_perf_namespace_proxy
00380 
00381 // Defines a performance test.
00382 //
00383 // The first parameter is the name of the test case, and the second
00384 // parameter is the name of the test within the test case.
00385 //
00386 // The user should put his test code between braces after using this
00387 // macro.  Example:
00388 //
00389 //   PERF_TEST(FooTest, InitializesCorrectly) {
00390 //     Foo foo;
00391 //     EXPECT_TRUE(foo.StatusIsOK());
00392 //   }
00393 #define PERF_TEST(test_case_name, test_name)\
00394     namespace PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name) {\
00395      class TestBase {/*compile error for this class means that you are trying to use perf::TestBase as a fixture*/};\
00396      class test_case_name : public ::perf::TestBase {\
00397       public:\
00398        test_case_name() {}\
00399       protected:\
00400        virtual void PerfTestBody();\
00401      };\
00402      TEST_F(test_case_name, test_name){ RunPerfTestBody(); }\
00403     }\
00404     void PERF_PROXY_NAMESPACE_NAME_(test_case_name, test_name)::test_case_name::PerfTestBody()
00405 
00406 // Defines a performance test that uses a test fixture.
00407 //
00408 // The first parameter is the name of the test fixture class, which
00409 // also doubles as the test case name.  The second parameter is the
00410 // name of the test within the test case.
00411 //
00412 // A test fixture class must be declared earlier.  The user should put
00413 // his test code between braces after using this macro.  Example:
00414 //
00415 //   class FooTest : public ::perf::TestBase {
00416 //    protected:
00417 //     virtual void SetUp() { TestBase::SetUp(); b_.AddElement(3); }
00418 //
00419 //     Foo a_;
00420 //     Foo b_;
00421 //   };
00422 //
00423 //   PERF_TEST_F(FooTest, InitializesCorrectly) {
00424 //     EXPECT_TRUE(a_.StatusIsOK());
00425 //   }
00426 //
00427 //   PERF_TEST_F(FooTest, ReturnsElementCountCorrectly) {
00428 //     EXPECT_EQ(0, a_.size());
00429 //     EXPECT_EQ(1, b_.size());
00430 //   }
00431 #define PERF_TEST_F(fixture, testname) \
00432     namespace PERF_PROXY_NAMESPACE_NAME_(fixture, testname) {\
00433      class TestBase {/*compile error for this class means that you are trying to use perf::TestBase as a fixture*/};\
00434      class fixture : public ::fixture {\
00435       public:\
00436        fixture() {}\
00437       protected:\
00438        virtual void PerfTestBody();\
00439      };\
00440      TEST_F(fixture, testname){ RunPerfTestBody(); }\
00441     }\
00442     void PERF_PROXY_NAMESPACE_NAME_(fixture, testname)::fixture::PerfTestBody()
00443 
00444 // Defines a parametrized performance test.
00445 //
00446 // The first parameter is the name of the test fixture class, which
00447 // also doubles as the test case name.  The second parameter is the
00448 // name of the test within the test case.
00449 //
00450 // The user should put his test code between braces after using this
00451 // macro.  Example:
00452 //
00453 //   typedef ::perf::TestBaseWithParam<cv::Size> FooTest;
00454 //
00455 //   PERF_TEST_P(FooTest, DoTestingRight, ::testing::Values(::perf::szVGA, ::perf::sz720p) {
00456 //     cv::Mat b(GetParam(), CV_8U, cv::Scalar(10));
00457 //     cv::Mat a(GetParam(), CV_8U, cv::Scalar(20));
00458 //     cv::Mat c(GetParam(), CV_8U, cv::Scalar(0));
00459 //
00460 //     declare.in(a, b).out(c).time(0.5);
00461 //
00462 //     TEST_CYCLE() cv::add(a, b, c);
00463 //
00464 //     SANITY_CHECK(c);
00465 //   }
00466 #define PERF_TEST_P(fixture, name, params)  \
00467     class fixture##_##name : public fixture {\
00468      public:\
00469       fixture##_##name() {}\
00470      protected:\
00471       virtual void PerfTestBody();\
00472     };\
00473     TEST_P(fixture##_##name, name /*perf*/){ RunPerfTestBody(); }\
00474     INSTANTIATE_TEST_CASE_P(/*none*/, fixture##_##name, params);\
00475     void fixture##_##name::PerfTestBody()
00476 
00477 
00478 #define CV_PERF_TEST_MAIN(testsuitname, ...) \
00479 int main(int argc, char **argv)\
00480 {\
00481     while (++argc >= (--argc,-1)) {__VA_ARGS__; break;} /*this ugly construction is needed for VS 2005*/\
00482     ::perf::Regression::Init(#testsuitname);\
00483     ::perf::TestBase::Init(argc, argv);\
00484     ::testing::InitGoogleTest(&argc, argv);\
00485     return RUN_ALL_TESTS();\
00486 }
00487 
00488 #define TEST_CYCLE_N(n) for(declare.iterations(n); startTimer(), next(); stopTimer())
00489 #define TEST_CYCLE() for(; startTimer(), next(); stopTimer())
00490 #define TEST_CYCLE_MULTIRUN(runsNum) for(declare.runs(runsNum); startTimer(), next(); stopTimer()) for(int r = 0; r < runsNum; ++r)
00491 
00492 namespace perf
00493 {
00494 namespace comparators
00495 {
00496 
00497 template<typename T>
00498 struct CV_EXPORTS RectLess_
00499 {
00500   bool operator()(const cv::Rect_<T>& r1, const cv::Rect_<T>& r2) const
00501   {
00502     return r1.x < r2.x
00503       || (r1.x == r2.x && r1.y < r2.y)
00504       || (r1.x == r2.x && r1.y == r2.y && r1.width < r2.width)
00505       || (r1.x == r2.x && r1.y == r2.y && r1.width == r2.width && r1.height < r2.height);
00506   }
00507 };
00508 
00509 typedef RectLess_<int> RectLess;
00510 
00511 struct CV_EXPORTS KeypointGreater
00512 {
00513     bool operator()(const cv::KeyPoint& kp1, const cv::KeyPoint& kp2) const
00514     {
00515         if(kp1.response > kp2.response) return true;
00516         if(kp1.response < kp2.response) return false;
00517         if(kp1.size > kp2.size) return true;
00518         if(kp1.size < kp2.size) return false;
00519         if(kp1.octave > kp2.octave) return true;
00520         if(kp1.octave < kp2.octave) return false;
00521         if(kp1.pt.y < kp2.pt.y) return false;
00522         if(kp1.pt.y > kp2.pt.y) return true;
00523         return kp1.pt.x < kp2.pt.x;
00524     }
00525 };
00526 
00527 } //namespace comparators
00528 
00529 void CV_EXPORTS sort(std::vector<cv::KeyPoint>& pts, cv::InputOutputArray descriptors);
00530 } //namespace perf
00531 
00532 #endif //__OPENCV_TS_PERF_HPP__