AIGlasses_for_navigation部署案例:国产昇腾910B服务器适配YOLO-Seg模型实践
1. 引言
想象一下,一个视障朋友走在陌生的街道上,他需要的不只是一根导盲杖,而是一个能“看见”并“理解”周围环境的智能伙伴。这个伙伴能告诉他前方是盲道还是台阶,能识别红绿灯的颜色,甚至能帮他找到掉在地上的钥匙。这就是AIGlasses_for_navigation正在做的事情——它不仅仅是一副眼镜,更是一个集成了AI视觉、实时导航和语音交互的智能可穿戴系统。
最近,我们团队面临一个有趣的挑战:将这个充满潜力的系统,从常见的x86或GPU服务器环境,迁移到国产的昇腾910B AI服务器上。为什么要这么做?一方面,国产化替代是大势所趋,昇腾平台在特定场景下的能效比和自主可控性优势明显;另一方面,系统的核心——基于YOLO-Seg的实时视觉分割模型,能否在昇腾的异构计算架构上“跑”得又快又稳,是一个必须回答的工程问题。
本文将分享我们完整的适配实践,从环境准备、模型转换、性能优化到最终部署。无论你是对昇腾开发感兴趣的工程师,还是正在寻找AI落地新硬件的探索者,相信这篇“踩坑”与“填坑”的记录都能给你带来一些启发。
2. 项目与硬件环境概览
2.1 AIGlasses_for_navigation是什么?
简单来说,它是一个为智能眼镜(或类似头戴设备)设计的导航辅助系统。它的核心能力是通过摄像头“看见”世界,并用AI模型理解这个世界,最后通过语音告诉用户该怎么做。
它的主要功能模块包括:
- 盲道导航:实时分割图像中的盲道区域,计算行走方向(直行、左转、右转)并语音提示。
- 过马路辅助:检测斑马线和交通信号灯(红绿灯),在绿灯亮起时引导用户安全通过。
- 物品查找:识别用户指定的常见物品(如饮料瓶、手机),并通过语音和视觉提示引导用户靠近。
- 实时语音交互:用户可以通过语音直接提问(如“前面有什么?”),系统通过多模态AI模型理解图像和语音,并给出回答。
整个系统的技术栈可以概括为“前端采集 + AI推理 + 后端服务 + 语音交互”。其中,AI视觉推理是性能瓶颈和核心所在,它直接决定了系统的响应速度和可用性。
2.2 昇腾910B服务器简介
我们这次使用的硬件是搭载了华为昇腾910B AI处理器的Atlas 800推理服务器。与大家熟悉的NVIDIA GPU不同,昇腾处理器采用达芬奇(DaVinci)架构,是一种面向AI计算的特化芯片。
对于开发者而言,切换到昇腾平台意味着几个关键变化:
我们的目标很明确:将AIGlasses_for_navigation系统中基于PyTorch和YOLOv8的Segmentation模型(.pt文件),高效地运行在这台昇腾910B服务器上。
3. 模型适配:从PyTorch到昇腾OM
这是整个适配过程中最具挑战性的一环。我们的模型包括用于盲道分割的 yolo-seg.pt 和用于障碍物检测的 yoloe-11l-seg.pt 等。下面是我们走过的完整路径。
3.1 环境准备与工具链安装
首先,需要在昇腾服务器上搭建模型转换和推理的环境。昇腾提供了CANN工具包,其中包含了模型转换工具(ATC)和推理框架(AscendCL)。
# 1. 安装CANN工具包(版本需与驱动匹配,这里以CANN 7.0为例)
# 假设安装包已下载为Ascend-cann-toolkit_7.0.0_linux-x86_64.run
chmod +x Ascend-cann-toolkit_7.0.0_linux-x86_64.run
./Ascend-cann-toolkit_7.0.0_linux-x86_64.run –install
# 2. 设置环境变量
source /usr/local/Ascend/ascend-toolkit/set_env.sh
# 3. 安装PyTorch(用于模型加载和预处理)
# 昇腾社区提供了适配的PyTorch版本,需从华为镜像站获取
pip3 install torch==2.1.0 –index-url https://mirrors.huaweicloud.com/repository/pypi/simple
# 4. 安装其他依赖,如ultralytics(YOLOv8)、opencv-python等
pip3 install ultralytics opencv-python numpy
3.2 模型转换实战:YOLO-Seg的“变身”
模型转换的核心工具是ATC(Ascend Tensor Compiler)。它需要先将PyTorch模型导出为ONNX(一种开放的模型格式),再将ONNX转换为昇腾的OM模型。
步骤一:导出ONNX模型
我们编写一个转换脚本,利用YOLOv8官方接口导出包含后处理(如Segmentation head)的正确ONNX图。
# export_onnx.py
from ultralytics import YOLO
import torch
# 加载训练好的PyTorch模型
model = YOLO('model/yolo-seg.pt')
model.fuse() # 融合模型中的一些层,可以加速
# 定义输入尺寸 (batch, channel, height, width)
dummy_input = torch.randn(1, 3, 640, 640)
# 导出ONNX模型
# 关键参数:
# – opset_version: ONNX算子集版本,建议12或以上
# – dynamic_axes: 指定动态维度,便于适配不同批大小和分辨率
model.export(
format='onnx',
imgsz=640,
dynamic=True, # 允许动态batch和尺寸
simplify=True, # 简化计算图
opset=12,
nms=True # 包含非极大值抑制后处理(根据需求选择)
)
print("ONNX model exported successfully.")
运行后,会得到 yolo-seg.onnx 文件。
步骤二:使用ATC转换ONNX至OM
这是最关键的一步,需要为ATC工具指定正确的配置。
# atc_conversion.sh
#!/bin/bash
MODEL_NAME="yolo-seg"
ONNX_PATH="./${MODEL_NAME}.onnx"
OM_PATH="./${MODEL_NAME}.om"
# 使用ATC命令进行转换
atc \\
–model=$ONNX_PATH \\
–framework=5 \\ # 5 代表 ONNX
–output=$OM_PATH \\
–input_format=NCHW \\
–input_shape="images:1,3,640,640" \\ # 与导出时一致
–log=error \\
–soc_version=Ascend910B \\ # 指定芯片型号
–insert_op_conf=./aipp_yoloseg.config # 重要的预处理配置!
echo "Model conversion completed: $OM_PATH"
这里有一个大坑:图像预处理。 在GPU上,我们通常在Python代码里用OpenCV或PyTorch进行归一化(如 img/255.0)、BGR2RGB转换等。但在昇腾上,为了极致性能,推荐使用AIPP(AI Pre-Processing)在模型推理前,通过硬件直接完成这些操作。这就需要编写一个AIPP配置文件 aipp_yoloseg.config。
# aipp_yoloseg.config
aipp_op {
aipp_mode: static
input_format : YUV420SP_U8 # 假设输入为YUV,也可设为RGB
src_image_size_w : 640
src_image_size_h : 640
# 归一化参数 (mean, min) 和 (scale, 1/255)
# 效果等同于 (x – mean) * scale
mean_chn_0 : 0
mean_chn_1 : 0
mean_chn_2 : 0
scale_chn_0 : 0.003921568627451 # 1/255
scale_chn_1 : 0.003921568627451
scale_chn_2 : 0.003921568627451
# 如果训练时用了mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]
# 则换算后 scale = 1/(255*std), mean = -mean/scale
# 这部分需要根据原始模型训练时的预处理方式仔细调整!
crop: false
padding: false
}
AIPP配置是否正确,直接影响到模型的识别精度。务必与原始PyTorch推理脚本中的预处理代码进行严格比对和验证。
4. 推理引擎开发与集成
得到OM模型后,下一步就是编写在昇腾上运行它的推理代码。我们需要使用AscendCL接口。
4.1 初始化与模型加载
AscendCL的编程范式有点类似于CUDA,需要显式地管理设备、上下文、内存和流。
# ascend_infer.py (部分代码)
import acl
import numpy as np
import cv2
class AscendYOLOSeg:
def __init__(self, model_path):
self.model_path = model_path
self.device_id = 0
self.context = None
self.stream = None
self.model_id = None
self.input_dataset = None
self.output_dataset = None
# 1. 初始化ACL
ret = acl.init()
# 2. 指定运算的Device
ret = acl.rt.set_device(self.device_id)
# 3. 创建Context和Stream
self.context, ret = acl.rt.create_context(self.device_id)
self.stream, ret = acl.rt.create_stream()
# 4. 从文件加载OM模型
self.model_id, ret = acl.mdl.load_from_file(model_path)
# 5. 创建模型描述信息,并准备输入输出数据结构
self.model_desc = acl.mdl.create_desc()
acl.mdl.get_desc(self.model_desc, self.model_id)
# … 创建输入输出Dataset …
def preprocess(self, cv2_image):
"""将OpenCV图像转换为模型需要的输入张量"""
# 这里通常进行resize到640×640,注意与AIPP配置匹配
# 如果AIPP完成了归一化,这里可能只需要转换颜色空间和尺寸
img_resized = cv2.resize(cv2_image, (640, 640))
# 从HWC转换为CHW
img_chw = img_resized.transpose(2, 0, 1)
# 如果AIPP未做归一化,这里需要做 img_chw = img_chw / 255.0
# 转换为float32
img_np = img_chw.astype(np.float32)
return img_np
def infer(self, input_numpy):
"""执行推理"""
# 1. 将numpy数据拷贝到Device侧内存
input_ptr = acl.util.numpy_to_ptr(input_numpy)
# 2. 设置输入Dataset的数据
# …
# 3. 执行模型推理
ret = acl.mdl.execute(self.model_id,
self.input_dataset,
self.output_dataset)
# 4. 从输出Dataset中取出数据
# …
# 5. 将数据从Device侧拷贝回Host侧(numpy)
output_data = acl.util.ptr_to_numpy(output_ptr, output_shape, output_dtype)
return output_data
def postprocess(self, model_outputs, orig_img_shape):
"""解析模型输出:框、置信度、类别、分割掩码"""
# 这里需要根据YOLO-Seg模型的输出结构进行解析
# 通常包括:
# output[0]: 检测框信息 (xywh, conf, cls)
# output[1]: 分割掩码原型
# 需要将原型与检测框结合,生成每个实例的分割图
boxes, masks = self._parse_yolo_seg_output(model_outputs)
# 将掩码上采样回原始图像尺寸
full_masks = self._process_masks(masks, boxes, orig_img_shape)
return boxes, full_masks
def __del__(self):
# 释放所有ACL资源
# …
acl.rt.reset_device(self.device_id)
acl.finalize()
4.2 与原有系统集成
AIGlasses_for_navigation的原系统使用PyTorch直接推理。我们需要将新的昇腾推理类嵌入到原有的业务逻辑中,主要修改推理引擎的调用部分。
# 原系统推理部分伪代码
# from ultralytics import YOLO
# model = YOLO('model/yolo-seg.pt')
# results = model(frame)
# 修改后的昇腾推理集成
from ascend_infer import AscendYOLOSeg
class NavigationEngine:
def __init__(self):
# 初始化昇腾推理引擎
self.seg_engine = AscendYOLOSeg('model/yolo-seg.om')
self.obj_engine = AscendYOLOSeg('model/yoloe-11l-seg.om')
# … 其他初始化
def process_frame(self, frame):
# 预处理
input_tensor = self.seg_engine.preprocess(frame)
# 昇腾推理
output_data = self.seg_engine.infer(input_tensor)
# 后处理
boxes, masks = self.seg_engine.postprocess(output_data, frame.shape)
# 后续的导航逻辑、语音提示生成等保持不变
direction = self._calculate_direction(masks)
self._give_voice_guidance(direction)
# …
5. 性能优化与踩坑记录
从GPU切换到昇腾,性能表现如何?我们做了一系列测试和优化。
5.1 性能对比测试
我们在同一台服务器的CPU、GPU(Tesla T4)和昇腾910B上,对640×640输入尺寸的盲道分割模型进行了推理速度测试(单位:毫秒,单帧处理时间)。
| Intel Xeon CPU | 450 – 550 | 500 – 600 | 约 1200 |
| NVIDIA Tesla T4 | 25 – 35 | 40 – 50 | 约 1500 |
| 华为昇腾 910B | 15 – 22 | 30 – 40 | 约 1000 |
结果分析:
对于AIGlasses_for_navigation这样的实时系统,每帧节省10-20毫秒,意味着更流畅的体验和更低的功耗,这对可穿戴设备至关重要。
5.2 遇到的主要问题与解决方案
模型精度下降
- 现象:转换后的OM模型,检测框位置基本正确,但分割掩码的边界模糊,IoU指标下降明显。
- 排查:对比ONNX和OM模型在相同输入下的输出,发现数值有微小差异。最终定位到AIPP中的归一化参数与PyTorch验证时的预处理不完全一致。PyTorch中是 (img/255.0 – mean) / std,而AIPP配置只做了 img * scale(等价于 img/255.0),忘记了减均值除标准差。
- 解决:根据公式 scale = 1.0 / (255.0 * std) 和 mean = -mean / scale,重新计算并修正AIPP配置中的 mean_chn 和 scale_chn 参数。
多模型并发推理效率低
- 现象:系统需要同时运行盲道分割、物品识别等多个模型。初始设计是顺序执行,总延迟叠加。
- 解决:利用昇腾ACL的Stream流并发机制。为每个模型创建独立的Stream,在Python端使用多线程,让不同模型的数据准备、计算、后处理过程重叠进行,实现了近乎并行的推理,整体吞吐量提升约40%。
动态形状支持不足
- 现象:为了兼容不同分辨率的输入,我们导出了动态维度的ONNX模型(dynamic_axes)。但在ATC转换时,某些算子对动态尺寸支持不友好,导致转换失败。
- 解决:采用折中方案。准备多个固定尺寸的OM模型(如640×640, 1280×720)。在推理前,根据输入图像的长宽比,选择最接近的模型尺寸,并进行相应的缩放和填充(Padding)。虽然增加了少量预处理开销,但保证了模型的通用性和转换成功率。
6. 部署与效果验证
6.1 系统部署
我们将修改后的代码与OM模型一起,打包部署到昇腾服务器上。由于原系统使用Supervisor进行进程管理,这部分配置无需改动。
# 部署目录结构
/root/AIGlasses_for_navigation_ascend/
├── app_main.py # 修改后的主程序
├── model_ascend/ # 昇腾OM模型目录
│ ├── yolo-seg.om
│ ├── yoloe-11l-seg.om
│ └── …
├── ascend_infer.py # 昇腾推理封装类
├── aipp_configs/ # AIPP配置文件
│ ├── aipp_yoloseg.config
│ └── …
└── requirements_ascend.txt # 昇腾环境专用依赖
启动服务后,通过Web界面(http://服务器IP:8081)可以观察到系统状态。在“模型加载情况”一栏,会显示如“盲道模型 (Ascend): 已加载”的提示。
6.2 功能与效果验证
我们进行了实地测试,使用摄像头采集街道场景。
- 盲道导航:系统能稳定识别出砖石盲道,在岔路口给出“向左转”或“向右转”的清晰语音提示,响应延迟在感知上几乎无感。
- 过马路辅助:成功检测到斑马线和远处的红绿灯。当绿灯亮起时,能准确发出“绿灯,可以安全通过”的提示。
- 物品查找:对“红牛”、“矿泉水”等训练集内的物品,识别和引导准确。由于模型本身精度限制,对未训练过的物品识别能力一般,这与硬件平台无关。
总体体验:在昇腾910B上运行的AIGlasses_for_navigation系统,其核心的视觉感知响应速度比在原有测试GPU上更快,整体运行稳定。证明了这套为视障人士服务的AI系统,完全可以在国产高性能AI芯片上良好运行。
7. 总结
回顾这次AIGlasses_for_navigation在昇腾910B上的适配实践,可以说是一次成功的“跨界”尝试。我们不仅完成了从GPU到昇腾AI处理器的迁移,更通过一系列优化,让系统性能得到了实实在在的提升。
核心收获有以下几点:
给后来者的建议:
- 从小模型开始:如果你的模型很复杂,不妨先用一个像YOLOv5s这样的小模型跑通全流程,理解每一个环节。
- 善用官方工具:华为昇腾社区提供的模型转换、性能 profiling 工具(如msame、profiling)非常有用,能帮你快速定位瓶颈。
- 精度验证必不可少:转换后一定要用测试集量化验证精度损失,确保业务可接受。
将AI关怀落地到现实世界,技术是桥梁。这次实践告诉我们,国产的AI算力平台已经具备了承载此类创新应用的能力。期待未来,能有更多像AIGlasses_for_navigation这样充满善意的项目,在各种计算平台上生根发芽,照亮更多人的生活。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
网硕互联帮助中心


评论前必须登录!
注册