PyTorch【3】图像数据的预处理与操作

一.流程简介

图片数据是深度学习中最常用的数据类型,好的图片数据集对模型训练起着至关重要的作用,要想获得好的数据集,就要对数据集进行预处理操作,比如旋转、切割、归一化等操作,预处理之后再进行数据分批化,就可以传入模型进行训练。总体步骤总结如下:

  • 预处理并加载数据集
    • 从本地加载数据集
    • 从框架加载数据集
  • 数据集操作

二.相关函数

1.预处理函数

不论数据从哪里获取,一般都要进行预处理变换操作,torchvision.transforms是 PyTorch 的图像变换操作库,该库下有很多预处理类,它们的功能各不相同。

import torchvision.transforms as transforms
描述
transforms.Compose([transforms.ToTensor(),...]) 预处理整合,放入其他预处理操作。
transforms.ToTensor() 图像 Tensor 化,将图片像素值转为 [0,1]范围;
shape转为 (C,H,W) 格式。
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) 图像归一化,参数为每个通道的均值与标准差;
若value为像素值,则转换后的value=(value-0.5)/0.5;
注意通道数要和输入图片的通道数相同。
transforms.CenterCrop(size) 从中心裁剪图像,裁剪图像到 (size,size) 大小(输入为整型或元组);
超过图像原本大小的部分填充黑色。
transforms.RandomCrop(size) 随机选取一个位置切割图像,裁剪图像到 (size,size) 大小(输入为整型或元组),
超过原图大小会报错。
transforms.RandomHorizontalFlip(p=0.5) 图像水平翻转,p 为被翻转的概率。
transforms.Resize(size) 调整图像大小。
参数:
size:期待输出图片的大小,元组或整型。
当输入为元组 (h,w) 时,输出的大小就是 (h,w)。
当输入为整型 size 时,如果原图 height > weight,输出的大小为 (size*height/width, size)。
interpolation:图像插值方式,默认为线性插值。一般默认即可。(可选)
max_size = None:最大尺寸,整型。(可选)
antialias = None:抗锯齿标志。(可选)
transforms.Scale(Resize) 也可以调整图像尺寸,但是被废弃,改用 transforms.Resize()

2.从框架加载数据集函数

PyTorch 自带以下数据。

from torchvision.datasets import FashionMNIST
数据集对应的类 描述
datasets.MNIST() 手写字体数据集
datasets.FashionMNIST() 衣服、鞋子、包等10类数据
datasets.KMNIST() 一些文字的灰度数据
datasets.CocoCaptions() 用于图像标注的MS COCO数据
datasets.CocoDetection() 用于检测的MS COCO数据
datasets.LSUN() 10个场景20个目标的分类数据集
datasets.CIFAR10() CIFAR10类的数据集
datasets.CIFAR100() CIFAR100类的数据集
datasets.STL10() 10类的分类数据和大量的未分类数据
datasets.ImageFolder() 从本地文件夹中加载并预处理数据,并将图片按照文件夹自动分类

参数:

train_data = FashionMNIST/MNIST/KMNIST/CIFAR10/CIFAR100(
    root,    							# 数据保存路径
    train=True,                     	# 下载训练数据集还是测试集
    transform=transforms.Compose([]),	# 数据预处理
    target_transform = None,			# 标签预处理
    download=False,						# 是否将数据下载到root中,一般为 True
)

属性:

d = FashionMNIST()

d.classes		# 标签名列表,['T-shirt/top', 'Trouser', ......, 'Ankle boot']
d.class_to_idx 	# 标签名_序号的字典,{'T-shirt/top': 0, ...... ,'Ankle boot': 9}
d.data			# 未经 transform 处理的原图片数据
d.targets		# 未经 transform 处理的原标签纸

3.从本地加载数据集函数

(1).创建本地文件夹

假设有 3 类图片数据,每一类图片单独放在一个文件夹中,那么数据目录应按照如下格式建立:

---- imgdata--------------数据库根目录
|
|---- classes1----------------类别1根目录
| |---- 1.png
| |---- …
|---- classes2----------------类别2根目录
| |---- 1.png
| |---- …
|---- classes3----------------类别3根目录
|---- 1.png
|---- …

此时的图片数据路径可以设为:train_data_root='imgdata/'
支持的图片类型:.jpg, .jpeg, .png, .ppm, .bmp, .pgm, .tif, .tiff, .webp

(2).函数

dataset =torchvision.datasets.ImageFolder():从本地文件夹中加载并预处理数据,并将图片按照文件夹自动分类

参数:

dataset =torchvision.datasets.ImageFolder(
	root					# 数据根目录(必选,str 类型)
	transform = None		# 对图片进行预处理的操作,返回转换后的图片。两种写法(可选,常用)
								'''
								# 1. transform=torchvision.transforms.ToTensor()
	    						# 2. transform=torchvision.transforms.Compose([
	                                       transforms.Resize(opt.img_size),
	                                       transforms.CenterCrop(opt.img_size),
	                                       transforms.ToTensor(),  # 转化成张量
	                                       ......])
	                            不管哪种写法,都要有 transforms.ToTensor(),否则容易报错
						        '''
	target_transform = None	# 对标签进行预处理的操作,返回转换后的标签(可选,不常用)
	loader = default_loader	# 数据集的加载方式,一般默认即可(可选)
	is_valid_file = None	# 获取图像文件的路径并检查该文件是否有效,用于检查损坏的文件,一般不用(可选)
)

属性:

classes			# 列表形式的分类名称,如 ['classes1','classes2','classes3']
class_to_idx	# 字典形式的类名与标签,如 {'classes1':0,'classes2':1,'classes3':2}
imgs			# 包含(image path, class_index)元组形式的列表

4.数据集操作

获取数据集后,可以将数据集进行合并、拆分以及分批化处理,在图像训练中最常用的就是分批化处理。

from torch.utils.data import *
数据集对应的类 描述
TensorDataset(a,b,c,...) 将多个tensor数据集沿水平方向合并,它们的第一个维度(batch_size)要相同
ConcatDataset([a,b,...]) 将多个tensor数据集沿垂直方向合并
Subset(a,[index1,index2,...]) 根据索引获取数据集的子集,[index,…] 为具体的索引值
random_split(a,[num1,num2,...,]) 随机将数据集拆分为给定长度的非重叠新数据集
num1+num2+…=len(a)
DataLoader() 数据集分批化

DataLoader常用参数:

dataloader = torch.utils.data.DataLoader(
    dataset				# 从本地或框架加载的数据集
    batch_size = 1		# batch_size 大小(可选,int 类型)
    shuffle = False		# 是否在每个 epoch 打乱数据(可选)
    drop_last = False	# 是否丢弃最后一个不完整的 batch(可选)
                            # drop_last=True  时 len(dataset)/batch_size 向下取整
                            # drop_last=False 时 len(dataset)/batch_size 向上取整
    num_workers = 0		# 使用的线程数(可选,int 类型)
)

三.示例

1.从框架获取数据处理

from torchvision.datasets import FashionMNIST
import torchvision.transforms as transforms
from torch.utils.data import random_split

dataset = FashionMNIST(
    root='./data/FashionMNIST',    		# 数据保存路径
    train=False,                     	# 下载训练数据集还是测试集
    transform=transforms.ToTensor(),
    download=True,						# 将数据下载到root中,已存在时不下载

)

print(len(dataset))	# 10000
d1,d2 = random_split(dataset,[2000,8000])
print(len(d1))	# 2000
print(len(d2))	# 8000

2.从本地获取数据处理

from torchvision.datasets import ImageFolder
from torch.utils.data import DataLoader
import torchvision.transforms as transforms
# 1.根目录
root = 'datasets/train'
# 2.预处理加载数据集
dataset = ImageFolder(root,transform=transforms.ToTensor())

print('图片总数量:',len(dataset))				# 3842
print('classes:', dataset.classes)				# ['leopard', 'lion', 'tiger']
print('class_to_idx:', dataset.class_to_idx)	# {'leopard': 0, 'lion': 1, 'tiger': 2}
print('imgs:\n', dataset.imgs)	
# [('datasets/train\\leopard\\1 (100).jpg', 0), ('datasets/train\\leopard\\1 (1000).jpg', 0), ...... ]

# 3.数据集分批
dataloader = DataLoader(dataset=dataset, batch_size=128, shuffle=True, drop_last=True)
print('loader总数量:',len(dataloader))			# 30

for step,(imgs,labels) in enumerate(dataloader):
    print('imgs.shape:',imgs.shape)			# torch.Size([128, 3, 512, 512])
    print('labels.shape:',labels.shape)		# labels.shape: torch.Size([128])
    print(labels)							# tensor([0, 0, 1, ......, 0, 2]

你可能感兴趣的:(PyTorch框架学习,pytorch,计算机视觉,深度学习)