test_motion_estimation.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html
  4. #include "test_precomp.hpp"
  5. namespace opencv_test { namespace {
  6. namespace testUtil
  7. {
  8. cv::RNG rng(/*std::time(0)*/0);
  9. const float sigma = 1.f;
  10. const float pointsMaxX = 500.f;
  11. const float pointsMaxY = 500.f;
  12. const int testRun = 5000;
  13. void generatePoints(cv::Mat points);
  14. void addNoise(cv::Mat points);
  15. cv::Mat generateTransform(const cv::videostab::MotionModel model);
  16. double performTest(const cv::videostab::MotionModel model, int size);
  17. }
  18. void testUtil::generatePoints(cv::Mat points)
  19. {
  20. CV_Assert(!points.empty());
  21. for(int i = 0; i < points.cols; ++i)
  22. {
  23. points.at<float>(0, i) = rng.uniform(0.f, pointsMaxX);
  24. points.at<float>(1, i) = rng.uniform(0.f, pointsMaxY);
  25. points.at<float>(2, i) = 1.f;
  26. }
  27. }
  28. void testUtil::addNoise(cv::Mat points)
  29. {
  30. CV_Assert(!points.empty());
  31. for(int i = 0; i < points.cols; i++)
  32. {
  33. points.at<float>(0, i) += static_cast<float>(rng.gaussian(sigma));
  34. points.at<float>(1, i) += static_cast<float>(rng.gaussian(sigma));
  35. }
  36. }
  37. cv::Mat testUtil::generateTransform(const cv::videostab::MotionModel model)
  38. {
  39. /*----------Params----------*/
  40. const float minAngle = 0.f, maxAngle = static_cast<float>(CV_PI);
  41. const float minScale = 0.5f, maxScale = 2.f;
  42. const float maxTranslation = 100.f;
  43. const float affineCoeff = 3.f;
  44. /*----------Params----------*/
  45. cv::Mat transform = cv::Mat::eye(3, 3, CV_32F);
  46. if(model != cv::videostab::MM_ROTATION)
  47. {
  48. transform.at<float>(0,2) = rng.uniform(-maxTranslation, maxTranslation);
  49. transform.at<float>(1,2) = rng.uniform(-maxTranslation, maxTranslation);
  50. }
  51. if(model != cv::videostab::MM_AFFINE)
  52. {
  53. if(model != cv::videostab::MM_TRANSLATION_AND_SCALE &&
  54. model != cv::videostab::MM_TRANSLATION)
  55. {
  56. const float angle = rng.uniform(minAngle, maxAngle);
  57. transform.at<float>(1,1) = transform.at<float>(0,0) = std::cos(angle);
  58. transform.at<float>(0,1) = std::sin(angle);
  59. transform.at<float>(1,0) = -transform.at<float>(0,1);
  60. }
  61. if(model == cv::videostab::MM_TRANSLATION_AND_SCALE ||
  62. model == cv::videostab::MM_SIMILARITY)
  63. {
  64. const float scale = rng.uniform(minScale, maxScale);
  65. transform.at<float>(0,0) *= scale;
  66. transform.at<float>(1,1) *= scale;
  67. }
  68. }
  69. else
  70. {
  71. transform.at<float>(0,0) = rng.uniform(-affineCoeff, affineCoeff);
  72. transform.at<float>(0,1) = rng.uniform(-affineCoeff, affineCoeff);
  73. transform.at<float>(1,0) = rng.uniform(-affineCoeff, affineCoeff);
  74. transform.at<float>(1,1) = rng.uniform(-affineCoeff, affineCoeff);
  75. }
  76. return transform;
  77. }
  78. double testUtil::performTest(const cv::videostab::MotionModel model, int size)
  79. {
  80. cv::Ptr<cv::videostab::MotionEstimatorRansacL2> estimator = cv::makePtr<cv::videostab::MotionEstimatorRansacL2>(model);
  81. estimator->setRansacParams(cv::videostab::RansacParams(size, 3.f*testUtil::sigma /*3 sigma rule*/, 0.5f, 0.5f));
  82. double disparity = 0.;
  83. for(int attempt = 0; attempt < testUtil::testRun; attempt++)
  84. {
  85. const cv::Mat transform = testUtil::generateTransform(model);
  86. const int pointsNumber = testUtil::rng.uniform(10, 100);
  87. cv::Mat points(3, pointsNumber, CV_32F);
  88. testUtil::generatePoints(points);
  89. cv::Mat transformedPoints = transform * points;
  90. testUtil::addNoise(transformedPoints);
  91. const cv::Mat src = points.rowRange(0,2).t();
  92. const cv::Mat dst = transformedPoints.rowRange(0,2).t();
  93. bool isOK = false;
  94. const cv::Mat estTransform = estimator->estimate(src.reshape(2), dst.reshape(2), &isOK);
  95. CV_Assert(isOK);
  96. const cv::Mat testPoints = estTransform * points;
  97. const double norm = cv::norm(testPoints, transformedPoints, cv::NORM_INF);
  98. disparity = std::max(disparity, norm);
  99. }
  100. return disparity;
  101. }
  102. TEST(Regression, MM_TRANSLATION)
  103. {
  104. EXPECT_LT(testUtil::performTest(cv::videostab::MM_TRANSLATION, 2), 7.f);
  105. }
  106. TEST(Regression, MM_TRANSLATION_AND_SCALE)
  107. {
  108. EXPECT_LT(testUtil::performTest(cv::videostab::MM_TRANSLATION_AND_SCALE, 3), 7.f);
  109. }
  110. TEST(Regression, MM_ROTATION)
  111. {
  112. EXPECT_LT(testUtil::performTest(cv::videostab::MM_ROTATION, 2), 7.f);
  113. }
  114. TEST(Regression, MM_RIGID)
  115. {
  116. EXPECT_LT(testUtil::performTest(cv::videostab::MM_RIGID, 3), 7.f);
  117. }
  118. TEST(Regression, MM_SIMILARITY)
  119. {
  120. EXPECT_LT(testUtil::performTest(cv::videostab::MM_SIMILARITY, 4), 7.f);
  121. }
  122. TEST(Regression, MM_AFFINE)
  123. {
  124. EXPECT_LT(testUtil::performTest(cv::videostab::MM_AFFINE, 6), 9.f);
  125. }
  126. }} // namespace