从零开始用 PyTorch 实现 YOLO (v3) 是什么体验(五)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zw__chen/article/details/84322511

从零开始用 PyTorch 实现 YOLO (v3) 是什么体验(五)

代码基于 Python 3.5, 和 PyTorch 0.4. 代码发布在 Github repo 上。

本体验分为5个部分:

在阅读完前四个部分后,相信大家都对yolov3代码有了一定对了解。在这最后一部分整理了鄙人的一些愚见,请各位指教。

1. 网络结构

通过修改代码(代码见篇头链接),yolo的网络结构可以如下打印:【有点长,大家可以大概浏览一下,后面还有简略版】
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
到这里就截止啦,一共有106层。光看这个106行,不是很直观,大家可以结合下图来看这106层,这样思路回清晰很多哦。
在这里插入图片描述

由以上的节点信息可以很直观的看出,yolov3借助来残差模型(darknet-53网络)和FPN架构(先卷积然后再上采样):【以下提到的第x层,是从以上网络结构的第x层】

  • 输入图片大小为416*416

  • 1)32倍采样特征图检测:

    • 从第74层出来的13x13x1024通过一个Convolutional Set再经过两个卷积进入第82层的detection层,我图中描述为yolo层,该层得到13x13x255维的向量,这个13x13就对应论文当中的169个cell,而255=(4+1+80)x3,表示center_x, center_y, w, h + confidence +
      Probability of 80 classes,而每个cell预测三个proposal . 对于这个32倍的采样特征图,可以有效的检测图中大目标的存在。
  • 2)16倍采样特征图检测:

    • 第83层接着一个route层,该层把79层的输出作为输入,输往84层卷积,然后采用上采样从13x13的特征图变为26x26大小的特征图。第86层又为route层,不同的是,该层结合了第85层的输出(26x26x256)和第61层(26x26x512)的输出,所以维度变成26x26x768(其中768=256+512)。
    • 接下来和上一个32倍采样一样的做法得到第二个yolo层:26x26x255维的向量。
  • 3)8倍采样特征图检测:

    • 8倍采样特征图检测和16倍的一样。
    • 第95层接着一个route层,该层把91层的输出作为输入,输往96层卷积,然后采用上采样从26x26的特征图变为52x52大小的特征图。第86层又为route层,不同的是,该层结合了第97层的输出(52x52x128)和第36层(52x52x256)的输出,所以维度变成26x26x384(其中384=128+25)。
    • 接下来和上一个32倍采样一样的做法得到第三个yolo层:52x52x255维的向量。

整个网络就是如此了,接下来就是对yolo层操作的整理,先见下图:
在这里插入图片描述
在yolo层中:【这里以第一个yolo层的输出13x13x255为栗子】

  1. 对13x13x255进行变换,具体变换见上图,最终变换为[1,507,85]维度的向量进行计算,其中507表示的是一共有507个proposas,每个cell预测3个,一共有169个cell,即507=13x13x3,85表示的是center_x, center_y, w, h + confidence + Probability of 80 classes。
  2. 对anchor进行处理,具体就是anchor对值处以stride,也就是倍数。本情况为32.
  3. centre_X, centre_Y. and object confidencceSigmoid
    # Sigmoid the  centre_X, centre_Y. and object confidencce
        prediction[:, :, 0] = torch.sigmoid(prediction[:, :, 0])
        prediction[:, :, 1] = torch.sigmoid(prediction[:, :, 1])
        prediction[:, :, 4] = torch.sigmoid(prediction[:, :, 4])
    
  4. 初始化x_offset和y_offset,我很疑惑为啥要初始化为0-12,具体变换见上图,最后是将这个offset与centre_X, centre_Y 相加。即: prediction[:, :, :2] += x_y_offset
  5. 将anchor这个[3,2]维度的矩阵纵向拷贝169次,再增加一个维度变为[1,507,2]的矩阵,接着使用anchor矩阵乘以e的宽高次幂,即prediction[:, :, 2:4] = torch.exp(prediction[:, :, 2:4]) * anchors
  6. 对80个类别做sigmoid操作,即prediction[:, :, 5: 5 + num_classes] = torch.sigmoid((prediction[:, :, 5: 5 + num_classes]))。
  7. 将坐标映射回原图,这里乘以stride32,可以映射回原图:prediction[:, :, :4] *= stride

yolo层就是这样子处理的,输出维度为[1,507,85].

接着就是再两个循环了,同理对第二、三个yolo层进行处理,其对应对输出维度分别为:[1,2028,85],[1,10647,85]。最后就把这些整合为:[1,10647,85].即:对一张图而言,一共生成了10647个proposals。

到此为止,yolo的工作就结束了。在代码后续就是对这10647个proposals进行处理,进行两次过滤:置信度过滤和NMS过滤。最终得到图片的proposal。

最后,附上一张检测的效果图把:

  • 没有经过任何处理的是这样子的:
    在这里插入图片描述
  • 没有经过nms处理的是这样子的:
    在这里插入图片描述
  • 经过完全处理的是这样子的:
    在这里插入图片描述
    第五部分也到此结束啦。若有疑问的小伙伴们,可以留言交流哦~

猜你喜欢

转载自blog.csdn.net/zw__chen/article/details/84322511