【问题标题】:How to skip missing images/frames within an image sequence when used with cv2.videocapture()?与 cv2.videocapture() 一起使用时,如何跳过图像序列中丢失的图像/帧?
【发布时间】:2020-11-24 13:42:32
【问题描述】:

我在一个目录中存储了大约 40K 帧。我正在使用以下代码来读取它们并最终将它们写入视频文件中。以下 sn-p 仅用于显示视频。

cap = cv2.VideoCapture('path/to/images/%010d.jpg')
while(True):
    ret, frame = cap.read()
    if (ret == True):
        cv2.imshow('video output', frame)
        cv2.waitKey(30)

它一直有效,直到序列中缺少图像。例如。就我而言,我没有图像'0000000021.jpg'。所以它返回以下错误:

[image2 @ 0x1401500] Could not open file : path/to/images/0000000021.jpg

我有两个问题:

  1. 如何获取丢失的图像/帧的名称?
  2. 有没有办法告诉 cap.read() 函数只是冷却并增加下一个序列,例如。在我的情况下,跳过“0000000021.jpg”并转到“0000000022.jpg”等等。

干杯

【问题讨论】:

    标签: python opencv computer-vision


    【解决方案1】:

    我无法产生错误,因此我的答案可能不准确。

    但它可能会为您提供如何解决它的线索。

    我认为对于这两个问题,以下是答案:

    from cv2 import VideoCapture
    from cv2 import imshow, waitKey
    
    missing_frames = []
    
    capture = VideoCapture('path/to/images/%010d.jpg')
    
    while True:
        _, frame = capture.read()
    
        if frame is None:
            missing_frames.append(frame)
        else:
            imshow('out', frame)
            waitKey(0)
    

    说明

    您正在使用VideoCapture 读取一系列图像,并且目录中缺少一些帧。

    如果缺少帧,ret 返回 False,frame 返回 None

    ret, frame = capture.read()
    

    我了解到您正在专注于阅读和编写框架。因此,您不需要 ret 变量。只需检查frame 就足够了。

    如果目录中没有frame,请将其添加到mssing_frames 列表中。否则显示它。

    我试着给你一个关于你如何解决它的意见。如果你问我,我解决的问题如下:

    from os import getcwd
    from os.path import join
    from cv2 import imshow
    from cv2 import waitKey
    from cv2 import imread
    from glob import glob
    
    
    def get_integer(frame_name):
        frame_name = frame_name.replace(path, '')
        frame_name = frame_name.replace('.jpg', '')
        frame_number = int(frame_name[1:])
        return frame_number
    
    
    if __name__ == '__main__':
        missing_frames = []
        path = join(getcwd(), 'test-case')
        capture = glob(join(path, '*.jpg'))
    
        name = capture[0]
        name_num = get_integer(name)
    
        for frame in capture:
            frame_num = get_integer(frame)
    
            if name_num != frame_num:
                missing_frames.append(frame)
    
            imshow('out', imread(frame))
            waitKey(0)
            name_num += 1
    
        print(missing_frames)
    

    输出:

    ['/Users/ahmettavli/PycharmProjects/StackOverFlow/test-case/0000000023.jpg']
    

    我使用glob 存储了所有图像,并通过其编号检查是否缺少帧。

    【讨论】:

    • 谢谢,这有帮助。在“finally”块中,我现在从另一个目录复制丢失的帧,因此在下一次迭代中 videocapture 对象会找到该帧:cheap fix alert!!。你对我的第二个问题有什么建议吗?我想告诉 videocapture 对象跳过丢失的帧。这可能是终极修复 O)
    • 所以,一旦我们处理了一个错误的 ret*,capture.read() 函数应该尝试读取下一帧,对吧?如果是,那么这在我的代码中不会发生。 **cap.read 尝试无限期地继续读取丢失的帧。并且不会移动到下一帧。我有两个帧目录,/all-frames//missing-frames/。 cap.read() 正在从 /missing-frames-dir/ 读取,当它遇到丢失的帧时,我从 /all-frames-dir/ 复制该帧(解决方法),然后 cap.read() 才会移动到下一帧。就像 cap.read() 不能跳过丢失的帧一样。
    • capture.read() 函数应该在我们处理错误的 ret* 后尝试读取下一帧,对吧?不,没有那么简单。请再读一遍我的答案,因为我建议使用glob。我测试了代码,是的,我发现丢失的帧没有错误。
    • 感谢您抽出宝贵时间。
    • 在第一个例子中,missing_frames.append(frame) 的意义何在? -- 你只是在制作Nones 的列表...如果框架不可用,则没有什么可添加的。
    猜你喜欢
    • 2020-09-20
    • 1970-01-01
    • 2017-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-05
    • 1970-01-01
    相关资源
    最近更新 更多