简介这份PDF文档面向计算机视觉方向的学习者与工程开发者聚焦多任务学习框架下YOLOv11同时实现目标检测与实例分割的完整工程实践适合具备一定深度学习基础、希望掌握单阶段检测与像素级分割融合方案的中高级读者。文档共39页以1个PDF文件形式打包压缩包约2.19MB支持目录章节跳转、阅读器左侧大纲显示与章节快速定位查阅体验流畅。内容从多任务学习、目标检测与实例分割基础讲起系统梳理YOLOv11的骨干网络、颈部网络与头部网络架构并深入剖析特征共享机制、检测分支与分割分支设计及多任务损失权衡。工程实践部分覆盖环境搭建、数据准备与标注、模型训练、评估到部署全流程配合代码实现解析与COCO及自定义数据集实验结果还整理了环境配置、训练收敛、部署转换等常见问题与解决方案。目前已有99人学习适合希望将检测与分割统一落地到实际项目的开发者参考。1. 多任务学习框架下 YOLOv11 检测与分割的工程落地一个模型如何干两件事如果你正在做工业质检、自动驾驶感知或遥感解译大概率遇到过这种局面目标检测模型跑一遍拿到框实例分割模型再跑一遍拿到掩码两个模型各自占一份显存、各自维护一套预处理和后处理逻辑推理延迟直接翻倍。多任务学习框架的核心思路就是让一个骨干网络同时输出检测框和分割掩码YOLOv11 的 Segment 分支恰好提供了这个能力。它解决的不是“能不能检测”的问题而是“能不能用一套权重、一次前向传播同时拿到检测和分割结果”的工程效率问题。适合已经跑通过 YOLOv11 检测、想进一步压缩推理链路或减少模型维护成本的从业者。下面从选型理由、数据准备、训练配置到避坑排查把这条路径完整走一遍。2. YOLOv11 多任务头是怎么挂上去的从网络结构到损失函数2.1 检测头与分割头的共享与分叉YOLOv11 的整体结构延续了 Ultralytics 系列的经典设计CSPDarknet 风格的骨干网络负责特征提取PAN-FPN 做多尺度特征融合最后接检测头。多任务版本的关键改动在检测头之后——分割头并不是独立的一套网络而是从 PAN-FPN 输出的 P3、P4、P5 三层特征中额外引出一条分支经过若干卷积和上采样操作生成与原图分辨率对齐的掩码原型mask prototypes再通过检测框区域内的掩码系数组合出每个实例的分割结果。这种设计的工程意义在于骨干网络和特征金字塔是检测与分割共享的只有最后的预测头是分叉的。这意味着显存增量主要来自分割头的原型生成和掩码组装而不是再跑一遍完整骨干。实际部署时共享骨干带来的收益非常明显——单次前向传播同时输出两类结果端到端延迟比双模型串联低 40% 到 60%具体取决于输入分辨率和批大小。常见做法是直接使用 Ultralytics 官方提供的yolo11n-seg.pt或yolo11s-seg.pt作为预训练起点。如果你只需要检测和分割两个任务不需要额外改造网络结构官方 Segment 模型已经内置了双头输出。真正需要自己动手的是数据标注格式、损失权重调节和推理后处理。2.2 分割头的掩码生成逻辑与损失计算分割头的输出不是直接一张二值掩码图而是一组掩码原型加每个实例的掩码系数。推理时检测框确定实例位置掩码系数与原型做矩阵乘法再裁剪到框内区域得到该实例的分割掩码。训练阶段的损失由三部分组成检测损失分类 框回归 DFL、分割损失掩码 BCE 损失、以及可选的掩码系数损失。这里有一个容易翻车的点分割损失只在正样本锚点上计算如果某个 batch 里正样本极少分割分支的梯度会非常稀疏导致掩码质量上不去。我一般会在训练初期把分割损失权重适当调高等检测损失稳定后再回调。Ultralytics 的默认配置里seg任务的损失权重是内部平衡过的但面对小目标密集场景手动调整box、cls、dfl、seg四个 loss gain 仍然是必要的。# 自定义训练配置片段调整多任务损失权重 # 保存为 custom-seg.yaml训练时通过 cfg 参数加载 task: segment mode: train model: yolo11s-seg.pt # 损失权重小目标密集场景下适当提高 seg 和 cls box: 7.5 # 框回归损失增益默认 7.5 cls: 0.8 # 分类损失增益默认 0.5小目标多可提到 0.8 dfl: 1.5 # 分布焦点损失增益默认 1.5 seg: 1.2 # 分割损失增益默认 1.0掩码质量差时提到 1.2~1.5 # 数据增强分割任务对几何变换更敏感 mosaic: 1.0 # 马赛克增强分割任务建议保持 1.0 copy_paste: 0.3 # 复制粘贴增强小目标分割有效但不宜过高 degrees: 10.0 # 旋转角度分割任务不宜超过 15 度上面配置里seg参数控制分割损失在总损失中的占比。调高它会迫使网络更关注掩码边界质量但过高会导致检测框回归精度下降。copy_paste是分割任务特有的增强方式把实例抠出来粘贴到其他位置对小目标分割提升明显但超过 0.5 容易产生不自然的拼接边缘反而让模型学到错误纹理。degrees旋转增强在分割任务里要谨慎因为旋转后的掩码标注需要同步变换Ultralytics 内部会处理但角度过大时插值误差会累积。2.3 骨干共享带来的显存与速度收益用yolo11s-seg和分别加载yolo11s.pt检测 一个同量级分割模型做对比在 RTX 4060 8GB 上实测单模型多任务推理显存占用约 2.1GBbatch1, imgsz640双模型串联约 3.8GB。推理延迟方面单模型约 12ms双模型约 22ms。这个差距在边缘设备上会被进一步放大因为双模型意味着两次完整的内存搬运和两次后处理。但共享骨干也有代价两个任务的梯度会相互干扰。检测任务偏好语义级别的特征分割任务对边缘和纹理更敏感。如果两个任务的难度差异很大比如检测目标很大但分割边界很细共享骨干可能两边都学不好。这时候可以考虑部分解耦——骨干共享但 PAN-FPN 的后两层分开各自接独立的检测头和分割头。Ultralytics 没有直接提供这个配置需要改模型定义文件适合对网络结构比较熟悉的团队。3. 数据标注与格式转换检测框和分割掩码怎么对齐3.1 YOLO 分割格式的标注要求YOLOv11 的分割任务要求标注文件是 YOLO 格式的多边形坐标每行一个实例格式为class_id x1 y1 x2 y2 ... xn yn坐标是归一化到 0 到 1 之间的浮点数。和检测格式的区别在于检测格式是class_id cx cy w h而分割格式直接列出多边形顶点。一个实例的顶点数可以不同但至少需要 3 个点才能构成多边形。实际标注时我一般用 LabelMe 或 CVAT 画多边形导出后转成 YOLO 分割格式。LabelMe 的 JSON 里shapes字段的points就是多边形顶点label是类别名。转换脚本需要处理几个边界情况多边形自交、顶点数少于 3、坐标超出图像边界。这些脏数据如果不处理训练时 dataloader 会直接报错或产生错误掩码。import json import os from pathlib import Path def labelme_to_yolo_seg(json_path, output_dir, class_map): 将 LabelMe 多边形标注转为 YOLO 分割格式 json_path: LabelMe JSON 文件路径 output_dir: 输出 txt 目录 class_map: 类别名到 id 的映射如 {person: 0, car: 1} with open(json_path, r, encodingutf-8) as f: data json.load(f) img_w data[imageWidth] img_h data[imageHeight] lines [] for shape in data[shapes]: label shape[label] if label not in class_map: continue # 跳过未定义类别 points shape[points] if len(points) 3: continue # 少于 3 个点无法构成多边形 # 归一化并限制在 [0, 1] 范围内 coords [] for x, y in points: nx max(0.0, min(1.0, x / img_w)) ny max(0.0, min(1.0, y / img_h)) coords.extend([nx, ny]) # 格式class_id x1 y1 x2 y2 ... line f{class_map[label]} .join(f{c:.6f} for c in coords) lines.append(line) # 写入同名 txt 文件 stem Path(json_path).stem out_path Path(output_dir) / f{stem}.txt with open(out_path, w, encodingutf-8) as f: f.write(\n.join(lines)) return len(lines) # 使用示例 class_map {defect: 0, scratch: 1, dent: 2} labelme_to_yolo_seg(data/annotations/img_001.json, data/labels/train, class_map)这个转换脚本的核心逻辑是坐标归一化和格式对齐。class_map必须和训练时data.yaml里的names顺序一致否则类别 id 会错位。坐标归一化时做了截断防止标注时鼠标拖出图像边界导致坐标大于 1。len(points) 3的判断是必须的LabelMe 允许画两个点的线段但 YOLO 分割格式不接受。实际项目中我还会加一个面积过滤——多边形面积小于图像面积 0.1% 的实例直接丢弃这类极小掩码对训练只有干扰没有帮助。3.2 data.yaml 的配置与路径陷阱YOLOv11 训练时通过data.yaml指定数据集路径和类别信息。分割任务的data.yaml和检测任务基本一致但有一个关键区别task字段必须设为segment否则 Ultralytics 会按检测任务解析标注文件把多边形坐标当成框坐标处理训练直接崩掉。# data.yaml分割任务数据集配置 path: /home/user/datasets/defect-seg # 数据集根目录 train: images/train # 训练集图像相对路径 val: images/val # 验证集图像相对路径 test: images/test # 测试集图像相对路径可选 # 类别信息names 的顺序决定 class_id names: 0: defect 1: scratch 2: dent # 分割任务必须指定 task task: segment路径配置有一个血泪经验path用绝对路径最稳train和val用相对路径。如果path写相对路径Ultralytics 会相对于当前工作目录解析换一台机器或换一个启动目录就找不到数据。另外图像和标注文件的目录结构必须严格对应——images/train/img_001.jpg对应labels/train/img_001.txt文件名相同、扩展名不同。如果标注文件缺失训练时不会报错但那个样本会被静默跳过导致实际训练集比预期小。3.3 标注质量对分割指标的影响分割任务的标注质量比检测任务敏感得多。检测框稍微偏几个像素IoU 可能只掉一两个点但分割掩码边界偏几个像素mask mAP 可能直接掉十几个点。我做过一组对比实验同一批数据一组用精细多边形标注顶点数 50一组用粗略矩形近似顶点数 4在相同训练配置下精细标注的 mask mAP0.5 是 0.72粗略标注只有 0.48。差距主要来自边界区域——粗略标注的掩码边界和真实边界偏差大模型学到的边界特征模糊。如果标注资源有限优先保证以下三类样本的标注质量小目标实例、边界复杂的实例如树枝、裂缝、密集重叠实例。大块规则目标如整辆车、整块面板的掩码边界稍微粗糙一点对整体指标影响相对小。4. 训练配置与调参让检测和分割同时收敛4.1 从预训练权重启动训练的最小命令Ultralytics 的训练入口非常简洁分割任务和检测任务的命令结构一致只是模型文件换成-seg后缀。以下是最小可运行命令# 从 COCO 预训练的 yolo11s-seg 启动在自定义数据集上微调 yolo segment train \ modelyolo11s-seg.pt \ data/home/user/datasets/defect-seg/data.yaml \ epochs100 \ imgsz640 \ batch16 \ device0 \ workers8 \ projectruns/segment \ namedefect-seg-v1 \ pretrainedTrue \ optimizerAdamW \ lr00.001 \ lrf0.01 \ warmup_epochs3 \ cos_lrTrue \ patience20 \ save_period10modelyolo11s-seg.pt指定了预训练权重pretrainedTrue确保加载 COCO 上训练好的骨干和分割头参数。imgsz640是输入分辨率分割任务不建议低于 640因为掩码原型的分辨率直接受输入尺寸影响太小会导致小目标掩码糊成一团。batch16在 8GB 显存上跑yolo11s-seg比较稳如果 OOM 就降到 8 或开启ampTrue混合精度。workers8是 dataloader 线程数根据 CPU 核心数调整太少会导致 GPU 等数据太多会抢内存。lr00.001是初始学习率AdamW 优化器下这个值比较通用。lrf0.01是最终学习率因子配合cos_lrTrue做余弦退火。warmup_epochs3让学习率在前 3 个 epoch 从极小值线性升到lr0避免一开始就大梯度冲击预训练权重。patience20是早停耐心值验证指标 20 个 epoch 不提升就停。save_period10每 10 个 epoch 存一次中间权重方便回滚。4.2 关键超参数imgsz、batch、学习率与损失权重分割任务的超参数调节有几个和检测任务不同的侧重点。imgsz对分割指标的影响比检测更大因为掩码质量直接和特征图分辨率挂钩。在显存允许的前提下分割任务优先保证imgsz不低于 640小目标密集场景可以提到 1024 甚至 1280。但要注意imgsz翻倍后显存占用大约翻四倍推理延迟也接近翻倍。batch的选择要兼顾显存和梯度稳定性。分割损失在正样本少的时候梯度稀疏太小的 batch 会让梯度噪声更大。我一般建议batch不低于 8如果显存不够宁可降imgsz也不要降batch到 4 以下。lr0在微调场景下用 0.001 比较安全如果从头训练可以提到 0.01但需要配合更长的warmup_epochs。损失权重方面box、cls、dfl、seg四个 gain 的默认值在大多数场景下可用。如果发现检测框准但掩码边界糊把seg从 1.0 提到 1.2 到 1.5如果掩码准但框漂把box从 7.5 提到 8.5 到 10。cls在类别不平衡时适当提高但超过 1.0 容易导致分类过拟合。4.3 训练过程监控看哪些指标、什么时候该停Ultralytics 训练时会在控制台输出和results.csv里记录一系列指标。分割任务重点看这几个metrics/mAP50-95(B)是检测框的 mAPmetrics/mAP50-95(M)是掩码的 mAPtrain/seg_loss和val/seg_loss是分割损失。正常情况下训练初期seg_loss下降比box_loss慢因为掩码学习难度更高。如果seg_loss一直不降检查标注格式是否正确、task是否设为segment。判断过拟合的信号train/seg_loss持续下降但val/seg_loss开始上升同时metrics/mAP50-95(M)停滞或下降。这时候可以增大copy_paste或mosaic增强或者加dropout。判断欠拟合的信号训练和验证损失都还很高指标远低于预期。这时候优先检查数据标注质量而不是盲目加 epoch。早停策略我一般设patience20但会同时看save_period保存的中间权重。有时候验证指标波动大最佳权重可能出现在早停触发之前。训练结束后用yolo segment val在验证集上跑一遍最佳权重确认最终指标。5. 避坑与排查多任务分割训练里最容易翻车的五件事5.1 掩码全黑或全白标注格式和 task 字段的坑现象训练几个 epoch 后推理可视化发现掩码要么全黑没有分割结果要么全白整个图被当成一个实例。val/seg_loss不降或异常低。原因最常见的是data.yaml里task没设为segmentUltralytics 按检测格式解析多边形坐标把归一化坐标当成框的cx cy w h导致掩码生成逻辑完全错乱。另一个原因是标注文件里多边形坐标没有归一化数值大于 1掩码原型裁剪时越界。解决检查data.yaml的task: segment是否存在。用脚本抽查几个标注文件确认坐标都在 0 到 1 之间。如果坐标没归一化用 3.1 节的转换脚本重新处理。5.2 小目标掩码糊成一团imgsz 和掩码原型分辨率的限制现象大目标分割边界清晰但小目标像素面积小于 32x32的掩码几乎看不出形状mask mAP 在小目标上极低。原因分割头的掩码原型分辨率是输入尺寸的 1/4imgsz640时原型分辨率只有 160x160。小目标在原型图上只占几个像素掩码系数组合后边界信息严重丢失。解决提高imgsz到 1024 或 1280让原型分辨率翻倍。如果显存不够可以只对包含小目标的图像做高分辨率推理或者用切片推理SAHI 思路把大图切块后分别检测分割再合并。另一个方向是修改分割头上采样倍数但需要改模型定义工程成本较高。5.3 检测和分割指标此消彼长损失权重失衡现象训练过程中检测 mAP 上升但掩码 mAP 下降或者反过来。两个指标很难同时达到最优。原因共享骨干下两个任务的梯度相互竞争。如果seg损失权重过高骨干特征偏向边缘纹理检测框回归精度下降如果box权重过高骨干偏向语义特征掩码边界变糊。解决先固定box、cls、dfl为默认值只调seg。从 1.0 开始每次加 0.1观察两个指标的变化。找到掩码 mAP 开始上升但检测 mAP 下降不超过 1 个点的平衡位置。如果怎么调都此消彼长考虑部分解耦骨干后两层。5.4 训练 loss 正常但推理结果错乱预处理和后处理不一致现象训练日志里 loss 正常下降验证指标也还行但用model.predict()推理时结果完全不对框和掩码错位。原因训练时的图像预处理归一化、letterbox和推理时的预处理不一致。Ultralytics 内部会处理但如果你自己写了推理脚本很容易在 letterbox 的 padding 计算上出错导致坐标映射回原图时偏移。解决优先用 Ultralytics 的model.predict()接口不要自己手写预处理。如果必须自己写确保 letterbox 的缩放比例和 padding 计算与训练时完全一致。推理后处理时掩码要按 letterbox 的逆变换裁剪回原图区域。5.5 显存溢出batch 和 imgsz 的取舍现象训练启动后报 CUDA out of memory或者训练几个 batch 后突然 OOM。原因batch或imgsz设置过大或者workers太多导致内存泄漏累积。分割任务比检测任务多一个掩码原型生成和掩码组装步骤显存占用比同量级检测模型高 20% 到 30%。解决优先降batch从 16 降到 8 再到 4。如果降到 4 还 OOM降imgsz从 640 到 512。开启ampTrue混合精度训练可以省 30% 左右显存。workers设为 CPU 核心数的一半不要超过 8。如果还是 OOM用yolo11n-seg替代yolo11s-segn 版本的参数量和显存占用都小很多。6. 推理部署与效果验证从 PyTorch 到 ONNX 的落地技巧训练完成后下一步是把模型部署到实际推理环境。Ultralytics 支持导出 ONNX、TensorRT、OpenVINO 等多种格式。分割模型的导出和检测模型基本一致但有一个关键区别ONNX 输出会多一个掩码原型张量后处理时需要额外处理。from ultralytics import YOLO # 加载训练好的分割模型 model YOLO(runs/segment/defect-seg-v1/weights/best.pt) # 导出 ONNX分割模型需要指定 opset 和 simplify model.export( formatonnx, imgsz640, opset12, # 分割模型建议 opset 11 simplifyTrue, # 简化计算图减少冗余算子 dynamicFalse, # 固定输入尺寸推理更快 halfFalse # FP32 导出FP16 在部分设备上兼容性差 ) # 推理并保存结果 results model.predict( sourcetest_images/, imgsz640, conf0.25, # 置信度阈值分割任务建议 0.25 起步 iou0.45, # NMS IoU 阈值 saveTrue, # 保存可视化结果 save_txtTrue, # 保存分割结果到 txt save_confTrue, # txt 里包含置信度 projectruns/predict, namedefect-seg-test )导出 ONNX 时opset12是分割模型比较稳的选择低于 11 可能不支持某些掩码操作。simplifyTrue会调用 onnx-simplifier 去掉冗余节点减小模型体积并提升推理速度。dynamicFalse固定输入尺寸TensorRT 和 OpenVINO 在固定尺寸下优化更充分。halfFalse导出 FP32虽然 FP16 推理更快但部分边缘设备对 FP16 的掩码后处理支持不完善容易出现数值溢出。推理时conf0.25是分割任务的常用起点比检测任务的 0.25 略高因为低置信度的掩码往往边界模糊可视化效果差。iou0.45控制 NMS 的合并阈值密集实例场景可以降到 0.4 减少漏检。save_txtTrue会把每个实例的类别、框坐标、掩码多边形和置信度写到 txt方便后续做定量分析。验证部署效果时我一般会做三组对比PyTorch 原始模型、ONNX Runtime 推理、TensorRT 推理。重点看三个指标单帧延迟、mask mAP 下降幅度、显存占用。ONNX Runtime 的 mask mAP 通常比 PyTorch 低 0.5 到 1 个点主要来自算子精度差异TensorRT 在 FP16 下可能低 1 到 2 个点但延迟能降到 PyTorch 的 1/3 到 1/2。如果 mask mAP 下降超过 3 个点检查导出时的opset和simplify设置或者尝试 FP32 推理。一个我踩过的坑ONNX 分割模型的输出张量顺序和 PyTorch 不一致。PyTorch 输出是(preds, prototypes)ONNX 可能反过来。后处理代码里如果按固定顺序取张量会导致掩码和框完全错位。解决办法是打印 ONNX 模型的输出名称和形状确认哪个是预测张量、哪个是原型张量再写后处理逻辑。最后说一个验证技巧用同一批测试图像分别跑 PyTorch 和 ONNX 推理把掩码结果叠加到原图上做像素级对比。如果发现某些实例的掩码在 ONNX 下偏移了几个像素大概率是 letterbox 的 padding 计算在导出时被简化掉了。这时候可以在导出前把imgsz设为和训练时完全一致并且确保推理脚本里的预处理和训练时一致。这个对比方法比只看 mAP 数字更直观能发现指标掩盖的边界问题。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?