深度学习 -- PyTorch学习 torchvision工具学习 Transforms模块 Normalize用法
前言
计算机视觉是深度学习的一个重要应用领域。PyTorch提供现成的torchvision工具,帮助处理图像和视频。torchvision包含一些常用的数据集、模型、转换函数等,学习和使用这些API有助于更快更好的在CV领域应用PyTorch。
torchvision
torchvision的数据集都是torch.utils.data.Dataset的子类,都实现了__getitem__ 和 __len__函数,可传递给支持并行处理的多进程torch.utils.data.DataLoader加载器进行数据加载。
使用torchvision编写图像数据集
假定现在手头里有25000张猫和狗的图像数据,它们存放在同一个目录下,文件名命名为dog.xxx.jpg和cat.xxx.jpg。(xxx为编号0-12499)
我们要对猫和狗进行分类任务
import torch
import os
import numpy as np
from PIL.Image import Image
from torch.utils.data import Dataset
class DogsCatsDataset(Dataset):
'''猫狗数据集定义'''
def __init__(self,root):
# root 为图片路径
imgs = os.listdir(root) # 把root目录下的文件名变成列表的形式
# 仅保存图片的完整路径
self.imgs = [os.path.join(root,img) for img in imgs]
def __getitem__(self, item):
img_path = self.imgs[item]
# 根据文件名确定标签,dog为1 cat为0
label = 1 if 'dog' in img_path else 0
pil_img = Image.open(img_path)
img_array = np.array(pil_img)
# 把图像数据转换为张量
img = torch.from_numpy(img_array)
return img ,label
def __len__(self):
return len(self.imgs)
if __name__ == '__main__':
dataset = DogsCatsDataset("./路径")
img,label = dataset[1]
print(img.shape,label)
这段代码假设您的数据集保存在一个名为 ./路径 的目录中,并且该目录包含多个子目录,每个子目录中包含多个图片文件。每个图片文件的文件名以 .jpg 或 .png 结尾。
首先,代码将根据图片的文件名确定其标签。‘dog’ 表示狗的标签,‘cat’ 表示猫的标签。
然后,代码将打开每个图片文件,并将其转换为张量。这里使用了 PyTorch 中的 torch.from_numpy() 函数将 NumPy 数组转换为张量。
最后,代码返回张量和标签。len() 方法返回数据集中图片的数量。
在示例中,代码将打印张量的形状和标签。在这种情况下,张量的形状为 (1,),标签为 1,因为图片文件名为 ‘dog’。
Transforms模块
前文定义的猫狗数据集类存在三个问题:
- 每张图片的宽、高不一样,需要进行处理
- 图片的每个像素的取值范围是0-255,深度网络需要归一化到0-1的范围内
- 注入PIL工具读取到的图片张量形状是(H,W,C),但是深度网络接收的图片张量形状为(B,C,H,W),需要进行转换,其中,B为一批样本中的图片数,H和W分别为图片的高和宽,C为图片的通道数。
对此,PyTorch torchvision工具的Transforms模块提供对PIL Image对象的图像转换功能,该模块提供了常用预处理功能的实现,如填充、裁剪、灰度模式、线性变换、将图像转换成PyTorch张量,以及一些实现数据增强的功能,如反转、随机剪裁、颜色抖动。
图像转换:
python
import torch
from PIL import Image
# 读取图像
img = Image.open('path/to/image.jpg')
# 转换为张量
img_tensor = torch.from_numpy(img.convert('RGB'))
# 转换为PIL Image对象
img_pil = Image.fromarray(img_tensor)
# 转换为RGBA四元组
img_tensor_4d = torch.stack([img_tensor, img_tensor, img_tensor], dim=0)
img_pil_4d = Image.fromarray(img_tensor_4d)
# 定义转换函数
transforms = {
'to_tensor': torch.nn.functional.to_tensor,
'to_pil_image': Image.fromarray,
'to_pil_image_data': Image.fromarray,
}
# 应用转换函数
for transform, method in transforms.items():
img_tensor_transformed = method(img_tensor)
# 处理转换后的张量
图像增强:
import torch
from PIL import Image
import numpy as np
# 读取图像
img = Image.open('path/to/image.jpg')
# 增强对比度
img_contrast = Image.eval(img, contrast=1.5)
# 增强亮度
img_brightness = Image.eval(img, brightness=1.5)
# 增强颜色
img_gamma = Image.eval(img, gamma=1.5)
# 定义增强函数
transforms = {
'contrast': lambda img: np.clip(img.astype(np.uint8) + np.random.randn_like(img), 0, 255),
'brightness': lambda img: np.clip(img.astype(np.uint8) + np.random.randn_like(img), 0, 255),
'gamma': lambda img: np.clip(img.astype(np.uint8) + np.random.randn_like(img), 0, 255),
}
# 应用增强函数
for transform, method in transforms.items():
img_transformed = method(img)
# 处理增强后的张量
数据转换:
import torch
from PIL import Image
# 读取张量
data = torch.randn(1, 3, 224, 224)
# 转换为PIL Image对象
img_pil = Image.fromarray(data.transpose(1, 2))
# 转换为RGBA四元组
data_tensor_4d = torch.stack([data.transpose(1, 0), data.transpose(0, 2), data], dim=0)
img_pil_4d = Image.fromarray(data_tensor_4d)
# 定义转换函数
transforms = {
'to_pil_image': Image.fromarray,
'to_pil_image_data': Image.fromarray,
}
# 应用转换函数
for transform, method in transforms.items():
data_tensor_transformed = method(data_tensor)
# 处理转换后的张量
数据增强:
import torch
from PIL import Image
# 读取张量
data = torch.randn(1, 3, 224, 224)
# 增强随机旋转
data_randrot = data.transpose(2, 0, 1)
data_rot = data_randrot.permute(0, 2, 3, 1)
# 增强随机缩放
data_randscale = data.unsqueeze(0).unsqueeze(0).unsqueeze(0)
Normalize用法
在TransFroms中通常使用Normalize来规范化张量图像,这是就需要计算数据集的均值和标准差。
Normalize是PyTorch中的一个函数,用于将张量的每个维度的均值和标准差都设置为0或1,使得张量的值在指定的范围内。
import torch
# 定义一个张量
x = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.float32)
# 定义Normalize的参数
mean = [0.0, 0.0]
std = [1.0, 1.0]
# 使用Normalize进行归一化
x_normalized = normalize(x, mean, std)
print(x_normalized)