- 人工智能
- 计算机视觉
- 深度学习
- 微调
【免费下载链接】jetson-inference
Hello AI World guide to deploying deep-learning inference networks and deep vision primitives with TensorRT and NVIDIA Jetson.
本篇指南聚焦 jetson-inference 仓库中的 Flask + REST 示例,讲解如何基于 Flask 微框架与 REST JSON 接口构建一个可在浏览器中实时观看、动态切换与调参的多模型深度学习推理控制台。读完本文,你将掌握该 WebApp 的启动方式、多 DNN 模型加载方法、前后端 REST 通信机制与每个模型可调参数的对应端点,并能结合源码理解其底层实现。
Flask 示例概览:Web 前端与 DNN 推理的桥接
Flask 是一个广受欢迎的 Python Web 微框架,负责把 HTTP/HTTPS 请求路由到用户实现的 Python 函数。在这个示例中,Flask 承担了两层职责:一是托管 WebRTC 视频流的页面呈现,二是处理来自前端用户操作的后端 REST 请求,让网页能够在运行时动态控制属性、触发推理内容。
该示例是一个可交互的 DNN "playground":多个视觉模型可以被同时加载并在 WebApp 中自由开关,每种模型的各种设置都可以通过 UI 实时调整:
界面组件使用 Bootstrap CSS 进行样式化。示例的四个核心源文件及其职责如下:
| 文件 | 职责 |
|---|---|
| python/www/flask/app.py | Flask 主程序:路由、命令行参数、启动服务器与流线程 |
| python/www/flask/stream.py | WebRTC 视频采集/传输与推理调度的后台线程 |
| python/www/flask/model.py | DNN 模型的封装:加载、推理(Process)与可视化(Visualize) |
| python/www/flask/templates/index.html | 前端页面:视频播放、模型控制面板的呈现与交互 |
此外还有两个关键辅助文件:utils.py 提供后端 REST 属性读写工具函数,templates/macros.html 提供渲染控制组件的 Jinja 宏模板。
启动示例:一条命令拉起 WebRTC 流与推理
进入示例目录、安装依赖并启动app.py,它会同时启动 Flask Web 服务器和一条独立运行的流处理线程(负责 WebRTC 的采集、传输与推理):
$ cd jetson-inference/python/www/flask $ pip3 install -r requirements.txt $ python3 app.py --detection=ssd-mobilenet-v2 --pose=resnet18-hand --action=resnet18-kinetics依赖清单 requirements.txt 中仅包含flask一项,因为其余推理与视频能力(jetson_inference、jetson_utils)来自仓库本体,需按项目 README.md 的构建流程预先安装好 Python 绑定(python/bindings)。
启动后,在浏览器中访问https://<JETSON-IP>:8050即可开始播放/发送流。要点如下:
- 默认端口 8050:可通过
--port=N命令行参数更改(源码见 app.py 第 35 行parser.add_argument("--port", default=8050, ...))。 - 默认输入输出均为 WebRTC:
--input默认值为webrtc://@:8554/input,--output默认值为webrtc://@:8554/output(app.py 第 39-40 行)。 - 改用其他视频输入:通过
--input指定,例如--input=/dev/video0使用直接连接 Jetson 的 V4L2 摄像头,也可传入 CSI 摄像头地址或视频文件,完整输入类型说明见 aux-streaming.md 中 "Input Streams" 一节。 - 接收浏览器摄像头必须启用 HTTPS/SSL:WebRTC 传输与网页默认走加密通道,详见下文"启用 HTTPS/SSL"一节,以及 webrtc-server.md 的说明。
前端页面会依据是否为 WebRTC 输入自动适配:在 index.html 中,当send_webrtc为真时,页面会在加载时调用checkMediaDevices()枚举浏览器的视频输入设备并填充到 "Webcam" 下拉框,用户点击 Send 即可将本机摄像头经 WebRTC 发送到 Jetson 侧参与推理(该功能需要 HTTPS 才能获取浏览器权限);当输入为本地设备时,页面则直接自动播放已运行的流。
同时加载多种 DNN 模型
该示例支持同时加载并运行多类 DNN 模型:图像分类、目标检测、语义分割、姿态估计、动作识别以及背景移除。启动应用时通过命令行参数选择加载哪些模型:
$ python3 app.py \ --classification=resnet18 \ --detection=ssd-mobilenet-v2 \ --segmentation=fcn-resnet18-mhp \ --pose=resnet18-body \ --action=resnet18-kinetics \ --background=u2net注意:取决于你的 Jetson 型号与后台进程负载,可能没有足够内存一次加载全部模型,也可能没有足够算力让它们全部实时运行。可以参考 pytorch-transfer-learning.md 中的 "Mounting Swap"(挂载交换分区)与 "Disabling the Desktop GUI"(关闭桌面图形界面)来释放内存。
想要查看内置模型清单,运行python3 app.py --help,或直接查看 data/networks/models.json。--help输出的参数说明由 stream.py 中的usage()汇总而来,它拼接了videoSource、videoOutput与Model.Usage()的帮助文本,后者依次包含imageNet/detectNet/segNet/actionNet/poseNet/backgroundNet的用法说明(model.py 第 150-155 行)。
Model.__init__(model.py 第 31-85 行)按type分派加载不同的网络类:
classification→imageNet(可选threshold、smoothing参数);detection→detectNet,若未指定output_layer则默认生成{'scores': '', 'bbox': ''};segmentation→segNet;pose→poseNet;action→actionNet;background→backgroundNet。
模型在页面中以可折叠卡片(card)呈现,每个卡片带一个展开/收起按钮(card_header+collapse_handler宏),卡片内是控制组件的组合。
REST 查询:前端 UI 与后端推理的实时联动
该应用在 webrtc-html.md 所述的基础 WebRTC HTML/JavaScript 流式播放代码之上,叠加了 REST JSON 查询,用于动态更新组件与参数。后端的路由桩代码在 app.py,前端的 JavaScript 查询在 templates/index.html,并通过模板与宏来减少新增设置项时的样板代码。以分类模型为例,完整的"开关 + 阈值调节"实现如下:
# backend - app.py (Python) @app.route('/classification/enabled', methods=['GET', 'PUT']) def classification_enabled(): return rest_property(stream.models['classification'].IsEnabled, stream.models['classification'].SetEnabled, bool) @app.route('/classification/confidence_threshold', methods=['GET', 'PUT']) def classification_confidence_threshold(): return rest_property(stream.models['classification'].net.GetThreshold, stream.models['classification'].net.SetThreshold, float)<!-- frontend - index.html (Jinja/HTML/JavaScript) --> {{ checkbox('classification_enabled', '/classification/enabled', 'Classification Enabled') }} {{ slider('classification_confidence_threshold', '/classification/confidence_threshold', 'Confidence Threshold') }}后端:rest_property()的 GET/PUT 语义
utils.py 中的rest_property(getter, setter, type, key=None)封装了读写 REST JSON 属性的全部样板逻辑:
- GET 请求:调用
getter()取值,若传入了key则取返回字典中的该键,最后flask.jsonify(value)序列化为 JSON 返回给前端; - PUT 请求:用
type(flask.request.get_json())把请求体 JSON 强制转换为目标类型(如bool、float、int),若有key则setter(**{key: value}),否则setter(value),随后返回 HTTP 200; - 每次请求都会在 Jetson 终端打印一行日志:
<客户端IP> - - REST <方法> <路径> => <值>。
检测模型的追踪参数(minFrames、dropFrames、overlapThreshold)就利用了key参数:rest_property(GetTrackingParams, SetTrackingParams, int, key='minFrames')(app.py 第 105-115 行),实现对同一个字典参数对象中不同键的单独读写。
前端:Jinja 宏与 fetch 客户端
index.html 中的{{ ... }}是 Jinja 模板表达式,由 Flask 在服务端渲染页面时求值,用于按命令行参数动态生成模型卡片。具体控件由 macros.html 提供:
slider(id, rest_path, label, min, max, step, oninput):生成 range 滑块,get_<id>()通过rest_get()拉取当前值回填,oninput事件经debounce触发rest_put()把新值推送到后端;step < 1时显示值会格式化为两位小数;checkbox(id, rest_path, label, oninput):生成开关,同样封装了rest_get/rest_put与初始回填;card_header/collapse_handler:生成 Bootstrap 折叠卡片头与事件处理。
前端 REST 客户端由 static/rest.js 实现,基于原生fetchAPI:rest_get(url)返回解析后的 JSON,rest_put(url, data)以PUT方法发送JSON.stringify(data)并设置Content-type: application/json; charset=UTF-8请求头。滑块拖拽时还借助 static/debounce.js 做防抖,避免高频 PUT 请求压垮后端。
各模型的可调参数与 REST 端点一览
app.py 为每类模型按命令行参数动态注册路由(只有加载了对应模型才会注册对应端点),完整端点映射如下:
分类(--classification,imageNet)
GET/PUT /classification/enabled→IsEnabled/SetEnabled(bool)GET/PUT /classification/confidence_threshold→GetThreshold/SetThreshold(float)GET/PUT /classification/output_smoothing→GetSmoothing/SetSmoothing(float)
目标检测(--detection,detectNet)
GET/PUT /detection/enabledGET/PUT /detection/confidence_threshold→GetConfidenceThreshold/SetConfidenceThresholdGET/PUT /detection/clustering_threshold→GetClusteringThreshold/SetClusteringThresholdGET/PUT /detection/overlay_alpha→GetOverlayAlpha/SetOverlayAlpha(float,前端滑块范围 0-255、步长 1)GET/PUT /detection/tracking_enabled→IsTrackingEnabled/SetTrackingEnabled(bool,开启后前端才会显示下方三个追踪参数滑块)GET/PUT /detection/tracking_min_frames→GetTrackingParams/SetTrackingParams,key=minFrames(int,滑块 0-60)GET/PUT /detection/tracking_drop_frames→ 同上,key=dropFrames(int,滑块 0-60)GET/PUT /detection/tracking_overlap_threshold→ 同上,key=overlapThreshold
语义分割(--segmentation,segNet)
GET/PUT /segmentation/enabledGET/PUT /segmentation/overlay_alpha→GetOverlayAlpha/SetOverlayAlpha(float,滑块 0-255)
姿态估计(--pose,poseNet)
GET/PUT /pose/enabledGET/PUT /pose/confidence_threshold→GetThreshold/SetThreshold(float)
动作识别(--action,actionNet)
GET/PUT /action/enabledGET/PUT /action/confidence_threshold→GetThreshold/SetThresholdGET/PUT /action/skip_frames→GetSkipFrames/SetSkipFrames(int,滑块 0-30)
背景移除(--background,backgroundNet)
GET/PUT /background/enabled
前端 index.html 中每种模型的卡片都只在对应模型被加载(模板变量非空)时才渲染,例如分类卡片的Confidence Threshold滑块默认min=0.0, max=1.0, step=0.01,检测的Overlay Alpha与分割的Overlay Alpha则显式指定min=0, max=255, step=1。
推理管线:流线程如何逐帧运行模型
stream.py 的Stream继承threading.Thread,构造时通过videoSource(args.input)与videoOutput(args.output)创建输入输出(源码见 stream.py 第 42-43 行)。它按背景→分割→分类→检测→姿态→动作的顺序维护self.models字典——该顺序即叠加层(overlay)的合成顺序,保证背景移除与分割结果先绘制、文本类标注最后叠加。
主循环process()每帧执行四步(第 68-84 行):
self.input.Capture()采集一帧图像;- 对每个模型调用
model.Process(img)执行推理; - 对每个模型调用
model.Visualize(img)绘制结果(检测的检测框、分割的类别着色、姿态的关键点/骨架连线、分类与动作的文本标签等); self.output.Render(img)把合成结果编码输出。
同时每 25 帧在终端打印一次统计:captured N frames from <input> => <output> (W x H)。app.py在定义完所有路由后调用stream.start()启动该线程,再以app.run(host=args.host, port=args.port, ssl_context=ssl_context, debug=True, use_reloader=False)启动 Web 服务器(app.py 第 155-164 行),--host默认0.0.0.0即绑定所有网卡接口。
加载自定义模型
除内置预训练模型外,app.py还支持加载用户自有的自定义模型,相关命令行参数如下(app.py 第 47-50 行):
--labels:labels.txt 路径(类别标签);--colors:colors.txt 路径(类别着色,用于检测/分割);--input-layer:模型输入层名称;--output-layer:输出层名称,多个以逗号分隔。
这些参数会透传给 model.py 的Model.__init__:例如检测模型要求output_layer必须能拆出scores与bbox两个 key(传入字符串时按逗号拆分为前两个元素),否则抛出ValueError(model.py 第 58-73 行)。自定义模型对应的标签与着色文件需要与 data/networks/models.json 中登记的内置条目保持相同的格式约定。
启用 HTTPS / SSL
接收浏览器摄像头、以及在公网场景下传输 WebRTC 流与网页内容,官方均推荐启用 HTTPS 加密(详细背景见 webrtc-server.md 的 "Enabling HTTPS / SSL" 一节)。首先生成自签名证书:
$ cd jetson-inference/data $ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -nodes -subj '/CN=localhost' $ export SSL_KEY=/jetson-inference/data/key.pem $ export SSL_CERT=/jetson-inference/data/cert.pem当设置$SSL_KEY与$SSL_CERT环境变量后,本仓库的应用会自动启用 HTTPS。若不想用环境变量,也可以在启动 Flask 示例时显式传入命令行参数:
$ python3 app.py --ssl-key=key.pem --ssl-cert=cert.pem --detection=ssd-mobilenet-v2app.py 中--ssl-key与--ssl-cert的默认值正是从环境变量SSL_KEY/SSL_CERT读取(第 36-37 行),并在第 160-161 行将二者组合为ssl_context传给app.run()。注意:首次用自签名证书访问页面时浏览器会提示安全警告,选择继续访问即可;证书可存放在任意路径,若使用 Docker 容器则建议放在data/目录下,因为它会挂载回宿主机,容器退出后证书依然保留。
延伸阅读
- webrtc-html.md:上一节的纯 HTML/JavaScript 前端,本示例的流式播放代码基础;
- webrtc-dash.md:下一节基于 Plotly 的仪表盘变体(python/www/dash),同样是 WebApp 框架系列;
- webrtc-server.md:WebRTC 服务器的发送/接收/全双工模式与 HTTPS 配置;
- aux-streaming.md:
videoSource/videoOutput支持的各类视频流输入输出; - python/examples:仓库提供的一组可运行 Python 示例,便于对比控制台与 Web 两种推理形态。
- 人工智能
- 计算机视觉
- 深度学习
- 微调
【免费下载链接】jetson-inference
Hello AI World guide to deploying deep-learning inference networks and deep vision primitives with TensorRT and NVIDIA Jetson.
相关推荐
jetson-inference WebRTC 网页应用实战:基于 HTML/JavaScript 的 DNN 推理流媒体前端
jetson inference WebRTC 网页应用实战:基于 HTML/JavaScript 的 DNN 推理流媒体前端 本文是 jetson infer
人工智能计算机视觉深度学习微调突破边缘视觉限制:Jetson-inference WebRTC与Unity3D低延迟交互方案
突破边缘视觉限制:Jetson inference WebRTC与Unity3D低延迟交互方案 在边缘计算场景中,实时视觉数据的高效传输与三维引擎的无缝集成一直
人工智能计算机视觉深度学习微调Flask Shell:flask shell 交互控制台原理与请求上下文实战
Flask Shell:flask shell 交互控制台原理与请求上下文实战 flask shell 是 Flask 提供的 CLI 命令,它在一个已加载好应
后端Web框架
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考