PyTorch学习(3):数据预处理
- Pytorch官方文档: https://pytorch-cn.readthedocs.io/zh/latest/
- Pytorch学习文档: https://github.com/tensor-yu/PyTorch_Tutorial
- 参考: https://blog.csdn.net/u011995719/article/details/85103712
https://www.cnblogs.com/mengfu188/p/13561693.html
https://pytorch-cn.readthedocs.io/zh/latest/torchvision/torchvision-transform/
文章目录
- PyTorch学习(3):数据预处理
- 前言
- 1.Torchvision.transforms模块
- 2.Transforms on PIL Image
- 1)裁剪
- (1)随机裁剪:transforms.RandomCrop
- (2)随机长宽比裁剪:transforms.RandomResizedCrop
- (3)中心裁剪:transforms.CenterCrop
- (4)上下左右中心裁剪:transforms.FiveCrop
- (5)上下左右中裁剪后翻转:transforms.TenCrop
- 2)镜像
- (1)水平翻转:transforms.RandomHorizontalFlip
- (2)垂直翻转:transforms.RandomVerticalFlip
- 3)随机旋转:transforms.RandomRotation
- 4)颜色变换:transforms.ColorJitter
- 5)随机擦除:transforms.RandomErasing
- 6)图像变换
- (1)resize图像:transforms.Resize
- (2)图像填充:transforms.Pad
- (3)透视变换:transforms.RandomPerspective
- (4)仿射变换:transforms.RandomAffine
- (5)随机灰度化:transforms.RandomGrayscale
- 3.Transforms on torch.Tensor
- (1)转为Tensor:transforms.ToTensor
- (2)转成BGRTensor:自定义实现
- (3)转为PILImage:transforms.ToPILImage
- 4.Conversion Transforms
- 5.Generic Transforms
- 6.对transforms操作,使数据增强更加灵活
- 总结
前言
在实际应用过程中,都会对训练数据进行一些预处理操作,包括:数据的标准化(减均值,再除以标准差),随机裁剪,旋转平移镜像等一系列操作,来提升模型的泛化性能。
Torchvision.transforms是PyTorch中的图像预处理包,包含了多种对图像数据进行变换的函数,这些都是在进行图像数据读取过程中必不可少的预处理步骤。
1.Torchvision.transforms模块
torchvision.transforms模块按照功能进行划分,主要分为4个部分,所有转换均可用torchvision.transforms.Compose() 来组合。
1)Transforms on PIL Image: 在PIL Image上进行的转换,比如随机翻转、裁剪等。
2)Transforms on torch.Tensor:在tensor上进行的转换,最常用的是归一化操作transforms.Normalize(mean, std, inplace=False)。
3)Conversion Transforms:PIL.Image/numpy.ndarray与Tensor的相互转换。
4)Generic Transforms:提供自定义转换接口。
Transforms的使用:
data_transforms = transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
transforms.Compose(transforms) 方法是将多种变换组合在一起。上述对data_transforms进行了四种变换,前两个是对PILImage进行的,分别对其进行随机大小和随机宽高比的裁剪,之后resize到指定大小224,以及对原始图像进行随机的水平翻转;
第三个transforms.ToTensor() 将PILImage转变为torch.FloatTensor的数据形式;
而最后一个Normalize则是对tensor进行的。
多种组合变换有一定的先后顺序,处理PILImage的变换方法(大多数方法)都需要放在ToTensor方法之前,而处理tensor的方法(比如Normalize方法)就要放在ToTensor方法之后。
2.Transforms on PIL Image
实例演示Code:
import matplotlib.pyplot as plt
import torchvision.transforms as transforms
from PIL import Image
import PIL
import numpy as np
import torch
import cv2
def show(img, transform=None):
if transform:
if isinstance(transform, (transforms.FiveCrop, transforms.TenCrop)):
t = transform(img)
for i in range(len(t)):
plt.subplot(len(t)/5, 5, 1+i)
plt.axis('off')
plt.imshow(t[i])
else:
for i in range(9):
plt.subplot(331 + i)
plt.axis('off')
t= transform(img)
plt.imshow(t)
print(str(transform))
print(t)
else:
plt.imshow(img)
plt.axis('off')
plt.show()
img = cv2.imread("pika.jpg")
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
img = Image.fromarray(img)
print(img)
show(img)
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854CBC3BE0>
1)裁剪
(1)随机裁剪:transforms.RandomCrop
随机取不同的点作为中心进行裁剪
show(img, transforms.RandomCrop(299))
show(img, transforms.RandomCrop(299,padding=50, pad_if_needed=True))
show(img, transforms.RandomCrop(299,padding=50, pad_if_needed=True, fill=(255,0,0)))
RandomCrop(size=(299, 299), padding=None)
<PIL.Image.Image image mode=RGB size=299x299 at 0x1854DEAC3A0>
RandomCrop(size=(299, 299), padding=50)
<PIL.Image.Image image mode=RGB size=299x299 at 0x1854C7EB550>
RandomCrop(size=(299, 299), padding=50)
<PIL.Image.Image image mode=RGB size=299x299 at 0x1854C7BC3A0>
(2)随机长宽比裁剪:transforms.RandomResizedCrop
随机大小,随机长宽比裁剪原始图片,最后将图片resize到设定好的size
size为缩放之后的大小
scala为裁剪比例
ratio为伸缩比例
interpolation为resize模式
show(img, transforms.RandomResizedCrop(299))
show(img, transforms.RandomResizedCrop(299, scale=(0.5, 2.0)))
show(img, transforms.RandomResizedCrop(299, ratio=(1/2, 2/1)))
RandomResizedCrop(size=(299, 299), scale=(0.08, 1.0), ratio=(0.75, 1.3333), interpolation=bilinear)
<PIL.Image.Image image mode=RGB size=299x299 at 0x1854DE94BE0>
RandomResizedCrop(size=(299, 299), scale=(0.5, 2.0), ratio=(0.75, 1.3333), interpolation=bilinear)
<PIL.Image.Image image mode=RGB size=299x299 at 0x1854CA90BE0>
RandomResizedCrop(size=(299, 299), scale=(0.08, 1.0), ratio=(0.5, 2.0), interpolation=bilinear)
<PIL.Image.Image image mode=RGB size=299x299 at 0x1854DF452E0>
(3)中心裁剪:transforms.CenterCrop
以图片中心为起点,按像素大小进行裁剪
show(img, transforms.CenterCrop(299))
show(img, transforms.CenterCrop(512))
CenterCrop(size=(299, 299))
<PIL.Image.Image image mode=RGB size=299x299 at 0x1854DC26580>
CenterCrop(size=(512, 512))
<PIL.Image.Image image mode=RGB size=512x512 at 0x1854CAD6F40>
(4)上下左右中心裁剪:transforms.FiveCrop
对图片进行上下左右以及中心裁剪,获得5张图片,返回一个4D-tensor。
show(img, transforms.FiveCrop(299))
FiveCrop(size=(299, 299))
(<PIL.Image.Image image mode=RGB size=299x299 at 0x1854C9D8490>, <PIL.Image.Image image mode=RGB size=299x299 at 0x1854C9D82E0>, <PIL.Image.Image image mode=RGB size=299x299 at 0x1854CBEACA0>, <PIL.Image.Image image mode=RGB size=299x299 at 0x1854CBEA9D0>, <PIL.Image.Image image mode=RGB size=299x299 at 0x1854CBEAE80>)
(5)上下左右中裁剪后翻转:transforms.TenCrop
对图片进行上下左右以及中心裁剪,然后全部翻转(水平或者垂直),获得10张图片,返回一个4D-tensor。
show(img, transforms.TenCrop(299))
TenCrop(size=(299, 299), vertical_flip=False)
(<PIL.Image.Image image mode=RGB size=299x299 at 0x185435D8820>, <PIL.Image.Image image mode=RGB size=299x299 at 0x1854CA2F9A0>, <PIL.Image.Image image mode=RGB size=299x299 at 0x1854CA2F4F0>, <PIL.Image.Image image mode=RGB size=299x299 at 0x1854CAD6E20>, <PIL.Image.Image image mode=RGB size=299x299 at 0x1854C69CDF0>, <PIL.Image.Image image mode=RGB size=299x299 at 0x18543BE8490>, <PIL.Image.Image image mode=RGB size=299x299 at 0x1854CAD6CA0>, <PIL.Image.Image image mode=RGB size=299x299 at 0x18543BE84C0>, <PIL.Image.Image image mode=RGB size=299x299 at 0x185437F59A0>, <PIL.Image.Image image mode=RGB size=299x299 at 0x185437F5880>)
2)镜像
(1)水平翻转:transforms.RandomHorizontalFlip
依据概率p对PIL图片进行水平翻转
show(img, transforms.RandomHorizontalFlip())
RandomHorizontalFlip(p=0.5)
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854CA79D90>
(2)垂直翻转:transforms.RandomVerticalFlip
依据概率p对PIL图片进行垂直翻转
show(img, transforms.RandomVerticalFlip())
RandomVerticalFlip(p=0.5)
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854CAA7B80>
3)随机旋转:transforms.RandomRotation
: 依degrees随机旋转一定角度
show(img, transforms.RandomRotation(30))
RandomRotation(degrees=[-30.0, 30.0], interpolation=nearest, expand=False, fill=0)
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854DD4F7C0>
4)颜色变换:transforms.ColorJitter
: 修改图像亮度、对比度、饱和度和色调
show(img, transforms.ColorJitter(brightness=0.5))
ColorJitter(brightness=[0.5, 1.5], contrast=None, saturation=None, hue=None)
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854C85CEB0>
show(img, transforms.ColorJitter(contrast=0.5))
ColorJitter(brightness=None, contrast=[0.5, 1.5], saturation=None, hue=None)
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854C774FD0>
show(img, transforms.ColorJitter(saturation=0.5))
ColorJitter(brightness=None, contrast=None, saturation=[0.5, 1.5], hue=None)
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854CB61310>
show(img, transforms.ColorJitter(hue=0.1))
ColorJitter(brightness=None, contrast=None, saturation=None, hue=[-0.1, 0.1])
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854C770760>
5)随机擦除:transforms.RandomErasing
: 对图像进行随机擦除
t = transforms.Compose([transforms.ToTensor(),transforms.RandomErasing(), transforms.ToPILImage()])
show(img, t)
Compose(
ToTensor()
RandomErasing()
ToPILImage()
)
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854C856850>
6)图像变换
(1)resize图像:transforms.Resize
重置图像分辨率
show(img, transforms.Resize(224))
Resize(size=224, interpolation=bilinear)
<PIL.Image.Image image mode=RGB size=224x224 at 0x1854DD92070>
(2)图像填充:transforms.Pad
对图像进行填充
show(img, transforms.Pad(50))
Pad(padding=50, fill=0, padding_mode=constant)
<PIL.Image.Image image mode=RGB size=500x500 at 0x1854CAE38B0>
show(img, transforms.Pad(50,padding_mode='edge'))
Pad(padding=50, fill=0, padding_mode=edge)
<PIL.Image.Image image mode=RGB size=500x500 at 0x1854DC6EA60>
show(img, transforms.Pad(50,padding_mode='reflect'))
Pad(padding=50, fill=0, padding_mode=reflect)
<PIL.Image.Image image mode=RGB size=500x500 at 0x1854CB440D0>
(3)透视变换:transforms.RandomPerspective
show(img, transforms.RandomPerspective())
RandomPerspective(p=0.5)
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854DCF5B20>
(4)仿射变换:transforms.RandomAffine
show(img, transforms.RandomAffine(50))
RandomAffine(degrees=[-50.0, 50.0])
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854C8F8670>
show(img, transforms.RandomAffine(0, shear=50))
RandomAffine(degrees=[0.0, 0.0], shear=[-50.0, 50.0])
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854C931040>
show(img, transforms.RandomAffine(0, translate=(0.1,0.3)))
RandomAffine(degrees=[0.0, 0.0], translate=(0.1, 0.3))
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854DE10F10>
show(img, transforms.RandomAffine(0, scale=(0.5, 1)))
RandomAffine(degrees=[0.0, 0.0], scale=(0.5, 1))
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854DDBC9A0>
(5)随机灰度化:transforms.RandomGrayscale
show(img, transforms.RandomGrayscale(0.5))
RandomGrayscale(p=0.5)
<PIL.Image.Image image mode=RGB size=400x400 at 0x1854CAAF2E0>
3.Transforms on torch.Tensor
(1)转为Tensor:transforms.ToTensor
功能: 把一个取值范围是[0,255]的PIL.Image或者shape为(H,W,C)的numpy.ndarray,转换成形状为[C,H,W],取值范围是[0,1.0]的torch.FloadTensor。
注意: 归一化至[0-1]是直接除以255,若自己的ndarray数据尺度有变化,则需要自行修改。
data = np.random.randint(0, 255, size=300)
img = data.reshape(10,10,3).astype(np.uint8)
print(img.shape,type(img))
img_tensor = transforms.ToTensor()(img)
print(img_tensor)
(2)转成BGRTensor:自定义实现
class ToBGRTensor(object):
def __call__(self, img):
assert isinstance(img, (np.ndarray, PIL.Image.Image))
if isinstance(img, PIL.Image.Image):
img = np.asarray(img)
img = img[:,:,::-1]
img = np.transpose(img, [2, 0, 1])
img = np.ascontiguousarray(img)
img = torch.from_numpy(img).float()
return img
(3)转为PILImage:transforms.ToPILImage
功能: 将shape为(C,H,W)的Tensor或shape为(H,W,C)的numpy.ndarray转换成PIL.Image,值不变。
参数: mode为None时,为1通道, mode=3通道默认转换为RGB,4通道默认转换为RGBA
4.Conversion Transforms
标准化:transforms.Normalize(mean, std)
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
功能: 给定均值:(R,G,B) 方差:(R,G,B),将会把Tensor正则化。即:Normalized_image=(image-mean)/std。
5.Generic Transforms
使用lambd作为转换器。
def foo(x):
r = x[0, ...] + 0.1
print(x.shape, x.max(), x.min(), r.shape, r.max(), r.min())
r= torch.clamp(r, 0, 1)
return r
t = transforms.Compose([transforms.ToTensor(),transforms.Lambda(foo), transforms.ToPILImage()])
show(img, t)
Compose(
ToTensor()
Lambda()
ToPILImage()
)
<PIL.Image.Image image mode=L size=400x400 at 0x1854C6B99D0>
6.对transforms操作,使数据增强更加灵活
transforms.RandomChoice(transforms),从给定的一系列transforms中选一个进行操作;
transforms.RandomApply(transforms, p=0.5),给每一个transform加上概率,依概率进行操作;
transforms.RandomOrder,将transforms中的操作随机打乱。
总结
至此,基于PyTorch的数据预处理Torchvision.transforms库已基本了解,无须自定义实现,基本满足需求。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)