虽然网上有很多YOLO 相关的文章,但是如果要用YOLO直接做一个落地产品,却没有一篇文章可以对每个步骤都进行指导了,为此,本文根据自己的项目经验,结合论文的精度和网络的相关文章,总结一篇可以从零到落地的文章。如有不详细或者遗漏的请在评论区留言,谢谢。
原始论文路径:pdf路径
讲解比较好的文章:YOLO文章详细解读
1,数据标注
1,推荐使用LabelImg,支持输出YOLO输出格式,安装教程和使用说明见链接
2,医学图像检测框标注工具可以采用3D slice,使用教程见链接
数据标注的存储格式如下:
dog.jpg 104 237 316 527 1 122 117 609 491 2 457 60 694 174 3
其中dog.jpg为图像的路径,接着每5个值为一个金标准框(x1,y1,x2,y2,类别)
2,DataSet:定义网络输入和loss的金标准输入
这里输入的是归一化之后并resize为固定大小[448,448]的图像;
输出为7x7x30的张量,所以这的标注数据格式需要做一个转换,转换为7x7x30的格式,一个参考代码如下:
h, w, _ = img.shape
grid_size = 7
stride = 1/grid_size
target = torch.zeros([grid_size, grid_size, 30])
boxes = boxes / torch.tensor([w, h, w, h]) # 归一化到0-1
wh = boxes[:, 2:] - boxes[:, :2]
cxcy = (boxes[:, 2:] + boxes[:, :2])/2
for i in range(cxcy.size(0)):
center = cxcy[i]
ij = (center * grid_size).floor()
delta_xy = (center - ij * stride) * grid_size
target[int(ij[1]), int(ij[0]), 2:4] = wh[i]
target[int(ij[1]), int(ij[0]), 7:9] = wh[i]
target[int(ij[1]), int(ij[0]), :2] = delta_xy
target[int(ij[1]), int(ij[0]), 5:7] = delta_xy
target[int(ij[1]), int(ij[0]), 4] = 1
target[int(ij[1]), int(ij[0]), 9] = 1
target[int(ij[1]), int(ij[0]), 9+int(label[i])] = 1
3,编写网络结构

1,一种方法是实现论文的网络结构,并书写转换接口,把原文的网络参数加载到自己实现的网络中,作为预训练的参数。
2,一种方法是修改当前主流的网络结构,如VGG16、U-Net、ResNet等,把最后几层网络进行修改,只要确保最后一层网络的输出为7x7x30就行。
4,编写Loss计算模块
loss的输入为predict和target,二者的尺寸都是7x7x30,一个loss类的架构如下:
class Loss(nn.Module):
def __init__(self):
super(Loss, self).__init__()
self.coord = 5.0
self.noobj = 0.5
def forward(self, pred, target):
'''
:param pred: Bx7x7x30 -inf, inf
:param target: Bx7x7x30 -inf, inf
:return:
'''
# xy loss
# wh loss
# iou loss
# label loss
5,训练网络结构
训练网络结构的步骤包括如下几个:
1,实例化net = YOLO
2,网络参数初始化
3,实例化Loss
4,实例化优化器
5,封装dataset
6,循环更新网络参数