How to Fix Images Being Written to Video in Random Order
Question:
I am attempting to write 271 images of a simulation that are already in numerical order (‘0.jpg’,’1.jpg’, …, ‘271.jpg’) into a video. cv2.videoWriter appears to be writing all of these images in random order, producing a video that doesn’t align with what is supposed to happen in the simulation.
I have already tried using glob
, which produces the same result as using os.path
import numpy as np
import os
from os.path import isfile, join
pathIn= 'path/simulation/'
pathOut = 'video.avi'
fps = 10
frame_array = []
files = [f for f in os.listdir(pathIn) if isfile(join(pathIn, f))]
# for sorting the file names properly
files.sort(key = lambda x: x[5:-4])
files.sort()
frame_array = []
files = [f for f in os.listdir(pathIn) if isfile(join(pathIn, f))]
for i in range(len(files)):
filename=pathIn + files[i]
# reading each file
img = cv2.imread(filename)
height, width, layers = img.shape
size = (width,height)
# inserting the frames into an image array
frame_array.append(img)
out = cv2.VideoWriter(pathOut,cv2.VideoWriter_fourcc(*'DIVX'), fps, size)
for i in range(len(frame_array)):
# writing to a image array
out.write(frame_array[i])
out.release()
Expected order of images converted to video:
‘0.jpg’, ‘1.jpg’, … ‘271.jpg’
Actual result:
’31.jpg’, ‘230.jpg’, ’12.jpg’, …
Answers:
There are two problems with
files.sort(key = lambda x: x[5:-4])
files.sort()
First, '0.jpg'[5:-4]
produces an empty string. I think you want something like
file.sort(key = lambda x: int(x[:-4]))
Second, you’re throwing away the result by sorting again. Drop the second sort.
I was facing the same problem with fourcc = "mp4v" and ".mp4" extension.
I changed to fourcc = "DIVX" and ".avi" extension, and the order of the written frames was kept as I sorted the filenames.
Since your case is DIVX-avi, it may be worth a shot to try another pair fourcc-extension
In my case I fixed that changing the coded.
Code with issues (order of frames was wrong – as if the video was playing forward and back in an infinite loop):
video_writer = cv2.VideoWriter(
'video.avi',
cv2.VideoWriter_fourcc(*"MPEG"),
fps,
(width, height)
)
Working code:
video_writer = cv2.VideoWriter(
'video.avi',
cv2.VideoWriter_fourcc(*"XVID"),
fps,
(width, height)
)
I am attempting to write 271 images of a simulation that are already in numerical order (‘0.jpg’,’1.jpg’, …, ‘271.jpg’) into a video. cv2.videoWriter appears to be writing all of these images in random order, producing a video that doesn’t align with what is supposed to happen in the simulation.
I have already tried using glob
, which produces the same result as using os.path
import numpy as np
import os
from os.path import isfile, join
pathIn= 'path/simulation/'
pathOut = 'video.avi'
fps = 10
frame_array = []
files = [f for f in os.listdir(pathIn) if isfile(join(pathIn, f))]
# for sorting the file names properly
files.sort(key = lambda x: x[5:-4])
files.sort()
frame_array = []
files = [f for f in os.listdir(pathIn) if isfile(join(pathIn, f))]
for i in range(len(files)):
filename=pathIn + files[i]
# reading each file
img = cv2.imread(filename)
height, width, layers = img.shape
size = (width,height)
# inserting the frames into an image array
frame_array.append(img)
out = cv2.VideoWriter(pathOut,cv2.VideoWriter_fourcc(*'DIVX'), fps, size)
for i in range(len(frame_array)):
# writing to a image array
out.write(frame_array[i])
out.release()
Expected order of images converted to video:
‘0.jpg’, ‘1.jpg’, … ‘271.jpg’
Actual result:
’31.jpg’, ‘230.jpg’, ’12.jpg’, …
There are two problems with
files.sort(key = lambda x: x[5:-4])
files.sort()
First, '0.jpg'[5:-4]
produces an empty string. I think you want something like
file.sort(key = lambda x: int(x[:-4]))
Second, you’re throwing away the result by sorting again. Drop the second sort.
I was facing the same problem with fourcc = "mp4v" and ".mp4" extension.
I changed to fourcc = "DIVX" and ".avi" extension, and the order of the written frames was kept as I sorted the filenames.
Since your case is DIVX-avi, it may be worth a shot to try another pair fourcc-extension
In my case I fixed that changing the coded.
Code with issues (order of frames was wrong – as if the video was playing forward and back in an infinite loop):
video_writer = cv2.VideoWriter(
'video.avi',
cv2.VideoWriter_fourcc(*"MPEG"),
fps,
(width, height)
)
Working code:
video_writer = cv2.VideoWriter(
'video.avi',
cv2.VideoWriter_fourcc(*"XVID"),
fps,
(width, height)
)