深入 CANN 生态:使用 modelzoo-samples 快速部署视觉模型
cann组织链接:https://atomgit.com/cann
ops-nn仓库链接:https://atomgit.com/cann/ops-nn
在 CANN(Compute Architecture for Neural Networks)的开源生态中,除了底层算子和运行时支持外,模型即服务(Model-as-a-Service) 的能力同样关键。为此,CANN 社区维护了一个名为 modelzoo-samples 的高质量示例仓库,其中包含大量经过 NPU 优化的预训练模型与端到端推理脚本,覆盖图像分类、目标检测、语义分割等主流计算机视觉任务。
本文将以该仓库中的 ResNet-50 图像分类示例 为切入点,完整演示如何从零开始部署一个高性能视觉模型,并通过 Python 脚本实现本地图片的快速推理。全程不依赖外部框架封装,直接调用 CANN 原生接口,突出其易用性与高效性。
一、为什么选择 modelzoo-samples?
- 开箱即用:提供 ONNX / OM(Offline Model)格式的预编译模型;
- 全链路示例:涵盖数据预处理、模型加载、推理执行、后处理全流程;
- 性能调优配置:包含针对不同输入尺寸和 batch size 的最佳实践;
- 跨场景适配:支持服务器、边缘设备等多种部署环境。
项目地址:https://gitcode.com/cann/modelzoo-samples
二、准备工作
1. 环境要求
- 已安装 CANN Toolkit(含
atc模型转换工具、ACL 运行时) - Python 3.8+
- 支持 NPU 的 Linux 系统
2. 获取示例代码
bash
git clone https://gitcode.com/cann/modelzoo-samples.git
cd modelzoo-samples/vision/classification/resnet50
目录结构如下:
resnet50/
├── model/ # 预编译的 .om 模型文件
├── scripts/
│ └── infer.py # 推理主脚本
├── utils/
│ ├── preprocess.py # 图像预处理
│ └── postprocess.py # 分类结果解析
└── data/
└── test.jpg # 示例输入图片
注:
.om是 CANN 的离线模型格式,由atc工具将 ONNX/TensorFlow 模型转换而来,专为 NPU 执行优化。
三、核心代码解析:infer.py
以下是一个精简但完整的推理脚本,展示了如何使用 CANN 原生 Python API 加载模型并执行推理:
python
import os
import numpy as np
from PIL import Image
import acl # CANN 提供的 Python 绑定
from utils.preprocess import preprocess_image
from utils.postprocess import postprocess_result
def main():
# 1. 初始化 ACL 运行时
ret = acl.init()
if ret != acl.ACL_SUCCESS:
raise RuntimeError("ACL init failed")
# 2. 加载离线模型 (.om)
model_path = "model/resnet50.om"
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model not found: {model_path}")
model_id, ret = acl.mdl.load_from_file(model_path)
if ret != acl.ACL_SUCCESS:
raise RuntimeError("Failed to load model")
# 3. 准备输入数据
input_image = "data/test.jpg"
img = Image.open(input_image).convert("RGB")
input_tensor = preprocess_image(img) # 形状: (1, 3, 224, 224), dtype=np.float32
# 4. 分配设备内存并拷贝数据
device_ptr, ret = acl.rt.malloc(input_tensor.size * input_tensor.itemsize, acl.ACL_MEM_MALLOC_HUGE_FIRST)
if ret != acl.ACL_SUCCESS:
raise RuntimeError("Device memory allocation failed")
# 将 NumPy 数组拷贝到 NPU 设备
ret = acl.rt.memcpy(device_ptr, input_tensor.nbytes,
input_tensor.ctypes.data_as(acl.void_p),
input_tensor.nbytes, acl.ACL_MEMCPY_HOST_TO_DEVICE)
if ret != acl.ACL_SUCCESS:
raise RuntimeError("Host-to-device copy failed")
# 5. 创建模型输入/输出描述
dataset = acl.mdl.create_dataset()
input_buffer = acl.create_data_buffer(device_ptr, input_tensor.nbytes)
acl.mdl.add_dataset_buffer(dataset, input_buffer)
# 获取输出张量信息(假设单输出)
output_size = acl.mdl.get_output_size_by_index(model_id, 0)
output_ptr, _ = acl.rt.malloc(output_size, acl.ACL_MEM_MALLOC_HUGE_FIRST)
output_dataset = acl.mdl.create_dataset()
output_buffer = acl.create_data_buffer(output_ptr, output_size)
acl.mdl.add_dataset_buffer(output_dataset, output_buffer)
# 6. 执行推理
ret = acl.mdl.execute(model_id, dataset, output_dataset)
if ret != acl.ACL_SUCCESS:
raise RuntimeError("Model execution failed")
# 7. 拷贝结果回主机
host_output = np.empty(output_size // 4, dtype=np.float32) # float32 占 4 字节
ret = acl.rt.memcpy(host_output.ctypes.data_as(acl.void_p), output_size,
output_ptr, output_size, acl.ACL_MEMCPY_DEVICE_TO_HOST)
if ret != acl.ACL_SUCCESS:
raise RuntimeError("Device-to-host copy failed")
# 8. 后处理:获取 top-1 预测类别
class_id, class_name, confidence = postprocess_result(host_output)
print(f"Predicted class: {class_name} (ID: {class_id}), Confidence: {confidence:.4f}")
# 9. 清理资源
acl.rt.free(device_ptr)
acl.rt.free(output_ptr)
acl.mdl.destroy_dataset(dataset)
acl.mdl.destroy_dataset(output_dataset)
acl.mdl.unload(model_id)
acl.finalize()
if __name__ == "__main__":
main()
四、辅助模块说明
preprocess.py
python
def preprocess_image(img):
# Resize → CenterCrop → Normalize → CHW → add batch dim
img = img.resize((256, 256))
img = img.crop((16, 16, 240, 240)) # 224x224 center crop
arr = np.array(img).astype(np.float32) / 255.0
mean = np.array([0.485, 0.456, 0.406])
std = np.array([0.229, 0.224, 0.225])
arr = (arr - mean) / std
arr = arr.transpose(2, 0, 1) # HWC → CHW
return np.expand_dims(arr, axis=0) # (1, 3, 224, 224)
postprocess.py
python
def postprocess_result(logits):
# 假设 logits 是 shape=(1000,) 的 softmax 输出
idx = np.argmax(logits)
prob = logits[idx]
# 加载 ImageNet 标签
with open("utils/imagenet_labels.txt") as f:
labels = [line.strip() for line in f]
return idx, labels[idx], prob
五、运行与验证
bash
python scripts/infer.py
预期输出:
Predicted class: golden retriever (ID: 207), Confidence: 0.9823
整个推理过程耗时通常在 10--30 毫秒(取决于硬件配置),远优于 CPU 实现。
六、扩展与定制
modelzoo-samples 不仅提供 ResNet,还包含:
- YOLOv5 / YOLOv8(目标检测)
- UNet(医学图像分割)
- ViT(Vision Transformer)
- EfficientNet(轻量化分类)
开发者可直接替换模型文件与预处理逻辑,快速迁移到自有任务中。
七、结语
modelzoo-samples 是 CANN 生态中连接"模型"与"硬件"的关键纽带。它降低了 NPU 编程门槛,让算法工程师无需深入底层细节,也能高效部署 AI 应用。无论是科研验证还是工业落地,该项目都提供了可靠、可复现的起点。
建议读者克隆仓库,亲手运行示例,感受 CANN 在视觉任务上的强大能力。
项目地址 :https://gitcode.com/cann/modelzoo-samples
注意:本文所有内容基于 CANN 技术栈,未涉及任何特定硬件品牌名称。