YOLOv8目标检测创新改进与实战案例专栏
专栏目录: YOLOv8有效改进系列及项目实战目录 包含卷积,主干 注意力,检测头等创新机制 以及 各种目标检测分割项目实战案例
专栏链接: YOLOv8基础解析+创新改进+实战案例
介绍
摘要
在本文中,我们介绍了U-Net v2,一种用于医学图像分割的新型、稳健且高效的U-Net变体。它旨在增强语义信息在低级特征中的注入,同时精细化高级特征的细节。对于输入图像,我们首先通过深度神经网络编码器提取多层次特征。接下来,我们通过从高级特征中注入语义信息,并通过Hadamard积整合来自低级特征的更精细细节,来增强每一层的特征图。我们新颖的跳跃连接使所有层次的特征都具备丰富的语义特征和复杂的细节。改进后的特征随后被传递到解码器进行进一步处理和分割。我们的方法可以无缝集成到任何编码器-解码器网络中。我们在多个公开的医学图像分割数据集上评估了我们的方法,包括皮肤病变分割和息肉分割,实验结果表明,我们的新方法在保持内存和计算效率的同时,在分割准确性上优于最先进的方法。代码可在:https://github.com/yaoppeng/U-Net v2 获取。
文章链接
论文地址:论文地址
代码地址:代码地址
基本原理
SDI(Semantics and Detail Infusion)模块是U-Net v2架构中的核心组件,旨在提高医疗图像分割的效果。以下是SDI模块的详细介绍:
SDI模块的概念
SDI模块的主要目的是将高层特征中的语义信息与低层特征中的细节信息相结合,从而增强各级特征图的表示能力。这一模块通过简单高效的跳跃连接实现这一点,使得网络能够更好地捕捉图像的语义信息和细节信息。
SDI模块的结构
1. 空间和通道注意力机制
首先,SDI模块对编码器生成的每一级特征图应用空间和通道注意力机制。这一步骤使特征图能够整合局部的空间信息和全局的通道信息,公式如下:
$$ f1_i = \phi_{c_i}(\phi_{s_i}(f0_i)) $$
其中,$f0i$表示第$i$级的原始特征图,$\phi{si}$和$\phi{c_i}$分别表示空间和通道注意力机制的参数,$f1_i$是处理后的特征图。
2. 特征图的通道数减少
接下来,通过1×1卷积将$f1_i$的通道数减少到一个超参数$c$,得到新的特征图$f2_i$。
3. 特征图的调整
为了将特征图传送到解码器,SDI模块将每一级的特征图调整为相同的分辨率。调整后的特征图表示为$f3_{ij}$,其中$i$表示目标级别,$j$表示特征图的来源级别。调整操作包括:
- 对于$j<i$的情况,使用自适应平均池化调整尺寸。
- 对于$j=i$的情况,使用恒等映射。
- 对于$j>i$的情况,使用双线性插值调整尺寸。
4. 特征图的平滑
调整尺寸后的特征图通过3×3卷积进行平滑,表示为$f4_{ij}$。
5. 哈达玛积
最后,使用哈达玛积将所有调整后的特征图融合在一起,增强每一级特征图的语义信息和细节信息,得到$f5_i$。
SDI模块的优势
- 语义和细节的融合:SDI模块通过将高层特征的语义信息与低层特征的细节信息相结合,增强了每一级特征图的表示能力。
- 简洁高效的跳跃连接:相较于传统的特征图拼接方式,SDI模块的跳跃连接更为简单高效,减少了计算复杂度和GPU内存使用。
- 提升分割精度:通过实验验证,SDI模块显著提升了U-Net v2在多种医疗图像分割任务中的精度。
核心代码
class SDI(nn.Module):
def __init__(self, channel):
super().__init__()
# 创建一个包含4个卷积层的模块列表,每个卷积层的输入和输出通道数都为channel,卷积核大小为3x3,步长为1,填充为1
self.convs = nn.ModuleList(
[nn.Conv2d(channel, channel, kernel_size=3, stride=1, padding=1) for _ in range(4)])
def forward(self, xs, anchor):
# 创建一个与anchor形状相同的全1张量
ans = torch.ones_like(anchor)
target_size = anchor.shape[-1] # 获取anchor的最后一个维度大小,即目标大小
for i, x in enumerate(xs):
# 如果当前张量x的最后一个维度大于目标大小,使用自适应平均池化将其调整为目标大小
if x.shape[-1] > target_size:
x = F.adaptive_avg_pool2d(x, (target_size, target_size))
# 如果当前张量x的最后一个维度小于目标大小,使用双线性插值将其调整为目标大小
elif x.shape[-1] < target_size:
x = F.interpolate(x, size=(target_size, target_size),
mode='bilinear', align_corners=True)
# 将调整大小后的张量x经过对应的卷积层,并将结果与ans相乘
ans = ans * self.convs[i](x)
return ans # 返回最终结果
task与yaml配置
详见: https://blog.csdn.net/shangyanaf/article/details/140498153