首页 > 其他分享 >【PIL】Torch.tensor和PIL.Image之间互相转换

【PIL】Torch.tensor和PIL.Image之间互相转换

时间:2024-11-11 22:48:36浏览次数:3  
标签:PIL tensor img Image print np image

A. 格式转换过程

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import torch
from torchvision import transforms
img = Image.open("test.png")
# 查看shape
print(np.array(img).shape)
# 得到 (936, 1809, 4),如果要转化成神经网络可读的格式,我们要转化成(4,936,1809)

transformOper = transforms.Compose([
    transforms.ToTensor()
])
img_tensor = transformOper(img)
print(img_tensor.shape) # (4,936,1809)

在这里插入图片描述

Tensor怎么转image?

torchvision.transforms.functional.to_pil_image(tensor)

B. 讨论

讨论a. Image对象的尺寸怎么输出?(w, h)?

1. Image对象输出图片尺寸使用size成员变量

img = Image.open("test.png")
print(img.size)

输出(1809, 936) #(w,h)

请添加图片描述

2. 没有size函数

img = Image.open("test.png")
print(img.size())

报错 TypeError: 'tuple' object is not callable

因为不可调用一个(w,h)()函数

3. Image对象没有shape函数

img = Image.open("test.png")
print(img.shape())

报错AttributeError: 'PngImageFile' object has no attribute 'shape'.

讨论b. np.array (Image)啥尺寸格式?

img = Image.open("test.png")
print(np.array(img).shape)

输出 (936, 1809, 4) # 真彩图

请添加图片描述

讨论c. array转tensor的底层实现.

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt


# 用随机数模拟一张图像
image = np.random.randint(256, size=60)
image = image.reshape((5,4,3))
image_hwc = np.uint8(image)

# 展示图像
image_show = Image.fromarray(image_hwc)
plt.imshow(image_show)
plt.show()

# 打印图像像素值,[h, w, c]格式
print(image_hwc)

# 打印像素值,[c, h, w]格式
image_chw = np.transpose(image_hwc, (2,0,1))
print(image_chw)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
【讨论c思考】所以数据只是一坨,不同的工具相当于是把数据按不同的方式规整起来。即,数据到整合工具之间的映射是不定的,即一张图片可能对应(c,h,w) / (w,h)/ (h,w,c)等多种规整形式。而显示出来的矩阵和对应规整形式的尺寸映射是单一的,即上图的矩阵一定对应的是(3, 5, 4)这个尺寸,上上图的矩阵一定对应的是(5,4,3)这个矩阵。
划分坨的方式:【c,h,w】1. tensor,按通道分成不同的堆,每堆中再按照高分成不同的堆(每一堆就是每一行),每堆中再按照宽分成不同的堆。【h,w,c】2. numpy,按照高分成不同的堆(每一堆就是每一行),每堆中再按照宽分成不同的堆,每堆中再按照通道分成不同的堆。尺寸组合[c,h,w]就和数据组织原理联系起来了![h,w,c]也是同理!
numpy到tensor格式转换底层实现:把numpy.array中第一大竖列拿出来bia到tensor的第一个通道各行。第二大竖列之后同理。

总结

注意1:

以后千万不要直接torch.tensor(numpy.array(Image.open('xx.png')。打个比方,numpy是现实世界的人(cpu上用的比较多),tensor是vr中的虚拟人物(gpu上用的比较多),人这个本体是联系两者的映射关系。transform.toTensor()可以让物理世界的人登录对应的虚拟账号,由于映射"非线性",所以扭曲后的信息格式肯定有所改变,但是信息没错。如果直接torch.tensor(),那就相当于登错号了,映射成了别的人的账号,那就出乱子了。有人说:那反正这里的映射关系是固定的,网络肯定能感知到吧?这点我暂时这么认为:你总要用别人的代码的,别人的格式是按照正确的登录方式去处理的,两段代码的数据处理对不齐,会出问题。除此以外,你用别人的权重和网络架构,自己写数据处理代码,也会出问题的,因为别人的是3,你的是5([5,4,3]的numpy直接torch.tensor了)。再除此以外,别人用你的权重,自己写数据处理代码,也会出问题,因为你的c是5,别人的是3。

参考资料:
https://zhuanlan.zhihu.com/p/644074730
https://blog.csdn.net/weixin_42468475/article/details/121869314

标签:PIL,tensor,img,Image,print,np,image
From: https://blog.csdn.net/hututufandou/article/details/143695304

相关文章