← 返回首页
Code for How to Extract Frames from Video in Python - Python Code
  The Python Code Menu

Code for How to Extract Frames from Video in Python Tutorial


View on Github

extract_frames_opencv.py

from datetime import timedelta import cv2 import numpy as np import os # i.e if video of duration 30 seconds, saves 10 frame per second = 300 frames saved in total SAVING_FRAMES_PER_SECOND = 10 def format_timedelta(td): """Utility function to format timedelta objects in a cool way (e.g 00:00:20.05) omitting microseconds and retaining milliseconds""" result = str(td) try: result, ms = result.split(".") except ValueError: return (result + ".00").replace(":", "-") ms = int(ms) ms = round(ms / 1e4) return f"{result}.{ms:02}".replace(":", "-") def get_saving_frames_durations(cap, saving_fps): """A function that returns the list of durations where to save the frames""" s = [] # get the clip duration by dividing number of frames by the number of frames per second clip_duration = cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap.get(cv2.CAP_PROP_FPS) # use np.arange() to make floating-point steps for i in np.arange(0, clip_duration, 1 / saving_fps): s.append(i) return s def main(video_file): filename, _ = os.path.splitext(video_file) filename += "-opencv" # make a folder by the name of the video file if not os.path.isdir(filename): os.mkdir(filename) # read the video file cap = cv2.VideoCapture(video_file) # get the FPS of the video fps = cap.get(cv2.CAP_PROP_FPS) # if the SAVING_FRAMES_PER_SECOND is above video FPS, then set it to FPS (as maximum) saving_frames_per_second = min(fps, SAVING_FRAMES_PER_SECOND) # get the list of duration spots to save saving_frames_durations = get_saving_frames_durations(cap, saving_frames_per_second) # start the loop count = 0 while True: is_read, frame = cap.read() if not is_read: # break out of the loop if there are no frames to read break # get the duration by dividing the frame count by the FPS frame_duration = count / fps try: # get the earliest duration to save closest_duration = saving_frames_durations[0] except IndexError: # the list is empty, all duration frames were saved break if frame_duration >= closest_duration: # if closest duration is less than or equals the frame duration, # then save the frame frame_duration_formatted = format_timedelta(timedelta(seconds=frame_duration)) cv2.imwrite(os.path.join(filename, f"frame{frame_duration_formatted}.jpg"), frame) # drop the duration spot from the list, since this duration spot is already saved try: saving_frames_durations.pop(0) except IndexError: pass # increment the frame count count += 1 if __name__ == "__main__": import sys video_file = sys.argv[1] main(video_file)

extract_frames_moviepy.py

from moviepy.editor import VideoFileClip import numpy as np import os from datetime import timedelta # i.e if video of duration 30 seconds, saves 10 frame per second = 300 frames saved in total SAVING_FRAMES_PER_SECOND = 10 def format_timedelta(td): """Utility function to format timedelta objects in a cool way (e.g 00:00:20.05) omitting microseconds and retaining milliseconds""" result = str(td) try: result, ms = result.split(".") except ValueError: return (result + ".00").replace(":", "-") ms = int(ms) ms = round(ms / 1e4) return f"{result}.{ms:02}".replace(":", "-") def main(video_file): # load the video clip video_clip = VideoFileClip(video_file) # make a folder by the name of the video file filename, _ = os.path.splitext(video_file) filename += "-moviepy" if not os.path.isdir(filename): os.mkdir(filename) # if the SAVING_FRAMES_PER_SECOND is above video FPS, then set it to FPS (as maximum) saving_frames_per_second = min(video_clip.fps, SAVING_FRAMES_PER_SECOND) # if SAVING_FRAMES_PER_SECOND is set to 0, step is 1/fps, else 1/SAVING_FRAMES_PER_SECOND step = 1 / video_clip.fps if saving_frames_per_second == 0 else 1 / saving_frames_per_second # iterate over each possible frame for current_duration in np.arange(0, video_clip.duration, step): # format the file name and save it frame_duration_formatted = format_timedelta(timedelta(seconds=current_duration)) frame_filename = os.path.join(filename, f"frame{frame_duration_formatted}.jpg") # save the frame with the current duration video_clip.save_frame(frame_filename, current_duration) if __name__ == "__main__": import sys video_file = sys.argv[1] main(video_file)