如何在无限循环的elif条件满足时实现轻量非阻塞计时器,不降低视频FPS
问题原因排查
- 你的计时逻辑存在两处致命错误,和FPS下降没有直接关系但会导致功能完全失效:
- 你将
old_time = time.time()放在了while循环第一行,每次循环都会重置计时起点,末尾的10秒超时判断永远无法触发 - 变量名书写错误:你定义的变量是
old_time,末尾判断用的是oldtime,少了下划线,运行时会直接抛出变量未定义的异常
- 你将
- 关于FPS下降的疑问:
old_time的变量赋值是Python最基础的操作,单次执行开销仅几十纳秒,哪怕每秒执行上千次也不会对视频帧率造成任何影响,你遇到的FPS下降和赋值操作无关,大概率是逻辑错误后你额外添加的阻塞逻辑、或者视频/姿态检测环节的其他代码导致的。
最优解决方案
方案1:主线程非阻塞计时(最推荐,无额外线程开销)
只需要把计时变量初始化移到循环外,不要每次循环重置即可,代码示例:
import time import cv2 # 计时器仅在循环外初始化一次 last_trigger_time = time.time() # 视频读取逻辑放在循环外 cap = cv2.VideoCapture(0) while True: # 优先处理核心视频流、姿态检测逻辑,保证帧率 ret, frame = cap.read() if not ret: break # 这里写mediapipe姿态检测代码 # 条件判断和计时逻辑 if condition1: last_trigger_time = time.time() # 执行condition1对应逻辑 elif condition2: last_trigger_time = time.time() # 执行condition2对应逻辑 elif condition3: last_trigger_time = time.time() # 执行condition3对应逻辑 elif time.time() - last_trigger_time > 10: print("You have waited too long") # 若触发超时后需要重置计时,此处可加 last_trigger_time = time.time() # 画面渲染必须加waitKey,否则会出现卡顿掉帧 cv2.imshow("frame", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break
如果你的循环帧率非常稳定,还可以用帧计数替代时间调用,进一步降低开销:比如固定帧率为30的情况下,10秒对应300帧,每次满足条件1/2/3时将计数器归零,计数器到300就触发超时。
方案2:独立线程定时器(完全不占用主线程资源)
threading.Timer不会阻塞主线程运行,正确实现方式如下:
import threading import cv2 def timeout_callback(): print("You have waited too long") # 初始化10秒定时器 timer = threading.Timer(10, timeout_callback) timer.start() cap = cv2.VideoCapture(0) while True: # 核心视频、姿态检测逻辑 ret, frame = cap.read() if not ret: break if condition1: # 重置定时器:先取消旧的,再启动新的 timer.cancel() timer = threading.Timer(10, timeout_callback) timer.start() # 执行condition1对应逻辑 elif condition2: timer.cancel() timer = threading.Timer(10, timeout_callback) timer.start() # 执行condition2对应逻辑 elif condition3: timer.cancel() timer = threading.Timer(10, timeout_callback) timer.start() # 执行condition3对应逻辑 cv2.imshow("frame", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break # 退出时销毁定时器 timer.cancel()
内容的提问来源于stack exchange,提问作者Barış Aktaş
相关产品推荐
相关产品推荐

