结合face_recognition使用cv2.VideoCapture时视频窗口崩溃无响应问题
问题根因
你遇到的崩溃是典型的OpenCV GUI事件循环阻塞问题:你当前使用cnn模型做人脸检测,CPU运行时单帧处理耗时极高,导致OpenCV无法通过waitKey及时处理窗口的刷新、交互事件,系统判定窗口无响应后强制结束,对应错误码就是0xCFFFFFFF。单独运行OpenCV摄像头捕获逻辑时没有高耗时计算,所以功能正常。
解决方案
按优先级从高到低尝试:
- 优先更换人脸检测模型:将代码中的
MODEL = "cnn"改为MODEL = "hog"。HOG模型是CPU优化的轻量检测模型,普通PC上能跑到30帧以上,完全满足日常人脸匹配需求,精度损失极小。 - 补充读帧合法性判断:原代码未判断
video.read()的返回值,摄像头读取失败时后续处理空帧会触发未知异常,需要在拿到帧后先判断ret是否为True,失败就退出循环。 - 调整
waitKey等待时长:将cv2.waitKey(1)改为cv2.waitKey(10),给GUI事件循环留足够的处理时间,10ms的延迟人眼感知不到,不会影响视频流畅度。 - 更换稳定依赖版本:如果修改模型后还是崩溃,可尝试将依赖换成稳定组合:
dlib==19.24、opencv-python==4.5.5.62、face-recognition==1.3.0,避免不同版本的兼容问题。 - (可选)启用GPU加速:如果你有NVIDIA显卡,编译安装支持CUDA的dlib版本,
cnn模型就能通过GPU加速跑满帧率,不会再出现阻塞问题。
修改后可直接运行的参考代码
import face_recognition import os import cv2 video = cv2.VideoCapture(0) # 补充摄像头打开校验 if not video.isOpened(): raise IOError("无法打开摄像头") KNOWN_FACES_DIR = "known_faces" TOLERANCE = 0.6 FRAME_THICKNESS = 3 FONT_THICKNESS = 2 MODEL = "hog" # 替换为hog模型 FONT = cv2.FONT_HERSHEY_SIMPLEX print("loading known faces...") known_faces = [] known_names = [] for name in os.listdir(KNOWN_FACES_DIR): for filename in os.listdir(f"{KNOWN_FACES_DIR}/{name}"): image = face_recognition.load_image_file(f"{KNOWN_FACES_DIR}/{name}/{filename}") encoding = face_recognition.face_encodings(image)[0] known_faces.append(encoding) known_names.append(name) print("processing unknown faces...") while True: ret, frame = video.read() # 补充读帧失败判断 if not ret: print("读取摄像头帧失败,退出程序") break locations = face_recognition.face_locations(frame, model=MODEL) encodings = face_recognition.face_encodings(frame, locations) for face_encoding, face_location in zip(encodings, locations): results = face_recognition.compare_faces(known_faces, face_encoding, TOLERANCE) match = None if True in results: match = known_names[results.index(True)] print(f"match found! = {match}") top_left = (face_location[3], face_location[0]) bottom_right = (face_location[1], face_location[2]) color = [0, 255, 0] cv2.rectangle(frame, top_left, bottom_right, color, FRAME_THICKNESS) top_left = (face_location[3], face_location[2]) bottom_right = (face_location[1], face_location[2]+22) cv2.rectangle(frame, top_left, bottom_right, color, cv2.FILLED) cv2.putText(frame, match, (face_location[3]+10, face_location[2]+15), FONT, 0.5, (0, 0, 0), FONT_THICKNESS) cv2.imshow('frame', frame) # 调整waitKey时长 if cv2.waitKey(10) & 0xFF == ord('q'): break video.release() cv2.destroyAllWindows() # 部分Windows环境下需要额外加几帧waitKey保证窗口正常销毁 for _ in range(5): cv2.waitKey(1)
内容的提问来源于stack exchange,提问作者Yusuf
相关产品推荐
相关产品推荐

