From db189ed8638ff5bb0ca4cbce8d24e29e04634b74 Mon Sep 17 00:00:00 2001 From: pbkx <93405617+pbkx@users.noreply.github.com> Date: Wed, 16 Sep 2026 18:41:52 -0700 Subject: [PATCH] fix calcCovarMatrix vector mean ROI handling --- modules/core/src/matmul.dispatch.cpp | 14 +++++------- modules/core/test/test_math.cpp | 34 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/modules/core/src/matmul.dispatch.cpp b/modules/core/src/matmul.dispatch.cpp index c78fcc0b7a..37a2b86b91 100644 --- a/modules/core/src/matmul.dispatch.cpp +++ b/modules/core/src/matmul.dispatch.cpp @@ -757,17 +757,15 @@ void calcCovarMatrix( InputArray _src, OutputArray _covar, InputOutputArray _mea if( (flags & cv::COVAR_USE_AVG) != 0 ) { CV_Assert( _mean.size() == size ); + Mat mean0 = _mean.getMat(); - if( mean.type() != ctype ) + if( mean0.isContinuous() && mean0.type() == ctype ) + mean = mean0.reshape(1, 1); + else { - mean = _mean.getMat(); - _mean.create(mean.size(), ctype); - Mat tmp = _mean.getMat(); - mean.convertTo(tmp, ctype); - mean = tmp; + mean0.convertTo(mean, ctype); + mean = mean.reshape(1, 1); } - - mean = _mean.getMat().reshape(1, 1); } calcCovarMatrix( _data, _covar, mean, (flags & ~(cv::COVAR_ROWS|cv::COVAR_COLS)) | cv::COVAR_ROWS, ctype ); diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index 55d0e595bf..ac4df3d937 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -3340,6 +3340,40 @@ TEST(CovariationMatrixVectorOfMatWithMean, accuracy) ASSERT_EQ(sDiff.dot(sDiff), 0.0); } +TEST(CovariationMatrixVectorOfMatWithMean, non_contiguous_mean) +{ + std::vector samples; + samples.push_back((cv::Mat_(2, 2) << 1, 2, 3, 4)); + samples.push_back((cv::Mat_(2, 2) << 2, 4, 6, 8)); + samples.push_back((cv::Mat_(2, 2) << 3, 6, 9, 12)); + + const float sentinel0 = 12345.0f; + const float sentinel1 = -12345.0f; + cv::Mat meanStorage = (cv::Mat_(2, 3) << + 10, 20, sentinel0, + 30, 40, sentinel1); + cv::Mat meanROI = meanStorage(cv::Rect(0, 0, 2, 2)); + cv::Mat expectedMean = meanROI.clone(); + cv::Mat continuousMean = expectedMean.clone(); + ASSERT_TRUE(continuousMean.isContinuous()); + ASSERT_FALSE(meanROI.isContinuous()); + ASSERT_EQ(0, cvtest::norm(expectedMean, meanROI, cv::NORM_INF)); + + const int flags = cv::COVAR_ROWS | cv::COVAR_USE_AVG; + cv::Mat covContinuous, covROI, covPointer; + ASSERT_NO_THROW(cv::calcCovarMatrix(samples, covContinuous, continuousMean, flags, CV_32F)); + ASSERT_NO_THROW(cv::calcCovarMatrix(&samples[0], static_cast(samples.size()), + covPointer, meanROI, flags, CV_32F)); + ASSERT_NO_THROW(cv::calcCovarMatrix(samples, covROI, meanROI, flags, CV_32F)); + + EXPECT_EQ(0, cvtest::norm(covContinuous, covROI, cv::NORM_INF)); + EXPECT_EQ(0, cvtest::norm(covPointer, covROI, cv::NORM_INF)); + EXPECT_EQ(0, cvtest::norm(expectedMean, continuousMean, cv::NORM_INF)); + EXPECT_EQ(0, cvtest::norm(expectedMean, meanROI, cv::NORM_INF)); + EXPECT_EQ(sentinel0, meanStorage.at(0, 2)); + EXPECT_EQ(sentinel1, meanStorage.at(1, 2)); +} + TEST(Core_Pow, special) { for( int i = 0; i < 100; i++ )