目录
一、准备工作
1.1数据集来源
利用ISIC2016数据集挑战皮肤图像分割。官网下载数据集地址为https://challenge.isic-archive.com/data/ 的第一行,如下图所示。
1.2模型来源
利用Pytorch的deeplabv3_resnet101模型进行图像分割;官网下载:模型下载地址为deeplabv3_resnet101 — Torchvision main documentation (pytorch.org);
百度网盘下载(包含ISIC2016数据集和预训练模型):链接:https://pan.baidu.com/s/1UqNNvv4WCnZUU7LcF14zlA
提取码:jnyy
二、模型简介
DeeplabV3+被认为是语义分割的新高峰,主要是因为这个模型的效果非常的好。DeepLabv3+主要在模型的架构上作文章,为了融合多尺度信息,其引入了语义分割常用的encoder-decoder形式。在 encoder-decoder 架构中,引入可任意控制编码器提取特征的分辨率,通过空洞卷积平衡精度和耗时。
DeeplabV3+与pspnet、segnet、unet相比,其最大的特点就是引入了空洞卷积,在不损失信息的情况下,加大了感受野,让每个卷积输出都包含较大范围的信息。如下就是空洞卷积的一个示意图,所谓空洞就是特征点提取的时候会跨像素;
2.1Encoder-Decoder部分
空洞卷积(Atrous Convolution)的目的是为了在不增加参数量的情况下扩展卷积的感受野,从而提取更有效的特征,因此它位于Encoder网络中用于特征提取。在这一部分有两个核心点:
在主干DCNN(深度卷积神经网络)里使用串行的Atrous Convolution: 串行的意思是一层接一层,普通的深度卷积神经网络的结构就是串行结构。通过在主干DCNN中使用串行的Atrous Convolution,网络能够有效地扩大感受野而不增加计算成本。这样可以捕捉到更多的上下文信息,有助于更精确的特征提取。例如,传统的卷积核可能只能看到局部的小区域,而经过Atrous Convolution处理的卷积核可以看到更大的区域。
将主干DCNN输出的结果分为两部分:一部分直接传入Decoder。这样可以保证原始的特征信息不丢失,直接用于后续的分割任务。另一部分经过并行的Atrous Convolution处理。具体来说,这部分输出会通过多个不同rate(膨胀率)的Atrous Convolution进行特征提取。不同的rate可以捕捉到不同尺度的特征信息。然后将这些提取到的特征进行合并,再通过一个1x1卷积层进行特征维度的压缩。这一步的目的是整合不同尺度的信息,形成更加丰富的特征表示。
Decoder部分的输入有两部分:
DCNN的直接输出:这个部分保留了原始的特征信息,确保了分割任务所需的基本信息不丢失。
DCNN输出经过并行空洞卷积后的结果:这一部分经过不同rate的空洞卷积处理后,提供了不同尺度的上下文信息。这些信息经过整合后,可以增强分割的准确性。
这两个部分的结果经过一定的处理后进行Concat(拼接)在一起。在DeepLabv3中,Upsample(上采样)的方式是使用双线性插值(bilinear interpolation)。双线性插值是一种常见的图像上采样方法,通过对邻近像素的线性插值来估算新像素值。这一步的目的是恢复图像的空间分辨率,使得输出的分割结果与原始输入图像具有相同的尺寸。
2.2Xception部分
修改后的Xception 如下:
- 更多的层(与 MSRA 的修改相同,除了入口流的变化);
- 所有最大池化操作都被跨步的深度可分离卷积所取代;
- 在每个 3 × 3 深度卷积之后添加额外的批量归一化和 ReLU,类似于 MobileNet;
三、建模及评估
3.1数据准备
在图像分割任务中,数据通常由原始图像和对应的分割掩码(Ground Truth)组成;具体步骤如下:
(1)加载数据集:通过自定义数据集类(例如 ISICDataset)加载数据。这个类需要实现 __init__、__len__ 和 __getitem__ 方法。
(2)数据预处理:对原始图像和掩码进行预处理,如调整大小、归一化等。可以使用 torchvision.transforms 提供的工具。
(3)数据加载器:使用 torch.utils.data.DataLoader 将数据集转换为可迭代对象,便于批量训练和验证。
# Define transforms
transform = transforms.Compose([
transforms.Resize((256, 256)), # Resize to a common size
transforms.ToTensor()
])
# Create datasets and dataloaders
train_dataset = ISICDataset('AI/data/Training_Data', 'AI/data/Training_GroundTruth', transform=transform)
train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)
test_dataset = ISICDataset('AI/data/Test_Data', 'AI/data/Test_GroundTruth', transform=transform)
test_loader = DataLoader(test_dataset, batch_size=1, shuffle=False)
3.2模型定义
深度学习模型是图像分割任务的核心。这里我们使用预训练的 DeepLabv3 模型,它在多个分割任务中表现优异;具体步骤如下:
(1)加载预训练模型:使用 torchvision.models.segmentation 加载预训练的 DeepLabv3 模型;
(2)修改输出层:根据具体的分割任务,调整模型的输出层。例如,对于二分类任务,可以将输出层修改为单通道;
class DeepLab(nn.Module):
def __init__(self, num_classes):
super(DeepLab, self).__init__()
# Load pre-trained DeepLabv3 with ResNet101 backbone
self.model = models.segmentation.deeplabv3_resnet101(pretrained=True, progress=True)
# Modify the classifier to match the output channels from ResNet101
self.model.classifier = nn.Conv2d(2048, num_classes, kernel_size=(1, 1), stride=(1, 1))
def forward(self, x):
return self.model(x)['out']
# Initialize model
model = DeepLab(num_classes=1) # Assuming binary segmentation
3.3模型训练
训练过程包括定义损失函数、优化器,并在每个训练周期中更新模型参数;具体步骤如下:
(1)定义损失函数和优化器:常用的损失函数有二值交叉熵损失(BCEWithLogitsLoss),优化器可以选择 Adam;
(2)训练循环:遍历训练数据,计算损失并更新模型参数。在每个 epoch 结束时,可以计算验证集上的损失和 IOU;
# Define loss function and optimizer
criterion = nn.BCEWithLogitsLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Training loop with metrics
import matplotlib.pyplot as plt
def train(model, train_loader, test_loader, criterion, optimizer, num_epochs=10):
train_losses = []
val_losses = []
val_ious = []
for epoch in range(num_epochs):
model.train()
train_loss = 0
for inputs, targets in train_loader:
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, targets)
loss.backward()
optimizer.step()
train_loss += loss.item()
train_loss /= len(train_loader)
train_losses.append(train_loss)
print(f'Epoch [{epoch+1}/{num_epochs}], Train Loss: {train_loss:.4f}')
val_loss, val_iou = validate(model, test_loader, criterion)
val_losses.append(val_loss)
val_ious.append(val_iou)
print(f'Epoch [{epoch+1}/{num_epochs}], Validation Loss: {val_loss:.4f}, IOU: {val_iou:.4f}')
# Train the model
train(model, train_loader, test_loader, criterion, optimizer, num_epochs=10)
3.4模型评估与结果可视化
在训练结束后,我们需要评估模型在测试集上的表现,并可视化分割结果;具体步骤如下:
(1)计算 IOU:对每张测试图像,计算预测掩码和真实掩码之间的 IOU;
(2)保存结果:将分割结果与真实掩码的可视化保存到指定目录;
import os
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
def evaluate(model, test_loader):
model.eval()
with torch.no_grad():
for idx, (inputs, targets) in enumerate(test_loader):
outputs = model(inputs)
predicted_mask = torch.sigmoid(outputs).squeeze().cpu().numpy() # Assuming binary output
groundtruth_mask = targets.squeeze().cpu().numpy()
# Calculate IOU
intersection = np.logical_and(predicted_mask > 0.5, groundtruth_mask > 0.5).sum()
union = np.logical_or(predicted_mask > 0.5, groundtruth_mask > 0.5).sum()
iou = intersection / union
# Visualization (save to results directory)
if idx < 100:
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.imshow(groundtruth_mask, cmap='Blues', alpha=0.5)
plt.title('Ground Truth')
plt.subplot(1, 2, 2)
plt.imshow(predicted_mask, cmap='Reds', alpha=0.5)
plt.title('Predicted')
plt.savefig(f'AI/results/image_{idx}.png')
plt.close()
print(f'Image {idx}: IOU = {iou}')
# Evaluate the model
evaluate(model, test_loader)
四、结果展示
4.1 分割效果
蓝色面积覆盖的实际掩码,红色面积覆盖的为预测掩码;
4.2 损失情况及IOU
(1)损失情况
随着训练进步,训练过程中的损失(Training loss)逐步降低且逐步收敛于0;而通过经过训练的网络运行验证数据集后的错误(Validation loss)随训练次数的增加并没有表现出很好的收敛性,仍然处于较大的波动中;
注:train_loss和val_loss关系分析可参考train_loss和val_loss关系分析-CSDN博客
(2)IOU
IOU平均预测值在epoch达到5之后基本上处于稳步提升的状态且逐步收敛
参考文献:
- Chen, L., Papandreou, G., Schroff, F., & Adam, H. (2017). Rethinking Atrous Convolution for Semantic Image Segmentation. ArXiv, abs/1706.05587.
- Chen, L., Papandreou, G., Kokkinos, I., Murphy, K.P., & Yuille, A.L. (2014). Semantic Image Segmentation with Deep Convolutional Nets and Fully Connected CRFs. CoRR, abs/1412.7062.
- Chen, L., Papandreou, G., Kokkinos, I., Murphy, K.P., & Yuille, A.L. (2016). DeepLab: Semantic Image Segmentation with Deep Convolutional Nets, Atrous Convolution, and Fully Connected CRFs. IEEE Transactions on Pattern Analysis and Machine Intelligence, 40, 834-848.
- L. -C. Chen, G. Papandreou, I. Kokkinos, K. Murphy and A. L. Yuille, "DeepLab: Semantic Image Segmentation with Deep Convolutional Nets, Atrous Convolution, and Fully Connected CRFs," in IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 40, no. 4, pp. 834-848, 1 April 2018, doi: 10.1109/TPAMI.2017.2699184.
- M. N. Mahmud, M. K. Osman, A. P. Ismail, F. Ahmad, K. A. Ahmad and A. Ibrahim, "Road Image Segmentation using Unmanned Aerial Vehicle Images and DeepLab V3+ Semantic Segmentation Model," 2021 11th IEEE International Conference on Control System, Computing and Engineering (ICCSCE), Penang, Malaysia, 2021, pp. 176-181, doi: 10.1109/ICCSCE52189.2021.9530950.
- S. M. Saranya, N. V, M. E, L. K. P, D. Komarasamy and M. S, "Image Segmentation Using DeepLab V3+ for Diabetic Retinopathy," 2024 1st International Conference on Innovative Sustainable Technologies for Energy, Mechatronics, and Smart Systems (ISTEMS), Dehradun, India, 2024, pp. 1-6, doi: 10.1109/ISTEMS60181.2024.10560140.
-
Chen, L., Zhu, Y., Papandreou, G., Schroff, F., & Adam, H. (2018). Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation. European Conference on Computer Vision.