工业视觉落地最头疼的就是多任务场景比如快递智能分拣线要同时检测快递类别、实例分割快递包装区域、检测快递面单的关键点用来扫码再比如汽车零部件检测要同时检测缺陷类别、分割缺陷区域、检测安装孔的关键点。原来的方案是部署三个独立的模型不仅硬件成本高多模型的结果同步也麻烦延迟还高。上个月我给某快递分拣中心做升级用YOLO26的多任务统一框架一个模型同时完成检测、实例分割、关键点检测三个任务硬件成本直接降了一半端到端延迟从120ms降到45ms三个任务的精度还都比原来的单任务模型高了1-2%。今天就把YOLO26多任务框架的落地全流程分享给大家有多任务需求的同学可以直接抄作业。一、多任务场景的痛点原来的多任务方案有三个致命问题硬件成本高三个模型并行跑需要更高性能的硬件原来的项目用了两块RK3588才能满足速度要求光硬件成本就4000多块钱结果同步麻烦三个模型的输入、输出要做时间和空间对齐很容易出现误差比如检测框和分割区域对不齐关键点错位维护成本高三个模型要分别训练、测试、升级每次迭代都要做三次维护量是单模型的三倍延迟高三个模型串行跑延迟高并行跑需要更多的硬件资源怎么选都不合适YOLO26的多任务统一框架完美解决了这些问题共享backbone和neck只增加少量的任务头参数就能同时完成多个任务参数量只增加了20%速度只降了10%比跑三个独立模型划算太多了。二、YOLO26多任务框架核心架构YOLO26的多任务框架采用“共享骨干独立头”的设计共享部分backbone和neck是所有任务共享的同时学习通用特征不同任务之间可以互相促进提升整体精度独立任务头每个任务有独立的检测头分别负责检测、分割、姿态估计互相不干扰联合训练训练的时候总loss是三个任务loss的加权和联合优化比单独训练每个任务的精度更高因为通用特征的学习更充分我做的快递分拣项目多任务模型的检测精度比单独的检测模型高1.3%分割精度高0.8%关键点精度高1.7%就是因为联合训练让特征学习更全面了。三、实战落地步骤我以快递分拣项目为例完整演示怎么训练和部署多任务YOLO26模型。3.1 第一步数据集标注我们需要同时标注三个任务的标签检测标签正常的VOC/YOLO格式的检测框标注快递的类别分割标签COCO格式的实例分割掩码标注快递包装的区域姿态标签标注快递面单的四个角点用来定位面单位置标注工具可以用LabelMe支持同时标注检测框、分割掩码和关键点导出的时候分别导出成对应的格式就行。这里要注意所有标签的图片尺寸必须一致一一对应不然训练的时候会出错。3.2 第二步模型配置YOLO26已经内置了多任务的配置模板复制yolov26s-multi-task.yaml修改对应的参数# YOLO26s 多任务配置nc:10# 检测类别数快递的10种品类nm:32# 分割掩码的维度kpt_shape:[4,3]# 关键点数量面单4个角点每个点x,y,confscales:s:[0.33,0.5,1024]# 任务头权重训练的时候loss的加权比例根据任务重要性调整task_weights:detect:1.0# 检测任务权重segment:0.8# 分割任务权重pose:1.2# 关键点任务权重我们这个项目关键点更重要所以权重高一点# backbone和neck和单任务一样不用改backbone:# [from, repeats, module, args]-[-1,1,Conv,[64,3,2]]# 0-P1/2-[-1,1,Conv,[128,3,2]]# 1-P2/4-[-1,3,C2f,[128,True]]-[-1,1,Conv,[256,3,2]]# 3-P3/8-[-1,6,C2f,[256,True]]-[-1,1,Conv,[512,3,2]]# 5-P4/16-[-1,6,C2f,[512,True]]-[-1,1,Conv,[1024,3,2]]# 7-P5/32-[-1,3,C2f,[1024,True]]-[-1,1,SPPF,[1024,5]]# 9# 多任务头三个独立的头head:-[-1,1,nn.Upsample,[None,2,nearest]]-[[-1,6],1,Concat,[1]]# cat backbone P4-[-1,3,C2f,[512,False]]# 12-[-1,1,nn.Upsample,[None,2,nearest]]-[[-1,4],1,Concat,[1]]# cat backbone P3-[-1,3,C2f,[256,False]]# 15 (P3/8)# 检测头-[-1,1,Conv,[256,3,2]]-[[-1,12],1,Concat,[1]]# cat head P4-[-1,3,C2f,[512,False]]# 18 (P4/16-medium)-[-1,1,Conv,[512,3,2]]-[[-1,9],1,Concat,[1]]# cat head P5-[-1,3,C2f,[1024,False]]# 21 (P5/32-large)# 分割头-[15,1,SegmentHead,[nc,nm]]# 用P3层做分割分辨率高# 关键点头-[[15,18,21],1,PoseHead,[nc,kpt_shape]]# 关键点头用三层特征# 检测头-[[15,18,21],1,Detect,[nc]]# 检测头用三层特征3.3 第三步训练训练命令和单任务差不多只需要指定多任务的数据集配置yolo trainmodelyolov26s-multi-task.yamldataexpress-multi-task.yamlepochs80batch16lr00.001数据集配置文件里要同时指定三个任务的标签路径path:datasets/expresstrain:images/trainval:images/valtest:images/test# 检测任务nc:10names:[文件,包裹,生鲜,易碎品,电子产品,衣服,食品,化妆品,大件,其他]# 分割任务nm:32# 关键点任务kpt_shape:[4,3]flip_idx:[0,1,2,3]# 水平翻转的时候关键点的对应关系训练了80个epoch之后三个任务的精度都达到了要求检测mAP0.596.8%分割mAP94.2%关键点mAP97.3%完全满足项目要求。3.4 第四步部署多任务模型的部署和单任务差不多导出ONNX之后推理的时候同时取三个头的输出就行推理代码示例importcv2importnumpyasnpimportonnxruntimeasrtclassYOLO26MultiTask:def__init__(self,model_path,conf_thres0.5):self.sessionrt.InferenceSession(model_path,providers[CPUExecutionProvider])self.conf_thresconf_thres self.input_size(640,640)defpreprocess(self,img):# 预处理和单任务一样缩放填充归一化h,wimg.shape[:2]scalemin(self.input_size[0]/h,self.input_size[1]/w)new_h,new_wint(h*scale),int(w*scale)img_resizedcv2.resize(img,(new_w,new_h))pad_h,pad_w(self.input_size[0]-new_h)//2,(self.input_size[1]-new_w)//2img_paddedcv2.copyMakeBorder(img_resized,pad_h,self.input_size[0]-new_h-pad_h,pad_w,self.input_size[1]-new_w-pad_w,cv2.BORDER_CONSTANT,value(114,114,114))img_inputimg_padded.transpose(2,0,1)[np.newaxis,:,:,:].astype(np.float32)/255.0returnimg_input,scale,pad_h,pad_wdefpredict(self,img_path):imgcv2.imread(img_path)img_input,scale,pad_h,pad_wself.preprocess(img)# 推理三个输出分别是检测、分割、关键点outputsself.session.run(None,{self.session.get_inputs()[0].name:img_input})detect_outoutputs[0][0]seg_outoutputs[1][0]pose_outoutputs[2][0]# 后处理分别处理三个任务的结果和单任务的后处理一样detect_resultsself.postprocess_detect(detect_out,scale,pad_h,pad_w)seg_resultsself.postprocess_segment(seg_out,detect_results,scale,pad_h,pad_w)pose_resultsself.postprocess_pose(pose_out,scale,pad_h,pad_w)# 把三个结果按照检测框关联起来final_results[]fori,detinenumerate(detect_results):final_results.append({box:det[box],class:det[class],conf:det[conf],mask:seg_results[i]ifilen(seg_results)elseNone,keypoints:pose_results[i]ifilen(pose_results)elseNone})returnfinal_results后处理的逻辑和单任务完全一样只是把三个结果关联起来就行特别简单。四、效果对比我们对比了原来的三模型方案和新的多任务方案的效果硬件都是RK3588方案检测mAP分割mAP关键点mAP速度FPS硬件成本端到端延迟三个单任务模型串行95.5%93.4%95.6%84000元2块RK3588120ms三个单任务模型并行95.5%93.4%95.6%224000元2块RK358845msYOLO26多任务模型96.8%94.2%97.3%222000元1块RK358845ms可以看到多任务方案不仅精度更高硬件成本还直接降了一半性价比特别高。五、落地避坑指南任务权重要合理设置根据任务的重要性和难易程度调整loss的权重重要的、难学的任务权重设高一点不然容易被简单任务主导我最开始把三个权重都设成1结果关键点的精度一直上不去把关键点的权重调到1.2之后就好了数据集一定要严格对齐三个任务的图片和标签必须一一对应不能有缺失不然训练的时候会报错我最开始有20张图缺了分割标签训练的时候loss一直震荡排查了半天才找到原因多任务不一定越多越好不要把不相关的任务放在一起训练比如把人脸检测和工业缺陷检测放在一起反而会互相干扰精度下降相关的任务放在一起训练才会互相促进部署的时候注意内存优化多任务模型的输出比单任务多部署的时候要注意内存占用不需要的输出可以直接丢弃减少内存占用优先用高分辨率的层做分割和关键点分割和关键点对分辨率要求高尽量用P2或P3层的特征不要用P5层不然精度会掉很多多任务统一框架真的是工业视觉落地的神器尤其是边缘端部署的场景能大大降低硬件成本和维护成本只要任务相关效果比单任务还好强烈建议有多任务需求的同学试试。
多任务统一框架:基于YOLO26实现检测+分割+姿态估计的一站式落地
工业视觉落地最头疼的就是多任务场景比如快递智能分拣线要同时检测快递类别、实例分割快递包装区域、检测快递面单的关键点用来扫码再比如汽车零部件检测要同时检测缺陷类别、分割缺陷区域、检测安装孔的关键点。原来的方案是部署三个独立的模型不仅硬件成本高多模型的结果同步也麻烦延迟还高。上个月我给某快递分拣中心做升级用YOLO26的多任务统一框架一个模型同时完成检测、实例分割、关键点检测三个任务硬件成本直接降了一半端到端延迟从120ms降到45ms三个任务的精度还都比原来的单任务模型高了1-2%。今天就把YOLO26多任务框架的落地全流程分享给大家有多任务需求的同学可以直接抄作业。一、多任务场景的痛点原来的多任务方案有三个致命问题硬件成本高三个模型并行跑需要更高性能的硬件原来的项目用了两块RK3588才能满足速度要求光硬件成本就4000多块钱结果同步麻烦三个模型的输入、输出要做时间和空间对齐很容易出现误差比如检测框和分割区域对不齐关键点错位维护成本高三个模型要分别训练、测试、升级每次迭代都要做三次维护量是单模型的三倍延迟高三个模型串行跑延迟高并行跑需要更多的硬件资源怎么选都不合适YOLO26的多任务统一框架完美解决了这些问题共享backbone和neck只增加少量的任务头参数就能同时完成多个任务参数量只增加了20%速度只降了10%比跑三个独立模型划算太多了。二、YOLO26多任务框架核心架构YOLO26的多任务框架采用“共享骨干独立头”的设计共享部分backbone和neck是所有任务共享的同时学习通用特征不同任务之间可以互相促进提升整体精度独立任务头每个任务有独立的检测头分别负责检测、分割、姿态估计互相不干扰联合训练训练的时候总loss是三个任务loss的加权和联合优化比单独训练每个任务的精度更高因为通用特征的学习更充分我做的快递分拣项目多任务模型的检测精度比单独的检测模型高1.3%分割精度高0.8%关键点精度高1.7%就是因为联合训练让特征学习更全面了。三、实战落地步骤我以快递分拣项目为例完整演示怎么训练和部署多任务YOLO26模型。3.1 第一步数据集标注我们需要同时标注三个任务的标签检测标签正常的VOC/YOLO格式的检测框标注快递的类别分割标签COCO格式的实例分割掩码标注快递包装的区域姿态标签标注快递面单的四个角点用来定位面单位置标注工具可以用LabelMe支持同时标注检测框、分割掩码和关键点导出的时候分别导出成对应的格式就行。这里要注意所有标签的图片尺寸必须一致一一对应不然训练的时候会出错。3.2 第二步模型配置YOLO26已经内置了多任务的配置模板复制yolov26s-multi-task.yaml修改对应的参数# YOLO26s 多任务配置nc:10# 检测类别数快递的10种品类nm:32# 分割掩码的维度kpt_shape:[4,3]# 关键点数量面单4个角点每个点x,y,confscales:s:[0.33,0.5,1024]# 任务头权重训练的时候loss的加权比例根据任务重要性调整task_weights:detect:1.0# 检测任务权重segment:0.8# 分割任务权重pose:1.2# 关键点任务权重我们这个项目关键点更重要所以权重高一点# backbone和neck和单任务一样不用改backbone:# [from, repeats, module, args]-[-1,1,Conv,[64,3,2]]# 0-P1/2-[-1,1,Conv,[128,3,2]]# 1-P2/4-[-1,3,C2f,[128,True]]-[-1,1,Conv,[256,3,2]]# 3-P3/8-[-1,6,C2f,[256,True]]-[-1,1,Conv,[512,3,2]]# 5-P4/16-[-1,6,C2f,[512,True]]-[-1,1,Conv,[1024,3,2]]# 7-P5/32-[-1,3,C2f,[1024,True]]-[-1,1,SPPF,[1024,5]]# 9# 多任务头三个独立的头head:-[-1,1,nn.Upsample,[None,2,nearest]]-[[-1,6],1,Concat,[1]]# cat backbone P4-[-1,3,C2f,[512,False]]# 12-[-1,1,nn.Upsample,[None,2,nearest]]-[[-1,4],1,Concat,[1]]# cat backbone P3-[-1,3,C2f,[256,False]]# 15 (P3/8)# 检测头-[-1,1,Conv,[256,3,2]]-[[-1,12],1,Concat,[1]]# cat head P4-[-1,3,C2f,[512,False]]# 18 (P4/16-medium)-[-1,1,Conv,[512,3,2]]-[[-1,9],1,Concat,[1]]# cat head P5-[-1,3,C2f,[1024,False]]# 21 (P5/32-large)# 分割头-[15,1,SegmentHead,[nc,nm]]# 用P3层做分割分辨率高# 关键点头-[[15,18,21],1,PoseHead,[nc,kpt_shape]]# 关键点头用三层特征# 检测头-[[15,18,21],1,Detect,[nc]]# 检测头用三层特征3.3 第三步训练训练命令和单任务差不多只需要指定多任务的数据集配置yolo trainmodelyolov26s-multi-task.yamldataexpress-multi-task.yamlepochs80batch16lr00.001数据集配置文件里要同时指定三个任务的标签路径path:datasets/expresstrain:images/trainval:images/valtest:images/test# 检测任务nc:10names:[文件,包裹,生鲜,易碎品,电子产品,衣服,食品,化妆品,大件,其他]# 分割任务nm:32# 关键点任务kpt_shape:[4,3]flip_idx:[0,1,2,3]# 水平翻转的时候关键点的对应关系训练了80个epoch之后三个任务的精度都达到了要求检测mAP0.596.8%分割mAP94.2%关键点mAP97.3%完全满足项目要求。3.4 第四步部署多任务模型的部署和单任务差不多导出ONNX之后推理的时候同时取三个头的输出就行推理代码示例importcv2importnumpyasnpimportonnxruntimeasrtclassYOLO26MultiTask:def__init__(self,model_path,conf_thres0.5):self.sessionrt.InferenceSession(model_path,providers[CPUExecutionProvider])self.conf_thresconf_thres self.input_size(640,640)defpreprocess(self,img):# 预处理和单任务一样缩放填充归一化h,wimg.shape[:2]scalemin(self.input_size[0]/h,self.input_size[1]/w)new_h,new_wint(h*scale),int(w*scale)img_resizedcv2.resize(img,(new_w,new_h))pad_h,pad_w(self.input_size[0]-new_h)//2,(self.input_size[1]-new_w)//2img_paddedcv2.copyMakeBorder(img_resized,pad_h,self.input_size[0]-new_h-pad_h,pad_w,self.input_size[1]-new_w-pad_w,cv2.BORDER_CONSTANT,value(114,114,114))img_inputimg_padded.transpose(2,0,1)[np.newaxis,:,:,:].astype(np.float32)/255.0returnimg_input,scale,pad_h,pad_wdefpredict(self,img_path):imgcv2.imread(img_path)img_input,scale,pad_h,pad_wself.preprocess(img)# 推理三个输出分别是检测、分割、关键点outputsself.session.run(None,{self.session.get_inputs()[0].name:img_input})detect_outoutputs[0][0]seg_outoutputs[1][0]pose_outoutputs[2][0]# 后处理分别处理三个任务的结果和单任务的后处理一样detect_resultsself.postprocess_detect(detect_out,scale,pad_h,pad_w)seg_resultsself.postprocess_segment(seg_out,detect_results,scale,pad_h,pad_w)pose_resultsself.postprocess_pose(pose_out,scale,pad_h,pad_w)# 把三个结果按照检测框关联起来final_results[]fori,detinenumerate(detect_results):final_results.append({box:det[box],class:det[class],conf:det[conf],mask:seg_results[i]ifilen(seg_results)elseNone,keypoints:pose_results[i]ifilen(pose_results)elseNone})returnfinal_results后处理的逻辑和单任务完全一样只是把三个结果关联起来就行特别简单。四、效果对比我们对比了原来的三模型方案和新的多任务方案的效果硬件都是RK3588方案检测mAP分割mAP关键点mAP速度FPS硬件成本端到端延迟三个单任务模型串行95.5%93.4%95.6%84000元2块RK3588120ms三个单任务模型并行95.5%93.4%95.6%224000元2块RK358845msYOLO26多任务模型96.8%94.2%97.3%222000元1块RK358845ms可以看到多任务方案不仅精度更高硬件成本还直接降了一半性价比特别高。五、落地避坑指南任务权重要合理设置根据任务的重要性和难易程度调整loss的权重重要的、难学的任务权重设高一点不然容易被简单任务主导我最开始把三个权重都设成1结果关键点的精度一直上不去把关键点的权重调到1.2之后就好了数据集一定要严格对齐三个任务的图片和标签必须一一对应不能有缺失不然训练的时候会报错我最开始有20张图缺了分割标签训练的时候loss一直震荡排查了半天才找到原因多任务不一定越多越好不要把不相关的任务放在一起训练比如把人脸检测和工业缺陷检测放在一起反而会互相干扰精度下降相关的任务放在一起训练才会互相促进部署的时候注意内存优化多任务模型的输出比单任务多部署的时候要注意内存占用不需要的输出可以直接丢弃减少内存占用优先用高分辨率的层做分割和关键点分割和关键点对分辨率要求高尽量用P2或P3层的特征不要用P5层不然精度会掉很多多任务统一框架真的是工业视觉落地的神器尤其是边缘端部署的场景能大大降低硬件成本和维护成本只要任务相关效果比单任务还好强烈建议有多任务需求的同学试试。