模型:
iic/cv_resnet50_product-bag-embedding-models(ModelScope) 任务: Product Retrieval Embedding — 手提包图片 → 512 维嵌入向量 框架: PyTorch + ONNX (目标检测) + Ascend NPU 硬件: 华为 Ascend 910 (NPU) / x86-64 (CPU)
| 组件 | 版本要求 | 备注 |
|---|---|---|
| Python | ≥ 3.10 | |
| torch | 2.9.0 | |
| torch_npu | 2.9.0 | Ascend NPU 插件 |
| modelscope | ≥ 1.35 | 模型下载与加载 |
| onnxruntime | 当前环境版本 | 用于 YOLOX 目标检测 |
| CANN | 8.0.RC3 | 昇腾 AI 处理器软件包 |
| Ascend NPU 驱动 | 当前环境版本 | npu-smi info 确认 |
# 安装 Python 依赖
pip install modelscope opencv-python-headless onnxruntime
# 确认 NPU 可用
python3 -c "import torch; import torch_npu; print(torch.npu.is_available())"# 通过 ModelScope SDK 自动下载
python3 -c "from modelscope import snapshot_download; snapshot_download('iic/cv_resnet50_product-bag-embedding-models')"模型缓存路径: ~/.cache/modelscope/hub/models/iic/cv_resnet50_product-bag-embedding-models/
# 进入项目目录
cd /opt/atomgit/product-bag-embedding
# 创建测试图片(已有则跳过)
python3 -c "
import cv2, numpy as np
img = np.ones((480, 640, 3), dtype=np.uint8) * 200
cv2.rectangle(img, (150, 100), (500, 400), (100, 150, 200), -1)
cv2.rectangle(img, (160, 110), (490, 390), (120, 170, 220), -1)
cv2.line(img, (200, 100), (250, 50), (80, 80, 80), 8)
cv2.line(img, (450, 100), (400, 50), (80, 80, 80), 8)
cv2.imwrite('assets/test_bag.jpg', img)
"
# CPU 推理
python3 inference.py --image assets/test_bag.jpg --device cpu
# NPU 推理
python3 inference.py --image assets/test_bag.jpg --device npu
# CPU + NPU 精度对比(带性能基准)
python3 inference.py --image assets/test_bag.jpg --device all --benchmarkpython3 scripts/accuracy_compare.py --image assets/test_bag.jpgproduct-bag-embedding/
├── assets/
│ └── test_bag.jpg # 测试图片(合成手提包图片)
├── logs/
│ ├── full_report.json # 完整推理报告(JSON, 含精度+性能数据)
│ ├── accuracy_report.json # 精度对比报告(JSON, 含误差分布详情)
│ └── inference_run.log # 完整运行日志(终端输出实录, 108行)
├── scripts/
│ └── accuracy_compare.py # 精度对比评测脚本
├── inference.py # 主推理脚本(CPU/NPU双后端)
├── run_all.sh # 一键复现脚本
└── README.md # 本文档| 参数 | 说明 | 默认值 |
|---|---|---|
--image | 输入图片路径 | assets/test_bag.jpg |
--model_dir | 模型路径 | ~/.cache/modelscope/... |
--device | 设备: cpu / npu / all | all |
--benchmark | 执行性能基准测试 | False |
--no_detection | 跳过目标检测 | False |
--output | 结果保存路径(JSON) | logs/inference_result_*.json |
输入图片 (BGR)
│
▼
┌─────────────────────────────────────┐
│ YOLOX 目标检测 (ONNX, CPU) │
│ 检测并裁剪手提包区域 │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 图像预处理 │
│ BGR→RGB → Resize 224x224 → │
│ Normalize(ImageNet) → NCHW │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ ResNet50 特征提取 (CPU / NPU) │
│ 输出 512 维 embedding 向量 │
└─────────────────────────────────────┘
│
▼
输出: {"embedding": [512维向量], "shape": [512]}import sys
sys.path.insert(0, "product-bag-embedding")
from inference import load_model, create_npu_model, run_inference
# 加载模型
model_det, model_feat_cpu = load_model("path/to/model")
# CPU 推理
result_cpu = run_inference(model_det, model_feat_cpu, "test.jpg", device="cpu")
print(result_cpu["embedding"]) # 512-dim vector
# NPU 推理
model_feat_npu = create_npu_model(model_feat_cpu)
result_npu = run_inference(model_det, model_feat_npu, "test.jpg", device="npu:0")
print(result_npu["embedding"]) # 512-dim vector测试时间: 2026-05-20 | 图片:
assets/test_bag.jpg(合成手提包)
| 指标 | CPU 值 | NPU 值 | 对比结果 |
|---|---|---|---|
| Embedding 维度 | 512 | 512 | — |
| 最大绝对误差 | — | — | 4.48e-05 |
| 平均绝对误差 | — | — | 1.22e-05 |
| 余弦相似度 | — | — | 1.0000000000 |
| allclose 检查 | — | — | ✅ 通过 (rtol=1e-3, atol=1e-3) |
绝对误差:
Min = 3.35e-08 Max = 4.48e-05
Mean = 1.22e-05 Median = 1.01e-05
Std = 9.31e-06
P90 = 2.57e-05 P99 = 3.70e-05
分布:
完全一致: 0 / 512
误差 > 1e-5: 258 / 512 │── 半数元素在此范围内
误差 > 1e-4: 0 / 512 │── 全部元素误差 < 1e-4
误差 > 1e-3: 0 / 512 │── 全部元素远低于阈值 维度 CPU 值 NPU 值 绝对误差 说明
------------------------------------------------------------------------
0 -0.02083722 -0.02083591 1.31e-06 ✓
1 0.02849168 0.02849949 7.81e-06 ✓
2 0.01743191 0.01742917 2.74e-06 ✓
3 -0.01979579 -0.01980022 4.43e-06 ✓
4 0.00650445 0.00648849 1.60e-05 ✓
5 -0.00091412 -0.00089983 1.43e-05 ✓
6 -0.01526569 -0.01526920 3.51e-06 ✓
7 0.00416239 0.00418195 1.96e-05 ✓
8 -0.02097007 -0.02097906 9.00e-06 ✓
9 -0.03137119 -0.03137886 7.67e-06 ✓
10 -0.04882537 -0.04880999 1.54e-05 ✓
11 -0.02784152 -0.02784257 1.05e-06 ✓
12 -0.04736265 -0.04734680 1.59e-05 ✓
13 -0.05195489 -0.05194357 1.13e-05 ✓
14 0.04666578 0.04667128 5.50e-06 ✓
15 -0.05786950 -0.05786415 5.35e-06 ✓
16 0.04575711 0.04574870 8.41e-06 ✓
17 0.02565357 0.02565229 1.28e-06 ✓
18 0.06328943 0.06327724 1.22e-05 ✓
19 0.02183735 0.02183516 2.19e-06 ✓ 索引 CPU 值 NPU 值 绝对误差 说明
----------------------------------------------------------------
142 0.02126813 0.02122337 4.48e-05 ✓
115 0.02522856 0.02527294 4.44e-05 ✓
350 0.01418181 0.01413757 4.42e-05 ✓
340 0.03114957 0.03110915 4.04e-05 ✓
182 -0.00613354 -0.00617379 4.02e-05 ✓
302 -0.03710321 -0.03706617 3.70e-05 ✓
162 -0.00571870 -0.00575559 3.69e-05 ✓
175 0.05123313 0.05126973 3.66e-05 ✓
51 0.00101624 0.00097967 3.66e-05 ✓
266 -0.06596250 -0.06599898 3.65e-05 ✓结论: NPU 推理结果与 CPU 推理结果高度一致,最大误差仅 4.48e-05,余弦相似度 1.0,精度完全达标。
测试条件: 预热 10 次 + 正式测试 50 次 (单张图片, 224×224)
| 指标 | CPU (Intel) | NPU (Ascend 910) | 加速比 |
|---|---|---|---|
| Mean | 416.46 ms | 8.03 ms | ~51.9× |
| Median | 410.42 ms | 5.52 ms | ~74.4× |
| Min | 405.69 ms | 5.26 ms | ~77.1× |
| Max | 474.26 ms | 38.48 ms | ~12.3× |
| P90 | 441.43 ms | 5.60 ms | ~78.8× |
| P99 | 462.45 ms | 38.16 ms | ~12.1× |
| Std | 14.10 ms | 8.56 ms | — |
--no_detection),仅特征提取 NPU 仅需 ~5ms,基本可实时
YOLOX ONNX 检测器 (CPU)
│
│ 检测到手提包 → crop
│
▼
┌─────────────────────────────────────┐
│ ResNet50 + GroupNorm (24.6M 参数) │
│ ├─ conv1 (7×7, 64) │
│ ├─ layer1: Bottleneck ×3 │
│ ├─ layer2: Bottleneck ×4 │
│ ├─ layer3: Bottleneck ×6 │
│ ├─ layer4: Bottleneck ×3 │
│ └─ Global Avg Pool → 512-d │
└─────────────────────────────────────┘脚本支持任何常见图片格式 (jpg/png/bmp),检测到手提包后自动裁剪。若图片中无手提包则会跳过裁剪,使用整图提取特征。
检测模型 (ONNX YOLOX) 运行在 CPU 上,典型耗时 50-100ms。对于批处理场景,可考虑:
# 跳过检测,直接提取特征
python3 inference.py --no_detection --device npu --benchmarkNPU 中位数延时 5.52ms(~181 QPS),叠加检测后约 60ms (16 QPS)。如需更高吞吐量:
torch_npu.compile 图模式加速ResNet50 特征提取模块原生支持 batch (NCHW),将多张预处理的张量 torch.cat 即可。
本仓库代码基于 Apache 2.0 发布。模型版权归 ModelScope 和原开发者所有。