Comment Extraire Une Image Dans Une Video Avec Python
Comment Extraire Une Image Dans Une Video Avec Python
Comment Extraire Une Image Dans Une Video Avec Python
Open options
Étant donné que toutes les vidéos n'ont pas la même longueur et le
même FPS , nous allons définir un paramètre pour ajuster le nombre
d'images que nous voulons extraire et enregistrer par seconde :
# i.e if video of duration 30 seconds, saves 10 frame per second = 300 frames saved in total
SAVING_FRAMES_PER_SECOND = 10
Nous utiliserons ce paramètre sur les deux méthodes. Par exemple, s'il est
défini sur 10 pour le moment, il n'enregistrera que 10 images par seconde
de la vidéo, même si le FPS vidéo est disons 24. Si la vidéo a une durée de
30 secondes, alors 300 images seront enregistrées au total. . Vous pouvez
également définir ce paramètre sur 0,5, ce qui économisera une image
toutes les 2 secondes, et ainsi de suite.
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):
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
Comme vous pouvez le voir, les images sont enregistrées avec l'horodatage
dans le nom du fichier.
Dans cette méthode, nous n'allons pas utiliser OpenCV, mais avec une autre
bibliothèque appelée MoviePy, je vais créer un fichier
appelé extract_frames_moviepy.pyet importer les modules nécessaires :
# i.e if video of duration 30 seconds, saves 10 frame per second = 300 frames saved in total
SAVING_FRAMES_PER_SECOND = 10
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)).replace(":", "-")
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)
Nous définissons ensuite notre pas de bouclage, qui est de 1 divisé par le
fps d'enregistrement, si nous définissons le SAVING_FRAMES_PER_SECONDà 10, alors
le pas serait de 0,1 (c'est-à-dire l'enregistrement d'une image toutes les 0,1
secondes).
if __name__ == "__main__":
import sys
video_file = sys.argv[1]
main(video_file)
Testons-le :
Après quelques secondes, le zoo-moviepydossier est créé et les images ont été
enregistrées dans ce dossier.
Conclusion
Après avoir utilisé les deux méthodes dans mon cas, je remarque que la
première méthode (utilisant OpenCV) est plus rapide en termes de temps
d'exécution mais enregistre des images plus grandes que MoviePy.
Ceci étant dit, j'ai mis entre vos mains deux méthodes d'extraction d'images
de vidéos en Python, à vous de choisir quelle méthode vous convient le
mieux.