AI-深度学习

从零搭建视觉模型 24:从摄像头输入到部署验收

展开合集目录
  1. 从零搭建视觉模型 01:图片进入模型后发生了什么
  2. 从零搭建视觉模型 02:Python 起步,写给 C/C++ 开发者
  3. 从零搭建视觉模型 03:从像素到张量的基础概念
  4. 从零搭建视觉模型 04:图片如何变成张量
  5. 从零搭建视觉模型 05:MLP 入门,从手算到图片输入
  6. 从零搭建视觉模型 06:亲手搭建一个小型 CNN
  7. 从零搭建视觉模型 07:模型怎样预测类别:分数、概率与决策
  8. 从零搭建视觉模型 08:让模型开始学习,损失、梯度与训练循环
  9. 从零搭建视觉模型 09:数据集、标签与数据划分
  10. 从零搭建视觉模型 10:损失函数与优化器:怎样把错误变成更新
  11. 从零搭建视觉模型 11:批次、训练轮次与学习率
  12. 从零搭建视觉模型 12:训练第一个真实图片分类器
  13. 从零搭建视觉模型 13:过拟合、数据增强与正则化
  14. 从零搭建视觉模型 14:验证、测试与错误分析
  15. 从零搭建视觉模型 15:保存模型、恢复训练与独立推理
  16. 从零搭建视觉模型 · 综合实践:实现 MLP,从损失计算、训练到 ONNX 推理
  17. 从零搭建视觉模型 16:ResNet 与残差连接
  18. 从零搭建视觉模型 17:预训练、迁移学习与微调
  19. 从零搭建视觉模型 18:轻量模型与计算成本
  20. 从零搭建视觉模型 19:目标检测与 YOLO:从类别到目标框
  21. 从零搭建视觉模型 20:图像分割与 U-Net:给每个像素一个判断
  22. 从零搭建视觉模型 21:注意力与视觉 Transformer
  23. 从零搭建视觉模型 22:从训练模型到 ONNX
  24. 从零搭建视觉模型 23:量化与精度对比
  25. 从零搭建视觉模型 24:从摄像头输入到部署验收
  26. 从零搭建视觉模型 25:发展历史、主流分类与当前格局
从零搭建视觉模型 24:从摄像头输入到部署验收的封面

学习初稿 · 第 24 课。 本篇已开放网页阅读,用于先建立完整认识。文中手算值和示意记录不代表真实训练成绩;真实数据训练、预训练权重和板端测试以本篇具体说明为准,本篇已附代码练习,实际验证范围见文末与包内记录。

从一张文件图片走向连续输入

训练程序处理静态数据,设备面对的是连续帧、缓冲区、时间戳和错误状态。即使同一模型离线准确率很好,也可能因图像格式、数据生命周期或排队策略在现场失效。

本课不假定某一块板子的 SDK 接口。先建立通用验收方法,再衔接已有的海思系列。没有目标设备测试记录之前,不给出“某型号能够达到多少帧”的结论。

先保存一帧,再接实时循环

摄像头原始输出可能是 YUV、RGB 或其他格式,还可能存在行步长与对齐。缓冲区占用不一定等于宽×高×通道数,读取时必须依据真实格式和 stride。

先保存一帧及其格式说明,把它交给 PC 与板端相同的处理逻辑。依次比较解码或颜色转换结果、缩放后的图片、最终输入张量及模型输出。这样能区分模型差异与相机每次拍摄内容不同。

例如 YUV 到 RGB 的矩阵、范围约定,RGB 与 BGR 顺序、缩放插值和 letterbox 填充都可能影响结果。训练预处理如果使用裁剪,设备却直接拉伸,网络看到的几何分布也变了。

写一张完整接口表

边界 必须确认的信息
相机到预处理 格式、尺寸、行步长、时间戳、缓冲生命周期
预处理到模型 布局、数据类型、颜色、数值范围、对齐
模型到后处理 输出名称、形状、精度、类别及坐标含义
后处理到应用 有效性、类别或框、分数、错误状态与输入时间

应用收到的结果应对应明确帧号或时间戳,不能把旧帧的预测标成当前画面。模型加载、内存分配和设备初始化通常在循环外完成,避免每帧反复创建资源。

队列策略决定延迟是否会失控

相机每秒 30 帧,模型每秒只能处理 10 帧,如果把所有帧无限排队,输出会越来越旧。实时观察场景可能采用有界队列或只保留最新帧;需要逐帧留档的任务则要降低采集率或提高处理能力。

丢帧策略没有统一答案,必须由任务决定。若计算目标轨迹,还要考虑时间间隔变化,而不是把所有帧都假定为等间距。异步推理时,提交后不能立刻复用仍被设备访问的输入缓冲。

分开统计四段耗时

端到端延迟包括等待输入、预处理、推理、后处理与输出。只计设备执行调用附近的时间,可能漏掉传输和队列;若接口异步,甚至只测到了提交耗时。

可以先学习如何报告中位数和较高分位。下面是人为构造的毫秒数据,用来演示 nearest-rank 分位数,不代表设备测量:

import math
import statistics

samples_ms = [10, 11, 10, 12, 13, 10, 11, 12, 50, 11]
ordered = sorted(samples_ms)
p95 = ordered[math.ceil(0.95 * len(ordered)) - 1]
print('median:', statistics.median(samples_ms))
print('p95:', p95)

少量样本的高分位很不稳定。正式测量要固定预热、测试时长、输入、线程和电源模式,并说明分位计算方式。首次加载延迟与稳定运行延迟分开报告。

验收顺序从数值到系统

第一步,PC 浮点模型在固定输入上的结果正确;第二步,导出模型在同样输入上数值一致;第三步,量化模型的质量损失可接受;第四步,设备使用同一张量时输出符合容差;第五步,接入相机预处理;最后做长时间运行与异常处理。

这样出现问题时能回到最近一个通过的边界。若从相机直接跳到最终报警,再同时修改预处理、量化和阈值,就无法确定是哪一项真正起作用。

稳定性测试应观察内存是否持续增长、温度和降频、队列是否积压、输入中断后能否恢复、停止时资源是否正确释放。准确率、延迟和功耗条件都达到任务要求,才可以说当前方案完成验收。

接到已有海思系列

通用部分理解后,再进入平台工具与文档地图,核对芯片、工具和 SDK;通过模型输入检查明确接口;最后参考板端最小推理闭环与性能排查完成具体平台操作。

这些文章的存在不代表本篇新模型已经在板上验证。实际模型名称、工具版本、配置、参考输入、结果与日志都应归档到本次实验,而不是复用其他项目的成功描述。

练习

  1. 相机 30 FPS、推理 10 FPS,队列无限长会怎样?
  2. PC 与板端比较时,两边各自拍一张“差不多”的图,能否直接判定数值误差?
  3. 模型推理 10 ms,能否宣称整个产品延迟是 10 ms?
参考答案

等待帧持续增加,结果越来越陈旧,需要明确吞吐或丢帧策略。输入不同无法直接比较后端数值,应先用同一固定张量。完整延迟还包括采集、排队、转换、传输和输出,必须说明计时边界。

到这里,分类学习、不同视觉任务与部署验证已经连起来。最后回看《视觉模型的发展历史、主流分类与当前格局》,把见过的运算、任务和技术路线放回全景中。

配套代码练习

实验:输入颜色契约与队列延迟

查看完整代码:main.py
"""输入颜色契约与队列延迟。运行方式与练习见 README.md。"""
import math
# 离线单像素帧,不访问摄像头;BGR 红色应转成 RGB 的 [1,0,0]。
bgr = [0,0,255]
rgb = list(reversed(bgr))
normalized = [v/255 for v in rgb]
assert normalized == [1.0,0.0,0.0]
print('RGB:',normalized)
# 确定性离散事件模拟:每 33ms 来一帧,每次推理耗时 50ms。
arrivals = list(range(0,3300,33))
def simulate(latest):
    now, i, latencies, dropped = 0,0,[],0
    while i<len(arrivals):
        now = max(now,arrivals[i])
        chosen = i
        if latest:
            while chosen+1<len(arrivals) and arrivals[chosen+1]<=now: chosen += 1
        dropped += chosen-i
        now += 50
        latencies.append(now-arrivals[chosen])
        i = chosen+1
    ordered = sorted(latencies)
    return len(latencies),dropped,sum(latencies)/len(latencies),ordered[math.ceil(.95*len(ordered))-1]
fifo,latest = simulate(False),simulate(True)
print('策略: 完成数/丢帧数/平均延迟/P95毫秒')
print('FIFO:',fifo,'保留最新:',latest)
assert latest[3]<fifo[3]
assert latest[0]+latest[1]==len(arrivals)
下载代码

在项目根目录执行;下载包解压后,在解压目录执行 python3 main.py。

cd 'content/posts/AI-深度学习/从零搭建视觉模型/24-摄像头输入与部署验收/code' && python3 main.py

本篇已附独立实验包,在代码卡片中查看源码、下载或复制运行命令。解压后执行 python3 main.py;依赖安装见包内 README.md。

观察目标: FIFO 延迟持续累积;保留最新帧降低 P95 但会丢帧。这里没有实际摄像头或 NPU 性能结论。

动手修改: 把推理耗时改为 20ms,观察两种策略差距;设备验收时用真实时间戳替换模拟到达时间。

所有输入均在本篇代码中构造;运行范围和验证记录见包内 verification.md。


完整阅读目录 · 上一篇 · 下一篇