Numpy - 将 RGB 图像数据集归一化

4

我的数据集是一个Numpy数组,尺寸为(N,W,H,C),其中N是图像数量,H和W分别是高度和宽度,C是通道数。

我知道有很多工具可以用,但我想只用Numpy来规范化这些图像。

我的计划是计算整个数据集中每个通道的平均值和标准差,然后减去平均值并除以标准差。

假设我们的数据集中有两张图片,这两张图片的第一个通道看起来像这样:

x=array([[[3., 4.],
          [5., 6.]],

          [[1., 2.],
          [3., 4.]]])

计算平均值:

numpy.mean(x[:,:,:,0])
= 3.5

计算标准差:

numpy.std(x[:,:,:,0])
= 1.5

将第一个通道归一化:

x[:,:,:,0] = (x[:,:,:,0] - 3.5) / 1.5

这正确吗?

谢谢!

1个回答

11

看起来不错,但有些NumPy的功能可以让它变得更好。我假设你想单独对每个通道进行归一化。

首先,注意到x有一个方法mean,我们可以写成x[..., 0].mean()而不是np.mean(x[:, :, :, 0])。另外,mean方法接受关键字参数axis,我们可以按以下方式使用:

means = x.mean(axis=(0, 1, 2)) # Take the mean over the N,H,W axes
means.shape # => will evaluate to (C,)

接下来,我们可以像这样从整个数据集中减去平均值:

centered = x - x.mean(axis=(0,1,2), keepdims=True)

请注意这里必须使用keepdims

还有一个x.std的方法也是同样的,所以我们可以在一行中完成整个归一化过程:

z = (x - x.mean(axis=(0,1,2), keepdims=True)) / x.std(axis=(0,1,2), keepdims=True)

查看numpy.ndarray.meannp.ndarray.std文档以获取更多信息。当您调用x.method而不是使用np.method(x)时,np.ndarray.method方法就会生效。


编辑:我后来了解到,当然还有scipy.stats.zscore。不确定这是否是在每个通道上获取z分数的更易读的方式,但有些人可能会更喜欢它:

z = zscore(x.reshape(-1, 3)).reshape(x.shape)

scipy函数只能在一个轴上操作,因此我们首先必须将其重塑为一个NHW x C矩阵,然后再将其重塑回来。


3
好的回答,建议提供Numpy文档链接,这样有兴趣的人就可以阅读文档中关于参数的内容。 - alkasm
如果整个数据集无法适应内存怎么办? - Antonio Sesto
可以通过滚动或在线方式计算均值和标准差,而无需一次性将整个数据集加载到内存中--有数百万个SO问题和其他来源描述了这一点,例如https://dev59.com/PnDXa4cB1Zd3GeqP9CZZ。然后,当您从磁盘加载数据的一部分以供以后使用时,只需将平均值和标准差插入`x.mean(...)`和`x.std(...)`的位置即可。 - mostsquares
我不知道 keepdims 选项,非常实用,谢谢! - Laurin Herbsthofer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接