Flask+OpenCV摄像头无法实时显示,仅捕获后显示静态图的问题
问题分析
你遇到的核心问题是capture()是阻塞式函数——它会暂停当前线程直到捕获完成,而你把它放在gen_frames的循环里,导致每生成一帧后就会卡住,直到capture执行完毕才会继续生成下一批帧,自然没法实现实时流。
解决方案
用后台线程执行capture,避免阻塞帧生成循环;同时设置标志位,捕获完成后切换为静态帧模式。
完整代码示例
import cv2 from flask import Flask, Response import threading import time app = Flask(__name__) # 初始化摄像头与全局状态变量 camera = cv2.VideoCapture(0) captured = False # 捕获完成标志 captured_frame = None # 存储捕获的帧数据 def capture(): """后台执行捕获逻辑,不阻塞帧流""" global captured, captured_frame # 模拟指定延迟(替换成你的实际触发逻辑) time.sleep(5) # 捕获并处理帧 success, frame = camera.read() if success: frame = cv2.flip(frame, 1) ret, buffer = cv2.imencode('.jpg', frame) captured_frame = buffer.tobytes() captured = True def gen_frames(): """生成视频流,捕获前实时,捕获后静态""" # 启动捕获线程(后台运行,不阻塞当前循环) threading.Thread(target=capture, daemon=True).start() while True: if captured: # 捕获完成后,持续返回静态帧 yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + captured_frame + b'\r\n') else: # 未捕获时,实时生成帧 success, frame = camera.read() if success: ret, buffer = cv2.imencode('.jpg', cv2.flip(frame, 1)) frame_bytes = buffer.tobytes() yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n') @app.route('/video_feed') def video_feed(): return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame') if __name__ == '__main__': try: app.run(debug=True) finally: camera.release() # 退出时释放摄像头资源
关键说明
- 线程隔离:用
threading.Thread把capture放到后台线程,gen_frames的帧生成循环不会被阻塞,保证实时流正常运行。 - 状态切换:通过
captured标志位控制帧流模式,捕获完成后自动切换为静态帧输出。 - 资源清理:添加
finally块确保退出时释放摄像头,避免资源泄漏。
内容的提问来源于stack exchange,提问作者PotatoDev
相关产品推荐
相关产品推荐

