gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 00:14:09 26 4
gpt4 key购买 nike

我需要使用 ffmpeg/avconv 将 jpg 帧通过管道传输到 python PIL (Pillow) Image 对象,使用 gst 作为中介*。我一直在到处寻找这个答案,但运气不佳。我想我很接近 - 但我被困住了。 使用 Python 2.7

我理想的管道,从 python 启动,看起来像这样:

  1. ffmpeg/avconv(作为 h264 视频)
  2. 管道 ->
  3. gst-streamer(帧拆分为 jpg)
  4. 管道 ->
  5. Pil 图像对象

我将前几个步骤控制为单个命令,以硬件允许的最快速度将 .jpg 写入磁盘。

该命令看起来像这样:

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 视频。

最佳答案

我假设最终目标是在 Linux 上以高帧率处理 USB 摄像头,下面解决了这个问题。

首先,虽然一些 USB 摄像头支持 H.264,但 USB 摄像头的 Linux 驱动程序(UVC 驱动程序)目前不支持基于流的有效负载,其中包括 H.264,请参阅 driver home page 上的“UVC 功能”表。 ffmpeg 等用户空间工具使用该驱动程序,因此对于用于 USB 传输的视频格式具有相同的限制。

好消息是,如果相机支持 H.264,它几乎肯定会支持 MJPEG,它由 UVC 驱动程序支持并且压缩得很好,可以通过 USB 2.0 以 30 fps 支持 1280x720。您可以使用 v4l2-ctl -d 0 --list-formats-ext 列出您的相机支持的视频格式。例如,对于 Microsoft Lifecam Cinema,1280x720 仅支持 10 fps 的 YUV 4:2:2,但支持 30 fps 的 MJPEG。

对于从相机读取,我对 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

关于python - 如何将实时视频帧从 ffmpeg 传输到 PIL?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41580034/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com