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

PiCamera2+Flask仅生成20帧后停止流传输的问题排查

PiCamera2仅输出20帧后停止流的问题解决

问题根源

  1. 缓冲区配置错误:你设置了buffer_count=20同时queue=False,这意味着相机只会分配20个缓冲区,且不会循环复用。当20个缓冲区都被消耗完后,相机无法生成新帧。
  2. 帧获取方式冲突:同时调用picam2.capture_buffer("lores")和picam2.capture_request(),两种操作都会占用缓冲区,加速缓冲区耗尽。
  3. 异常处理过于激进:只要捕获到一次异常就执行break终止生成器,导致流直接停止。

修复方案

  • 启用队列机制:将配置中的queue=False改为queue=True,让相机自动循环复用缓冲区。
  • 统一帧获取逻辑:使用capture_request()同时获取main和lores流的帧,避免重复占用缓冲区。
  • 优化异常处理:移除异常块中的break,仅在严重错误时退出,小错误跳过当前帧继续运行。

修改后的完整代码

#!/usr/bin/python3
from flask import Flask, render_template, Response
import cv2
from picamera2 import Picamera2, MappedArray

app = Flask(__name__)

# Initialize the face detector
face_detector = cv2.CascadeClassifier("/var/www/fullfacescanner.xml")

# Initialize and configure the camera
picam2 = Picamera2()
# 启用队列,让缓冲区循环复用
config = picam2.create_preview_configuration(main={"size": (480, 480)},
                                             lores={"size": (320, 240), "format": "YUV420"},
                                             buffer_count=20, queue=True)
picam2.configure(config)
picam2.start(show_preview=False)

(w0, h0) = picam2.stream_configuration("main")["size"]
(w1, h1) = picam2.stream_configuration("lores")["size"]
s1 = picam2.stream_configuration("lores")["stride"]

def detect_faces(buffer):
    grey = buffer[:s1 * h1].reshape((h1, s1))
    return face_detector.detectMultiScale(grey, 1.1, 3)

def generate_frames():
    while True:
        try:
            # 统一使用capture_request获取帧,同时处理两个流
            with picam2.capture_request() as request:
                # 获取lores流用于人脸检测
                lores_buffer = request.make_buffer("lores")
                detected_faces = detect_faces(lores_buffer)
                
                # 在main流上绘制人脸框
                with MappedArray(request, "main") as m:
                    for f in detected_faces:
                        (x, y, w, h) = [c * n // d for c, n, d in zip(f, (w0, h0) * 2, (w1, h1) * 2)]
                        cv2.rectangle(m.array, (x, y), (x + w, y + h), (0, 255, 0), 2)
                    
                    _, buffer = cv2.imencode('.jpg', m.array)
                    frame = buffer.tobytes()
                    yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
        except Exception as e:
            print(f"帧处理出错: {e}")
            # 仅打印错误,不终止生成器,继续尝试下一帧
            continue

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/video_feed')
def video_feed():
    return Response(generate_frames(),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, threaded=True)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:49:52