pytorch初学笔记(四):常见的Transforms使用(ToTensor、Normalize、Resize、Compose、RandomCrop)

目录


小技巧:如何取消在pycharm中敲代码时的大小写匹配

一、 Python中内置函数__call__详解

该方法的功能类似于在类中重载 () 运算符,使得类实例对象可以像调用普通函数那样,以“对象名()”的形式使用,而无需使用对象名.方法名方式来调用方法。 

下面使用新建一个CallTest.py文件来测试call方法。

class Person:
    def __call__(self, name):
        print("调用内置__call__方法  "+name)

    def hello(self,name):
        print("调用hello方法  "+name)

p = Person()
p("zhangsan")
p.hello("lisi")

可以看到:

  • 当传入“zhangsan”字符串时,使用的是:对象名()形式进行方法调用,调用了内置call方法。
  • 当传入“lisi”字符串时,使用的是:对象名.方法名()形式进行方法调用,调用的是hello方法。

因此内置call方法可以使用对象名()形式进行调用,更加方便。

二. ToTensor

具体ToTensor的使用可以见上一章笔记:(4条消息) pytorch初学笔记(三)Tranforms的使用_好喜欢吃红柚子的博客-CSDN博客 

需要注意的是:

  • ToTensor作用:Convert a “PIL Image“ or “numpy.ndarray“ to tensor
  • add_image()方法可接受的图像类型:img_tensor (torch.Tensor, numpy.array, or string/blobname): Image data
     
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms


writer = SummaryWriter("logs")

img = Image.open("image/dog.jpg")
tensor_tool = transforms.ToTensor()
img_tensor = tensor_tool()

writer.add_image("test",img)

三、归一化Normalize

1. Normalize作用

T.Normalize(mean, std)

输入(channel,height,width)形式的tensor,并输入每个channel对应的均值和标准差作为参数,函数会利用这两个参数分别将每层标准化(使数据均值为0,方差为1)后输出。

 2. 所需参数

  • mean:(list)长度与输入的通道数相同,代表每个通道上所有数值的平均值。
  • std:(list)长度与输入的通道数相同,代表每个通道上所有数值的标准差。

3. 计算方法

3.1 计算公式 

3.2 参数传入0.5的含义 

有时我们会设置传入的mean和std为固定值0.5,是因为把0.5代入如下公式,

可以得到:

output = 2 * input -1

 如果我们的输入在[0,1]之间,经过归一化之后结果即可在[-1 , 1]之间。

作用:将两个参数都设置为0.5并与transforms.ToTensor()一起使用可以使将数据强制缩放到[-1,1]区间上

4. 归一化应用

4.1 步骤  

  1.  创建PIL型图片
  2. 使用ToTensor转换为tensor型对象
  3. 使用transforms.Normalize(means, std )实例化Normalize对象norm_tool中
  4. 把tensor图像传入norm_tool中进行归一化处理
  5. 使用tensorboard可视化图像

4.2 代码 

from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms


writer = SummaryWriter("logs")

img = Image.open("image/dog.jpg")
tensor_tool = transforms.ToTensor()
img_tensor = tensor_tool(img)

writer.add_image("ToTensor",img_tensor)

#normalized的使用,需要输入均值和标准差

trans_norm = transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
img_norm = trans_norm(img_tensor)

writer.add_image("Normalize",img_norm)


writer.close()

4.3 结果可视化 

结果如下,可以看到经过归一化后的图片产生了明显的变化。

4.4 进阶版代码

为了让归一化结果更加明显,我们创建3个step,并且依次修改不同的mean和std,查看对应结果。 

from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms


writer = SummaryWriter("logs")

img = Image.open("image/dog.jpg")
tensor_tool = transforms.ToTensor()
img_tensor = tensor_tool(img)

writer.add_image("ToTensor",img_tensor)

#normalized的使用,需要输入均值和标准差

norm_tool = transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
img_norm = norm_tool(img_tensor)
writer.add_image("Normalize",img_norm)

norm_tool = transforms.Normalize([1,3,5],[3,1,2])
img_norm = norm_tool(img_tensor)
writer.add_image("Normalize",img_norm,1)

norm_tool = transforms.Normalize([2,5,3],[1,5,6])
img_norm = norm_tool(img_tensor)
writer.add_image("Normalize",img_norm,2)

writer.close()

可以看到每一个step的图片都是不一样的。

四、Resize

1. 作用

resize可以把输入的图片按照输入的参数值重新设定大小。

2.  所需参数

需要输入想要重新设定的图片大小。

 输入的参数类型可以为包含长和宽数值的一个序列(h,w)或者一个整数x。 

size (sequence or int): Desired output size. If size is a sequence like
    (h, w), output size will be matched to this. If size is an int,
    smaller edge of the image will be matched to this number.
  • 如果输入的参数是一个序列,即长和宽两个整数,则图像会按该长和宽进行resize。
  • 如果输入的参数是一个整数x,将图片短边缩放至x,长宽比保持不变。

!!!   新版的resize的输入图形类型可以是PIL型或者tensor型   !!!

warning:
    The output image might be different depending on its type: when downsampling, the interpolation of PIL images and tensors is slightly different, because PIL applies antialiasing. This may lead to significant differences in the performance of a network. Therefore, it is preferable to train and serve a model with the same input types.

注意:

输出图像可能根据其类型不同而不同:当下采样时,PIL图像的插值和张量略有不同,因为PIL应用了抗锯齿。这可能会导致显著的差异在网络的性能中。因此,最好是训练和服务一个具有相同输入的模型类型。

3. 具体使用

    下面给出输入图片类型为PIL和tensor的两张类型的图片resize,使用的图片为狗狗图片,原大小为960*600,resize的输入参数为一个序列(512,512),即经过resize后图片会被缩放成长和宽均为512的正方形大小。

    由于输入类型为PIL型图片,后续使用add_image方法时需要再把PIL型转换为tensor型,因此我们的操作分为两步,有两种实现方法。

3.1 第一种方法

  1. 将PIL型图片resize
  2. 将resize后的PIL型图片转换为tensor进行输出 
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms


writer = SummaryWriter("log")
img_path = "image/dog.jpg"
#创建PIL类型图片
img_PIL = Image.open(img_path)
#resize图形为512*512
trans_resize_tool = transforms.Resize((512,512))
img_resized_PIL = trans_resize_tool(img_PIL)
#将resize后的PIL图形转换成tensor
trans_totensor_tool = transforms.ToTensor()
img_resized_tensor = trans_totensor_tool(img_resized_PIL)
#使用tensorboard输出
writer.add_image("resize",img_resized_tensor)
writer.close()

3.2 第二种方法

  1. 将PIL型图片先转换为tensor型
  2. 将tensor型图片进行resize
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms


writer = SummaryWriter("log")
img_path = "image/dog.jpg"
#创建PIL对象
img_PIL = Image.open(img_path)
#把PIL转换为tensor类型
trans_totensor_tool = transforms.ToTensor()
img_tensor = trans_totensor_tool(img_PIL)
#resize
trans_resize_tool = transforms.Resize((512,512))
img_tensor_resized = trans_resize_tool(img_tensor)
#输出
writer.add_image("resize2",img_tensor_resized)
writer.close()

4. 输出结果

原始图像:960*600大小,为长方形。 

 resize后:可以看到两次操作都把图像缩放成了512*512的正方形大小,。

     

五、Compose

1. 作用 

可以把几个tranforms组合在一起使用,相当于一个组合器,可以对输入图片一次进行多个transforms的操作。

看下图example中给出的例子,该compose把transforms中的CenterCrop和ToTensor组合在了一起。 作用即为:可以先把图片中心裁剪为10的大小,然后再把图片转换为tensor类型。

  

2. 参数介绍

  • compose中传入的参数需要是一个列表,列表中的数据类型是transforms型。
  • 参数1的输出类型必须与参数2的输入类型匹配。 

因为compose的工作顺序是从左到右的,第一个参数transform介绍之后再进行第二个transform的操作,所以需要前一个的输出和后一个的输入匹配。

3. Compose和Resize的结合使用

我们结合上面resize的学习进行一个compose的使用,这次resize的参数只输入一个数字,300,即会等比例缩放为短边为300大小的图片。

compose负责把ToTensor和resize组合起来,一步到位实现PIL图形到resize后的tensor图形的转换。

注:

为了测试参数顺序对compose的影响,代码中我写了2个compose,分别调换了ToTensor和resize的顺序,结果完全一致,这是因为ToTensor的输出tensor可以作为resize的输入,而resize的输出PIL也可以作为ToTensor的输入,因此无影响。

from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms


writer = SummaryWriter("log")
img_path = "image/dog.jpg"
#创建PIL对象
img_PIL = Image.open(img_path)
#创建totensor和resize工具
trans_totensor_tool =transforms.ToTensor()
trans_resize_tool =transforms.Resize(300)
#compose
trans_compose_tool1 = transforms.Compose([trans_totensor_tool,trans_resize_tool])
trans_compose_tool2 = transforms.Compose([trans_resize_tool,trans_totensor_tool])
#图形转换
img_tensor_resized = trans_compose_tool1(img_PIL)

writer.add_image("compose",img_tensor_resized)
writer.add_image("compose",img_tensor_resized,1)

writer.close()

4. 结果

图片如期进行了缩放。 

六、RandomCrop 随机裁剪

1. 作用

把图像按照随机位置进行裁剪。

2. 参数介绍

参数需要输入想要裁剪成的图片大小。

  • 如果输入的是序列(h,w),会按照该长和宽进行裁剪。
  • 如果输入的是一个整数x,则会按照(x,x)的大小裁剪。

3. 具体使用

结合compose进行使用,完成10张大小为512*512的图片的随机裁剪。

需要使用到for循环。

from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms

writer = SummaryWriter("log")
img_path = "image/dog.jpg"
#创建PIL对象
img_PIL = Image.open(img_path)
#创建工具
trans_totensor_tool = transforms.ToTensor()
trans_randomcrop_tool = transforms.RandomCrop(512)
#compose
trans_compose_tool = transforms.Compose([trans_totensor_tool,trans_randomcrop_tool])
for i in range(10):
    img_tensor_ramdomcroped = trans_compose_tool(img_PIL)
    writer.add_image("randomcrop",img_tensor_ramdomcroped,i)

writer.close()

4. 结果

可以看到step一共有10步,而且每一步中的小狗位置都是不一样的,实现了随机裁剪的功能。 

    

      

七、transforms使用总结

参考文章

(4条消息) pytorch个人学习笔记(2)—Normalize()参数详解及用法_吃米的鹰的博客-CSDN博客_normalize参数

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
社会演员多的头像社会演员多普通用户
上一篇 2023年10月18日
下一篇 2023年10月18日

相关推荐