PyTorch学习(3):数据预处理

2023-05-16

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)
                #print(t.size)
                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))  # 大于图片大小则进行中心缩小,边缘填充0
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))
#show(img, transforms.TenCrop(299, vertical_flip=True))
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))  # 色调,只能是-0.5~0.5.
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

  : 对图像进行随机擦除

# Erasing需要组合使用
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))  # 旋转角度
#show(img, transforms.RandomAffine(50, resample=PIL.Image.BILINEAR))
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))  # 使用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) # 转换成tensor
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] # 2 BGR
        img = np.transpose(img, [2, 0, 1]) # 2 (3, H, W)
        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(使用前将#替换为@)

PyTorch学习(3):数据预处理 的相关文章

随机推荐