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

OpenCV指定坐标范围筛选轮廓时boundingRect报断言错误解决

报错触发原因

代码存在两处逻辑错误直接触发OpenCV断言:

  • 入参类型错误:cv.contourArea(cnt)返回值是表示轮廓面积的浮点数,并非轮廓点集。你将这个数值传入要求接收轮廓点数组的cv.boundingRect(),完全不符合函数入参规范,直接触发npoints >= 0 && (depth == CV_32F || depth == CV_32S)的断言失败。
  • 存储对象错误:筛选逻辑中你往filtercnts列表存入的是轮廓面积数值,不是轮廓对象本身,后续取最大值时也无法得到合法轮廓。
修复方案

按以下规则调整代码即可:

  1. 调用cv.boundingRect()时,入参传入原始轮廓对象cnt,不要传入contourArea返回的面积值
  2. 坐标校验通过后,将原始轮廓对象cnt加入筛选列表,不要存面积值
  3. 从筛选后列表取最大轮廓时,传入cv.contourArea作为max函数的取值key,和无筛选场景的逻辑保持一致
修复后完整代码
def detectObject(self, lower, upper, topVal = False, botVal = False):
    # 阈值分割HSV图像提取目标颜色区域
    mask = cv.inRange(self.hsv, lower, upper)
    cnts = self.findContours(mask)
    filtercnts = []
    cntArea = None
    if len(cnts) > 0:
        # topVal为Y轴区间下限,botVal为Y轴区间上限
        if botVal is not False and topVal is not False:
            for cnt in cnts:
                if self.is_bad_contour(cnt) == False:
                    # 传入轮廓点集计算外接矩形
                    (xg, yg, wg, hg) = cv.boundingRect(cnt)
                    # 校验Y坐标是否落在指定区间
                    if yg > topVal and yg < botVal:
                        # 存入合法轮廓对象
                        filtercnts.append(cnt)
            
            if len(filtercnts) > 0:
                # 取筛选后列表中面积最大的轮廓
                cntArea = max(filtercnts, key=cv.contourArea)
        else:
            cntArea = max(cnts, key=cv.contourArea)

    return cntArea

可选优化

如果你的需求是轮廓质心落在质心上下75像素的Y轴区间,而非轮廓外接矩形左上角落在区间,可以将坐标判断逻辑替换为质心计算逻辑,精度更高:

for cnt in cnts:
    if self.is_bad_contour(cnt) == False:
        M = cv.moments(cnt)
        # 跳过面积为0的无效轮廓
        if M["m00"] == 0:
            continue
        # 计算轮廓质心Y坐标
        cy = int(M["m01"] / M["m00"])
        if topVal < cy < botVal:
            filtercnts.append(cnt)

内容的提问来源于stack exchange,提问作者I try so hard but I cry harder

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 00:45:38