Skip to main content

端侧商品图像识别方案:搭建、部署与实测数据

先看这里

识别结果不是法定计量,不能作为计价或法定计数的依据。

这套方案是干什么的​

一台摄像头对着收银台传送带或货架正面。画面里的每件商品被框出、裁下、变成 512 维向量,再到已注册 SKU 的商品库里检索。收银台侧输出一份清单(SKU→数量,按 track id 聚合,同一件商品经过相机只计一次);货架侧输出货位状态(ok、empty、wrong_sku、unknown,按 planogram 位置聚合)。每帧一条 MQTT 消息带出这些结果。

门店上新品不用重训:给新 SKU 拍三到八张照片,发到管理端,商品库生成一个新的不可变版本。检测器是单类的,只回答「这里有一件商品」,不认识具体商品;嵌入器也不更新。

  • 选型与部署:可部署方案页
  • 开源地址:暂无。本包没有 intro.links.github,打包时代码在内部仓库。
  • 新增 SKU 拍 3–8 张照片,不用重训

    注册生成一个新的不可变商品库版本。注册图从 1 张加到 8 张,top-1 提高 28 个百分点(见性能与实测数据)。

  • 检测在 NPU 或 GPU 上运行

    RK3588 上 RKNN fp16 与 CPU 参考的框一致率 99.85%、p50 56.7 ms;Hailo-8 的 INT8 HEF p50 9.04 ms、一致率 94.77%;reComputer J40 系列(J4012)上 TensorRT fp16 p50 5.18 ms、一致率 99.91%。

  • 自有摄像头与门店系统直接接入

    任意 RTSP / USB 摄像头;收银机从 MQTT 读 SKU→数量,补货系统读缺货与错放货位,HTTP API 提供事件查询与商品库管理。

  • 数据不出现场

    摄像头、识别主机、管理端主机都在本地,broker 也跑在管理端容器里。随包 broker 是匿名明文的,上线前加账号与 TLS。

管理界面​

上游包里有四张管理界面截图:事件列表、单事件逐框详情、商品库、收银台与货架看板。四张都由上游 web_demo 工具用合成夹具生成,里面的 SKU、相似度与事件是测试数据,只展示界面布局。

货架看板上的三种状态​

货架判定在 reComputer RK3588 系列与 reComputer R2000 系列 + Hailo-8 上实测过。看板对每个货位给出三种状态之一:摆放正确、缺货、错放。

货架看板:所有货位与商品库一致,标记为摆放正确
同一货架取走一件后,该货位转为缺货
放了一件不属于这个货位的商品,该货位标记为错放并给出实际匹配到的 SKU

三种状态连续切换的过程:

同一货架依次经过摆放正确、缺货、错放三种状态

收银台链路输出逐件商品的轨迹:

收银台画面上的商品跟踪轨迹与逐件识别结果

以上画面来自 edge-retail-recognition/evaluation/runs/2026-09-07-runtime-* 两轮真机运行,商品为项目自购实物,不来自任何数据集。

需要哪些硬件​

每个站点四样:摄像头、识别主机、管理端主机,以及一台 x86_64 转换机(每个模型用一次)。

① 摄像头 — 任意一台装在收银台上方或正对货架的 RTSP / USB 摄像头,上面不跑任何程序。输入尺寸编译进产物:收银台 640²,货架 1280²。

② 识别主机 — 三个套餐的区别在这里:

主机这套硬件上测过什么什么时候选它
reComputer Industrial R2035-12reComputer Industrial R2035-12(Hailo-8,26 TOPS)
检测上 NPU,嵌入跑在四个 A76 核上
两段都测了:检测 9.04 ms,嵌入每裁剪 91.95 ms检测与嵌入都要有实测数据
reComputer RK3588-30reComputer RK3588-30
检测上 Rockchip NPU,嵌入在 CPU 或 NPU
检测框一致率 99.85%,56.7 ms;嵌入上 NPU 后,20 SKU 货架回放从检出到结果发出 p50 924 ms已经在用 Rockchip 板卡,或相机对着货架。RK3576 工具链相同
reComputer Super J4012reComputer Super J4012(Orin NX 16GB) 或 reComputer Super J3011(Orin Nano 8GB)
TensorRT 路线,检测与嵌入都上 GPU
J4012:检测 5.18 ms,嵌入每裁剪 4.23 ms;2956 帧收银回放 0 丢帧已经在用 Jetson,或要整条链路跑在一台机器上

数字都是该行硬件上的实测。

③ 管理端主机 — 你自己的 amd64 或 arm64 Linux 机器,装 Docker,不需要 GPU,每台识别设备都能访问到。它跑三个容器:注册/查询服务、管理界面、MQTT broker。两个容器镜像都在这台主机上从上游仓库构建,不从 registry 拉取。

④ 一台 x86_64 转换机 — rknn-toolkit2 与 Hailo Dataflow Compiler 都不在目标板上运行。每个模型转换一次,部署时不用重复。

选型排他边界​

  • 商品 SKU 规模与检索延迟:单机嵌入向量库若超过 200 个 SKU,端侧线性比对时延会增加。超过 500 SKU 的大型便利店建议在本地部署近似近邻检索(ANN)或上云比对。
  • 无 NPU 运行商品嵌入:请勿在纯 CPU 模式下运行商品特征提取嵌入模型(单裁剪耗时超 900ms),务必确保编译上板至 NPU 或 TensorRT。

现场怎么部署​

先定产物与机位,再装软件,软件部分每个套餐四步。

一、装硬件:先定产物,再定机位​

输入尺寸在转换时确定

输入尺寸编译进产物,运行时不能改。用 640² 的产物看货架会漏掉远端商品;换到 1280² 后 SKU-110K test 上的小目标 mAP50-95 从 17.49 升到 26.88。先确定是收银台还是货架,再把机位装到商品在画面里占比合适的位置。

Hailo-8 套餐的嵌入是每个框一次 CPU 推理。按 reComputer R2000 系列上实测的每裁剪 91.95 ms 算,五件商品的篮子约半秒;货架一帧按实测密度 157.6 个框算约 14 秒。这个套餐做货架部署要抽帧或按货位采样。 reComputer J40 系列(J4012)上嵌入在 GPU 上,每裁剪 4.23 ms。

二、装软件:四步​

逐设备的操作步骤在可部署方案页,这里只列流程。三个套餐都是同样四步:


  1. 拉起管理端 — 注册服务、界面与 broker 跑在管理端主机上,部署时写入角色 token 表。没有默认 token,不允许匿名读,表为空时服务拒绝启动。
  2. 放好嵌入模型 — 把 DINOv2 ONNX 放到管理端挂载的位置,并把 RETAIL_EMBEDDER 从占位实现切走。上游默认是 fake,它把图片字节哈希成向量;GET /api/health 不报告这一点,唯一的症状是注册正常但每次检索都返回错误的 SKU。
  3. 注册 SKU — 每个 3 到 8 张照片,至少正面、背面、侧面,两种光照。少于三张会被拒绝;同一个 sku_id 返回 409,除非显式 replace=true。
  4. 在板上转换并核对检测器 — 在 x86_64 主机上转换,把产物拷到板上,再与 CPU 参考做一次一致性核对。

每个套餐四步预留约 90 分钟,另加管理端主机上的容器构建时间。

确认嵌入模型已接上。 一次识别会在事件流里留下一条完整记录:货位、匹配到的 SKU、相似度与逐框坐标。fake 实现下相似度分布会明显异常。

一条识别事件的完整字段:货位、匹配 SKU、相似度与逐框坐标

有哪些接口​

出口全在管理端主机上:1883 的 MQTT,以及 8089 与 8080 两个 HTTP 接口,都在本地网络内,除 broker 外都走同一个 token 校验。

  • 收银机 / POS 订阅 retail/v1/events,读 summary.items:这一帧的 SKU→数量映射,不需要解析逐框数组。
  • 补货或货架稽核系统 从同一条消息里读 summary.empty_slots 与 summary.wrong_slots。
  • 需要追溯某次判断的系统 读 detections[]:每个框带 track_id、归一化 bbox、sku_id、similarity、top2_margin、ocr 块与 fallback 标志。

完整的主题与 payload​

接口 / 端口内容说明
MQTT retail/v1/events,1883event_id、scene、timestamp、gallery.{version,sha256}、detections[]、summary.{items,empty_slots,wrong_slots}、models.{detector_sha256,embedder_sha256}一帧一条,不逐框发
HTTP /v1/gallery/skus,8089POST 提交 sku_id、显示名、别名、许可字段与 3–8 张图 → 生成一个新的不可变版本同 sku_id 返回 409,除非 replace=true
HTTP /v1/gallery、/v1/gallery/{version}、/v1/gallery/current/download、/v1/gallery/rollback/{version},8089版本列表、单版本 manifest、带 SHA256SUMS 的 tar.gz,以及切换前重校目标 SHA 的回滚回滚不产生新版本
HTTP /api/events、/api/events/{id}、/api/summary,8080按场景/SKU/设备/时间过滤的事件列表、逐框详情、看板汇总只读 API,同一个 token 校验

similarity 要连同同一条消息里的 gallery.version、gallery.sha256 与模型哈希一起看。 两个不同嵌入器产生的向量不可比,混用时表现为什么都识别不出来;每条消息都带上这四项。

鉴权是 Bearer <token>,角色 viewer < operator < admin。broker 随包配置为匿名明文,任何能访问 1883 端口的人都能写入伪造的识别事件。

性能与实测数据​

检测,设备实测​

设备产物p50 / p95与 CPU 参考的框一致率
reComputer R2000 系列 + Hailo-8INT8 HEF,640²9.04 / 9.10 ms94.77%(200 张),94.68%(300 张)
reComputer RK3588 系列RKNN fp16,640²56.7 / 89.5 ms99.85%
reComputer RK3588 系列RKNN INT8,640²26.0 / 33.2 ms98.35%
reComputer RK3576 系列RKNN fp16,640²,双核51.05 / 54.18 ms99.91%
reComputer J40 系列(J4012)TensorRT fp16,640²5.18 / 5.28 ms99.91%
reComputer J30 系列(J3011)TensorRT fp16,640²5.88 / 8.89 ms99.27%(收银台帧)

条件:一致率按 IoU ≥ 0.5 与 CPU 参考比对;RK3588、RK3576 与 J4012 用同一批 50 张 SKU-110K 图,J3011 用 50 张收银台帧。Hailo 单流吞吐 110.4 fps(hailortcli benchmark 110.64 fps,纯硬件时间 8.21 ms,多出的 0.8 ms 是 Python vstream 往返)。reComputer R2000 系列上端到端(含 letterbox、输出拼接、解码与 NMS)p50 18.74 ms / p95 24.25 ms:对约 160 个框做纯 numpy 逐类 NMS,耗时超过推理本身。

复现:evaluation/runs/2026-09-06-det-hef/、evaluation/runs/2026-09-06-det-rk3588-radxa/、evaluation/runs/2026-09-07-embed-rknn-rk3576/、evaluation/runs/2026-09-07-jetson-trt/、evaluation/runs/2026-09-08-orin-nano-acceptance/

嵌入,设备实测​

设备变体单裁剪 p50 / p95相对 fp32 的检索代价
reComputer R2000 系列(CPU,4 线程)DINOv2-small,动态量化 INT891.95 / 105.98 ms全部 7 个实测档位上均在 0.65pp 以内
reComputer R2000 系列(CPU,4 线程)DINOv2-small,fp32180.75 / 233.41 ms基线
reComputer RK3588 系列(NPU)DINOv2-small,RKNN fp1648.68 / 49.86 ms21 个指标最大差 0.85pp
reComputer RK3576 系列(NPU,双核)DINOv2-small,RKNN fp1656.38 / 62.17 ms21 个指标最大差 0.36pp
reComputer J40 系列(J4012)DINOv2-small,TensorRT fp164.23 / 4.69 ms21 个指标最大差 0.24pp
reComputer J30 系列(J3011)DINOv2-small,TensorRT fp165.06 / 7.64 ms21 个指标最大差 0.21pp

条件:21 个指标是 Grocery Store Dataset 4 个注册档位与 Products-10K 3 个注册档位上的 top-1、top-5 与开集 AUROC。CPU 上只量化权重几乎不损失检索精度,激活一起量化则损失明显。

复现:evaluation/runs/2026-09-06-embed-small/ §8、evaluation/runs/2026-09-07-embed-rknn/、evaluation/runs/2026-09-07-embed-rknn-rk3576/、evaluation/runs/2026-09-07-jetson-trt/、evaluation/runs/2026-09-08-orin-nano-acceptance/

整链路回放与货架裁剪,设备实测​

设备场景结果条件
reComputer J40 系列(J4012)收银台回放检出到结果发出 p50 22.3 ms / p95 42.8 ms;2956 帧 0 丢帧录制视频回放,30 SKU 商品库,检测、嵌入、检索与 MQTT 上报在同一台设备上
reComputer J30 系列(J3011)收银台回放6726 帧(2.27 轮)0 丢帧,84 个事件全部发布同一段录制视频与商品库
reComputer RK3588 系列货架回放检出到结果发出 p50 924 ms / p95 1153 ms;704 张货位裁剪 top-1 541/704,与 CPU fp32 参考相同20 SKU,检测与嵌入都用 RKNN fp16 上 NPU
reComputer RK3576 系列货架裁剪704 张 top-1 76.28%(CPU fp32 76.99%),同 SKU 一致率 99.29%;嵌入单裁剪 p50 61.0 ms同一批 704 张裁剪,检测与嵌入都用 RKNN fp16

复现:evaluation/runs/2026-09-07-jetson-trt/、evaluation/runs/2026-09-08-orin-nano-acceptance/、evaluation/runs/2026-09-08-rk3588-console-acceptance-020/、evaluation/runs/2026-09-08-rk3576-acceptance/

检索与检测准确率(非设备端)​

配置结果数据集
DINOv2-base,每 SKU 8 张注册图top-1 84.67% / top-5 96.66%Grocery Store Dataset,81 类,fp32
DINOv2-small,每 SKU 8 张注册图top-1 79.11%同上
DINOv2-small,每 SKU 1 张注册图top-1 51.11%同上
DINOv2-base,每 SKU 8 张,留出 SKUtop-1 78.92%Products-10K 留出集,类别多得多
检测器,640²mAP50-95 52.84,mAP50 88.26SKU-110K test
检测器,1280²mAP50-95 56.32SKU-110K test

SKU-110K 的公开成绩是 mAP50-95 58.0(DenseDet,Cascade R-CNN + ResNeXt-101)到 58.7(arXiv 2007.11946)。640² 的 mAP50 为 88.26 而 mAP50-95 为 52.84:框能找到,定位精度不足。注册视角数对检索影响最大:同一模型、同一数据集上,每 SKU 1 张 51.11%,8 张 79.11%。

复现:evaluation/runs/(嵌入评测 evaluation/eval_embedder.py)

运行时与关键参数​

设备检测器嵌入器模型怎么到设备上
reComputer RK3588 / RK3576 系列NPU 上的 .rknn,fp16 或 INT8CPU 上的 onnxruntime,或 NPU 上的 RKNN fp16在 x86_64 主机上用 rknn-toolkit2 2.3.2 转换;toolkit 版本必须与板上 librknnrt.so 匹配
reComputer R2000 系列 + Hailo-8NPU 上的 INT8 .hefCPU 上动态量化 INT8 的 DINOv2-small在 x86_64 主机上用 Hailo Dataflow Compiler 编译后拷到板上
reComputer J40 / J30 系列(Jetson Orin)TensorRT fp16(GPU)TensorRT fp16(GPU)部署时在设备上从 ONNX 构建 engine,J3011 上检测 427 s、嵌入 132 s

检测器是单类 YOLOX-Tiny(640² 或 1280²);嵌入器是在电商商品图上用 ArcFace 微调的 DINOv2,base(348 MB fp32)或 small(23.5 MB INT8),每个裁剪输出一个 512 维向量;SKU 身份只在版本化商品库的 FAISS 余弦检索里。

  • 输入尺寸:收银台 640²,货架 1280²,编译进产物,运行时不能改
  • 注册图:每个 SKU 3–8 张,少于三张拒绝
  • RETAIL_EMBEDDER:上游默认 fake(把图片字节哈希成向量),部署时必须切到 DINOv2 ONNX

已知退化​

  • Hailo-8 套餐上嵌入是每个框一次 CPU 推理:按每裁剪 91.95 ms,五件商品的篮子约半秒,货架一帧(157.6 个框)约 14 秒,货架部署要抽帧或按货位采样。
  • DINOv2 嵌入器在 Hailo-8 上的两次量化都没有得到可用结果(其中一次所有图映射到同一个向量),所以 Hailo-8 套餐的嵌入留在 CPU。
  • 检测与嵌入共用一块 GPU 时,reComputer J40 系列(J4012)进程内检测 p50 从单独运行的 5.18 ms 升到 8.76 ms,嵌入从 4.23 ms 升到 5.37 ms。
  • 静态 QDQ INT8(激活也量化)检索掉 3.78–9.96 个百分点,不可用。
  • rknn-toolkit2 与 librknnrt.so 版本不匹配时可能照常加载并给出错误数值;每次转换后与 CPU 参考做一致性核对。
  • 用 640² 产物看货架会漏掉远端商品;SKU-110K 小目标 mAP50-95 在 640² 为 17.49,1280² 为 26.88。
  • 两个不同嵌入器的向量不可比,混用时什么都识别不出来。
  • 设备端拉取商品库版本、校验、原子切换的运行时未实现,新注册的 SKU 不会自动下发到设备。
  • OCR 重排与 VLM 兜底未实现:消息结构里已有 top2_margin、ocr、fallback 块,代码未实现。

下一步​

  • 测收银台计数准确率与货架货位准确率,作为验收指标。
  • 实现设备端拉取商品库版本、校验、原子切换的运行时,让新注册的 SKU 自动下发到设备。

数据与素材出处​

本包不含任何模型权重与数据集图片。 下面的限制会被基于这些数据训练出来的模型继承,商用部署需要用可商用数据重训检测器与嵌入器。

资产许可 / 使用范围说明
检测器权重(训练于 SKU-110K)Trax 许可:学术与非商用;第 (iii) 条禁止衍生作品use_scope: academic-only、redistributable: false
嵌入器权重(微调于京东 Products-10K)非商用研究与教育use_scope: non-commercial、redistributable: false
facebook/dinov2-base、facebook/dinov2-small 骨干Apache-2.0骨干可商用,限制来自训练数据
Grocery Store DatasetMIT只用于检索评测;这一组里唯一可商用的数据集
RPC、Unitail-OCR、GroZi-120CC BY-NC-SA 4.0 / 仅学术 / 许可需向数据集方确认出现在上游评测计划里,属非商用范围
项目自身代码Apache-2.0

逐产物字段(license_id、use_scope、redistributable、source_revision、sha256)在上游的 model card 里;摘要在包内 gallery/ATTRIBUTION.md。可部署方案页上的架构图按本包的设备清单自绘。

Loading Comments...