I would like to use OpenCV in Python to compile a video from a number of images. I get the error
OpenCV: FFMPEG: tag is not supported with codec id 12 and format 'mp4 / MP4
I searched here for an answer how to fix it. I got an answer in this post, but it does not generate a video, the file is just 5.7kB, no matter which number of images I add.
Here is an example code:
import os
import numpy as np
from glob import glob
import cv2
path = "where to find some images"
fname_video="where the video should go"
os.chdir(path)
size=(1024,768)
fps=20
files = [y for x in os.walk(path) for y in glob(os.path.join(x[0], '*.JPG'))][0:10] # just 10 images
image_array = []
for file in files:
frame = cv2.imread(os.path.join(path,file),0)
frame = cv2.resize(frame,size)
image_array.append(frame)
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(fname_video, fourcc, fps, size)
for i in range(len(image_array)):
out.write(image_array[i])
out.release()
Maybe somebody can give me a hint how to get a valid video file?
File Path Handling: The files list is being created using os.walk and glob, but the os.path.join(path, file) in the loop is redundant because files already contains the full paths.
Grayscale vs. Color: You're reading the images in grayscale (cv2.IMREAD_GRAYSCALE), but the VideoWriter expects color images (3 channels). If you want to create a grayscale video, you need to convert the grayscale images to 3-channel images.
Filename: My file name end with *.jpg. Both are worked after change name from *.JPG to *.jpg.
New Method:-
Instead of 'mp4v', try using a more widely supported codec like 'XVID' or 'MJPG'
import os
import numpy as np
from glob import glob
import cv2
path = os.path.join(os.getcwd(), 'media', 'images')
fname_video = os.path.join(os.getcwd(), 'media', 'video', 'go.avi') # Save as AVI
os.chdir(path)
size = (1024, 768)
fps = 20
# Get the list of image files (only the first 10 images)
files = [y for x in os.walk(path) for y in glob(os.path.join(x[0], '*.jpg'))][0:10]
image_array = []
for file in files:
frame = cv2.imread(file, cv2.IMREAD_GRAYSCALE) # Read image in grayscale
frame = cv2.resize(frame, size)
frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR) # Convert grayscale to 3-channel image
image_array.append(frame)
# Create a video writer object
fourcc = cv2.VideoWriter_fourcc(*'XVID') # Use XVID codec
out = cv2.VideoWriter(fname_video, fourcc, fps, size, isColor=True)
# Write frames to the video
for i in range(len(image_array)):
out.write(image_array[i])
Edited Code:-
import os
import numpy as np
from glob import glob
import cv2
path = os.path.join(os.getcwd(), 'media', 'images')
fname_video = os.path.join(os.getcwd(), 'media', 'video', 'go.mp4') # Ensure the file has a .mp4 extension
os.chdir(path)
size = (1024, 768)
fps = 20
# Get the list of image files (only the first 10 images)
files = [y for x in os.walk(path) for y in glob(os.path.join(x[0], '*.jpg'))][0:10]
image_array = []
for file in files:
frame = cv2.imread(file, cv2.IMREAD_GRAYSCALE) # Read image in grayscale
frame = cv2.resize(frame, size)
frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR) # Convert grayscale to 3-channel image
image_array.append(frame)
# Create a video writer object
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(fname_video, fourcc, fps, size, isColor=True)
# Write frames to the video
for i in range(len(image_array)):
out.write(image_array[i])
# Release the video writer
out.release()
print(f"Video saved to {fname_video}")