保姆级教程:修改YOLOv8的plotting.py,让分割结果图自动显示每个目标的掩膜面积

张开发
2026/4/20 2:07:21 15 分钟阅读

分享文章

保姆级教程:修改YOLOv8的plotting.py,让分割结果图自动显示每个目标的掩膜面积
深度定制YOLOv8分割可视化为每个目标自动标注掩膜面积的技术实现在计算机视觉项目的实际落地过程中模型输出的可视化效果往往直接影响着技术方案的沟通效率和决策质量。当我们使用YOLOv8进行实例分割任务时默认的可视化输出虽然能够展示目标的边界框和类别信息但缺乏对分割区域量化指标的直观呈现——特别是每个目标的掩膜面积数据。这种缺失使得我们在进行效果评估、结果汇报或进一步分析时不得不额外编写脚本来提取这些基础指标严重影响了工作效率。1. 理解YOLOv8分割输出的数据结构要实现对掩膜面积的自动标注首先需要深入理解YOLOv8分割模型的输出结构。当我们使用如下代码进行预测时from ultralytics import YOLO model YOLO(yolov8n-seg.pt) results model(bus.jpg)得到的results对象是一个包含丰富信息的容器。对于分割任务以下几个关键属性尤为重要boxes包含检测框的坐标、置信度和类别信息masks存储每个检测目标的分割掩膜names类别名称的字典映射掩膜数据的核心是形状为(n,h,w)的张量其中n是目标数量h和w是掩膜的高度和宽度。这个张量中的每个元素值为0或1表示该像素是否属于对应目标的掩膜区域。提示在YOLOv8的处理流程中原始图像会先被缩放到统一尺寸进行推理掩膜数据默认也是在这个缩放后的尺寸上生成的。如果需要原始尺寸的掩膜需要通过scale_image函数进行转换。2. 掩膜面积计算的两种技术方案计算掩膜面积主要有两种方法论各有其适用场景和技术特点2.1 基于轮廓几何计算的方法这种方法利用OpenCV的cv2.contourArea()函数通过目标的轮廓点计算几何面积。其核心代码如下import cv2 for mask in masks: contour mask.xy[0] # 获取第一个目标的轮廓点 area cv2.contourArea(contour) print(f轮廓面积: {area})特点对比方法特性轮廓计算法像素计数法计算维度几何面积实际像素数中空处理忽略内部空洞计算全部像素计算效率较高中等适用场景需要几何面积时需要精确像素计数时2.2 基于像素直接计数的方法这种方法直接统计掩膜中非零像素的数量更直接反映实际的像素覆盖面积import torch for mask in masks: pixel_count torch.sum(mask.data).item() print(f像素数量: {pixel_count})在实际项目中选择哪种方法取决于具体需求。如果关注目标的物理尺寸如实际场景中的面积轮廓计算法可能更合适如果需要精确的像素级统计如医学图像分析则像素计数法更为准确。3. 修改plotting.py实现自动面积标注要实现分割结果图中自动显示掩膜面积的功能我们需要修改Ultralytics库中的plotting.py文件。具体位置通常在Python环境的site-packages/ultralytics/utils/plotting.py。3.1 定位关键修改点找到Annotator类中的masks方法这是负责绘制分割掩膜的核心函数。我们需要在绘制掩膜的同时添加面积标注的功能。3.2 实现代码修改以下是修改后的masks方法关键部分def masks(self, masks, colors, im_gpu, alpha0.5, retina_masksFalse): # ...原有代码保持不变... # 新增面积标注功能 for i in range(len(masks)): mask_area torch.sum(masks[i]).item() mask_positions np.where(masks[i].cpu().numpy() 0) if len(mask_positions[0]) 0: # 确保有有效像素 center_x int(np.mean(mask_positions[1])) center_y int(np.mean(mask_positions[0])) # 计算文本位置避免超出图像边界 text_x max(10, min(center_x - 30, self.im.shape[1] - 50)) text_y max(20, min(center_y, self.im.shape[0] - 10)) # 白色文本带黑色描边确保在各种背景下可读 cv2.putText(im_mask_np, f{int(mask_area)}, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,0,0), 3) # 黑色描边 cv2.putText(im_mask_np, f{int(mask_area)}, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255,255,255), 1) # 白色文本 # ...后续代码保持不变...3.3 修改后的效果验证修改完成后运行标准预测代码model YOLO(yolov8n-seg.pt) results model(zidane.jpg, saveTrue)输出图像将在每个目标的掩膜附近显示其像素面积如下图所示[人: 57275] [领带: 2563] [人: 38664]4. 高级定制与疑难排解4.1 处理多尺度预测的场景当处理不同尺寸的输入图像时需要注意面积值的实际意义。YOLOv8默认会将图像缩放到640x640或指定尺寸进行推理因此直接计算的面积是基于这个尺寸的。如果需要原始图像尺寸的面积可以通过以下方式转换from ultralytics.utils.ops import scale_image # 获取原始尺寸的掩膜 orig_mask scale_image(mask.data.cpu().numpy(), mask.orig_shape) orig_area orig_mask.sum()4.2 常见错误与解决方案文本位置超出图像边界解决方法在调用cv2.putText前检查计算出的文本位置是否在图像范围内面积值显示重叠优化方案对于密集目标可以采用偏移策略将面积值显示在目标中心的上方或下方性能下降问题优化建议对于实时性要求高的场景可以考虑只在最后几帧显示面积信息4.3 扩展功能实现除了基本面积显示还可以通过修改代码实现更多实用功能显示类别和置信度text f{names[cls]}:{conf:.1f} ({area})不同颜色区分大小color (0,255,0) if area threshold else (0,0,255)导出CSV报告import pandas as pd data [] for result in results: for box, mask in zip(result.boxes, result.masks): data.append({ class: names[int(box.cls)], confidence: float(box.conf), area: float(torch.sum(mask.data).item()) }) pd.DataFrame(data).to_csv(report.csv, indexFalse)5. 工程实践中的优化建议在实际项目部署时还需要考虑以下工程化因素性能考量面积计算和文本渲染会增加少量计算开销对于批量处理可以考虑异步渲染方式可视化清晰度使用高对比度的文本颜色添加文本背景框增强可读性根据目标大小动态调整字体大小多模态输出同时生成可视化图像和结构化数据报告支持不同尺寸单位的面积显示像素、平方毫米等版本兼容性注意不同YOLOv8版本中plotting.py的差异建议通过Git管理自定义修改便于后续升级在医疗影像分析项目中这种可视化增强帮助团队快速识别出异常大小的细胞区域在工业质检场景中质检员能立即发现尺寸不合格的零件。这种直观的反馈极大提升了模型结果的可解释性和实用性。

更多文章