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. */