从 H264 流中提取每个单独的帧,以便使用 OpenCV 进行实时分析



>问题大纲

我在 Process1 中捕获了一个 h264 实时视频流(我称之为">"(。我的目标是从流中提取每个帧,并使用 Process2 使用 OpenCV 对其进行分析。(Process1 是 nodejs,Process2 是 Python(

我尝试过的事情,以及它们的失败模式:

  • 通过命名的 fifo 管道将流从一个进程 1 直接发送到进程 2

我成功地将流从进程 1 定向到管道中。但是,在Process2(这是Python(中,我无法(a(从流中提取单个帧,并且(b(将从h264中提取的任何数据转换为OpenCV格式(例如.JPEG numpy数组(。

我曾希望使用OpenCV的VideoCapture((方法,但它不允许你将FIFO管道作为输入传递。我能够通过将 h264 流保存到 .h264 文件,然后将其作为文件路径传递来使用 VideoCapture。这对我没有帮助,因为我需要实时进行分析(即,在将流读入OpenCV之前,我无法将流保存到文件中(。

  • 将流从进程 1 传送到 FFMPEG,使用 FFMPEG 将流格式从 h264 更改为 MJPEG,然后将输出通过管道传输到进程 2

我尝试使用以下命令执行此操作:

猫管从过程1.fifo | ffmpeg -i 管道:0 -f h264 -f mjpeg 管道:1 | cat> pipeToProcess2.fifo

这种方法的最大问题是FFMPEG从进程1获取输入,直到进程1被杀死,然后进程2才开始接收数据。

此外,在 Process2 方面,我仍然不明白如何从通过管道的数据中提取单个帧。我打开管道进行读取(作为"f"(,然后执行数据 = f.readline((。数据的大小变化很大(有些读取的长度约为 100,其他读取的长度约为 1,000(。当我使用 f.read(( 而不是 f.readline(( 时,长度要大得多,大约 100,000。

如果我知道我得到了正确大小的数据块,我仍然不知道如何将其转换为与OpenCV兼容的数组,因为我不了解它的格式。这是一个字符串,但是当我打印出来时,它看起来像这样:

_M~0A0 tQ,\% e f/H #Y p f# Kus } F ra G +$x %V }[ Wo 1'̶A c * &=Z^ o' T۽ SX-TƑV&H| $~ u 7 cR f = 9 fs q ڄا 9v ] TƷ & gr] n IRל 檯 + I w } 9 o w M m IJ m = Soՙ}S>j , ƙ ' tad =i WY FeC֓z 2 g ;EXX S ʁ*, w _| & y H = ( Ɗ3@ h Ѻ Ɋ ZzR' ( y c ڋ. v !u S I# $9R TƯ0py z 8 # A q ە ijc bp= ۹ c SqH

从 base64 转换似乎没有帮助。我也试过:

array = np.fromstring(data, dtype=np.uint8)

它确实转换为数组,但不是基于我尝试解码的帧的 640x368x3 尺寸有意义的大小。

  • 使用百老汇等解码器.js转换 h264 流

这些似乎专注于流式传输到网站,而我试图将它们重新用于我的目标并没有成功。

澄清我不想做什么:

我发现了许多有关将 h264 视频流式传输到网站的相关问题。这是一个已解决的问题,但没有一个解决方案可以帮助我提取单个帧并将它们放入与 OpenCV 兼容的格式中。

此外,我需要连续实时使用提取的帧。因此,将每一帧另存为.jpg没有帮助。

系统规格

莓派 3 运行树莓派杰西

其他详细信息

我试图概括我在问题中遇到的问题。如果知道有用的话,Process1 正在使用 node-bebop 包从 Parrot Bebop 2.0 中拉下 h264 流(使用 drone.getVideoStream(((。我尝试使用通过node-bebop(getMjpegStream(((提供的其他视频流。这奏效了,但几乎不是实时的;我得到的数据流非常间歇性。我已经在 node-bebop 存储库中将该特定问题作为问题输入。

感谢您的阅读;我真的很感谢任何人能给予的任何帮助!

通过设置以下环境变量,我能够解决在 Python 中使用 OpenCV(使用 FFMPEG 构建(打开 Parrot Anafi 流的问题:

export OPENCV_FFMPEG_CAPTURE_OPTIONS="rtsp_transport;udp"

FFMPEG 默认为 TCP 传输,但来自无人机的馈送是 UDP,因此这会为 FFMPEG 设置正确的模式。

然后使用:

cv2.VideoCapture(<stream URI>, cv2.CAP_FFMPEG)
ret, frame = cap.read()
while ret:
    cv2.imshow('frame', frame)
    # do other processing on frame...
    ret, frame = cap.read()
    if (cv2.waitKey(1) & 0xFF == ord('q')):
        break
cap.release()
cv2.destroyAllWindows()

照常。

这也适用于鹦鹉Bebop,但我没有一个可以测试它。

网上有一些建议,可以使用标准将h264流输送到opencv程序中:

some-h264-stream | ./opencv-program

其中 OpenCV-Program 包含以下内容:

VideoCapture cap("/dev/stdin");

相关内容

  • 没有找到相关文章