当前位置:  开发笔记 > 编程语言 > 正文

如何将实时视频帧从ffmpeg传输到PIL?

如何解决《如何将实时视频帧从ffmpeg传输到PIL?》经验,为你挑选了1个好方法。

我需要使用ffmpeg/avconv将jpg帧传输到python PIL(Pillow)Image对象,使用gst作为中介*.我一直在寻找这个答案而没有太多运气.我想我很接近 - 但我被困住了.使用Python 2.7

我从python启动的理想管道如下所示:

    ffmpeg/avconv(作为h264视频)

    管道 - >

    gst-streamer(帧分为jpg)

    管道 - >

    Pil图像对象

我将控制的前几个步骤作为单个命令,将.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()

这段代码不起作用 - 我甚至不确定我是否可以这样使用"while pipe".我很擅长以这种方式使用缓冲区和管道.

我不知道如何知道图像已写入管道或何时读取"下一个"图像.

在理解如何从管道而不是磁盘读取图像时,将非常感谢任何帮助.

这最终是一个Raspberry Pi 3管道,为了提高我的帧速率,我不能(A)读/写磁盘或(B)使用逐帧捕获方法 - 而不是直接从H246视频运行相机芯片.

Ulrich Stern.. 6

我认为最终的目标是在Linux上以高帧率处理USB摄像头,以下解决这个问题.

首先,虽然一些USB摄像头支持H.264,但USB摄像头的Linux驱动程序(UVC驱动程序)目前不支持基于流的有效载荷,其中包括H.264,请参阅驱动程序主页上的"UVC功能"表.像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,1280x720仅支持10 fps,而对于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),请参阅此答案.



1> Ulrich Stern..:

我认为最终的目标是在Linux上以高帧率处理USB摄像头,以下解决这个问题.

首先,虽然一些USB摄像头支持H.264,但USB摄像头的Linux驱动程序(UVC驱动程序)目前不支持基于流的有效载荷,其中包括H.264,请参阅驱动程序主页上的"UVC功能"表.像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,1280x720仅支持10 fps,而对于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),请参阅此答案.

推荐阅读
虎仔球妈_459
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有