相关文章推荐
谦和的凉面  ·  python - change ...·  2 年前    · 
狂野的充值卡  ·  Color::Color ...·  2 年前    · 

用ffmpeg从python openCV中流传图像

0 人关注

为了尝试嵌入式人工智能,我想通过rtsp流来传输一个图像数据集。 我想做的是每隔X秒读取一张图片,并将其发送到流中,然后在上面推导出我的AI。我尝试使用这个github repo :https://gist.github.com/takidog/2c981c34d5d5b41c0d712f8ef4ac60d3#file-main-py

这是我到目前为止所尝试的。

import cv2
import time
import subprocess as sp 
import glob, os
__PATH = "./DATASET"
os.chdir(__PATH)
IMG_LIST = glob.glob("*.jpg")
IMG_LIST_LEN = len(IMG_LIST)
IMG_INDEX = 0
IMG_DELAY = 2
IMG_WIDTH = 1280
IMG_HEIGHT = 720
IMG_SIZE = str(IMG_WIDTH)+"x"+str(IMG_HEIGHT)
FPS = 5
RTSP_SERVER = "rtsp://localhost:31415/stream"
COMMAND = ['ffmpeg',
           '-re',
            '-s', IMG_SIZE,
            '-r', str(FPS),
            '-i', '-',
            '-bufsize', '64M',
            '-maxrate', "4M",
            '-rtsp_transport', 'tcp',
            '-muxdelay','0.1',
            RTSP_SERVER]
process = sp.Popen(COMMAND,stdin=sp.PIPE)
while(True):
    CURRENT_IMG = cv2.imread(IMG_LIST[IMG_INDEX])
    IMG_INDEX = (IMG_INDEX+1)%IMG_LIST_LEN
    while(CURRENT_IMG.shape[0]!=720): #We dump images with a bad format
        CURRENT_IMG = cv2.imread(IMG_LIST[IMG_INDEX])
        IMG_INDEX = (IMG_INDEX+1)%IMG_LIST_LEN
    _,FRAME = cv2.imencode('.png', CURRENT_IMG)
    process.stdin.write(FRAME.tobytes())
    time.sleep(1/FPS)

令人惊讶的是,这并不奏效,给我带来了这个错误。

Input #0, png_pipe, from 'pipe:':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: png, rgb24(pc), 1280x720, 25 fps, 25 tbr, 25 tbn, 25 tbc
[NULL @ 0x55ba3fe1b860] Unable to find a suitable output format for 'rtsp://localhost:31415/stream'
rtsp://localhost:31415/stream: Invalid argument
Traceback (most recent call last):
  File "main.py", line 47, in <module>
    process.stdin.write(FRAME.tobytes())
BrokenPipeError: [Errno 32] Broken pipe
    
5 个评论
添加 '-f', 'rtsp', 参数,再试一次。
嗨,对不起,回答得太晚了:当我添加这个参数时,它给了我: [tcp @ 0x5591ee1734c0] Connection to tcp://localhost:31415?timeout=0 failed: Connection refused Could not write header for output file #0 (incorrect codec parameters ?): Connection refused Error initializing output stream 0:0 -- Conversion failed! Traceback (most recent call last): File "main.py", line 47, in <module> process.stdin.write(FRAME.tobytes()) BrokenPipeError: [Errno 32] Broken pipe
我建议你先试试UDP。TCP协议要求在流媒体开始之前,TCP服务器(接收大小)必须启动。这可能是出错的原因(我不确定)。
我试着用 -rtsp_transport udp ,但错误仍然完全一样。
我发布了一个可重复的代码样本。如果还是不行的话,可以尝试更新FFmpeg的版本。我的回答试图解决FFmpeg的流媒体问题(不解决你的AI推理案例)。你也许可以用 cap = cv2.VideoCapture 替换FFplay(监听器),但我没有测试。
python
python-3.x
opencv
ffmpeg
opencv-python
Max D.
Max D.
发布于 2021-07-27
1 个回答
Rotem
Rotem
发布于 2021-08-03
0 人赞同

这里有一个可重现的例子--希望你能复制粘贴并执行,但什么也不答应......

这个例子适用于以下阶段。

  • ./test_dataset 文件夹中创建10张合成JPEG图像,作为输入。
  • 作为RTSP监听器执行 FFplay 子进程。
    当使用TCP协议时,我们应该首先启动TCP服务器(FFplay在本例中被用作TCP服务器)。
    我们还需要接收进程,因为没有它,FFmpeg流媒体进程在第一帧后就会停止。
  • 执行FFmpeg的RTSP流媒体子进程。
    循环读取JPEG图像到NumPy数组(BGR颜色格式),并将数组作为原始视频帧写到stdin管道。
    注意:写原始视频帧比将每一帧编码为PNG(如你的参考样本所使用的)更有效。
  • 以下是代码。

    import cv2
    #import time
    import subprocess as sp 
    import glob
    import os
    img_width = 1280
    img_height = 720
    test_path = './test_dataset'  # Folder with synthetic sample images.
    os.makedirs(test_path, exist_ok=True)  # Create folder for input images.
    os.chdir(test_path)
    ffmpeg_cmd = 'ffmpeg'  # May use full path like: 'c:\\FFmpeg\\bin\\ffmpeg.exe'
    ffplay_cmd = 'ffplay'  # May use full path like: 'c:\\FFmpeg\\bin\\ffplay.exe'
    # Create 10 synthetic JPEG images for testing (image0001.jpg, image0002.jpg, ..., image0010.jpg).
    sp.run([ffmpeg_cmd, '-y', '-f', 'lavfi', '-i', f'testsrc=size={img_width}x{img_height}:rate=1:duration=10', 'image%04d.jpg'])
    img_list = glob.glob("*.jpg")
    img_list_len = len(img_list)
    img_index = 0
    fps = 5
    rtsp_server = 'rtsp://localhost:31415/live.stream'
    # You will need to start the server up first, before the sending client (when using TCP). See: https://trac.ffmpeg.org/wiki/StreamingGuide#Pointtopointstreaming
    ffplay_process = sp.Popen([ffplay_cmd, '-rtsp_flags', 'listen', rtsp_server])  # Use FFplay sub-process for receiving the RTSP video.
    command = [ffmpeg_cmd,
               '-re',
               '-f', 'rawvideo',  # Apply raw video as input - it's more efficient than encoding each frame to PNG
               '-s', f'{img_width}x{img_height}',
               '-pixel_format', 'bgr24',
               '-r', f'{fps}',
               '-i', '-',
               '-pix_fmt', 'yuv420p',
               '-c:v', 'libx264',
               '-bufsize', '64M',
               '-maxrate', '4M',
               '-rtsp_transport', 'tcp',
               '-f', 'rtsp',
               #'-muxdelay', '0.1',
               rtsp_server]
    process = sp.Popen(command, stdin=sp.PIPE)  # Execute FFmpeg sub-process for RTSP streaming
    while True:
        current_img = cv2.imread(img_list[img_index])  # Read a JPEG image to NumPy array (in BGR color format) - assume the resolution is correct.
        img_index = (img_index+1) % img_list_len  # Cyclically repeat images
        process.stdin.write(current_img.tobytes())  # Write raw frame to stdin pipe.
        cv2.imshow('current_img', current_img)  # Show image for testing
        # time.sleep(1/FPS)
        key = cv2.waitKey(int(round(1000/fps)))  # We need to call cv2.waitKey after cv2.imshow
        if key == 27:  # Press Esc for exit
            break