如何优化OpenCV中视频流的框架抓取



我遇到了一个问题的问题。

  1. 硬件&软件。

    • Raspberry Pi 3(1,2 GHz四核臂(带有HDMI Display
    • IP摄像机:连接LAN,RTSP,H264编解码器,1280x720分辨率,20 fps,1 GOP,2500 kb/s vbr bitrate(可以更改参数(。
    • os raspbian stretch
    • Python 3.5
    • OPENCV 4.1
    • GSTREAMER 1.0
  2. 任务。

从IP摄像机获取视频流,识别图像并显示结果视频(带有标记和消息(。

重要特征:实时处理,高清分辨率(1280x720(,高帧速率(> 20 fps(,连续操作几个小时。

  1. 我的解决方案。

常规算法:源视频流 ->解码和框架抓取 ->使用OpenCV中的帧 ->将处理的帧组装到视频流中 ->使用Raspberry Pi GPU

显示视频

OpenCV输出/显示方法 - IMSHOW - 即使在低分辨率视频中也无法正常工作。唯一允许使用Raspberry Pi GPU解码和显示视频的库是Gstreamer。

i编译了具有OMX支持的GSTREAMER模块(GSTREAMER1.0-PLUGINS-BAD,GSTREAMER1.0-OMX(并对其进行了测试:

gst-launch-1.0 rtspsrc location='rtsp://web_camera_ip' latency=400 ! queue ! rtph264depay ! h264parse ! omxh264dec ! glimagesink

它运行良好, CPU使用率约为9%

接下来,我用GSTREAMER,NEON,VFPV3支持。

我使用以下代码进行测试:

import cv2
import numpy as np
src='rtsp://web_camera_ip'
stream_in = cv2.VideoCapture(src)
pipeline_out = "appsrc ! videoconvert ! video/x-raw, framerate=20/1, format=RGBA ! glimagesink sync=false"
fourcc = cv2.VideoWriter_fourcc(*'H264')
stream_out = cv2.VideoWriter(pipeline_out, cv2.CAP_GSTREAMER, fourcc, 20.0, (1280,720))
while True:
    ret, frame = stream_out.read()
    if ret:
      stream_out.write(frame)
      cv2.waitKey(1)

它也有效,但不如GSTREAMER本身。 CPU使用率约为50%没有stream_out.write(frame(-35%。在帧速率以上15 上,有滞后和延迟。

  1. 我如何尝试解决问题。

4.1。使用GSTREAMER解码视频流:

pipline_in='rtspsrc location=rtsp://web_camera_ip latency=400 ! queue ! rtph264depay ! h264parse ! omxh264dec ! videoconvert ! appsink'
stream_in = cv2.VideoCapture(pipline_in)

它甚至加剧了情况 - CPU负载增加了几个百分比,延迟已变得更加多。

4.2。我还尝试使用pyimagesearch.com的方法优化库 - 使用Imutils库中的WebCamvideostream进行线程。

from threading import Thread
import cv2
import numpy as np
import imutils
src='rtsp://web_camera_ip'
stream_in = WebcamVideoStream(src).start()
pipeline_out = "appsrc ! videoconvert ! video/x-raw, framerate=20/1, format=RGBA ! glimagesink sync=false"
fourcc = cv2.VideoWriter_fourcc(*'H264')
stream_out = cv2.VideoWriter(pipeline_out, cv2.CAP_GSTREAMER, fourcc, 20.0, (1280,720))
while True:
    frame = stream_in.read()
    out.write(frame)
    cv2.waitKey(1)

CPU使用率已增加到70%,输出视频流的质量尚未更改。

4.3(键(以下参数无济于事:whaitkey(1-50(,videostream bitrate(1000-5000 kb/s(,videostream gop(1-20(。

  1. 问题。

据我了解,Videocaputre/VideOwritter方法的效率非常低。也许在PC上并不明显,但对于Raspberry Pi 3来说至关重要。

  • 是否有可能提高视频的性能(VideOwritter(?
  • 是否有另一种方法可以捕获从视频到OpenCV?

预先感谢您的答案!

更新1

我想我知道问题是什么,但是我不知道如何解决。

  1. 在使用视频贴和视频访问 GStreamer时,有关CPU使用的细化。VideoCapture(SRC( VideOwriter(GSTREAMER_PIPLENE_OUT(-50-60%,VideoCapture(gstreamer_pipline_in( VideOwriter(gstreamer_piplene_out_out(-40-50%。
  2. comloror格式我程序的不同部分都可以使用。H264视频流 - YUV ,OPENCV- BGR ,OMX层输出 - RGBA 。OpenCV只能与BGR颜色格式的帧一起使用。OMX层输出尝试以不同的颜色格式启动收集的视频时,显示黑屏。
  3. 使用 videoconvert 在Gstremeer Pipline中进行。在某些情况下,该方法可以自动工作(无需指定参数(,也可以强行指定颜色格式。而且我不知道它是如何在"纯"视频贴(SRC(中起作用的。

主要问题是 videoconvert 不支持gpu - 主要CPU负载是由于颜色格式转换!

我使用"纯" GSTREAMER测试了此假设,添加了视频对照:

gst-launch-1.0 rtspsrc location='web_camera_ip' latency=400 ! queue ! rtph264depay ! h264parse ! omxh264dec ! videoconvert ! video/x-raw, format=BGR ! glimagesink sync=false

黑色显示, CPU负载是25%

检查此管道:

gst-launch-1.0 rtspsrc location='web_camera_ip' latency=400 ! queue ! rtph264depay ! h264parse ! omxh264dec ! videoconvert ! video/x-raw, format=RGBA ! glimagesink sync=false

显示视频, CPU负载为5%。我还假设OMXH264DEC使用GPU将颜色格式转换为RGBA(OMXH264DEC之后,VideoConver不加载CPU(。

  1. 我不知道如何在覆盆子上使用gpu进行颜色格式转换。

在此线程6By9中,Rapberry工程师和图形编程专家,写道:" IL Video_encode组件支持OMX_COLOR_FORMAT24BITBGR888,我似乎回想起opencv的RGB的地图。

>

有什么想法吗?

您真的需要识别所捕获的每个图像吗?您可以使用第一个管道进行显示图像(您可以将视频覆盖层用于水印和其他工件(,但是例如,每六个图像进行CPU识别。在这种情况下,您将仅使用GPU进行捕获和显示无CPU加载的视频,而CPU则用于选择性图像识别

最新更新