Skip to main content

HRNet Human Pose Estimation

Run HRNet human pose estimation with the preinstalled image. The sample uses the QNN HTP backend on the DSP and publishes both an image with the rendered skeleton and human keypoints in the original image coordinate system.

This page covers image input only. QRB, GMSL, and USB camera input were not verified.

Pipeline

input_image.jpg
-> image_publisher -> /image_raw
-> HRNet image preprocessing
-> /qrb_inference_input_tensor
-> QNN HRNetPose inference
-> /qrb_inference_output_tensor
-> heatmap postprocessing and confidence filtering
-> /pose_estimation_results + /pose_estimation_points

Output Topics

TopicTypeDescription
/pose_estimation_resultssensor_msgs/msg/ImageResult image with keypoints and skeleton
/pose_estimation_pointsgeometry_msgs/msg/PolygonStampedHuman keypoint coordinates in the input image

Prerequisites

  • QIR SDK installed
  • GitHub and Hugging Face access from the Q900
  • At least 60 MB free under /opt/model

Install Dependencies

radxa@airbox$
sudo apt install -y \
ros-jazzy-qrb-ros-camera \
ros-jazzy-qrb-ros-nn-inference \
ros-jazzy-qrb-ros-tensor-list-msgs \
ros-dev-tools

Initialize rosdep before using it for the first time:

radxa@airbox$
sudo rosdep init
rosdep update

If sudo rosdep init reports that /etc/ros/rosdep/sources.list.d/20-default.list already exists, rosdep is already initialized; run only rosdep update.

Prepare the Source and Model

Step 1: Clone the Source

Use the workspace path from the official sample:

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

Step 2: Download the Model

radxa@airbox$
sudo mkdir -p /opt/model
sudo wget \
https://huggingface.co/qualcomm/HRNetPose/resolve/6011b6e69a84dad8f53fb555b11035a5e26c8755/HRNetPose.bin?download=true \
-O /opt/model/HRNetPose.bin

Verify the model:

radxa@airbox$
echo "f593694f4e8afecd8be7bc5304ea9408c33b99f412b5eb2493123ea718cb2838  /opt/model/HRNetPose.bin" | \
sha256sum --check

Expected output:

/opt/model/HRNetPose.bin: OK

Build from Source

Step 1: Install Source Dependencies

radxa@airbox$
cd ~/qrb_ros_sample_ws/src/qrb_ros_samples/ai_vision/sample_hrnet_pose_estimation
rosdep install --from-paths . --ignore-src --rosdistro jazzy -y \
--skip-keys "qrb_ros_tensor_list_msgs qrb_ros_nn_inference qrb_ros_camera"

Step 2: Build

radxa@airbox$
source /opt/ros/jazzy/setup.bash
colcon build --cmake-args -DBUILD_TESTING=OFF
source install/setup.bash

Expected output:

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

Run

radxa@airbox$
cd ~/qrb_ros_sample_ws/src/qrb_ros_samples/ai_vision/sample_hrnet_pose_estimation
source /opt/ros/jazzy/setup.bash
source install/setup.bash
export ROS_DOMAIN_ID=123
ros2 launch sample_hrnet_pose_estimation launch_with_image_publisher.py \
image_path:=/opt/ros/jazzy/share/sample_hrnet_pose_estimation/input_image.jpg

The launch file publishes the selected image at 10 Hz. The model_path argument is the directory containing HRNetPose.bin; its default is /opt/model/.

Expected Output

The model initializes and repeatedly publishes both image and keypoint results:

Loading model from binary file: /opt/model/HRNetPose.bin
/usr/lib/libQnnHtp.so initialize successfully
Qnn device initialize successfully
Initialize Qnn graph from binary file successfully
Inference init successfully!
Inference execute successfully!
Publisher pose_estimation_results&pose_estimation_points message

The /pose_estimation_results captured on the device is shown below:

HRNet human pose estimation result

Keypoint Order

/pose_estimation_points uses the following 1-based numbering:

IDBody PartIDBody Part
1Nose10Right Wrist
2Right Eye11Left Wrist
3Left Eye12Right Hip
4Right Ear13Left Hip
5Left Ear14Right Knee
6Right Shoulder15Left Knee
7Left Shoulder16Right Ankle
8Right Elbow17Left Ankle
9Left Elbow

The source publishes only points with confidence above 0.3. PolygonStamped does not include confidence values or explicit keypoint IDs, so array positions fully match this table only when all 17 points are emitted.

Validation

Check both result topics from another terminal:

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

The default test image should produce 17 polygon.points. Every x coordinate should be between 0 and 668, and every y coordinate should be between 0 and 892.

Stop

Press Ctrl + C in the terminal running the sample.

When stopped during continuous inference, the QNN container may exit with -11, and the Python node may print ExternalShutdownException. These errors occur during shutdown and do not affect results published earlier; confirm that the related processes have exited.

Limitations

  • Only the preinstalled image input was verified. QRB, GMSL, and USB camera input were not tested.
  • Cross-device rqt display was not verified. Only local Q900 inference and result-topic publication were validated.
  • The points message does not contain confidence, names, or explicit IDs; downstream applications must interpret coordinates using the output order and point count.

    You need to be logged into GitHub to post a comment. If you are already logged in, please ignore this message.

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