OpenCV递归实现车辆视频录制时第4轮报NoneType无shape属性错误
错误根因
- 直接原因:
cv.VideoCapture.read()方法在读取帧失败时,会返回(False, None),你没有对返回结果做校验直接访问image.shape,就会触发NoneType无shape属性的报错。 - 第四次才触发的核心原因:你用递归调用
camera()的方式做重启逻辑存在严重的资源泄漏问题:你在postprocess函数内直接触发递归,上一轮的VideoCapture、VideoWriter对象根本没有执行到末尾的release()逻辑,RTSP连接、文件句柄、内存资源持续被占用,4次之后资源耗尽导致RTSP拉流失败,读不到帧就返回了None。 - 额外隐患:递归调用会持续累积调用栈,次数多了还会触发Python栈溢出报错,完全不适合做循环重启逻辑。
修复步骤
- 所有
read()操作都加帧有效性校验,避免空帧直接崩溃
# 初始化后第一次读帧加校验 ret, image = cap.read() if not ret or image is None: print("RTSP拉流失败,2秒后重试") cap.release() time.sleep(2) return # 循环内读帧也要加校验 hasFrame, frame = cap.read() if not hasFrame or frame is None: continue
- 替换递归重启为外层循环,保证每轮资源都正确释放
删除postprocess里直接调用camera()的逻辑,新增重启标志位,触发重启时先跳出当前循环,走资源释放逻辑后再由外层循环重启:
# 新增全局重启标志 need_restart = False def camera(): global need_restart need_restart = False # ... 原有初始化逻辑 ... while cv.waitKey(1) < 0: if need_restart: break # ... 原有帧处理逻辑 ... # 这里一定会走到,资源正常释放 cap.release() output.release() # 外层循环跑逻辑,不要用递归 if __name__ == "__main__": import time while True: camera()
- 修正
postprocess里的重启触发逻辑,把调用camera()的地方改成修改标志位:
if len(empty)>100: empty.clear() if (os.path.isfile(newname+".avi"))==True and os.path.getsize(newname+".avi")!=0: # 不要直接调camera(),改设重启标志 need_restart = True
- 检查你的RTSP地址末尾多了一个多余的冒号
:,删除后可以提升拉流稳定性。
内容的提问来源于stack exchange,提问作者Chingiz K
相关产品推荐
相关产品推荐

