OpenCV计算目标中心与面积时因moments()返回零触发ZeroDivisionError
修复OpenCV计算二值掩码目标面积和中心时的ZeroDivisionError问题
问题根源
你遇到的ZeroDivisionError是因为其中一个轮廓是一维线段(对应掩码底部的整行1),这类轮廓的面积为0,导致计算矩时M["m00"](零阶矩,代表面积)为0,触发除法错误。OpenCV的findContours会检测所有连通的前景区域,包括仅由线组成的一维结构。
修复方案
1. 过滤无效轮廓(零面积)
在处理轮廓前,先筛选掉面积小于极小阈值的轮廓(避免浮点精度误差):
import numpy as np import cv2 binary_mask = np.array([ [0, 0, 1, 1, 0, 0], [0, 0, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1]]) contours, _ = cv2.findContours( binary_mask.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 过滤掉面积接近0的轮廓 valid_contours = [cnt for cnt in contours if cv2.contourArea(cnt) > 1e-6]
2. 增强中心计算函数的鲁棒性
在计算中心前,先检查M["m00"]是否有效,避免除法错误:
def get_centroid_from_contour(contour): M = cv2.moments(contour) if M["m00"] < 1e-6: return None # 无有效面积,返回None cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) return (cX, cY) # 处理有效轮廓 for cnt in valid_contours: area = cv2.contourArea(cnt) centroid = get_centroid_from_contour(cnt) print(f"面积: {area}, 中心坐标: {centroid}")
3. 可选:调整轮廓检测模式(针对特定场景)
如果你只关心闭合的二维区域,可以尝试调整findContours的检索模式(如cv2.RETR_CCOMP或cv2.RETR_TREE),但过滤零面积轮廓是更通用的解决方案。
测试结果
运行上述代码后,只会处理2×2的方形目标:
面积: 4.0, 中心坐标: (2, 0)
(注:实际浮点中心为(2.5, 0.5),可根据需求修改代码保留小数)
内容的提问来源于stack exchange,提问作者Luca Clissa
相关产品推荐
相关产品推荐

