Home > Mobile >  Convert large amount of images (frames) to video using python
Convert large amount of images (frames) to video using python

Time:08-04

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). 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. 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.

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. Snippet for the attempt with numpy array:

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

CodePudding user response:

Credit to @André for suggesting i shouldn't load all the images and make it so i wouldn't iterate over imgArray at all

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()
  • Related