imx8mp-npu-pose — single-person pose estimation on the i.MX8M Plus NPU
Prerequisites: Avocado CLI (>=0.26.0), Docker, a ucm-imx8m-plus board with a
USB webcam, and the eIQ ML stack in your feed (packagegroup-avocado-imx-ml). A
display is optional — the browser preview works headless.
1. Fetch the model + calibration images
./fetch-model.sh # MoveNet SavedModel -> app/build/movenet, ~40 images -> app/build/rep
For real accuracy, drop frames with people (in your scene's lighting/poses) into
app/build/rep/ and re-run the build.
2. Build (quantization happens here, in the SDK)
avocado build
app-compile.sh runs in the SDK: it uv pip installs TensorFlow 2.16, runs
quantize-model.py to produce a per-tensor INT8 movenet_int8.tflite, and
app-install.sh copies it into the app extension. TensorFlow is not shipped to
the target.
3. Provision
avocado provision -r dev # then flash per your board (uuu-emmc / sd)
4. View it
- Browser (headless or not): open
http://<board-ip>:8080/— live camera with the skeleton overlaid. - HDMI display: if a KMS display + weston are up, the skeleton renders there automatically too.
- Journal:
journalctl -fu imx8mp-npu-poseshows FPS + visible-keypoint count.
Confirm the NPU is doing the work:
lsmod | grep galcore 2>/dev/null; ls -l /dev/galcore # NPU present
journalctl -u imx8mp-npu-pose | grep -i "vx delegate" # error_during_* = 0
5. NPU vs CPU
systemctl set-environment USE_NPU=1 && systemctl restart imx8mp-npu-pose # NPU
systemctl set-environment USE_NPU=0 && systemctl restart imx8mp-npu-pose # CPU
The INT8 MoveNet should run materially faster on the NPU. Equal FPS ⇒ the model fell back to CPU (check the journal for VX-delegate errors / per-op fallback).
Troubleshooting
- No skeleton, "0/17 keypoints": no person in frame, or
SCORE_THRESHtoo high (systemctl set-environment SCORE_THRESH=0.2). Stand back so your whole body is in the (square-cropped) frame. - Wrong camera: auto-detect picks the first real capture node; override with
CAMERA_DEVICE=/dev/videoN. - Skeleton offset/mirrored: coordinate mapping assumes the square crop — if
you change
PREVIEW_SIZEor the crop, re-check the mapping inon_draw. - Black screen on HDMI: that's the display path, not pose — see the
imx8mp-npu-nnstreamernotes (needs a KMS display + weston). The web preview sidesteps it entirely.