尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Jetson Nano 边缘AI实战:调优、TensorRT检测与手势识别

发布时间:2026/9/29 7:21:57

资讯中心
01
ARTICLE

Jetson Nano 边缘AI实战:调优、TensorRT检测与手势识别

Jetson Nano 边缘AI实战:调优、TensorRT检测与手势识别
从一个塞在抽屉里吃灰的 Jetson Nano 说起。很多人第一次拿到这块 4GB B01 的板子都是被边缘 AI 入门最便宜的 CUDA 平台这句话种草的然后兴冲冲刷完系统插上摄像头结果卡在三个地方摄像头ls /dev/video*什么都没有、跑官方 Demo 一帧要等三秒、想看手势识别却发现官方只给了手部关键点。我自己在这块板子上前后重装过四次系统从 JetPack 4.4 一路折腾到 4.6把目标检测、手势识别这两个 Demo 完整跑通、又接到了几个小项目上。这篇就把 Jetson Nano 的系统安装、环境调优、官方 Demo 验证这条链路一次性讲透——包括哪些坑是必然踩的、哪些参数是会误导你的、以及手势识别这个说法在官方仓库里到底对应什么。只要你会基本的 Linux 命令跟着走一遍能省下至少两个晚上。1. 开工之前先把硬件账算清楚1.1 4GB B01 和 A02 到底差在哪B01 是现在市面上能买到的绝大多数版本和早期的 A02 相比最实用的差别是载板上多了一个 MIPI CSI 摄像头接口也就是 CAM0 和 CAM1 两个 15 针 FPC 座子这意味着你可以上双目。此外 B01 还留了 PoE 模块的焊接位、一个风扇供电座以及用于选择供电来源的J48 跳线。A02 对应的跳线是 J25两者不通用网上很多老教程写 J25你照着插在 B01 上会找半天。4GB这个数字要特别理解一下它不是显存是CPU 和 GPU 共享的 LPDDR4128 位位宽、25.6GB/s 带宽。也就是说你跑一个 TensorRT 模型engine 加载进显存的部分就是从这 4GB 里切的桌面环境、Python 进程、OpenCV 的 buffer 全都在里面抢。这是后面所有调优动作的根本出发点——不是性能不够是内存和带宽双紧张。如果你正在犹豫要不要直接上 Orin Nano我的判断是这样如果目标是验证一个已经成型的算法能不能跑起来、跑通数据链路、做个小 Demo 交差Nano 完全够几百块的成本能跑通 CUDA TensorRT 全链路这个学习价值没有替代品如果目标是要做多路视频流、要跑现代检测模型的原生精度、要在板子上训练那别在 Nano 上耗省下的时间成本远超几百块差价。1.2 SD 卡、电源、散热三个最容易被低估的前置条件新手最容易在这三样上省钱然后花三倍时间排查玄学问题。我整理成一张表都是踩过之后才认账的项目推荐做法省钱的后果microSD 卡32GB 起步A1/A2 认证U3 或至少 U1选大牌高耐久系列ext4 报 I/O error、系统无故重启、编译到一半卡死供电5V 4A 圆孔电源 短接 J48 跳线micro-USB 只能跑 5W 模式负载一上来直接掉电重启散热至少一片铝散热片最好加 5V 小风扇连续推理 10 分钟后热降频帧率断崖式下跌关于 SD 卡再补一个细节Nano 的系统写入非常频繁日志、swap、模型缓存普通卡跑半年出现坏块的概率不低。我现在的习惯是买两张同型号的卡一张主力一张做备份镜像的载体。另外首次开机时系统会自动把根分区扩展到整张卡所以卡买大一点是无痛的不存在用不满浪费的问题。关于风扇B01 上那个风扇座是 5V 直供的JetPack 4.6 之后可以通过写/sys/devices/pwm-fan/target_pwm0 到 255来调速。我的做法是写个小脚本按cat /sys/devices/virtual/thermal/thermal_zone0/temp的温度分档控制60 度以下停转70 度以上拉满。这样白天跑 Demo 不吵晚上挂机编译也不会烧。1.3 镜像选择JetPack 4.6.x 是这条产品线的终点Nano 能用的最高版本就是JetPack 4.6.x 系列对应 L4T r32.7.x底层是 Ubuntu 18.04 LTS上面捆了 CUDA 10.2、cuDNN 8.2、TensorRT 8.2、带 CUDA 支持的 OpenCV 4.1.1还有 VisionWorks 和一套 GStreamer 插件。JetPack 5 之后官方就不再支持 Nano 了所以不要去看 5.x 的文档命令对不上会浪费大量时间。下载官方 SD 卡镜像的时候注意两点。第一压缩包大概 6GB 出头解压后接近 14GB硬盘空间要留够。第二一定核对官网页面上的校验值我遇到过一次下载中断导致写到 80% 报错白白浪费一张卡的写入寿命。提示镜像版本一旦确定就别乱换。不同小版本的 TensorRT 不兼容彼此的 engine 缓存文件换版本后所有.engine都得重新编译YOLOv5s 一次要十几分钟很肉疼。2. 刷写镜像与首次开机把硬件变成一台能用的机器2.1 写卡这件事Etcher 比 dd 省心在哪写卡工具我推荐 balenaEtcher理由不是它快而是它写完会回读校验。Nano 这种卡写坏了要排查半天才发现的设备写入阶段的校验价值很高。步骤很简单选镜像、选目标卡、点 Flash等进度条走完自动校验。需要提醒的是写完卡之后重新插回 Windows系统会弹窗说此磁盘需要格式化——千万别点格式化。那是因为卡上有好几个 ext4 和 FAT 分区Windows 认不出来。点了格式化就得重刷。如果习惯用命令行在 Linux 下也是可以的# 先确认目标设备千万别写错盘 lsblk # 假设卡是 /dev/sdb sudo dd ifnv-jetson-nano-sd-card-image-r32.7.1.zip of/dev/sdb bs4M statusprogress sync注意dd是可以直接吃官方那个 zip 的因为镜像内部就是逐字节的 raw 数据。写完务必sync否则拔卡太早会缺尾部数据。2.2 没有显示器怎么开机串口控制台这条后路第一次开机我建议老老实实接 HDMI 显示器加 USB 键鼠走一遍 Ubuntu 的首次配置向导选语言、设用户名密码、设时区、选键盘布局。这套向导走完系统才算真正可用。但如果你的板子是要装在机器人底盘上、藏在设备里没有显示器可用那就得靠串口控制台。方法是找一个 3.3V 电平的 USB-TTL 小板接到 Nano 40 针排针的6 号脚 GND、8 号脚 UART_TX、10 号脚 UART_RX参数 115200 8N1用 picocom 或者 PuTTY 连上。上电之后你能看到完整的启动日志首次配置向导也可以在纯文本模式下走完。注意USB-TTL 模块一定要选 3.3V 的5V 电平的模块接上去有可能打坏 SoC 的 UART 引脚。这是硬损伤救不回来。串口这条链路还有个额外好处系统崩溃卡在启动阶段时屏幕可能黑着什么都不显示但串口日志会把报错打出来是排障时最有价值的一手信息。2.3 首次进入系统后立刻要做的六件事别急着跑 Demo先花二十分钟把地基打好后面能省掉一堆莫名其妙的错误换 apt 源。Nano 是 aarch64 架构Ubuntu 18.04 对应的源是ubuntu-ports不是普通的ubuntu。国内用户可以直接换成清华或者中科大的ubuntu-ports镜像否则apt update会等到你怀疑人生。确认分区已经扩展。df -h看一下根分区是不是已经撑满整张卡正常应该自动扩展过了。打开 SSH。sudo systemctl enable --now ssh之后就能通过网络连上去不用一直占着显示器。设置静态 IP 或 DHCP 保留。做摄像头 Demo 的时候你会频繁重启板子IP 变来变去很烦。检查温度与风扇。cat /sys/class/thermal/thermal_zone*/temp同时确认风扇在转。先做一次系统备份。这一步很多人跳过然后在后面某次误操作后追悔莫及。哪怕只是用dd把卡 dump 成镜像放起来也能在关键时刻救你一命。关于apt upgrade我要单独给个警告首次开机不要盲目执行全量升级。JetPack 里的 L4T 相关包内核、dtb、nvidia 驱动和系统其他部分版本是严格绑定的某些升级路径会导致启动时卡在黑屏或者进不了图形界面。稳妥的做法是先apt list --upgradable看清楚要动哪些包如果里面出现nvidia-l4t-*或者linux-image系列就先按住别升。3. 把系统调成能跑模型的状态3.1 交换空间4GB 内存的生存法则先用free -h和swapon --show看当前状态。官方镜像里通常会有一份默认的交换文件但容量不大2GB 量级跑个 Demo 够编译大型项目就不够。我的做法是把它扩到 4GB 到 8GBsudo swapoff -a sudo fallocate -l 6G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile # 写入 fstab 让它开机自动挂载 echo /swapfile none swap sw 0 0 | sudo tee -a /etc/fstab这里有个容易忽略的调优点vm.swappiness。默认值是 60介于尽量用内存和尽量用 swap之间。Nano 上我的经验是分场景调——编译 jetson-inference 或者导出 TensorRT engine 这种内存峰值很高的任务把 swappiness 临时调到 80 左右让它老老实实往 swap 里塞宁可慢也别被 OOM Killer 干掉日常跑推理时调到 10 到 20避免 SD 卡被反复读写拖慢帧率。# 临时改立即生效 sudo sysctl vm.swappiness80至于 zram内存压缩当 swap 用它在 Nano 上的定位是日常轻负载救急优点是快、不伤卡缺点是要吃 CPU 做压缩解压而 Nano 的 CPU 本来就是瓶颈。我个人的取舍是编译用 swapfile长期运行的推理服务用 zram 或者干脆不用。提示swap 放在 SD 卡上会显著加速卡的磨损。如果你打算长期跑强烈建议换成 eMMC 版本或者通过 USB 3.0 挂一块 SSD——B01 上虽然没有 M.2 插槽但 USB 3.0 口是可以挂 SATA 转接的把 swap 和模型缓存都放过去体验差别很大。3.2 nvpmodel 与 jetson_clocks白捡的那 30% 性能这两个命令是 Nano 上性价比最高的调优手段没有之一。nvpmodel是功耗模式切换。Nano 上有两个官方模式模式 0 是 10W四个 A57 核心全开主频能到 1.47GHz模式 1 是 5W只开两个核心主频降到 0.92GHz。默认镜像跑的是 10W 还是 5W 取决于你首次开机时的供电判断所以一定要手动确认sudo nvpmodel -q # 查询当前模式 sudo nvpmodel -m 0 # 切到 10Wjetson_clocks则是把当前模式下 CPU、GPU、EMC内存控制器的频率全部锁到最高同时关闭动态调频。它不改变功耗上限只是把动态升降频变成一直高频代价是发热和耗电都上去。sudo jetson_clocks # 拉满 sudo jetson_clocks --show # 看当前各域频率 sudo jetson_clocks --restore # 恢复默认动态调频实测下来nvpmodel -m 0加jetson_clocks之后ssd-mobilenet-v2 的推理帧率大概能提升 20% 到 40%具体取决于场景复杂度和散热条件。这个提升幅度比换一张更快的 SD 卡明显得多而且不要钱。注意模式 0 必须配合圆孔供电使用。如果你用 micro-USB 供电切到模式 0 之后很可能在高负载瞬间掉电重启表现是跑着跑着黑屏重启。这种情况九成是供电问题不是系统问题。3.3 环境自查把版本账本先对一遍跑 Demo 之前把环境版本摸清楚出问题时能立刻定位是版本不匹配还是用法不对。这几条命令我基本每次装完系统都会跑一遍组件自查命令JetPack 4.6 期望值L4T 版本cat /etc/nv_tegra_releaseR32.7.xCUDAnvcc --version10.2cuDNNdpkg -lgrep cudnnTensorRTdpkg -lgrep nvinferOpenCVpython3 -c import cv2; print(cv2.__version__)4.1.1OpenCV CUDApython3 -c import cv2; print(cv2.cuda.getCudaEnabledDeviceCount())1摄像头ls /dev/video*video0这里有个必须记住的禁忌绝对不要用 pip 装opencv-python。系统自带的 4.1.1 是编译时带 CUDA 支持的pip 上那个是纯 CPU 版本装上之后除了覆盖掉 CUDA 加速能力还会把 numpy 版本搅乱然后import cv2直接报错。我见过太多人卡在这一步以为是 OpenCV 装坏了其实是装好了。另一个小细节是 pip 本身的版本。系统 Python 是 3.6.9pip 21.3 之后就放弃了对 3.6 的支持所以升级 pip 时最好加个约束python3 -m pip install --upgrade pip21.3 setuptools60 wheel装包的时候建议用 venv 隔离但要用--system-site-packages参数创建否则jetson.inference和系统自带的带 CUDA 的 cv2 就都找不到了python3 -m venv --system-site-packages ~/venv-proj source ~/venv-proj/bin/activate4. 摄像头这条链路比模型更容易出问题4.1 CSI 排线、IMX219 与 nvargus 的那些坑CSI 摄像头是 Nano 上性能最好的方案因为它走的是 MIPI 直连配合nvarguscamerasrc能做 NVMM 零拷贝图像数据直接进 GPU 内存不经过 CPU 搬一遍。原理上的优势决定了它在帧率上会比 USB 摄像头高一大截。但这条链路有三个必踩的坑第一是排线方向。这个真的能把人逼疯。Jetson Nano B01 上 CSI 排线的金属触点要朝向 Jetson 模组那一侧和树莓派的方向正好相反。插反了不会烧板子但ls /dev/video*会是空的dmesg | grep imx也什么都看不到。我第一次就插反了对着树莓派的教程折腾了四十分钟。第二是模组兼容性。JetPack 4.6 内置的驱动支持IMX219树莓派 Camera V2以及市面上一大堆 IMX219-160、IMX219-77 模组和OV5647Camera V1。但树莓派 Camera V3 用的 IMX708 不支持插上去一样是识别不到。买模组之前一定确认芯片型号不要看着树莓派摄像头几个字就下单。第三是 nvargus-daemon 会假死。这个是 JetPack 4.x 上的老毛病。表现是摄像头本来好好的跑了一段时间后突然打不开报 Failed to create CaptureSession 之类的错误。九成情况重启一下这个服务就好sudo systemctl restart nvargus-daemon如果还不行就sudo killall nvargus-daemon之后再看它自动拉起或者直接重启板子。B01 有两个 CSI 接口的时候默认用的是 CAM0。如果你插在 CAM1 上需要在 40 针配置里切一下sudo /opt/nvidia/jetson-io/jetson-io.py这个工具能做硬件接口的图形化配置比手动改 dtb 友好太多。4.2 USB 摄像头能用但你要知道代价USB 摄像头的好处是免驱、插上就能用UVC 标准坏处有三个走的是 USB 2.0 通道带宽撑不住高分辨率高帧率没有 NVMM 零拷贝每一帧都要经过 CPU 搬运和格式转换最后就是会和别的 USB 设备抢带宽。实际测试下来USB 摄像头在 MJPG 编码下跑 1280x720 30fps 是勉强的YUV 格式基本只能到 640x480。对于目标检测 Demo 来说其实够用了因为 ssd-mobilenet 的输入本来就是 300x300 或者 640x360 这个量级。但如果你要做高帧率的手势跟踪CSI 的优势就体现出来了。4.3 先用 GStreamer 单独验证通路这是我最想强调的一条经验把能看到画面和能跑模型分成两步验证。很多人一上来就跑目标检测 Demo结果黑屏然后就得同时怀疑摄像头驱动、GStreamer 管道、模型加载、显示输出四条链路排查成本翻好几倍。先用最底层的 GStreamer 管道确认摄像头通了gst-launch-1.0 nvarguscamerasrc ! \ video/x-raw(memory:NVMM),width1280,height720,framerate30/1 ! \ nvvidconv ! nvoverlaysink画面出来说明驱动和硬件都没问题。接着装好 jetson-inference 之后用自带的video-viewer工具再验一遍video-viewer csi://0 # CSI 摄像头 video-viewer /dev/video0 # USB 摄像头 video-viewer csi://0 --input-width1280 --input-height720 --input-rate30这一步过了后面模型跑不出结果就一定是模型侧的问题排查范围一下子收窄了。5. 官方 Demo 实战jetson-inference 从编译到跑通5.1 源码编译耗时、报错与两个关键选择官方 Demo 的主体是 NVIDIA 工程师维护的jetson-inference项目也就是常说的 Hello AI World。它不是 apt 包得自己编译。sudo apt-get install git cmake libpython3-dev python3-numpy git clone --recursive https://github.com/dusty-nv/jetson-inference cd jetson-inference mkdir build cd build cmake ../ make -j2 sudo make install sudo ldconfig这里有两个关键选择值得解释为什么必须加--recursive这个仓库依赖jetson-utils、pybind11等好几个子模块。不加这个参数子模块目录是空的cmake 阶段就会报找不到 jetson-utils而且报错信息不会直接告诉你是子模块没拉下来新手很容易卡在这里。如果已经 clone 了没加参数补救方法是git submodule update --init --recursive。为什么是make -j2而不是-j4因为 4GB 内存扛不住四个并行编译进程。我试过-j4跑到一半直接被 OOM Killer 干掉报 Killed看着像编译错误其实是内存不够。为稳妥起见用-j2如果想快一点先按前面说的把 swap 加到 6GB 以上再用-j3。整个编译过程在这块板子上大概要 40 分钟到一个半小时跟 SD 卡速度关系很大建议泡杯茶。cmake 阶段会弹出一个文本界面的模型下载器让你选要下哪些预训练模型。我的建议是先按 ESC 跳过等编译完成之后再用./tools/download-models.sh单独下载——那个脚本可以反复运行选择更灵活而且在编译前下载模型纯粹是在浪费时间。如果原生编译怎么都过不去还有一条退路是 Dockerdocker run --runtime nvidia -it --rm \ --network host \ --device /dev/video0 \ -v /tmp/argus_socket:/tmp/argus_socket \ dustynv/jetson-inference:r32.7.1注意-v /tmp/argus_socket:/tmp/argus_socket这行挂载没有它容器里是访问不到 CSI 摄像头的这个坑非常隐蔽。5.2 detectnet 目标检测实测分辨率与帧率的取舍编译安装完成后可执行文件会被装到/usr/local/bin直接敲名字就能用。第一步先下模型cd ~/jetson-inference/tools ./download-models.sh用方向键和空格勾选需要的网络然后回车。目标检测这块主要就是 SSD-Mobilenet 系列和 PedNet前者是通用 COCO 90 类检测后者是行人检测。下载完成后可以先拿静态图片验证detectnet --networkssd-mobilenet-v2 \ ~/jetson-inference/data/images/peds_0.jpg \ /tmp/out.jpg图片上出现框就说明模型和 TensorRT 这条链路完全通了。接着换成摄像头实时推理detectnet --networkssd-mobilenet-v2 /dev/video0我实测的帧率区间大致是这样模式 0 加 jetson_clocks散热正常网络输入尺寸精度帧率区间典型用途ssd-mobilenet-v2640x360FP1630-45 FPS通用目标检测ssd-mobilenet-v1640x360FP1625-35 FPS精度稍低但更轻pednet640x360FP1625-40 FPS行人统计YOLOv5sTRT640x640FP1615-22 FPS自训练目标YOLOv5nTRT640x640FP1625-32 FPS轻量边缘场景几个实操要点。--threshold默认 0.5实际用的时候根据场景调检测小目标时往下压到 0.3 左右能多召回一些但误检也会变多。--overlaybox,labels,conf控制叠加显示的内容跑无头模式的时候可以只留 box 省点绘制开销。如果要做成无显示器的服务加--headless同时可以用--output-urirtsp://:8554/out把结果推出去用 VLC 看。还有一个必须知道的认知ssd-mobilenet-v2 用的是 COCO 数据集90 个通用类别里面没有人以外的工业目标。想检测你自己场景里的东西比如某种零件、某种病害必须自己准备数据训练官方 Demo 只能帮你验证整条链路是通的。5.3 Python 接口的最小可跑示例很多人最终是要在 Python 里做二次开发因为后处理逻辑用 C 写太累。jetson-inference 提供了 Python 绑定一个能跑的最小例子长这样import jetson.inference import jetson.utils net jetson.inference.detectNet(ssd-mobilenet-v2, threshold0.5) camera jetson.utils.videoSource(csi://0) display jetson.utils.videoOutput(display://0) while display.IsStreaming(): img camera.Capture() detections net.Detect(img, overlaybox,labels,conf) display.Render(img) display.SetStatus(Object Detection | Network {:.0f} FPS.format(net.GetNetworkFPS()))有两个细节容易翻车。第一是首次运行会加载 TensorRT engine可能要等十几秒到一分钟屏幕一片黑不要以为卡死了。engine 加载完之后会缓存下来第二次启动就快了。第二是 Python 版本系统 Python 是 3.6jetson.inference会被装到系统的 dist-packages 里所以如果你用了 venv一定要带--system-site-packages参数否则import jetson.inference会直接报 ModuleNotFoundError。6. 手势识别 Demo 的真相官方给的是关键点不是手势6.1 posenet 加 resnet18-hand先搞清楚你拿到的是什么这是整篇文章里我最想澄清的一点。网上搜Jetson Nano 手势识别很多文章会告诉你跑官方 Demo 就行但实际上官方 Demo 给到的是手部关键点检测hand pose estimation不是手势分类。这两件事差了一层。具体来说jetson-inference 里的posenet支持几个模型resnet18-body做人体姿态resnet18-hand做手部姿态。手部模型会输出手腕、掌指关节、指间关节、指尖等一串关键点以及它们之间的骨骼连线。你看到的画面是一只手上叠了一堆点和线但系统并不知道这是石头还是布。先用download-models.sh把 Pose 类别下的模型勾上然后posenet --networkresnet18-hand /dev/video0画面里出现手部骨架就说明模型通了。到这一步算是完成了检测接下来才是识别。6.2 用几何规则做第一版手势判断如果你的目标只是判断几种固定手势握拳、张开、OK、点赞、剪刀手完全不需要训练模型用几何规则就能做出一个能用的版本而且帧率毫无损失。核心思路是判断每根手指是伸直还是弯曲。方法有两种一种是比较指尖到手腕的距离和近端指节到手腕的距离另一种是算指节之间的夹角。第一种实现简单、对噪声容忍度高我一般先用它。判断逻辑大概是把指尖到腕部的距离除以手掌宽度做归一化超过某个阈值认为伸直否则认为弯曲。拇指因为活动方向特殊阈值要单独设。把五根手指的伸直状态拼成一个五位向量就能映射到手势了。我用过的映射大致是这样手势五指向量拇食中无名小判断依据张开手掌1 1 1 1 1五根全伸直握拳0 0 0 0 0五根全弯曲点赞1 0 0 0 0只有拇指伸直剪刀手0 1 1 0 0食指中指伸直OK 手势0 0 0 0 0 特殊拇指尖与食指尖距离小于阈值这套规则版的优点是零训练、推理开销可以忽略、改起来快缺点也很明显手转个角度、稍微侧对镜头、或者被遮挡判断就会抖。所以一定要加时序平滑——用一个 8 到 10 帧的滑动窗口做多数投票只有超过一半帧数判定为同一个手势才输出。这一步加上之后观感上的稳定性提升非常明显比调阈值有用得多。6.3 把关键点当特征训一个小分类器规则版只能覆盖你预先想好的几种手势想识别更多种类就得上一层的分类器。好在这件事在 Nano 上并不难因为输入维度太低了。做法是把每帧的关键点坐标相对于手掌包围盒做归一化消除位置和尺度影响得到一个几十维的特征向量然后喂给一个三四层的全连接网络比如 128 到 64 到类别数。样本可以从摄像头采每类手势录两三百帧标好标签在 PC 上几分钟就训完了模型小到可以在 Nano 的 CPU 上跑完全不占 GPU。NVIDIA 官方那个 trt_pose 手部项目用的就是这套思路在公开手势数据集上训了一个小分类头。我的实操建议是先用规则版把整条链路跑通、把延迟和稳定性问题摸清楚再决定要不要上分类器。因为实际项目里你会发现手势识别的难点从来不是分类精度而是用户的手在什么位置、有没有进框、光照够不够、背景里有没有另一只手。这些问题跟分类器是规则还是神经网络没有任何关系。还有一个性能上的判断手部关键点网络本身在 Nano 上跑 224x224 输入大概能到几十 FPS取决于你是否同时跑检测而那个小分类器的开销基本可以忽略。也就是说瓶颈在关键点网络上不在分类上优化时别搞错方向。7. YOLOv5 与自训练模型在 Nano 上的落地节奏7.1 为什么必须经过 TensorRT直接拿 PyTorch 在 Nano 上推理 YOLOv5s实测只有 1 到 3 FPS基本没法用。而经过 TensorRT 优化之后同样的模型能到 15 到 22 FPS差了将近十倍。这个差距从哪来的TensorRT 主要做三件事算子融合把卷积、批归一化、激活合并成一个 kernel减少内核启动和中间内存读写、精度量化FP16 甚至 INT8直接吃满 Nano 的算力、针对具体硬件做 kernel 自动调优同一份网络在不同的 GPU 上会用不同的实现方式。这三件事叠加起来才有了那个数量级的提升。代价是engine 文件和硬件、TensorRT 版本、甚至驱动版本强绑定。换一块板子、升一次 JetPackengine 就得重新编译。所以千万别把.engine当成可移植的模型文件到处传它是针对这台机器编译出来的产物。7.2 从 PyTorch 权重到 engine 的完整流程第一步是装 PyTorch。Nano 的 ARM 架构装不了 pip 上的官方包得用 NVIDIA 论坛发布的预编译 wheel而且版本必须和 JetPack 4.6 加 Python 3.6 严格对上。装完记得验证torch.cuda.is_available()返回 True 才算成功。第二步是选 YOLOv5 的版本。这里有个必须知道的限制Nano 的系统 Python 是 3.6.9而 YOLOv5 从 7.0 开始要求 Python 3.7 以上。所以在 Nano 上你要用 6.x 分支6.0 到 6.2 都可以直接 clone 最新的 master 会在pip install -r requirements.txt阶段就卡住。这个坑我踩过报错信息是某个依赖要求更高的 Python 版本看起来很突兀。第三步是导出和编译# 方式一直接从 PyTorch 导出 engine python3 export.py --weights yolov5s.pt --include engine --device 0 --half --imgsz 640 # 方式二先转 ONNX再用 trtexec 编译可控性更强 python3 export.py --weights yolov5s.pt --include onnx --imgsz 640 /usr/src/tensorrt/bin/trtexec \ --onnxyolov5s.onnx \ --saveEngineyolov5s_fp16.engine \ --fp16 \ --workspace1024关于--workspace单位是 MB。Nano 内存本来就紧张别照着桌面显卡的教程写 8192那会直接 OOM。1024 到 2048 之间是比较稳的区间。编译过程在 Nano 上要十几到三十分钟如果你看到 OOM during engine build先关掉图形界面sudo systemctl set-default multi-user.target然后重启再把 swap 加大一般就能过了。编译出来的 engine一定要保存好我习惯在项目里建一个engines/目录专门放顺便记一下编译时的 TRT 版本号方便以后对照。7.3 连续跑二十分钟之后会发生什么这是纸面参数看不到的部分。Nano 是无风扇被动散热设计除非你自己加了风扇连续推理二十分钟左右SoC 温度会爬到 70 度以上然后开始热降频帧率可能出现 20% 到 30% 的下跌。如果你发现刚启动的时候很流畅跑一会儿就卡先摸一下散热片八成是这个问题。内存方面也要有预期。4GB 里系统占用大概 500MB 到 800MB带桌面TensorRT engine 加载后还要吃掉几百 MB再跑个 Python 进程加 OpenCV 的 bufferfree -h里 available 剩几百 MB 是常态。所以生产环境一定要关掉图形界面用 headless 模式跑能省下两三百 MB 内存和一部分 GPU 占用。还有一个反直觉的经验不是模型越小帧率越高。YOLOv5n 和 YOLOv5s 在 Nano 上的帧率差距比在桌面显卡上的差距要小因为当模型小到一定程度后瓶颈从算力转移到了内存带宽和数据搬运上。所以别一味追小模型先看实测数据。8. 那些让我重装过系统的坑以及怎么躲开8.1 apt upgrade 之后启动不了的根因我重装系统的四次里有两次是因为执行了全量升级。背后的原因前面提过JetPack 的 L4T 组件内核、dtb、驱动是一套整体版本严格对应。某些升级路径会把内核更新到一个和当前 dtb 不匹配的版本结果是启动阶段卡住屏幕上什么都不显示。预防手段很简单把关键包锁住。sudo apt-mark hold nvidia-l4t-kernel nvidia-l4t-kernel-dtbs nvidia-l4t-bootloader这样apt upgrade就不会动它们了。如果已经中招进串口控制台看日志或者在启动时进 U-Boot 选择旧的启动项把新装的内核卸载掉一般还能救回来。8.2 一张排查表顶十次瞎试下面这张表是我这几年在 Nano 上遇到的问题的汇总按现象到你该敲什么命令组织比按原因分类更实用现象优先排查方向命令或动作开机黑屏无输出供电、SD 卡、HDMI 线换圆孔电源重新刷卡接串口看 logls /dev/video*为空CSI 排线方向、模组型号、nvargus重插排线确认 IMX219/OV5647重启 nvargus-daemonimport cv2报错numpy 版本冲突或装了 pip 版 opencv卸掉 pip 版恢复系统包编译中途 Killed内存不足加 swapmake -j1或-j2跑模型花屏或重启供电不足触发掉电换 5V 4A 电源并短接 J48帧率跑一会儿就掉热降频检查温度加风扇TensorRT 报 engine 不兼容TRT 版本或硬件变了删掉旧 engine 重新编译8.3 给 SD 卡留一份体检报告第一次把系统调通、Demo 跑起来之后立刻做一次全盘备份。这件事花二十分钟能在后面无数次救你。# 在 PC 上操作先确认卡挂载已全部卸载 lsblk sudo umount /dev/sdb* sudo dd if/dev/sdb ofnano-golden.img bs4M statusprogress convfsyncconvfsync会强制把数据刷到磁盘避免命令返回了但文件还没写完的情况。镜像文件大小会和你卡容量相同32GB 卡大概产出 29GB 左右如果嫌大可以再用gzip压一下系统里全是零块压缩率通常能到 30% 以下。恢复的时候反过来把 img 写回卡就行几分钟就能回到一个完全调好的状态比重新走一遍安装调优流程快得多。我现在的习惯是给每个项目的板子都存一份调通后的黄金镜像换板子或者搞坏了直接刷回去。后续如果想继续往下走比较自然的方向是把目标检测和手势识别合成一个应用检测框住手之后只对手部区域跑关键点网络——这样能在同样的算力下把有效分辨率提高不少。前提是先把单条链路跑稳别一上来就上多模型流水线Nano 的内存会教你怎么做人。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。