在numpy中按通道对一批图像进行归一化处理

3
我有一个numpy ndarray,其形状为[batch_size, width, height, num_channels](它们不是RGB图像,但类似于2D场的概念)。
我想对每个通道的图像进行归一化。有没有更多的numpy方法可以做到这一点,而不是下面的方法?特别是我不喜欢循环通道,并且我发现在切片上执行np.min和np.max很奇怪。此外,这个方法被硬编码为仅适用于秩为4的张量,如何使其适应动态秩或通道在动态轴上的情况?
def get_img_ch_min_max(imgs):
    '''return minimum and maximum for each channel of [batch, width, height, channels]'''
    if len(imgs.shape)==3: imgs = np.expand_dims(imgs, axis=-1)
    # iterate each channel
    ch_min = np.array([np.min(imgs[:,:,:,i]) for i in range(imgs.shape[-1])])
    ch_max = np.array([np.max(imgs[:,:,:,i]) for i in range(imgs.shape[-1])])
    return ch_min, ch_max


def normalise_per_channel(imgs):
    '''normalise batch of images per channel, [batch, width, height, channels]'''
    if len(imgs.shape)==3: imgs = np.expand_dims(imgs, axis=-1)
    ch_min, ch_max = get_img_ch_min_max(imgs)
    ch_range = ch_max - ch_min
    imgs_ret = np.copy(imgs)
    for i in range(imgs.shape[-1]): # iterate each channel
        if ch_range[i] > 0: # avoid divide by zero
            imgs_ret[:,:,:,i] = (imgs[:,:,:,i] - ch_min[i]) / ch_range[i]
    imgs_ret = np.squeeze(imgs_ret)
    return imgs_ret
1个回答

1
这是我的尝试,回答您的问题,但没有在您的数据上测试我的解决方案。
我认为关键的想法是使用numpy.amin()(或amax())并指定axis参数。这将有助于避免循环:
rank = 4
ch_mins = np.amin(imgs, axis=tuple(range(rank - 1)))
ch_maxs = np.amax(imgs, axis=tuple(range(rank - 1)))
ch_range = ch_max - ch_min
idx = np.where(ch_range == 0)
ch_mins[idx] = 0
ch_range[idx] = 1
imgs = (imgs - ch_mins) / ch_range

针对“动态轴”的情况,我建议您适当使用newaxis[None,:,None,etc.],如有必要,可以使用numpy.moveaxis()或类似的函数。

谢谢回复。我没有意识到轴参数可以是一个数组,听起来应该可以解决问题。但是我遇到了一个错误:TypeError: only integer scalar arrays can be converted to a scalar index。(我正在使用numpy v14) - memo
好的,如果它是一个元组,它就可以工作,谢谢!(我会进行微调并接受你的答案) - memo
@memo 感谢您尝试并报告错误。我在最后一次编辑中已经修复了它。当然,您始终可以手动指定轴为(0, 1, 2) - AGN Gazer
@备忘录 你尝试修改我的回答了吗?当我想编辑它时,会有一个短暂的消息弹出,告诉我已经有人编辑过了。请随意再试一次。 - AGN Gazer
@memo:我在最后添加了一个提示,关于如何处理“动态轴”。 - AGN Gazer
是的,我曾尝试编辑您的答案以更正轴,但您的编辑更好,谢谢。 - memo

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