如何为实时人脸情绪识别绘制实时预测情绪频率图
实时人脸情绪频率动态图表实现
核心逻辑
- 用线程分离视频流处理和图表渲染,避免互相阻塞
- 维护全局情绪计数字典,每次模型输出情绪后更新对应计数
- 通过
matplotlib.animation.FuncAnimation实时刷新柱状图
完整代码
%matplotlib notebook from keras.models import load_model from keras_preprocessing.image import img_to_array import cv2 import numpy as np from matplotlib import pyplot as plt from matplotlib.animation import FuncAnimation from threading import Thread import time # 加载模型和分类器 face_classifier = cv2.CascadeClassifier(r'haarcascade_frontalface_default.xml') classifier = load_model(r'FinalModel64.h5') emotion_labels = ['Angry','Fear','Happy','Neutral', 'Sad', 'Surprise'] # 初始化情绪计数 emotion_counts = {emotion: 0 for emotion in emotion_labels} # 线程控制标志 running = True def video_processing_thread(): global emotion_counts cap = cv2.VideoCapture(0) while running: _, frame = cap.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_classifier.detectMultiScale(gray) current_emotion = None for (x,y,w,h) in faces: cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,255),2) roi_color = frame[y:y+h,x:x+w] roi_color = cv2.resize(roi_color,(48,48),interpolation=cv2.INTER_AREA) if np.sum([roi_color]) != 0: roi = roi_color.astype('float')/255.0 roi = img_to_array(roi) roi = np.expand_dims(roi,axis=0) prediction = classifier.predict(roi)[0] current_emotion = emotion_labels[prediction.argmax()] emotion_counts[current_emotion] += 1 label_position = (x,y) cv2.putText(frame, current_emotion, label_position, cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2) else: cv2.putText(frame,'No Faces',(30,80),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2) cv2.imshow('Emotion Detector',frame) if cv2.waitKey(1) & 0xFF == ord('q'): global running running = False break cap.release() cv2.destroyAllWindows() # 初始化图表 fig, ax = plt.subplots() bars = ax.bar(emotion_labels, [emotion_counts[emotion] for emotion in emotion_labels]) ax.set_ylabel('出现次数') ax.set_title('实时情绪频率统计') def update_chart(frame): # 更新每个柱子的高度 for bar, emotion in zip(bars, emotion_labels): bar.set_height(emotion_counts[emotion]) # 自动调整y轴范围,避免柱子超出图表 ax.set_ylim(0, max(emotion_counts.values()) + 1 if max(emotion_counts.values()) > 0 else 1) return bars # 启动视频处理线程 thread = Thread(target=video_processing_thread) thread.start() # 启动图表动画,每200ms刷新一次 ani = FuncAnimation(fig, update_chart, interval=200) plt.show() # 等待线程结束 thread.join()
关键部分说明
- 线程分离:视频捕获和情绪预测在单独线程中运行,避免阻塞matplotlib的渲染循环
- 全局计数:
emotion_counts字典实时记录各类情绪的出现次数,单写操作无需额外锁保证线程安全 - 图表更新:
update_chart函数每次被动画触发时,更新柱状图高度并自动调整y轴范围,确保显示正常 - 退出逻辑:通过
running标志控制线程结束,保证程序退出时资源正常释放
内容的提问来源于stack exchange,提问作者Arash
相关产品推荐
相关产品推荐

