1. 数据增强
  2. transforms — 裁剪
  3. transforms — 翻转和旋转

一、数据增强

数据增强又称为数据增广,数据扩增,它是对训练集进行变换,增加训练集的数量,使训练集更丰富,从而让模型更具泛化能力。
image.png
左边是一张原始图片,我们对这张图片进行一系列的操作变换,得到右边的这64张增强样本供模型去训练。模型可以监控更多更丰富的样本,从而来提高模型的泛化能力。下面我们开始学习具体的方法。

二、transforms — 裁剪Crop

01. transforms.CenterCrop()

  1. transforms.CenterCrop(size)
  • 功能:从图像中心裁剪图片
  • size:所需裁剪图片尺寸

image.png

02. transforms.RandomCrop()

  1. transforms.RandomCrop(
  2. size,
  3. padding=None,
  4. pad_if_needed=False,
  5. fill=0,
  6. padding_mode='constant')
  • 功能:从图片中随机位置裁剪出尺寸为size的图片
  • size :所需裁剪图片尺寸
  • padding :设置填充大小
    • 当为a时,上下左右均填充a个像素
    • 当为(a, b)时,上下填充b个像素,左右填充a个像素
    • 当为(a, b, c, d)时,左,上,右,下分别填充a, b, c, d
  • pad_if_need :若图像小于设定size,则填充
  • padding_mode :填充模式,有4种模式
    • constant :像素值由 fill 设定
    • edge :像素值由图像边缘像素决定
    • reflect :镜像填充,最后一个像素不镜像,eg:[1,2,3,4] → [3, 2 | 1 | 2,3 | 4 | 3,2]
    • symmetric :镜像填充,最后一个像素镜像,eg:[1,2,3,4] → [2, 1 | 1,2,3,4 | 4,3]
  • fill :constant时,设置填充的像素值

    03. transforms.RandomResizedCrop()

    1. RandomResizedCrop(
    2. size,
    3. scale=(0.08, 1.0),
    4. ratio=(3/4, 4/3),
    5. interpolation)
  • 功能:随机大小、长宽比裁剪图片

  • size :所需裁剪图片尺寸
  • scale :随机裁剪面积比例,默认(0.08, 1)
  • ratio :随机长宽比,默认(3/4, 4/3)
  • interpolation :插值方法

    • PIL.Image.NEAREST
    • PIL.Image.BILINEAR
    • PIL.Image.BICUBIC

      04. transforms.FiveCrop()transforms.TenCrop()

      1. transforms.FiveCrop(size)
      2. transforms.TenCrop(size, vertical_flip=False)
  • 功能:在图像的上下左右以及中心裁剪出尺寸为size的5张图片,TenCrop对这5张图片进行水平或者垂直镜像获得10张图片

  • size :所需裁剪图片尺寸
  • vertical_flip :是否垂直翻转

    三、 transforms - 翻转、旋转Flip and Rotation

    01. transforms.RandomHorizontalFlip()transforms.RandomVerticalFlip()

    1. RandomHorizontalFlip(p=0.5)
    2. RandomVerticalFlip(p=0.5)
  • 功能:依概率水平(左右)或垂直(上下) 翻转图片

  • p :翻转概率

    02. transforms.RandomRotation()

    1. RandomRotation(degrees,
    2. resample=False,
    3. expand=False,
    4. center=None)
  • 功能:随机旋转图片

  • degrees :旋转角度
    • 当为a时,在数据增强的22种方式 - 图3之间选择旋转角度
    • 当为数据增强的22种方式 - 图4时,在数据增强的22种方式 - 图5之间选择旋转角度
  • resample :重采样方法
  • expand :是否扩大图片,以保持原图信息
  • center :输入值为坐标。旋转点设置,默认中心旋转

    四、transforms - 图像变换

    01. transforms.Pad()

    1. transforms.Pad(
    2. padding,
    3. fill=0,
    4. padding_mode='constant')
  • 功能:对图片边缘进行填充

  • padding :设置填充大小
    • 当为 a 时,上下左右均填充a个像素
    • 当为 (a, b) 时,上下填充b个像素,左右填充a个像素
    • 当为 (a, b, c, d) 时,左,上,右,下分别填充a, b, c, d
  • padding_mode :填充模式,有4种模式,
    • constant
    • edge
    • reflect
    • symmetric
  • fillconstant 时,设置填充的像素值,(R, G, B) or (Gray)

    02. transforms.ColorJitter()

    1. transforms.ColorJitter(
    2. brightness=0,
    3. contrast=0,
    4. saturation=0,
    5. hue=0)
  • 功能:调整亮度、对比度、饱和度和色相

  • brightness :亮度调整因子
    • 当为a时,从数据增强的22种方式 - 图6中随机选择
    • 当为 (a, b) 时,从数据增强的22种方式 - 图7中随机选择
  • contrast :对比度参数,同brightness
  • saturation :饱和度参数,同brightness
  • hue :色相参数

    • 当为 a 时,从数据增强的22种方式 - 图8中选择参数,注:数据增强的22种方式 - 图9
    • 当为 (a, b) 时,从数据增强的22种方式 - 图10 中选择参数,注:数据增强的22种方式 - 图11

      03. transforms.Grayscale()transforms.RandomGrayscale()

      1. RandomGrayscale(num_output_channels, p=0.1)
      2. Grayscale(num_output_channels)
  • 功能:依概率将图片转换为灰度图

  • num_ouput_channels :输出通道数。 注意:只能设 13
  • p :概率值,图像被转换为灰度图的概率

    04. transforms.RandomAffine()

    1. RandomAffine(
    2. degrees,
    3. translate=None,
    4. scale=None,
    5. shear=None,
    6. resample=False,
    7. fillcolor=0)
  • 功能:对图像进行仿射变换,仿射变换是二维的线性变换,由五种基本原子变换构成,分别是旋转、平移、缩放、错切和翻转

  • degrees :旋转角度设置
  • translate :平移区间设置,如(a, b), a设置宽(width),b设置高(height) 图像在宽维度平移的区间为数据增强的22种方式 - 图12
  • scale :缩放比例(以面积为单位)
  • fill_color :填充颜色设置
  • shear :错切角度设置,有水平错切和垂直错切
    • 若为 a,则仅在x轴错切,错切角度在(-a, a)之间
    • 若为(a,b),则a设置x轴角度,b设置y的角度
    • 若为(a, b, c, d),则a, b设置x轴角度,c, d设置y轴角度
  • resample :重采样方式,有NEAREST 、BILIN

    05. transforms.RandomErasing()

    1. RandomErasing(
    2. p=0.5,
    3. scale=(0.02, 0.33),
    4. ratio=(0.3, 3.3),
    5. value=0,
    6. inplace=False)
  • 功能:对图像进行随机遮挡

  • p :概率值,执行该操作的概率
  • scale :遮挡区域的面积
  • ratio :遮挡区域长宽比
  • value :设置遮挡区域的像素值,(R, G, B) or (Gray)

    参考文献:《Random Erasing Data Augmentation 》

06. transforms.Lambda()

  1. transforms.Lambda(lambda)
  • 功能:用户自定义lambda方法
  • lambda :lambda匿名函数
    1. # 模板
    2. lambda [arg1 [,arg2, , argn]] : expression
    3. # 例子
    4. transforms.TenCrop(200, vertical_flip=True),
    5. transforms.Lambda(lambda crops: torch.stack([transforms.Totensor()(crop) for crop in crops])),

    五、Transforms Operation

    01. transforms.RandomChoice()

    transforms.RandomChoice([transforms1, transforms2, transforms3])
    
    功能:从这一系列transforms方法中随机挑选一个进行图像变换

    02. transforms.RandomApply()

    transforms.RandomApply([transforms1, transforms2, transforms3], p=0.5)
    
    功能:执行该组transforms操作的概率为0.5

    03. transforms.RandomOrder()

    transforms.RandomOrder([transforms1, transforms2, transforms3])
    
    功能:对一组transforms操作打乱顺序

    六、自定义transforms

    我们想要自定义 transforms 方法,首先要熟悉 transforms 方法的运行机制。之前讲解的 DataLoaderDataSet 以及我们数据的读取机制的时候,就知道 transforms 方法是在 Compose 类中的 __call__函数 被调用的。我们对一组 transforms 方法进行 for循环 ,顺序执行 transforms方法
    class Compose(object):
      def __call__(self, img):
          for t in self.transforms:
          img = t(img)
          return img
    
    在第四行, t 就是 transforms方法 。对 transforms方法 只输入一个参数,返回一个参数:也就是 transforms方法 必须只能接受一个参数,返回一个参数,这是他的第一个限制。第二限制是我们看到他是一个 for循环 ,也就是我们当前 transforms方法input 是上一个 transforms方法output,也就是我们要注意上下要输入输出的一个匹配关系。

所以总结下来,我们自定义transforms方法 有两个注意的地方:第

  1. 一个是自定义transforms方法 只能接受一个参数,返回一个参数。
  2. 需要注意上下游的输入输出的一个对应关系。当前的 transforms方法 的输入是上一个 transforms方法 的输出,以及当前的transforms方法 的输出是下一个 transforms方法 的输入。所以我们这些输入输出之间的数据类型必须要匹配。

说道数据类型必须匹配,比如说我们都是PIL image的数据类型,或者是都是tensor数据类型,然后我们在设计transforms方法 时需要多个参数,比如说我们还要设置概率取值、信噪比。那这些参数该怎么实现?这时候就可以用到类方法:可以用到类来实现多参数传入。下面这个代码结构就是我们自定义transforms方法的一个基本的一个结构。

class YourTransforms(object):
    def __init__(self, ...):
        ...
    def __call__(self, img):
        ...
        return img

先是一个 __init__函数 ,初始化函数可以传入我们想要的参数。比如说信噪比、概率值等等。然后我们在这一个类当中,还必须要有一个 __call__函数 ,也就是这个类的实例可以被调用的。我们在这个__call__函数 当中,只能接受一个input,只有一个参数 img ,返回一个参数 img 。在__call__函数中实现我们具体想要的功能。这就是一个基本的自定义transforms方法 的结构。

下面我们通过定义添加椒盐噪声的 transforms方法 来学习如何自定义transforms方法 。椒盐噪声又称为脉冲噪声,它是一种随机出现了黑点或者白点,我们白点成为盐噪声,黑色成为椒噪声。椒盐噪声当中的一个重要的参数叫做信噪比。信噪比是用来衡量噪声的比例:图像中图像像素占整张图像的一个比例。

来看一个例子。这是对小猫图像进行增加不同信噪比的一个效果图。
image.png
下面我们就通过自定义 transforms方法 对图像进行增加椒盐噪声
自定义椒盐噪声 transforms方法 的基本结构


class AddPepperNoise(object):
    """增加椒盐噪声
    Args:
        snr (float): Signal Noise Rate
        p (float): 概率值,依概率执行该操作
    """

    def __init__(self, snr=0.9, p):
        assert isinstance(snr, float) or (isinstance(p, float))
        self.snr = snr  # 信噪比
        self.p = p  # 概率值:按照一定的概率值执行程序


    def __call__(self, img):
        """
        Args:
            img (PIL Image): PIL Image
        Returns:
            PIL Image: PIL image.
        """
        if random.uniform(0, 1) < self.p:
            img_ = np.array(img).copy()  # 将PIL图像转化为数组
            h, w, c = img_.shape  # 获取高、宽、channel
            signal_pct = self.snr  # 信号比例
            noise_pct = (1 - self.snr)  # 噪声比例
            mask = np.random.choice((0, 1, 2),  # 0原图1 盐噪声 2 椒噪声
                                    size=(h, w, 1),
                                    # 原图的比例     盐噪声的比例     椒噪声的比例
                                    p=[signal_pct, noise_pct/2., noise_pct/2.])
            mask = np.repeat(mask, c, axis=2)
            img_[mask == 1] = 255   # 盐噪声
            img_[mask == 2] = 0     # 椒噪声
            return Image.fromarray(img_.astype('uint8')).convert('RGB')  # 将数组转化为PIL形式
        else:
            return img

总结: transforms 方法

  • 裁剪
    • transforms.CenterCrop
    • transforms.RandomCrop
    • transforms.RandomResizedCrop
    • transforms.FiveCrop
      1. transforms.TenCrop
  • 二、翻转和旋转
    • transforms.RandomHorizontalFlip
    • transforms.RandomVerticalFlip
    • transforms.RandomRotation
  • 三、图像变换
    • transforms.Pad
    • transforms.ColorJitter
    • transforms.Grayscale
    • transforms.RandomGrayscale
    • transforms.RandomAffine
    • transforms.LinearTransformation
    • transforms.RandomErasing
    • transforms.Lambda
    • transforms.Resize
    • transforms.Totensor
    • transforms.Normalize
  • 四、transforms的操作
    • transforms.RandomChoice
    • transforms.RandomApply
    • transforms.RandomOrder

      数据增强原则:让训练集与测试集更接近