focus结构原理
对输入图片进行切片操作, 即每隔一个像素取一个值, W和H信息集中到通道空间,输入通道扩充了4倍,再进行卷积得到二倍下采样特征图(在YOLOv5新版本中,Focus层可能已经被6×6卷积层所替代)
focus结构作用
- 提高模型对小目标的检测能力:由于Focus结构通过切片和拼接操作,使得模型更加关注小目标的特征,从而提高检测效果。
- 减少计算量和内存占用:Focus结构通过压缩和重构输入的特征图,减少了输入特征图的通道数,同时保留了特征图中的重要信息,从而降低了计算量和内存占用。
代码
class Focus(nn.Module):
# Focus wh information into c-space
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups
super(Focus, self).__init__()
self.conv = Conv(c1 * 4, c2, k, s, p, g, act)
def forward(self, x): # x(b,c,w,h) -> y(b,4c,w/2,h/2)
return self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1))
解释
-
__init__
方法:c1
:输入特征图的通道数。c2
:输出特征图的通道数。k
:卷积核的大小(默认为1)。s
:卷积步长(默认为1)。p
:卷积填充(默认为None
,但在YOLOv5中通常不使用填充)。g
:卷积组的数量(默认为1)。act
:一个布尔值,用于确定是否在卷积层后使用激活函数(默认为True
)。
在这个初始化方法中,创建了一个
Conv
对象(尽管在您的代码片段中没有给出Conv
的定义,但我们可以假设它是一个卷积层,可能包含卷积、批量归一化和激活函数)。这个Conv
层接受c1 * 4
个输入通道(因为输入特征图会被切片并拼接成四部分),并输出c2
个通道。 -
forward
方法:- 输入
x
是一个四维张量,形状为(b, c1, w, h)
,其中b
是批量大小,c1
是输入通道数,w
和h
是特征图的宽度和高度。
在
forward
方法中,首先使用切片操作将输入特征图x
拆分成四个部分:x[..., ::2, ::2]
:取原始特征图的左上角像素。x[..., 1::2, ::2]
:取原始特征图的右上角像素。x[..., ::2, 1::2]
:取原始特征图的左下角像素。x[..., 1::2, 1::2]
:取原始特征图的右下角像素。
然后,这四个部分在通道维度上进行拼接,得到一个新的四维张量,形状为
(b, c1 * 4, w/2, h/2)
。这个张量随后被传递给之前定义的Conv
层,得到最终的输出。 - 输入