赞
踩
Deeplab系列也是分割领域的经典算法,Deeplabv3+则是这个系列的最新算法,充分融合了前面几个版本的优点,很适合大家上手。本文会详细介绍如何使用DeepLabv3+训练自己的数据集,很适合初学者上手。
原文链接:https://arxiv.org/pdf/1802.02611.pdf
代码链接:https://github.com/bubbliiiing/deeplabv3-plus-pytorch
(注:代码来源于github上的bubbliiiing大神,上一篇unet的文章也是使用的他的项目。整个项目注释非常详细,对初学者非常友好)
实验环境:linux torch1.12.0+cu116、windows torch1.9.0+cu102;其他版本应该也没有问题。
在深度神经网络中,空间金字塔池化模块或编码-解码结构常被用于语义分割任务。前者通过在不同速率和多个有效视场范围内对输入特征进行过滤器或池化操作探查,能够编码多尺度上下文信息;而后者网络则通过逐步恢复空间信息来捕获更锐利的物体边界。在本工作中,我们提议结合这两种方法的优点。具体来说,我们提出的模型DeepLabv3+在DeepLabv3的基础上进行了扩展,通过添加一个简单且有效的解码模块,特别是在物体边界处细化分割结果。我们进一步探索了Xception模型,并将深度可分离卷积应用于空洞空间金字塔池化和解码模块中,从而构建出更快更强的编码-解码网络。我们在PASCAL VOC 2012和Cityscapes数据集上验证了所提模型的有效性,在没有任何后处理的情况下,分别达到了89.0%和82.1%的测试集性能水平。
Deeplabv3+与原来的Deeplab系列算法相比,创新点主要体现在三个方面:
(1) ASPP优化:在原有Deeplab系列的基础上,Deeplabv3+进一步优化了ASPP模块,通过采用不同扩张率(dilation rate)的空洞卷积(atrous convolution)并行提取多尺度上下文信息,同时引入全局上下文池化层,从而能够在不降低分辨率的前提下,有效捕获图像中不同大小的目标和上下文特征。
(2) 编码-解码结构改进:Deeplabv3+在维持了编码器强大的特征提取能力之外,还新增了一个简洁而高效的解码器模块。该解码器通过与编码器不同层次的特征进行跳跃连接(skip connections),能够逐步恢复空间信息,特别是在物体边界处进行细化处理,从而提高分割结果的精确度,特别是对于边界清晰度的提升显著。
(3)借鉴深度可分离卷积:模型借鉴了Xception模型中的深度可分离卷积(depthwise separable convolution)思想,将其应用于ASPP模块和解码器模块中,大幅减少了模型的计算复杂性和参数量,既提高了运算速度,又保证了模型的分割性能。
使用git或者download zip都行。
(1) 安装labelme,选择Edit–>Create Polygons,然后进行标注。下载labelme时,版本最好一致。否则在进行第二步时会报错。(标注图像版本没有要求,只是在将json转图片的时候会有问题)
pip install labelme==3.16.7
labelme
这个数据集是一个火灾数据集,红色多边形区域是烟熏区域,绿色线段则表示裂缝区域。在这里对于一些裂缝、细线等,我们可以使用Create Line的标注方式,然后在生成的mask图像中,对该像素值进行膨胀即可。
(2)自定义数据集
将标注好的数据放在 datasets/before
然后修改json_to_dataset.py第23行,将classes中修改成自己的标签名称,第一个类别__background__不变,后面依次修改成自己的标签,再运行该文件(此处为了方便使用1,2表示类别)。
if __name__ == '__main__':
jpgs_path = "datasets/JPEGImages"
pngs_path = "datasets/SegmentationClass"
# 修改classes
classes = ["_background_","1","2"]
然后datasets/JPEGImages和datasets/SegmentationClass中会生成对应的原图和label文件。
然后生成对应的train.txt和val.txt
import os
import random
imgdir="datasets/SegmentationClass"
imglist=os.listdir(imgdir)
imglist = [imgname[:-4]+'\n' for imgname in imglist]
train_sample = random.sample(imglist, int(0.8* len(imglist)))
with open("datasets/train.txt", 'w') as f:
f.writelines(train_sample)
valid_sample = []
for name in imglist:
if name not in train_sample:
valid_sample.append(name)
with open("datasets/val.txt", 'w') as f:
f.writelines(valid_sample)
最后数据集格式为
训练时,只需要修改train.py中的几处就行了,其中注释非常详细,基本不用修改,需要注意以下几点
(1)num_classes = 分割的类别+1,因为0为背景
(2)该项目并不是原本Unet模型,其backbone为vgg或者resnet50,如果需要model_path,则需要去github上下载对应的权重
(3)训练时需要修改以下几处数据集路径(此处尤为重要)。
train.py中
# 数据集路径
#------------------------------#
VOCdevkit_path = 'datasets'
# 读取数据集对应的txt
#---------------------------#
with open(os.path.join(VOCdevkit_path, "train.txt"),"r") as f:
train_lines = f.readlines()
with open(os.path.join(VOCdevkit_path, "val.txt"),"r") as f:
val_lines = f.readlines()
dataloader.py中
# 从文件中读取图像
#-------------------------------#
jpg = Image.open(os.path.join(os.path.join(self.dataset_path, "JPEGImages"), name + ".jpg"))
png = Image.open(os.path.join(os.path.join(self.dataset_path, "SegmentationClass"), name + ".png"))
然后就可以进行训练
推理时,只需要修改predict.py和unet.py中的一些参数,注释非常详细,按需求修改即可
后续会在一些任务中,对现有结构进行优化,以及onnx、openvino等部署,敬请期待。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。