sunpongber

常见的Transforms

使用Transforms其实也就是使用Transforms中各种各样的类,不同的类有不同的作用
为了更好的使用它,我们需要关注3个点,输入、输出、作用

作用一般比较清楚,主要关注输入和输出,因为图片有不同的格式
PIL-->Image.open(),python自带
tensor-->ToTensor(),tensor包所带
narrays-->cv.imread(),opencv包所带

先读取一张图片

from PIL import Image
img = Image.open("dataset/train/bees_image/85112639_6e860b0469.jpg")
print(img)

看看call什么作用,transforms_compose_call_test

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

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

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

返回:

__call__Hellozhangsan
hellolisi
  1. ToTensor的使用
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms

writer = SummaryWriter(log_dir='logs')
img = Image.open("dataset/train/bees_image/85112639_6e860b0469.jpg")
print(img)

trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)

writer.add_image("ToTensor", img_tensor)
writer.close()

现在我们把一个PIL的Image通过transforms中的ToTensor的对象把它变为一个tensor数据类型的Image,然后Image就可以放入tensorboard中
之前的log会存在,可以删除,如何不显示可以CTRL+C退出、删除,然后编译完重新打开端口即可

ToPILImage的使用就是Convert a tensor or an ndarray to PIL Image - this does not scale values(tensor的转换为PIL Image),不常用,这里不再演示

  1. Normalize的使用
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms

writer = SummaryWriter(log_dir='logs')
img = Image.open("dataset/train/bees_image/85112639_6e860b0469.jpg")
print(img)

trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)

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

writer.add_image("Normalize", img_norm)
writer.close()

返回:
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=500x382 at 0x19D0B0496C0>
tensor(0.5725)
tensor(0.1451)
在终端输入tensorboard --logdir=logs,在tensorboard中查看

进行一个夸张一点的
trans_norm = transforms.Normalize([1, 3, 5], [3, 2, 1])
writer.add_image("Normalize", img_norm, 1)
返回:
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=500x382 at 0x19D0B0496C0>
tensor(0.5725)
tensor(-0.1425)
在tensorboard中查看,图片都黑了

归一化一个tensor的Image,就是说需要给入一个平均值和标准差,一般的是RGB,3个通道的图片,transforms能将每一个通道的输入进行归一化

ToTensor时已经将像素范围从0-255变为0-1,因为图片按照tensor的存储顺序存成C H W(通道、长、宽)的图像张量,默认为(3, H, W) ,3通道,设置3个0.5

归一化的公式:output[channel] = (input[channel] - mean[channel]) / std[channel]
(input - 0.5) = 2 * input - 1
input[0, 1]
result[-1, 1]

对于图像数据,像素值通常在 [0, 1] 或 [0, 255] 范围内。将像素值转换到 [-1, 1] 范围可以帮助模型更快地收敛,并且减少不同特征(如颜色通道)之间的差异
对于原始像素值为 0 的像素,归一化后的值为 (0 - 0.5) / 0.5 = -1
对于原始像素值为 1 的像素,归一化后的值为 (1 - 0.5) / 0.5 = 1
这种归一化方式对于许多深度学习模型(如卷积神经网络)来说是一种标准的预处理步骤,可以帮助模型更有效地学习图像特征

  1. Resize的使用
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms

writer = SummaryWriter(log_dir='logs')
img = Image.open("dataset/train/bees_image/85112639_6e860b0469.jpg")

print(img.size)
trans_resize = transforms.Resize((300, 400))
img_resize = trans_resize(img)
print(img_resize)
trans_totensor = transforms.ToTensor()
img_resize = trans_totensor(img_resize)

writer.add_image("Resize", img_resize, 0)
print(img_resize)
writer.close()

resize之前不知道图片尺寸,print(img.size)
返回(500, 382)
resize之后没说输出什么格式的图片,print(img_resize)
返回<PIL.Image.Image image mode=RGB size=400x300 at 0x1F8D837AE60>
转换为totensor的图片格式,print(img_resize)
返回

tensor([[[0.5804, 0.6078, 0.6314,  ..., 0.1922, 0.2078, 0.2118],
         [0.5843, 0.6118, 0.6353,  ..., 0.1961, 0.2039, 0.2039],
         [0.5765, 0.6118, 0.6353,  ..., 0.2078, 0.2118, 0.2118],
         ...,
         [0.4745, 0.4784, 0.4745,  ..., 0.2039, 0.1961, 0.2000],
         [0.4784, 0.4745, 0.4706,  ..., 0.2078, 0.1961, 0.1961],
         [0.4824, 0.4784, 0.4745,  ..., 0.2039, 0.2000, 0.2039]],

        [[0.5922, 0.6000, 0.6275,  ..., 0.1490, 0.1647, 0.1647],
         [0.5922, 0.6039, 0.6275,  ..., 0.1569, 0.1686, 0.1686],
         [0.5882, 0.6118, 0.6275,  ..., 0.1529, 0.1608, 0.1647],
         ...,
         [0.6431, 0.6510, 0.6510,  ..., 0.1843, 0.1843, 0.1882],
         [0.6471, 0.6471, 0.6471,  ..., 0.1882, 0.1882, 0.1922],
         [0.6431, 0.6471, 0.6510,  ..., 0.1882, 0.1882, 0.1922]],

        [[0.4745, 0.5176, 0.5804,  ..., 0.1412, 0.1412, 0.1373],
         [0.4667, 0.5176, 0.5804,  ..., 0.1451, 0.1412, 0.1412],
         [0.4667, 0.5216, 0.5765,  ..., 0.1451, 0.1412, 0.1412],
         ...,
         [0.9098, 0.9098, 0.9059,  ..., 0.1725, 0.1725, 0.1725],
         [0.9137, 0.9098, 0.9098,  ..., 0.1765, 0.1725, 0.1725],
         [0.9098, 0.9137, 0.9137,  ..., 0.1765, 0.1725, 0.1686]]])

Compose - Resize的第二种用法

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

writer = SummaryWriter(log_dir='logs')
img = Image.open("dataset/train/bees_image/85112639_6e860b0469.jpg")

trans_totensor = transforms.ToTensor()
trans_resize_2 = transforms.Resize(300)
trans_compose = transforms.Compose([trans_resize_2, trans_totensor])

img_resize_2 = trans_compose(img)

writer.add_image("Resize", img_resize_2, 1)
writer.close()

给一个数,不改变高和宽的比例,只单纯改变最小边和最长边之间的一个大小关系
Compose()用法,其中的参数需要是一个列表,Python中,列表的表示形式为[数据1, 数据2, ...]
在Compose中数据需要是transforms类型,所以得到,Compose([transforms参数1, transforms参数2, ...])

  1. RandomCrop的使用
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms

writer = SummaryWriter(log_dir='logs')
img = Image.open("dataset/train/bees_image/85112639_6e860b0469.jpg")

trans_totensor = transforms.ToTensor()
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()

也可以传入参数为序列,指定希望输出的裁剪尺寸:
指定高和宽,trans_random = transforms.RandomCrop(128, 256)
重新命名,writer.add_image("RandomCropHW", img_crop, i)

  1. 总结使用方法

重点学会了tensorboard需要tensor数据类型进行显示
最重要的是不同的步数可以看到不同的结果,因为在后面训练过程中有大量数据集,当每训练多少步的时候需要看训练的结果的话可以拖动查看

原始资料地址:
常见的Transforms(一)
常见的Transforms(二)
参考资料地址:
Python - 如何将图片读取为这3种格式:PIL, tensor, narrays
如有侵权联系删除 仅供学习交流使用