Transforms的使用

发布时间 2023-07-13 00:11:19作者: 码头牛牛

一、Transforms的结构及用法

  • 导入transforms
from torchvision import transforms
  • 作用:图片输入transforms后,可以得到一些预期的变换

1. Transforms的python用法

写在前面:tensor数据类型

通过transforms.ToTensor去说明两个问题:第一,transforms该如何使用;第二,Tensor数据类型相较于普通数据类型有什么区别,为什么需要tensor这个数据类型。

(1)将PIL或numpy.ndarray类型的图片转化为tensor数据类型

具体方法:transforms.Totensor()

from torchvision import transforms
tensor_trans=transforms.ToTensor()  #创建transforms.ToTensor()工具
tensor_img=tensor_trans(pic)   #pic为要转化为tensor类的PIL或numpy.ndarray类型的图像数据

举例:

from torchvision import transforms
from PIL import Image

#读入图像如果读取绝对路径要把\改为\\,如果读取相对路径,则没有这样的困扰
img_path="E:\\Desktop\\hymenoptera_data\\hymenoptera_data\\train\\ants\\0013035.jpg"  #图片路径
img=Image.open(img_path)
print(img)

#将PIL类型图片转化为tensor类型的图片
tensor_trans=transforms.ToTensor()
tensor_img=tensor_trans(img)
print(tensor_img)

#将numpy.ndarray类型的图片转化为tensor类型
import cv2
cv_img=cv2.imread(img_path)  #将图片转化为ndarray数据
tensor_cv_img=tensor_trans(cv_img)
print(tensor_cv_img)

补充:如何读取tensor类型的图片数据

  • 方法:同样是上一篇提到的SummaryWriter中的add_image函数。下面是一个代码实例。
from torch.utils.tensorboard import SummaryWriter
writer=SummaryWriter("logs")
writer.add_image("Tensor_img",tensor_img)
writer.close()

(2)为什么需要tensor数据类型?

  • tensor数据类型内部包含了神经网络理论基础需要的一些参数

二、常见的Transforms

功能 数据类型 对应函数
输入 PIL Image.open()
输出 tensor Totensor()
作用 narrays cv.imread()

1. Compose类详解

  • 主要作用:将不同的transforms结合到一起,不同类型的数据先经过一个中心裁剪,再合成一个tensor类型的数据

(1)关于Compose类中__call__函数的一些说明

随便写个类举例子:

class Person:
    def __call__(self, name):
        print("__call__ "+"Hello "+name)

    def hello(self,name):
        print("hello "+name)

person=Person()
person("zhangsan")     #[Run] __call__ Hello zhangsan
person.hello("lisi")   #[Run] hello lisi

总结:

  • 像def __call__这样的函数是不需要用”.函数名“这样的方式去调用的,可以直接使用”对象名(参数)“这样的方法去调用

  • 但def hello这样的函数需要用”对象名.函数(参数)“的形式调用

(2)Compose调用例子

from torchvision import transforms
img=transforms.compose([transforms.CenterCrop(10),transforms.ToTensor()])

2. ToTensor类详解

  • 上面有提到,Totensor的主要作用为将图像数据转化为tensor类型

(1)ToTensor输入数据类型

只支持输入以下两类的数据:

  • PIL类型的图像数据

  • numpy.ndarray类型的图像数据

(2)Totensor的使用

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

img=Image.open("E:\\Desktop\\hymenoptera_data\\hymenoptera_data\\train\\ants\\0013035.jpg")   #读取图片

writer=SummaryWriter("logs")

#Totensor的使用
trans_totensor=transforms.ToTensor()
img_tensor=trans_totensor(img)   #将PIL类型的图片转化为tensor类型
writer.add_image("ToTensor",img_tensor)  #将tensor数据类型的图像可视化
writer.close()

3. ToPILImage类详解

  • 主要作用:将tensor类型的图像数据转化为PIL类型

  • 支持两种类型数据的输入:tensor、numpy.ndarray

  • 返回:一个PIL的Image

4. Normalize类详解

  • 主要作用:归一化tensor Image,并输入该组图像的均值或标准差,进行归一化处理

  • 归一化公式:

    \[input(channel)=\frac{input(channel)-mean(channel)}{std(channel)} \]

(1)Normalize输入图像数据类型

  • 必须为tensor类型

(2)Normalize的使用

from PIL import Image
from torchvision import transforms

img=Image.open("E:\\Desktop\\hymenoptera_data\\hymenoptera_data\\train\\ants\\0013035.jpg")   #读取图片

#Normalize的使用
trans_norm=transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])  #设置mean和std,因为是三通道数据,所以输入维度有3维
img_norm=trans_norm(img_tensor)  #标准化tensor图像数据类型
writer.add_image("Normalize",img_norm)  #将标准化后的图像可视化
writer.close()

可以对比原来的图片(下)和标准化后的图片(上):颜色都变了诶!

从代码上看不出啥东西,所以这里从标准化计算公式的角度去解释:

  • 代码中设定的均值mean和std都是0.5,那么有:

    \[\frac{input-0.5}{0.5}=2×input-1 \]

  • 这条公式的意义在于:假如\(input\)图片像素值在\([0,1]\)这个范围内,那么标准化后会变成\([-1,1]\)这样一个范围内的图像数据

  • 用下面的代码验证这条公式:

print(img_tensor[0][0][0])  #[Run] tensor(0.8275)
trans_norm=transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])  #设置mean和std,因为是三通道数据,所以输入维度有3维
img_norm=trans_norm(img_tensor)  #标准化tensor图像数据类型
print(img_norm[0][0][0])    #[Run] tensor(0.6549)  0.6549=2*0.8275-1
  • 可以看出:\(input=0.8275, mean=0.5, std=0.5\),输出的结果恰好是\(2×0.8275=0.6549\)