繁体   English   中英

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

[英]Extracting each individual frame from an H264 stream for real-time analysis with OpenCV

问题大纲

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

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

  • 通过命名的 fifo 管道将流直接从 Process1 发送到 Process2

我成功地将来自 Process1 的流引导到管道中。 但是,在 Process2(它是 Python)中,我无法 (a) 从流中提取单个帧,以及 (b) 将从 h264 中提取的任何数据转换为 OpenCV 格式(例如 JPEG、numpy 数组)。

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

  • 将流从 Process1 传输到 FFMPEG,使用 FFMPEG 将流格式从 h264 更改为 MJPEG,然后将输出通过管道传输到 Process2

我尝试使用以下命令:

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

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

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

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

_M~0A0 tQ,\\% e f/ H #Y p f# Kus } F ʳa G +$ x %V }[ Wo 1'̶A c * &=Z^ o' Ͽ SX-涶V&H| $ ~ < E > u 7 cR f = 9 fs q ڄ觇 9v ] Ӷ & 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 Ԯ0py z 8 # A q ͕ ijc bp= ۹ c SqH

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

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

它确实转换为一个数组,但不是基于我试图解码的帧的 640x368x3 维度的一个有意义的大小。

  • 使用 Broadway.js 等解码器转换 h264 流

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

澄清我不想做的事情:

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

此外,我需要持续实时地使用提取的帧。 所以将每一帧保存为 .jpg 是没有帮助的。

系统规格

树莓派 3 运行 Raspian Jessie

附加细节

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

感谢阅读; 我非常感谢任何人可以提供的任何帮助!

网上有一些使用标准将 h264 流传输到 opencv 程序的建议:

some-h264-stream | ./opencv-program

其中 opencv-program 包含以下内容:

VideoCapture cap("/dev/stdin");

通过设置以下环境变量,我能够解决在 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()

像往常一样。

这也应该适用于 Parrot Bebop,但我没有测试它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM