YOLO26-seg的转ncnn模型
参考链接YOLO26实现安卓ncnn实战部署在原文的基础之上seg可能与当前的版本不一样因此我重新对齐了一下最终转出与原作者一样的ncnn文件1.首先我们拿到我们训练好的原始权重.pt文件接下来转为对应的.torchscriptyolo export modelyolo26n-seg.pt formattorchscript2.转换静态尺寸输入的 torchscriptpnnx yolo26n-seg.torchscript转完之后就会出现下面的文件3.修改 yolo26n_seg_pnnx.py 模型脚本注意在用pnnx转完之后发现这里怎么有个红线也就是报错其实这里是C转python这里出现了问题实际上这段源码等价于v_335 v_333.float()(1).修改为动态尺寸# 修改前 v_95 self.model_10_m_0_attn_qkv_conv(v_94) v_96 v_95.reshape(1, 2, 128, 400) v_106 v_105.reshape(1, 128, 20, 20) v_107 v_99.reshape(1, 128, 20, 20) # 修改后 v_95 self.model_10_m_0_attn_qkv_conv(v_94) v_96 v_95.reshape(1, 2, 128, -1) # 这里的400改为-1 v_106 v_105.reshape(1, 128, v_95.size(2), v_95.size(3)) # 这里2020修改为v_95.size(2), v_95.size(3) v_107 v_99.reshape(1, 128, v_95.size(2), v_95.size(3)) # 这里2020修改为v_95.size(2), v_95.size(3)# 修改前 v_210 self.model_22_m_0_1_attn_qkv_conv(v_209) v_211 v_210.reshape(1, 2, 128, 400) v_221 v_220.reshape(1, 128, 20, 20) v_222 v_214.reshape(1, 128, 20, 20) # 修改后 v_210 self.model_22_m_0_1_attn_qkv_conv(v_209) v_211 v_210.reshape(1, 2, 128,-1) # 这里的400修改为-1 v_221 v_220.reshape(1, 128, v_210.size(2) ,v_210.size(3)) # 这里的2020修改为v_210.size(2) ,v_210.size(3) v_222 v_214.reshape(1, 128, v_210.size(2) ,v_210.size(3)) # 这里的2020修改为v_210.size(2) ,v_210.size(3)(2).检测头输出三个尺度—— 动态展平 维度调整也就是将之前的维度1与2进行了颠倒变成了(1,N_total,4)因此我们不能在cat最后那个维度应该是1这个维度# 修改前 v_241 v_240.reshape(1, 4, 6400) v_247 v_246.reshape(1, 4, 1600) v_253 v_252.reshape(1, 4, 400) v_254 torch.cat((v_241, v_247, v_253), dim-1) v_264 v_263.reshape(1, 80, 6400) v_274 v_273.reshape(1, 80, 1600) v_284 v_283.reshape(1, 80, 400) v_285 torch.cat((v_264, v_274, v_284), dim-1) v_291 v_290.reshape(1, 32, 6400) v_297 v_296.reshape(1, 32, 1600) v_303 v_302.reshape(1, 32, 400) v_304 torch.cat((v_291, v_297, v_303), dim2) # 修改后 v_241 v_240.reshape(1, 4, -1).transpose(1, 2) v_247 v_246.reshape(1, 4, -1).transpose(1, 2) v_253 v_252.reshape(1, 4, -1).transpose(1, 2) v_254 torch.cat((v_241, v_247, v_253), dim1) v_264 v_263.reshape(1, 80, -1).transpose(1, 2) v_274 v_273.reshape(1, 80, -1).transpose(1, 2) v_284 v_283.reshape(1, 80, -1).transpose(1, 2) v_285 torch.cat((v_264, v_274, v_284), dim1) v_det torch.cat((v_254, v_285), dim2) # 这里进行返回也就是和目标检测一样 v_291 v_290.reshape(1, 32, -1).transpose(1, 2) v_297 v_296.reshape(1, 32, -1).transpose(1, 2) v_303 v_302.reshape(1, 32, -1).transpose(1, 2) v_304 torch.cat((v_291, v_297, v_303), dim1) # 这里主要是掩码原作者后面还有一部分的修改此时我们先不进行修改我们先运行会发现在v_308这里出现了维度不匹配的问题(3).进行维度对齐这里就不做过多的解释了具体原因可以通过debug查看或者可以私信我# 修改前 v_305 self.pnnx_fold_anchor_points_1_data v_306, v_307 torch.chunk(v_254, chunks2, dim1) # 修改后 v_305 self.pnnx_fold_anchor_points_1_data.transpose(1,2) v_306, v_307 torch.chunk(v_254, chunks2, dim2)修改之后又发现v_311又出现问题了其实是v_234少了一个维度给他补齐# 修改前 v_310 torch.cat((v_308, v_309), dim1) v_311 (v_310 * v_234) # 修改后 v_310 torch.cat((v_308, v_309), dim2) v_311 (v_310 * v_234.unsqueeze(-1))v_313这里有出现问题了其实v_314其实也有问题的因为他俩的操作是一模一样的# 修改前 v_313 torch.cat((v_311, v_312), dim1) v_314 torch.cat((v_313, v_304), dim1) # 修改后 v_313 torch.cat((v_311, v_312), dim-1) v_314 torch.cat((v_313, v_304), dim-1)v_316,v_317,v_318这里也出现问题了这里还是维度有问题应该分割第一个维度而不是最后那个维度分割完成之后我们将下面的(12)维度进行互换这样后面的就不用再对齐维度了# 修改前 v_316, v_317, v_318 torch.split(tensorv_315, dim-1, split_size_or_sections(4,80,32)) # 修改后 v_316, v_317, v_318 torch.split(tensorv_315, dim1, split_size_or_sections(4,80,32)) v_316 v_316.permute(0, 2, 1) v_317 v_317.permute(0, 2, 1) v_318 v_318.permute(0, 2, 1)至此维度对齐这部分已基本完成接下来就是改其余部分了。(4).其余修改v_170 self.pnnx_unique_53(v_169) # 修改前 v_342 self.pnnx_unique_91(v_341) v_343 F.upsample_nearest(v_342, size(v_170.shape[2], v_170.shape[3])) v_344 (v_170 v_343) v_345 self.model_23_proto_feat_refine_1_conv(v_233) v_346 self.pnnx_unique_92(v_345) v_347 F.upsample_nearest(v_346, size(v_344.shape[2], v_344.shape[3])) v_348 (v_344 v_347) # 修改后 v_342 self.pnnx_unique_91(v_341) v_343 F.upsample_nearest(v_342, size(v_170.shape[2], v_170.shape[3])) v_344 (v_170 v_343) v_345 self.model_23_proto_feat_refine_1_conv(v_233) v_346 self.pnnx_unique_92(v_345) v_347 F.upsample_nearest(v_346, size(v_344.shape[2], v_344.shape[3])) v_348 (v_344 v_347)(5).结尾# 修改前 v_357 self.pnnx_unique_96(v_356) v_358 (v_340, v_357, ) return v_358 # 修改后 v_357 self.pnnx_unique_96(v_356) return v_det, v_304, v_357至此我们已经全部修改完毕重新导出4.重新导出修改后的模型python -c import yolo26n_seg_pnnx; yolo26n_seg_pnnx.export_torchscript()5.动态尺寸转换新 torchscriptpnnx yolo26n_seg_pnnx.py.pt inputshape[1,3,640,640] inputshape2[1,3,320,320]6.与原作者对比左边是我们转的右边是原作者的制作不易欢迎大家前来学习讨论如果想要转好的原文件也可以私信我谢谢。如果有需要制作yolo系类的安卓部署替换自己模型的可以找我。