【问题标题】:Extracting frames from multiple videos in for loop在for循环中从多个视频中提取帧
【发布时间】:2020-03-23 15:30:32
【问题描述】:

我正在尝试使用 OpenCV 在 for 循环中从多个视频文件中提取帧。我在网上找到了几种从单个视频中提取帧的方法,但是我很难在 for 循环中运行帧提取。

从单个视频(视频变量)中提取帧的工作代码是:

cap=cv2.VideoCapture(video)
i=0
while (cap.isOpened()):    #
    ret, frame=cap.read()
    if ret == False:
        break
    cv2.imwrite(str(i) + '.jpg', frame)
    i+=1

cap.release()
cv2.destroyAllWindows()

我想扩展它以包含一个 for 循环,以便我可以遍历多个视频(视频变量中的路径)并提取所有帧。我希望视频路径中的帧号一个接一个地运行-即,如果视频 1 提取了 30 帧,则视频 2 帧将保存为 31、32、33 等。

我试图将上面的代码放入一个for循环,但它似乎永远运行并且没有保存任何东西:

i=0 #place i outside of for-loop so it doesn't reset each iteration
for v in videos:
    cap=cv2.VideoCapture(v)
    while (cap.isOpened()):    #
        ret, frame=cap.read()
        if ret == False:
        break
        cv2.imwrite(str(i) + '.jpg', frame)
        i+=1

cap.release()
cv2.destroyAllWindows()

有人可以帮忙吗?谢谢!

【问题讨论】:

    标签: python opencv for-loop


    【解决方案1】:

    迭代几个视频文件与您的实现没有太大区别:

    • 在每个“视频文件迭代”开始时使用cap = cv2.VideoCapture(intput_filename)。 和你一样。
    • 在每次“视频文件迭代”结束时使用cap.release()。
      在您发布的代码中,您似乎将cap.release() 放在了错误的位置。
    • 继续推进图像计数器(用于给出连续的文件名)。
      和你一样。

    我不确定你的代码:

        if ret == False:
        break
    

    看来断点的缩进不正确。


    我创建了一个“自包含”的代码示例:

    • 生成两个合成视频文件(用作输入)。
    • 迭代视频文件名(在外循环中)。
      • 从视频文件中读取帧(在内部循环中)。
      • 将帧写入 JPEG 图像文件。
      • 在阅读时显示视频帧(用于测试)。

    代码如下:

    import numpy as np
    import cv2
    import os
    
    intput_filename1 = 'input_vid1.avi'
    intput_filename2 = 'input_vid2.avi'
    
    # List of video file names
    intput_filenames = [intput_filename1, intput_filename2]
    
    # Generate two synthetic video files to be used as input:
    ###############################################################################
    width, height, n_frames = 640, 480, 30  # 30 frames, resolution 640x480
    
    # Use motion JPEG codec (for testing)
    synthetic_out = cv2.VideoWriter(intput_filename1, cv2.VideoWriter_fourcc(*'MJPG'), 25, (width, height))
    
    for i in range(n_frames):
        img = np.full((height, width, 3), 60, np.uint8)
        cv2.putText(img, str(i+1), (width//2-100*len(str(i+1)), height//2+100), cv2.FONT_HERSHEY_DUPLEX, 10, (30, 255, 30), 20)  # Green number
        synthetic_out.write(img)
    
    synthetic_out.release()
    
    width, height, n_frames = 320, 240, 20 # 20 frames, resolution 320x240
    synthetic_out = cv2.VideoWriter(intput_filename2, cv2.VideoWriter_fourcc(*'MJPG'), 25, (width, height))
    
    for i in range(n_frames):
        img = np.full((height, width, 3), 60, np.uint8)
        cv2.putText(img, str(i+1), (width//2-50*len(str(i+1)), height//2+50), cv2.FONT_HERSHEY_DUPLEX, 5, (255, 30, 30), 10)  # Blue number
        synthetic_out.write(img)
    
    synthetic_out.release()
    ###############################################################################
    
    
    i = 1  # Images file counter
    
    # Iterate file names:
    for intput_filename in intput_filenames:
        cap = cv2.VideoCapture(intput_filename)
    
        # Keep iterating break
        while True:
            ret, frame = cap.read()  # Read frame from first video
    
            if ret:
                cv2.imwrite(str(i) + '.jpg', frame)  # Write frame to JPEG file (1.jpg, 2.jpg, ...)
                cv2.imshow('frame', frame)  # Display frame for testing
                i += 1 # Advance file counter
            else:
                # Break the internal loop when res status is False.
                break
    
            cv2.waitKey(100) #Wait 100msec (for debugging)
    
        cap.release() #Release must be inside the outer loop
    
    cv2.destroyAllWindows()
    

    更新:

    把这个放到一个函数中:

    def extract_multiple_videos(intput_filenames):
        """Extract video files into sequence of images.
           Intput_filenames is a list for video file names"""
    
        i = 1  # Counter of first video
    
        # Iterate file names:
        for intput_filename in intput_filenames:
            cap = cv2.VideoCapture(intput_filename)
    
            # Keep iterating break
            while True:
                ret, frame = cap.read()  # Read frame from first video
    
                if ret:
                    cv2.imwrite(str(i) + '.jpg', frame)  # Write frame to JPEG file (1.jpg, 2.jpg, ...)
                    cv2.imshow('frame', frame)  # Display frame for testing
                    i += 1 # Advance file counter
                else:
                    # Break the interal loop when res status is False.
                    break
    
                cv2.waitKey(100) #Wait 100msec (for debugging)
    
            cap.release() #Release must be inside the outer loop
    

    【讨论】:

    • 谢谢,这真的很清楚,很有帮助!它工作得很好,谢谢你告诉我我哪里错了(和正确的!)
    • 如何将其放入函数中?我只是把它包装成一个函数结构`def extractframes(video_list):`在开始,然后`return print('frames extract from', video_path)`在最后但它不起作用......?任何见解都会非常感谢!
    • 只需添加将intput_filenames 作为输入参数的函数。我更新了我的帖子。
    • @Rotem 我遵循了您的代码。我有一个视频文件列表。我使用给定的 for 循环逐一迭代它们,` for videofile in list_of_video_files: print(videofile) cap = cv2.VideoCapture(videofile) # 保持迭代 break while True: ret, frame = cap.read() #从第一个视频中读取帧 print(ret, frame) if ret: print(ret)` 但是ret 总是打印False 和frame 是None。如何解决?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-30
    • 2014-09-07
    • 2014-02-27
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多