常见的Transforms(二)
1.Resize() 的使用
1.1 作用
resize可以把输入的图片按照输入的参数值重新设定大小。
1.2 所需参数
需要输入想要重新设定的图片大小。
输入的参数类型可以为包含长和宽数值的一个序列(h,w)或者一个整数x。
- 如果输入的参数是一个序列,即长和宽两个整数,则图像会按该长和宽进行resize。
- 如果输入的参数是一个整数x,将图片短边缩放至x,长宽比保持不变。
- 序列:(h,w)高度,宽度
- **一个整数:**不改变高和宽的比例,只单纯改变最小边和最长边之间的大小关系。之前图里最小的边将会匹配这个数(等比缩放)
新版的resize的输入图形类型可以是PIL型或者tensor型
注意:
输出图像可能根据其类型不同而不同:当下采样时,PIL图像的插值和张量略有不同,因为PIL应用了抗锯齿。这可能会导致显著的差异在网络的性能中。因此,最好是训练和服务一个具有相同输入的模型类型。
PyCharm小技巧设置:忽略大小写,进行提示匹配
一般情况下,你需要输入R,才能提示出Resize
我们想设置,即便你输入的是r,也能提示出Resize,也就是忽略了大小写进行匹配提示
File—> Settings—> 搜索case—> Editor-General-Code Completion-去掉Match case前的√—>Apply—>OK
返回值还是 PIL Image
1.3 具体使用
下面给出输入图片类型为PIL和tensor的两张类型的图片resize,使用的图片为狗狗图片,原大小为960*600,resize的输入参数为一个序列(512,512),即经过resize后图片会被缩放成长和宽均为512的正方形大小。
第一种方法
- 将PIL型图片resize
- 将resize后的PIL型图片转换为tensor进行输出
# Resize的使用
print(img.size) # 直接用上面的PIL.Image格式的img,先查看一下原本的size
trans_resize = transforms.Resize((512, 512)) #resize图形为512*512
# img:PIL --> resize --> img_resize:PIL
img_resize = trans_resize(img) # 输出还是PIL Image
# img_resize:PIL --> totensor --> img_resize:tensor(同名,覆盖)
img_resize = trans_totensor(img_resize)
writer.add_image("Resize", img_resize, 0)
print(img_resize)
运行后,在 Terminal 里输入:
tensorboard --logdir=logs
打开tensorboard查看,图片resize后进行了缩放
第二种方法
- 将PIL型图片先转换为tensor型
- 将tensor型图片进行resize
#法二,先将PIL型图片先转换为tensor型,再将tensor型图片进行resize
#把PIL转换为tensor类型
trans_totensor_tool = transforms.ToTensor()
img_tensor = trans_totensor_tool(img)
#resize
trans_resize_tool = transforms.Resize((512,512))
img_tensor_resized = trans_resize_tool(img_tensor)
#输出
writer.add_image("resize2",img_tensor_resized)
刷新tensorboard,可以看到图片经过resize后进行了缩放
1.4输出结果
原始图像:889*500大小,为长方形。
resize后:可以看到两次操作都把图像缩放成了512*512的正方形大小。
2.Compose() 的使用
2.1 作用
可以把几个tranforms组合在一起使用,相当于一个组合器,可以对输入图片一次进行多个transforms的操作。
2.2 参数介绍
Compose() 中的参数需要是一个列表,Python中列表的表示形式为[数据1,数据2,…]
在Compose中,数据需要是transforms类型,所以得到Compose([transforms参数1,transforms参数2,…])
参数1的输出类型必须与参数2的输入类型匹配。 因为compose的工作顺序是从左到右的,第一个参数transform介绍之后再进行第二个transform的操作,所以需要前一个的输出和后一个的输入匹配。
2.3 Compose和Resize的结合使用
我们结合上面resize的学习进行一个compose的使用,这次resize的参数只输入一个数字,512,即会等比例缩放为短边为512大小的图片。
compose负责把ToTensor和resize组合起来,一步到位实现PIL图形到resize后的tensor图形的转换。
# Compose的使用(结合上面resize的学习进行一个compose的使用)
#创建resize工具trans_resize_2,totensor工具直接用上面创建好的trans_totensor即可
trans_resize_2 = transforms.Resize(512) # 将图片短边缩放至512,长宽比保持不变
# PIL --> resize --> PIL --> totensor --> tensor
# compose()就是把两个参数功能整合,第一个参数是改变图像大小,第二个参数是转换类型,前者的输出类型与后者的输入类型必须匹配
trans_compose1 = transforms.Compose([trans_resize_2, trans_totensor])
#为测试参数顺序对compose的影响,写了第2个compose,调换了ToTensor和resize的顺序
trans_compose2 = transforms.Compose([trans_totensor,trans_resize_2,])
# 分别用两个cmpose进行图形转换
img_resize_2 = trans_compose1(img) # 输入需要是PIL Image,第一个compose
img_resize_3 = trans_compose2(img) #第二个compose
writer.add_image("compose",img_resize_2)
writer.add_image("compose", img_resize_3, 1)
注:
为了测试参数顺序对compose的影响,代码中我写了2个compose,分别调换了ToTensor和resize的顺序,结果完全一致,这是因为ToTensor的输出tensor可以作为resize的输入,而resize的输出PIL也可以作为ToTensor的输入,因此无影响。
2.4 结果
运行后,刷新tensorboard,对比step0,step1,图像没有差别,如期进行了缩放
3.RandomCrop() 的使用
3.1 作用
输入PIL Image,把图像按照随机位置进行裁剪。
3.2 参数介绍
参数需要输入想要裁剪成的图片大小。
- sequence:如果输入的是序列(h,w),会按照该长和宽进行裁剪。
- int:如果输入的是一个整数x,则会按照(x,x)的大小裁剪,注意x不能超过待处理图片的短边大小。
(1)以 int 为例:
#RandomCrop()的使用
trans_random = transforms.RandomCrop(500)
trans_compose3 = transforms.Compose([trans_random,trans_totensor])
for i in range(10): #裁剪10个
img_crop = trans_compose3(img) # 输入需要是PIL Image
writer.add_image("RandomCrop",img_crop,i)
输出结果:
(2)以 sequence 为例:
#RandomCrop()的使用,以 sequence 为例
trans_random = transforms.RandomCrop((200,500))
trans_compose_4 = transforms.Compose([trans_random,trans_totensor])
for i in range(10): #裁剪10个
img_crop = trans_compose_4(img)
writer.add_image("RandomCropHW",img_crop,i)
输出结果:
总结
1.关注输入和输出类型
2.多看官方文档
3.关注方法需要什么参数:参数如果设置了默认值,保留默认值即可,没有默认值的需要指定(看一下要求传入什么类型的参数)
4.不知道变量的输出类型可以
直接print该变量
print(type()),看结果里显示什么类型
断点调试 dubug
最后要 totensor,在 tensorboard 看一下结果(tensorboard需要tensor数据类型进行显示)
UsefulTransforms.py完整代码
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
from torchvision.transforms import ToPILImage
writer = SummaryWriter("logs")
img = Image.open("image/pytorch.png") #创建PIL类型图片
print(img) # 可以看到类型是PIL
# ToTensor的使用
trans_totensor = transforms.ToTensor() # 将类型转换为tensor
img_tensor = trans_totensor(img) # img变为tensor类型后,就可以放入TensorBoard当中
writer.add_image("ToTensor", img_tensor)
# ToPILImage的使用
imagePIL = ToPILImage()(img_tensor)
print(imagePIL)
print(img_tensor)
#Normalize的使用,,需要输入均值mean和标准差std
print(img_tensor[0][0][0]) # 第0层第0行第0列
trans_norm = transforms.Normalize([6,3,2],[9,3,5]) # mean,std,因为图片是RGB三信道,故传入三个数
img_norm = trans_norm(img_tensor) # 参数输入的类型要是tensor
print(img_norm[0][0][0])
writer.add_image("Normalize",img_norm,2)#第二步
# Resize的使用
#法一,先将PIL型图片resize,再将resize后的PIL型图片转换为tensor进行输出
print(img.size) # 直接用上面的PIL.Image格式的img,先查看一下原本的size
trans_resize = transforms.Resize((512, 512)) #resize图形为512*512
# img:PIL --> resize --> img_resize:PIL
img_resize = trans_resize(img) # 输出还是PIL Image
# img_resize:PIL --> totensor --> img_resize:tensor(同名,覆盖)
img_resize = trans_totensor(img_resize)
writer.add_image("Resize", img_resize, 0)
print(img_resize)
#法二,先将PIL型图片先转换为tensor型,再将tensor型图片进行resize
#把PIL转换为tensor类型
trans_totensor_tool = transforms.ToTensor()
img_tensor = trans_totensor_tool(img)
#resize
trans_resize_tool = transforms.Resize((512,512))
img_tensor_resized = trans_resize_tool(img_tensor)
#输出
writer.add_image("resize2",img_tensor_resized)
# Compose的使用(结合上面resize的学习进行一个compose的使用)
#创建resize工具trans_resize_2,totensor工具直接用上面创建好的trans_totensor即可
trans_resize_2 = transforms.Resize(512) # 将图片短边缩放至512,长宽比保持不变
# PIL --> resize --> PIL --> totensor --> tensor
# compose()就是把两个参数功能整合,第一个参数是改变图像大小,第二个参数是转换类型,前者的输出类型与后者的输入类型必须匹配
trans_compose1 = transforms.Compose([trans_resize_2, trans_totensor])
#为测试参数顺序对compose的影响,写了第2个compose,调换了ToTensor和resize的顺序
trans_compose2 = transforms.Compose([trans_totensor,trans_resize_2,])
# 分别用两个cmpose进行图形转换
img_resize_2 = trans_compose1(img) # 输入需要是PIL Image,第一个compose
img_resize_3 = trans_compose2(img) #第二个compose
writer.add_image("compose",img_resize_2)
writer.add_image("compose", img_resize_3, 1)
#RandomCrop()的使用,以 int 为例
trans_random = transforms.RandomCrop(500)
trans_compose3 = transforms.Compose([trans_random,trans_totensor])
for i in range(10): #裁剪10个
img_crop = trans_compose3(img) # 输入需要是PIL Image
writer.add_image("RandomCrop",img_crop,i)
#RandomCrop()的使用,以 sequence 为例
trans_random = transforms.RandomCrop((200,500))
trans_compose_4 = transforms.Compose([trans_random,trans_totensor])
for i in range(10): #裁剪10个
img_crop = trans_compose_4(img)
writer.add_image("RandomCropHW",img_crop,i)
writer.close()
)
#RandomCrop()的使用,以 sequence 为例
trans_random = transforms.RandomCrop((200,500))
trans_compose_4 = transforms.Compose([trans_random,trans_totensor])
for i in range(10): #裁剪10个
img_crop = trans_compose_4(img)
writer.add_image(“RandomCropHW”,img_crop,i)
writer.close()