加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

【Python】改善 VideoCapture 的影像延迟

发布时间:2020-12-20 10:46:28 所属栏目:Python 来源:网络整理
导读:许多的范例程序大多仅介绍该如何用 VideoCapture 撷取摄影机的画面,却没有充分说明其隐含的问题。 以下示范一个最基本的影像撷取程序。 # -*- coding: utf-8 -*-import cv2# ip camera 的撷取路径URL = "rtsp://admin:[email?protected]/video.h264"# 建立

许多的范例程序大多仅介绍该如何用 VideoCapture 撷取摄影机的画面,却没有充分说明其隐含的问题。
以下示范一个最基本的影像撷取程序。


# -*- coding: utf-8 -*-
import cv2

# ip camera 的撷取路径
URL = "rtsp://admin:[email?protected]/video.h264"

# 建立 VideoCapture 对象
ipcam = cv2.VideoCapture(URL)

# 使用无穷循环撷取影像,直到按下Esc键结束
while True:
    # 使用 read 方法取回影像
    stat,I = ipcam.read()

    # 加上一些影像处理...

    # imshow 和 waitkey 需搭配使用才能展示影像
    cv2.imshow(‘Image‘,I)
    if cv2.waitKey(1) == 27:
        ipcam.release()
        cv2.destroyAllWindows()
        break

一般而言,都是这样写的。
先取回一帧影像,然后进行处理,膨胀闭合之类的,再使用CNN来辨识一下...等等。

全部都处理完了,再继续截取下一帧影像。

这种范例程序占了90%的google版面。
当然了,那个趴数是夏恩胡诌的,这边只是想表示 "很多" 的意思。

这种写法有什么问题呢?
其实只要稍微改动一下上述的程序,就可以看出来。
我们把 cv2.waitkey(1) 改成?cv2.waitkey(1000),意思是程序到这边等待 1 秒。

在实际上的情况,我们不会直接使用waitkey(1000),
而是每一次循环内影像处理的流程费时 1?秒,也许会快一些或是慢一些。

然后我们就会发现一件事:怎么影像不动了?或是影像怎么会延迟?

尤其是影像上面如果有日期时间的话,就更明显的看到秒数连动都不会动。
明明已经过了10秒钟,取回10张影像,但是影像显示的时间却没有任何改变?

原因是因为VideoCapture会把从摄影机取回来的影像先放到缓冲区,等待使用者将缓冲区内的影像取走,再填充新的影像进去。

如果摄影机的拍摄频率是一秒10帧影像(10fps),但我们一秒只读取一张,
那就表示我们会一直读取到同一时刻的影像,直到把缓冲区清空为止,
又缓冲区有多少帧影像,则是取决于摄影机设定的拍摄频率。

也因此在不明所以的人眼中看起来的问题就是:
为什么怎么我的影像串流会出现延迟的问题?

而这个问题最根本的原因是:

从缓冲区取出影像的速度,低于填入影像的速度!

要解决这个问题的方法有两个:

一、降低摄影机的拍摄速度

摄影机都可以手动调整撷取影像的频率,既然程序无法消耗这么多帧影像,那就把摄影机的频率降低。


那如果是即时影像辨识,非要这么快的速度不可,
例如在门口的人脸辨识系统,速度太慢的可能会被主管电到飞上天。

这时候就可以考虑使用多线程的技巧。

二、多线程

将撷取影像的循环单独放进一个线程,使其不断地清空缓冲区,保留最新的影像。
另外在主程序的部分就是有需要的时候再将最新的影像取回来。

所以把上面的那支程序改成以下这样:

# -*- coding: utf-8 -*-
import cv2
import time
import threading

# 接收摄影机串流影像,采用多线程的方式,降低缓冲区栈图帧的问题。
class ipcamCapture:
    def __init__(self,URL):
        self.Frame = []
        self.status = False
        self.isstop = False
		
	# 摄影机连接。
        self.capture = cv2.VideoCapture(URL)

    def start(self):
	# 把程序放进子线程,daemon=True 表示该线程会随着主线程关闭而关闭。
        print(‘ipcam started!‘)
        threading.Thread(target=self.queryframe,daemon=True,args=()).start()

    def stop(self):
	# 记得要设计停止无限循环的开关。
        self.isstop = True
        print(‘ipcam stopped!‘)
   
    def getframe(self):
	# 当有需要影像时,再回传最新的影像。
        return self.Frame
        
    def queryframe(self):
        while (not self.isstop):
            self.status,self.Frame = self.capture.read()
        
        self.capture.release()

URL = "rtsp://admin:[email?protected]/video.h264"

# 连接摄影机
ipcam = ipcamCapture(URL)

# 启动子线程
ipcam.start()

# 暂停1秒,确保影像已经填充
time.sleep(1)

# 使用无穷循环撷取影像,直到按下Esc键结束
while True:
    # 使用 getframe 取得最新的影像
    I = ipcam.getframe()
    
    cv2.imshow(‘Image‘,I)
    if cv2.waitKey(1000) == 27:
        cv2.destroyAllWindows()
        ipcam.stop()
        break

以上两个建议,是夏恩觉得比较容易解决问题的方法。
若您也遇到相同的问题,请随意参考。

原文:大专栏 ?【Python】改善 VideoCapture 的影像延迟

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读