常用的transforms
- [1. ToTensor()](#1. ToTensor())
- [2. Normalize()](#2. Normalize())
- [3. Resize()](#3. Resize())
- [4. Compose()](#4. Compose())
- [5. RandomCrop()](#5. RandomCrop())
- [1-5 代码](#1-5 代码)
- [6. Python魔法函数](#6. Python魔法函数)
- 总结一下
B站小土堆 pytorch学习教程视频
https://www.bilibili.com/video/BV1hE411t7RN/?p=13&spm_id_from=pageDriver&vd_source=9607a6d9d829b667f8f0ccaaaa142fcb
1. ToTensor()
- ToTensor 把PIL图片类型数据或ndarry numpy数据类型转换为tensor类型数据
- 使用tensorboard 传入的必须是tensor类型的数据
2. Normalize()
- normalize 用平均值和标准差对张量图像做归一化
- 自己的torch版本没有内置call函数 有forward可以调用
思考:图片输入均值标准差时,根据RGB三个维度,所以均值标准差是三维数值,那么语音识别的输入维度应该是多少,根据什么来的,均值标准差应该是多少维的,平常说的pcen或者fbank 40维特征,根据特征多少维来确定均值标准差是多少维吗?
3. Resize()
输入一个PIL数据,输出一个PIL数据;
在compose调用resize的时候,是可以传递tensor参数的,但是我单独调用resize的时候,也报错必须传递PIL参数,暂时不知道原因,使用时注意。
4. Compose()
trans_resize 需要的参数是PIL图片格式,trans_totensor 可以将PIL图片数据转换为tensor数据,compose类将两个操作组合起来,可以理解为compose就是一次执行多个transforms的操作
列表的两个transforms操作顺序我当前的torch--1.11.0版本可以互换,有的torch版本不能互换,否则resize会因为使用的不是PIL数据,导致报错
trans_compose = transforms.Compose([trans_resize, trans_totensor]) # 设置compose需要的参数 都是transforms的类实例化
5. RandomCrop()
resize输入一个int 输出是等比裁剪, randomcrop输入一个int 输出是正方形裁剪【也可以指定高宽】
1-5 代码
py
# 1. ToTensor 把PIL图片类型数据或ndarry numpy数据类型转换为tensor类型数据
from PIL import Image
from cv2 import imread
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter
img_path = 'hymenoptera_data/train/bees/85112639_6e860b0469.jpg'
writer = SummaryWriter('logs')
def totensor():
cv2_np = imread(img_path)
trans_totensor = transforms.ToTensor()
cv2_tensor = trans_totensor(cv2_np)
writer.add_image('totensor', cv2_tensor)
# 2. normalize 用平均值和标准差对张量图像做归一化
def normalize():
'''
output[channel] = (input[channel] - mean[channel]) / std[channel]
:return:
'''
cv2_np = imread(img_path)
trans_totensor = transforms.ToTensor()
cv2_tensor = trans_totensor(cv2_np)
print(cv2_tensor[0][0][0])
trans_norm = transforms.Normalize([1, 2, 1], [1, 1, 6])
norm_tensor = trans_norm.forward(cv2_tensor)
writer.add_image('norm totensor', norm_tensor, 2)
print(norm_tensor[0][0][0])
def resize():
'''
resize 转换图片尺寸 输入需要是PIL格式图片 其他数据类型不对
:return:
'''
img = Image.open(img_path)
print(img, img.size)
# PIL-->resize --> PIL
trans_resize = transforms.Resize((256, 256))
img_resize_PIL = trans_resize.forward(img)
print(img_resize_PIL)
trans_totensor = transforms.ToTensor()
# PIL --> totensor --> tensor
img_resize_PIL = trans_totensor(img_resize_PIL) # tensor
writer.add_image('resize PIL', img_resize_PIL)
# TypeError: img should be PIL Image. Got <class 'torchvision.transforms.transforms.ToTensor'> Got <class 'numpy.ndarray'>
def compose():
'''
可以理解为compose就是一次执行多个transforms的操作
:return:
'''
img = Image.open(img_path)
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image('ori PIL', img_tensor)
print(img)
# trans_resize = transforms.Resize(256)
trans_resize = transforms.Resize(128)
# trans_resize 需要的参数是PIL图片格式,trans_totensor 可以将PIL图片数据转换为tensor数据,compose类将两个操作组合起来,
# 列表的两个transforms操作顺序我当前的torch--1.11.0版本可以互换,有的torch版本不能互换,否则resize会因为使用的不是PIL数据,导致报错
# trans_compose = transforms.Compose([trans_resize, trans_totensor]) # 设置compose需要的参数 都是transforms的类实例化
trans_compose = transforms.Compose([trans_totensor, trans_resize])
img_resize_compose_tensor = trans_compose(img)
print(img_resize_compose_tensor.size()) # tensor
# writer.add_image('compose resize PIL', img_resize_compose_tensor, 1)
writer.add_image('compose resize PIL', img_resize_compose_tensor, 4)
def randomcrop():
'''
只提供一个size值(int) 会裁剪出来一个正方形 size*size
也可以提供序列 指定高宽 (512, 100)
:return:
'''
img = Image.open(img_path)
print(img)
trans_totensor = transforms.ToTensor()
# trans_randomcrop = transforms.RandomCrop(128)
trans_randomcrop = transforms.RandomCrop((128, 200))
trans_compose = transforms.Compose([trans_randomcrop, trans_totensor])
for i in range(10):
img_crop = trans_compose(img)
# writer.add_image("randomcrop", img_crop, i)
writer.add_image("randomcrop2", img_crop, i)
if __name__ == '__main__':
totensor()
normalize()
resize()
compose()
randomcrop()
writer.close()
6. Python魔法函数
Python中的魔法函数是指一些特殊的函数,可以通过对应的魔法方法来实现对对象的特殊操作,例如初始化、属性访问、运算符重载等等
py
#示例代码:
class MyClass:
def __init__(self, items): # 在创建对象时自动调用,用于对象的初始化。
self.items = items
def __str__(self): # 在使用print输出对象时自动调用,返回对象的字符串表示
return "This is MyClass"
def __len__(self): # 返回对象的长度或元素个数,可用于内建函数len()调用。
return len(self.items)
def __getitem__(self, index): # 允许通过索引访问对象的元素,可用于切片操作
return self.items[index]
def __call__(): # 对象通过提供call()方法可以模拟函数的行为,如果一个对象提供了该方法,就可以像函数一样使用它
print("call print")
my_obj = MyClass([1, 2, 3, 4, 5]) # 创建对象时自动调用 __init__ 方法
print(my_obj) # 输出:This is MyClass
print(len(my_obj)) # 输出:5
print(my_obj[2]) # 输出:3
my_obj() # 输出: call print 可以看到,我们在像使用函数一样使用类,实在是很有意思的事