test_ipc.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. #include <vector>
  6. namespace opencv_test { namespace {
  7. Mat CropMid(InputArray src, int w, int h)
  8. {
  9. Mat mat = src.getMat();
  10. return mat(Rect(mat.cols / 2 - w / 2, mat.rows / 2 - h / 2, w, h));
  11. }
  12. Mat GenerateTestImage(Size size)
  13. {
  14. Mat image = Mat::zeros(size.height * 2, size.width * 2, CV_32F);
  15. rectangle(image,
  16. Point(static_cast<int>(size.width * 0.1), static_cast<int>(size.height * 0.1)),
  17. Point(static_cast<int>(size.width * 0.9), static_cast<int>(size.height * 0.9)),
  18. Scalar(1),
  19. -1);
  20. return image;
  21. }
  22. void TestPhaseCorrelationIterative(const Size& size, const double maxShift)
  23. {
  24. const auto iters = std::max(201., maxShift * 10 + 1);
  25. const Point2d shiftOffset(-maxShift * 0.5, -maxShift * 0.5);
  26. Mat image1 = GenerateTestImage(size);
  27. Mat crop1 = CropMid(image1, size.width, size.height);
  28. Mat image2 = image1.clone();
  29. std::vector<double> pcErrors;
  30. std::vector<double> ipcErrors;
  31. for (int i = 0; i < iters; ++i)
  32. {
  33. const auto shift =
  34. Point2d(maxShift * i / (iters - 1), maxShift * i / (iters - 1)) + shiftOffset;
  35. const Mat Tmat = (Mat_<double>(2, 3) << 1., 0., shift.x, 0., 1., shift.y);
  36. warpAffine(image1, image2, Tmat, image2.size());
  37. Mat crop2 = CropMid(image2, size.width, size.height);
  38. const auto ipcshift = phaseCorrelateIterative(crop1, crop2);
  39. const auto pcshift = phaseCorrelate(crop1, crop2);
  40. pcErrors.push_back(
  41. 0.5 * std::abs(pcshift.x - shift.y) + 0.5 * std::abs(pcshift.y - shift.x));
  42. ipcErrors.push_back(
  43. 0.5 * std::abs(ipcshift.x - shift.y) + 0.5 * std::abs(ipcshift.y - shift.x));
  44. // error should be low
  45. EXPECT_NEAR(ipcshift.x - shift.x, 0.0, 0.1);
  46. EXPECT_NEAR(ipcshift.y - shift.y, 0.0, 0.1);
  47. }
  48. cv::Scalar pcMean, pcStddev, ipcMean, ipcStddev;
  49. meanStdDev(ipcErrors, ipcMean, ipcStddev);
  50. meanStdDev(pcErrors, pcMean, pcStddev);
  51. // average error should be low
  52. ASSERT_LT(ipcMean[0], 0.03);
  53. // average error should be less than non-iterative average error
  54. ASSERT_LT(ipcMean[0], pcMean[0]);
  55. // error stddev should be less than non-iterative error stddev
  56. ASSERT_LT(ipcStddev[0], pcStddev[0]);
  57. }
  58. TEST(Imgproc_PhaseCorrelationIterative, 256x128_accuracy)
  59. {
  60. TestPhaseCorrelationIterative(Size(256, 128), 1);
  61. }
  62. TEST(Imgproc_PhaseCorrelationIterative, 64x64_accuracy_shift_1)
  63. {
  64. TestPhaseCorrelationIterative(Size(64, 64), 1);
  65. }
  66. TEST(Imgproc_PhaseCorrelationIterative, 64x64_accuracy_shift_16)
  67. {
  68. TestPhaseCorrelationIterative(Size(64, 64), 16);
  69. }
  70. TEST(Imgproc_PhaseCorrelationIterative, 0x0_image)
  71. {
  72. ASSERT_ANY_THROW(TestPhaseCorrelationIterative(Size(0, 0), 1));
  73. }
  74. TEST(Imgproc_PhaseCorrelationIterative, 1x1_image)
  75. {
  76. ASSERT_ANY_THROW(TestPhaseCorrelationIterative(Size(1, 1), 1));
  77. }
  78. TEST(Imgproc_PhaseCorrelationIterative, accuracy_real_img)
  79. {
  80. Mat img = imread(cvtest::TS::ptr()->get_data_path() + "shared/airplane.png", IMREAD_GRAYSCALE);
  81. if (img.empty())
  82. return;
  83. img.convertTo(img, CV_64FC1);
  84. const int xLen = 256;
  85. const int yLen = 256;
  86. const int xShift = 40;
  87. const int yShift = 14;
  88. Mat roi1 = img(Rect(xShift, yShift, xLen, yLen));
  89. Mat roi2 = img(Rect(0, 0, xLen, yLen));
  90. const Point2d ipcShift = phaseCorrelateIterative(roi1, roi2);
  91. ASSERT_NEAR(ipcShift.x, (double)xShift, 1.);
  92. ASSERT_NEAR(ipcShift.y, (double)yShift, 1.);
  93. }
  94. }} // namespace opencv_test