OpenCV程序如何检测特定目标移出画面 实现离屏超时音频提醒
原代码核心问题
- 缺失依赖导入:未引入计时所需的
time模块、音频播放所需的pygame模块,代码无法直接运行 - 死循环阻塞流程:检测到无人脸时嵌套了
while len(faces) == 0内层循环,循环内不会重新读取摄像头帧、不会更新人脸检测结果,直接导致程序卡死 - 计时逻辑错误:每次检测到无人脸就重置
start_time,无法累计连续离开时长;超时后重复初始化音频模块、重复触发播放,会出现音频叠放问题 - 缺失返回检测逻辑:没有实现人脸回到画面后立即停止音频的分支
修正后可运行代码
import cv2 as cv import sys import time import pygame # 初始化人脸检测器、摄像头 cascPath = sys.argv[1] faceCascade = cv.CascadeClassifier(cascPath) video_capture = cv.VideoCapture(0) # 提前初始化音频模块、加载提醒音,避免循环内重复创建资源 pygame.mixer.init() alert_sound = pygame.mixer.Sound("Recording.mp3") # 流程状态变量 away_start_time = None # 连续离开的起始时间,None表示当前画面有人 is_alert_playing = False # 提醒音频播放状态标记 AWAY_TIME_THRESHOLD = 120 # 离开触发提醒的时长阈值,单位秒 while True: # 逐帧读取摄像头画面 ret, frame = video_capture.read() if not ret: break # 人脸检测 gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale( gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30), flags=cv.CASCADE_SCALE_IMAGE ) # 绘制人脸矩形框 for (x, y, w, h) in faces: cv.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2) # 显示画面 cv.imshow('Video', frame) # 离开/返回状态判断 if len(faces) > 0: # 检测到人脸,立刻停止提醒、重置计时 if is_alert_playing: alert_sound.stop() is_alert_playing = False away_start_time = None else: # 未检测到人脸 current_time = time.time() # 刚从有人状态切到无人,记录离开起始时间 if away_start_time is None: away_start_time = current_time away_duration = current_time - away_start_time print(f"已离开时长: {away_duration:.1f}秒") # 离开时长超阈值且未在播提醒,触发音频循环播放 if away_duration >= AWAY_TIME_THRESHOLD and not is_alert_playing: alert_sound.play(loops=-1) # loops=-1为持续循环播放,需手动停止;如果要固定播放次数可改对应数值 is_alert_playing = True # 按q键退出程序 if cv.waitKey(1) & 0xFF == ord('q'): break # 退出前释放所有资源 if is_alert_playing: alert_sound.stop() pygame.mixer.quit() video_capture.release() cv.destroyAllWindows()
核心逻辑说明
- 所有检测、判断逻辑都放在主视频采集循环内,每轮循环都会读取新帧、更新人脸检测结果,不会出现流程卡死问题
- 用两个状态变量分离计时、播放逻辑,避免重复触发音频、重复计时的问题
- 检测到人脸回归的第一时间就停止音频播放、清空离开计时,满足返回即停的需求
- 音频相关初始化、资源加载全部放在主循环外完成,减少不必要的性能开销
内容的提问来源于stack exchange,提问作者Abinesh Prakash
相关产品推荐
相关产品推荐

