【语义分割项目实战】Augmentor数据增强与U-Net的综合应用

之前已经介绍过了数据增强工具Augmentor的使用 

【语义分割项目实战】基于Augmentor工具的语义分割中常见几种数据增强方式(一)_Bill~QAQ~的博客-CSDN博客

以及简单的复现U-Net网络

【语义分割项目实战】制作语义分割数据集,并使用U-Net进行实战检测_Bill~QAQ~的博客-CSDN博客_unet医学图像分割实战

现在我们需要将两者综合运用起来,其中还是有不少问题需要微调的

1.进行格式转换

 首先按照要求,我们需要制作好自己的VOC格式数据集 ,也就是原图的图片(一般是jpg)和与其一一对应的掩膜图像(一般是png)

要想使用Augmentor进行数据增强,我们需要确保所有的图片都是jpg格式,因此需要进行格式转换,把imgs文件夹下的jpg原图转换成png

import os
import string
dirName = ".\imgs\\"         #改成自己的路径,最后要加双斜杠
li=os.listdir(dirName)
for filename in li:
    newname = filename
    newname = newname.split(".")
    if newname[-1]=="jpg":
        newname[-1]="png"
        newname = str.join(".",newname)  #这里要用str.join
        filename = dirName+filename
        newname = dirName+newname
        os.rename(filename,newname)
        print(newname,"updated successfully")

2.进行增强 

随后就可以把图片进行数据增强了,下面是我使用的方法,均来自Augmentor的功能库

import Augmentor
#原图的路径
p=Augmentor.Pipeline(".\imgs")
#掩膜图像的路径
p.ground_truth(".\jsons")
p.rotate(probability=1,max_left_rotation=25,max_right_rotation=25)
p.flip_left_right(probability=1)
p.flip_top_bottom(probability=1)
p.scale(probability=1,scale_factor=1.25)
# #缩小
# p.zoom_random(probability=1,percentage_area=0.4)
# #从中心裁剪
# p.crop_centre(probability=1,percentage_area=0.6)
# #按大小裁剪
# p.crop_by_size(probability=1,width=100,height=100)
#垂直形变
p.skew_tilt(probability=1,magnitude=1)
#斜四角形变
p.skew_corner(probability=1,magnitude=1)
# #弹性扭曲
# p.random_distortion(probability=1,grid_height=5,grid_width=16,magnitude=8)
#错切变换
p.shear(probability=1,max_shear_left=25,max_shear_right=25)
# #生成的原图+掩膜图像的总数目,建议是偶数
p.sample(700)

生成的结果如下,因为数据太多了所以我只截取部分进行展示

【语义分割项目实战】Augmentor数据增强与U-Net的综合应用_第1张图片

3.格式统一

可以明显的看到,得到的所有图片文件的命名都发生了改变,这样使得我们的原图在网络中不能找到与其一一对应的掩膜图像,同时所有的掩膜图像和原图都放在output文件夹下面,不利于我们的网络进行图片的读取,因此我们需要一些脚本作为辅助。

首先是将原图和掩膜图像分别存在不同的文件夹中,我这里是单独将掩膜图像划分到另一个文件夹下

import os
# 文件夹筛选器
formFilter = lambda form :\
    lambda f : True if f[-len(form):] == form else False

# 只对文件名称中有mark的进行操作
markFilter = lambda mark:\
    lambda f : True if mark in f else False

# 输入文件夹,返回文件夹下所有dType类型数据
getAllFiles = lambda path,dType : \
    list(filter(formFilter(dType),os.listdir(path))) #筛选文件

# 新建文件夹
def mkDir(path):
    if not os.path.exists(path):
        os.mkdir(path)

def splitFolder(path=r'imgs/output',mark="groundtruth"):
    if path[-1]!='\\':
        path += "\\"
    files = getAllFiles(path,"png")
    files = list(filter(markFilter(mark),files))
    for f in files:
        try:
            folder = f.split(mark)[0]
            newName = f[len(folder)+1:]
            mkDir(path+folder)
            os.rename(path+f,path+folder+'\\'+newName)
        except:
            print(f)

if __name__ == "__main__":
    splitFolder()

【语义分割项目实战】Augmentor数据增强与U-Net的综合应用_第2张图片

可以看到所有的掩膜图像都被存到了一个名为-的文件夹中

然后我们就需要对原图和掩膜图像都进行改名,需要知道的是,操作系统对于图片的读取是有一定规律的,比如我有若干个命名分别为1,2,10,20,3,30的文件,那么系统读取图片的顺序是:1,10,2,20,3,30,先看第一位数字再看第二位数字。

这也就说明。虽然在读取原图和掩膜图像的过程中,会使得原有的存放顺序发生改变,但是如果这种改变是有规律的,且相同的,那么就说明得到的结果原图和掩膜图像还是会保持一一对应的关系,不信我们就测试一下

import os


class BatchRename():

    def __init__(self):
        self.path = 'imgs/output/_'#改成自己的路径,分别对掩膜和原图进行改名,就是要运行两次

    def rename(self):
        filelist = os.listdir(self.path)
        filelist.sort()
        total_num = len(filelist)
        i = 0
        for item in filelist:
            if item.endswith('.png'):
                src = os.path.join(os.path.abspath(self.path), item)
                s = str(i)
                s = s.zfill(6)
                dst = os.path.join(os.path.abspath(self.path), s + '.png')

                try:
                    os.rename(src, dst)
                    print('converting %s to %s ...' % (src, dst))
                    i = i + 1
                except:
                    continue
        print('total %d to rename & converted %d jpgs' % (total_num, i))


if __name__ == '__main__':
    demo = BatchRename()
    demo.rename()

 我们可以直接用肉眼比较一下生成的结果,很明显可以看出他们仍然是一一对应的

【语义分割项目实战】Augmentor数据增强与U-Net的综合应用_第3张图片

随后我们将结果放入U-Net下的data文件夹中,进行训练即可,具体的参数(epoch,batch-size,learning rate)根据自身需求和硬件条件自行调整

【语义分割项目实战】Augmentor数据增强与U-Net的综合应用_第4张图片

__________________________________________________________________________

记录两个改错记录,希望对大家有所帮助

第一个:

 我遇到这个错误是在将batch-size从1调大到3的时候遇到的,意思是读入图像的大小不一致

修改方法:在Augmentor进行数据增强的时候使用resize方法把图像大小都调成一样的

#修改图像的大小
p.resize(probability=1,width=500,height=500)

第二个:

RuntimeError: Trying to resize storage that is not resizable

修改方法:在train.py的第45行,num_workers数量改为0

#把num_workers改为0
 loader_args = dict(batch_size=batch_size, num_workers=0, pin_memory=True)

这是调参之后的结果,调参的目的是为了train loss收敛的更快更低,同时提高validation dice

【语义分割项目实战】Augmentor数据增强与U-Net的综合应用_第5张图片

使用predict.py进行一下测试

 【语义分割项目实战】Augmentor数据增强与U-Net的综合应用_第6张图片

 【语义分割项目实战】Augmentor数据增强与U-Net的综合应用_第7张图片

 简单说一下调参的过程

1.首先控制batch-size不变,从1e-3开始调learning-rate,每次除以2,我大概调到1e-5是最优

2.保持learning-rate不变,增大或者减少batch-size

除此之外,还有以下参数可以调整:

Epoch:一个epoch代表遍历了一次训练集中的所有样本

Batch-size:批大小,会影响训练速度,建议设置为2n2^n

Optimizer:优化器,包括SGDAdamRMSprop

Learning-rate:学习率,要根据优化器和batch-size进行调整

Weight_decay:正则化系数(权重衰减系数),防止过拟合

Momentum:动量,用于优化器中

Load:是否预加载模型

Validation:验证集的比例

Class:需要分割的类数目(包括背景)

Scale:图像放入网络时缩放的比例

你可能感兴趣的:(语义分割)