diff --git a/modules/imgproc/src/phasecorr_iterative.cpp b/modules/imgproc/src/phasecorr_iterative.cpp index ced9339c87..c2b03190bd 100644 --- a/modules/imgproc/src/phasecorr_iterative.cpp +++ b/modules/imgproc/src/phasecorr_iterative.cpp @@ -1,11 +1,13 @@ #include "precomp.hpp" #include +#include namespace { template void calculateCrossPowerSpectrum(const cv::Mat& dft1, const cv::Mat& dft2, cv::Mat& cps) { + const T eps = std::numeric_limits::epsilon(); // prevent div0 problems for (int row = 0; row < dft1.rows; ++row) { auto* cpsp = cps.ptr>(row); @@ -15,7 +17,7 @@ void calculateCrossPowerSpectrum(const cv::Mat& dft1, const cv::Mat& dft2, cv::M { const T re = dft1p[col][0] * dft2p[col][0] + dft1p[col][1] * dft2p[col][1]; const T im = dft1p[col][0] * dft2p[col][1] - dft1p[col][1] * dft2p[col][0]; - const T mag = std::sqrt(re * re + im * im); + const T mag = std::sqrt(re * re + im * im) + eps; cpsp[col][0] = re / mag; cpsp[col][1] = im / mag; } diff --git a/modules/imgproc/test/test_ipc.cpp b/modules/imgproc/test/test_ipc.cpp index 321b1f2fe3..5e26a6dd14 100644 --- a/modules/imgproc/test/test_ipc.cpp +++ b/modules/imgproc/test/test_ipc.cpp @@ -24,6 +24,17 @@ Mat GenerateTestImage(Size size) return image; } +Mat GenerateGaussianImage(Size size, Point2d center) +{ + Mat image(size, CV_32F); + for (int row = 0; row < size.height; ++row) + for (int col = 0; col < size.width; ++col) + image.at(row, col) = static_cast(std::exp( + -((col - center.x) * (col - center.x) + (row - center.y) * (row - center.y)) / + 32.)); + return image; +} + void TestPhaseCorrelationIterative(const Size& size, const double maxShift) { const auto iters = std::max(201., maxShift * 10 + 1); @@ -114,4 +125,17 @@ TEST(Imgproc_PhaseCorrelationIterative, accuracy_real_img) ASSERT_NEAR(ipcShift.y, (double)yShift, 1.); } +TEST(Imgproc_PhaseCorrelationIterative, accuracy_32f_smooth_img) +{ + const Point2d center(30., 28.); + const Point2d shift(-3., 2.); + const Mat image1 = GenerateGaussianImage(Size(64, 64), center); + const Mat image2 = GenerateGaussianImage(Size(64, 64), center + shift); + + const Point2d ipcShift = phaseCorrelateIterative(image1, image2); + + ASSERT_NEAR(ipcShift.x, shift.x, 1.); + ASSERT_NEAR(ipcShift.y, shift.y, 1.); +} + }} // namespace opencv_test