我需要使用ffmpeg / avconv将jpg帧传输到python PIL( Pillow )Image对象,使用gst作为中介*。我没有太多运气,一直在寻找这个答案。我想我已经接近了 - 但是我被困了。 使用Python 2.7
我从python启动的理想管道如下所示:
我将控制的前几个步骤作为单个命令,将.jpgs写入磁盘的速度与硬件允许的速度一样快。
该命令看起来像这样:
command = [
"ffmpeg",
"-f video4linux2",
"-r 30",
"-video_size 1280x720",
"-pixel_format 'uyvy422'",
"-i /dev/video0",
"-vf fps=30",
"-f H264",
"-vcodec libx264",
"-preset ultrafast",
"pipe:1 -",
"|", # Pipe to GST
"gst-launch-1.0 fdsrc !",
"video/x-h264,framerate=30/1,stream-format=byte-stream !",
"decodebin ! videorate ! video/x-raw,framerate=30/1 !",
"videoconvert !",
"jpegenc quality=55 !",
"multifilesink location=" + Utils.live_sync_path + "live_%04d.jpg"
]
如果使用popen或os.system运行,这将成功将帧写入磁盘。
但是我没有将帧写入磁盘,而是想要捕获我的子进程管道中的输出,并在写入时将帧读取到类似文件的缓冲区中,然后由PIL读取。
这样的事情:
import subprocess as sp
import shlex
import StringIO
clean_cmd = shlex.split(" ".join(command))
pipe = sp.Popen(clean_cmd, stdout = sp.PIPE, bufsize=10**8)
while pipe:
raw = pipe.stdout.read()
buff = StringIO.StringIO()
buff.write(raw)
buff.seek(0)
# Open or do something clever...
im = Image.open(buff)
im.show()
pipe.flush()
这段代码不起作用 - 我甚至不确定我可以使用"而管道#34;通过这种方式。我以这种方式使用缓冲区和管道是相当新的。
我不知道如何知道图片已写入管道或何时阅读“下一步”图片。图片。
在理解如何从管道而不是磁盘读取图像时,将非常感谢任何帮助。
答案 0 :(得分:5)
我认为最终目标是在Linux上以高帧率处理USB摄像头,以下内容解决了这个问题。
首先,虽然一些USB摄像头支持H.264,但USB摄像头的Linux驱动程序(UVC驱动程序)目前不支持基于流的有效载荷,其中包括H.264,参见" UVC功能" driver home page上的表格。像ffmpeg这样的用户空间工具使用驱动程序,因此对于使用哪种视频格式进行USB传输有相同的限制。
好消息是,如果摄像头支持H.264,它几乎肯定支持MJPEG,它受UVC驱动程序的支持,压缩得足够好,可以通过USB 2.0以30 fps支持1280x720。您可以使用v4l2-ctl -d 0 --list-formats-ext
列出相机支持的视频格式。对于Microsoft Lifecam Cinema,例如,对于YUV 4:2:2,仅支持10 fps的1280x720,但对于MJPEG,支持30 fps。
从相机读取,我对OpenCV有很好的经验。在我的一个项目中,我有24个(!)Lifecams连接到一台Ubuntu 6核i7机器,该机器使用320x240(每个相机7.5 fps)对果蝇进行实时跟踪(以及为每个摄像机保存一个MJPEG AVI以记录实验)。由于OpenCV直接使用V4L2 API,它应该比使用ffmpeg,gst-streamer和两个管道的解决方案更快。
使用OpenCV从相机读取的裸骨(无错误检查)代码并创建PIL图像如下所示:
import cv2
from PIL import Image
cap = cv2.VideoCapture(0) # /dev/video0
while True:
ret, frame = cap.read()
if not ret:
break
pil_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
... # do something with PIL image
最后说明:您可能需要构建v4l版本的OpenCV才能获得压缩(MJPEG),请参阅this answer。