【深度学习基础模型】轻量级实时语义分割经典之作BiSeNet!Bilateral Segmentation Network for Real-time Semantic Segmentation!
【深度学习基础模型】轻量级实时语义分割经典之作BiSeNet!Bilateral Segmentation Network for Real-time Semantic Segmentation!
文章目录
欢迎宝子们点赞、关注、收藏!欢迎宝子们批评指正!
祝所有的硕博生都能遇到好的导师!好的审稿人!好的同门!顺利毕业!
论文链接:https://arxiv.org/pdf/1808.00897
大多数高校硕博生毕业要求需要参加学术会议,发表EI或者SCI检索的学术论文会议论文:
可访问艾思科蓝官网,浏览2024年即将召开的学术会议列表。会议入口:https://ais.cn/u/mmmiUz
1. BiSeNet 的起源
BiSeNet,全称为 Bilateral Segmentation Network,由 Yu et al. 于 2018 年提出,最早发表于论文《BiSeNet: Bilateral Segmentation Network for Real-time Semantic Segmentation》【ECCV 2018】。
该网络旨在解决语义分割任务中的 实时性 和 精度 之间的权衡问题,即在保证高效推理速度的同时,尽量提高分割精度。
2. BiSeNet 的原理
BiSeNet 的核心思想是将特征提取过程划分为两个独立的分支:
-
Spatial Path(空间路径):用于保留高分辨率的空间信息(即位置信息),以弥补语义分割中的精度损失。该分支使用较少的卷积操作,保持较高的空间分辨率。
-
Context Path(上下文路径):用于捕捉场景中的上下文信息,帮助模型理解全局语义。该分支主要通过轻量化的卷积操作和全局池化,提供丰富的语义信息。
通过这两个路径的 融合,BiSeNet 在处理复杂的语义分割任务时既能保持高分辨率空间信息,又能获取足够的上下文信息。
-
Spatial Path
Spatial Path 由三个逐渐减小通道数的卷积层组成。该路径保留了输入图像的高分辨率空间信息,有助于精确定位物体的边界。 -
Context Path
Context Path 通过轻量化的网络(如 ResNet18)来提取全局的语义信息,同时采用 全局平均池化 来捕获全局的上下文信息。上下文路径的输出具有较低的分辨率,但提供了丰富的全局语义特征。 -
特征融合(Feature Fusion Module)
BiSeNet 将 Spatial Path 和 Context Path 的输出通过一个 特征融合模块(Feature Fusion Module, FFM) 进行融合。该模块通过 1x1 卷积和通道注意力机制来融合来自两个路径的特征,进一步提升分割性能。
3. BiSeNet 的创新点
BiSeNet 提出了以下创新点:
-
双路径结构(Dual Path Structure):BiSeNet 通过设计空间路径和上下文路径,成功解决了以往网络在实时分割任务中的两大问题——无法兼顾精度和速度。空间路径保留了高分辨率信息,而上下文路径提供了全局语义信息。
-
特征融合模块(Feature Fusion Module, FFM):BiSeNet 通过 FFM 模块有效融合了两个分支的特征,保证了两者的互补性,提升了分割精度。
-
轻量化设计:BiSeNet 的上下文路径采用轻量化的骨干网络(如 ResNet18),确保了其具有较快的推理速度,适合实时应用。
4. BiSeNet 的发展
BiSeNet 提出后,针对其结构和应用场景,出现了许多改进版本。例如:
-
BiSeNetV2:BiSeNetV2 是对原始 BiSeNet 的改进版,针对实时语义分割任务进一步优化,去除了部分冗余模块,同时引入了增强的上下文路径,提高了速度和精度。
-
应用于高分辨率图像的分割任务:BiSeNet 在高清图像(如城市场景)中,能够有效处理复杂的场景和边界分割问题,并且在嵌入式设备上表现优秀。
5. BiSeNet 的应用
-
实时语义分割:BiSeNet 的轻量化设计使其广泛应用于对实时性要求较高的场景,如自动驾驶、视频监控、机器人视觉等任务。
-
医学图像分割:BiSeNet 在医学图像中的应用也较为广泛,特别是在实时分割和精度要求较高的场景中,诸如病灶检测等任务。
-
无人机图像处理:BiSeNet 在无人机图像分析中,也可进行实时场景分割,以实现自动识别和导航任务。
6. BiSeNet 的 Python 实现
接下来,使用 PyTorch
实现一个简化版的 BiSeNet,并基于 Cityscapes 数据集进行训练和测试。代码包含详细的逐行解释。
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import models
# 定义空间路径(Spatial Path)
class SpatialPath(nn.Module):
def __init__(self):
super(SpatialPath, self).__init__()
# 三层卷积,每次通道数减半,但保持较高的空间分辨率
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
self.bn1 = nn.BatchNorm2d(64)
self.relu = nn.ReLU(inplace=True)
self.conv2 = nn.Conv2d(64, 128, kernel_size=3, stride=2, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(128)
self.conv3 = nn.Conv2d(128, 256, kernel_size=3, stride=2, padding=1, bias=False)
self.bn3 = nn.BatchNorm2d(256)
def forward(self, x):
x = self.relu(self.bn1(self.conv1(x)))
x = self.relu(self.bn2(self.conv2(x)))
x = self.relu(self.bn3(self.conv3(x)))
return x
# 定义上下文路径(Context Path),使用预训练的ResNet作为基础
class ContextPath(nn.Module):
def __init__(self):
super(ContextPath, self).__init__()
# 使用预训练的ResNet18模型作为上下文路径
resnet = models.resnet18(pretrained=True)
self.backbone = nn.Sequential(*list(resnet.children())[:-2]) # 去掉最后的FC层
# 全局平均池化
self.global_pool = nn.AdaptiveAvgPool2d(1)
def forward(self, x):
feature = self.backbone(x)
global_context = self.global_pool(feature)
global_context = F.interpolate(global_context, size=feature.size()[2:], mode='bilinear', align_corners=True)
return feature, global_context
# 定义特征融合模块(Feature Fusion Module, FFM)
class FeatureFusionModule(nn.Module):
def __init__(self, in_channels, out_channels):
super(FeatureFusionModule, self).__init__()
self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False)
self.bn = nn.BatchNorm2d(out_channels)
self.relu = nn.ReLU(inplace=True)
# 通道注意力机制
self.channel_attention = nn.Sequential(
nn.AdaptiveAvgPool2d(1),
nn.Conv2d(out_channels, out_channels // 4, kernel_size=1, bias=False),
nn.ReLU(inplace=True),
nn.Conv2d(out_channels // 4, out_channels, kernel_size=1, bias=False),
nn.Sigmoid()
)
def forward(self, sp_feature, context_feature):
# 先将两个路径的特征拼接
fused_feature = torch.cat([sp_feature, context_feature], dim=1)
fused_feature = self.conv(fused_feature)
fused_feature = self.relu(self.bn(fused_feature))
# 通道注意力
attention = self.channel_attention(fused_feature)
fused_feature = fused_feature * attention
return fused_feature
# 定义BiSeNet
class BiSeNet(nn.Module):
def __init__(self, num_classes):
super(BiSeNet, self).__init__()
self.spatial_path = SpatialPath()
self.context_path = ContextPath()
# 特征融合
self.feature_fusion = FeatureFusionModule(256 + 512, 256)
self.conv_out = nn.Conv2d(256, num_classes, kernel_size=1)
def forward(self, x):
# 空间路径输出
sp = self.spatial_path(x)
# 上下文路径输出
context, global_context = self.context_path(x)
fused = self.feature_fusion(sp, global_context)
# 输出分类
out = self.conv_out(fused)
out = F.interpolate(out, size=x.size()[2:], mode='bilinear', align_corners=True)
return out
# 定义模型、损失函数和优化器
model = BiSeNet(num_classes=19) # 对应 Cityscapes 数据集有 19 类
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 模拟训练和测试过程
def train(model, device, train_loader, optimizer, criterion):
model.train()
for data, target in train_loader:
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
def test(model, device, test_loader):
model.eval()
test_loss = 0
correct = 0
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
output = model(data)
test_loss += criterion(output, target).item()
test_loss /= len(test_loader.dataset)
print(f'Average loss: {test_loss:.4f}')
# 定义训练和测试数据集(此处需加载 Cityscapes 数据集)
# train_loader = ...
# test_loader = ...
# 设置设备
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)
# 训练和测试模型
for epoch in range(1, 11):
train(model, device, train_loader, optimizer, criterion)
test(model, device, test_loader)
代码解释:
-
SpatialPath:用于保留空间信息,采用 3 个卷积层,逐步减小通道数。
-
ContextPath:使用预训练的 ResNet18 提取全局上下文特征,并通过全局平均池化获取场景的全局语义信息。
-
Feature Fusion Module:融合空间路径和上下文路径的特征,并使用通道注意力机制进一步提升分割精度。
-
BiSeNet:组合空间路径、上下文路径和特征融合模块,输出最终的语义分割结果。
-
训练与测试:模拟了 BiSeNet 在 Cityscapes 数据集上的训练与测试流程。
通过 BiSeNet 的架构,模型既保留了空间信息,又获得了上下文语义信息,适合实时语义分割任务。
欢迎宝子们点赞、关注、收藏!欢迎宝子们批评指正!
祝所有的硕博生都能遇到好的导师!好的审稿人!好的同门!顺利毕业!
大多数高校硕博生毕业要求需要参加学术会议,发表EI或者SCI检索的学术论文会议论文:
可访问艾思科蓝官网,浏览2024年即将召开的学术会议列表。会议入口:https://ais.cn/u/mmmiUz