YOLO实例分割与OpenCV在工业缺陷检测中的实战应用
2026/7/13 8:22:51 网站建设 项目流程

在工业质检、医疗影像和安防监控等实际场景中,缺陷识别往往需要同时完成两个任务:不仅要找到缺陷的位置(目标检测),还要精确描绘缺陷的轮廓(分割检测)。传统方法要么只能框出大致区域,要么分割速度跟不上产线节奏。YOLO 作为单阶段检测算法的代表,从 YOLOv8 开始原生支持实例分割,配合 OpenCV 的图像处理能力,可以在保证实时性的前提下实现像素级缺陷定位。

本文面向计算机视觉方向的毕业设计学生和工程实践开发者,将完整演示如何基于 YOLO 和 OpenCV 构建一个覆盖目标检测与实例分割的缺陷识别系统。我们将从环境配置开始,逐步完成数据准备、模型训练、推理部署和效果验证,重点解释 YOLO 分割模型的输出结构解析、OpenCV 后处理技巧以及常见工业缺陷的适配方法。最终实现一个可对焊接缺陷、表面划痕等典型问题进行检测和分割的完整流程。

1. 理解 YOLO 分割模型的工作机制

1.1 YOLO 目标检测与实例分割的差异

YOLO 的目标检测任务输出的是边界框(Bounding Box)和类别概率,而实例分割在此基础上增加了掩码(Mask)预测。YOLOv8-seg 模型在检测头之后连接了一个分割头,通过原型掩码和掩码系数来生成实例级别的分割结果。

关键区别在于:

  • 目标检测:输出格式为[x_center, y_center, width, height, confidence, class_prob]
  • 实例分割:在检测结果基础上增加[mask_coefficients],需要与原型掩码矩阵相乘得到最终掩码

1.2 YOLO 分割模型的数据流

YOLO 分割模型的推理流程可以分解为三个主要阶段:

  1. 特征提取:Backbone 网络(通常是 CSPDarknet)提取多尺度特征
  2. 检测与分割头:Neck 部分(PAN-FPN)融合特征,检测头预测边界框和类别,分割头预测掩码系数
  3. 后处理:对原始输出进行非极大值抑制(NMS)和掩码重构
import torch from ultralytics import YOLO # 加载预训练的分割模型 model = YOLO('yolov8n-seg.pt') # 查看模型结构 print(model.model)

模型输出包含两个部分:

  • det_output:形状为[1, 116, 8400]的检测结果(116 = 4坐标 + 1置信度 + 80类别 + 32掩码系数)
  • proto:形状为[1, 32, 160, 160]的原型掩码

1.3 掩码重构的数学原理

分割结果的生成过程可以表示为:

def process_mask(protos, masks_in, bboxes, shape): """ protos: [1, 32, 160, 160] 原型掩码 masks_in: [n, 32] 掩码系数 bboxes: [n, 4] 边界框坐标 shape: 原始图像尺寸 """ # 矩阵乘法得到粗粒度掩码 c, mh, mw = protos.shape # 32, 160, 160 masks = (masks_in @ protos.reshape(c, -1)).reshape(-1, mh, mw) # 通过sigmoid激活 masks = masks.sigmoid() # 根据边界框坐标裁剪和缩放掩码 masks = crop_mask(masks, bboxes) masks = F.interpolate(masks[None], shape, mode='bilinear', align_corners=False)[0] return masks.gt(0.5) # 二值化

理解这个机制对于后续自定义后处理和优化性能至关重要。

2. 环境准备与依赖配置

2.1 基础环境要求

缺陷识别项目对环境和版本有较强依赖,建议使用以下配置:

组件推荐版本备注
Python3.8-3.103.11+可能存在兼容性问题
PyTorch2.0+需要CUDA 11.7/11.8
Ultralytics8.0+YOLOv8官方库
OpenCV4.5+图像处理核心库
CUDA11.7/11.8GPU加速(可选)

2.2 详细安装步骤

创建并激活conda环境:

conda create -n yolo_defect python=3.9 conda activate yolo_defect

安装PyTorch(根据CUDA版本选择):

# CUDA 11.7 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu117 # 或CPU版本 pip install torch torchvision torchaudio

安装项目依赖:

pip install ultralytics opencv-python pillow matplotlib seaborn pip install albumentations # 数据增强 pip install wandb # 实验跟踪(可选)

2.3 环境验证脚本

创建验证脚本检查关键组件:

# check_environment.py import torch import cv2 from ultralytics import YOLO import numpy as np def check_environment(): print("=== 环境检查 ===") # 检查PyTorch print(f"PyTorch版本: {torch.__version__}") print(f"CUDA可用: {torch.cuda.is_available()}") if torch.cuda.is_available(): print(f"GPU设备: {torch.cuda.get_device_name(0)}") # 检查OpenCV print(f"OpenCV版本: {cv2.__version__}") # 检查Ultralytics try: model = YOLO('yolov8n-seg.pt') print("YOLO模型加载成功") except Exception as e: print(f"YOLO加载失败: {e}") # 测试基本功能 test_image = np.random.randint(0, 255, (640, 640, 3), dtype=np.uint8) results = model(test_image, verbose=False) print("推理测试通过") if __name__ == "__main__": check_environment()

运行验证脚本确保环境正常:

python check_environment.py

3. 缺陷数据集准备与标注

3.1 缺陷数据类型与特点

工业缺陷识别项目常见的数据类型:

缺陷类别典型场景数据特点标注难点
表面划痕金属加工、玻璃制造细长、低对比度边界模糊,易漏标
焊接缺陷制造业、建筑业形状不规则,尺寸多变与背景对比度低
气泡杂质塑料制品、食品包装圆形或椭圆形,大小不一密集小目标检测
腐蚀斑点管道检测、设备维护颜色变化,纹理异常需要多尺度检测

3.2 数据标注规范

使用LabelImg或更专业的CVAT进行标注时,需要统一规范:

  1. 边界框标注:完全包围缺陷区域,不留过多空白
  2. 多边形标注:对于分割任务,使用多边形精确勾勒缺陷轮廓
  3. 类别定义:明确定义每个缺陷类别的判断标准
  4. 质量检查:确保标注的一致性和准确性

YOLO格式的标注文件示例:

# 目标检测格式 (class x_center y_center width height) 0 0.512 0.634 0.124 0.089 # 实例分割格式 (class x_center y_center width height mask_points...) 0 0.512 0.634 0.124 0.089 0.501 0.621 0.523 0.625 0.518 0.647 ...

3.3 数据增强策略

针对缺陷检测的特点,设计合适的数据增强管道:

import albumentations as A from albumentations.pytorch import ToTensorV2 def get_train_transform(image_size=640): return A.Compose([ A.HorizontalFlip(p=0.5), A.VerticalFlip(p=0.5), A.RandomRotate90(p=0.5), A.RandomBrightnessContrast(p=0.2), A.GaussNoise(var_limit=(10.0, 50.0), p=0.3), A.MotionBlur(blur_limit=3, p=0.2), A.CoarseDropout(max_holes=8, max_height=32, max_width=32, p=0.3), A.Resize(image_size, image_size), A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ToTensorV2(), ], bbox_params=A.BboxParams(format='yolo', label_fields=['class_labels'])) def get_val_transform(image_size=640): return A.Compose([ A.Resize(image_size, image_size), A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ToTensorV2(), ])

3.4 数据集目录结构

规范的数据集结构对于训练至关重要:

defect_dataset/ ├── images/ │ ├── train/ │ │ ├── defect_001.jpg │ │ ├── defect_002.jpg │ │ └── ... │ └── val/ │ ├── defect_101.jpg │ ├── defect_102.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── defect_001.txt │ │ ├── defect_002.txt │ │ └── ... │ └── val/ │ ├── defect_101.txt │ ├── defect_102.txt │ └── ... └── dataset.yaml

数据集配置文件dataset.yaml

# dataset.yaml path: /path/to/defect_dataset train: images/train val: images/val nc: 3 # 类别数量 names: ['scratch', 'weld_defect', 'corrosion'] # 类别名称 # 可选配置 roboflow: workspace: your-workspace project: your-project version: 1

4. YOLO 分割模型训练与优化

4.1 模型选择与预训练权重

根据硬件条件和精度要求选择合适的模型:

模型参数量推理速度适用场景
YOLOv8n-seg3.2M最快移动端、边缘设备
YOLOv8s-seg11.2M较快通用工业场景
YOLOv8m-seg25.9M中等高精度要求
YOLOv8l-seg43.7M较慢研究实验
YOLOv8x-seg68.2M最慢极限精度追求

加载预训练权重:

from ultralytics import YOLO # 加载COCO预训练的分割模型 model = YOLO('yolov8s-seg.pt') # 查看模型信息 print(f"模型类别数: {model.model.nc}") print(f"模型输入尺寸: {model.model.args['imgsz']}")

4.2 训练参数配置

针对缺陷检测任务优化训练参数:

# 训练配置 def train_defect_model(): model = YOLO('yolov8s-seg.pt') results = model.train( data='dataset.yaml', epochs=100, imgsz=640, batch=16, lr0=0.01, lrf=0.01, momentum=0.937, weight_decay=0.0005, warmup_epochs=3.0, warmup_momentum=0.8, box=7.5, # 边界框损失权重 cls=0.5, # 分类损失权重 dfl=1.5, # 分布焦点损失权重 pose=12.0, # 姿态损失权重(分割任务相关) kobj=1.0, # 关键点对象损失权重 overlap_mask=True, # 训练时掩码重叠处理 mask_ratio=4, # 掩码下采样比率 optimizer='auto', verbose=True, save=True, device=0, # GPU设备 workers=8, project='defect_detection', name='exp1' ) return results

4.3 训练过程监控

使用内置工具和自定义回调监控训练:

from ultralytics import YOLO import matplotlib.pyplot as plt def monitor_training(): model = YOLO('yolov8s-seg.pt') # 添加自定义回调 def on_train_epoch_end(trainer): metrics = trainer.metrics print(f"Epoch {trainer.epoch}: " f"box_loss={metrics.get('train/box_loss', 0):.3f}, " f"seg_loss={metrics.get('train/seg_loss', 0):.3f}") model.add_callback('on_train_epoch_end', on_train_epoch_end) # 开始训练 results = model.train( data='dataset.yaml', epochs=100, imgsz=640, ... ) # 绘制训练曲线 results.plot() plt.savefig('training_metrics.png')

4.4 模型评估与选择

训练完成后评估模型性能:

def evaluate_model(model_path='runs/segment/exp1/weights/best.pt'): model = YOLO(model_path) # 在验证集上评估 metrics = model.val( data='dataset.yaml', split='val', imgsz=640, conf=0.25, # 置信度阈值 iou=0.6, # IoU阈值 device=0 ) print(f"mAP50: {metrics.box.map50:.3f}") print(f"mAP50-95: {metrics.box.map:.3f}") print(f"掩码mAP50: {metrics.seg.map50:.3f}") print(f"掩码mAP50-95: {metrics.seg.map:.3f}") return metrics # 比较多个模型 def compare_models(): models = { 'yolov8n': 'yolov8n-seg.pt', 'yolov8s': 'yolov8s-seg.pt', 'yolov8m': 'yolov8m-seg.pt' } results = {} for name, path in models.items(): print(f"评估 {name}...") results[name] = evaluate_model(path) return results

5. OpenCV 与 YOLO 集成推理

5.1 模型加载与初始化

使用OpenCV的dnn模块加载YOLO模型:

import cv2 import numpy as np class YOLOSegmentation: def __init__(self, model_path, conf_threshold=0.5, nms_threshold=0.5): self.conf_threshold = conf_threshold self.nms_threshold = nms_threshold # 加载模型 self.net = cv2.dnn.readNet(model_path) # 获取输出层名称 layer_names = self.net.getLayerNames() output_layers = [layer_names[i - 1] for i in self.net.getUnconnectedOutLayers()] # 尝试设置推理后端(GPU加速) try: self.net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA) self.net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA) print("使用CUDA加速") except: print("使用CPU推理") def preprocess(self, image): """图像预处理""" # 调整尺寸到模型输入大小 blob = cv2.dnn.blobFromImage( image, 1/255.0, (640, 640), swapRB=True, crop=False ) return blob

5.2 推理与后处理

实现完整的推理管道:

def infer(self, image): """执行推理""" # 预处理 blob = self.preprocess(image) self.net.setInput(blob) # 推理 outputs = self.net.forward() # 后处理 boxes, confidences, class_ids, masks = self.postprocess(outputs, image.shape) return boxes, confidences, class_ids, masks def postprocess(self, outputs, image_shape): """后处理:解析输出,应用NMS,重构掩码""" height, width = image_shape[:2] boxes = [] confidences = [] class_ids = [] masks = [] # 解析输出(YOLOv8输出格式) # outputs[0]: 检测结果 [1, 116, 8400] # outputs[1]: 原型掩码 [1, 32, 160, 160] detection_output = outputs[0] proto_output = outputs[1] if len(outputs) > 1 else None # 转置并重塑检测结果 detection_output = detection_output[0].T num_detections = detection_output.shape[0] for i in range(num_detections): detection = detection_output[i] scores = detection[4:4+80] # COCO 80类别 class_id = np.argmax(scores) confidence = scores[class_id] if confidence > self.conf_threshold: # 解析边界框(cx, cy, w, h 格式) cx, cy, w, h = detection[0:4] # 转换为像素坐标 x = int((cx - w/2) * width) y = int((cy - h/2) * height) w = int(w * width) h = int(h * height) boxes.append([x, y, w, h]) confidences.append(float(confidence)) class_ids.append(class_id) # 解析掩码系数(如果有分割输出) if proto_output is not None and detection.shape[0] > 84: mask_coeff = detection[84:84+32] masks.append(mask_coeff) # 应用NMS indices = cv2.dnn.NMSBoxes(boxes, confidences, self.conf_threshold, self.nms_threshold) if len(indices) > 0: indices = indices.flatten() boxes = [boxes[i] for i in indices] confidences = [confidences[i] for i in indices] class_ids = [class_ids[i] for i in indices] masks = [masks[i] for i in indices] if masks else [] return boxes, confidences, class_ids, masks

5.3 掩码可视化与结果渲染

使用OpenCV绘制检测和分割结果:

def draw_detections(self, image, boxes, confidences, class_ids, masks=None, class_names=None): """绘制检测结果和分割掩码""" result = image.copy() for i, (box, confidence, class_id) in enumerate(zip(boxes, confidences, class_ids)): x, y, w, h = box # 绘制边界框 color = self.get_color(class_id) cv2.rectangle(result, (x, y), (x + w, y + h), color, 2) # 绘制标签 label = f"{class_names[class_id] if class_names else class_id}: {confidence:.2f}" label_size = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 2)[0] cv2.rectangle(result, (x, y - label_size[1] - 10), (x + label_size[0], y), color, -1) cv2.putText(result, label, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2) # 绘制分割掩码 if masks and i < len(masks): mask = self.reconstruct_mask(masks[i], proto_output, box, image.shape) self.draw_mask(result, mask, color, alpha=0.3) return result def reconstruct_mask(self, mask_coeff, proto, box, image_shape): """重构分割掩码""" # 简化版掩码重构 # 实际实现需要完整的原型掩码处理 mask = np.zeros(image_shape[:2], dtype=np.uint8) x, y, w, h = box # 创建粗略掩码(实际项目需要完整实现) cv2.rectangle(mask, (x, y), (x + w, y + h), 255, -1) return mask def draw_mask(self, image, mask, color, alpha=0.3): """在图像上绘制半透明掩码""" # 创建彩色掩码 color_mask = np.zeros_like(image) color_mask[mask > 0] = color # 融合到原图 cv2.addWeighted(color_mask, alpha, image, 1 - alpha, 0, image) # 绘制掩码边界 contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cv2.drawContours(image, contours, -1, color, 2) def get_color(self, class_id): """根据类别ID生成颜色""" colors = [ (255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (255, 0, 255), (0, 255, 255), (128, 0, 0), (0, 128, 0), (0, 0, 128) ] return colors[class_id % len(colors)]

6. 完整缺陷识别系统实现

6.1 系统架构设计

构建完整的缺陷识别流水线:

import cv2 import numpy as np from pathlib import Path import time class DefectDetectionSystem: def __init__(self, model_path, class_names=None): self.detector = YOLOSegmentation(model_path) self.class_names = class_names or [] # 统计信息 self.frame_count = 0 self.processing_times = [] def process_image(self, image_path): """处理单张图像""" start_time = time.time() # 读取图像 image = cv2.imread(image_path) if image is None: print(f"无法读取图像: {image_path}") return None # 执行推理 boxes, confidences, class_ids, masks = self.detector.infer(image) # 绘制结果 result = self.detector.draw_detections( image, boxes, confidences, class_ids, masks, self.class_names ) # 计算处理时间 processing_time = time.time() - start_time self.processing_times.append(processing_time) self.frame_count += 1 print(f"检测到 {len(boxes)} 个缺陷,处理时间: {processing_time:.3f}s") return result, boxes, confidences, class_ids def process_video(self, video_path, output_path=None): """处理视频流""" cap = cv2.VideoCapture(video_path) if not cap.isOpened(): print(f"无法打开视频: {video_path}") return # 获取视频属性 fps = cap.get(cv2.CAP_PROP_FPS) width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 设置输出视频 if output_path: fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter(output_path, fourcc, fps, (width, height)) frame_id = 0 while True: ret, frame = cap.read() if not ret: break # 处理每一帧 result, boxes, confidences, class_ids = self.process_image_frame(frame) # 显示结果 cv2.imshow('Defect Detection', result) # 写入输出视频 if output_path: out.write(result) # 按q退出 if cv2.waitKey(1) & 0xFF == ord('q'): break frame_id += 1 # 释放资源 cap.release() if output_path: out.release() cv2.destroyAllWindows() # 打印性能统计 self.print_statistics() def process_image_frame(self, frame): """处理视频帧的简化版本""" boxes, confidences, class_ids, masks = self.detector.infer(frame) result = self.detector.draw_detections( frame, boxes, confidences, class_ids, masks, self.class_names ) return result, boxes, confidences, class_ids def print_statistics(self): """打印性能统计""" if self.processing_times: avg_time = np.mean(self.processing_times) fps = 1.0 / avg_time if avg_time > 0 else 0 print(f"\n=== 性能统计 ===") print(f"总处理帧数: {self.frame_count}") print(f"平均处理时间: {avg_time:.3f}s") print(f"估计FPS: {fps:.1f}") print(f"最长处理时间: {max(self.processing_times):.3f}s") print(f"最短处理时间: {min(self.processing_times):.3f}s")

6.2 系统使用示例

def main(): # 初始化系统 class_names = ['scratch', 'weld_defect', 'corrosion', 'bubble'] system = DefectDetectionSystem( model_path='runs/segment/exp1/weights/best.pt', class_names=class_names ) # 处理单张图像 result, boxes, confidences, class_ids = system.process_image('test_image.jpg') if result is not None: cv2.imwrite('result.jpg', result) cv2.imshow('Result', result) cv2.waitKey(0) cv2.destroyAllWindows() # 处理视频(可选) # system.process_video('test_video.mp4', 'output_video.avi') if __name__ == "__main__": main()

7. 常见问题排查与优化

7.1 训练阶段问题

问题1:损失不收敛或震荡

可能原因和解决方案:

  • 学习率过高:逐步降低学习率,尝试lr0=0.001
  • 数据质量差:检查标注准确性,清理错误样本
  • 类别不平衡:使用数据增强或类别权重
  • 模型复杂度不匹配:换用更简单或更复杂的模型

问题2:过拟合

解决方案:

# 在训练配置中添加正则化 results = model.train( data='dataset.yaml', epochs=100, # 增加数据增强 hsv_h=0.015, # 图像色调增强 hsv_s=0.7, # 图像饱和度增强 hsv_v=0.4, # 图像明度增强 degrees=10.0, # 旋转角度范围 translate=0.1, # 平移范围 scale=0.5, # 缩放范围 # 早停机制 patience=10, # 早停耐心值 save_period=5 # 保存周期 )

7.2 推理阶段问题

问题3:推理速度慢

优化策略:

# 1. 模型量化 model.export(format='onnx', half=True) # FP16量化 # 2. 调整推理尺寸 results = model.predict(source, imgsz=320) # 减小输入尺寸 # 3. 批处理优化 results = model.predict(source, batch=4) # 批量推理 # 4. 后端优化 import torch torch.backends.cudnn.benchmark = True # 启用CuDNN基准测试

问题4:漏检或误检多

调整策略:

# 调整置信度阈值 results = model.predict( source, conf=0.3, # 降低阈值减少漏检 iou=0.5 # 调整NMS阈值 ) # 使用测试时增强(TTA) results = model.predict(source, augment=True) # 集成多个模型 def ensemble_predict(models, image): all_results = [] for model in models: results = model(image, verbose=False) all_results.extend(results[0].boxes if hasattr(results[0], 'boxes') else []) # 融合结果 return fuse_detections(all_results)

7.3 掩码质量问题

问题5:分割边界不精确

改进方法:

# 1. 后处理优化 def refine_mask(mask, box, image): """优化掩码边界""" x, y, w, h = box # 提取ROI区域 roi = image[y:y+h, x:x+w] mask_roi = mask[y:y+h, x:x+w] # 使用GrabCut优化边界 if np.sum(mask_roi) > 0: bgd_model = np.zeros((1, 65), np.float64) fgd_model = np.zeros((1, 65), np.float64) # 设置初始掩码 mask_grabcut = np.where(mask_roi > 0, 3, 2).astype('uint8') # 执行GrabCut cv2.grabCut(roi, mask_grabcut, None, bgd_model, fgd_model, 3, cv2.GC_INIT_WITH_MASK) # 更新掩码 refined_mask = np.where((mask_grabcut == 2) | (mask_grabcut == 0), 0, 1).astype('uint8') mask[y:y+h, x:x+w] = refined_mask * 255 return mask # 2. 多尺度测试 def multi_scale_inference(model, image, scales=[0.5, 1.0, 1.5]): """多尺度推理融合""" masks = [] for scale in scales: # 缩放图像 h, w = image.shape[:2] new_size = (int(w * scale), int(h * scale)) scaled_image = cv2.resize(image, new_size) # 推理 results = model(scaled_image, verbose=False) if hasattr(results[0], 'masks') and results[0].masks is not None: mask = results[0].masks.data[0].cpu().numpy() mask = cv2.resize(mask, (w, h)) masks.append(mask) # 融合多个尺度的结果 if masks: fused_mask = np.mean(masks, axis=0) > 0.5 return fused_mask.astype(np.uint8) * 255 return None

8. 生产环境部署建议

8.1 性能优化清单

部署前需要检查的关键点:

检查项目标值检查方法
推理速度<100ms/帧批量测试100张图像
内存占用<2GB监控推理过程内存使用
GPU利用率>80%nvidia-smi监控
模型精度mAP50 >0.8在测试集上验证
稳定性连续运行24小时无崩溃压力测试

8.2 错误处理与日志

生产环境需要完善的错误处理:

import logging from datetime import datetime class ProductionDefectDetector: def __init__(self, model_path, log_file='defect_detection.log'): self.setup_logging(log_file) self.model = self.load_model_safely(model_path) def setup_logging(self, log_file): """配置日志系统""" logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler(log_file), logging.StreamHandler() ] ) self.logger = logging.getLogger(__name__) def load_model_safely(self, model_path): """安全加载模型""" try: model = YOLO(model_path) self.logger.info(f"模型加载成功: {model_path}") return model except Exception as e: self.logger.error(f"模型加载失败: {e}") raise def process_with_fallback(self, image): """带降级处理的推理""" try: results = self.model(image, verbose=False) # 验证结果完整性 if not results or len(results) == 0: self.logger.warning("推理结果为空") return [], [], [], [] result = results[0] boxes = result.boxes.xywh if hasattr(result, 'boxes') else [] confidences = result.boxes.conf if hasattr(result, 'boxes') else [] class_ids = result.boxes.cls if hasattr(result, 'boxes') else [] masks = result.masks.data if hasattr(result, 'masks') else [] return boxes, confidences, class_ids, masks except Exception as e: self.logger.error(f"推理过程错误: {e}") # 返回空结果,避免系统崩溃 return [], [], [], []

8.3 监控与维护

建立完整的监控体系:

import psutil import GPUtil class SystemMonitor: def __init__(self): self.metrics = { 'inference_count': 0, 'error_count

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询