简体   繁体   English

使用 python 将大量图像(帧)转换为视频

[英]Convert large amount of images (frames) to video using python

I'm writing a python script that takes as input a directory path (that directory is filled with large amount of.png images), and combines all of the images into one video file (.avi).我正在编写一个 python 脚本,该脚本将目录路径(该目录充满大量.png图像)作为输入,并将所有图像组合成一个视频文件(.avi)。 the script works great for most usages, my problem starts when i need to the same operation on a folder which contains over 4000 (more or less) images.该脚本适用于大多数用途,当我需要对包含超过 4000 个(或多或少)图像的文件夹进行相同操作时,我的问题就开始了。 on those cases what happens is that once my list (which contains all the images, each as ndarray) gets too big, my whole PC freezes and after a few minutes the python program exits with the "killed" message.在这些情况下,一旦我的列表(包含所有图像,每个图像都为 ndarray)变得太大,我的整个 PC 就会冻结,几分钟后 python 程序退出并显示“已终止”消息。

below is snippet my current code in order to reproduce my problem:下面是我当前的代码片段,以便重现我的问题:

import time
import cv2
import os
import glob
from tqdm import tqdm
import numpy as np

class FramesToVid ():
    def __init__(self , dirPath , saveName):
        self.dirPath = dirPath
        self.saveName = saveName
        self.images = glob.glob(f'{dirPath}/*png')
        self.images.sort()

    def convert_folder (self , imgPathsList = None):
        if imgPathsList is None:
            imgPathsList = self.images
        print(f'start converting {self.dirPath}')
        self.build_array_and_write_vid(imgPathsList)
        
    
    def build_array_and_write_vid (self , imgPathList):
        imgArray = []
        print('building array...')
        for filename in tqdm(imgPathList):
            try:
                img = cv2.imread(filename)
                height, width, layers = img.shape
                size = (width, height)
                imgArray.append(img)
            except Exception as e:
                print(filename)
                print(e)

        pathToSave = os.path.join(os.curdir , f'{self.saveName}_video.avi')
        out = cv2.VideoWriter(pathToSave, cv2.VideoWriter_fourcc(*'DIVX'), 25, size)
        print('writing to video...')
        for img in tqdm(imgArray):
            out.write(img)
        out.release()

Adding to that, iv'e made an attempt to change my code so that the images' ndarray will appended to a numpy array instead of a list, but the output videos from that script are not opening at all.除此之外,iv'e 尝试更改我的代码,以便图像的 ndarray 将附加到 numpy 数组而不是列表,但该脚本中的 output 视频根本没有打开。 Snippet for the attempt with numpy array:尝试使用 numpy 数组的片段:

class FramesToVid ():
    def __init__(self , dirPath , saveName):
        self.dirPath = dirPath
        self.saveName = saveName
        self.images = glob.glob(f'{dirPath}/*png')
        self.images.sort()


    def convert_folder (self , imgPathsList = None):
        if imgPathsList is None:
            imgPathsList = self.images
        print(f'start converting {self.dirPath}')
        self.build_array_and_write_vid(imgPathsList)
        
    
    def build_array_and_write_vid (self , imgPathList):
        imgArray = np.array([])
        print('building array...')
        for filename in tqdm(imgPathList):
            try:
                img = cv2.imread(filename) # ndarray
                height, width, layers = img.shape
                size = (width, height)
                imgArray = np.append(imgArray , img , axis=0)
            except Exception as e:
                print(filename)
                print(e)

        pathToSave = os.path.join(os.curdir , f'{self.saveName}_video.avi')
        out = cv2.VideoWriter(pathToSave, cv2.VideoWriter_fourcc(*'DIVX'), 25, size)
        print('writing to video...')
        for frame in tqdm(imgArray):
            out.write(frame)
        out.release()

For both code snippets the method is being called in the following way:对于这两个代码片段,方法都以下列方式调用:

f = FramesToVid(dirPath= pathToConvert , saveName= dirName)
f.convert_folder()

i would like to know if my goal of converting very large amounts of images can be done with changes to my code我想知道我转换大量图像的目标是否可以通过更改我的代码来完成

Credit to @André for suggesting i shouldn't load all the images and make it so i wouldn't iterate over imgArray at all感谢@André 建议我不应该加载所有图像并制作它,所以我根本不会迭代imgArray

Below is my final working code for anyone needing this in the future:以下是我为将来需要此功能的任何人提供的最终工作代码:

class FramesToVid ():
    def __init__(self , dirPath , saveName):
        self.dirPath = dirPath
        self.saveName = saveName
        self.images = glob.glob(f'{dirPath}/*png')
        self.images.sort()

    def convert_folder (self):
        imgPathsList = self.images
        print(f'start converting {self.dirPath}')
        height, width, layers = cv2.imread(imgPathsList[0]).shape
        size = (width, height)
        pathToSave = f'{self.saveName}_video.avi'
        out = cv2.VideoWriter(pathToSave, cv2.VideoWriter_fourcc(*'DIVX'), 25, size)
        print(f'saving to {pathToSave}...')
        for filename in tqdm(imgPathsList):
            try:
                out.write(cv2.imread(filename))
            except Exception as e:
                print(filename)
                print(e)
        out.release()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM