❤️

消除Python OpenCV显示摄像头画面的延迟

消除Python OpenCV显示摄像头画面的延迟

1. 问题描述

用 Python 通过 OpenCV显示摄像头画面时,如果对视频帧进行一些处理,常常会遇到一个问题,显示的画面比眼睛看到真实场景慢几秒甚至更多,给用户的体验不好。

画面延迟与卡顿的区别 卡顿是指视频播放时,出现一顿一顿的现象,不流畅,通常每秒播放速率少于10帧就可以感受到。 延迟是显示的画面比实际的场景慢了一段时间,不同步,但可能是流畅的。摄像头画面出现卡顿,通常也会造成延迟。

关于画面卡顿的原因及解决方案,不是本文讨论范围,但本人另1篇文章可能对此有帮助, 可参阅 用Numba加速OpenCV Python视频处理代码,提升6.5倍性能

2. 画面延迟原因

在视频处理应用程序中,由于对图像帧进行处理,通常会消耗一些时间,而OpenCV低层读帧时有缓存队列,会保存未取出的图像,用 read()方法读出的,可能是缓存里的旧帧,不是摄像头当前的帧。缓存中的帧较多时,就出现了明显的延迟。

解决方法

自定义1个无缓存读视频的VideoCapture接口类,来代替OpenCV的VideoCapture类。 开发步骤: 1) 建立1个队列queue 2) 开启1个子线程, 实时读取摄像头视频帧,队列中总是保存最后一帧,删除旧帧。 3) 显示时,从新接口类的队列中读取帧。

实现代码

import cv2

import queue

import threading

import time

# 自定义无缓存读视频类

class VideoCapture:

"""Customized VideoCapture, always read latest frame """

def __init__(self, camera_id):

# "camera_id" is a int type id or string name

self.cap = cv2.VideoCapture(camera_id)

self.q = queue.Queue(maxsize=3)

self.stop_threads = False # to gracefully close sub-thread

th = threading.Thread(target=self._reader)

th.daemon = True # 设置工作线程为后台运行

th.start()

# 实时读帧,只保存最后一帧

def _reader(self):

while not self.stop_threads:

ret, frame = self.cap.read()

if not ret:

break

if not self.q.empty():

try:

self.q.get_nowait()

except queue.Empty:

pass

self.q.put(frame)

def read(self):

return self.q.get()

def terminate(self):

self.stop_threads = True

self.cap.release()

if __name__ == "__main__":

# 测试自定义VideoCapture类

cap = VideoCapture(0)

while True:

frame = cap.read()

time.sleep(0.05) # 模拟耗时操作,单位:秒

cv2.imshow("frame", frame)

if chr(cv2.waitKey(1)&255) == 'q': # 按 q 退出

cap.terminate()

break

使用上述方式,即使对视频帧处理时间过长,出现卡顿,由于新类会将未处理的帧丢弃,总是读取摄像头当前帧,因此消除了延迟,画面还是实时的。

实际应用时,可在本例代码基础上,进行优化。

🎀 相关推荐

【原创】上海九龙柱,城市地标的神秘传说与独特魅力
纤丝缘加盟费要多少
bt365备用网址

纤丝缘加盟费要多少

📅 10-01 👀 4240
世界杯来了卖点啥?
体育365下载

世界杯来了卖点啥?

📅 08-19 👀 3693