专栏目录 :《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有40+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进——点击即可跳转
近年来,基于深度学习的人脸检测算法取得了很大进步。这些算法大致可以分为两类,即类似于Faster R-CNN的两阶段检测器和类似于YOLO的一阶段检测器。由于在一阶段检测器中准确性和速度之间有更好的平衡,因此它们被广泛应用于许多应用中。研究者设计了一个名为RFE的感受野增强模块,用于增强小目标的感受野。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。
1. 原理
RFEM(Receptive Field Enhancement Module)是用于增强神经网络中特征图感受野的模块。在深度学习和计算机视觉中,感受野(Receptive Field)是指卷积神经网络中某个神经元能够“看到”或影响输入图像的区域。RFEM的设计目的是为了提升神经网络在处理小目标和多尺度目标时的性能。以下是RFEM的主要原理和功能:
感受野的扩展:RFEM通过使用扩张卷积(Dilated Convolution)技术来扩大特征图的感受野。扩张卷积能够在不增加参数数量的情况下增加卷积核的感受野,从而能够更好地捕捉到输入图像中的远程依赖关系和上下文信息。
多尺度特征融合:RFEM不仅仅是简单地扩展感受野,还通过多尺度特征融合来增强特征图的表示能力。在卷积神经网络中,不同层的特征图包含不同尺度的信息,通过融合这些多尺度特征,RFEM能够更有效地处理不同尺度的目标。
处理小目标和大尺度变化:在许多应用中,例如人脸检测,小目标和尺度变化大的目标检测是一个重要挑战。RFEM通过感受野的扩展和多尺度特征的融合,能够提高对小目标和大尺度变化目标的检测能力。
集成到现有的检测架构中:RFEM可以很容易地集成到现有的检测架构中,例如YOLO、Faster R-CNN等。通过在这些架构的特定层次上加入RFEM模块,可以显著提升检测性能,特别是在处理复杂场景和小目标时。
总结来说,RFEM通过扩展感受野和多尺度特征融合,提高了神经网络在处理小目标和多尺度目标时的检测能力,并且可以集成到各种现有的检测架构中以提升其性能。这使得RFEM成为一种有效的改进模块,用于提升深度学习模型在复杂场景中的表现。
2. C3RFEM的代码实现
2.1 将C3RFEM添加到YOLOv8中
关键步骤一: 将下面代码粘贴到在/ultralytics/ultralytics/nn/modules/block.py中,并在该文件的__all__中添加“C3RFEM”
*注:代码太长,完整代码请查看下方的完整代码分享
class TridentBlock(nn.Module):
def __init__(self, c1, c2, stride=1, c=False, e=0.5, padding=None, dilate=None, bias=False):
super(TridentBlock, self).__init__()
if padding is None:
padding = [1, 2, 3]
if dilate is None:
dilate = [1, 2, 3]
self.stride = stride
self.c = c
c_ = int(c2 * e)
self.padding = padding
self.dilate = dilate
self.share_weightconv1 = nn.Parameter(torch.Tensor(c_, c1, 1, 1))
self.share_weightconv2 = nn.Parameter(torch.Tensor(c2, c_, 3, 3))
self.bn1 = nn.BatchNorm2d(c_)
self.bn2 = nn.BatchNorm2d(c2)
self.act = nn.SiLU()
nn.init.kaiming_uniform_(self.share_weightconv1, nonlinearity="relu")
nn.init.kaiming_uniform_(self.share_weightconv2, nonlinearity="relu")
if bias:
self.bias = nn.Parameter(torch.Tensor(c2))
else:
self.bias = None
if self.bias is not None:
nn.init.constant_(self.bias, 0)
def forward_for_small(self, x):
residual = x
out = nn.functional.conv2d(x, self.share_weightconv1, bias=self.bias)
out = self.bn1(out)
out = self.act(out)
out = nn.functional.conv2d(out, self.share_weightconv2, bias=self.bias, stride=self.stride,
padding=self.padding[0],
dilation=self.dilate[0])
out = self.bn2(out)
out += residual
out = self.act(out)
return out
def forward_for_middle(self, x):
residual = x
out = nn.functional.conv2d(x, self.share_weightconv1, bias=self.bias)
out = self.bn1(out)
out = self.act(out)
out = nn.functional.conv2d(out, self.share_weightconv2, bias=self.bias, stride=self.stride,
padding=self.padding[1],
dilation=self.dilate[1])
out = self.bn2(out)
out += residual
out = self.act(out)
return out
def forward_for_big(self, x):
residual = x
out = nn.functional.conv2d(x, self.share_weightconv1, bias=self.bias)
out = self.bn1(out)
out = self.act(out)
out = nn.functional.conv2d(out, self.share_weightconv2, bias=self.bias, stride=self.stride,
padding=self.padding[2],
dilation=self.dilate[2])
out = self.bn2(out)
out += residual
out = self.act(out)
return out
def forward(self, x):
xm = x
base_feat = []
if self.c is not False:
x1 = self.forward_for_small(x)
x2 = self.forward_for_middle(x)
x3 = self.forward_for_big(x)
else:
x1 = self.forward_for_small(xm[0])
x2 = self.forward_for_middle(xm[1])
x3 = self.forward_for_big(xm[2])
base_feat.append(x1)
base_feat.append(x2)
base_feat.append(x3)
return base_feat