V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
clevertension
V2EX  ›  Python

用 yolo 做实时视频检测, 摄像头接入超过 3 路, Python 内存占用就飙高,请问有没有解决办法?

  •  
  •   clevertension · 2 天前 · 1428 次点击

    问一下做过实时视频检测的大佬,我现在用 opencv 获取摄像头的数据,如果超过 3 路以后, python 的内存占用就飙上去了,基本的实现逻辑如下:

    vid = cv2.VideoCapture('rtmp_url') 
    while(True): 
        # Capture the video frame 
        # by frame 
        ret, frame = vid.read() 
        queue.put(frame)
    

    上面代码跑在 python 的 thread 里,3 路视频就 3 个 thread, 感觉这里线程之前有竞争导致一个摄像头数据取完了,另一个没有取,就堆积下来了,然后内存占用就上去了, 我感觉好像还没到 yolo 的 predict , 就是多线程获取 camera 的数据,就会造成内存占用过高

    17 条回复    2024-06-28 10:30:06 +08:00
    a33291
        1
    a33291  
       2 天前
    看过海康本身的策略,他们有 2 种方案
    1 是实时检测,也就是实时取流检测,这种的话需要独立的服务器并且同时检测路数不高
    2 是摄像头自己抓拍图片然后传递给超脑,抓拍图片在设备侧做并且不需要每一帧都分析所以极大减少了计算量,从而可以提供更大的吞吐

    基本策略应该类似,比如结合设备本身的移动侦测来做,对移动侦测的图进行分析应该也可以极大减少计算量
    此外,可以考虑分析子码流,对子码流降低码率分辨率(太低可能影响分析结果)
    capric
        2
    capric  
       2 天前   ❤️ 1
    cv2.VideoCapture 的 read 是调用 ffmpeg 库实现的,涉及到几个耗时操作,解析 rtmp 封装,H.264/H.264 视频解码(最占用 CPU),yuv 颜色空间转换成 rgb24 ,打包成 numpy 数组。如果你是在 pc 在操作,需要自己重新编译 ffmpeg ,启用 nvdec/qsv 硬件加速,这个解码负载就可以移动到 GPU 上来做,CPU 占用就很低了。
    capric
        3
    capric  
       2 天前
    clevertension
        4
    clevertension  
    OP
       2 天前
    @capric 谢谢你的建议,ffmpeg 硬解码我试过了,确实速度很快, 确实能降 cpu , 从 300%到 80%,但是内存占用呢,比如 CPU 解码帧率只有 30 左右(和 CPU 性能相关),GPU 解码帧率 7600 多, 那 opencv 一次 read ,读取的 frame 不是很多吗,全部放到内存里了吗,而且,一个 thread 读取的时候,其他 thread 没时间执行, 那是不是会造成 frame 积压,从而内存就飙高了
    murmurkerman
        5
    murmurkerman  
       2 天前
    搞一个帧队列,丢掉来不及处理的视屏帧。背压肯定会有的,选择丢帧或者提升模型处理性能。
    vicalloy
        6
    vicalloy  
       2 天前
    处理不过来就是处理不过来,除了增加算力或是减少工作量,没有别的办法。
    最简单的处理就是 yolo 的取样频率不要这么高,比如 5 frame 只取一个 frame 做识别。
    vicalloy
        7
    vicalloy  
       2 天前
    另外 python 都多线程是用不了多核处理器的。
    可以一个摄像头一个 yolo 处理进程。
    Motorola3
        8
    Motorola3  
       2 天前
    实时视频检测不是耗时操作吗?放线程里不会造成阻塞吗
    paopjian
        9
    paopjian  
       2 天前
    你这是 yolo 处理不完,queue 堆积图片数据了吧
    clevertension
        10
    clevertension  
    OP
       2 天前
    @paopjian 我试了一下,好像 yolo 处理还是快的,就是多线程去读取视频流的时候,一路视频读取的时候,另一路就读得不快,堆积了,瓶颈并不在 yolo
    clevertension
        11
    clevertension  
    OP
       2 天前
    @vicalloy 嗯,准备用 multiprocessing 试一下
    mightybruce
        12
    mightybruce  
       2 天前   ❤️ 1
    不要用多线程,python 多线程只能利用一个核,有 GIL, 另外视频不需要每一帧都要读的, 可以每隔几帧读一下,然后降低图像的分辨率, 多路摄像头也建议解耦视频读取和图像处理,通过 zeromq 实现一下高速进程通信就可以

    可以看看这个项目
    https://github.com/jeffbass/imagezmq
    vivisidea
        13
    vivisidea  
       2 天前
    就是多线程获取 camera 的数据,就会造成内存占用过高
    ==
    看下来就是 yolo 处理不过来,frame 都积压在 queue 里面导致的内存过高,这个很容易验证吧,把 queue 长度打印一下就知道了

    一个策略就是采样,不处理每个 frame ,每隔 xx 个 frame 处理一个,根据对实时性的要求来调整,或者把 yolo 剥离出来,多部署几个副本
    capric
        14
    capric  
       2 天前
    @clevertension 你这个 rtmp 是实时流吗,如果是实时流,一般只有 25/30/60 几种,不会有 7600 那么高,你统计出来 7600 fps ,应该绝大多数 frame 都是 None 。另外可以用 multiprocessing 和 queue 分发。
    clevertension
        15
    clevertension  
    OP
       2 天前
    @capric 现在 opencv 重新编译好了,cpu 占用降了,处理速度都正常,但是内存偶尔会下降一点,但是还是慢慢地会升高,最终 OOM ,我好像是这个问题 https://github.com/opencv/opencv/issues/21985
    LANB0
        16
    LANB0  
       1 天前
    @clevertension #4 层主的建议是对的,就是软解和颜色空间转换导致的 CPU 占用,这部分换硬解占用就会下来。至于 frame 积压,耗时操作都在 GPU 的话,单核处理 60 帧一点问题也没有的。
    wh1isper
        17
    wh1isper  
       1 天前
    每帧都用 CPU 做撞 GIL 了,要么换硬解,要么多进程
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2294 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 04:58 · PVG 12:58 · LAX 21:58 · JFK 00:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.