2015-04-18 3 views
17

Ich möchte eine scikit-image Funktion (speziell die Vorlage Matching-Funktion match_template) auf die Rahmen einer mp4 Video, h264 Codierung anwenden. Es ist wichtig für meine Anwendung, die Zeit jedes Frames zu verfolgen, aber ich kenne die Framerate, so kann ich leicht aus der Frame-Nummer berechnen.Wie liest man mp4-Videos, die von scikit-image verarbeitet werden sollen?

Bitte beachten Sie, dass ich mit niedrigen Ressourcen arbeite, und ich möchte Abhängigkeiten so schlank wie möglich halten: numpy wird sowieso benötigt, und da ich scikit-image verwenden möchte, würde ich vermeiden, zu importieren (und kompilieren) openCV nur um das Video zu lesen.

Ich sehe auf der Unterseite der this Seite, die scikit-image kann seaslearly verarbeitet Video als numpy Array gespeichert, wodurch das wäre ideal.

+0

Nun habe ich versucht, OpenCV, während ein Prototyp meiner Anwendung auf dem PC zu entwickeln. Aber da ich die App auf raspberry pi liefern werde, bewerte ich leichtere Alternativen, auch unter Berücksichtigung des Aufwands und der Abhängigkeiten, um opencv auf raspi zu kompilieren. – gaggio

+3

Siehe auch [diese Übersicht] (https://github.com/danielballan/scikit-image/blob/video-guide/doc/source/user_guide/video.txt), die wir für das Benutzerhandbuch vorbereiten. –

+0

@StefanvanderWalt: Die Übersicht ist eigentlich sehr hilfreich, danke. Es könnte verbessert werden, Image hinzuzufügen, was auch das Problem des Zugriffs auf eine bestimmte Frame-Nummer löst, die auch in Ihrem Review erwähnt wird. – gaggio

Antwort

35

Imageio Python-Paket sollte tun, was Sie wollen. Hier ist ein Python-Schnipsel mit diesem Paket:

import pylab 
import imageio 
filename = '/tmp/file.mp4' 
vid = imageio.get_reader(filename, 'ffmpeg') 
nums = [10, 287] 
for num in nums: 
    image = vid.get_data(num) 
    fig = pylab.figure() 
    fig.suptitle('image #{}'.format(num), fontsize=20) 
    pylab.imshow(image) 
pylab.show() 

enter image description here enter image description here

können Sie auch direkt iterieren über die Bilder in der Datei (see the documentation):

for i, im in enumerate(vid): 
    print('Mean of frame %i is %1.1f' % (i, im.mean())) 

installieren ImageIO können Sie Verwenden Sie pip:

pip install imageio 

Eine andere Lösung wäre, moviepy zu verwenden (die einen ähnlichen Code verwenden, um Video zu lesen), aber ich denke, imageio ist leichter und macht den Job.


Antwort auf ersten Kommentar

Um, wenn die Nennframerate zu überprüfen die gleiche über die gesamte Datei ist, die Anzahl der Rahmen in der Iterator zählen:

count = 0 
try: 
    for _ in vid: 
     count += 1 
except RuntimeError: 
    print('something went wront in iterating, maybee wrong fps number') 
finally: 
    print('number of frames counted {}, number of frames in metada {}'.format(count, vid.get_meta_data()['nframes'])) 


In [10]: something went wront in iterating, maybee wrong fps number 
     number of frames counted 454, number of frames in metada 461 

um den Zeitstempel jedes Rahmens anzuzeigen:

try: 
    for num, image in enumerate(vid.iter_data()): 
     if num % int(vid._meta['fps']): 
      continue 
     else: 
      fig = pylab.figure() 
      pylab.imshow(image) 
      timestamp = float(num)/ vid.get_meta_data()['fps'] 
      print(timestamp) 
      fig.suptitle('image #{}, timestamp={}'.format(num, timestamp), fontsize=20) 
      pylab.show() 
except RuntimeError: 
    print('something went wrong') 
+0

Danke für den nützlichen Link und das Beispiel. Was ausgelassen wird, ist nur die Zeit, die jedem Rahmen entspricht. Ich gebe es an, die Zeit könnte in den Frame-Metadaten liegen, ansonsten muss sie aus der Frame-Nummer berechnet werden, was in Ordnung ist unter der Annahme, dass die nominale Framerate während der Videoaufnahme korrekt beibehalten wird. – gaggio

+0

Gute Frage, und bei einigen Videos wird die nominale Framerate nicht korrekt beibehalten. Um es zu überprüfen, können Sie die Anzahl der Frames im Iterator zählen und mit der Anzahl der Frames in den Metadaten vergleichen. Wenn sie gleich sind, können Sie den Timestamp jedes Frames basierend auf frame_number/fps_rate berechnen. Ich habe meine Antwort aktualisiert, um die beiden Zahlen zu vergleichen. – head7

+1

Das funktioniert gut für mich. Vielen Dank. IMO viel freundlicher als ffmpeg/avconv/opencv/scikit-video opencv fühlen. Ich wünschte, ich hätte das früher entdeckt. – rd11

16

Sie könnten scikit-video verwenden, wie folgt aus:

from skvideo.io import VideoCapture 

cap = VideoCapture(filename) 
cap.open() 

while True: 
    retval, image = cap.read() 
    # image is a numpy array containing the next frame 
    # do something with image here 
    if not retval: 
     break 

Dies verwendet avconv oder ffmpeg unter der Haube. Die Leistung ist ziemlich gut, mit einem kleinen Overhead, um die Daten in Python zu verschieben, verglichen mit dem Decodieren des Videos in avconv.

Der Vorteil von scikit-video ist, dass die API genau der API zum Lesen/Schreiben von Videos von OpenCV entspricht; Ersetzen Sie einfach cv2.VideoCapture durch skvideo.io.VideoCapture.

Verwandte Themen