天天看点

YOLOv1-从零到落地

虽然网上有很多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,编写网络结构

YOLOv1-从零到落地

1,一种方法是实现论文的网络结构,并书写转换接口,把原文的网络参数加载到自己实现的网络中,作为预训练的参数。

2,一种方法是修改当前主流的网络结构,如VGG16、U-Net、ResNet等,把最后几层网络进行修改,只要确保最后一层网络的输出为7x7x30就行。

4,编写Loss计算模块

YOLOv1-从零到落地

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,循环更新网络参数

6,模型的inference

7,工程化模型

继续阅读