test_undistort_points.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. class CV_UndistortTest : public cvtest::BaseTest
  7. {
  8. public:
  9. CV_UndistortTest();
  10. ~CV_UndistortTest();
  11. protected:
  12. void run(int);
  13. private:
  14. void generate3DPointCloud(vector<Point3f>& points, Point3f pmin = Point3f(-1,
  15. -1, 5), Point3f pmax = Point3f(1, 1, 10));
  16. void generateCameraMatrix(Mat& cameraMatrix);
  17. void generateDistCoeffs(Mat& distCoeffs, int count);
  18. double thresh;
  19. RNG rng;
  20. };
  21. CV_UndistortTest::CV_UndistortTest()
  22. {
  23. thresh = 1.0e-2;
  24. }
  25. CV_UndistortTest::~CV_UndistortTest() {}
  26. void CV_UndistortTest::generate3DPointCloud(vector<Point3f>& points, Point3f pmin, Point3f pmax)
  27. {
  28. RNG rng_Point = cv::theRNG(); // fix the seed to use "fixed" input 3D points
  29. for (size_t i = 0; i < points.size(); i++)
  30. {
  31. float _x = rng_Point.uniform(pmin.x, pmax.x);
  32. float _y = rng_Point.uniform(pmin.y, pmax.y);
  33. float _z = rng_Point.uniform(pmin.z, pmax.z);
  34. points[i] = Point3f(_x, _y, _z);
  35. }
  36. }
  37. void CV_UndistortTest::generateCameraMatrix(Mat& cameraMatrix)
  38. {
  39. const double fcMinVal = 1e-3;
  40. const double fcMaxVal = 100;
  41. cameraMatrix.create(3, 3, CV_64FC1);
  42. cameraMatrix.setTo(Scalar(0));
  43. cameraMatrix.at<double>(0,0) = rng.uniform(fcMinVal, fcMaxVal);
  44. cameraMatrix.at<double>(1,1) = rng.uniform(fcMinVal, fcMaxVal);
  45. cameraMatrix.at<double>(0,2) = rng.uniform(fcMinVal, fcMaxVal);
  46. cameraMatrix.at<double>(1,2) = rng.uniform(fcMinVal, fcMaxVal);
  47. cameraMatrix.at<double>(2,2) = 1;
  48. }
  49. void CV_UndistortTest::generateDistCoeffs(Mat& distCoeffs, int count)
  50. {
  51. distCoeffs = Mat::zeros(count, 1, CV_64FC1);
  52. for (int i = 0; i < count; i++)
  53. distCoeffs.at<double>(i,0) = rng.uniform(0.0, 1.0e-3);
  54. }
  55. void CV_UndistortTest::run(int /* start_from */)
  56. {
  57. Mat intrinsics, distCoeffs;
  58. generateCameraMatrix(intrinsics);
  59. vector<Point3f> points(500);
  60. generate3DPointCloud(points);
  61. vector<Point2f> projectedPoints;
  62. projectedPoints.resize(points.size());
  63. int modelMembersCount[] = {4,5,8};
  64. for (int idx = 0; idx < 3; idx++)
  65. {
  66. generateDistCoeffs(distCoeffs, modelMembersCount[idx]);
  67. projectPoints(Mat(points), Mat::zeros(3,1,CV_64FC1), Mat::zeros(3,1,CV_64FC1), intrinsics, distCoeffs, projectedPoints);
  68. vector<Point2f> realUndistortedPoints;
  69. projectPoints(Mat(points), Mat::zeros(3,1,CV_64FC1), Mat::zeros(3,1,CV_64FC1), intrinsics, Mat::zeros(4,1,CV_64FC1), realUndistortedPoints);
  70. Mat undistortedPoints;
  71. undistortPoints(Mat(projectedPoints), undistortedPoints, intrinsics, distCoeffs);
  72. Mat p;
  73. perspectiveTransform(undistortedPoints, p, intrinsics);
  74. undistortedPoints = p;
  75. double diff = cvtest::norm(Mat(realUndistortedPoints), undistortedPoints, NORM_L2);
  76. if (diff > thresh)
  77. {
  78. ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
  79. return;
  80. }
  81. ts->set_failed_test_info(cvtest::TS::OK);
  82. }
  83. }
  84. TEST(Calib3d_Undistort, accuracy) { CV_UndistortTest test; test.safe_run(); }
  85. TEST(Calib3d_Undistort, stop_criteria)
  86. {
  87. Mat cameraMatrix = (Mat_<double>(3,3,CV_64F) << 857.48296979, 0, 968.06224829,
  88. 0, 876.71824265, 556.37145899,
  89. 0, 0, 1);
  90. Mat distCoeffs = (Mat_<double>(5,1,CV_64F) <<
  91. -2.57614020e-01, 8.77086999e-02, -2.56970803e-04, -5.93390389e-04, -1.52194091e-02);
  92. RNG rng(2);
  93. Point2d pt_distorted(rng.uniform(0.0, 1920.0), rng.uniform(0.0, 1080.0));
  94. std::vector<Point2d> pt_distorted_vec;
  95. pt_distorted_vec.push_back(pt_distorted);
  96. const double maxError = 1e-6;
  97. TermCriteria criteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 100, maxError);
  98. std::vector<Point2d> pt_undist_vec;
  99. undistortPoints(pt_distorted_vec, pt_undist_vec, cameraMatrix, distCoeffs, noArray(), noArray(), criteria);
  100. std::vector<Point2d> pt_redistorted_vec;
  101. std::vector<Point3d> pt_undist_vec_homogeneous;
  102. pt_undist_vec_homogeneous.push_back( Point3d(pt_undist_vec[0].x, pt_undist_vec[0].y, 1.0) );
  103. projectPoints(pt_undist_vec_homogeneous, Mat::zeros(3,1,CV_64F), Mat::zeros(3,1,CV_64F), cameraMatrix, distCoeffs, pt_redistorted_vec);
  104. const double obtainedError = sqrt( pow(pt_distorted.x - pt_redistorted_vec[0].x, 2) + pow(pt_distorted.y - pt_redistorted_vec[0].y, 2) );
  105. ASSERT_LE(obtainedError, maxError);
  106. }
  107. TEST(undistortPoints, regression_14583)
  108. {
  109. const int col = 720;
  110. // const int row = 540;
  111. float camera_matrix_value[] = {
  112. 437.8995f, 0.0f, 342.9241f,
  113. 0.0f, 438.8216f, 273.7163f,
  114. 0.0f, 0.0f, 1.0f
  115. };
  116. cv::Mat camera_interior(3, 3, CV_32F, camera_matrix_value);
  117. float camera_distort_value[] = {-0.34329f, 0.11431f, 0.0f, 0.0f, -0.017375f};
  118. cv::Mat camera_distort(1, 5, CV_32F, camera_distort_value);
  119. float distort_points_value[] = {col, 0.};
  120. cv::Mat distort_pt(1, 1, CV_32FC2, distort_points_value);
  121. cv::Mat undistort_pt;
  122. cv::undistortPoints(distort_pt, undistort_pt, camera_interior,
  123. camera_distort, cv::Mat(), camera_interior);
  124. EXPECT_NEAR(distort_pt.at<Vec2f>(0)[0], undistort_pt.at<Vec2f>(0)[0], col / 2)
  125. << "distort point: " << distort_pt << std::endl
  126. << "undistort point: " << undistort_pt;
  127. }
  128. }} // namespace