Передайте необработанные изображения OpenCV в FFmpeg - PullRequest
25 голосов
/ 29 апреля 2011

Вот довольно простой пример чтения веб-камеры с использованием привязок Python OpenCV:

'''capture.py'''
import cv, sys
cap = cv.CaptureFromCAM(0)                    # 0 is for /dev/video0
while True :
    if not cv.GrabFrame(cap) : break
    frame = cv.RetrieveFrame(cap)
    sys.stdout.write( frame.tostring() )

Теперь я хочу передать вывод в ffmpeg, как в:

$ python capture.py | ffmpeg -f image2pipe -pix_fmt bgr8 -i - -s 640x480 foo.avi

К сожалениюЯ не могу правильно понять магическое заклинание ffmpeg, и оно не работает с

  libavutil     50.15. 1 / 50.15. 1
  libavcodec    52.72. 2 / 52.72. 2
  libavformat   52.64. 2 / 52.64. 2
  libavdevice   52. 2. 0 / 52. 2. 0
  libavfilter    1.19. 0 /  1.19. 0
  libswscale     0.11. 0 /  0.11. 0
  libpostproc   51. 2. 0 / 51. 2. 0
Output #0, avi, to 'out.avi':
    Stream #0.0: Video: flv, yuv420p, 640x480, q=2-31, 19660 kb/s, 90k tbn, 30 tbc
[image2pipe @ 0x1508640]max_analyze_duration reached
[image2pipe @ 0x1508640]Estimating duration from bitrate, this may be inaccurate
Input #0, image2pipe, from 'pipe:':
  Duration: N/A, bitrate: N/A
    Stream #0.0: Video: 0x0000, bgr8, 25 fps, 25 tbr, 25 tbn, 25 tbc
swScaler: 0x0 -> 640x480 is invalid scaling dimension
  • Захваченные кадры определенно имеют размер 640x480.
  • Я уверен, что порядок пикселейтип изображения OpenCV (IplImage) - GBR, один байт на канал.По крайней мере, это то, что кажется с камеры.

Я не гуру ffmpeg.Кто-нибудь сделал это успешно?

Ответы [ 4 ]

32 голосов
/ 30 апреля 2011

Взял кучу возни, но я понял это с помощью FFmpeg rawvideo demuxer :

python capture.py | ffmpeg -f rawvideo -pixel_format bgr24 -video_size 640x480 -framerate 30 -i - foo.avi

Поскольку в необработанном видео отсутствует заголовок, указывающий предполагаемые параметры видео, пользователь должен указать их, чтобы иметь возможность правильно декодировать данные:

  • -framerate Установка входной частоты кадров видео. Значение по умолчанию - 25.
  • -pixel_format Установите формат входного пикселя видео. Значением по умолчанию является yuv420p.
  • -video_size Установите размер входного видео. Нет значения по умолчанию, поэтому это значение должно быть указано явно.

А вот что-то лишнее для опытных пользователей. То же самое, но с использованием VLC для потоковой передачи выходных данных в Интернет, формат Flash:

python capture.py | cvlc --demux=rawvideo --rawvid-fps=30 --rawvid-width=320 --rawvid-height=240  --rawvid-chroma=RV24 - --sout "#transcode{vcodec=h264,vb=200,fps=30,width=320,height=240}:std{access=http{mime=video/x-flv},mux=ffmpeg{mux=flv},dst=:8081/stream.flv}"

Edit: Создайте поток webm, используя ffmpeg и ffserver

python capture.py | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 640x480 -framerate 25 -i - http://localhost:8090/feed1.ffm
2 голосов
/ 01 мая 2019

Я в порядке, но мой мощный VidGear Библиотека Python автоматизирует процесс конвейеризации кадров OpenCV в FFmpeg на любой платформе . Вот основной пример Python:

# import libraries
from vidgear.gears import WriteGear
import cv2

output_params = {"-vcodec":"libx264", "-crf": 0, "-preset": "fast"} #define (Codec,CRF,preset) FFmpeg tweak parameters for writer

stream = cv2.VideoCapture(0) #Open live webcam video stream on first index(i.e. 0) device

writer = WriteGear(output_filename = 'Output.mp4', compression_mode = True, logging = True, **output_params) #Define writer with output filename 'Output.mp4' 

# infinite loop
while True:

    (grabbed, frame) = stream.read()
    # read frames

    # check if frame empty
    if not is grabbed:
        #if True break the infinite loop
        break


    # {do something with frame here}
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # write a modified frame to writer
        writer.write(gray) 

        # Show output window
    cv2.imshow("Output Frame", frame)

    key = cv2.waitKey(1) & 0xFF
    # check for 'q' key-press
    if key == ord("q"):
        #if 'q' key-pressed break out
        break

cv2.destroyAllWindows()
# close output window

stream.release()
# safely close video stream
writer.close()
# safely close writer

Источник: https://github.com/abhiTronix/vidgear/wiki/Compression-Mode:-FFmpeg#2-writegear-classcompression-mode-with-opencv-directly

Вы можете проверить VidGear Docs для более продвинутых приложений и функций.

Надеюсь, это поможет!

1 голос
/ 06 августа 2016

Мне потребовался час, чтобы понять, что по умолчанию каналы Windows не являются двоичными. Это приводит к тому, что некоторые байты (в частности, новые строки) изменяются / опускаются, а результирующее видео медленно смещается, потому что размер кадра не постоянен.

Чтобы обойти это, модифицированный файл python:

"""
videoCapture.py
"""
import cv2, sys
import time

if sys.platform == "win32":
    import os, msvcrt
    msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)

cap = cv2.VideoCapture(0)                    # 0 is for /dev/video0
while True :
    ret, frm = cap.read()
    sys.stdout.write( frm.tostring() )

Чтобы проверить успешность передачи необработанного видео, используйте ffplay. Убедитесь, что вы указали более высокую частоту кадров, чем у канала, в противном случае видео начнет отставать

python videoCapture.py | ffplay -f rawvideo -pix_fmt bgr24 -s 640x480 -framerate 40 -i -
0 голосов
/ 21 марта 2018

Не уверен, что это для Mac OS или для python3, но мне нужно было привести кадр к строке, чтобы это работало для меня, например так:

sys.stdout.write(str(frame.tostring()))
...