imgproc: guard against zero magnitude in phaseCorrelateIterative

This commit is contained in:
Lazizbek Ergashev
2026-09-02 18:20:26 +05:00
parent 2ce3cbc260
commit bf4a8248c9
2 changed files with 27 additions and 1 deletions

View File

@@ -1,11 +1,13 @@
#include "precomp.hpp"
#include <cmath>
#include <limits>
namespace {
template <typename T>
void calculateCrossPowerSpectrum(const cv::Mat& dft1, const cv::Mat& dft2, cv::Mat& cps)
{
const T eps = std::numeric_limits<T>::epsilon(); // prevent div0 problems
for (int row = 0; row < dft1.rows; ++row)
{
auto* cpsp = cps.ptr<cv::Vec<T, 2>>(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;
}

View File

@@ -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<float>(row, col) = static_cast<float>(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