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

如何为实时人脸情绪识别绘制实时预测情绪频率图

实时人脸情绪频率动态图表实现

核心逻辑

  • 用线程分离视频流处理和图表渲染,避免互相阻塞
  • 维护全局情绪计数字典,每次模型输出情绪后更新对应计数
  • 通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 20:00:47