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

Flask结合OpenCV实现Jetson Nano摄像头网页直播存快照页面卡死问题求助

问题解决方法

核心根因

你遇到的问题本质是摄像头资源竞争+Flask单线程阻塞+请求逻辑设计缺陷,具体分为4点:

  • Flask默认单线程运行,视频流请求、按钮POST请求、页面刷新请求互相阻塞,摄像头被占用后新的视频流请求无法获取资源,导致无限加载
  • 全局快照标记变量没有线程锁,多线程并发修改时状态异常,会卡住帧生成逻辑
  • 按钮用form表单提交,每次点击都会刷新页面,旧的视频流连接未正常释放,重复请求摄像头导致设备锁死
  • 多个视频流请求会同时调用camera.read()抢同一设备资源,导致读取失败率极高,前端收不到新帧就会停留在最后一张快照

具体修复步骤

1. 开启Flask多线程模式

修改启动代码,允许多请求并行处理:

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

关闭debug模式避免调试模式的重复启动问题,同时支持多客户端同时访问。

2. 新增后台帧采集线程,避免资源竞争

单独开一个线程持续读摄像头,把最新帧存在全局变量,所有视频流请求直接读缓存的帧,不再直接访问摄像头:

import threading

global latest_frame, frame_lock, Polluted, Clear, Treated, OutOfService 
latest_frame = None
frame_lock = threading.Lock()
Polluted=0
Clear=0
Treated=0
OutOfService=0

def capture_frame():
    global latest_frame, camera
    while True:
        success, frame = camera.read()
        if success:
            with frame_lock:
                latest_frame = frame.copy()
        time.sleep(0.01) # 控制采集帧率,避免占用过高资源

# 启动后台采集线程,放在app初始化之后
capture_thread = threading.Thread(target=capture_frame, daemon=True)
capture_thread.start()

3. 重写帧生成逻辑,从缓存读帧

def gen_frames():
    global latest_frame, frame_lock, Polluted,Clear,Treated,OutOfService
    while True:
        with frame_lock:
            if latest_frame is None:
                continue
            frame = latest_frame.copy()
            # 处理快照逻辑
            if Polluted:                
                snapshot(frame,"Polluted Water")
                Polluted = 0 
            if Clear:
                snapshot(frame,"Cleared Water")
                Clear = 0
            if Treated:
                snapshot(frame,"Treated Water")
                Treated = 0   
            if OutOfService:
                snapshot(frame,"Out of Service")
                OutOfService = 0
        # 编码返回
        try:
            ret, buffer = cv2.imencode('.jpg', cv2.flip(frame,1))
            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('encode error', e)
            continue

4. 修改按钮请求逻辑,避免页面刷新

要么给按钮加AJAX异步提交,不用form表单刷新页面;要么修改POST处理完之后重定向回首页,避免重复提交:

from flask import redirect

@app.route('/requests',methods=['POST','GET'])
def tasks():
    if request.method == 'POST':
        if request.form.get('Polluted') == 'Polluted':
            global Polluted
            Polluted=1
            print('in polluted')
        elif  request.form.get('Clear') == 'Clear':
            global Clear
            Clear = 1
        elif  request.form.get('Treated') == 'Treated':
            global Treated
            Treated = 1
        elif  request.form.get('OutOfService') == 'OutOfService':
            global OutOfService
            OutOfService = 1 
        return redirect('/') # 重定向避免重复提交
    return render_template('index.html')

5. 前置检查&小问题修复

  • 启动时先创建四个存储文件夹,避免cv2.imwrite写入失败阻塞逻辑:
save_base = "/home/ava/Documents/AVA/Get pictures/"
for folder in ["Polluted Water", "Cleared Water", "Treated Water", "Out of Service"]:
    os.makedirs(os.path.join(save_base, folder), exist_ok=True)
  • 修复快照颜色错误:cv2读出来的帧本身是BGR格式,不需要再做cv2.COLOR_RGB2BGR转换,直接保存即可,否则会颜色偏蓝。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 12:18:02