tensorflow2实现YOLOv6交通标志检测

1. 前言

最近频繁的使用了YOLOv6网络模型,发现性能是真的强,那就来写一篇博客记录一下吧。。。

首先来比较一下YOLOv6与其它YOLO性能,如下图,图来自美团YOLOv6。
tensorflow2实现YOLOv6交通标志检测_第1张图片
tensorflow2实现YOLOv6交通标志检测_第2张图片
通过上面2张图比较发现,无论是速度还是精度均超越其他同体量算法。

2. YOLOv6网络结构

tensorflow2实现YOLOv6交通标志检测_第3张图片
如上图是YOLOv6的整体网络结构,主要由三个部分组成Backbone、Neck还有Head部分组成。

其流程为:先对输入的图片预处理,处理成640*640大小的RGB图片,再送入Backbone网络结构,由Backbone网络经过特征提取,输出三层特征层,再将这三层的特征层传入Neck部分,进行特征融合,输出三层特征图,输入到Head部分,对图像检测的三类任务(分类、前后背景分类、边框)预测,输出最后的结果。

接下里就来看看YOLOv6的细节部分。

3. YOLOv6的Backbone

tensorflow2实现YOLOv6交通标志检测_第4张图片
如上图,其中Input代表输入,一般是图片预处理之后分辨率为640*640大小的图片。stem代表的是RepConv,也就是RepVGG网络中的卷积模块,是一种在训练时具有多分支拓扑,而在实际部署时可以等效融合为单个 3x3 卷积的一种可重参数化的结构,融合过程如下图,该卷积模块的作用:可以有效利用计算密集型硬件计算能力,同时提高算法的精度,让检测网络更快更强。其Tensorflow2代码现实方式如下:

tensorflow2实现YOLOv6交通标志检测_第5张图片

def ConvBn(inputs, filters, kernel_size, stride, padding, groups=1, weight_decay=5e-4):
    x = Conv2D(filters=filters, kernel_size=kernel_size, strides=stride, padding=padding, 
               groups=groups, use_bias=False, kernel_initializer=RandomNormal(stddev=0.02),
               kernel_regularizer=l2(weight_decay))(inputs)
    x = BatchNormalization()(x)
    return x

# RepVGG网络中的卷积模块
def RepVGGBlock(inputs, filters, kernel_size=3, stride=1, padding='same', dilation=1, groups=1,
                deploy=False, weight_decay=5e-4):
    if deploy:
        x = Conv2D(filters=filters, kernel_size=kernel_size, strides=stride, padding=padding, 
                   dilation_rate=dilation, use_bias=True, kernel_initializer=RandomNormal(stddev=0.02),
                   kernel_regularizer=l2(weight_decay))(inputs)
        x = ReLU()(x)
        return x
    else:
        if inputs.shape[-1] == filters and stride == 1:
            x0 = ConvBn(inputs, filters, kernel_size, stride, padding=padding, groups=groups)
            x1 = ConvBn(inputs, filters, 1, stride, padding=padding, groups=groups)
            x = Add()([x0, x1, BatchNormalization()(inputs)])
            return ReLU()(x)
        else:
            x0 = ConvBn(inputs, filters, kernel_size, stride, padding=padding, groups=groups)
            x1 = ConvBn(inputs, filters, 1, stride, padding=padding, groups=groups)
            x = Add()([x0, x1])
            return ReLU()(x)

RepBlock代表的是n个RepConv叠加SimSPPF代表的是原来YOLOv5、YOLOX的优化设计,如下图,其中cat代表特征层的融合
tensorflow2实现YOLOv6交通标志检测_第6张图片
其中SimConv代表卷积+标准化+激活函数,Tensorflow2实现代码如下:

def SimConv(inputs, filters, kernel_size, stride, groups=1, bias=False, padding='same', weight_decay=5e-4):
    x = Conv2D(filters=filters, kernel_size=kernel_size, strides=stride, padding=padding,
               groups=groups, use_bias=bias, kernel_initializer=RandomNormal(stddev=0.02),
               kernel_regularizer=l2(weight_decay))(inputs)
    x = BatchNormalization()(x) 
    x = ReLU()(x)
    return x

# 原始的 SPPF 优化设计
def SimSPPF(inputs, filters, kernel_size=5, weight_decay=5e-4):
    c_ = filters // 2
    x = SimConv(inputs, c_, 1, 1, padding='valid', weight_decay=weight_decay)
    with warnings.catch_warnings():
        warnings.simplefilter('ignore')
        y1 = MaxPool2D(pool_size=kernel_size, strides=1, padding='same')(x)
        y2 = MaxPool2D(pool_size=kernel_size, strides=1, padding='same')(y1)
        y3 = MaxPool2D(pool_size=kernel_size, strides=1, padding='same')(y2)
        out = Concatenate(axis=-1)([x, y1, y2, y3])
        return SimConv(out, filters, 1, 1, padding='valid', weight_decay=weight_decay)

tensorflow2实现YOLOv6交通标志检测_第7张图片

其Backbone的主要流程为:输入640x640x3的图片,通过stem层(s=2,步长为2)输出为32032032,后面接几个block(如上图的1、2、3、4),每个block均做特征层的下采样和channel的增大,每个block由一个RepConv和一个RepBlock组成(4多加SPPF层),在RepConv中做特征层的下采样,同时channel增大,在RepBlock中对特征层充分融合后输出,最后Backbone输出三个特征层分别为(20x20x512(第4个block), 40x40x128(第3个block), 80x80x64(第2个block))。

4. YOLOv6的Necktensorflow2实现YOLOv6交通标志检测_第8张图片

如上图,其中Upsimple代表上采样

Neck流程为:左侧,从Backbone第4个block输出20x20x512的特征层,通过SimConv 变成20x20x128大小,上采样后宽和高较之前增大一倍后与Backbone第3个block的输出在通道数上融合后特征层变成40x40x384,通过一个RepBlock后,输出 40x40x128,重复上述步骤后,输出80x80x64的特征层。右侧,将80x80x64的特征层先SimConv下采样,得到40x40x64的特征层,与左侧宽和高一致的特征层在通道数上融合后,通过一个RepBlock,输出第二个特征层,重复右侧以上步骤,输出第三个特征层。至此,Neck层输出三个特征层分别为(20x20x256, 40x40x128, 80x80x64)。

5. YOLOv6的Head

tensorflow2实现YOLOv6交通标志检测_第9张图片
如上图,其中YOLO-Head结构如下图。
tensorflow2实现YOLOv6交通标志检测_第10张图片
其中,Conv代表普通卷积+标准化+SiLU激活函数Conv2D代表普通卷积

Head流程:从Neck层输出三个分支,对于每个分支,先对输出特征图通过Conv层,做特征图的特征融合后,分成两个分支一个分支通过Conv+Conv2D完成分类任务的预测,另外一个分支先通过Conv融合特征后再分成两个分支,一个分支通过卷积完成边框的回归,一个分支通过Conv2D完成前后背景的分类,至此三个分支再通过合并在通道数上融合,输出未经后处理的预测结果。

6. 训练策略

6.1 基于Anchor-free预测目标

采用了更简洁的 Anchor-free 检测方法。由于 Anchor-based检测器需要在训练之前进行聚类分析以确定最佳 Anchor 集合,这会一定程度提高检测器的复杂度;同时,在一些边缘端的应用中,需要在硬件之间搬运大量检测结果的步骤,也会带来额外的延时。而 Anchor-free 无锚范式因其泛化能力强,解码逻辑更简单。与YOLOX类似。

6.2 SimOTA 标签分配策略

为了获得更多高质量的正样本,YOLOv6 引入了 SimOTA算法动态分配正样本,进一步提高检测精度。此类方法会根据训练过程中的网络输出来分配正样本,从而可以产生更多高质量的正样本,继而又促进网络的正向优化。与YOLOX的训练策略类似,可以先学习一下YOLOX。

6.3 使用了SIOU

论文地址:https://arxiv.org/ftp/arxiv/papers/2205/2205.12740.pdf

SIOU考虑框中心之间的距离、重叠区域和纵横比,这使得帮助了训练收敛过程和效果,因为它可以让预测框很快地移动到最近的轴,并且随后的方法只需要一个坐标 X 或 Y 的回归。简而言之,添加Angle惩罚成本有效地减少了损失的总自由度。

具体原理很简单,可以看该博客讲解SIOU

7. 交通标志数据集

数据集网址:
https://aistudio.baidu.com/aistudio/datasetdetail/49531
下载之后需要将文件夹格式处理成如下命名格式:

VOCdevkit
	- VOC2007
		- Annotations
		- ImageSets
		- JPEGImages

8. 代码仓库

gitee地址:https://gitee.com/Hao_gg/yolov6_-traffic_signs/tree/master
github地址:https://github.com/hao-ux/YOLOv6_Traffic_signs

9. 检测效果

tensorflow2实现YOLOv6交通标志检测_第11张图片

你可能感兴趣的:(目标检测,tensorflow,人工智能,深度学习)