web-dev-qa-db-fra.com

Python - Extraction et enregistrement d'images vidéo

J'ai donc suivi ce tutoriel mais cela ne semble rien faire. Simplement rien. Il attend quelques secondes et ferme le programme. Quel est le problème avec ce code?

import cv2
vidcap = cv2.VideoCapture('Compton.mp4')
success,image = vidcap.read()
count = 0
success = True
while success:
  success,image = vidcap.read()
  cv2.imwrite("frame%d.jpg" % count, image)     # save frame as JPEG file
  if cv2.waitKey(10) == 27:                     # exit if Escape is hit
      break
  count += 1

En outre, dans les commentaires, il est indiqué que cela limite les cadres à 1 000? Pourquoi?

EDIT: J'ai essayé de faire success = True d'abord mais cela n'a pas aidé. Il n'a créé qu'une image de 0 octet.

81
GShocked

Donc, voici le code final qui a fonctionné:

import cv2
print(cv2.__version__)
vidcap = cv2.VideoCapture('big_buck_bunny_720p_5mb.mp4')
success,image = vidcap.read()
count = 0
success = True
while success:
  cv2.imwrite("frame%d.jpg" % count, image)     # save frame as JPEG file
  success,image = vidcap.read()
  print 'Read a new frame: ', success
  count += 1

Donc, pour que cela fonctionne, vous devrez vous procurer des choses. Tout d'abord, téléchargez OpenCV2 . Alors installez ceci pour Python 2.7.x. Allez dans le dossier ffmpeg dans le dossier tiers (quelque chose comme C:\OpenCV\3rdparty\ffmpeg, mais je ne suis pas sûr). Copiez opencv_ffmpeg.dll (ou la version x64 si votre version python est x64) et collez-la dans votre dossier Python (probablement C:\Python27). Renommez-le opencv_ffmpeg300.dll si votre version de l'opencv est 3.0.0 (vous pouvez le trouver ici ) et modifiez-le en conséquence. Au fait, vous devez avoir votre dossier python dans votre chemin d’environnement .

36
GShocked

De ici téléchargez ceci vidéo nous avons donc le même fichier vidéo pour le test. Assurez-vous d’avoir ce fichier mp4 dans le même répertoire que votre code python. Ensuite, assurez-vous également d’exécuter l’interprète python à partir du même répertoire.

Puis modifiez le code, fossé waitKey qui fait perdre du temps également sans fenêtre, il ne peut pas capturer les événements du clavier. De plus, nous imprimons la valeur success pour nous assurer qu’elle lit correctement les images.

import cv2
vidcap = cv2.VideoCapture('big_buck_bunny_720p_5mb.mp4')
success,image = vidcap.read()
count = 0
while success:
  cv2.imwrite("frame%d.jpg" % count, image)     # save frame as JPEG file      
  success,image = vidcap.read()
  print('Read a new frame: ', success)
  count += 1

Comment ça se passe?

149
fireant

Pour prolonger cette question (et la réponse de @ user2700065) dans des cas légèrement différents, si quelqu'un ne veut pas extraire chaque image mais veut extraire une image toutes les secondes. Donc, une vidéo d'une minute donnera 60 images (images).

import sys
import argparse

import cv2
print(cv2.__version__)

def extractImages(pathIn, pathOut):
    count = 0
    vidcap = cv2.VideoCapture(pathIn)
    success,image = vidcap.read()
    success = True
    while success:
      vidcap.set(cv2.CAP_PROP_POS_MSEC,(count*1000))    # added this line 
      success,image = vidcap.read()
      print ('Read a new frame: ', success)
      cv2.imwrite( pathOut + "\\frame%d.jpg" % count, image)     # save frame as JPEG file
      count = count + 1

if __name__=="__main__":
    print("aba")
    a = argparse.ArgumentParser()
    a.add_argument("--pathIn", help="path to video")
    a.add_argument("--pathOut", help="path to images")
    args = a.parse_args()
    print(args)
    extractImages(args.pathIn, args.pathOut)
22
Bhushan Babar

Ceci est un tweak de la réponse précédente pour python 3.x de @GShocked, je le posterais dans le commentaire, mais je n'ai pas assez de réputation

import sys
import argparse

import cv2
print(cv2.__version__)

def extractImages(pathIn, pathOut):
    vidcap = cv2.VideoCapture(pathIn)
    success,image = vidcap.read()
    count = 0
    success = True
    while success:
      success,image = vidcap.read()
      print ('Read a new frame: ', success)
      cv2.imwrite( pathOut + "\\frame%d.jpg" % count, image)     # save frame as JPEG file
      count += 1

if __name__=="__main__":
    print("aba")
    a = argparse.ArgumentParser()
    a.add_argument("--pathIn", help="path to video")
    a.add_argument("--pathOut", help="path to images")
    args = a.parse_args()
    print(args)
    extractImages(args.pathIn, args.pathOut)
8
XRarach

Après de nombreuses recherches sur la conversion des images en vidéo, j'ai créé cette fonction et j'espère que cela aidera. Nous avons besoin de l'opencv pour cela:

import cv2
import numpy as np
import os

def frames_to_video(inputpath,outputpath,fps):
   image_array = []
   files = [f for f in os.listdir(inputpath) if isfile(join(inputpath, f))]
   files.sort(key = lambda x: int(x[5:-4]))
   for i in range(len(files)):
       img = cv2.imread(inputpath + files[i])
       size =  (img.shape[1],img.shape[0])
       img = cv2.resize(img,size)
       image_array.append(img)
   fourcc = cv2.VideoWriter_fourcc('D', 'I', 'V', 'X')
   out = cv2.VideoWriter(outputpath,fourcc, fps, size)
   for i in range(len(image_array)):
       out.write(image_array[i])
   out.release()


inputpath = 'folder path'
outpath =  'video file path/video.mp4'
fps = 29
frames_to_video(inputpath,outpath,fps)

changez la valeur de fps (images par seconde), le chemin du dossier d'entrée et le chemin du dossier de sortie en fonction de vos propres emplacements locaux

7
Puja Sharma

C'est la fonction qui convertira la plupart des formats vidéo en nombre d'images contenues dans la vidéo. Cela fonctionne sur Python3 avec OpenCV 3+

import cv2
import time
import os

def video_to_frames(input_loc, output_loc):
    """Function to extract frames from input video file
    and save them as separate frames in an output directory.
    Args:
        input_loc: Input video file.
        output_loc: Output directory to save the frames.
    Returns:
        None
    """
    try:
        os.mkdir(output_loc)
    except OSError:
        pass
    # Log the time
    time_start = time.time()
    # Start capturing the feed
    cap = cv2.VideoCapture(input_loc)
    # Find the number of frames
    video_length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) - 1
    print ("Number of frames: ", video_length)
    count = 0
    print ("Converting video..\n")
    # Start converting the video
    while cap.isOpened():
        # Extract the frame
        ret, frame = cap.read()
        # Write the results back to output location.
        cv2.imwrite(output_loc + "/%#05d.jpg" % (count+1), frame)
        count = count + 1
        # If there are no more frames left
        if (count > (video_length-1)):
            # Log the time again
            time_end = time.time()
            # Release the feed
            cap.release()
            # Print stats
            print ("Done extracting frames.\n%d frames extracted" % count)
            print ("It took %d seconds forconversion." % (time_end-time_start))
            break

if __name__=="__main__":

    input_loc = '/path/to/video/00009.MTS'
    output_loc = '/path/to/output/frames/'
    video_to_frames(input_loc, output_loc)

Il supporte .mts et les fichiers normaux tels que .mp4 et .avi. Essayé et testé sur les fichiers .mts. Fonctionne comme un charme.

7
Harsh Patel

Ce code extrait des images de la vidéo et les enregistre au format .jpg

import cv2
import numpy as np
import os

# set video file path of input video with name and extension
vid = cv2.VideoCapture('VideoPath')


if not os.path.exists('images'):
    os.makedirs('images')

#for frame identity
index = 0
while(True):
    # Extract images
    ret, frame = vid.read()
    # end of frames
    if not ret: 
        break
    # Saves images
    name = './images/frame' + str(index) + '.jpg'
    print ('Creating...' + name)
    cv2.imwrite(name, frame)

    # next frame
    index += 1
5
Rejoice T J

Les réponses précédentes ont perdu la première image. Et ce sera bien de stocker les images dans un dossier.

# create a folder to store extracted images
import os
folder = 'test'  
os.mkdir(folder)
# use opencv to do the job
import cv2
print(cv2.__version__)  # my version is 3.1.0
vidcap = cv2.VideoCapture('test_video.mp4')
count = 0
while True:
    success,image = vidcap.read()
    if not success:
        break
    cv2.imwrite(os.path.join(folder,"frame{:d}.jpg".format(count)), image)     # save frame as JPEG file
    count += 1
print("{} images are extacted in {}.".format(count,folder))

En passant, vous pouvez vérifier le frame rat e par VLC. Accédez à Windows -> Informations sur les médias -> Détails du codec

5
Yuchao Jiang

J'utilise Python via le logiciel Spyder d'Anaconda. En utilisant le code original répertorié dans la question de ce fil par @Gshocked, le code ne fonctionne pas (le python ne lira pas le fichier mp4). J'ai donc téléchargé OpenCV 3.2 et copié "opencv_ffmpeg320.dll" et "opencv_ffmpeg320_64.dll" du dossier "bin". J'ai collé ces deux fichiers DLL dans le dossier "Dlls" d'Anaconda.

Anaconda a également un dossier "pckgs" ... J'ai copié et collé l'intégralité du dossier "OpenCV 3.2" que j'ai téléchargé dans le dossier Anaconda "pckgs".

Enfin, Anaconda a un dossier "Library" qui a un sous-dossier "bin". J'ai collé les fichiers "opencv_ffmpeg320.dll" et "opencv_ffmpeg320_64.dll" dans ce dossier.

Après avoir fermé et redémarré Spyder, le code a fonctionné. Je ne sais pas laquelle des trois méthodes a fonctionné, et je suis trop paresseux pour revenir en arrière et comprendre. Mais ça marche tellement, à la vôtre!

3
SpaceFarmer2020

Cette fonction extrait les images de la vidéo avec 1 ips, IN ADDITION identifie la dernière image et arrête la lecture aussi:

import cv2
import numpy as np

def extract_image_one_fps(video_source_path):

    vidcap = cv2.VideoCapture(video_source_path)
    count = 0
    success = True
    while success:
      vidcap.set(cv2.CAP_PROP_POS_MSEC,(count*1000))      
      success,image = vidcap.read()

      ## Stop when last frame is identified
      image_last = cv2.imread("frame{}.png".format(count-1))
      if np.array_equal(image,image_last):
          break

      cv2.imwrite("frame%d.png" % count, image)     # save frame as PNG file
      print '{}.sec reading a new frame: {} '.format(count,success)
      count += 1
3
Bence Kővári