超市商品图像识别 — 部署指南

套餐

Rockchip NPU —— RK3588 / RK3576

reComputer RK3588 或 RK3576 在 NPU 上运行商品检测和嵌入,一台 Linux 服务器运行注册服务、管理界面、MQTT broker 和商品库。

  • 服务器: 一台装有 Docker 的 Linux 服务器,不需要 GPU。
  • 摄像头: RTSP 或 USB 摄像头,对准收银台或货架。
  • 模型转换: 一台 x86_64 机器,rknn-toolkit2 不能在板卡上运行。
  • 模型许可: 检测器和嵌入模型仅限非商用,不随本方案提供;商用部署需要用自采或许可宽松的数据重训。
1

部署注册管理端

在服务器上启动注册服务、管理界面和 MQTT broker,并设置角色 token。

前置条件
  • 一台装有 Docker 和 compose 插件的 Linux 服务器,识别设备能访问到它。
  • 至少设置一个 admin token,服务不允许匿名访问。
  • 需要从本地网络之外访问管理界面时,在前面加一个 TLS 反向代理。
  • 默认使用已发布的镜像;使用自建镜像时覆盖 RETAIL_SERVER_IMAGERETAIL_WEB_IMAGE
故障排查
现象处理
compose 运行前提示 "MISSING: <image>"检查服务器能否访问镜像仓库;使用自建镜像时先在本机构建。
找不到 docker compose安装 docker-compose-plugin
匿名 GET /v1/gallery 返回 200token 校验没有生效,停止使用并检查配置。
带 admin token 的 GET /v1/gallery 返回空库首次注册前属正常。
8089 端口被占用修改服务端口,设备端配置使用同一个端口。
部署方式

部署到识别设备可以访问的一台 Linux 服务器。

部署时需要填写(在 SenseCraft Solution 应用里填)
  • 管理端主机 IP*
  • SSH 用户名*默认 ubuntu
  • SSH 密码*
  • 注册服务镜像*默认 sensecraft-missionpack.seeed.cn/solution/edge-retail-console-server:0.2.0

    已发布在 sensecraft-missionpack.seeed.cn/solution/edge-retail-console-server:0.2.0 (linux/amd64 + linux/arm64)。要用自建镜像的话,在这台主机上用上游仓库的 platforms/console/Dockerfile.server 构建,把构建出的 tag 填在这里。 registry 给得出 digest 就钉 digest:一个构建写出的商品库向量,只与同一个嵌入模型、 同一套预处理写出的向量可比,对不上的症状是"什么都认不出来",不是显眼的版本错误。

  • 管理界面镜像*默认 sensecraft-missionpack.seeed.cn/solution/edge-retail-console-web:0.1.0

    已发布在 sensecraft-missionpack.seeed.cn/solution/edge-retail-console-web:0.1.0 (linux/amd64 + linux/arm64)。要自建的话,先构建 SPA (`npm --prefix web/ui ci && npm --prefix web/ui run build`), 再用 platforms/console/Dockerfile.web 构建这个镜像。镜像里不跑 npm。

  • Admin Token*

    可以注册 SKU、替换 SKU、回滚商品库。发给有权决定"商品目录里有什么"的人。

  • Operator Token

    只读权限,外加设备侧的上报角色。不能改商品库。

  • Viewer Token

    只读——事件、汇总、商品库版本。不能注册任何东西。

  • 注册服务端口*默认 8089

    设备从这个端口拉商品库。它必须对每一台识别设备可达,不只是对浏览器可达。

  • 管理界面端口*默认 8080

    在本地网络之外能访问它之前,先在前面放一个终止 TLS 的反向代理。共享 bearer token 走明文 HTTP 等于没有鉴权。

  • MQTT 端口*默认 1883

    随包的 broker 配置是匿名明文,config/mosquitto.conf 开头就写了这一条。 任何能访问这个端口的人都能往 retail/v1/events 上灌伪造事件。只能用于台面测试—— 离开实验台之前先加账号与 TLS。

2

放置嵌入模型

把 DINOv2-base 嵌入模型放到管理端的模型目录,并启用它。

前置条件
  • 步骤 1 的管理端已部署。
  • dinov2b_arcface_products10k_224_b1.onnx(348 MB,sha256 01ae07d10f638a2ebeb85100325ad79765a325d1026b728b60f1ee106e76eaae),需自行获取,仅限非商用。
  • 服务器上 350 MB 可用空间。
故障排查
现象处理
注册成功,但每次检索都返回错的 SKU嵌入模型没有启用。设置 RETAIL_EMBEDDER=onnx,重启服务,然后重新注册所有 SKU。
设置 RETAIL_EMBEDDER=onnxserver 容器立刻退出确认 RETAIL_EMBEDDER_ONNX 已填写,文件在 assets/console/models/ 里且文件名一致。
换模型前后注册的商品库对不上不同模型的商品库不能混用,用新模型重新注册所有 SKU。
计划商用部署用自采或许可宽松的数据重训嵌入模型,并重建商品库。
3

注册 SKU

在管理界面的商品库中,为每个 SKU 上传 3 到 8 张图完成注册,每次注册生成一个新的商品库版本。

前置条件
  • 步骤 1 的 admin token。
  • 每个 SKU 3 到 8 张图,至少包括正面、背面、侧面,覆盖两种光照。
  • 先确定嵌入模型,之后更换需要重建所有商品库版本。
故障排查
现象处理
注册被拒,提示图片少于三张至少上传 3 张。
同一个 sku_id 返回 409需要替换时带 replace=true
出了新版本,但设备仍然认不出这个 SKU设备端拉取、校验并切换商品库版本的功能尚未实现。
top-1 明显偏低先增加每个 SKU 的注册图数量;仍偏低时用现场图片微调模型。
4

在 Rockchip 上转换并核对检测器

在 x86_64 主机上把检测器 ONNX 转成 .rknn,拷到板卡上。

前置条件
  • x86_64 机器装有 rknn-toolkit2 2.3.2、onnx 1.16.1、setuptools 低于 81。
  • toolkit 版本与板卡上 librknnrt.so 版本一致,不一致时可能加载成功但结果错误。
  • 检测器 ONNX,需自行获取,仅限学术与非商用。
  • 步骤 2 的嵌入模型 ONNX。
  • 设备端为检测和嵌入分配不同的 NPU 核:RETAIL_RKNN_DET_CORE_MASK=2RETAIL_RKNN_EMBED_CORE_MASK=01,不要用 AUTO
故障排查
现象处理
load_onnxonnx.mapping 上失败安装 onnx 1.16.1。
找不到 pkg_resources把 setuptools 降到 81 以下。
INT8 一致率明显低于 98%校准图从整个验证集等间隔抽取,不要按文件名取前 N 张。
板卡上没有 cv2 和 PIL在其他机器上做 letterbox 预处理,打包成 (N, 640, 640, 3) uint8 BGR 的 .npy;设备端只需要 numpy 和 rknnlite。
5

验证注册、检索与设备产物

验证管理端注册与下载,并核对转换后的模型与 CPU 结果一致。

前置条件
  • 步骤 1 到 4 已完成。
  • 上游仓库克隆,已执行 uv sync
  • 自己 SKU 的照片,使用未注册过的角度拍摄。
故障排查
现象处理
检测框一致率远低于参考值检查解码路径和输出布局。
软件闭环通过但板卡上不工作软件闭环只验证协议,板卡问题按步骤 4 排查。
商品库在服务器上校验通过、在设备上不通过对比两边的 sha256,重新传输文件。
部署完成后

快速验证

  • uv run python tools/verify_software_loop.py 通过。
  • 管理端带 admin token 时每注册一次版本号加一,不带 token 时返回 401 或 403。
  • GET /v1/gallery/current/download 返回的 tar.gz 中 SHA256SUMS 校验通过。
  • .rknn 与 CPU 结果的检测框一致率(IoU ≥ 0.5):fp16 接近 99.85%,INT8 接近 98.35%。

后续步骤

  • 用自己货架或收银台的数据微调两个模型。
  • 设备端进程 platforms/rk3588/runtime.py(配置 platforms/rk3588/runtime.yaml)串联检测、嵌入、检索与上报,本套餐不负责部署和托管它。
  • 用真实摄像头和门店流量测量端到端延迟。