如何在临时变量中设置一个较大的Numpy来编写视频?

问题描述

您好,您可以在这里给我一些帮助吗?我在这代码中的意图是在构成视频的一系列图像中设置一个简单的阈值。主要问题是我无法在单个变量中存储237帧,在这种情况下,:= outputdata

我想打谷的视频的形状为(284,640,352,3)。正如您在第22行看到的那样,我将杀死rgb通道,因为进一步只需要灰度来设定阈值方法。所以这给了我一个大于63Gb的np.array

您可能会在video.nextFrame()循环中找到怪异的手动输出数据索引;但只有这样,我才能使代码运行无错误。但是,当我在调试器上看到outputdata变量的值时,它们向我展示了所有嵌套的-1的np.arrays

import skvideo.io
import skvideo.datasets
import numpy as np
import argparse
import cv2
import time

def threshOneFrame(frame):
    frame = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(frame,(7,7),0)
    thresh = cv2.threshold(blurred,20,255,cv2.THRESH_BINARY)
    thresh = thresh[1].astype(np.uint8)
    return thresh

ap = argparse.ArgumentParser()
ap.add_argument("-v","--video",required=True,help="path to input video file")
args = vars(ap.parse_args())

vidSh = skvideo.io.vread(args["video"])
vidSh = vidSh.shape[:3]

video = skvideo.io.FFmpegReader(args["video"])
outputdata = np.zeros(vidSh,dtype=np.int8)

for id,frame in enumerate(video.nextFrame()):
    frame = threshOneFrame(frame)
    outputdata[id] = frame
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) == ord('q'):
        break



lapstime = time.time()
skvideo.io.vwrite("outputvideo"+time.ctime(lapstime)+".mp4",outputdata)
video.close()

解决方法

就像您说的那样,输出视频太大了,无法一次将其所有帧保存在内存中。

解决方案是在创建输出帧时将它们写入磁盘。一种方法是:创建一个skvideo.io.FFmpegWriter实例,然后在for循环中调用writer.writeFrame(frame)来写出该框架。

或另一种可能性:例如使用PIL库将每个帧写为图像文件:Image.fromarray(frame).save(f'frame-{id:06}.png')。然后,在Python外部运行FFmpeg to convert the images to a video