如何解决Opencv读取多路rtsp视频流cpu占用率过高的问题?

系统:win10
使用cv2.videocapture()方法获取rtsp视频流,随着视频路数增加,cpu占用率会逐步提高直至100%。
请问win下有基于python的GPU硬编码rtsp视频流的方案吗?

CPU占用率逐步到100%和电脑性能也有关系但关系不大
套用Python更改优先级参考链接:
https://blog.csdn.net/jningwei/article/details/120299978

#或者限制Python程序所能使用的最大内存,我们可以使用Python自带的resource模块:

import resource
soft, hard = resource.getrlimit(resource.RLIMIT_AS)

其中的 resource.RLIMIT_AS实际上就是数字5,表示内存资源。而 soft限制是一个可以调节的内存使用上限, hard是一个一旦设定就很难动态调整的内存使用量上限。
一开始 soft和 hard的值是一样的。并且它们的单位不是比特。而是比比特还小的单位。我的电脑是8GB内存,而 8*1024^6 正好约等于这里的hard和soft的值。
接下来,设置当前运行的这个Python程序能够使用的最大内存:

resource.setrlimit(resource.RLIMIT_AS, (最大上限, hard))

最大上限是整数!
当前Python程序使用的内存超过500MB以后,程序就会抛出 MemoryError。

直接使用opencv的cv2.VideoCapture直接读取rtsp视频流,但是这样做的缺点是延迟严重、出现掉帧、花屏现象等,原因在于opencv自己有一个缓存,每次会顺序从自己的缓存中读取,而不是直接读取最新帧。

没有现成程序,网上找了一个抓:
每次都读取最新帧

import cv2
import threading
import sys


class RTSCapture(cv2.VideoCapture):
    _cur_frame = None
    _reading = False
    schemes = ["rtsp://","rtmp://"]
    @staticmethod
    def create(url, *schemes):
        rtscap = RTSCapture(url)
        rtscap.frame_receiver = threading.Thread(target=rtscap.recv_frame, daemon=True)
        rtscap.schemes.extend(schemes)
        if isinstance(url, str) and url.startswith(tuple(rtscap.schemes)):
            rtscap._reading = True
        elif isinstance(url, int):
            pass
        return rtscap

    def isStarted(self):
        ok = self.isOpened()
        if ok and self._reading:
            ok = self.frame_receiver.is_alive()
        return ok

    def recv_frame(self):
        while self._reading and self.isOpened():
            ok, frame = self.read()
            if not ok: break
            self._cur_frame = frame
        self._reading = False

    def read2(self):
        frame = self._cur_frame
        self._cur_frame = None
        return frame is not None, frame

    def start_read(self):
        self.frame_receiver.start()
        self.read_latest_frame = self.read2 if self._reading else self.read

    def stop_read(self):
        self._reading = False
        if self.frame_receiver.is_alive(): self.frame_receiver.join()


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("usage:")
        print("need rtsp://xxx")
        sys.exit()

    rtscap = RTSCapture.create(sys.argv[1])
    rtscap.start_read()

    while rtscap.isStarted():
        ok, frame = rtscap.read_latest_frame()
        if cv2.waitKey(100) & 0xFF == ord('q'):
            break
        if not ok:
            continue


        # inhere
        cv2.imshow("cam", frame)


    rtscap.stop_read()
    rtscap.release()
    cv2.destroyAllWindows()



降低CPU占用率可能的方案:

  1. 使用现成的基于opencv的多线程框架来优化多路视频调用方式,例如

https://abhitronix.github.io/vidgear/latest/

https://abhitronix.github.io/vidgear/latest/bonus/TQM/#threaded-queue-mode
2.使用Redis获取rstp视频流,然后opencv从redis中读取视频帧来减少cpu使用
3.从代码层次来避免冗余的计算开销
可能的建议:

  1. 保证每一路视频都获取最新的视频帧而不是重复获取旧的视频帧
  2. 做必要的检查,例如
    cap = cv2.VideoCapture("rtsp://test:Test12345@127.0.0.1")
    assert cap.isOpened()
    # or
    while True:
         ret, frame = cap.read()
         if not ret:
             break
    
    3 在读取视频的过程中加sleep降低读取或处理的频率

希望对你有帮助

可以使用nvidia的deepstream工具,读取多路视频流。再进行后处理

使用子码流

第一种静态视频
本地打开这么多视频流干嘛。
要是服务器,视频和代码分开放,算是分流。
第二种实时监控(摄像头实时视频采集)
这个没办法,编程电脑太垃圾。需要升级电脑拉。比如弄个高级cpu,或视频采集卡之类的设备。程序调用他们就可。编程电脑也要顶级才可以噢。

https://blog.csdn.net/submarineas/article/details/110083906
CSDN内可以搜索相关文章去对照参考下,例如这篇文章