numpy 数组中特定轴上的模式

Mode on a specific axis in numpy array

目标

给定一个图像列表,我想创建一个新图像,其中每个像素都包含输入列表中该位置最常出现的值 (R,G,B)。

详情

输入:长度 >=2 的列表 L。列表中的每个 image/object 都是一个 float32 numpy 数组,维度为 (288, 512, 3),其中 3 表示 R/G/B 颜色通道。

输出:一个具有相同形状 (288,512,3) 的 numpy 数组。如果没有最频繁出现的像素,则可以返回该位置的任何像素。

尝试

image = stats.mode(L)[0][0]

这种方法的问题在于它会单独查看像素的每个 R/G/B 值。但我希望一个像素只有在所有颜色通道都匹配时才被认为与另一个像素相同(即 R1=R2、G1=G2、B1=B2)。

试试这个:

def packRGB(RGB):
    return np.left_shift(RGB, [0, 8, 16]).sum(-1)

def unpackRGB(i24):
    B = np.right_shift(i24, 16)
    G = np.right_shift(i24, 8) - np.left_shift(B, 8)
    R = i24 - np.left_shift(G, 8) - np.left_shift(B, 16)
    return np.stack([R, G, B]).T

def img_mode(imgs_list, average_singles = True):
    imgs = np.array(imgs_list) #(10, 100, 100, 3)
    imgs24 = packRGB(imgs) # (10, 100, 100)
    mode, count = scipy.stats.mode(imgs24, axis = 0) # (1, 100,100)
    mode, count = mode.squeeze(), count.squeeze()  #(100, 100)
    if average_singles:
        out = np.empty(imgs.shape[1:])
        out[count == 1] = np.rint(np.average(imgs[:, count == 1], axis = 0))
        out[count > 1] = unpackRGB(mode[count > 1])
    else:
        out = unpackRGB(mode)
    return out

编辑:修复错误并从您的其他问题中添加选项:Aany value in set if no mode,由于没有除法或舍入,应该更快。 scipy.stats.mode returns 最低值,在本例中为具有最低蓝色值的像素。您可能还想尝试 median,因为 mode 会因输入中非常小的差异而变得不稳定(特别是如果只有十个)

这也会比 Photoshop 的统计功能慢很多(我假设您正在尝试做类似 this 的事情),因为您希望将功能并行化为很好地提高了时间效率。