OpenCV指定坐标范围筛选轮廓时boundingRect报断言错误解决
报错触发原因
代码存在两处逻辑错误直接触发OpenCV断言:
- 入参类型错误:
cv.contourArea(cnt)返回值是表示轮廓面积的浮点数,并非轮廓点集。你将这个数值传入要求接收轮廓点数组的cv.boundingRect(),完全不符合函数入参规范,直接触发npoints >= 0 && (depth == CV_32F || depth == CV_32S)的断言失败。 - 存储对象错误:筛选逻辑中你往
filtercnts列表存入的是轮廓面积数值,不是轮廓对象本身,后续取最大值时也无法得到合法轮廓。
修复方案
按以下规则调整代码即可:
- 调用
cv.boundingRect()时,入参传入原始轮廓对象cnt,不要传入contourArea返回的面积值 - 坐标校验通过后,将原始轮廓对象
cnt加入筛选列表,不要存面积值 - 从筛选后列表取最大轮廓时,传入
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
相关产品推荐
相关产品推荐

