(六)Transforms的使用
transforms.py工具箱
本事就是将图片经过transforms工具得到一个想要的变换结果
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
img_path = "data/train/bees_image/16838648_415acd9e3f.jpg"
img = Image.open(img_path)
writer = SummaryWriter("logs")#引用一个方法或者类需要看到所需参数可以用Ctrl+p
#1.transforms该如何使用
tensor_trans = transforms.ToTensor()#引用一下ToTensor类,创建一个具体的工具
tensor_img = tensor_trans(img)#将img转换成tensor类型
writer.add_image("Tensor_img",tensor_img)
writer.close()
常见的transforms:
1.transforms.normalize的作用及好处:
用于将图像数据进行标准化处理。它的作用是通过减去均值并除以标准差,将输入数据的分布调整为标准正态分布(零均值,单位方差)。这个操作通常应用在神经网络的输入数据上。
具体而言,对于每个通道,Normalize
的变换公式如下:
input[channel] = (input[channel] - mean[channel]) / std[channel]input[channel] = (input[channel] - mean[channel]) / std[channel]
其中,input[channel]input[channel] 是输入图像的某一通道的像素值,mean[channel]mean[channel] 是该通道的均值,std[channel]std[channel] 是该通道的标准差。
使用transforms.Normalize
的好处包括:
-
减少数据的偏差: 将数据标准化到零均值可以减少数据的偏差,有助于模型更好地学习数据的特征。
-
加速训练过程: 标准化可以加速模型的训练过程,因为它有助于避免梯度消失或梯度爆炸的问题,使得优化算法更容易收敛。
-
提高模型的泛化能力: 数据标准化有助于提高模型对未见过数据的泛化能力,因为它使得输入数据的分布更加一致。
-
处理不同尺度的数据: 标准化可以使不同特征之间的尺度差异变得更小,有助于模型更好地处理不同尺度的输入数据。
在使用transforms.Normalize
时,通常需要提供每个通道的均值和标准差作为参数。这些值可以通过对训练集进行统计计算得到。例如,对于RGB图像,通常会计算每个通道的均值和标准差,然后将它们传递给Normalize
变换。
#Normalize数据标准化
print(img_tensor[0][0][0])
tran_norm = transforms.Normalize(mean=[0.5,0.5,0.5],std=[0.5,0.5,0.5])
#这组参数的选择是基于经验和实验结果的。在许多情况下,将均值设置为0.5,标准差设置为0.5的目的是将图像像素值标准化到[-1, 1]的范围内。具体的归一化参数可能会根据数据集的特性而有所不同
img_norm = tran_norm(img_tensor)
print(img_norm[0][0][0])#用于输出经过归一化处理后图像张量的第一个通道、第一个行、第一个列的像素值
writer.add_image("Normalize",img_norm)
2.transforms.resize():改变图像大小
print(img.size)
trans_resize = transforms.Resize((512,512))#输入两个参数则直接修改图片尺寸
img_resize = trans_resize(img_tensor)#在使用resize时应当先用原始的PIL图像
#img_resize = trans_totensor(img_resize)##为了在tensorboard上呈现,再转为tensor类型
writer.add_image("Resize",img_resize,0)
print(img_resize)
3.transforms.totensor():将图像类型转为tensor类型
4.compose()用法:compose的参数是一个列表
#compose - resize-2 只传入一个参数就会等比缩放
trans_resize_2 = transforms.Resize(512)
trans_compose = transforms.Compose([trans_resize_2,trans_totensor])#注意后面一个参数的输入和前一个参数的输出进行匹配
img_resize_2 = trans_compose(img)
writer.add_image("Resize",img_resize_2,1)
需要注意的是,在使用transforms.Compose
时,确保前一个操作的输出和后一个操作的输入匹配,否则可能会导致错误(即列表中的两个参数颠倒)。在这里,transforms.Resize
的输出是一个PIL图像,而trans_totensor
的输入需要是一个PIL图像。
5.RandomCrop()随机裁剪
这样的代码可能会出现报错。因为随机裁剪的尺寸超过了原始图像的尺寸。你可以通过使用transforms.RandomResizedCrop
来解决这个问题
#RandomCrop
trans_random = transforms.RandomCrop(512)
trans_compose_2 = transforms.Compose([trans_random,trans_totensor])
for i in range(10):
img_crop = trans_compose_2(img)
writer.add_image("RandomCrop",img_crop,i)
transforms.RandomResizedCrop
是为了解决在使用 transforms.RandomCrop
时可能出现的尺寸大于原图尺寸的问题 。这引入了一个额外的缩放操作。具体来说,它首先对原始图像进行缩放,然后再进行随机裁剪。这个缩放操作的目的是确保裁剪框不会超出原始图像的边界。
学习新的方法使用:
关注输入和输出类型
多看官方文档
关注方法需要什么参数
不知道返回值的时候(*print,*print(type())
读取图像时 PIL 和 opencv 的选择
在自己建立 dataset 迭代器时,一般操作是检索数据集图像的路径,然后使用 PIL 库或 opencv库读取图片路径。
1>使用 PIL.Image 读取的图像是一种 PIL 类,mode=RGB,要想获得图像的像素值还需要将其转为 np.array 格式。
2>而 opencv 可以直接将图像读取为 np.array 格式,因此首选 opencv
import cv2
filePath="Dataset/FFHQ/00000.png"
img=cv2.imread(filePath)
print(f"img.shape = {img.shape}") # img.shape = (128, 128, 3)
print(f"img = {img}") # img.dtype = uint8