-
-
Save gnsx/826062506c694b00d7b166f4fc85f5c0 to your computer and use it in GitHub Desktop.
Feeding Python Opencv with FFmpeg
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Reading video from FFMPEG using subprocess - aka when OpenCV VideoCapture fails | |
# | |
# 2017 note: I have realized that this is similar to moviepy ffmpeg reader with the difference that here we support YUV encoding | |
# BUT we lack: bufsize in POpen and creation flags for windows | |
# https://github.com/Zulko/moviepy/blob/master/moviepy/video/io/ffmpeg_reader.py | |
# | |
# Emanuele Ruffaldi 2016 | |
import cv2 | |
import subprocess | |
import numpy as np | |
import os | |
class FFmpegVideoCapture: | |
# TODO probe width/height | |
# TODO enforce width/height | |
# | |
# mode=gray,yuv420p,rgb24,bgr24 | |
def __init__(self,source,width,height,mode="gray",start_seconds=0,duration=0,verbose=False): | |
x = ['ffmpeg'] | |
if start_seconds > 0: | |
#[-][HH:]MM:SS[.m...] | |
#[-]S+[.m...] | |
x.append("-accurate_seek") | |
x.append("-ss") | |
x.append("%f" % start_seconds) | |
if duration > 0: | |
x.append("-t") | |
x.append("%f" % duration) | |
x.extend(['-i', source,"-f","rawvideo", "-pix_fmt" ,mode,"-"]) | |
self.nulldev = open(os.devnull,"w") if not verbose else None | |
self.ffmpeg = subprocess.Popen(x, stdout = subprocess.PIPE, stderr=subprocess.STDERR if verbose else self.nulldev) | |
self.width = width | |
self.height = height | |
self.mode = mode | |
if self.mode == "gray": | |
self.fs = width*height | |
elif self.mode == "yuv420p": | |
self.fs = width*height*6/4 | |
elif self.mode == "rgb24" or self.mode == "bgr24": | |
self.fs = width*height*3 | |
self.output = self.ffmpeg.stdout | |
def read(self): | |
if self.ffmpeg.poll(): | |
return False,None | |
x = self.output.read(self.fs) | |
if x == "": | |
return False,None | |
if self.mode == "gray": | |
return True,np.frombuffer(x,dtype=np.uint8).reshape((self.height,self.width)) | |
elif self.mode == "yuv420p": | |
# Y fullsize | |
# U w/2 h/2 | |
# V w/2 h/2 | |
k = self.width*self.height | |
return True,(np.frombuffer(x[0:k],dtype=np.uint8).reshape((self.height,self.width)), | |
np.frombuffer(x[k:k+(k/4)],dtype=np.uint8).reshape((self.height/2,self.width/2)), | |
np.frombuffer(x[k+(k/4):],dtype=np.uint8).reshape((self.height/2,self.width/2)) | |
) | |
elif self.mode == "bgr24" or self.mode == "rgb24": | |
return True,(np.frombuffer(x,dtype=np.uint8).reshape((self.height,self.width,3))) | |
if __name__ == '__main__': | |
import sys | |
if len(sys.argv) < 5: | |
print "filename w h mode\nWhere mode is: gray|yuv420p|bgr24" | |
else: | |
capture = FFmpegVideoCapture(sys.argv[1],int(sys.argv[2]),int(sys.argv[3]),sys.argv[4]) | |
while True: | |
ret, img = capture.read() | |
if not ret: | |
print "exit with",ret,img | |
break | |
if type(img) is tuple: | |
cv2.imshow("Y",img[0]) | |
cv2.imshow("U",img[1]) | |
cv2.imshow("V",img[2]) | |
else: | |
cv2.imshow("img",img) | |
cv2.waitKey(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment