You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 01:03:24