2017-01-10 6 views
6

Мне нужно использовать ffmpeg/avconv для подключения кадров jpg к python PIL (Pillow) Объект изображения, используя gst как посредник *. Я везде искал этот ответ без большой удачи. Я думаю, что я рядом, но я застрял. Использование Python 2.7Как подключить живые видеокадры от ffmpeg до PIL?

Мой идеальный трубопроводный, запущенная из питона, выглядит следующим образом:

  1. FFmpeg/avconv (как h264 видео)
  2. Водопроводной ->
  3. GST -отвод (рамы разделены на jpg)
  4. Трубы ->
  5. Пил Объект Image

У меня есть несколько первых шагов под контролем как одну команду, которая записывает .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() 

Этот код не работает - я даже не уверен, что я могу использовать «в то время как труба» таким образом. Я довольно новичок в использовании буферов и трубопроводов таким образом.

Я не уверен, как бы я знал, что изображение было записано в трубу или когда было прочитано «следующее» изображение.

Любая помощь будет принята с благодарностью при понимании того, как читать изображения из трубы, а не на диск.

  • Это в конечном счете, трубопровод Малина Pi 3 и для того, чтобы увеличить свои частоты кадров я не могу (А) чтения/записи на/с диска или (В) используют кадр методом захвата кадра - в качестве против прямого запуска видео H246 непосредственно с чипа камеры.
+0

Почему вы не можете использовать что-то вроде [pyav] (https://github.com/mikeboers/PyAV)? – Priyatham

+0

Вы уверены, что вам нужно перепрыгнуть через эти обручи? Можно получить хорошую частоту кадров от пикамера. См. Http://raspberrypi.stackexchange.com/questions/22040/take-images-in-a-short-time-using-the-raspberry-pi-camera-module –

+0

Я не пользуюсь камерой Pi - камера USB-камера –

ответ

2

Я предполагаю, что конечная цель состоит в том, чтобы обрабатывать USB-камеру с высокой частотой кадров в Linux, и следующие адреса этого вопроса.

Во-первых, в то время как несколько USB-камер поддерживают H.264, драйвер Linux для USB-камер (драйвер UVC) в настоящее время не поддерживает поточную полезную нагрузку, которая включает H.264, см. Таблицу «UVC Feature» на driver home page , Инструменты пользовательского пространства, такие как ffmpeg, используют драйвер, поэтому имеют те же ограничения, что и формат видео для передачи USB.

Хорошей новостью является то, что если камера поддерживает H.264, она почти наверняка поддерживает MJPEG, который поддерживается драйвером UVC и сжимается достаточно хорошо, чтобы поддерживать 1280x720 при скорости 30 кадров в секунду по USB 2.0. Вы можете указать видеоформаты, поддерживаемые вашей камерой, с помощью v4l2-ctl -d 0 --list-formats-ext. Для кинотеатра Microsoft Lifecam Cinema, например, 1280x720 поддерживается только 10 кадров в секунду для YUV 4: 2: 2, но при 30 fps для MJPEG.

Для чтения с камеры у меня есть хороший опыт работы с OpenCV. В одном из моих проектов у меня есть 24 (!) Lifecams, подключенных к одной 6-ядерной машине i7 Ubuntu, которая делает в режиме реального времени отслеживание плодовых мух с использованием 320x240 при 7,5 кадрах в секунду на камеру (а также сохраняет MJPEG AVI для каждая камера должна иметь запись эксперимента). Поскольку OpenCV напрямую использует API V4L2, он должен быть быстрее, чем решение, использующее 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.

+0

1. Ваше предположение точно верное. 2. Ваш костяной код работает отлично 3. Спасибо за то, что вы приняли мой вопрос, интерпретировали, что нужно сделать, и обеспечив работу , хорошо продуманный ответ с примером. –

+0

Добро пожаловать и рад, что код работает на Pi! –