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

基于Streamlit的表情识别系统仅显示视频静态帧,无法播放完整视频

问题分析

你的代码核心问题是仅读取并处理了视频的第一帧,没有循环遍历视频的所有帧,所以只能显示静态图像,无法播放完整视频。此外,模型和人脸检测器在每次处理帧时重复加载,会导致性能严重下降。

修复后的代码
import tempfile
import cv2
import numpy as np
from tensorflow.keras.models import model_from_json
import streamlit as st

# 提前加载模型和检测器,避免重复加载
emotion_dict = {0: "Angry", 1: "Disgusted", 2: "Fearful", 3: "Happy", 4: "Neutral", 5: "Sad", 6: "Surprised"}

# load json and create model
json_file = open('./model/model4.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
emotion_model = model_from_json(loaded_model_json)

# load weights into new model
emotion_model.load_weights("./model/model4.h5")

face_detector = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_default.xml')

FRAME_WINDOW = st.image([])
uploaded_video = st.file_uploader("Upload Video")

if uploaded_video is not None:
    tfile = tempfile.NamedTemporaryFile(delete=False) 
    tfile.write(uploaded_video.read())
    tfile.close()  # 关闭临时文件,避免占用

    camera = cv2.VideoCapture(tfile.name)
    
    # 循环读取视频的每一帧
    while camera.isOpened():
        ret, frame = camera.read()
        if not ret:
            break  # 视频读取完毕,退出循环
        
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        # 检测人脸
        num_faces = face_detector.detectMultiScale(gray_frame, scaleFactor=1.3, minNeighbors=5)

        # 处理每一张检测到的人脸
        for (x, y, w, h) in num_faces:
            cv2.rectangle(frame, (x, y-50), (x+w, y+h+10), (0, 255, 0), 4)
            roi_gray_frame = gray_frame[y:y + h, x:x + w]
            cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray_frame, (48, 48)), -1), 0)

            # 预测表情
            emotion_prediction = emotion_model.predict(cropped_img, verbose=0)  # verbose=0关闭预测日志
            maxindex = int(np.argmax(emotion_prediction))
            cv2.putText(frame, emotion_dict[maxindex], (x+5, y-20), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2, cv2.LINE_AA)
        
        # 更新图像组件,实现视频播放效果
        FRAME_WINDOW.image(frame)
    
    camera.release()  # 释放视频捕获资源
关键修改点
  • 添加帧循环:使用while camera.isOpened()循环读取视频的每一帧,直到视频结束。
  • 提前加载模型:将模型、权重和人脸检测器的加载代码移到文件上传逻辑之外,避免每次处理帧都重复加载,大幅提升性能。
  • 关闭临时文件:添加tfile.close()确保临时文件可以被正常读取。
  • 关闭预测日志:在emotion_model.predict()中添加verbose=0,避免控制台输出大量预测信息干扰Streamlit界面。
  • 释放资源:循环结束后调用camera.release()释放视频捕获对象,避免资源泄漏。
额外优化建议
  • 可以添加帧率控制,比如用time.sleep(1/30)来匹配视频原帧率,避免播放速度过快。
  • 对于长视频,考虑添加暂停/播放按钮,提升用户体验,可使用Streamlit的st.button()结合状态变量实现。
  • 如果视频处理速度较慢,可以考虑多线程处理,将帧处理逻辑放到单独线程中,避免界面卡顿。

内容的提问来源于stack exchange,提问作者isme_

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 13:21:24