From d3c539bf7173b4d92a8b2869b11bbbdd63e644a6 Mon Sep 17 00:00:00 2001 From: Dheeraj Alamuri Date: Tue, 23 Dec 2025 23:23:43 +0530 Subject: [PATCH] Merge pull request #28227 from dheeraj25406:docs-moments-degenerate docs(imgproc): clarify cv::moments behavior for degenerate contours #28227 relates to https://github.com/opencv/opencv/issues/28222 Clarifies that for degenerate contours (single point or collinear points), cv::moments() returns m00 == 0 and centroid is undefined. Documents common workarounds such as boundingRect center or point averaging. --- modules/imgproc/include/opencv2/imgproc.hpp | 12 ++++++++++++ modules/imgproc/test/test_contours.cpp | 15 +++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index e02d57875e..375c0ab9bb 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -3876,6 +3876,18 @@ used for images only. @note Only applicable to contour moments calculations from Python bindings: Note that the numpy type for the input array should be either np.int32 or np.float32. +@note For contour-based moments, the zeroth-order moment \c m00 represents +the contour area. + +If the input contour is degenerate (for example, a single point or all points +are collinear), the area is zero and therefore \c m00 == 0. + +In this case, the centroid coordinates (\c m10/m00, \c m01/m00) are undefined +and must be handled explicitly by the caller. + +A common workaround is to compute the center using cv::boundingRect() or by +averaging the input points. + @sa contourArea, arcLength */ CV_EXPORTS_W Moments moments( InputArray array, bool binaryImage = false ); diff --git a/modules/imgproc/test/test_contours.cpp b/modules/imgproc/test/test_contours.cpp index 5fb88dce32..9e76cfabb2 100644 --- a/modules/imgproc/test/test_contours.cpp +++ b/modules/imgproc/test/test_contours.cpp @@ -593,5 +593,20 @@ TEST(Imgproc_PointPolygonTest, regression_10222) EXPECT_GT(result, 0) << "Desired result: point is inside polygon - actual result: point is not inside polygon"; } +TEST(Imgproc_Moments, degenerateContours) +{ + std::vector c1; + c1.push_back(cv::Point(10,10)); + cv::Moments m1 = cv::moments(c1, false); + EXPECT_EQ(m1.m00, 0); + + std::vector c2; + c2.push_back(cv::Point(0,0)); + c2.push_back(cv::Point(5,5)); + c2.push_back(cv::Point(10,10)); + cv::Moments m2 = cv::moments(c2, false); + EXPECT_EQ(m2.m00, 0); +} + }} // namespace /* End of file. */