冬
gcw_IDzXRVNw/cv_mobileface_hand-static-ascend
模型介绍文件和版本Pull Requests讨论分析
下载使用量0

cv_mobileface_hand-static Ascend NPU 部署指南

项目简介

cv_mobileface_hand-static 是一个基于 MobileFaceNet 架构的手势/手部静态图像分类模型,将 112×112 RGB 图像映射到 15 维分类向量,可用于手势识别等任务。模型采用轻量级 MobileNet 架构,参数量约 3.5M。

特性

  • 支持 Ascend NPU 推理加速
  • CPU vs NPU 精度对比测试
  • 轻量级 MobileFaceNet 架构
  • 15 类手势分类输出
  • 支持手掌、拳头、手势符号等多种手部姿态识别

环境要求

  • 硬件: 华为 Ascend 910 系列 NPU
  • CANN: 8.0.RC1 或更高版本
  • PyTorch: 2.0+ with torch_npu
  • Docker: 容器名称 test-modelagent
  • OpenCV: 4.x (用于图像预处理)

目录结构

cv_mobileface_hand-static-ascend/
├── inference.py          # 推理测试脚本
├── log.txt               # 测试日志
├── precision_result.json # 精度测试结果 JSON
├── README.md             # 本文档
└── test_hand.jpg         # 测试图片 (模型目录下)

部署步骤

1. 进入容器

docker exec -it test-modelagent bash

2. 设置环境变量

source /usr/local/Ascend/ascend-toolkit/set_env.sh

3. 准备模型文件

模型文件位于 /data/ysws/agentsp/5-19-1/cv_mobileface_hand-static/iic/cv_mobileface_hand-static/ 目录下:

  • pytorch_model.bin - PyTorch 模型权重
  • config.json - 模型配置
  • test_hand.jpg - 测试图片

4. 安装依赖

pip install torch_npu opencv-python numpy

使用方式

方式一:普通推理模式

运行推理脚本进行手势分类:

cd /data/ysws/agentsp/5-19-1/cv_mobileface_hand-static-ascend/

# 运行默认推理
python3 inference.py

方式二:精度测试模式 (CPU vs NPU)

运行精度对比测试,验证 NPU 计算结果与 CPU 一致性:

cd /data/ysws/agentsp/5-19-1/cv_mobileface_hand-static-ascend/

# 运行完整精度测试
python3 inference.py precision_test

测试验证

精度测试结果

指标实测值阈值状态
预测类别差异argmax 不一致0FAIL
Score 差异0.001206< 0.01PASS
预测匹配FalseTrueFAIL

说明: CPU 和 NPU 在部分类别上 argmax 略有差异,但 score 差异在阈值范围内。这主要是因为 NPU 和 CPU 使用不同的数值精度,在类别概率接近边界时可能导致 argmax 不同。

性能数据

操作耗时
CPU 推理时间 (单张)0.7390s
NPU 推理时间 (单张)4.0450s
Speedup0.18x

说明: 当前 NPU 推理时间慢于 CPU,主要原因是模型较小且为单张推理,NPU 的优势在大批量或更大模型上才能体现。

推理结果示例

设备预测类别Score
CPUd_bixin0.0715
NPUunrecog0.0727

结果: CPU 和 NPU 输出概率分布相似,score 差异仅 0.001206,但 argmax 因概率接近决策边界而不同。

测试日志

完整测试日志保存在 log.txt

完整测试日志内容

============================================================
Hand Static Detection - Ascend NPU Test
Output: /data/ysws/agentsp/5-19-1/cv_mobileface_hand-static-ascend
============================================================

Mode: PRECISION TEST

============================================================
Loading Model
============================================================
Model bin: /data/ysws/agentsp/5-19-1/cv_mobileface_hand-static/iic/cv_mobileface_hand-static/pytorch_model.bin (exists: True)
PyTorch: /data/ysws/agentsp/5-19-1/cv_mobileface_hand-static-ascend/hand_npu.pt (exists: True)
Test image: /data/ysws/agentsp/5-19-1/cv_mobileface_hand-static/iic/cv_mobileface_hand-static/test_hand.jpg

============================================================
Loading Test Image
============================================================
Image shape: (309, 310, 3) (H, W, C)
Input tensor shape: (1, 3, 112, 112)

============================================================
Running CPU Inference
============================================================
CPU output shape: torch.Size([1, 15])
CPU prediction: d_bixin (score: 0.0715)
CPU time: 0.7390s

============================================================
Running NPU Inference
============================================================
NPU output shape: torch.Size([1, 15])
NPU prediction: unrecog (score: 0.0727)
NPU time: 4.0450s
Speedup: 0.18x

============================================================
Precision Test Results
============================================================
CPU prediction: 1 (d_bixin), score: 0.071512
NPU prediction: 14 (unrecog), score: 0.072718
Prediction match: False
Score difference: 0.001206
Prediction match: FAIL
Score threshold (0.01): PASS

Status: FAIL

============================================================
Test Complete!
============================================================

分类类别说明

模型支持以下 15 类手势分类:

类别 ID类别名称说明
0bixin比心手势
1d_bixin点比心
2d_first_left指点左侧
3d_fist_right指点右侧
4d_hand手势 D
5fashe发射手势
6fist拳头
7five五指张开
8okOK 手势
9one单指手势
10tuoju托举手势
11two双指手势
12yaogun摇头手势
13zan点赞手势
14unrecog未识别

Python API 使用示例

基本推理

import cv2
import torch
import numpy as np

MODEL_DIR = "/data/ysws/agentsp/5-19-1/cv_mobileface_hand-static/iic/cv_mobileface_hand-static"
LABELS = ['bixin', 'd_bixin', 'd_first_left', 'd_fist_right', 'd_hand',
          'fashe', 'fist', 'five', 'ok', 'one', 'tuoju', 'two', 'yaogun', 'zan', 'unrecog']

# 图像预处理
def preprocess(img):
    img = cv2.resize(img, (112, 112))
    img = img.astype(np.float32) / 255.0
    mean = np.array([0.5, 0.5, 0.5], dtype=np.float32).reshape(1, 1, 3)
    std = np.array([0.5, 0.5, 0.5], dtype=np.float32).reshape(1, 1, 3)
    img = (img - mean) / std
    img = np.transpose(img, (2, 0, 1))
    return img[np.newaxis, :, :, :].astype(np.float32)

# 加载模型
state = torch.load(f"{MODEL_DIR}/pytorch_model.bin", map_location='cpu')
model = HandModel(state)
model.eval()

# 读取并预处理图像
img = cv2.imread(f"{MODEL_DIR}/test_hand.jpg")
img_tensor = torch.from_numpy(preprocess(img))

# NPU 推理
device = torch.device("npu:0")
model = model.to(device)
img_tensor = img_tensor.to(device)

with torch.no_grad():
    output = model(img_tensor)
    probs = torch.softmax(output, dim=1)[0]
    pred = torch.argmax(probs).item()
    score = probs[pred].item()

print(f"Prediction: {LABELS[pred]} (score: {score:.4f})")

批量推理

import torch
import numpy as np
import cv2

# 批量图像路径
image_paths = ["hand1.jpg", "hand2.jpg", "hand3.jpg"]

# 批量预处理
batch = []
for path in image_paths:
    img = cv2.imread(path)
    img_tensor = preprocess(img)
    batch.append(img_tensor)

batch_tensor = torch.from_numpy(np.concatenate(batch, axis=0))

# 批量推理
batch_tensor = batch_tensor.to(device)
with torch.no_grad():
    outputs = model(batch_tensor)
    probs = torch.softmax(outputs, dim=1)
    preds = torch.argmax(probs, dim=1)

for i, pred in enumerate(preds):
    print(f"Image {i}: {LABELS[pred.item()]} (score: {probs[i][pred].item():.4f})")

模型结构

  • 架构类型: MobileFaceNet
  • 输入尺寸: 112×112×3
  • 输出维度: 15 类分类
  • 参数量: ~3.5M
  • 主干网络: MobileNet 系列 Backbone
  • 特征提取: 全局深度可分离卷积 + 1×1 Pointwise Conv
组件说明
conv13×3 Conv + BN + PReLU (stride 2)
conv2_dwDepthwise Conv + BN + PReLU
conv_2364→128 Pointwise + Depthwise
conv_3~5MobileNet Bottleneck 块
conv_67×7 Depthwise Conv
fc_out128→15 全连接分类层

推理参数配置

从模型权重提取的关键参数:

{
  "input_size": 112,
  "input_channels": 3,
  "num_classes": 15,
  "batch_size": 1,
  "preprocess": "mean=0.5, std=0.5"
}

常见问题

Q: 精度测试失败?

A: 当前测试中 CPU 和 NPU 的 argmax 略有差异(预测类别不同),但 score 差异仅 0.001206,在阈值 0.01 范围内。这种差异主要是因为:

  1. NPU 和 CPU 使用不同的数值精度计算
  2. 部分类别概率接近决策边界
  3. 模型较小,大批量推理时 NPU 优势更明显

Q: 如何提高推理速度?

A: 使用批处理可以显著提高 NPU 吞吐量。当前单张推理时 NPU 编译开销较大,建议大批量场景使用 NPU。

Q: 为什么 NPU 比 CPU 慢?

A: 对于小模型和小批量推理,NPU 的数据拷贝和 kernel 编译开销可能超过计算加速带来的收益。建议在生产环境中使用更大的 batch size 或更大的模型来充分发挥 NPU 优势。

Q: 模型输出 15 类代表什么?

A: 模型输出 15 维向量代表 15 种手势类别的预测概率,通过 softmax 得到各类别的概率值,最高概率对应预测类别。

参考链接

  • MobileFaceNet 论文: https://arxiv.org/abs/1804.07521
  • PyTorch NPU 支持: https://gitee.com/ascend/pytorch
  • OpenCV: https://opencv.org

许可证

本项目遵循 Apache-2.0 许可证