opencv处理视频速度跟不上视频送过来的速度,会导致资源积压!如何设置一个缓冲区,在一定时间里只取最新的资源,剩下资源的清空?

在使用opencv处理视频的过程中,通常我们会读取视频帧,读取出来的视频帧就相当于一幅图像,我们只要读取到了图像就可以对图像进行各种各样的操作。

例如,行人检测,汽车检测这些算法,目前非常火的目标识别算法就是yolo3,无论是在速度上还是精度上,yolo3都要比他的前辈,RCNN,FASTRCNN,YOLOv1要好很多。

但是就算是这样的背景下,我们在实际运用yolo的过程中,也是会遇到这样那样的问题,例如尽管网上对于yolo的速度大加赞赏,但是我在使用过程中,用cpu进行一次80类别数据集的检测却要耗费0.6秒,普通的视频fps大约25-30,对于每帧0.6秒的处理速度来说是远远不够的,那么性能好的gpu呢,在使用gpu的情况下,一次检测也需要将近0.08秒,接近0.1秒,在将算法应用到视频中时,会发现明显的卡顿,但是卡顿都是可以接受的,令人无法接受的是,opencv自带的帧缓冲区,这个就是cap函数读取视频时存放帧的地方,在实测过程中发现,cap函数无法获取最新帧,而是按照cap缓冲区中顺序一帧一帧的读取,这导致了我算法的延时,会导致延时越来越严重,我们期望cap能够跳过算法的处理时间,直接读取当前帧而抛掉算法运行过程中的帧,但是事实显示,opencv并不是这样做的,在和同学的讨论中,一位同学告诉我,cap能够读取当前帧,但是我在实验过程中发现,事实并不是这样,在研究中发现,opencv的确会在一定时间清空帧缓冲区,但这个清空的时机并不是我们能够控制的,也就是说我没有发现一个api可以让我们手动清空帧缓冲区。

方法一:编写我们自己的帧缓冲区就很重要。

大致思路就是,创建一个自定义的帧缓冲区,开启一个线程使用cap函数读取视频帧,将读取到的视频帧存入我们自定义的缓冲区,这个缓冲区可以设计成固定大小,每次新增新的帧进入缓冲区,将挤掉旧的帧。代码可以参考:

class Stack:
 
    def __init__(self, stack_size):
        self.items = []
        self.stack_size = stack_size
 
    def is_empty(self):
        return len(self.items) == 0
 
    def pop(self):
        return self.items.pop()
 
    def peek(self):
        if not self.isEmpty():
            return self.items[len(self.items) - 1]
 
    def size(self):
        return len(self.items)
 
    def push(self, item):
        if self.size() >= self.stack_size:
            for i in range(self.size() - self.stack_size + 1):
                self.items.remove(self.items[0])
        self.items.append(item)
另外,开启一个线程,这里用主线程也可以,读取视频缓冲区中的帧并进行算法,然后显示。

def capture_thread(video_path, frame_buffer, lock):
    print("capture_thread start")
    vid = cv2.VideoCapture(video_path)
    if not vid.isOpened():
        raise IOError("Couldn't open webcam or video")
    while True:
        return_value, frame = vid.read()
        if return_value is not True:
            break
        lock.acquire()
        frame_buffer.push(frame)
        lock.release()
        cv2.waitKey(25)
def play_thread(frame_buffer, lock):
    print("detect_thread start")
    print("detect_thread frame_buffer size is", frame_buffer.size())
 
    while True:
        if frame_buffer.size() > 0:
            lock.acquire()
            frame = frame_buffer.pop()
            lock.release()
            # TODO 算法
            cv2.imshow("result", frame)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
主函数可以参考这里:

from thread import capture_thread, play_thread
from stack import Stack
import threading
 
 
path = ''
rtsp_url = ''
frame_buffer = Stack(3)
lock = threading.RLock()
t1 = threading.Thread(target=capture_thread, args=(path, frame_buffer, lock))
t1.start()
t2 = threading.Thread(target=play_thread, args=(frame_buffer, lock))
t2.start()
这样,我们就可以控制自己的帧缓冲区,并且每次处理耗时算法以后,能够获取到最新的一帧进行处理,虽然画面可以能会掉帧的样子,但是不会再有延时的情况。

后来又在github上,看到一个完整代码,网址如下:https://github.com/cxstdio/pycv4rtsp

方法二:采用网络摄像头的辅码或者调低摄像的分辨率和图像贞率

参考资料: https://www.jianshu.com/p/2b79012c0228 验证摄像头分辨率的方法

使用 RTSCapture 类可以防止帧处理速度小于接收速度而导致花屏或者断流(崩溃)opencv-python RTSP相关推荐

  1. OTT TV影音系统,不丢帧、不卡顿、不花屏

    800li IPTV互联网电视系统目前已由苏州八百里网络的多家合作伙伴在海外正式运营,是最适合海外华人圈使用的电视盒影音聚合系统:同时也适合酒店.宾馆.小区.学校等局域网中开建自己的影音系统.支持电视 ...

  2. OTT TV影音系统如何做到不丢帧、不卡顿、不花屏

    随着互联网时代的到来,我们的生活正呈现出日新月异的变化,伴随着各种智能终端的出现,媒体信息的共享与无缝传递成为可能,传统的家庭客厅已不再是电视机一霸天下的局面,各种数字设备与电视机一起共同构成现代家庭 ...

  3. 视频帧数据用硬件编码输出,仅仅使用FFMPEG将硬件编码出的数据推流RTSP数据后严重花屏且画面卡住不动

    由于使用的是其他硬件编码器出来的数据,所以不再是使用av_read_frame来获取AVPacket包了,所以在输出编码数据的回调接口里写伪代码如下: //相当于初始化AVPacket包 AVPack ...

  4. Object类 任何类都是object类的子类 用object对象接收数组 object类的向上向下转型...

    任何类都是object类的子类 用object对象接收数组 object类的向上向下转型 转载于:https://www.cnblogs.com/qingyundian/p/7744351.html

  5. 【clickhouse】clickchouse的分区合并速度小于插入速度会怎么样

    文章目录 1.概述 1.概述 问题: clickchouse的分区合并速度小于插入速度会咋样啊? 我们10秒插入一下 我们插入这么快的话会影响到clickhouse的合并吗? 怎么缓解呢? 参考:[c ...

  6. 记一次因为丢帧导致视频播放花屏问题的排查

    ​问题背景: 最近开发了一个HLS服务,主要是满足用户在浏览器上播放直播和点播视频的需求,特别像小程序或者微信这种,只有有链接就能查看视频,也不用装APP,还是方便不少.在开发过程中排查了一次花屏问题 ...

  7. FFmpeg花屏解决(修改源码,丢弃不完整帧)

    linux下模拟丢帧的命令,因为帧之间的参考关系,实测如果是1%几乎没有完好的帧. sudo tc qdisc add dev enp0s31f6 root netem loss 0.1% 删除上面的 ...

  8. 达芬奇在AMD处理器的联想电脑上编辑视频时花屏、卡帧、闪烁的解决方法

    故障描述:达芬奇在使用AMD 4000系列移动端处理器的联想笔记本电脑上处理视频时出现了时间线花屏.修改时间线上的素材后播放时画面卡在两帧以内反复闪烁.画面闪烁黑帧的问题,重装软件.更换版本均无法有效 ...

  9. Glide加载gif动画只播放一次的方法 Glide加载gif动画先显示最后一帧再开始播放动画导致闪屏的解决方案

    场景: Android App利用ViewPager制作引导页,然后利用Glide加载gif动画. 问题: 1.Glide加载gif动画如何只播放一次? 2.Glide加载gif动画,在viewPag ...

最新文章

  1. 为什么SpringBoot的 jar 可以直接运行?
  2. python输入正整数n、求n以内能被17整除的最大正整数_求100之内自然数中最大的能被17整除的数...
  3. 用php获取header头信息
  4. spock_在扩展Spock时输出给定值
  5. 英语阅读测试,很神奇吧~
  6. sql怎么读_mysql由于快照读,造成数据混乱,该如何解决
  7. 《Python学习笔记》——南溪的python编程笔记
  8. 1038. 统计同成绩学生(20)-PAT乙级真题
  9. 项目管理应该注意问题
  10. React 服务端渲染完美的解决方案
  11. mycat err:java.sql.SQLNonTransientException: find no Route:select日志报错
  12. linux系统fsck.ext4,Ext4文件系统fsck后损坏修复过程一例
  13. 商品详情页php代码,微信小程序商品详情页规格属性选择示例代码
  14. 联想拯救者r7000p安装Linux双系统(二)
  15. 网上关于'好人卡'的定义
  16. ORACLE updata是提示违反唯一约束条件
  17. 序列(SEQUENCE)、同义词(SYNONYM)
  18. PBR来龙去脉九:继续Unreal的IBL部分
  19. Inno Setup 制作exe安装包
  20. 读书 | 设计模式之禅 - 策略模式

热门文章

  1. 复旦大学计算机学院教师简介,复旦大学计算机科学技术学院导师教师师资介绍简介-危辉...
  2. 使用EditPlus技巧,提高工作效率(自动完成文件、语法文件下载)
  3. Windows Server 2003的32位企业版支持4G以上内存
  4. faile什么意思_faile to是什么意思
  5. 怎样提高工作积极性与工作效率
  6. type-c英文怎么读音发音,type-c怎么读英语发音
  7. html 键盘按键与按钮功能关联
  8. 【LSR标签平滑理解】
  9. 微信支付生成签名和验签SDK源码分析
  10. item_sku - 获取sku详细信息