From 39d6adea173e81df8eeada17d558f42310849152 Mon Sep 17 00:00:00 2001 From: Daniil Osokin Date: Fri, 10 Aug 2012 16:39:36 +0400 Subject: [PATCH] Added perf test --- modules/calib3d/perf/perf_pnp.cpp | 40 +++ modules/core/perf/perf_mat.cpp | 96 ++++++++ modules/features2d/perf/perf_batchDistance.cpp | 175 ++++++++++++++ modules/stitching/perf/perf_stich.cpp | 323 +++++++++++++++---------- 4 files changed, 500 insertions(+), 134 deletions(-) create mode 100644 modules/core/perf/perf_mat.cpp create mode 100644 modules/features2d/perf/perf_batchDistance.cpp diff --git a/modules/calib3d/perf/perf_pnp.cpp b/modules/calib3d/perf/perf_pnp.cpp index 315022d..9608c7c 100644 --- a/modules/calib3d/perf/perf_pnp.cpp +++ b/modules/calib3d/perf/perf_pnp.cpp @@ -11,6 +11,8 @@ CV_ENUM(pnpAlgo, CV_ITERATIVE, CV_EPNP /*, CV_P3P*/) typedef std::tr1::tuple PointsNum_Algo_t; typedef perf::TestBaseWithParam PointsNum_Algo; +typedef perf::TestBaseWithParam 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(0, 1) = 0.f; + camera_mat.at(1, 0) = 0.f; + camera_mat.at(2, 0) = 0.f; + camera_mat.at(2, 1) = 0.f; + + Mat dist_coef(1, 8, CV_32F, cv::Scalar::all(0)); + + vector 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 index 0000000..3749feb --- /dev/null +++ b/modules/core/perf/perf_mat.cpp @@ -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 index 0000000..e95a41c --- /dev/null +++ b/modules/features2d/perf/perf_batchDistance.cpp @@ -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 Norm_Destination_CrossCheck_t; +typedef perf::TestBaseWithParam Norm_Destination_CrossCheck; + +typedef std::tr1::tuple Norm_CrossCheck_t; +typedef perf::TestBaseWithParam Norm_CrossCheck; + +typedef std::tr1::tuple Source_CrossCheck_t; +typedef perf::TestBaseWithParam 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(0, elem) += diff; + } + } +} diff --git a/modules/stitching/perf/perf_stich.cpp b/modules/stitching/perf/perf_stich.cpp index bf62f86..c344267 100644 --- a/modules/stitching/perf/perf_stich.cpp +++ b/modules/stitching/perf/perf_stich.cpp @@ -1,134 +1,189 @@ -#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 stitch; -typedef TestBaseWithParam match; - -#ifdef HAVE_OPENCV_NONFREE -#define TEST_DETECTORS testing::Values("surf", "orb") -#else -#define TEST_DETECTORS testing::Values("orb") -#endif - -PERF_TEST_P(stitch, a123, TEST_DETECTORS) -{ - Mat pano; - - vector 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 featuresFinder = GetParam() == "orb" - ? (detail::FeaturesFinder*)new detail::OrbFeaturesFinder() - : (detail::FeaturesFinder*)new detail::SurfFeaturesFinder(); - - Ptr 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 imgs; - imgs.push_back( imread( getDataPath("stitching/b1.jpg") ) ); - imgs.push_back( imread( getDataPath("stitching/b2.jpg") ) ); - - Ptr featuresFinder = GetParam() == "orb" - ? (detail::FeaturesFinder*)new detail::OrbFeaturesFinder() - : (detail::FeaturesFinder*)new detail::SurfFeaturesFinder(); - - Ptr 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 finder; - Ptr 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(); - } -} +#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 stitch; +typedef TestBaseWithParam match; +typedef std::tr1::tuple matchVector_t; +typedef TestBaseWithParam matchVector; + +#ifdef HAVE_OPENCV_NONFREE +#define TEST_DETECTORS testing::Values("surf", "orb") +#else +#define TEST_DETECTORS testing::Values("orb") +#endif + +PERF_TEST_P(stitch, a123, TEST_DETECTORS) +{ + Mat pano; + + vector 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 featuresFinder = GetParam() == "orb" + ? (detail::FeaturesFinder*)new detail::OrbFeaturesFinder() + : (detail::FeaturesFinder*)new detail::SurfFeaturesFinder(); + + Ptr 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 imgs; + imgs.push_back( imread( getDataPath("stitching/b1.jpg") ) ); + imgs.push_back( imread( getDataPath("stitching/b2.jpg") ) ); + + Ptr featuresFinder = GetParam() == "orb" + ? (detail::FeaturesFinder*)new detail::OrbFeaturesFinder() + : (detail::FeaturesFinder*)new detail::SurfFeaturesFinder(); + + Ptr 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 finder; + Ptr 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 finder; + Ptr 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 features; + vector 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(); + } +} -- 2.7.4