Python while循环内如何实现函数调用仅一次,间隔5秒再触发且不阻塞循环
解决方案
核心是给触发逻辑加5秒冷却校验,全程不会阻塞主线程的视频流处理逻辑:
- 新增变量记录上一次成功触发
play_save的时间 - 每次检测到笑脸时,先校验当前时间与上一次触发时间的间隔是否达到5秒,只有满足间隔要求才启动新线程执行保存和播放逻辑,同时更新上次触发时间
修改后的完整代码
import cv2 import datetime import threading import time from playsound import playsound def play_save(save_img): print("Saving Image") time_stamp = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S') file_name = f'selfie-{time_stamp}.png' cv2.imwrite(file_name, save_img) print("Playing Song") playsound("Happy_birthday.mp3") def main(): face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') smile_cascade = cv2.CascadeClassifier('haarcascade_smile.xml') cap = cv2.VideoCapture(0) # 新增:记录上一次触发的时间,初始值设为5秒前保证首次检测到笑脸可以直接触发 last_trigger_time = datetime.datetime.now() - datetime.timedelta(seconds=5) COOLDOWN_SECONDS = 5 while True: ret, img = cap.read() frame = img.copy() if not ret: break gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.3, 5) for (x, y, w, h) in faces: cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) roi_gray = gray[y:y + h, x:x + w] roi_color = img[y:y + h, x:x + w] smile = smile_cascade.detectMultiScale(roi_gray, 1.3, 25) for x1, y1, w1, h1 in smile: cv2.rectangle(img, (x1, y1), (x1 + w1, y1 + h1), (0, 0, 255), 2) # 新增:冷却校验逻辑 current_time = datetime.datetime.now() if (current_time - last_trigger_time).total_seconds() >= COOLDOWN_SECONDS: multithread = threading.Thread(target=play_save, args=(frame,)) multithread.start() # 更新触发时间 last_trigger_time = current_time cv2.imshow('Smile Birthday', img) k = cv2.waitKey(30) & 0xff if k == 27: break cap.release() cv2.destroyAllWindows() if __name__ == "__main__": main()
方案说明
- 时间差判断逻辑只有简单的数值计算,耗时可以忽略,完全不会阻塞while循环的帧读取、渲染流程,视频画面不会出现卡顿
- 冷却期内所有检测到的笑脸触发请求都会被直接跳过,不会重复启动线程,避免了歌曲重叠、重复存图的问题
- 冷却时长可以通过修改
COOLDOWN_SECONDS变量灵活调整
内容的提问来源于stack exchange,提问作者git-ruthvik
相关产品推荐
相关产品推荐

