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) # transformOper(np.array(img))也行, np.uint8(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是游戏a中的人(cpu上用的比较多),tensor是游戏b中的人(gpu上用的比较多),物理世界中人这个本体(Image)可以分别映射到游戏a和游戏b。但你不能说我苦茶一下,b就等于torch.tensor(a)了,这不对,两者的映射关系应该以物理世界的人为基础。因此映射关系是复杂的,所以游戏a中的人numpy.array(Image)
在transforms.ToTensor()的参与下才能成功映射到b。
参考资料:
https://zhuanlan.zhihu.com/p/644074730
https://blog.youkuaiyun.com/weixin_42468475/article/details/121869314