基于OpenCV与DeepFace的人脸认证程序帧捕获警告问题排查
解决OpenCV人脸认证程序的MSMF帧抓取警告与线程终止问题
问题原因
认证成功后主线程立即释放摄像头并销毁窗口,但子线程仍在循环执行读取帧或显示窗口的操作,此时访问已释放的摄像头资源就会触发MSMF can't grab frame警告;同时子线程未被正确终止,导致程序无法完全退出。
修复后的完整代码
import cv2 import time import threading import sys from deepface import DeepFace class AuthHandler: @staticmethod def authenticate_user(users): video = cv2.VideoCapture(0) start_time = time.time() capture = False frame = None flag = False def video_thread(): nonlocal capture, frame while not flag: # 检查摄像头是否仍处于打开状态 if not video.isOpened(): break capture, frame = video.read() if not capture: continue def video_show(): while not flag: # 检查窗口是否还存在,避免窗口销毁后继续操作 if cv2.getWindowProperty("the video", cv2.WND_PROP_VISIBLE) < 1: break if frame is not None: cv2.imshow("the video", frame) # 处理窗口关闭事件,支持按q提前退出 if cv2.waitKey(30) & 0xFF == ord('q'): nonlocal flag flag = True capture_thread1 = threading.Thread(target=video_thread) capture_thread1.start() capture_thread2 = threading.Thread(target=video_show) capture_thread2.start() while time.time() - start_time < 20 and not flag: if capture: for user in users: user_id, user_name, user_type, image_path = user registered_image = cv2.imread(image_path) result = DeepFace.verify(frame, registered_image, model_name='VGG-Face', enforce_detection=False) if result['verified']: print(f"Authenticated as {user_name}") flag = True break # 强制触发子线程退出循环 flag = True # 等待子线程完全执行完毕 capture_thread1.join() capture_thread2.join() # 最后释放摄像头资源并销毁窗口 video.release() cv2.destroyAllWindows() if flag: return user_type print("Failed to authenticate ") sys.exit()
关键修改说明
- 同步线程终止:主线程结束认证循环后,先设置
flag=True触发子线程退出循环,再调用join()等待子线程完全结束,避免子线程操作已释放的资源。 - 子线程状态校验:
- 帧读取线程中增加摄像头打开状态检查,防止读取已释放的设备。
- 窗口显示线程中检查窗口可见性,同时支持按
q键手动终止认证流程。
- 优化窗口事件处理:调整
cv2.waitKey()间隔为30ms,平衡视频流畅度与线程响应速度,避免线程阻塞。
内容的提问来源于stack exchange,提问作者ZR07
相关产品推荐
相关产品推荐

