之前已经介绍过了数据增强工具Augmentor的使用
【语义分割项目实战】基于Augmentor工具的语义分割中常见几种数据增强方式(一)_Bill~QAQ~的博客-CSDN博客
以及简单的复现U-Net网络
【语义分割项目实战】制作语义分割数据集,并使用U-Net进行实战检测_Bill~QAQ~的博客-CSDN博客_unet医学图像分割实战
现在我们需要将两者综合运用起来,其中还是有不少问题需要微调的
首先按照要求,我们需要制作好自己的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")
随后就可以把图片进行数据增强了,下面是我使用的方法,均来自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)
生成的结果如下,因为数据太多了所以我只截取部分进行展示
可以明显的看到,得到的所有图片文件的命名都发生了改变,这样使得我们的原图在网络中不能找到与其一一对应的掩膜图像,同时所有的掩膜图像和原图都放在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()
可以看到所有的掩膜图像都被存到了一个名为-的文件夹中
然后我们就需要对原图和掩膜图像都进行改名,需要知道的是,操作系统对于图片的读取是有一定规律的,比如我有若干个命名分别为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()
我们可以直接用肉眼比较一下生成的结果,很明显可以看出他们仍然是一一对应的
随后我们将结果放入U-Net下的data文件夹中,进行训练即可,具体的参数(epoch,batch-size,learning rate)根据自身需求和硬件条件自行调整
__________________________________________________________________________
记录两个改错记录,希望对大家有所帮助
第一个:
我遇到这个错误是在将batch-size从1调大到3的时候遇到的,意思是读入图像的大小不一致
修改方法:在Augmentor进行数据增强的时候使用resize方法把图像大小都调成一样的
#修改图像的大小
p.resize(probability=1,width=500,height=500)
第二个:
修改方法:在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
使用predict.py进行一下测试
简单说一下调参的过程
1.首先控制batch-size不变,从1e-3开始调learning-rate,每次除以2,我大概调到1e-5是最优
2.保持learning-rate不变,增大或者减少batch-size
除此之外,还有以下参数可以调整:
Epoch:一个epoch代表遍历了一次训练集中的所有样本
Batch-size:批大小,会影响训练速度,建议设置为2n2^n
Optimizer:优化器,包括SGD,Adam,RMSprop等
Learning-rate:学习率,要根据优化器和batch-size进行调整
Weight_decay:正则化系数(权重衰减系数),防止过拟合
Momentum:动量,用于优化器中
Load:是否预加载模型
Validation:验证集的比例
Class:需要分割的类数目(包括背景)
Scale:图像放入网络时缩放的比例