search替代作为OpenCV不会提供实时相机stream(在Windows上) ,这是我的计算机视觉algorithm所需的时间戳,我发现ffmpeg和这个优秀的文章https://zulko.github.io/blog/2013/09 / 27 / read-and-write-video-frames-in-python-using-ffmpeg /解决scheme使用ffmpeg,访问其标准输出(stdout)stream。 我扩展它来读取标准错误(stderr)stream。
在windows上处理python代码,而我从ffmpeg stdout接收video帧,但stderr在为第一帧传送showinfo videofilter细节(时间戳)之后冻结。
我回忆起在ffmpeg论坛上看到,像showinfo这样的videofilter在redirect时被绕过。 这就是为什么下面的代码不能按预期工作?
预期:它应该写video帧到磁盘以及打印时间戳详细信息。
实际:它写入video文件,但没有得到时间戳(showinfo)的细节。
PyWin32:Windows经典主题
我怎样才能找出谁在Windows中使用.NET创build一个文件?
我怎么能创build一个像微软应用程序的TreeView
如何让DirectShow从资源播放video?
从Java执行batch file不能访问完整的PATH
这是我尝试的代码:
import subprocess as sp import numpy import cv2 command = [ 'ffmpeg','-i','e:sample.wmv','-pix_fmt','rgb24','-vcodec','rawvideo','-vf','showinfo',# video filter - showinfo will provide frame timestamps '-an','-sn',#-an,-sn disables audio and sub-title processing respectively '-f','image2pipe','-'] # we need to output to a pipe pipe = sp.Popen(command,stdout = sp.PIPE,stderr = sp.PIPE) # Todo someone on ffmpeg forum said video filters (eg showinfo) are bypassed when stdout is redirected to pipes??? for i in range(10): raw_image = pipe.stdout.read(1280*720*3) img_info = pipe.stderr.read(244) # 244 characters is the current output of showinfo video filter print "showinfo output",img_info image1 = numpy.fromstring(raw_image,dtype='uint8') image2 = image1.reshape((720,1280,3)) # write video frame to file just to verify videoFrameName = 'Video_Frame{0}.png'.format(i) cv2.imwrite(videoFrameName,image2) # throw away the data in the pipe's buffer. pipe.stdout.flush() pipe.stderr.flush()
那么如何仍然从ffmpeg帧时间戳到Python代码,以便它可以在我的计算机视觉algorithm中使用…
GAE Python – PyCrypto – 没有名为winrandom的模块
即使我已经安装了jdk,Android studio也不能识别jvm
Windows http.sys替代linux平台
Docker错误:从Win10运行时找不到或不存在容器命令
Ant set platforms.JDK_1.6.home不带参数
您可以使用MoviePy :
import moviepy.editor as mpy vid = mpy.VideoFileClip('e:\sample.wmv') for timestamp,raw_img in vid.iter_frames(with_times=True): # do stuff
重定向stderr在Python中工作。
所以不是这个pipe = sp.Popen(command,stderr = sp.PIPE)
做这个pipe = sp.Popen(command,stderr = sp.STDOUT)
我们可以通过添加异步调用来读取ffmpeg的标准流(stdout和stderr)来避免重定向。 这将避免视频帧和时间戳的混合,从而避免错误的分离。 所以修改原来的代码来使用threading模块看起来像这样:
# Python script to read video frames and timestamps using ffmpeg import subprocess as sp import threading import matplotlib.pyplot as plt import numpy import cv2 ffmpeg_command = [ 'ffmpeg','-nostats',# do not print extra statistics #'-debug_ts',# -debug_ts Could provide timestamps avoiding showinfo filter (-vcodec copy). Need to check by providing expected fps Todo '-r','30',# output 30 frames per second '-i','-an',-sn disables audio and sub-title processing respectively '-pix_fmt',#'-vcodec','copy',# very fast!,direct copy - Note: No Filters,No Decode/Encode,no quality loss #'-vframes','20',# process n video frames only. For Debugging '-vf',# showinfo videofilter provides frame timestamps as pts_time '-f','pipe:1' ] # outputs to stdout pipe. can also use '-' which is redirected to pipe # seperate method to read images on stdout asynchronousously def AppendProcStdout(proc,nbytes,AppendList): while proc.poll() is None: # continue while the process is alive AppendList.append(proc.stdout.read(nbytes)) # read image bytes at a time # seperate method to read image info. on stderr asynchronousously def AppendProcStderr(proc,AppendList): while proc.poll() is None: # continue while the process is alive try: AppendList.append(proc.stderr.next()) # read stderr until empty except stopiteration: continue # ignore stderr empty exception and continue if __name__ == '__main__': # run ffmpeg command pipe = sp.Popen(ffmpeg_command,stdout=sp.PIPE,stderr=sp.PIPE) # 2 threads to talk with ffmpeg stdout and stderr pipes framesList = []; frameDetailsList = [] appendFramesThread = threading.Thread(group=None,target=AppendProcStdout,name='FramesThread',args=(pipe,1280*720*3,framesList),kwargs=None,verbose=None) # assuming rgb video frame with size 1280*720 appendInfoThread = threading.Thread(group=None,target=AppendProcStderr,name='InfoThread',frameDetailsList),verbose=None) # start threads to capture ffmpeg frames and info. appendFramesThread.start() appendInfoThread.start() # wait for few seconds and close - simulating cancel import time; time.sleep(2) pipe.terminate() # check if threads finished and close appendFramesThread.join() appendInfoThread.join() # save an image per 30 frames to disk savedList = [] for cnt,raw_image in enumerate(framesList): if (cnt%30 != 0): continue image1 = numpy.fromstring(raw_image,3)) # assuming rgb image with size 1280 X 720 # write video frame to file just to verify videoFrameName = 'video_frame{0}.png'.format(cnt) cv2.imwrite(videoFrameName,image2) savedList.append('{} {}'.format(videoFrameName,image2.shape)) print '### Results ###' print 'Images captured: ({}) nImages saved to disk:{}n'.format(len(framesList),savedList) # framesList contains all the video frames got from the ffmpeg print 'Images info captured: n',''.join(frameDetailsList) # this contains all the timestamp details got from the ffmpeg showinfo videofilter and some initial noise text which can be easily removed while parsing
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。