You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 17:18:13