AttributeError: ‘NoneType‘ object has no attribute ‘shape‘ 解决方案&OpenCV视频末帧处理不当导致的错误

AttributeError: ‘NoneType’ object has no attribute 'shape’解决方案

作者:小初
时间: 2021-05-08

摘要

AttributeError: ‘NoneType’ object has no attribute 'shape’解决方案&OpenCV视频末帧处理不当导致的错误

总结

使用cv读取视频末尾帧时,程序会一直停留在最后一帧,capture.isOpened()一直为true,但是frame数组矩阵已经为空,此时自然无法检测其shape。利用异常处理机制或者if判断可以有效解决此问题。

目录

文章目录

  • AttributeError: 'NoneType' object has no attribute 'shape'解决方案
      • 摘要
      • 总结
    • 目录
        • 问题的出现:
        • 解决过程:

问题的出现:

​ 在pycharm中对车道线视频的检测完毕之后,在不人为终止程序运行的情况下,系统总是提示如下错误:

AttributeError: 'NoneType' object has no attribute 'shape'

AttributeError: ‘NoneType‘ object has no attribute ‘shape‘ 解决方案&OpenCV视频末帧处理不当导致的错误_第1张图片

#处理过程
if __name__ == '__main__':
    # 打开视频
    capture = cv2.VideoCapture('video1.mp4')
    fourcc = cv2.VideoWriter_fourcc(*'MJPG')
    outfile = cv2.VideoWriter('output.avi', fourcc, 25., (1280, 368))
    # 循环处理每一帧
    while capture.isOpened():
        _, frame = capture.read()
        origin = np.copy(frame)
        frame = process_an_image(frame)
        output = np.concatenate((origin, frame), axis=1)
        outfile.write(output)
        cv2.imshow('video1_out', output)
        # 处理退出
        if cv2.waitKey(1) == ord('q'):
            cv2.destroyAllWindows()
            break

解决过程:

​ 从报错的字面意思看是找不到 对象的shape属性,上网查询了相关经验帖,说是路径不对,一一试过之后发现问题并没有解决。询问了老师之后,老师建议抛出异常,检查frame。我就简单修改了下代码,观察frame。

while capture.isOpened():
    testM = capture.isOpened()
    _, frame = capture.read()
    origin = np.copy(frame)
    try:
        frame = process_an_image(frame)
        output = np.concatenate((origin, frame), axis=1)
        outfile.write(output)
        cv2.imshow('video1_out', output)
     except:
         print(frame)
     #   exit(0)
    if cv2.waitKey(1) == ord('q'):
            cv2.destroyAllWindows()
            break

此时发现系统一直在输出 None

AttributeError: ‘NoneType‘ object has no attribute ‘shape‘ 解决方案&OpenCV视频末帧处理不当导致的错误_第2张图片

此时似乎明白了一些,当程序运行到最后的时候frame数组矩阵全是空的,此时shape属性自然不存在。

为了进一步验证我的观点,我采用debug单步调试,调出frame矩阵数组,逐帧观察frame里面的数据,在车道线视频处理结束之前,数据一切都很正常,frame中保存着图像信息

AttributeError: ‘NoneType‘ object has no attribute ‘shape‘ 解决方案&OpenCV视频末帧处理不当导致的错误_第3张图片

而当视频处理完毕之后,frame中的数据则立即被清空

AttributeError: ‘NoneType‘ object has no attribute ‘shape‘ 解决方案&OpenCV视频末帧处理不当导致的错误_第4张图片

这下算是证实了我上面的想法。当程序运行到最后,frame数组矩阵为空,此时shape属性自然不存在,此时程序自然会发生异常。

解决代码代码如下:

while capture.isOpened():
   # testM = capture.isOpened()
    _, frame = capture.read()
    origin = np.copy(frame)
    try:
        frame = process_an_image(frame)
        output = np.concatenate((origin, frame), axis=1)
        outfile.write(output)
        cv2.imshow('video1_out', output)
     except:
        # print(frame)
         exit(0)
    if cv2.waitKey(1) == ord('q'):
            cv2.destroyAllWindows()
            break

运行结束完美解决问题!

但是此时我还在想一个问题,为什么视频都已经处理完毕了,while循环还能继续执行导致异常,capture.isOpened()的bool值在程序运行中究竟是怎样变化的?

因此我决定继续debug单步执行,同时将capture.isOpened()存储起来到testM便于观察,调出frame窗口、图像输出窗口、testM窗口,逐帧观察

 testM = capture.isOpened() #插入到while 执行语句中

当视频结束时,程序果然没有结束,此时观察到如下结果
AttributeError: ‘NoneType‘ object has no attribute ‘shape‘ 解决方案&OpenCV视频末帧处理不当导致的错误_第5张图片

此时可以看到,即使视频已经处理完毕,但是capture. isOpened()的值仍为true,而此时的frame已然为None,这才是系统报错的真正原因,视频处理完毕直接结束程序即可。

问题的关键在于isOpened函数会一直检测视频的载入与否,当使用VideoCapture()捕获视频时,并不会因为视频结束而停止此操作,而是会一直停留在视频的最后一帧,因此在不加外界干预的情况下,capture.isOpened()在程序运行期间都会是 true。而如果从外界输入 ‘ q ’ 来手动停止时,可以保证在程序的运行期间,frame都是正常存储数据的,因此手动停止时,系统并不会报错。这个才是整个问题的关键。此博客也有相关解释https://blog.csdn.net/archer_wu2/article/details/85628536

可以在图像处理前对 _(也就是常用的ret) 值进行判断

 if _ == True:
       ......
    else:
        break

问题解决!

除了上面给出的一种更改方法,增加一条对 frame 的判断也可以解决此问题。

while capture.isOpened():
    testM = capture.isOpened()
    _, frame = capture.read()
    origin = np.copy(frame)
    if frame is not None:
        try:
            frame = process_an_image(frame)
            output = np.concatenate((origin, frame), axis=1)
            outfile.write(output)
            cv2.imshow('video1_out', output)
        except:
             print(frame)
     #   exit(0)
    else :
        exit(0)

    # 处理退出
    if cv2.waitKey(1) == ord('q'):
        cv2.destroyAllWindows()
        break

运行结果如下:
AttributeError: ‘NoneType‘ object has no attribute ‘shape‘ 解决方案&OpenCV视频末帧处理不当导致的错误_第6张图片

问题解决!!!

问题的关键在于读取视频末尾帧时发生错误,上述三种方法均可以解决此类问题。

第一次写博客,如有错误,欢迎各位大佬批评指正。

你可能感兴趣的:(python,计算机视觉,opencv)