跳到主要内容

ResNet101 图像分类

使用 Qualcomm 随示例提供的 glasses.jpg 运行 ResNet101 图像分类。示例将输入图片缩放为 224 x 224,通过 QNN HTP 后端在 DSP 上执行推理,再将最高分类别发布为文本消息。

本文仅介绍本地图片输入,未验证 QRB、GMSL 或 USB 摄像头输入。

管线

glasses.jpg
-> image_publisher -> /image_raw
-> 缩放为 224 x 224
-> /qrb_inference_input_tensor
-> QNN ResNet101 推理
-> /qrb_inference_output_tensor
-> ImageNet 标签映射
-> /resnet101_output

ROS 2 话题

话题类型说明
/image_rawsensor_msgs/msg/Image输入图片
/qrb_inference_input_tensorqrb_ros_tensor_list_msgs/msg/TensorList预处理后的张量
/qrb_inference_output_tensorqrb_ros_tensor_list_msgs/msg/TensorListQNN 推理输出张量
/resnet101_outputstd_msgs/msg/StringImageNet 分类标签

Qualcomm 用户指南的话题表将输出写为 /resnet101_results,但当前 Debian 软件包和源码实际发布的话题均为 /resnet101_output

前提条件

  • 已完成 QIR SDK 安装
  • Q900 可以访问 GitHub 和 Hugging Face
  • /opt/model 至少有 50 MB 可用空间

使用 Debian 软件包运行

步骤 1:安装示例

radxa@airbox$
sudo apt install -y ros-jazzy-sample-resnet101

步骤 2:校验模型并修复 ImageNet 标签文件

安装后先校验自动下载的模型。当前 ros-jazzy-sample-resnet101 1.0.1 的安装后脚本使用了已经迁移的 GitHub 路径,可能会留下 0 字节的 /opt/model/imagenet_labels.txt,因此还需从新路径重新下载标签:

radxa@airbox$
echo "bfed3e96598ed276600a1e53c8a59decd287258881cd9849141a20a76e0da803  /opt/model/ResNet101_w8a8.bin" | \
sha256sum --check
sudo wget \
https://raw.githubusercontent.com/quic/ai-hub-models/refs/heads/main/src/qai_hub_models/labels/imagenet_labels.txt \
-O /opt/model/imagenet_labels.txt
echo "e697a491aa735cc6c2aaf982f8e86e8fc7b0a1ea7750a2cc6a2bdfc1e109012f /opt/model/imagenet_labels.txt" | \
sha256sum --check

预期输出:

/opt/model/ResNet101_w8a8.bin: OK
/opt/model/imagenet_labels.txt: OK

步骤 3:启动示例

radxa@airbox$
source /opt/ros/jazzy/setup.bash
export ROS_DOMAIN_ID=123
ros2 launch sample_resnet101 launch_with_image_publisher.py

launch 文件默认以 10 Hz 发布 /opt/ros/jazzy/share/sample_resnet101/glasses.jpg,并使用 /opt/model/ResNet101_w8a8.bin。也可以指定其他本地图片:

radxa@airbox$
ros2 launch sample_resnet101 launch_with_image_publisher.py \
image_path:=<your-local-image-path>

从源码构建

步骤 1:安装依赖

radxa@airbox$
sudo apt install -y \
ros-dev-tools \
ros-jazzy-rclpy \
ros-jazzy-sensor-msgs \
ros-jazzy-std-msgs \
ros-jazzy-cv-bridge \
ros-jazzy-ament-index-python \
ros-jazzy-qrb-ros-tensor-list-msgs \
ros-jazzy-image-publisher \
ros-jazzy-qrb-ros-nn-inference \
ros-jazzy-qrb-ros-camera \
python3-opencv \
python3-numpy

步骤 2:准备模型和标签

radxa@airbox$
sudo mkdir -p /opt/model
sudo wget \
https://huggingface.co/qualcomm/ResNet101/resolve/121564046ebb2353d4a0aa67bf89c11e0c8e80d9/ResNet101_w8a8.bin?download=true \
-O /opt/model/ResNet101_w8a8.bin
sudo wget \
https://raw.githubusercontent.com/quic/ai-hub-models/refs/heads/main/src/qai_hub_models/labels/imagenet_labels.txt \
-O /opt/model/imagenet_labels.txt

校验两个文件:

radxa@airbox$
echo "bfed3e96598ed276600a1e53c8a59decd287258881cd9849141a20a76e0da803  /opt/model/ResNet101_w8a8.bin" | \
sha256sum --check
echo "e697a491aa735cc6c2aaf982f8e86e8fc7b0a1ea7750a2cc6a2bdfc1e109012f /opt/model/imagenet_labels.txt" | \
sha256sum --check

步骤 3:克隆源码

使用官方示例的工作区路径:

radxa@airbox$
mkdir -p ~/qrb_ros_ws/src && cd ~/qrb_ros_ws/src
git clone https://github.com/qualcomm-qrb-ros/qrb_ros_samples.git

步骤 4:构建

radxa@airbox$
cd ~/qrb_ros_ws/src/qrb_ros_samples/ai_vision/sample_resnet101
source /opt/ros/jazzy/setup.bash
colcon build
source install/setup.bash

预期输出:

Starting >>> sample_resnet101
Finished <<< sample_resnet101
Summary: 1 package finished

步骤 5:运行源码版本

radxa@airbox$
cd ~/qrb_ros_ws/src/qrb_ros_samples/ai_vision/sample_resnet101
source /opt/ros/jazzy/setup.bash
source install/setup.bash
export ROS_DOMAIN_ID=123
ros2 launch sample_resnet101 launch_with_image_publisher.py

预期输出

模型完成初始化并持续执行推理:

Loaded 1000 class labels.
/usr/lib/libQnnHtp.so initialize successfully
Qnn device initialize successfully
Initialize Qnn graph from binary file successfully
Inference init successfully!
Inference execute successfully!

验证

在另一个终端中检查实际输出话题:

radxa@airbox$
export ROS_DOMAIN_ID=123
source /opt/ros/jazzy/setup.bash
ros2 topic info /resnet101_output -v
ros2 topic echo /resnet101_output --once

默认 glasses.jpg 的分类结果应为:

data: sunglass
---

Debian 软件包 1.0.1 的输出可能在 sunglass 后显示额外换行,这是标签读取方式造成的格式差异,不影响分类结果;当前源码版本会移除该换行。

停止

在运行示例的终端中按 Ctrl + C

连续推理期间停止时,QNN 容器可能以 -11 退出,Python 节点也可能打印 ExternalShutdownException。这些错误发生在关闭阶段,不影响此前已发布的分类结果;确认相关进程退出后即可。

限制

  • 本次仅验证 Qualcomm 随示例提供的本地图片,未验证摄像头输入。
  • 未验证跨设备查看话题,仅验证 Q900 本地推理和结果发布。
  • ResNet101 仅能输出 ImageNet 1000 类标签,不会返回目标位置或检测框。

    您需要登录 GitHub 才能发表评论。如果您已登录,请忽略此消息。

    Radxa-docs © 2026 by Radxa Computer (Shenzhen) Co.,Ltd. is licensed under CC BY 4.0