diff --git a/modules/core/src/kmeans.cpp b/modules/core/src/kmeans.cpp index bca8b9bd79..544882ef1d 100644 --- a/modules/core/src/kmeans.cpp +++ b/modules/core/src/kmeans.cpp @@ -143,6 +143,8 @@ static void generateCentersPP(const Mat& data, Mat& _out_centers, std::swap(tdist, tdist2); } } + if (bestCenter < 0) + CV_Error(Error::StsNoConv, "kmeans: can't update cluster center (check input for huge or NaN values)"); centers[k] = bestCenter; sum0 = bestSum; std::swap(dist, tdist); diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index 8b13a391cb..066475b19e 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -2949,6 +2949,34 @@ TEST(Core_KMeans, compactness) } } +TEST(Core_KMeans, bad_input) +{ + const int N = 100; + const int attempts = 4; + const TermCriteria crit = TermCriteria(TermCriteria::COUNT, 5, 0); // low number of iterations + const int K = 3; + Mat data(N, 1, CV_32FC2); + cv::randu(data, Scalar(-200, -200), Scalar(200, 200)); + { + SCOPED_TRACE("Huge value"); + data.at(10, 0) = Vec2f(1e20f, 0); + Mat labels, centers; + EXPECT_ANY_THROW(kmeans(data, K, labels, crit, attempts, KMEANS_PP_CENTERS, centers)); + } + { + SCOPED_TRACE("Negative value"); + data.at(10, 0) = Vec2f(0, -1e20f); + Mat labels, centers; + EXPECT_ANY_THROW(kmeans(data, K, labels, crit, attempts, KMEANS_PP_CENTERS, centers)); + } + { + SCOPED_TRACE("NaN"); + data.at(10, 0) = Vec2f(0, std::numeric_limits::quiet_NaN()); + Mat labels, centers; + EXPECT_ANY_THROW(kmeans(data, K, labels, crit, attempts, KMEANS_PP_CENTERS, centers)); + } +} + TEST(CovariationMatrixVectorOfMat, accuracy) { unsigned int col_problem_size = 8, row_problem_size = 8, vector_size = 16;