Question: I am fairly new to this platform. I will do my best to be clear as possible. My goal is to convert frames from my directory into a video. For some reason, it is including the first frame in every 15 fps. Here is my code below: import cv2 import glob from pathlib import Path def play_frames(frames_dir, fps, output_video_path): # Get the list of frames in the directory frames = sorted(glob.glob(str(frames_dir / '*.png'))) # Read the first frame to get the width and height frame = cv2.imread(frames[0]) height, width, _ = frame.shape # Create the video writer object fourcc = cv2.VideoWriter_fourcc(*'mp4v') video_writer = cv2.VideoWriter(output_video_path, fourcc, fps, (width, height)) for frame_path in frames: # Read the frame frame = cv2.imread(frame_path) # Display the frame cv2.imshow('Frame', frame) cv2.waitKey(int(1000 / fps)) # Write the frame to the video video_writer.write(frame) # Release the video writer video_writer.release() cv2.destroyAllWindows() # Directory path frames_dir = Path('./detected_objects') fps = 15 output_video_path = 'vid2output.mp4' # Play the frames and save as video play_frames(frames_dir, fps, output_video_path)  I have tried countless of codes here, but all the codes (that I have tried) keeps adding the first frame in every fps. What am I doing wrong? Is there another way to convert images to video without adding the first frame in every fps? (I have checked my frames in the directory, and they are all in the correct sequence.) I appreciate everyone's help and happy to provide more information! Update: I added resolution size to the code, but the first frame keeps showing up every fps. import cv2 import glob import numpy as np from pathlib import Path def play_frames(frames_dir, fps, output_video_path): # Get the list of frames in the directory frames = sorted(glob.glob(str(frames_dir / '*.png'))) # Read the first frame to get the width and height frame = cv2.imread(frames[0]) height, width, _ = frame.shape # Calculate the maximum width and height among all frames max_width = width max_height = height for frame_path in frames[1:]: # Read each frame to get its dimensions frame = cv2.imread(frame_path) height, width, _ = frame.shape # Update the maximum width and height if necessary max_width = max(max_width, width) max_height = max(max_height, height) # Create the video writer object fourcc = cv2.VideoWriter_fourcc(*'mp4v') video_writer = cv2.VideoWriter(output_video_path, fourcc, fps, (max_width, max_height)) # Resize and pad each frame before writing to the video for frame_path in frames: frame = cv2.imread(frame_path) # Resize the frame to the maximum dimensions resized_frame = cv2.resize(frame, (max_width, max_height)) # Write the resized frame to the video video_writer.write(resized_frame) # Release the video writer video_writer.release() # Directory path frames_dir = Path('./detected_objects') fps = 15 output_video_path = 'vid1output.mp4' # Play the frames and save as video play_frames(frames_dir, fps, output_video_path) 

Answer: sorted(), when given a list of strings, sorts them as strings, not as numbers. The following demonstrates why this is a problem: >>> ', '.join(sorted([str(i) for i in range(67)])) '0, 1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 2, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 3, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 4, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 5, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 6, 60, 61, 62, 63, 64, 65, 66, 7, 8, 9'  See how instead of 0, 1, 2 we get 0, 1, 10? Similarly, we jump back to 2 between 19 and 20; jump to 3 between 29 and 30; 4 between 39 and 40; etc. It's easy to see how this could look like jumping back to frame 1, even though that's not actually quite what it's doing.  You need to either pad your filenames so they all have the same number of digits (001.png instead of 1.png), or tell Python to sort them numerically instead of as strings. To do the latter, use the key argument to sorted, passing it as an argument a function that extracts the correct number. For example: import os.path def file_number(filename): return int(os.path.basename(filename).split('.')[0]) frames = sorted(glob.glob(str(frames_dir / '*.png')), key=file_number)