【天池赛事】零基础入门语义分割-地表建筑物识别
Task1:赛题理解与 baseline(3 天)
– 学习主题:理解赛题内容解题流程
– 学习内容:赛题理解、数据读取、比赛 baseline 构建
– 学习成果:比赛 baseline 提交
Task2:数据扩增方法(3 天)
– 学习主题:语义分割任务中数据扩增方法
– 学习内容:掌握语义分割任务中数据扩增方法的细节和使用
– 学习成果:数据扩增方法的实践
Task3:网络模型结构发展(3 天)
– 学习主题:掌握语义分割模型的发展脉络
– 学习内容: FCN、 Unet、 DeepLab、 SegNet、 PSPNet
– 学习成果:多种网络模型的搭建
Task4:评价函数与损失函数(3 天)
– 学习主题:语义分割模型各种评价函数与损失函数
– 学习内容: Dice、 IoU、 BCE、 Focal Loss、 Lovász-Softmax
– 学习成果:评价/损失函数的实践
Task5:模型训练与验证(3 天)
– 学习主题:数据划分方法
– 学习内容:三种数据划分方法、模型调参过程
– 学习成果:数据划分具体操作
Task6:分割模型模型集成(3 天)
– 学习主题:语义分割模型集成方法
– 学习内容: LookaHead、 SnapShot、 SWA、 TTA
– 学习成果:模型集成思路
Task2:数据扩增方法
1 学习目标2 常见的数据增广方法3 OpenCV数据增广4 数据增广5 PyTorch数据读取6 小结本章对语义分割任务中常见的数据扩增方法进行介绍,并使用 OpenCV 和 albumentations 两个库完成具体的数据扩增操作。主要内容为数据扩增方法、 OpenCV 数据扩增、 albumentations 数据扩增和 Pytorch 读取赛题数据四个部分组成。
1 学习目标
• 理解基础的数据扩增方法
• 学习 OpenCV 和 albumentations 完成数据扩增
• Pytorch 完成赛题读取
2 常见的数据增广方法
数据扩增是一种有效的正则化方法,可以防止模型过拟合,在深度学习模型的训练过程中应用广泛。数据扩增的目的是增加数据集中样本的数据量,同时也可以有效增加样本的语义空间。
需注意:
不同的数据,拥有不同的数据扩增方法;数据扩增方法需要考虑合理性,不要随意使用;数据扩增方法需要与具体问题相结合,同时要考虑到标签的变化;
对于图像分类,数据扩增方法可以分为两类:
标签不变的数据扩增方法:数据变换之后图像类别不变;标签变化的数据扩增方法:数据变换之后图像类别变化;
而对于语义分割而言,常规的数据扩增方法都会改变图像的标签。如Vertical Flip(垂直翻转),Horizontal Flip(水平翻转),Random Rotate 90(随机旋转90度),Transpose(转置),Shift Scale Rotate(移位刻度旋转),Random Size Crop(随机剪裁)。
3 OpenCV数据增广
OpenCV 是计算机视觉必备的库,可以很方便的完成数据读取、图像变化、边缘检测和模式识别等任务,这里首先介绍 OpenCV 完成数据扩增的操作。
import numpy as npimport pandas as pdimport pathlib, sys, os, random, timeimport numba, cv2, gcfrom tqdm import tqdm_notebookimport matplotlib.pyplot as plt%matplotlib inlineimport warningswarnings.filterwarnings('ignore')from tqdm.notebook import tqdmimport albumentations as Aimport rasteriofrom rasterio.windows import Windowdef rle_encode(im):'''im: numpy array, 1 - mask, 0 - backgroundReturns run length as string formated'''pixels = im.flatten(order = 'F')pixels = np.concatenate([[0], pixels, [0]])runs = np.where(pixels[1:] != pixels[:-1])[0] + 1runs[1::2] -= runs[::2]return ' '.join(str(x) for x in runs)def rle_decode(mask_rle, shape=(512, 512)):'''mask_rle: run-length as string formated (start length)shape: (height,width) of array to return Returns numpy array, 1 - mask, 0 - background'''s = mask_rle.split()starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]starts -= 1ends = starts + lengthsimg = np.zeros(shape[0]*shape[1], dtype=np.uint8)for lo, hi in zip(starts, ends):img[lo:hi] = 1return img.reshape(shape, order='F')
train_mask = pd.read_csv('data/train_mask.csv',sep='\t',names=['name','mask'])train_mask['name'] = train_mask['name'].apply(lambda x: 'data/train/' + x)
# 读取原始图片img = cv2.imread(train_mask['name'].iloc[0])mask = rle_decode(train_mask['mask'].iloc[0])plt.figure(figsize=(16,8))plt.subplot(1,2,1)plt.imshow(img)plt.subplot(1,2,2)plt.imshow(mask,cmap='gray')plt.savefig('aug-1.png')
# 垂直翻转plt.figure(figsize=(16,8))plt.subplot(1,2,1)plt.imshow(cv2.flip(img,0))plt.subplot(1,2,2)plt.imshow(cv2.flip(mask,0),cmap='gray')
# 随机裁剪x, y = np.random.randint(0, 256), np.random.randint(0, 256)plt.figure(figsize=(16,8))plt.subplot(1,2,1)plt.imshow(img[x:x+256, y:y+256])plt.subplot(1,2,2)plt.imshow(mask[x:x+256,y:y+256],cmap='gray')
4 数据增广
albumentations 是基于 OpenCV 的快速训练数据增强库,拥有非常简单且强大的可以用于多种任务(分割、检测)的接口,易于定制且添加其他框架非常方便。
albumentations 也是计算机视觉数据竞赛中最常用的库:
GitHub: /albumentations-team/albumentations
示例: /albumentations-team/albumentations_examples
与 OpenCV 相比 albumentations 具有以下优点:
• albumentations 支持的操作更多,使用更加方便;
• albumentations 可以与深度学习框架(Keras 或 Pytorch)配合使用;
• albumentations 支持各种任务(图像分流)的数据扩增操作
albumentations 它可以对数据集进行逐像素的转换,如模糊、下采样、高斯造点、高斯模糊、动态模糊、 RGB 转换、随机雾化等;也可以进行空间转换(同时也会对目标进行转换),如裁剪、翻转、随机裁剪等。
def show_img_mask(img,mask):plt.figure(figsize=(16,8))plt.subplot(1,2,1)plt.imshow(img)plt.subplot(1,2,2)plt.imshow(mask,cmap='gray')plt.show()
import albumentations as A# 水平翻转augments = A.HorizontalFlip(p=1)(image=img, mask=mask)img_aug, mask_aug = augments['image'], augments['mask']show_img_mask(img_aug, mask_aug)
# 随机裁剪augments = A.RandomCrop(p=1, height=256, width=256)(image=img, mask=mask)img_aug, mask_aug = augments['image'], augments['mask']show_img_mask(img_aug, mask_aug)
# 旋转augments = A.ShiftScaleRotate(p=1)(image=img, mask=mask)img_aug, mask_aug = augments['image'], augments['mask']show_img_mask(img_aug, mask_aug)
albumentations 还可以组合多个数据扩增操作得到更加复杂的数据扩增操作:
trfm = pose([A.Resize(256,256),A.HorizontalFlip(p=0.5),A.VerticalFlip(p=0.5),A.RandomRotate90(),])augments = trfm(image=img, mask=mask)img_aug, mask_aug = augments['image'], augments['mask']show_img_mask(img_aug, mask_aug)
5 PyTorch数据读取
由于本次赛题我们使用 Pytorch 框架讲解具体的解决方案,接下来将是解决赛题的第一步使用 Pytorch 读取赛题数据。在 Pytorch 中数据是通过 Dataset 进行封装,并通过 DataLoder 进行并行读取。所以我们只需要重载一下数据读取的逻辑就可以完成数据的读取。
Dataset:数据集,对数据进行读取并进行数据扩增;DataLoder:数据读取器,对 Dataset 进行封装并进行批量读取;
import torch.utils.data as Dimport torchvision.transforms as TIMAGE_SIZE = 512class TianChiDataset(D.Dataset):def __init__(self, paths, rles, transform, test_mode=False):self.paths = pathsself.rles = rlesself.transform = transformself.len = len(paths)self.test_mode = test_modeself.as_tensor = pose([T.ToPILImage(),T.Resize(IMAGE_SIZE),T.ToTensor(),T.Normalize([0.625,0.448,0.688], [0.131,0.177,0.101]),])# get data operationdef __getitem__(self, index):img = cv2.imread(self.paths[index])if not self.test_mode:mask = rle_decode(self.rles[index])augments = self.transform(image=img, mask=mask)return self.as_tensor(augments['image']), augments['mask'][None]else:return self.as_tensor(img), ''def __len__(self):'''Total number of samples in the dataset'''return self.len
trfm = pose([A.Resize(IMAGE_SIZE, IMAGE_SIZE),A.HorizontalFlip(p=0.5),A.VerticalFlip(p=0.5),A.RandomRotate90(),])dataset = TianChiDataset(train_mask['name'].values,train_mask['mask'].fillna('').values,trfm, False)
loader = D.DataLoader(dataset, batch_size=10, shuffle=True, num_workers=0)for batch_id, data in enumerate(loader):image, target = dataprint(image.shape)print(target.shape)break
torch.Size([10, 3, 512, 512])
torch.Size([10, 1, 512, 512])
6 小结
本章对数据扩增方法进行简单介绍,并介绍并完成 OpenCV 数据扩增、 albumentations 数据扩增和Pytorch 读取赛题数据的具体操作。
如果觉得《【天池赛事】零基础入门语义分割-地表建筑物识别 Task2:数据扩增方法》对你有帮助,请点赞、收藏,并留下你的观点哦!