深度之眼Pytorch打卡(十一):Pytorch数据预处理——数据增强(下)

前言


  这篇笔记继续上一篇笔记的内容,接着深入的学习了解Pytorch的各种数据增强方法,由于内容很多,所以分为了上下两篇。上篇笔记学习了裁剪,这篇笔记主学习旋转翻转、拓展、颜色增强和仿射变换等的数据增强方法。本笔记的知识框架主要来源于深度之眼,并依次作了内容的丰富拓展,拓展内容主要源自对torch文档的翻译理解,所用数据来源于网络。

  代码结构与其他数据处理方法见:

  深度之眼Pytorch打卡(九):Pytorch数据预处理——预处理过程与数据标准化(transforms过程、Normalize原理、常用数据集均值标准差与数据集均值标准差计算) 深度之眼Pytorch打卡(十):Pytorch数据预处理——数据统一与数据增强(上)

  几篇数据增强笔记所涉代码见:Poetair/Pytorch-Learning/transforms


数据增强——翻转(Flip)


torchvision.transforms.RandomVerticalFlip(p=0.5)
    transforms.RandomVerticalFlip(0.5),
    transforms.ToTensor(),

  依概率竖直翻转,只有一个参数p,一般设为0.5,表示获取到的图片有一半的概率是竖直翻转过的,而有一半的概率是原样,任取10张图的效果如图1所示。

在这里插入图片描述

图1.依概率竖直翻转
torchvision.transforms.RandomHorizontalFlip(p=0.5)
    transforms.RandomHorizontalFlip(0.5),
    transforms.ToTensor(),

  依概率水平翻转,只有一个参数p,一般设为0.5,表示获取到的图片有一半的概率是水平翻转过的,而有一半的概率是原样,任取10张图的效果如图2所示。
在这里插入图片描述

图2.依概率水平翻转

数据增强——旋转(Rotation)


torchvision.transforms.RandomRotation(degrees, resample=False, expand=False, center=None, fill=None)

  degrees: 随机旋转角度的上下限,若为一数a,则限为(-a,a),若为一个序列(a,b)则限为(a,b)。每次取出的图像,都是在限内随机旋转一个角度值而得到处理后的图像。
  resample: 重采样,其实就是插值方法,决定旋转前后像素的映射方式。有如下方法:resample=False或1=PIL.Image.NEARESTresample=2=PIL.Image.BILINEARresample=3=PIL.Image.BICUBIC
  expand: 是否拓展,旋转后图片边角会出界,如果不想边角信息丢失,设置expand=True,表示拓展图像以保留边角。不同的旋转角度,保留边角后形成的图像尺寸不一致,故如果设置expand=True,必须后面再跟一个Resize。以绕图像中心旋转的情况来计算的,所以绕其他点时,就算拓展了也会存在信息丢失。
  center: 旋转中心,默认是图像中心。用元组(x,y)表示旋转中心位置,如(0,0)就表示左上角,(width,0)表示右上角。
  fill: 拓展时填充的值,默认0,即填充黑色。为一个值时就是灰度值,为一个元组(R,G,B)是表示颜色。

transforms.RandomRotation(90, resample=2),
transforms.ToTensor()

在这里插入图片描述

图3.无拓展的旋转,有丢失
transforms.RandomRotation(90, resample=2, expand=True, fill=(0, 0, 255)),
transforms.ToTensor()

在这里插入图片描述

图4.有拓展的旋转,填充蓝色,尺寸不一致
    transforms.RandomRotation(90, resample=2, center=(224, 0)),
    transforms.ToTensor(),

在这里插入图片描述

扫描二维码关注公众号,回复: 12025489 查看本文章
图5.右上角为中心旋转、信息可能丢失很多,拓展了也会丢失

数据增强——拓展(Pad)


torchvision.transforms.Pad(padding, fill=0, padding_mode='constant')

  padding: 拓展边缘的宽度,为常数a时,表示四条边均拓展宽度a。为元组(a,b)时,表示左右拓展a,上下拓展b,为元组(a,b,c,d)时,表示左,上,右,下,分别拓展abcd
  fill:padding_mode='constant'时,填充边缘的颜色值。若为一个值,则表示灰度(发现也有颜色,应该不是灰度,有点像是通道R),如默认0,填充黑色。若为一个元组(R,G,B)时,表示填充某种RGB颜色。
  padding_mode: 填充模式。填充常数,padding_mode='constant'。以在原图中与该拓展点关于原图边缘对称位置的像素值填充,即镜像,padding_mode='reflect'padding_mode='symmetric'。以原图最边缘的点的值进行填充,padding_mode='edge'

    transforms.Pad((30, 200, 100, 20), fill=200),
    transforms.ToTensor(),

在这里插入图片描述

图6.四周填充不同宽度,恒定值,也有颜色,可能单值时代表R
    transforms.Pad((30, 200, 100, 20), fill=200, padding_mode='edge'),
    transforms.ToTensor(),

在这里插入图片描述

图6.用最边缘像素填充,可以看到有由此产生的条纹

数据增强——变色(ColorJitter)


  很常用的一种数据增强方式,平时由于采集设备、光线等原因,采到的图像的亮度brightness、饱和度saturation、对比度contrast甚至是色相hue都会发生变化。用进行过色彩增强的数据训练出的模型,能更好的克服这些因素变化带来的干扰。

torchvision.transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0)

  该函数源码中,对输入的单个数进行了如下处理。对于亮度、饱和度和对比度而言,center=1clip_first_on_zero=True。对于色相而言,center=0clip_first_on_zero=False。由此便可以确定输入是单个数时的取值范围。

if isinstance(value, numbers.Number):    # 如果输入是个数
	value = [center - value, center + value]
	    if clip_first_on_zero:
	        value[0] = max(value[0], 0)

  再深入探究源码的操作过程,可以发现输出是由两个部分构成的。如下,alpha是在取值范围内随机产生的数,image2是原图片,image1是在特定类中为达到增强目的而新产生的一幅图像。

out = image1 * (1.0 - alpha) + image2 * alpha

  brightness类中产生的image1,是一张全黑图像,叠加之后,输出相当于是输入亮度的alpha倍。

Image.new(image.mode, image.size, 0)

  Contrast类中取原图的平均值,以此形成的image1。易得,若alpha>1,则1-alpha<0,此时就相当于减去均值,为锐化操作,提升对比度,反之则减小对比度。

Image.new("L", image.size, mean).convert(image.mode)

  saturationimage1是在Color类中产生的。由一幅灰度图像转成的RGB图像,所以三个通道都是一样的值,即白色。若alpha<1,则1-alpha>0,此时就相当于加上白光,主色调被稀释,饱和度降低。

image.convert(self.intermediate_mode).convert(image.mode)

  色调hue,需要将图像转换到HSI空间后单独调整H才可以实现。下面代码中,hue_factor=alpha是那个区间内的随机数,h = h+255*alpha

np_h += np.uint8(hue_factor * 255)

  通过以上分析,可以更好地理解以下参数。
  brightness: 亮度,决定明暗,为非负值,即bound=(0, float('inf')。为正常数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

    transforms.ColorJitter(brightness=(1,2)),  # (1,2),区间内随机选一个数来作为倍数
    transforms.ToTensor(),

在这里插入图片描述

图7.改变亮度

  1-alpha<0效果相当于锐化,增加对比度。

    transforms.ColorJitter(contrast=(1, 2)),
    transforms.ToTensor(),

在这里插入图片描述

图8.增加对比度
    transforms.ColorJitter(contrast=(0, 1)),
    transforms.ToTensor(),

  1-alpha>0效果相当于平滑,降低对比度。
在这里插入图片描述

图9.减小对比度

  1-alpha>0加白光,主色调被稀释,饱和度降低。

    transforms.ColorJitter(saturation=(0, 1)),
    transforms.ToTensor(),

在这里插入图片描述

图10.降低饱和度
    transforms.ColorJitter(hue=0.5),
    transforms.ToTensor(),

在这里插入图片描述

图11.改变色调

数据增强——转灰度图(Grayscale)


torchvision.transforms.RandomGrayscale(p=0.1)

  对于输入图片,被转换成灰度图像的概率是p。当输入是一个通道时,输出自动也是一个通道,当输入是三个通道时,输出也是三个通道,且R=G=B

    transforms.RandomGrayscale(0.5),
    transforms.ToTensor(),

在这里插入图片描述

图12.以概率为0.5转换灰度图
transforms.Grayscale(num_output_channels=1)

  该函数可以看做是RandomGrayscale()的特例。输出通道数需要手动设置。当num_output_channels=1输出是单通道。当num_output_channels=3时,输出是三通道,且R=G=B


数据增强——仿射变换(Affine)


torchvision.transforms.RandomAffine(degrees, translate=None, scale=None, shear=None, resample=False, fillcolor=0)

  随机进行仿射变换。仿射变换包括平移,旋转,缩放,翻转和错切,一般通过乘一个变换矩阵来实现,是一种二维线性变换。
  degrees: 设置旋转角度。为元组或者数值。为数字a时也表示旋转(-a,a)间任意角度。
  translate: 设置平移区间,为一个二元组(a,b)a表示,在宽维度(一般是左右)方向移动的距离是在区间-width * a < dx < width * ab表示,在高维度(一般是上下)方向移动的距离是在区间-hight * b < dy < hight * b。移动的是高度或者宽度的若干倍。
  scale: 缩放比例,该值是与原图的面积比。为二元组,设置上下限。
  resample: 重采样,即插值,详见上述旋转方法
  fillcolor: 产生空白时的填充颜色,同上述旋转方法中的fill
  shear: 错切角度设置。为单个数字或者元组。所谓错切,笔者理解的就是向x或者y方向倾斜原图成平行四边形(即为错),然后切出中间的部分(即为切),倾斜角度与往那边倾斜由shear定。为单值a时,表示在x方向错切,且往x方向倾斜角度在区间(-a,a)间随机取值。为二元组(a,b)时,表示往x方向倾斜角度在区间(-a,a)间随机取值,往y方向倾斜角度在区间(-b,b)间随机取值。为四元组(a,b,c,d)时,表示往x方向倾斜角度在区间(a,b)间随机取值,往y方向倾斜角度在区间(c,d)间随机取值。

  transforms.RandomAffine(degrees=60),
  transforms.ToTensor(),

在这里插入图片描述

图13.只旋转变换,绕图像中心旋转,角度是(-60,60)间随机取的值
    transforms.RandomAffine(degrees=0, translate=(0.2, 0.5)),
    transforms.ToTensor(),

在这里插入图片描述

图14.只平移变换,左右平移值是(-0.2*w,0.2*w)间随机取的值。
上下平移值是(-0.5*h,0.5*h)间随机取的值
    transforms.RandomAffine(degrees=0, scale=(0.5, 1.5), fillcolor=(255, 0, 255)),
    transforms.ToTensor(),

在这里插入图片描述

图15.只尺度变换,面积比值在区间(0.5,1.5)之间随机取值,自动resize。
    transforms.RandomAffine(degrees=0, shear=40, fillcolor=(0, 255, 255)),
    transforms.ToTensor(),

在这里插入图片描述

图16.只错切变换,在x方向错切。

数据增强——擦除(Erasing)


torchvision.transforms.RandomErasing(p=0.5, scale=(0.02, 0.33), ratio=(0.3, 3.3), value=0, inplace=False)

  随机遮挡。实际应用中,取得的图片,目标可能被部分遮挡。这样会降低模型判断的准确率。如果在模型训练时,就用随机遮挡来增强训练集,那么最后训练出来的模型对于部分遮挡的目标就会比较鲁棒。p是执行遮挡操作的概率。

  scale: 遮挡区域面积与原图面积的比值,区间内随机选取。根据目标的大小,设置合适的值区间,不要太大了避免将目标盖住。为二元组,表上下限。
  ratio: 遮挡区域的长宽比,在区间内随机选取。为二元组,表上下限。
  value: 遮挡区域的像素值。大致同上述旋转方法中的fill。不过当值为某字符串时,是填随机值。

  注:该方法输入是Tessor,故在此之前需要进行ToTensor操作,否则会报错。

    transforms.ToTensor(),
    transforms.RandomErasing(value=(100, 130, 110)),

在这里插入图片描述

图17.默认参数进行遮挡,对于了口罩而言有些遮挡显然太大了。
    transforms.ToTensor(),
    transforms.RandomErasing(scale=(0.1, 0.15), value='xyz', ratio=(1, 1)),

在这里插入图片描述

图17.随机色彩,面积比和长宽比进行遮挡。

参考


  https://pytorch.org/docs/stable/torchvision/transforms.html
  https://ai.deepshare.net/detail/p_5df0ad9a09d37_qYqVmt85/6

猜你喜欢

转载自blog.csdn.net/sinat_35907936/article/details/107539370