transforms的使用
torchvision和 torchaudio
torchvision是pytorch的一个图形库,它服务于PyTorch深度学习框架的,主要用来构建计算机视觉模型。以下是torchvision的构成:
-
torchvision.datasets: 一些加载数据的函数及常用的数据集接口;常用数据集的dataset实现,MNIST,CIFAR-10,ImageNet等;
-
torchvision.models: 模型预训练,包含常用的模型结构(含预训练模型),例如AlexNet、VGG、ResNet等;
-
torchvision.transforms: 常用的图片变换,例如裁剪、旋转等
-
torchvision.utils: 其他的一些有用的方法。
- torchvision.transforms
torchvision.transforms主要是用于常见的一些图形变换。
torchvision.transforms.Compose()类。这个类的主要作用是串联多个图片变换的操作。
torchaudio 支持以 wav 和 mp3 格式加载声音文件。 我们称波形为原始音频信号。
- 下面列出的是 torchaudio 支持的转换,这个列表还在不断增长中。
- 重采样:将波形重新采样到不同的采样率。
- 频谱图:从波形创建频谱图。
- MelScale:它使用转换矩阵将普通 STFT 转换为梅尔频率 STFT。
- AmplitudeToDB:它将一个频谱图从功率/振幅刻度转换为分贝刻度。
- MFCC:从波形创建梅尔频率的cepstrum系数。
- MelSpectrogram:使用 PyTorch 中的 STFT 函数从波形创建 MEL 频谱图。
- MuLawEncoding:基于mu-law比较编码波形。
- **MuLawDecode:**解码mu-law编码波形。
transforms结构及用法
transforms在计算机视觉工具包torchvision下:
torchvision.transforms : 常用的图像预处理方法
torchvision.transforms : 常用的图像预处理方法,提高泛化能力
• 数据中心化
• 数据标准化
• 缩放
• 裁剪
• 旋转
• 翻转
• 填充
• 噪声添加
• 灰度变换
• 线性变换
• 仿射变换
• 亮度、饱和度及对比度变换
tensor数据类型
通过transforms.ToTensor来看:
-
transforms如何使用:
- ToTensor类的具体内容:
class ToTensor: """Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor. This transform does not support torchscript. Converts a PIL Image or numpy.ndarray (H x W x C) in the range [0, 255] to a torch.FloatTensor of shape (C x H x W) in the range [0.0, 1.0] if the PIL Image belongs to one of the modes (L, LA, P, I, F, RGB, YCbCr, RGBA, CMYK, 1) or if the numpy.ndarray has dtype = np.uint8 In the other cases, tensors are returned without scaling. .. note:: Because the input image is scaled to [0.0, 1.0], this transformation should not be used when transforming target image masks. See the `references`_ for implementing the transforms for image masks. .. _references: https://github.com/pytorch/vision/tree/main/references/segmentation """ def __init__(self) -> None: _log_api_usage_once(self) def __call__(self, pic): """ Args: pic (PIL Image or numpy.ndarray): Image to be converted to tensor. Returns: Tensor: Converted image. """ return F.to_tensor(pic) def __repr__(self) -> str: return f"{self.__class__.__name__}()"
可以看到,ToTensor对输入有要求,
pic (PIL Image or numpy.ndarray): Image to be converted to tensor
Converts a PIL Image or numpy.ndarray (H x W x C) in the range [0, 255] to a torch.FloatTensor of shape (C x H x W) in the range [0.0, 1.0]
(H,W,C)【高,宽,通道数】:例子[28,28,3] 28*28像素大小的三通道图片(彩色图片)。
‘’’ torchvision.transforms.ToTensor ‘’’ np.ndarray与Tensor中图像格式区别 两者均以三维数组来表示一张图像,他们的区别在于图像信息被保存在数组中的不同位置,具体来说:
np.ndarray的[h, w, c]格式:数组中第一层元素为图像的每一行像素,第二层元素为每一列像素,最后一层元素为每一个通道的像素值,它将图片中的每一个像素作为描述单元,记录它三个通道的像素值。 Tensor的[c, h, w]格式:数组中第一层元素为图像的三个通道,第二层元素为某个通道上的一行像素,第三层为该通道上某列的像素值,它将图像某个通道的某行像素值作为描述单元。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KMAtxbjU-1652838845502)(D:\STUDY\神经网络和深度学习\images\ndarry的图片形式.png)]
- 实现对图片打开
# 针对使用PIL的pic图片数据的ToTensor的使用方法 from PIL import Image img_path = "DataSet/hymenoptera_data/train/ants/5650366_e22b7e1065.jpg" img = Image.open(img_path) print(img) #输出结果: #<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=500x375 at 0x2AC38B67160> #具体如何使用transforms, tensor_trans= transforms.ToTensor() tensor_img = tensor_trans(img) print(type(tensor_img))
# 针对使用opencv 的 ndarray数据类型的ToTensor的使用 from torchvision import transforms import cv2 img_path="DataSet/hymenoptera_data/train/ants/5650366_e22b7e1065.jpg" tensor_trans= transforms.ToTensor() cv_img = cv2.imread(img_path) print(type(cv_img)) cv_img_Ts = tensor_trans(cv_img) print(type(cv_img_Ts)) 输出结果: <class 'numpy.ndarray'> <class 'torch.Tensor'>
需要注意:在使用opencv进行图片读取时,路径要求是非中文路径
重要的一点时图像只要经过转换及存储后,其模式就不会变,只是读取时以不同的模式读会有差异,不用担心
常见的Transforms
关注的三个点:输入、输出、作用
-
ToTensor
已经介绍过了,不赘述
-
Normalize 标准化化操作
-
Resize
将输入图像调整为给定大小。如果图像是 Torch Tensor,它应该具有 […, H, W] 形状,其中 … 表示任意数量的前导维度
-
Compose
将多个变换组合在一起。此转换不支持 torchscript;一般用Compose把多个步骤整合到一起:
比如说:
transforms.Compose([transforms.CenterCrop(10),transforms.ToTensor(),])
这样就把两个步骤整合到了一起。
-
RandomCrop():随机裁剪,根据输入的大小进行图片裁剪,
参数输入:一个数值大小或一个(h,w)的序列
注意:当给的数值大于源图片实际大小时会报错。
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
img_path = "DataSet/hymenoptera_data/train/bees/17209602_fe5a5a746f.jpg"
img = Image.open(img_path)
# ToTensor 的使用
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer = SummaryWriter("logs")
writer.add_image(tag="ants2", img_tensor=img_tensor)
# normalize(归一化) 的使用
print("归一化前数值:")
print(img_tensor[0][0][0])
trans_norm = transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
img_norm = trans_norm(img_tensor)
print("归一化后数值:")
print(img_norm[0][0][0])
writer.add_image("Normalize", img_tensor=img_norm)
# Resize-1:
print(img.size)
trans_resize = transforms.Resize((512, 512)) #这种使用tuple作为大小改变的方法会修改图片的整体比例
# img PIL --resize,重新变化大小,类型依旧是 PIL--》 img_resize PIL
img_resize = trans_resize(img)
# img_resize PIL --totensor--》 img_resize_tensor Tensor
img_resize_tensor = trans_totensor(img_resize)
writer.add_image("resize", img_resize_tensor)
# Resize -2
'''
Compose()的用法:参数需要一个列表[],在Compose中数据需要是transforms类型
'''
trans_resize2 = transforms.Resize(512)
trans_compose = transforms.Compose([trans_resize2,trans_totensor])
img_resize_2 = trans_compose(img)
writer.add_image("Resize",img_resize_2,1)
#RandomCrop()用法
trans_random = transforms.RandomCrop(128)
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)
writer.close()