YOLOV3网络搭建 and 代码复现Pytorch and 元器件检测

目录

一. YOLOV3 网络

1.主干网络DarkNet53

二. 代码复现        

1.DarkNet53搭建

2.特征加强 and 结果预测​编辑

3. 源码地址

三. 检测效果


一. YOLOV3 网络

1.主干网络DarkNet53

YoloV3所使用的主干特征提取网络为Darknet53,它具有两个重要特点:
1、Darknet53具有一个重要特点是使用了残差网络Residual(残差结构可以在"分类"栏中的ResNet中了解)...... 。通过不断的1X1卷积和3X3卷积以及残差边的叠加,我们便大幅度的加深了网络。残差网络的特点是容易优化,并且能够通过增加相当的深度来提高准确率。其内部的残差块使用了跳跃连接,缓解了在深度神经网络中增加深度带来的梯度消失问题。

2、Darknet53的每一个卷积部分使用了特有的DarknetConv2D结构,每一次卷积的时候进行l2正则化,完成卷积后进行BatchNormalization标准化与LeakyReLU。普通的ReLU是将所有的负值都设为零,Leaky ReLU则是给所有负值赋予一个非零斜率。以数学的方式我们可以表示为:

Fig1. DarkNet53结构表 

画成流程图如下,更好理解:

上述流程图的关键字均与下面列出的代码中的参数名一样, 对照网络结构看代码 更易于理解。 

二. 代码复现
        

1.DarkNet53搭建

import math
from collections import OrderedDictimport torch.nn as nn#---------------------------------------------------------------------#
#   残差块结构
#   利用一个1x1卷积下降通道数,然后利用一个3x3卷积提取特征并且上升通道数
#   最后接上一个残差边
#---------------------------------------------------------------------#
class BasicBlock(nn.Module):def __init__(self, inplanes, planes):super(BasicBlock, self).__init__()self.conv1 = nn.Conv2d(inplanes, planes[0], kernel_size=1, stride=1, padding=0, bias=False)self.bn1   = nn.BatchNorm2d(planes[0])self.relu1 = nn.LeakyReLU(0.1)self.conv2 = nn.Conv2d(planes[0], planes[1], kernel_size=3, stride=1, padding=1, bias=False)self.bn2   = nn.BatchNorm2d(planes[1])self.relu2 = nn.LeakyReLU(0.1)def forward(self, x):residual = xout = self.conv1(x)out = self.bn1(out)out = self.relu1(out)out = self.conv2(out)out = self.bn2(out)out = self.relu2(out)out = out + residualreturn outclass DarkNet(nn.Module):def __init__(self, layers):super(DarkNet, self).__init__()   #调用父类nn.Mudule的构造函数self.inplanes = 32                #输入通道# 416,416,3 -> 416,416,32 Conv2D 32x3x3   卷积核          步长       填充       偏置self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=3, stride=1, padding=1, bias=False)self.bn1   = nn.BatchNorm2d(self.inplanes)self.relu1 = nn.LeakyReLU(0.1)    #和cnn的Relu()不同 此LeakyReLU不为0->0.1*x# 416,416,32 -> 208,208,64self.layer1 = self._make_layer([32, 64], layers[0])# 208,208,64 -> 104,104,128self.layer2 = self._make_layer([64, 128], layers[1])# 104,104,128 -> 52,52,256self.layer3 = self._make_layer([128, 256], layers[2])# 52,52,256 -> 26,26,512self.layer4 = self._make_layer([256, 512], layers[3])# 26,26,512 -> 13,13,1024self.layer5 = self._make_layer([512, 1024], layers[4])self.layers_out_filters = [64, 128, 256, 512, 1024]#进行权值初始化# isinstance(m, nn.Conv2d) 判断 m 是否是 Conv2dfor m in self.modules():if isinstance(m, nn.Conv2d):n = m.kernel_size[0] * m.kernel_size[1] * m.out_channelsm.weight.data.normal_(0, math.sqrt(2. / n))elif isinstance(m, nn.BatchNorm2d):m.weight.data.fill_(1)m.bias.data.zero_()#---------------------------------------------------------------------#
#   在每一个layer里面,首先利用一个步长为2的3x3卷积进行下采样
#   然后进行残差结构的堆叠
#---------------------------------------------------------------------#def _make_layer(self, planes, blocks):layers = []# 步长为2 的 下采样  , 卷积核为3x3layers.append(("ds_conv", nn.Conv2d(self.inplanes, planes[1], kernel_size=3, stride=2, padding=1, bias=False)))layers.append(("ds_bn", nn.BatchNorm2d(planes[1])))layers.append(("ds_relu", nn.LeakyReLU(0.1)))#加入残差结构self.inplanes = planes[1]    #更新当前的输入通道数for i in range(0, blocks):layers.append(("residual_{}".format(i), BasicBlock(self.inplanes, planes)))return nn.Sequential(OrderedDict(layers))def forward(self, x):x = self.conv1(x)x = self.bn1(x)x = self.relu1(x)x = self.layer1(x)x = self.layer2(x)out3 = self.layer3(x)out4 = self.layer4(out3)out5 = self.layer5(out4)return out3, out4, out5def darknet53():model = DarkNet([1, 2, 8, 8, 4])return model

2.特征加强 and 结果预测

 从特征获取预测结果的过程可以分为两个部分,分别是:

  • 构建FPN特征金字塔进行加强特征提取(红色部分)
  • 利用Yolo Head对三个有效特征层进行预测(绿色部分)
from tensorflow.keras.layers import Concatenate, Input, Lambda, UpSampling2D
from tensorflow.keras.models import Model
from utils.utils import composefrom nets.darknet import DarknetConv2D, DarknetConv2D_BN_Leaky, darknet_body
from nets.yolo_training import yolo_loss#---------------------------------------------------#
#   特征层->最后的输出
#---------------------------------------------------#
def make_five_conv(x, num_filters, weight_decay=5e-4):x = DarknetConv2D_BN_Leaky(num_filters, (1,1), weight_decay=weight_decay)(x)x = DarknetConv2D_BN_Leaky(num_filters*2, (3,3), weight_decay=weight_decay)(x)x = DarknetConv2D_BN_Leaky(num_filters, (1,1), weight_decay=weight_decay)(x)x = DarknetConv2D_BN_Leaky(num_filters*2, (3,3), weight_decay=weight_decay)(x)x = DarknetConv2D_BN_Leaky(num_filters, (1,1), weight_decay=weight_decay)(x)return xdef make_yolo_head(x, num_filters, out_filters, weight_decay=5e-4):y = DarknetConv2D_BN_Leaky(num_filters*2, (3,3), weight_decay=weight_decay)(x)# 255->3, 85->3, 4 + 1 + 80y = DarknetConv2D(out_filters, (1,1), weight_decay=weight_decay)(y)return y#---------------------------------------------------#
#   FPN网络的构建,并且获得预测结果
#---------------------------------------------------#
def yolo_body(input_shape, anchors_mask, num_classes, weight_decay=5e-4):inputs      = Input(input_shape)#---------------------------------------------------#   #   生成darknet53的主干模型#   获得三个有效特征层,他们的shape分别是:#   C3 为 52,52,256#   C4 为 26,26,512#   C5 为 13,13,1024#---------------------------------------------------#C3, C4, C5  = darknet_body(inputs, weight_decay)#---------------------------------------------------##   第一个特征层#   y1=(batch_size,13,13,3,85)#---------------------------------------------------## 13,13,1024 -> 13,13,512 -> 13,13,1024 -> 13,13,512 -> 13,13,1024 -> 13,13,512x   = make_five_conv(C5, 512, weight_decay)P5  = make_yolo_head(x, 512, len(anchors_mask[0]) * (num_classes+5), weight_decay)# 13,13,512 -> 13,13,256 -> 26,26,256x   = compose(DarknetConv2D_BN_Leaky(256, (1,1), weight_decay=weight_decay), UpSampling2D(2))(x)# 26,26,256 + 26,26,512 -> 26,26,768x   = Concatenate()([x, C4])#---------------------------------------------------##   第二个特征层#   y2=(batch_size,26,26,3,85)#---------------------------------------------------## 26,26,768 -> 26,26,256 -> 26,26,512 -> 26,26,256 -> 26,26,512 -> 26,26,256x   = make_five_conv(x, 256, weight_decay)P4  = make_yolo_head(x, 256, len(anchors_mask[1]) * (num_classes+5), weight_decay)# 26,26,256 -> 26,26,128 -> 52,52,128x   = compose(DarknetConv2D_BN_Leaky(128, (1,1), weight_decay=weight_decay), UpSampling2D(2))(x)# 52,52,128 + 52,52,256 -> 52,52,384x   = Concatenate()([x, C3])#---------------------------------------------------##   第三个特征层#   y3=(batch_size,52,52,3,85)#---------------------------------------------------## 52,52,384 -> 52,52,128 -> 52,52,256 -> 52,52,128 -> 52,52,256 -> 52,52,128x   = make_five_conv(x, 128, weight_decay)P3  = make_yolo_head(x, 128, len(anchors_mask[2]) * (num_classes+5), weight_decay)return Model(inputs, [P5, P4, P3])def get_train_model(model_body, input_shape, num_classes, anchors, anchors_mask):y_true = [Input(shape = (input_shape[0] // {0:32, 1:16, 2:8}[l], input_shape[1] // {0:32, 1:16, 2:8}[l], \len(anchors_mask[l]), num_classes + 5)) for l in range(len(anchors_mask))]model_loss  = Lambda(yolo_loss, output_shape    = (1, ), name            = 'yolo_loss', arguments       = {'input_shape'       : input_shape, 'anchors'           : anchors, 'anchors_mask'      : anchors_mask, 'num_classes'       : num_classes, 'balance'           : [0.4, 1.0, 4],'box_ratio'         : 0.05,'obj_ratio'         : 5 * (input_shape[0] * input_shape[1]) / (416 ** 2), 'cls_ratio'         : 1 * (num_classes / 80)})([*model_body.output, *y_true])model       = Model([model_body.input, *y_true], model_loss)return model

3. 源码地址

https://github.com/mcuwangzaiacm/YOLOV3_Pytorch/tree/main/utils

三. 检测效果

训练采用5000张电路板, 每张电路板上标记了4-30个的电容,4个种类(上,下,左, 右),检测电容极性,检测效果如下


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部