2017-01-10 58 views
6

Potrzebuję użyć programu ffmpeg/avconv do obsługi ramek jpg do python PIL (Poduszka) Obiekt obrazu, używając gst jako pośrednika *. Szukałem wszędzie tej odpowiedzi bez powodzenia. Myślę, że jestem blisko - ale utknąłem. Używanie Pythona 2.7Jak potasować klatki wideo na żywo z ffmpeg do PIL?

Mój ideał rurociąg, wystrzelony z pytona, wygląda następująco:

  1. ffmpeg/avconv (jak h264 wideo)
  2. rurami ->
  3. GST -streamer (ramki podzielone na jpg)
  4. Piped ->
  5. Pil Object Obraz

Mam kilka pierwszych kroków pod kontrolą jako jedno polecenie, które zapisuje na dysku jako .jpgs wściekle szybki jak sprzęt pozwoli.

tego polecenia wygląda tak:

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" 
     ] 

To będzie z powodzeniem napisać klatek na dysk czy biegł z popen lub os.system.

Ale zamiast zapisywać klatki na dysku, chcę przechwycić dane wyjściowe w potoku podprocesu i odczytać klatki, tak jak zostały napisane, w buforze podobnym do pliku, który może zostać odczytany przez PIL.

coś takiego:

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() 

Ten kod nie działa - nie jestem nawet pewien, czy mogę użyć „natomiast rura” w ten sposób. Jestem całkiem nowy w używaniu buforów i rurociągów w ten sposób.

Nie jestem pewien, skąd wiedziałbym, że obraz został zapisany w rurze lub kiedy należy przeczytać "następny" obraz.

Każda pomoc byłaby bardzo ceniona w zrozumieniu, jak odczytać obrazy z rury zamiast z dysku.

  • To ostatecznie Raspberry Pi 3 rurociąg oraz w celu zwiększenia swoich klatek nie mogę (A) odczyt/zapis do/z dysku lub (b) stosowanie ramkę metodą przechwytywania klatek - jak w przeciwieństwie do uruchamiania wideo H246 bezpośrednio z układu kamery.
+0

Dlaczego nie możesz użyć czegoś takiego jak [pyav] (https://github.com/mikeboers/PyAV)? – Priyatham

+0

Czy na pewno chcesz przeskoczyć przez te obręcze? Można uzyskać dobrą częstość klatek z pikamera. Zobacz http://raspberrypi.stackexchange.com/questions/22040/take-images-in-a-short-time-using-the-raspberry-pi-camera-module –

+0

Nie używam aparatu Pi - kamera jest kamera USB –

Odpowiedz

2

Zakładam, że ostatecznym celem jest obsługa kamery USB z wysoką częstością klatek w systemie Linux, a poniższe adresy to pytanie.

Po pierwsze, podczas gdy kilka kamer USB obsługuje standard H.264, sterownik Linux dla kamer USB (sterownik UVC) obecnie nie obsługuje ładunków opartych na strumieniu, w tym H.264, patrz tabela "Tabela UVC" na driver home page . Narzędzia przestrzeni użytkownika, takie jak ffmpeg, używają sterownika, więc mają te same ograniczenia dotyczące formatu wideo używanego do transferu USB.

Dobrą wiadomością jest to, że jeśli kamera obsługuje standard H.264, prawie na pewno obsługuje MJPEG, który jest obsługiwany przez sterownik UVC i kompresuje wystarczająco dobrze, aby obsłużyć 1280x720 przy 30 fps na USB 2.0. Możesz wyświetlić listę formatów wideo obsługiwanych przez kamerę, używając v4l2-ctl -d 0 --list-formats-ext. W kinie Microsoft Lifecam np. 1280 x 720 jest obsługiwane tylko przy 10 fps dla YUV 4: 2: 2, ale przy 30 fps dla MJPEG.

Do czytania z kamery mam dobre doświadczenia z OpenCV. W jednym z moich projektów mam 24 (!) Lifecam podłączone do pojedynczej 6-rdzeniowej maszyny i7 z Ubuntu, która wykonuje w czasie rzeczywistym śledzenia muszek owocowych za pomocą 320x240 przy 7,5 fps na kamerę (a także zapisuje MJPEG AVI dla każda kamera ma zapis eksperymentu). Ponieważ OpenCV bezpośrednio korzysta z API V4L2, powinno być szybsze niż rozwiązanie z użyciem ffmpeg, gst-streamer i dwóch potoków.

szkielety (bez sprawdzania błędów) kod do odczytu z aparatu za pomocą OpenCV i tworzenia obrazów PIL wygląda następująco:

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 

Ostatnia uwaga: prawdopodobnie trzeba zbudować wersję v4l z OpenCV uzyskać kompresję (MJPEG), patrz this answer.

+0

1. Twoje założenie jest dokładnie poprawne 2. Twój nagi kod kości działa doskonale 3. Dziękuję za wzięcie mojego pytania, interpretację tego, co należy zrobić i zapewnienie pracy , dobrze przemyślana odpowiedź na przykładzie. –

+0

Zapraszamy i szczęśliwy kod działa na Pi! –

Powiązane problemy