在神经网络中,图像被表示成[c, h, w]
格式或者[n, c, h, w]
格式,但如果想要将图像以np.ndarray
形式输入,因np.ndarray
默认将图像表示成[h, w, c]
个格式,需要对其进行转化。
n:样本数量
c:图像通道数
w:图像宽度
h:图像高度
np.ndarray如何表示图像
我们可以用PIL打开一张图像,然后通过array()
方法将其转为np.ndarray
形式,最后打印出它的shape
即能得到图像时如何存储在np.ndarray
中的。
from PIL import Image
imoprt numpy as np
img_path = ('./test.jpg')
img = Image.open(img_path)
img_arr = np.array(img)
print(img_arr.shape)
# 输出的结果是(500, 300, 3)
从上面的试验结果我们可以知道,图像以[h, w, c]的格式存储在np.ndarray
中的。
np.ndarray与Tensor中图像格式区别
两者均以三维数组来表示一张图像,他们的区别在于图像信息被保存在数组中的不同位置,具体来说:
-
np.ndarray
的[h, w, c]
格式:数组中第一层元素为图像的每一行像素,第二层元素为每一列像素,最后一层元素为每一个通道的像素值,它将图片中的每一个像素作为描述单元,记录它三个通道的像素值。 -
Tensor
的[c, h, w]
格式:数组中第一层元素为图像的三个通道,第二层元素为某个通道上的一行像素,第三层为该通道上某列的像素值,它将图像某个通道的某行像素值作为描述单元。
上面的说法可能有点抽象,我们可以用图像来说明两者的区别:
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)
以上代码模拟生成的图像如下图所示,图中有5行4列总共20个像素。
上图的所有像素及其像素值如下图所示,[h, w, c]
格式。可以看出,最里层的括号内为单个像素在三个通道上的像素值。
如果以[c, h, w]
格式表示的话,应该是下图这样的:
如何从[w, h, c]转为[c, w, h]
可以借助numpy
的transpose()
函数来实现这个转换。是的只要像下面简简单单的一句话即可实现。
image_chw = np.transpose(image_hwc, (2,0,1))
以某维度为(3, 2, 3),即3行2列共6个像素的图像转换为例,简要地说明一下上述语句产生的转换过程:
# step 1: 转换前的图像及其像素值
[[[ 33 155 80]
[155 245 29]]
[[ 25 238 206]
[164 99 182]]
[[213 21 194]
[ 11 9 124]]]
# step 2: 轴与索引之间的对应关系
意义 轴 索引 --> 索引 轴 意义
高 3 0 2 3 通道
宽 2 1 0 3 高
通道 3 2 1 2 宽
# step 3: 转换过程
1. 其实数据可以看做是一堆无序的数据,轴的存在让这些数据按照一定层级及次序排布
2. 转换前的数据是这样排布的,先按照图像高分成3堆,对这3堆的每一堆按照图像图像宽分2堆,分好的2堆分别按照通道数分成3堆
3. 转换后的数据排布顺序变了,它先按照通道数分成3堆,分好的3堆各自按照图像高分成3堆,再按照图像宽分成2堆。
# step 4: 转换结果
[[[ 33 155]
[ 25 164]
[213 11]]
[[155 245]
[238 99]
[ 21 9]]
[[ 80 29]
[206 182]
[194 124]]]
transpose()
的说明及具体的转换原理,可以参考文章《转置(transpose)和轴对换》,其他一些转换方式可以参考文章《图像通道转换[n c h w] 转 [n h w c]》
参考资料
[1] https://www.cnblogs.com/sunshinewang/p/6893503.html
[2] https://blog.csdn.net/zhangxin4832/article/details/83015480