OpenCV4.5.1摄像头实时轮廓检测时cv2.drawContours()报错如何解决
报错根源
当前触发的OpenCV断言错误,本质是两处对API规则的理解偏差:
- 对
cv2.findContours的返回值结构认知错误
OpenCV 4.x版本中,findContours会返回三元组结果:(被修改的二值图, 轮廓列表, 轮廓层级关系),而非单独的轮廓列表。原代码直接把整个三元组赋值给contours变量,后续遍历过程中,会把二值图、层级数组都当成轮廓集合传入绘制函数。 - 对
cv2.drawContours的参数规则认知错误drawContours的第二个参数要求传入完整的轮廓集合数组,第三个参数contourIdx必须是集合内的合法索引(满足0 <= contourIdx < 集合内轮廓总数)。原代码在循环内每次把单个数组元素(二值图、层级数组、甚至单条轮廓)作为第二个参数传入,OpenCV内部解析时计算出的合法索引范围上限远小于传入的contourIdx=1,直接触发断言失败。
修正方案
按照API规则调整逻辑后,可直接运行的完整代码如下:
import cv2 import sys import time import numpy as np cap = cv2.VideoCapture(0) if not cap.isOpened(): print("无法打开摄像头") sys.exit(1) while True: ret, frame = cap.read() # 单帧读取失败时直接跳过,避免空帧引发后续处理报错 if not ret: print("当前帧读取失败,跳过") time.sleep(0.1) continue gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) thresh, binary = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY) # 正确拆分findContours的三元返回值,非必要返回值用_占位 _ , contours, hierarchy = cv2.findContours(binary, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE) # 存在有效轮廓时再执行绘制 if len(contours) > 0: # 过滤面积过小的噪点轮廓,避免画面被细碎线条干扰 valid_contours = [] for cnt in contours: if cv2.contourArea(cnt) > 100: valid_contours.append(cnt) # contourIdx=-1代表绘制传入集合内的所有轮廓 cv2.drawContours(frame, valid_contours, -1, (0, 0, 255), 3) cv2.imshow("frame", frame) key = cv2.waitKey(1) time.sleep(0.05) # 按下ESC键退出循环 if key == 27: break cap.release() cv2.destroyAllWindows()
关键注意事项
- 版本差异适配:OpenCV 3.x版本的
findContours返回二元组(轮廓列表, 层级),4.x版本新增了第一个返回的修改后二值图,直接照搬旧版本代码会出现返回值结构解析错误。 - 绘制参数规范:调用
drawContours时,即使要画单个轮廓,也不能把单个轮廓数组直接作为第二个参数传入——要么把单个轮廓包成列表格式[cnt]传入,要么始终传完整的轮廓列表,通过第三个参数指定要绘制的轮廓索引。 - 视频流畅度优化:原代码中0.5秒的帧延迟会导致画面卡顿,调整为0.05秒即可兼顾采集效率和系统负载。
内容的提问来源于stack exchange,提问作者Rolling
相关产品推荐
相关产品推荐

