【问题标题】:Error message when I save my video with OpenCV使用 OpenCV 保存视频时出现错误消息
【发布时间】:2019-05-18 18:22:31
【问题描述】:

我在运行代码时遇到错误,我不明白发生了什么,但我认为是程序完成时,因为我得到了我想要的结果,即将现有视频转换为灰度和保存它。

cv2.error: OpenCV(4.1.0) C:\projects\opencv-python\opencv\modules\imgproc\src\color.cpp:182: error: (-215:Assertion failed) !_src.empty( ) 在函数'cv::cvtColor'中

cap = cv2.VideoCapture('videos/output.avi')
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('results/output.avi', fourcc, 20.0, (640, 480))

while (cap.isOpened()):
    _, frame = cap.read()
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    out.write(frame)

    # Key events
    key = cv2.waitKey(1)
    if key == 27:  # esc
        break

cap.release()
cv2.destroyAllWindows()

谢谢!

【问题讨论】:

    标签: python python-3.x opencv


    【解决方案1】:

    在某些情况下,您的视频中至少有一个帧未正确读入。这就是cv2.cvtColor 方法抛出错误的原因,因为您提供的帧数据是空的。

    您应该考虑使用cv2.VideoCapture.read() 的第一个输出来确保正确捕获视频帧,然后将其写入文件。第一个输出是一个标志,用于确定当前帧是否已成功读入。此外,您需要处理我们到达视频结尾的结尾。在这种情况下,标志将是False,因此我们应该退出循环。最后,如果您打算编写灰度帧,cv2.VideoWriter 中有一个可选的第五个参数,称为isColor,我们可以将其设置为False,以允许我们直接编写灰度帧。这意味着不再需要调用cv2.cvtColor

    我推荐的另一件事是从视频文件中推断帧的宽度和高度,而不是自己设置。这样输入和输出分辨率是相同的。最后,完成后不要忘记释放cv2.VideoWriter 对象,我已经为视频文件添加了额外的检查以查看它是否已正确打开:

    import numpy as np
    import cv2
    import sys
    
    cap = cv2.VideoCapture('videos/output.avi')
    
    # Check to see if the video has properly opened
    if not cap.isOpened():
        print("File could not be opened")
        sys.exit(1)
    
    fourcc = cv2.VideoWriter_fourcc(*'XVID')
    frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))  # Get the frame width and height
    frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) 
    
    # Change
    out = cv2.VideoWriter('results/output.avi', fourcc, 20.0, (frame_width, frame_height), isColor=False)
    
    while True:
        ret, frame = cap.read() # New
    
        if not ret: # New
            break # Get out if we don't read a frame successfully
    
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        out.write(frame)
    
        # Key events
        key = cv2.waitKey(1)
        if key == 27:  # esc
            break
    
    cap.release()
    out.release() # New
    cv2.destroyAllWindows()
    

    作为一个小提示,您没有显示任何窗口,因此cv2.destroyAllWindows() 在这里是多余的。考虑将其从您的代码中删除。

    【讨论】:

    • 我必须对此投反对票,因为即使您从视频文件中读取了最后一帧,cap.isOpened() 仍将继续返回true。一旦你到达终点,ret 将变成 failseframe 将永远是 None....由于if not ret: continue 位,您的脚本将陷入无限循环。
    • @DanMašek 是的,当我不测试我的代码时会发生这种情况。
    • @DanMašek 我想我修好了。请再为我验证一次。
    • 是的,这看起来很合理。我会在while 循环之前添加一个cap.isOpened 测试,以检查输入文件是否正确打开。最后 3 行在这里是不必要的,但它不会受到伤害。也许为 numpy 和 cv2 添加导入语句以使其完整。最后,我可能会添加对输入帧形状的验证,因为如果它与打开 VideoWriter 时指定的 640x480 不匹配,我似乎最终只能得到一个无法播放的 5kB 视频。
    • 不客气,我已经 +1 了。我只是冒昧地摆脱了那里的几个幻数,用命名常量替换它们。
    【解决方案2】:

    所以这个答案有另一种方法(这里,你也可以通过改变B,G,R值前面的相应权重来提取不同的颜色)

    import cv2
    cap = cv2.VideoCapture('videos/output.avi')
    frame_width = int(cap.get(3))  # finds the frame width automatically
    frame_height = int(cap.get(4))  # finds the frame height automatically
    
    fourcc = cv2.VideoWriter_fourcc(*'XVID')
    out = cv2.VideoWriter('results/outpy.avi', cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), 10, (frame_width, frame_height))
    
    while (cap.isOpened()): # value is true if the file is successfully opened.
        ret, frame = cap.read()
        if ret == True:  # checks if the return value is True or False. False means file ended.
            # grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # the grey matrix has a different shape than the frame matrix
            # that's why the output files were blank
            # to circumvent this RGB2GRAY, I manually added the "NORMALIZED" R,G,B values.
    
            frame[:,:,0] = 0.114*frame[:,:,0]+0.587*frame[:,:,1]+0.299*frame[:,:,2] #multiplying normalized co-efficients to B,G,R
    # for extracting red, make 0.299 as 1.0 and others as 0.0; same goes for other colours.
            frame[:, :, 1]=frame[:,:,0] # making the G and R values same as the B.
            frame[:, :, 2]=frame[:,:,0]
            # now frame is a 3d grayscale matrix. Identical to the cv2.cvtColor method....except it is 3d
            # now frame is grey scaled...R,G,B values for each pixel,holds the same number....
            out.write(frame)
        else:
            break
    cap.release()
    out.release()
    cv2.destroyAllWindows()
    

    【讨论】:

    • 先生。 rayryeng 的代码正在创建空白的 avi 文件,所以我修复了它。我已经用 avi 视频测试了我的代码。它工作......耶!
    • 这行不通,因为您在添加代码示例时弄乱了while 循环体的缩进。请修复它。
    • @DanMašek 是的,我删除了我的答案。当您使用手机并且没有彻底测试代码时,就会发生这种情况。
    • 不幸的是,您“绕过这个 RGB2GRAY”的尝试非常糟糕——原始转换为灰度并不是 3 个通道的简单平均值(它是加权的,请参阅 documentation)。因此,您的输出将与预期不同。
    • @DebajyotiMajumder 在转换为灰度之后你真的应该使用cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)。您的解决方法不会产生正确的结果。
    猜你喜欢
    • 1970-01-01
    • 2014-01-28
    • 1970-01-01
    • 1970-01-01
    • 2019-07-11
    • 2019-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多