Datawhale Zero Foundation Entry CV Competition-Task02 Lectura y amplificación de datos

El contenido principal de esta parte se compone de tres partes: lectura de datos, método de amplificación de datos y datos del concurso de lectura de Pytorch.

2.1 Lectura de imágenes

Dado que los datos de la pregunta son datos de imagen, la tarea de la pregunta es reconocer los personajes de la imagen. Por lo tanto, primero debemos completar la operación de lectura de datos. Hay muchas bibliotecas en Python que pueden completar la operación de lectura de datos. Las más comunes son Pillow y OpenCV.

2.1.1 Almohada

Pillow es una rama de la biblioteca de procesamiento de imágenes de Python (PIL). Pillow proporciona operaciones comunes de lectura y procesamiento de imágenes y se puede integrar sin problemas con el portátil ipython.Es una biblioteca ampliamente utilizada.

efecto Código
Inserte la descripción de la imagen aquí # Importar biblioteca de almohadas
desde PIL importar imagen
importar matplotlib.pyplot como plt
# Leer la imagen y mostrar la imagen
img = Image.open ('image / bird.jpg')
plt.imshow (img)
Inserte la descripción de la imagen aquí
de PIL importar Imagen, ImageFilter
importar matplotlib.pyplot como plt
img = Image.open ('image / bird.jpg')
# 应用 模糊 滤镜:
img = img.filter (ImageFilter.BLUR)
plt.imshow (img)
img. guardar ('desenfoque.jpg', 'jpeg')
Inserte la descripción de la imagen aquí de PIL import Image, ImageFilter
import matplotlib.pyplot as plt
img = Image.open ('image / bird.jpg')
w, h = img.size [: 2]
# El método resize () puede acercar o alejar, mientras que la miniatura El método () solo puede encoger
img.thumbnail ((w // 8, h // 8))
plt.imshow (img)

Por supuesto, lo anterior solo demuestra las operaciones más básicas de Pillow. Pillow también tiene muchas operaciones de imagen, que es una biblioteca necesaria para el procesamiento de imágenes.
Documentación oficial de Pillow: https://pillow.readthedocs.io/en/stable/

2.1.2 OpenCV

OpenCV es una biblioteca de visión por computadora multiplataforma, originalmente de código abierto de Intel. OpenCV se desarrolló muy temprano y tiene muchas funciones, como visión artificial, procesamiento de imágenes digitales y visión artificial. OpenCV es mucho más poderoso que Pillow en función, y el costo de aprendizaje es mucho mayor.

efecto Código
Inserte la descripción de la imagen aquí # Importar biblioteca
Opencv importar cv2
importar matplotlib.pyplot como plt
img = cv2.imread ('image / bird.jpg')
# El orden de canal de color predeterminado de Opencv es BRG, convertir
img = cv2.cvtColor (img, cv2.COLOR_BGR2RGB)
plt .imshow (img)
Inserte la descripción de la imagen aquí importar cv2
importar matplotlib.pyplot como plt
img = cv2.imread ('image / bird.jpg')
# Convertir a escala de grises
img = cv2.cvtColor (img, cv2.COLOR_BGR2GRAY)
plt.imshow (img, "gris")
Inserte la descripción de la imagen aquí importar cv2
importar matplotlib.pyplot como plt
img = cv2.imread ('image / bird.jpg')
img = cv2.cvtColor (img, cv2.COLOR_BGR2GRAY)
# Canny 边缘 检测
bordes = cv2.Canny (img, 20, 70)
plt.imshow (bordes, "gris")
cv2.imwrite ('canny.jpg', bordes)

OpenCV contiene una gran cantidad de funciones de procesamiento de imágenes, OpenCV contiene siempre que puedas imaginar operaciones relacionadas con imágenes. Además, OpenCV también tiene muchos algoritmos de procesamiento de funciones de imagen incorporados, como detección de puntos clave, detección de bordes y detección de líneas.
Sitio web oficial de OpenCV: https://opencv.org/
OpenCV Github: https://github.com/opencv/opencv
Biblioteca de algoritmos extendidos de OpenCV: https://github.com/opencv/opencv_contrib

2.2 Método de amplificación de datos

上面初步介绍了Pillow和OpenCV的使用,现在回到赛题街道字符识别任务中。在赛题中我们需要对的图像进行字符识别,因此需要我们完成的数据的读取操作,同时也需要完成数据扩增(Data Augmentation)操作。

2.2.1 数据扩增介绍

在深度学习中数据扩增方法非常重要,数据扩增可以增加训练集的样本,同时也可以有效缓解模型过拟合的情况,也可以给模型带来的更强的泛化能力。
Inserte la descripción de la imagen aquí

  • 数据扩增为什么有用?

在深度学习模型的训练过程中,数据扩增是必不可少的环节。现有深度学习的参数非常多,一般的模型可训练的参数量基本上都是万到百万级别,而训练集样本的数量很难有这么多。
其次数据扩增可以扩展样本空间,假设现在的分类模型需要对汽车进行分类,左边的是汽车A,右边为汽车B。如果不使用任何数据扩增方法,深度学习模型会从汽车车头的角度来进行判别,而不是汽车具体的区别。
Inserte la descripción de la imagen aquí

  • 有哪些数据扩增方法?

数据扩增方法有很多:从颜色空间、尺度空间到样本空间,同时根据不同任务数据扩增都有相应的区别。
对于图像分类,数据扩增一般不会改变标签;对于物体检测,数据扩增会改变物体坐标位置;对于图像分割,数据扩增会改变像素标签。

2.2.2 Pytorch中的数据扩增方法

在常见的数据扩增方法中,一般会从图像颜色、尺寸、形态、空间和像素等角度进行变换。当然不同的数据扩增方法可以自由进行组合,得到更加丰富的数据扩增方法。

torchvision.transforms为例,首先整体了解数据扩增的方法,包括:
1、裁剪

中心裁剪:transforms.CenterCrop
随机裁剪:transforms.RandomCrop
随机长宽比裁剪:transforms.RandomResizedCrop
上下左右中心裁剪:transforms.FiveCrop
上下左右中心裁剪后翻转: transforms.TenCrop

2、翻转和旋转

依概率p水平翻转:transforms.RandomHorizontalFlip(p=0.5)
依概率p垂直翻转:transforms.RandomVerticalFlip(p=0.5)
随机旋转:transforms.RandomRotation

3、随机遮挡

对图像进行随机遮挡: transforms.RandomErasing

4、图像变换

尺寸变换:transforms.Resize
标准化:transforms.Normalize
填充:transforms.Pad
修改亮度、对比度和饱和度:transforms.ColorJitter
转灰度图:transforms.Grayscale
依概率p转为灰度图:transforms.RandomGrayscale
线性变换:transforms.LinearTransformation()
仿射变换:transforms.RandomAffine
将数据转换为PILImage:transforms.ToPILImage
转为tensor,并归一化至[0-1]:transforms.ToTensor
用户自定义方法:transforms.Lambda

5、对transforms操作,使数据增强更灵活

transforms.RandomChoice(transforms): 从给定的一系列transforms中选一个进行操作
transforms.RandomApply(transforms, p=0.5): 给一个transform加上概率,依概率进行操作
transforms.RandomOrder: 将transforms中的操作随机打乱

下面详细介绍各种数据增强方法的使用:

2.2.2.1 裁剪

1.中心裁剪

transforms.CenterCrop(size)
功能:依据给定的size从中心裁剪
参数:
[size]- (sequence or int),若为sequence,则为(h,w),若为int,则(size,size)

2.随机裁剪

transforms.RandomCrop(size, padding=None, pad_if_needed=False, fill=0, padding_mode=‘constant’)
功能:依据给定的size随机裁剪
参数:
[size]- (sequence or int),若为sequence,则为(h,w),若为int,则(size,size)
[padding]-(sequence or int, optional),此参数是设置填充多少个pixel。
当为int时,图像上下左右均填充int个,例如padding=4,则上下左右均填充4个pixel,若为3232,则会变成4040。
当为sequence时,若有2个数,则第一个数表示左右扩充多少,第二个数表示上下的。当有4个数时,则为左,上,右,下。
[pad_if_need]:若图像小于设定size,则填充 [
[fill]- (int or tuple) 填充的值是什么(仅当填充模式为constant时有用)。int时,各通道均填充该值,当长度为3的tuple时,表示RGB通道需要填充的值。
[padding_mode]- 填充模式,这里提供了4种填充模式:
1.constant,常量
2.edge 按照图片边缘的像素值来填充
3.reflect,镜像填充,最后一个像素不镜像, eg: [1,2,3,4] → [3,2,1,2,3,4,3 ,2]
4. symmetric,镜像填充,最后一个像素镜像, eg: [1 ,2,3 ,4] → [2,1,1,2,3,4,4,3]

3.随机长宽比裁剪

transforms.RandomResizedCrop(size, scale=(0.08, 1.0), ratio=(0.75, 1.3333333333333333), interpolation=2)
功能:随机大小,随机长宽比裁剪原始图片,最后将图片resize到设定好的size
参数:
[size]- 输出的分辨率
[scale]- 随机crop的大小区间,如scale=(0.08, 1.0),表示随机crop出来的图片会在的0.08倍至1倍之间。
[ratio]- 随机长宽比设置
[interpolation]- 插值的方法,默认为双线性插值(PIL.Image.BILINEAR)

4.上下左右中心裁剪

transforms.FiveCrop(size)
功能:对图片进行上下左右以及中心裁剪,获得5张图片,返回一个4D-tensor
参数:
[size]- (sequence or int),若为sequence,则为(h,w),若为int,则(size,size)

5.上下左右中心裁剪后翻转

transforms.TenCrop(size, vertical_flip=False)
功能:对图片进行上下左右以及中心裁剪,然后全部翻转(水平或者垂直),获得10张图片,返回一个4D-tensor。
参数:
[size]- (sequence or int),若为sequence,则为(h,w),若为int,则(size,size)
vertical_flip (bool) - 是否垂直翻转,默认为flase,即默认为水平翻转

2.2.2.2 翻转和旋转

6.依概率p水平翻转

transforms.RandomHorizontalFlip(p=0.5)
功能:依据概率p对PIL图片进行水平翻转
参数:
[p]- 概率,默认值为0.5

7.依概率p垂直翻转

transforms.RandomVerticalFlip(p=0.5)
功能:依据概率p对PIL图片进行垂直翻转
参数:
[p]- 概率,默认值为0.5

8.随机旋转

transforms.RandomRotation(degrees, resample=False, expand=False, center=None)
功能:依degrees随机旋转一定角度
参数:
[degress]- (sequence or float or int) ,若为单个数,如 30,则表示在(-30,+30)之间随机旋转;若为sequence,如(30,60),则表示在30-60度之间随机旋转
[resample]- 重采样方法选择,可选 PIL.Image.NEAREST, PIL.Image.BILINEAR, PIL.Image.BICUBIC,默认为最近邻
[expand]- 是否扩大图片,以保持原图信息
[center]- 可选为中心旋转还是左上角旋转

2.2.2.3 随机遮挡

9.随机遮挡

transforms.RandomErasing (p=0.5,scale=(0.02,0.33),ratio=(0.3,3.3),value=0,inplace=False)
参数:
[p] - 概率值,执行该操作的概率
[sacle] - 遮挡区域的面积
[ratio] - 遮挡区域的长宽比
[value] - 设置遮挡区域的像素值,(R、G、B)or (Gray)

2.2.2.4 图像变换

10.尺寸变换

transforms.Resize(size, interpolation=2)
功能:重置图像分辨率
参数:
[size]- If size is an int, if height > width, then image will be rescaled to (size * height / width, size),所以建议size设定为h*w
interpolation- 插值方法选择,默认为PIL.Image.BILINEAR。一共有四种插值方法,分别为Image.BICUBIC,PIL.Image.LANCZOS,PIL.Image.BILINEAR,PIL.Image.NEAREST。

11.标准化

transforms.Normalize(mean, std)
功能:对数据按通道进行标准化,即先减均值,再除以标准差,注意是 hwc

12.填充

transforms.Pad(padding, fill=0, padding_mode=‘constant’)
功能:对图像进行填充
参数:
[padding]-(sequence or int, optional),此参数是设置填充多少个pixel。
当为int时,图像上下左右均填充int个,例如padding=4,则上下左右均填充4个pixel,若为3232,则会变成4040。
当为sequence时,若有2个数,则第一个数表示左右扩充多少,第二个数表示上下的。当有4个数时,则为左,上,右,下。
[fill]- (int or tuple) 填充的值是什么(仅当填充模式为constant时有用)。int时,各通道均填充该值,当长度为3的tuple时,表示RGB通道需要填充的值。
[padding_mode]- 填充模式,这里提供了4种填充模式:
1.constant,常量
2.edge,按照图片边缘的像素值来填充
3.reflect,镜像填充,最后一个像素不镜像
4. symmetric,镜像填充,最后一个像素镜像

13.修改亮度、对比度和饱和度

transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0)
功能:修改修改亮度、对比度、饱和度、色相。
[brightness] - 亮度调整因子
当为a时,从[max(0, 1-a), 1+a]中随机选择,当为(a, b)时,从[a, b]中选择
[contrast] - 对比度参数,同brightness
[saturation] - 饱和度参数,同brightness
[hue] - 色相参数,当为a时,从[-a, a]中选择参数,注: 0<= a <= 0.5;当为(a, b)时,从[a, b]中选择参数,注: -0.5 <= a <= b <= 0.5

14.转灰度图

transforms.Grayscale(num_output_channels=1)
功能:将图片转换为灰度图
参数:
[num_output_channels] - (int) ,当为1时,正常的灰度图,当为3时, 3 channel with r == g == b

15.依概率p转为灰度图

transforms.RandomGrayscale(p=0.1)
功能:依概率p将图片转换为灰度图,若通道数为3,则3 channel with r == g == b

16.线性变换

transforms.LinearTransformation(transformation_matrix)
功能:对矩阵做线性变化,可用于白化处理!
参数:
[transformation_matrix] (Tensor) – tensor [D x D], D = C x H x W

17.仿射变换

transforms.RandomAffine(degrees, translate=None, scale=None, shear=None, resample=False, fillcolor=0)
功能:对图像进行仿射变换,仿射变换是二维的线性变换,由5种基本原子变换构成,分别是旋转、平移、缩放、错切和翻转。
参数:
[degrees] - 旋转角度设置
[translate] - 平移区间设置,如(a,b),a设置宽,b设置高,图像在宽维度平移的区间为 -img_widtha < dx < img_widtha
[scale] - 缩放比例,以面积为单位
[shear] - 错切角度设置,有水平错切和垂直错切
[resample] - 重采样方式
[fill_color] - 填充颜色设置

18.转为tensor

transforms.ToTensor()
功能:将PIL Image或者 ndarray 转换为tensor,并且归一化至[0-1]
注意事项:归一化至[0-1]是直接除以255,若自己的ndarray数据尺度有变化,则需要自行修改。

19.将数据转换为

transforms.ToPILImage(mode=None)
功能:将tensor 或者 ndarray的数据转换为 PIL Image 类型数据
参数:
[mode] - 为None时,为1通道, mode=3通道默认转换为RGB,4通道默认转换为RGBA

20.用户自定义方法

transforms.Lambda(lambd)
功能:用户自定义lambda方法
参数:
[lambd] - lambda匿名函数

2.2.2.5 对transforms操作,使数据增强更灵活

PyTorch不仅可设置对图片的操作,还可以对这些操作进行随机选择、组合。
21.transforms.RandomChoice(transforms)

功能:从给定的一系列transforms中选一个进行操作
例:transforms.RandomChoice([transforms1, transforms2, transforms3])

22.transforms.RandomApply(transforms, p=0.5)

功能:给一个transform加上概率,以一定的概率执行该操作
例:transforms.RandomApply([transforms1, transforms2, transforms3], p=0.5)

23.transforms.RandomOrder

功能:将transforms中的操作顺序随机打乱
例:transforms.RandomOrder([transforms1, transforms2, transforms3])

Inserte la descripción de la imagen aquí
在本次赛题中,赛题任务是需要对图像中的字符进行识别,因此对于字符图片并不能进行翻转操作。比如字符6经过水平翻转就变成了字符9,会改变字符原本的含义。

2.2.3 常用的数据扩增库

  • torchvision

https://github.com/pytorch/vision
pytorch官方提供的数据扩增库,提供了基本的数据扩增方法,可以无缝与torch进行集成;但数据扩增方法种类较少,且速度中等;

  • imgaug

https://github.com/aleju/imgaug
imgaug是常用的第三方数据扩增库,提供了多样的数据扩增方法,且组合起来非常方便,速度较快;

  • albumentations

https://albumentations.readthedocs.io
是常用的第三方数据扩增库,提供了多样的数据扩增方法,对图像分类、语义分割、物体检测和关键点检测都支持,速度较快。

2.3 Pytorch读取数据

由于本次赛题我们使用Pytorch框架讲解具体的解决方案,接下来将是解决赛题的第一步使用Pytorch读取赛题数据。
在Pytorch中数据是通过Dataset进行封装,并通过DataLoder进行并行读取。所以我们只需要重载一下数据读取的逻辑就可以完成数据的读取。

import os, sys, glob, shutil, json
import cv2
from PIL import Image
import numpy as np
import torch
from torch.utils.data.dataset import Dataset
import torchvision.transforms as transforms

class SVHNDataset(Dataset):

    def __init__(self, img_path, img_label, transform=None):
        self.img_path = img_path
        self.img_label = img_label 
        if transform is not None:
            self.transform = transform
        else:
            self.transform = None
            
    def __getitem__(self, index):
        img = Image.open(self.img_path[index]).convert('RGB')
        if self.transform is not None:
            img = self.transform(img)        
        # 原始SVHN中类别10为数字0
        lbl = np.array(self.img_label[index], dtype=np.int)
        lbl = list(lbl)  + (5 - len(lbl)) * [10]        
        return img, torch.from_numpy(np.array(lbl[:5]))
        
    def __len__(self):
        return len(self.img_path)
        
train_path = glob.glob('input/train/*.png')
train_path.sort()
train_json = json.load(open('input/train.json'))
train_label = [train_json[x]['label'] for x in train_json]

data = SVHNDataset(train_path, train_label,
          transforms.Compose([
              # 缩放到固定尺寸
              transforms.Resize((64, 128)),
              # 随机颜色变换
              transforms.ColorJitter(0.2, 0.2, 0.2),
              # 加入随机旋转
              transforms.RandomRotation(5),
              # 将图片转换为pytorch 的tesntor
              # transforms.ToTensor(),
              # 对图像像素进行归一化
              # transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])
            ]))

通过上述代码,可以将赛题的图像数据和对应标签进行读取,在读取过程中的进行数据扩增,效果如下所示:
Inserte la descripción de la imagen aquí
接下来我们将在定义好的Dataset基础上构建DataLoder,你可以会问有了Dataset为什么还要有DataLoder?其实这两个是两个不同的概念,是为了实现不同的功能。

  • Dataset:对数据集的封装,提供索引方式的对数据样本进行读取
  • DataLoder:对Dataset进行封装,提供批量读取的迭代读取

Después de unirse a DataLoder, el código de lectura de datos se cambia de la siguiente manera:

import os, sys, glob, shutil, json
import cv2
from PIL import Image
import numpy as np
import torch
from torch.utils.data.dataset import Dataset
import torchvision.transforms as transforms

class SVHNDataset(Dataset):

    def __init__(self, img_path, img_label, transform=None):
        self.img_path = img_path
        self.img_label = img_label 
        if transform is not None:
            self.transform = transform
        else:
            self.transform = None
            
    def __getitem__(self, index):
        img = Image.open(self.img_path[index]).convert('RGB')
        if self.transform is not None:
            img = self.transform(img)        
        # 原始SVHN中类别10为数字0
        lbl = np.array(self.img_label[index], dtype=np.int)
        lbl = list(lbl)  + (5 - len(lbl)) * [10]       
        return img, torch.from_numpy(np.array(lbl[:5]))
        
    def __len__(self):
        return len(self.img_path)
train_path = glob.glob('input/train/*.png')
train_path.sort()
train_json = json.load(open('input/train.json'))
train_label = [train_json[x]['label'] for x in train_json]
train_loader = torch.utils.data.DataLoader(
        SVHNDataset(train_path, train_label,
                   transforms.Compose([
                       transforms.Resize((64, 128)),
                       transforms.ColorJitter(0.3, 0.3, 0.2),
                       transforms.RandomRotation(5),
                       transforms.ToTensor(),
                       transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
            ])), 
    batch_size=10, # 每批样本个数
    shuffle=False, # 是否打乱顺序
    num_workers=10, # 读取的线程个数
)
for data in train_loader:
    break

Después de agregar DataLoder, los datos se obtienen en lotes y cada lote se denomina Conjunto de datos para leer una sola muestra para el empalme. El formato de los datos en este momento es:

torch.Size([10, 3, 64, 128]), torch.Size([10, 6])

El primero es un archivo de imagen en el orden de tamaño de lote * chanel * alto * ancho; el segundo es una etiqueta de carácter.

2.4 Resumen de este capítulo

Este capítulo ofrece una explicación detallada de la lectura de datos, presenta métodos y usos comunes de amplificación de datos y, finalmente, utiliza el marco Pytorch para leer los datos de esta competencia.

Supongo que te gusta

Origin blog.csdn.net/OuDiShenmiss/article/details/106296558
Recomendado
Clasificación