一、视觉模型分类1.1 模型类型视觉模型三大类: 分类模型 (Classification) ResNet, VGG, EfficientNet, ViT 输入: 图像 → 输出: 类别概率 检测模型 (Detection) YOLO, SSD, Faster R-CNN, DETR 输入: 图像 → 输出: 边界框 类别 分割模型 (Segmentation) U-Net, DeepLab, Mask R-CNN 输入: 图像 → 输出: 像素级掩码1.2 部署流程通用部署流程: PyTorch 模型 → ONNX 导出 → ATC 转换 → .om 模型 → 推理 分类模型: 简单直接转换成功率高 检测模型: 后处理复杂可能需要自定义算子 分割模型: 输出尺寸大显存需求高二、分类模型部署2.1 ResNet 部署importtorchimporttorchvision.modelsasmodels# 1. 导出 ONNXmodelmodels.resnet50(pretrainedTrue)model.eval()dummy_inputtorch.randn(1,3,224,224)torch.onnx.export(model,dummy_input,resnet50.onnx,input_names[image],output_names[logits],dynamic_axes{image:{0:batch_size}},opset_version14)print(ONNX 模型已导出)# 2. ATC 转换atc--modelresnet50.onnx\--framework5\--outputresnet50\--input_shapeimage:1,3,224,224\--soc_versionAscend310\--loginfo# 3. 推理实现importnumpyasnpclassResNetClassifier:def__init__(self,model_path):self.modelself._load_model(model_path)self.meannp.array([0.485,0.456,0.406])self.stdnp.array([0.229,0.224,0.225])defpreprocess(self,image):图像预处理fromPILimportImage# Resizeimageimage.resize((224,224))# 转 numpyimagenp.array(image)/255.0# 归一化image(image-self.mean)/self.std# 转置 CHWimageimage.transpose(2,0,1)# 添加 batch 维度imagenp.expand_dims(image,axis0).astype(np.float32)returnimagedefpredict(self,image):推理input_dataself.preprocess(image)outputself._run_model(input_data)# Softmaxprobsnp.exp(output)/np.sum(np.exp(output))returnprobsdeftop_k(self,image,k5):Top-K 预测probsself.predict(image)# 加载 ImageNet 类别classesself._load_imagenet_classes()# 获取 Top-Ktop_k_idxnp.argsort(probs[0])[-k:][::-1]top_k[(classes[idx],probs[0][idx])foridxintop_k_idx]returntop_k# 使用示例classifierResNetClassifier(resnet50.om)fromPILimportImage imageImage.open(cat.jpg)top5classifier.top_k(image,k5)forclass_name,probintop5:print(f{class_name}:{prob:.4f})三、检测模型部署3.1 YOLO 部署importtorch# 1. 导出 YOLO ONNXfromultralyticsimportYOLO modelYOLO(yolov8n.pt)# 导出model.export(formatonnx,imgsz640,simplifyTrue)print(YOLO ONNX 已导出)# 2. YOLO 后处理classYOLOPostprocessor:def__init__(self,conf_threshold0.5,iou_threshold0.45):self.conf_thresholdconf_threshold self.iou_thresholdiou_thresholddefprocess(self,output,original_size):YOLO 后处理# output shape: (1, 84, 8400) for YOLOv8# 转置outputoutput[0].T# (8400, 84)# 提取边界框和类别boxesoutput[:,:4]# x1, y1, x2, y2scoresoutput[:,4:]# 类别分数# 获取最大类别分数max_scoresnp.max(scores,axis1)class_idsnp.argmax(scores,axis1)# 过滤低置信度maskmax_scoresself.conf_threshold boxesboxes[mask]max_scoresmax_scores[mask]class_idsclass_ids[mask]# NMSkeep_idsself._nms(boxes,max_scores,self.iou_threshold)# 缩放到原始尺寸boxesboxes[keep_ids]boxesself._scale_boxes(boxes,original_size)return{boxes:boxes,scores:max_scores[keep_ids],class_ids:class_ids[keep_ids]}def_nms(self,boxes,scores,iou_threshold):非极大值抑制x1boxes[:,0]y1boxes[:,1]x2boxes[:,2]y2boxes[:,3]areas(x2-x1)*(y2-y1)orderscores.argsort()[::-1]keep[]whilelen(order)0:iorder[0]keep.append(i)xx1np.maximum(x1[i],x1[order[1:]])yy1np.maximum(y1[i],y1[order[1:]])xx2np.minimum(x2[i],x2[order[1:]])yy2np.minimum(y2[i],y2[order[1:]])wnp.maximum(0,xx2-xx1)hnp.maximum(0,yy2-yy1)intersectionw*h iouintersection/(areas[i]areas[order[1:]]-intersection)indsnp.where(iouiou_threshold)[0]orderorder[inds1]returnkeepdef_scale_boxes(self,boxes,original_size):缩放边界框orig_h,orig_woriginal_size# 假设输入是 640x640scale_xorig_w/640scale_yorig_h/640boxes[:,[0,2]]*scale_x boxes[:,[1,3]]*scale_yreturnboxes# 使用示例yoloYOLOInference(yolov8n.om)postprocessorYOLOPostprocessor(conf_threshold0.5)imageload_image(street.jpg)raw_outputyolo.detect(image)detectionspostprocessor.process(raw_output,image.shape[:2])# 绘制结果forbox,score,class_idinzip(detections[boxes],detections[scores],detections[class_ids]):print(f类别:{class_id}, 置信度:{score:.4f}, 边界框:{box})四、分割模型部署4.1 U-Net 部署classUNetSegmentor:def__init__(self,model_path):self.modelself._load_model(model_path)defsegment(self,image):语义分割# 预处理input_dataself.preprocess(image)# 推理outputself._run_model(input_data)# 后处理maskself.postprocess(output,image.shape[:2])returnmaskdefpreprocess(self,image):预处理fromPILimportImage# Resize 到模型输入尺寸imageimage.resize((256,256))# 转 numpyimagenp.array(image)/255.0# 归一化image(image-[0.485,0.456,0.406])/[0.229,0.224,0.225]# 转置 CHWimageimage.transpose(2,0,1)# 添加 batch 维度imagenp.expand_dims(image,axis0).astype(np.float32)returnimagedefpostprocess(self,output,original_size):后处理# output shape: (1, num_classes, H, W)# 获取类别masknp.argmax(output[0],axis0)# 缩放到原始尺寸masknp.array(Image.fromarray(mask.astype(np.uint8)).resize((original_size[1],original_size[0]),Image.NEAREST))returnmask# 使用示例segmentorUNetSegmentor(unet.om)imageImage.open(medical.jpg)masksegmentor.segment(image)print(f分割掩码形状:{mask.shape})print(f类别数:{len(np.unique(mask))})五、常见问题问题原因解决方案检测框不准后处理参数不对调整 NMS 阈值分割边缘模糊输出分辨率低使用上采样或高分辨率模型推理速度慢预处理在 CPU使用 NPU 预处理类别错误ImageNet 类别映射错检查类别文件显存不足输入分辨率太大降低分辨率或使用分块推理相关仓库torchvision- 视觉模型 https://gitee.com/pytorch/visionultralytics- YOLO 模型 https://github.com/ultralytics/ultralyticstorch_npu- 昇腾推理 https://gitee.com/ascend/torch_npu