一、数据集准备
图片加载,标签定义,数据增强
-
首先要将照片批量处理成512*512像素的照片
- os.path.join()函数用于路径拼接文件路径,可以传入多个路径
- 如果不存在以‘’/’开始的参数,则函数会自动加上
- 存在以‘’/’’开始的参数,从最后一个以”/”开头的参数开始拼接,之前的参数全部丢弃
- 同时存在以‘’./’与‘’/’’开始的参数,以‘’/’为主,从最后一个以”/”开头的参数开始拼接,之前的参数全部丢弃
- 只存在以‘’./’开始的参数,会从”./”开头的参数的上一个参数开始拼接
- 使用PIL库中的image类
- open()打开图片文件
- save()方法保存
- size属性返回二元元组(w,h)
- new()方法生成新图像
- paste()将一张图片粘贴到另一张图像。box变量或者是一个给定左上角的2元组,或者是定义了左,上,右和下像素坐标的4元组,或者为空(与(0,0)一样)。如果给定4元组,被粘贴的图像的尺寸必须与区域尺寸一样。如果模式不匹配,被粘贴的图像将被转换为当前图像的模式
- resize()方法返回改变尺寸的图像的拷贝。变量size是所要求的尺寸,是一个二元组:(width, height)。变量filter为NEAREST、BILINEAR、BICUBIC或者ANTIALIAS之一
- 处理思路:
- img大小<512:直接用resize()会使图片比例失真造成扭曲,使用填充但是image类中不直接提供方法,所以先创建一纯黑512*512的底,再将原图粘贴在中央
- img大小>512:使用resize()
- os.path.join()函数用于路径拼接文件路径,可以传入多个路径
-
使用labelme标记
-
运行label2voc.py脚本,将json文件转换PASCAL VOC的语义分割标签格式或运行labelme自带的json_to_dataset.py,转换为数据集,运行前修改
-
处理后有97张,81张用作训练数据,剩余的作为测试数据
读取自己数据的基本流程:1.制作存储了图片的路径和标签信息的txt 2. 将这些信息转化为list,该list每一个元素对应一个样本 3. 通过getitem函数,读取数据和标签,并返回数据和标签
- . 对图像信息进行提取,提取图片路径和标签:方法就是将图片的系统路径和标签信息放在一个txt文件当中,然后再从这个txt中读取信息。
- 制作存储了图片系统路径和标签的txt文件
- 将这些信息转换成一个list,这个list的每一个元素对应一个样本
- 重写Dataset:
- __init__方法里面进行读取数据文件
- getitem函数,getitem接收一个index,然后返回图片数据和标签,这个index通常指的是一个list的index,这个list的每个元素就包含了图片数据的路径和标签信息
- 制作list,通常的方法是将图片的路径和标签信息存储在一个txt中,然后从该txt中读取(即第5步)
二、定义网络
- encoder和decoder结构
- 上采样/反卷积:放大图像(或称为上采样(upsampling)或图像插值(interpolating))的主要目的是:
放大原图像,从而可以显示在更高分辨率的显示设备上
方法:nn.ConvTranspose2d和nn.Upsample。Upsample通过插值方法完成上采样,所以不需要训练参数。ConvTranspose2d可以理解为卷积的逆过程,所以可以训练参数。 - skip-connection:特征融合,因编码阶段卷积池化过程会使图像的细节信息丢失,feature map进行拼接是为了尽可能的找回编码阶段所丢失的图像细节信息。U-net采用拼接(Concat),将特征在channel维度拼接在一起,形成更厚的特征。
- conv1(kernel_size=3,stride=1,padding=0) pooling(max pooling 2*2)up-conv()
- encoder:特征提取,应用了图像增强的方法,在数据集有限的情况下获得了不错的精度
1. 第一层:conv,ReLU,pooling
2. 第二层:conv,ReLU,pooling
3. 第三层:conv,ReLU,pooling
4. 第四层:conv,ReLU,pooling
5. 第五层:conv,ReLU,up-conv - decoder:
1. 第一层:conv,ReLU,up-conv
2. 第二层:conv,ReLU,up-conv
3. 第三层:conv,ReLU,up-conv
4. 第四层:conv,ReLU,conv
三、定义优化器和损失
- 定义损失:
pixel-wise softmax,其实这个没什么特别的,就是每个像素对应的输出单独做softmax,也就是做了w*h个softmax - 优化器:
四 参考博客
制作自己的数据集,使用Unet网络训练测试
代码
PIL库Image类
python PIL 填充图片 更改到规定尺寸
Pillow Image 填充图像
【计算机视觉】数据预处理-统一图片大小-image_resize-crop-pad-SPPnet-OpenCV-Python实现
Python实现批量修改图像大小尺寸
Pytorch加载自己的数据集(使用DataLoader加载Dataset)
labelme批量解析json文件出现PermissionErorr问题
https://blog.csdn.net/qq_51110792/article/details/116233439
制作用于图像语义分割训练的标签数据【图像分割】【labelme】
pythorch教程
五、报错
-
TypeError: default_collate: batch must contain tensors, numpy arrays, numbers, dicts or lists; found <class ‘_io.TextIOWrapper’>
需要是tensors, numpy arrays, numbers, dicts or lists等类型,在读取数据时使用torchvision.transforms.ToTensor()
-
TypeError: pic should be PIL Image or ndarray. Got <class ‘_io.TextIOWrapper’>
解决上一个问题后,又报错,查看别人博客,猜测是读取文件方法错了,改用Image.open()
-
RuntimeError: Given groups=1, weight of size [64, 1, 3, 3], expected input[27, 3, 512, 512]
to have 1 channels, but got 3 channels instead因为彩色图片channel为3。weight of size [64, 1, 3, 3]代表卷积核channel是1->64,大小为3x3;input[27, 3, 512, 512] to have 1 channels代表现在要卷积的featuremap大小512x512,channe 3,bachsize是27
-
RuntimeError: [enforce fail at …\c10\core\CPUAllocator.cpp:79] data. DefaultCPUAllocator: not enough
设置的张量过大,导致内存分配不足。
-
RuntimeError: all elements of input should be between 0 and 1
需要在网络的输出层之后新加一个Sigmoid层,这样便可以将输出值的取值规范到0和1之间;或将输出值送入交叉熵公式进行性计算之前,手动用Simgmoid函数做一个映射;或BCEWithLogitsLoss方法,它可以直接将输入的值规范到0和1 之间,相当于将Sigmoid和BCELoss集成在了一个方法中