torchvision.transforms.ToTensor
将PIL.Image
或numpy.ndarray
类型的图片转为torch.Tensor
类型,如果图片的灰度级在[0, 255]
,会除以255.0
,归一化到[0.0, 1.0]
。这个基本上每个数据集都会用到。
不用给参数。
>>> from torchvision import transforms
>>> import numpy as np
>>> a = np.array([[255, 199, 30]], dtype=np.uint8)
>>> a
array([[255, 199, 30]], dtype=uint8)
>>> t = transforms.ToTensor()
>>> b = t(a)
>>> b
tensor([[[1.0000, 0.7804, 0.1176]]])
torchvision.transforms.Grayscale(num_output_channels=1)
将彩色图片转为灰度图片。图片必须是PIL.Image
或torch.Tensor
类型。
如果num_output_channels=1
,返回单通道灰度图片;如果num_output_channels=3
,返回三通道的灰度图片,其中r == g == b
。一般我们不用设置,默认为1
就行了。
from PIL import Image
from torchvision import transforms
img = Image.open('test.jpg')
transform = transforms.Grayscale()
img = transform(img)
torchvision.transforms.Normalize(mean, std, inplace=False)
用均值和标准差标准化数据,将数据映射到区间[-1, 1]
,能加快模型的收敛速度,一般加到ToTensor
后面。仅限torch.Tensor
类型。
mean (sequence)
:各通道的均值。
std (sequence)
:各通道的标准差。
inplace
:是否直接在原数据上操作。
torchvision.transforms.Compose(transforms)
将若干个转换方法组合起来。
transforms
:带组合的转换方法
# 以mnist数据集为例, 单通道, 其均值和标准差分别为0.1307和0.3081
train_file = datasets.MNIST(
root='./dataset/',
train=True,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
)
torchvision.transforms.CenterCrop(size)
对图片进行中心裁剪。中心就是图片高和宽二分之一的交点。图片必须是PIL.Image
或torch.Tensor
类型。
size
是输出图片的高、宽。你可以给一个整型的数字,比如3
,表示输出3x3
的图片;你也可以给一个元组,比如(3, 5)
,表示输出高为3
,宽为5
的图片。
from PIL import Image
from torchvision import transforms
img = Image.open('test.jpg')
# 300x300
transform_1 = transforms.CenterCrop(300)
img_1 = transform_1(img)
# 500x500
transform_2 = transforms.CenterCrop(500)
img_2 = transform_2(img)
# 500x300
transform_3 = transforms.CenterCrop((500,300))
img_3 = transform_3(img)
torchvision.transforms.Pad(padding, fill=0, padding_mode=‘constant’)
对图像边缘进行拓展填充。
padding
:拓展宽度。如果是整型,则所有边都拓展;如果是二元组,则指定左右和上下的拓展宽度。如果是四元组,则指定左、上、右、下的拓展宽度。
fill
:像素填充的值,默认是0
,代表黑色。可以指定整型,也可以用三元组表示分别填充RGB通道。
padding_mode
:拓展模式,默认为constant
,表示所有填的所有值都一样。edge
表示用边缘值填充;reflecty
以边缘为对称轴进行轴对称填充(边缘不重复),如在[1, 2, 3, 4]
的两边填充2个元素就是[3, 2, 1, 2, 3, 4, 3, 2]
;symmetricy
以边缘为对称轴进行轴对称填充(边缘重复),如在[1, 2, 3, 4]
的两边填充2个元素就是[2, 1, 1, 2, 3, 4, 4, 3]
。
from PIL import Image
from torchvision import transforms
img = Image.open('test.jpg')
transform = transforms.Pad(100, (255, 0, 0))
img = transform(img)
torchvision.transforms.RandomCrop(size, padding=None, pad_if_needed=False, fill=0, padding_mode=‘constant’)
在随机位置对图像进行裁剪
size
:输出图片的高、宽。与中心裁剪的参数定义一致。
padding
:拓展宽度。与边缘拓展的参数定义一致。
pad_if_needed
:如果设置为True
,当图像小于目标尺寸时会先填充再随机裁剪。
fill
:像素填充值。与边缘拓展的参数定义一致。
padding_mode
:拓展模式。与边缘拓展的参数定义一致。
from PIL import Image
from torchvision import transforms
img = Image.open('test.jpg')
transform = transforms.RandomCrop(300)
img_1 = transform(img)
img_2 = transform(img)
img_3 = transform(img)
torchvision.transforms.Resize(size, interpolation=2)
调整图像的大小到指定尺寸。图像必须是PIL.Image
或torch.Tensor
类型。这个也用的比较多,训练是按批的,必须保证每批图像的尺寸是相同,所以一般都会在训练前进行resize
操作。
size
: 可以输入一个元组,表示图像的高、宽。比如(300, 500)
,返回高为300
,宽为500
的图片;也可以只输入一个整型的数字,短边就是这个数字,然后长边按照相同的长宽比进行调整。比如一张高、宽分别为400
、200
的图片,指定size = 300
,那么返回的图像高、宽分别是600
、300
。计算过程:∵ with < height ∴ width = size = 300, height = size*height/width = 300*400*200 = 600
。
interpolation
:插值法,默认即可。
尺寸缩放的size
参数如果只给定一个整数值,返回的图像不一定是方形的。要注意和中心裁剪的size
参数区分开来。
from PIL import Image
from torchvision import transforms
img = Image.open('test.jpg')
transform = transforms.Resize((720, 720))
img = transform(img)
img.save('img.jpg')
torchvision.transforms.RandomRotation(degrees, resample=False, expand=False, center=None, fill=None)
按角度随机旋转图像。图像必须是PIL.Image
或torch.Tensor
类型。
degrees
: 旋转的角度范围。如果只填一个整型或浮点型的数字,比如90
,表示在-90°
和90°
之间随机旋转。也可以给一个序列类型的值,比如(45, 90)
,表示逆时针旋转,旋转角度从45°
到90°
之间随机取一个值。
resample
:重采样方法,默认即可。
expand
:是否扩展。默认为False
表示输出图和输入图大小一样,旋转超出区域就丢掉不要了;设置为True
表示扩展边界以保证显示整个原图。
center
:旋转中心的坐标,可接受的输入是元组或列表类型。默认是图片的中心,比如1280x720
的图片中心就是(640, 360)
。
fill
:图像外部区域的填充颜色。默认是0也就是黑色,也支持RGB
格式的颜色,比如(255, 0, 0)
就表示用红色填充。
官方只给了按角度随机旋转的方法,并没有给指定角度旋转的方法,但指定角度旋转也可以通过通过设置随机旋转的参数实现。比如图像顺时针旋转90°
,只需要设置degrees=(-90, -90)
。官方确实很聪明,只用一个函数就把随机旋转和定向旋转都实现了。
from PIL import Image
from torchvision import transforms
img = Image.open('test.jpg')
# 逆时针旋转45°
transform_1 = transforms.RandomRotation(degrees=(45, 45))
img_1 = transform_1(img)
# 逆时针旋转45°,启动拓展
transform_2 = transforms.RandomRotation(degrees=(45, 45), expand=True)
img_2 = transform_2(img)
# 逆时针旋转45°,绿色填充
transform_3 = transforms.RandomRotation(degrees=(45, 45), fill=(255, 0, 0))
img_3 = transform_3(img)
torchvision.transforms.RandomHorizontalFlip(p=0.5)
字面意思,就是水平翻转图像。不过是否翻转是随机的。
p
:水平翻转的概率,如果是1
就一定翻转,如果给0就一定不翻转,如果其它值则按概率随机选择是否翻转。比如0.5
,那么就有一半的可能翻转,一般的可能不翻转。图像必须是PIL.Image
或torch.Tensor
类型。
from PIL import Image
from torchvision import transforms
img = Image.open('test.jpg')
transform = transforms.RandomHorizontalFlip(p=1)
img = transform(img)
img.save('img.jpg')
torchvision.transforms.RandomVerticalFlip(p=0.5)
字面意思,就是垂直翻转图像。不过是否翻转是随机的。
p
:垂直翻转的概率,如果是1
就一定翻转,如果给0就一定不翻转,如果其它值则按概率随机选择是否翻转。比如0.5
,那么就有一半的可能翻转,一般的可能不翻转。图像必须是PIL.Image
或torch.Tensor
类型。
from PIL import Image
from torchvision import transforms
img = Image.open('test.jpg')
transform = transforms.RandomVerticalFlip(p=1)
img = transform(img)
img.save('img.jpg')
torchvision.transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0)
随机改变图片的亮度,对比度和饱和度。
brightness
:亮度;允许输入浮点型或二元组(min, max)
。如果是浮点型,那么亮度在[max(0, 1 ## brightness), 1 + brightness]
区间随机变换;如果是元组,亮度在给定的元组间随机变换。不允许输入负值。
contrast
:对比度。允许输入规则和亮度一致。
saturation
:饱和度。允许输入规则和亮度一致。
hue
:色调。允许输入浮点型或二元组(min, max)
。如果是浮点型,那么亮度在[-hue, hue]
区间随机变换;如果是元组,亮度在给定的元组间随机变换。不允许输入负值。必须满足0<= hue <= 0.5 or -0.5 <= min <= max <= 0.5
。
from PIL import Image
from torchvision import transforms
img = Image.open('test.jpg')
# 亮度设置为2
transform_1 = transforms.ColorJitter(brightness=(2, 2))
img_1 = transform_1(img)
# 对比度设置为2
transform_2 = transforms.ColorJitter(contrast=(2, 2))
img_2 = transform_2(img)
# 饱和度设置为2
transform_3 = transforms.ColorJitter(saturation=(2, 2))
img_3 = transform_3(img)
torchvision.transforms.GaussianBlur(kernel_size, sigma=(0.1, 2.0))
对图像应用高斯模糊
kernel_size
:模糊半径。必须是奇数。
sigma
:正态分布的标准差。如果是浮点型,则固定;如果是二元组(min, max)
,sigma
在区间中随机选取一个值。
from PIL import Image
from torchvision import transforms
img = Image.open('test.jpg')
# 模糊半径越大, 正态分布标准差越大, 图像就越模糊
transform_1 = transforms.GaussianBlur(21, 10)
img_1 = transform_1(img)
transform_2 = transforms.GaussianBlur(101, 10)
img_2 = transform_2(img)
transform_3 = transforms.GaussianBlur(101, 100)
img_3 = transform_3(img)
torchvision.transforms.RandomAffine(degrees, translate=None, scale=None, shear=None, resample=0, fillcolor=0)
汇总了旋转、平移、缩放、扭曲等图像变换方法,并且支持叠加。比如旋转的同时又进行平移或缩放等。
degrees
(sequence or float or int):随机旋转的角度范围。和随机旋转的参数定义一致。设置为0表示不旋转。
translate
(tuple, optional) :水平和垂直平移的因子。如(a, b)
,表示在-img_width * a < dx < img_width * a
范围内随机水平平移,在-img_height * b < dy < img_height * b
范围内随机垂直平移。
scale
(tuple, optional):缩放因子。如(a, b)
,表示在a <= scale <= b
随机缩放。
shear
(sequence or float or int, optional):随机扭曲的角度范围。如(45, 90)
,表示在45~90范围内随机选取一个角度进行与横轴平行的扭曲。
resample
(int, optional) :重采样。
fillcolor
(tuple or int) :填充色。默认为0
,也就是黑色。支持三元组的RGB
颜色。
from PIL import Image
from torchvision import transforms
img = Image.open('test.jpg')
# 随机旋转
transform_1 = transforms.RandomAffine(90)
img_1 = transform_1(img)
# 随机平移
transform_2 = transforms.RandomAffine(0, (0.1, 0))
img_2 = transform_2(img)
# 随机缩放
transform_3 = transforms.RandomAffine(0, None, (0.5, 2))
img_3 = transform_3(img)
# 随机扭曲
transform_4 = transforms.RandomAffine(0, None, None, (45, 90))
img_4 = transform_4(img)
名称 | 尺寸 |
---|---|
test.jpg | 1280x720 |
数据增强的transform
操作会增加样本量吗?需不需要单独的把数据集拿出来增强一下再训练?
如果tranform
里面有随机的方法,那么每个epoch
训练的数据集将会不同,就相当于增加了样本数量,所以直接训练即可,不用单独拿出来做增强。
如果是对批数据进行变换,那么该批的所有变换都是相同的。为什么要这样说?之前不是提到随机旋转这些随机的操作嘛,pytorch
在训练前需要把数据做成批数据,然后用数据加载器喂到模型中训练,也就是说这些随机的方法对于同一批数据的随机是相同,比如要旋转45°
的话就都旋转45°
,而不同批可能会不同。
https://pytorch.org/docs/stable/torchvision/transforms.html