From 45c49a9088132b63dc561f51705694cc23b2aeb0 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 ++++++++++ .../features2d/perf/perf_batchDistance.cpp | 175 ++++++++++++++++++ modules/stitching/perf/perf_stich.cpp | 55 ++++++ 4 files changed, 366 insertions(+) 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 315022d9af..9608c7c284 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 0000000000..3749feb384 --- /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 0000000000..e95a41c1df --- /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 dd97bb2789..c344267317 100644 --- a/modules/stitching/perf/perf_stich.cpp +++ b/modules/stitching/perf/perf_stich.cpp @@ -16,6 +16,8 @@ using std::tr1::get; 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") @@ -132,3 +134,56 @@ PERF_TEST_P( match, bestOf2Nearest, TEST_DETECTORS) 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(); + } +}