Added perf test
authorDaniil Osokin <daniil.osokin@itseez.com>
Fri, 10 Aug 2012 12:39:36 +0000 (16:39 +0400)
committerDaniil Osokin <daniil.osokin@itseez.com>
Fri, 10 Aug 2012 12:39:36 +0000 (16:39 +0400)
modules/calib3d/perf/perf_pnp.cpp
modules/core/perf/perf_mat.cpp [new file with mode: 0644]
modules/features2d/perf/perf_batchDistance.cpp [new file with mode: 0644]
modules/stitching/perf/perf_stich.cpp

index 315022d..9608c7c 100644 (file)
@@ -11,6 +11,8 @@ CV_ENUM(pnpAlgo, CV_ITERATIVE, CV_EPNP /*, CV_P3P*/)
 typedef std::tr1::tuple<int, pnpAlgo> PointsNum_Algo_t;
 typedef perf::TestBaseWithParam<PointsNum_Algo_t> PointsNum_Algo;
 
+typedef perf::TestBaseWithParam<int> PointsNum;
+
 PERF_TEST_P(PointsNum_Algo, solvePnP,
             testing::Combine(
                 testing::Values(4, 3*9, 7*13),
@@ -86,3 +88,41 @@ PERF_TEST(PointsNum_Algo, solveP3P)
     SANITY_CHECK(rvec, 1e-6);
     SANITY_CHECK(tvec, 1e-6);
 }
+
+PERF_TEST_P(PointsNum, SolvePnPRansac, testing::Values(4, 3*9, 7*13))
+{
+    int count = GetParam();
+
+    Mat object(1, count, CV_32FC3);
+    randu(object, -100, 100);
+
+    Mat camera_mat(3, 3, CV_32FC1);
+    randu(camera_mat, 0.5, 1);
+    camera_mat.at<float>(0, 1) = 0.f;
+    camera_mat.at<float>(1, 0) = 0.f;
+    camera_mat.at<float>(2, 0) = 0.f;
+    camera_mat.at<float>(2, 1) = 0.f;
+
+    Mat dist_coef(1, 8, CV_32F, cv::Scalar::all(0));
+
+    vector<cv::Point2f> image_vec;
+    Mat rvec_gold(1, 3, CV_32FC1);
+    randu(rvec_gold, 0, 1);
+    Mat tvec_gold(1, 3, CV_32FC1);
+    randu(tvec_gold, 0, 1);
+    projectPoints(object, rvec_gold, tvec_gold, camera_mat, dist_coef, image_vec);
+
+    Mat image(1, count, CV_32FC2, &image_vec[0]);
+
+    Mat rvec;
+    Mat tvec;
+
+    solvePnPRansac(object, image, camera_mat, dist_coef, rvec, tvec);
+
+    declare.time(3.0);
+
+    TEST_CYCLE()
+    {
+        solvePnPRansac(object, image, camera_mat, dist_coef, rvec, tvec);
+    }
+}
diff --git a/modules/core/perf/perf_mat.cpp b/modules/core/perf/perf_mat.cpp
new file mode 100644 (file)
index 0000000..3749feb
--- /dev/null
@@ -0,0 +1,96 @@
+#include "perf_precomp.hpp"
+
+using namespace std;
+using namespace cv;
+using namespace perf;
+using std::tr1::make_tuple;
+using std::tr1::get;
+
+PERF_TEST_P(Size_MatType, Mat_Eye,
+            testing::Combine(testing::Values(TYPICAL_MAT_SIZES),
+                             testing::Values(TYPICAL_MAT_TYPES))
+
+             )
+{
+    Size size = get<0>(GetParam());
+    int type = get<1>(GetParam());
+    Mat diagonalMatrix(size.height, size.width, type);
+
+    declare.out(diagonalMatrix);
+
+    TEST_CYCLE()
+    {
+        diagonalMatrix = Mat::eye(size, type);
+    }
+
+    SANITY_CHECK(diagonalMatrix, 1);
+}
+
+PERF_TEST_P(Size_MatType, Mat_Zeros,
+            testing::Combine(testing::Values(TYPICAL_MAT_SIZES),
+                             testing::Values(TYPICAL_MAT_TYPES, CV_32FC3))
+
+             )
+{
+    Size size = get<0>(GetParam());
+    int type = get<1>(GetParam());
+    Mat zeroMatrix(size.height, size.width, type);
+
+    declare.out(zeroMatrix);
+
+    TEST_CYCLE()
+    {
+        zeroMatrix = Mat::zeros(size, type);
+    }
+
+    SANITY_CHECK(zeroMatrix, 1);
+}
+
+PERF_TEST_P(Size_MatType, Mat_Clone,
+            testing::Combine(testing::Values(TYPICAL_MAT_SIZES),
+                             testing::Values(TYPICAL_MAT_TYPES))
+
+             )
+{
+    Size size = get<0>(GetParam());
+    int type = get<1>(GetParam());
+    Mat source(size.height, size.width, type);
+    Mat destination(size.height, size.width, type);;
+
+    declare.in(source, WARMUP_RNG).out(destination);
+
+    TEST_CYCLE()
+    {
+        source.clone();
+    }
+    destination = source.clone();
+
+    SANITY_CHECK(destination, 1);
+}
+
+PERF_TEST_P(Size_MatType, Mat_Clone_Roi,
+            testing::Combine(testing::Values(TYPICAL_MAT_SIZES),
+                             testing::Values(TYPICAL_MAT_TYPES))
+
+             )
+{
+    Size size = get<0>(GetParam());
+    int type = get<1>(GetParam());
+
+    unsigned int width = size.width;
+    unsigned int height = size.height;
+    Mat source(height, width, type);
+    Mat destination(size.height/2, size.width/2, type);
+
+    declare.in(source, WARMUP_RNG).out(destination);
+
+    Mat roi(source, Rect(width/4, height/4, 3*width/4, 3*height/4));
+
+    TEST_CYCLE()
+    {
+        roi.clone();
+    }
+    destination = roi.clone();
+
+    SANITY_CHECK(destination, 1);
+}
diff --git a/modules/features2d/perf/perf_batchDistance.cpp b/modules/features2d/perf/perf_batchDistance.cpp
new file mode 100644 (file)
index 0000000..e95a41c
--- /dev/null
@@ -0,0 +1,175 @@
+#include "perf_precomp.hpp"
+
+using namespace std;
+using namespace cv;
+using namespace perf;
+using std::tr1::make_tuple;
+using std::tr1::get;
+
+CV_FLAGS(NormType, NORM_L1, NORM_L2, NORM_L2SQR, NORM_HAMMING, NORM_HAMMING2)
+CV_ENUM(SourceType, CV_32F, CV_8U)
+CV_ENUM(DestinationType, CV_32F, CV_32S)
+
+typedef std::tr1::tuple<NormType, DestinationType, bool> Norm_Destination_CrossCheck_t;
+typedef perf::TestBaseWithParam<Norm_Destination_CrossCheck_t> Norm_Destination_CrossCheck;
+
+typedef std::tr1::tuple<NormType, bool> Norm_CrossCheck_t;
+typedef perf::TestBaseWithParam<Norm_CrossCheck_t> Norm_CrossCheck;
+
+typedef std::tr1::tuple<SourceType, bool> Source_CrossCheck_t;
+typedef perf::TestBaseWithParam<Source_CrossCheck_t> Source_CrossCheck;
+
+void generateData( Mat& query, Mat& train, const int sourceType );
+
+PERF_TEST_P(Norm_Destination_CrossCheck, batchDistance_8U,
+            testing::Combine(testing::Values((int)NORM_L1, (int)NORM_L2SQR),
+                             testing::Values(CV_32S, CV_32F),
+                             testing::Bool()
+                             )
+            )
+{
+    NormType normType = get<0>(GetParam());
+    DestinationType destinationType = get<1>(GetParam());
+    bool isCrossCheck = get<2>(GetParam());
+
+    Mat queryDescriptors;
+    Mat trainDescriptors;
+    Mat dist;
+    Mat ndix;
+    int knn = 1;
+
+    generateData(queryDescriptors, trainDescriptors, CV_8U);
+    if(!isCrossCheck)
+    {
+        knn = 0;
+    }
+
+    declare.time(30);
+    TEST_CYCLE()
+    {
+        batchDistance(queryDescriptors, trainDescriptors, dist, destinationType, (isCrossCheck) ? ndix : noArray(),
+                      normType, knn, Mat(), 0, isCrossCheck);
+    }
+}
+
+PERF_TEST_P(Norm_CrossCheck, batchDistance_Dest_32S,
+            testing::Combine(testing::Values((int)NORM_HAMMING, (int)NORM_HAMMING2),
+                             testing::Bool()
+                             )
+            )
+{
+    NormType normType = get<0>(GetParam());
+    bool isCrossCheck = get<1>(GetParam());
+
+    Mat queryDescriptors;
+    Mat trainDescriptors;
+    Mat dist;
+    Mat ndix;
+    int knn = 1;
+
+    generateData(queryDescriptors, trainDescriptors, CV_8U);
+    if(!isCrossCheck)
+    {
+        knn = 0;
+    }
+
+    declare.time(30);
+    TEST_CYCLE()
+    {
+        batchDistance(queryDescriptors, trainDescriptors, dist, CV_32S, (isCrossCheck) ? ndix : noArray(),
+                      normType, knn, Mat(), 0, isCrossCheck);
+    }
+}
+
+PERF_TEST_P(Source_CrossCheck, batchDistance_L2,
+            testing::Combine(testing::Values(CV_8U, CV_32F),
+                             testing::Bool()
+                             )
+            )
+{
+    SourceType sourceType = get<0>(GetParam());
+    bool isCrossCheck = get<1>(GetParam());
+
+    Mat queryDescriptors;
+    Mat trainDescriptors;
+    Mat dist;
+    Mat ndix;
+    int knn = 1;
+
+    generateData(queryDescriptors, trainDescriptors, sourceType);
+    if(!isCrossCheck)
+    {
+        knn = 0;
+    }
+
+    declare.time(30);
+    TEST_CYCLE()
+    {
+        batchDistance(queryDescriptors, trainDescriptors, dist, CV_32F, (isCrossCheck) ? ndix : noArray(),
+                      NORM_L2, knn, Mat(), 0, isCrossCheck);
+    }
+}
+
+PERF_TEST_P(Norm_CrossCheck, batchDistance_32F,
+            testing::Combine(testing::Values((int)NORM_L1, (int)NORM_L2SQR),
+                             testing::Bool()
+                             )
+            )
+{
+    NormType normType = get<0>(GetParam());
+    bool isCrossCheck = get<1>(GetParam());
+
+    Mat queryDescriptors;
+    Mat trainDescriptors;
+    Mat dist;
+    Mat ndix;
+    int knn = 1;
+
+    generateData(queryDescriptors, trainDescriptors, CV_32F);
+    if(!isCrossCheck)
+    {
+        knn = 0;
+    }
+
+    declare.time(30);
+    TEST_CYCLE()
+    {
+        batchDistance(queryDescriptors, trainDescriptors, dist, CV_32F, (isCrossCheck) ? ndix : noArray(),
+                      normType, knn, Mat(), 0, isCrossCheck);
+    }
+}
+
+void generateData( Mat& query, Mat& train, const int sourceType )
+{
+    const int dim = 500;
+    const int queryDescCount = 300; // must be even number because we split train data in some cases in two
+    const int countFactor = 4; // do not change it
+    RNG& rng = theRNG();
+
+    // Generate query descriptors randomly.
+    // Descriptor vector elements are integer values.
+    Mat buf( queryDescCount, dim, CV_32SC1 );
+    rng.fill( buf, RNG::UNIFORM, Scalar::all(0), Scalar(3) );
+    buf.convertTo( query, sourceType );
+
+    // Generate train decriptors as follows:
+    // copy each query descriptor to train set countFactor times
+    // and perturb some one element of the copied descriptors in
+    // in ascending order. General boundaries of the perturbation
+    // are (0.f, 1.f).
+    train.create( query.rows*countFactor, query.cols, sourceType );
+    float step = 1.f / countFactor;
+    for( int qIdx = 0; qIdx < query.rows; qIdx++ )
+    {
+        Mat queryDescriptor = query.row(qIdx);
+        for( int c = 0; c < countFactor; c++ )
+        {
+            int tIdx = qIdx * countFactor + c;
+            Mat trainDescriptor = train.row(tIdx);
+            queryDescriptor.copyTo( trainDescriptor );
+            int elem = rng(dim);
+            float diff = rng.uniform( step*c, step*(c+1) );
+            trainDescriptor.at<float>(0, elem) += diff;
+        }
+    }
+}
index bf62f86..c344267 100644 (file)
-#include "perf_precomp.hpp"\r
-#include "opencv2/highgui/highgui.hpp"\r
-#include "opencv2/core/internal.hpp"\r
-#include "opencv2/flann/flann.hpp"\r
-#include "opencv2/opencv_modules.hpp"\r
-\r
-using namespace std;\r
-using namespace cv;\r
-using namespace perf;\r
-using std::tr1::make_tuple;\r
-using std::tr1::get;\r
-\r
-#define SURF_MATCH_CONFIDENCE 0.65f\r
-#define ORB_MATCH_CONFIDENCE  0.3f\r
-#define WORK_MEGAPIX 0.6\r
-\r
-typedef TestBaseWithParam<String> stitch;\r
-typedef TestBaseWithParam<String> match;\r
-\r
-#ifdef HAVE_OPENCV_NONFREE\r
-#define TEST_DETECTORS testing::Values("surf", "orb")\r
-#else\r
-#define TEST_DETECTORS testing::Values<String>("orb")\r
-#endif\r
-\r
-PERF_TEST_P(stitch, a123, TEST_DETECTORS)\r
-{\r
-    Mat pano;\r
-\r
-    vector<Mat> imgs;\r
-    imgs.push_back( imread( getDataPath("stitching/a1.jpg") ) );\r
-    imgs.push_back( imread( getDataPath("stitching/a2.jpg") ) );\r
-    imgs.push_back( imread( getDataPath("stitching/a3.jpg") ) );\r
-\r
-    Ptr<detail::FeaturesFinder> featuresFinder = GetParam() == "orb"\r
-            ? (detail::FeaturesFinder*)new detail::OrbFeaturesFinder()\r
-            : (detail::FeaturesFinder*)new detail::SurfFeaturesFinder();\r
-\r
-    Ptr<detail::FeaturesMatcher> featuresMatcher = GetParam() == "orb"\r
-            ? new detail::BestOf2NearestMatcher(false, ORB_MATCH_CONFIDENCE)\r
-            : new detail::BestOf2NearestMatcher(false, SURF_MATCH_CONFIDENCE);\r
-\r
-    declare.time(30 * 20).iterations(20);\r
-\r
-    while(next())\r
-    {\r
-        Stitcher stitcher = Stitcher::createDefault();\r
-        stitcher.setFeaturesFinder(featuresFinder);\r
-        stitcher.setFeaturesMatcher(featuresMatcher);\r
-        stitcher.setWarper(new SphericalWarper());\r
-        stitcher.setRegistrationResol(WORK_MEGAPIX);\r
-\r
-        startTimer();\r
-        stitcher.stitch(imgs, pano);\r
-        stopTimer();\r
-    }\r
-}\r
-\r
-PERF_TEST_P(stitch, b12, TEST_DETECTORS)\r
-{\r
-    Mat pano;\r
-\r
-    vector<Mat> imgs;\r
-    imgs.push_back( imread( getDataPath("stitching/b1.jpg") ) );\r
-    imgs.push_back( imread( getDataPath("stitching/b2.jpg") ) );\r
-\r
-    Ptr<detail::FeaturesFinder> featuresFinder = GetParam() == "orb"\r
-            ? (detail::FeaturesFinder*)new detail::OrbFeaturesFinder()\r
-            : (detail::FeaturesFinder*)new detail::SurfFeaturesFinder();\r
-\r
-    Ptr<detail::FeaturesMatcher> featuresMatcher = GetParam() == "orb"\r
-            ? new detail::BestOf2NearestMatcher(false, ORB_MATCH_CONFIDENCE)\r
-            : new detail::BestOf2NearestMatcher(false, SURF_MATCH_CONFIDENCE);\r
-\r
-    declare.time(30 * 20).iterations(20);\r
-\r
-    while(next())\r
-    {\r
-        Stitcher stitcher = Stitcher::createDefault();\r
-        stitcher.setFeaturesFinder(featuresFinder);\r
-        stitcher.setFeaturesMatcher(featuresMatcher);\r
-        stitcher.setWarper(new SphericalWarper());\r
-        stitcher.setRegistrationResol(WORK_MEGAPIX);\r
-\r
-        startTimer();\r
-        stitcher.stitch(imgs, pano);\r
-        stopTimer();\r
-    }\r
-}\r
-\r
-PERF_TEST_P( match, bestOf2Nearest, TEST_DETECTORS)\r
-{\r
-    Mat img1, img1_full = imread( getDataPath("stitching/b1.jpg") );\r
-    Mat img2, img2_full = imread( getDataPath("stitching/b2.jpg") );\r
-    float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));\r
-    float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));\r
-    resize(img1_full, img1, Size(), scale1, scale1);\r
-    resize(img2_full, img2, Size(), scale2, scale2);\r
-\r
-    Ptr<detail::FeaturesFinder> finder;\r
-    Ptr<detail::FeaturesMatcher> matcher;\r
-    if (GetParam() == "surf")\r
-    {\r
-        finder = new detail::SurfFeaturesFinder();\r
-        matcher = new detail::BestOf2NearestMatcher(false, SURF_MATCH_CONFIDENCE);\r
-    }\r
-    else if (GetParam() == "orb")\r
-    {\r
-        finder = new detail::OrbFeaturesFinder();\r
-        matcher = new detail::BestOf2NearestMatcher(false, ORB_MATCH_CONFIDENCE);\r
-    }\r
-    else\r
-    {\r
-        FAIL() << "Unknown 2D features type: " << GetParam();\r
-    }\r
-\r
-    detail::ImageFeatures features1, features2;\r
-    (*finder)(img1, features1);\r
-    (*finder)(img2, features2);\r
-\r
-    detail::MatchesInfo pairwise_matches;\r
-\r
-    declare.in(features1.descriptors, features2.descriptors)\r
-            .iterations(100);\r
-\r
-    while(next())\r
-    {\r
-        cvflann::seed_random(42);//for predictive FlannBasedMatcher\r
-        startTimer();\r
-        (*matcher)(features1, features2, pairwise_matches);\r
-        stopTimer();\r
-        matcher->collectGarbage();\r
-    }\r
-}\r
+#include "perf_precomp.hpp"
+#include "opencv2/highgui/highgui.hpp"
+#include "opencv2/core/internal.hpp"
+#include "opencv2/flann/flann.hpp"
+#include "opencv2/opencv_modules.hpp"
+
+using namespace std;
+using namespace cv;
+using namespace perf;
+using std::tr1::make_tuple;
+using std::tr1::get;
+
+#define SURF_MATCH_CONFIDENCE 0.65f
+#define ORB_MATCH_CONFIDENCE  0.3f
+#define WORK_MEGAPIX 0.6
+
+typedef TestBaseWithParam<String> stitch;
+typedef TestBaseWithParam<String> match;
+typedef std::tr1::tuple<String, int> matchVector_t;
+typedef TestBaseWithParam<matchVector_t> matchVector;
+
+#ifdef HAVE_OPENCV_NONFREE
+#define TEST_DETECTORS testing::Values("surf", "orb")
+#else
+#define TEST_DETECTORS testing::Values<String>("orb")
+#endif
+
+PERF_TEST_P(stitch, a123, TEST_DETECTORS)
+{
+    Mat pano;
+
+    vector<Mat> imgs;
+    imgs.push_back( imread( getDataPath("stitching/a1.jpg") ) );
+    imgs.push_back( imread( getDataPath("stitching/a2.jpg") ) );
+    imgs.push_back( imread( getDataPath("stitching/a3.jpg") ) );
+
+    Ptr<detail::FeaturesFinder> featuresFinder = GetParam() == "orb"
+            ? (detail::FeaturesFinder*)new detail::OrbFeaturesFinder()
+            : (detail::FeaturesFinder*)new detail::SurfFeaturesFinder();
+
+    Ptr<detail::FeaturesMatcher> featuresMatcher = GetParam() == "orb"
+            ? new detail::BestOf2NearestMatcher(false, ORB_MATCH_CONFIDENCE)
+            : new detail::BestOf2NearestMatcher(false, SURF_MATCH_CONFIDENCE);
+
+    declare.time(30 * 20).iterations(20);
+
+    while(next())
+    {
+        Stitcher stitcher = Stitcher::createDefault();
+        stitcher.setFeaturesFinder(featuresFinder);
+        stitcher.setFeaturesMatcher(featuresMatcher);
+        stitcher.setWarper(new SphericalWarper());
+        stitcher.setRegistrationResol(WORK_MEGAPIX);
+
+        startTimer();
+        stitcher.stitch(imgs, pano);
+        stopTimer();
+    }
+}
+
+PERF_TEST_P(stitch, b12, TEST_DETECTORS)
+{
+    Mat pano;
+
+    vector<Mat> imgs;
+    imgs.push_back( imread( getDataPath("stitching/b1.jpg") ) );
+    imgs.push_back( imread( getDataPath("stitching/b2.jpg") ) );
+
+    Ptr<detail::FeaturesFinder> featuresFinder = GetParam() == "orb"
+            ? (detail::FeaturesFinder*)new detail::OrbFeaturesFinder()
+            : (detail::FeaturesFinder*)new detail::SurfFeaturesFinder();
+
+    Ptr<detail::FeaturesMatcher> featuresMatcher = GetParam() == "orb"
+            ? new detail::BestOf2NearestMatcher(false, ORB_MATCH_CONFIDENCE)
+            : new detail::BestOf2NearestMatcher(false, SURF_MATCH_CONFIDENCE);
+
+    declare.time(30 * 20).iterations(20);
+
+    while(next())
+    {
+        Stitcher stitcher = Stitcher::createDefault();
+        stitcher.setFeaturesFinder(featuresFinder);
+        stitcher.setFeaturesMatcher(featuresMatcher);
+        stitcher.setWarper(new SphericalWarper());
+        stitcher.setRegistrationResol(WORK_MEGAPIX);
+
+        startTimer();
+        stitcher.stitch(imgs, pano);
+        stopTimer();
+    }
+}
+
+PERF_TEST_P( match, bestOf2Nearest, TEST_DETECTORS)
+{
+    Mat img1, img1_full = imread( getDataPath("stitching/b1.jpg") );
+    Mat img2, img2_full = imread( getDataPath("stitching/b2.jpg") );
+    float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));
+    float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));
+    resize(img1_full, img1, Size(), scale1, scale1);
+    resize(img2_full, img2, Size(), scale2, scale2);
+
+    Ptr<detail::FeaturesFinder> finder;
+    Ptr<detail::FeaturesMatcher> matcher;
+    if (GetParam() == "surf")
+    {
+        finder = new detail::SurfFeaturesFinder();
+        matcher = new detail::BestOf2NearestMatcher(false, SURF_MATCH_CONFIDENCE);
+    }
+    else if (GetParam() == "orb")
+    {
+        finder = new detail::OrbFeaturesFinder();
+        matcher = new detail::BestOf2NearestMatcher(false, ORB_MATCH_CONFIDENCE);
+    }
+    else
+    {
+        FAIL() << "Unknown 2D features type: " << GetParam();
+    }
+
+    detail::ImageFeatures features1, features2;
+    (*finder)(img1, features1);
+    (*finder)(img2, features2);
+
+    detail::MatchesInfo pairwise_matches;
+
+    declare.in(features1.descriptors, features2.descriptors)
+            .iterations(100);
+
+    while(next())
+    {
+        cvflann::seed_random(42);//for predictive FlannBasedMatcher
+        startTimer();
+        (*matcher)(features1, features2, pairwise_matches);
+        stopTimer();
+        matcher->collectGarbage();
+    }
+}
+
+PERF_TEST_P( matchVector, bestOf2NearestVectorFeatures, testing::Combine(
+                 TEST_DETECTORS,
+                 testing::Values(2, 4, 6, 8))
+             )
+{
+    Mat img1, img1_full = imread( getDataPath("stitching/b1.jpg") );
+    Mat img2, img2_full = imread( getDataPath("stitching/b2.jpg") );
+    float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));
+    float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));
+    resize(img1_full, img1, Size(), scale1, scale1);
+    resize(img2_full, img2, Size(), scale2, scale2);
+
+    Ptr<detail::FeaturesFinder> finder;
+    Ptr<detail::FeaturesMatcher> matcher;
+    String detectorName = get<0>(GetParam());
+    int featuresVectorSize = get<1>(GetParam());
+    if (detectorName == "surf")
+    {
+        finder = new detail::SurfFeaturesFinder();
+        matcher = new detail::BestOf2NearestMatcher(false, SURF_MATCH_CONFIDENCE);
+    }
+    else if (detectorName == "orb")
+    {
+        finder = new detail::OrbFeaturesFinder();
+        matcher = new detail::BestOf2NearestMatcher(false, ORB_MATCH_CONFIDENCE);
+    }
+    else
+    {
+        FAIL() << "Unknown 2D features type: " << get<0>(GetParam());
+    }
+
+    detail::ImageFeatures features1, features2;
+    (*finder)(img1, features1);
+    (*finder)(img2, features2);
+    vector<detail::ImageFeatures> features;
+    vector<detail::MatchesInfo> pairwise_matches;
+    for(int i = 0; i < featuresVectorSize/2; i++)
+    {
+        features.push_back(features1);
+        features.push_back(features2);
+    }
+
+    declare.time(200);
+    while(next())
+    {
+        cvflann::seed_random(42);//for predictive FlannBasedMatcher
+        startTimer();
+        (*matcher)(features, pairwise_matches);
+        stopTimer();
+        matcher->collectGarbage();
+    }
+}