让我们为python的numpy创建Ndimensional pixel binning/bucketing的参考实现

2024-04-26 00:17:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我经常想pixel bin/pixel bucket一个numpy数组,意思是,用一个单独的像素来替换一组N连续像素,这是N替换的像素的总和。例如,从以下值开始:

x = np.array([1, 3, 7, 3, 2, 9])

当bucket大小为2时,将转换为:

^{pr2}$

据我所知,没有专门的numpy函数可以做到这一点(如果我错了,请纠正我!),所以我经常自己滚。对于1d numpy阵列,这还不错:

import numpy as np

def bucket(x, bucket_size):
    return x.reshape(x.size // bucket_size, bucket_size).sum(axis=1)

bucket_me = np.array([3, 4, 5, 5, 1, 3, 2, 3])
print(bucket(bucket_me, bucket_size=2)) #[ 7 10  4  5]

……然而,我很容易对多维的情况感到困惑,最后我一次又一次地为这个“简单”的问题提出自己有缺陷的、半途而废的解决方案。如果我们能建立一个很好的N维参考实现,我会很高兴的。在

  • 最好是函数调用允许沿着不同的轴使用不同的bin大小(可能类似于bucket(x, bucket_size=(2, 2, 3))

  • 最好的解决方案是合理有效的(整形和求和在numpy中相当快)

  • 当一个整数的边缘处理不能很好地将一个整数桶的数量划分成一个效果。

  • 允许用户选择初始箱边缘偏移的加分。

正如Divakar所建议的,以下是我在二维示例中所期望的行为:

x = np.array([[1, 2, 3, 4],
              [2, 3, 7, 9],
              [8, 9, 1, 0],
              [0, 0, 3, 4]])

bucket(x, bucket_size=(2, 2))
= [[1 + 2 + 2 + 3, 3 + 4 + 7 + 9],
   [8 + 9 + 0 + 0, 1 + 0 + 3 + 4]]
= [[8, 23],
   [17, 8]]

……希望我的算术正确;)


Tags: numpysizebinbucketnp整数像素数组
3条回答

要为ndarray事例指定沿每个轴的不同bin大小,可以沿其每个轴迭代使用^{},如下-

def bucket(x, bin_size):
    ndims = x.ndim
    out = x.copy()
    for i in range(ndims):
        idx = np.append(0,np.cumsum(bin_size[i][:-1]))
        out = np.add.reduceat(out,idx,axis=i)
    return out

样本运行-

^{pr2}$

从阿苏大步走来:

x = array([[1, 2, 3, 4],
           [2, 3, 7, 9],
           [8, 9, 1, 0],
           [0, 0, 3, 4]])

from numpy.lib.stride_tricks import as_strided     
def bucket(x,bucket_size):
      x=np.ascontiguousarray(x)
      oldshape=array(x.shape)
      newshape=concatenate((oldshape//bucket_size,bucket_size))
      oldstrides=array(x.strides)
      newstrides=concatenate((oldstrides*bucket_size,oldstrides))
      axis=tuple(range(x.ndim,2*x.ndim))
      return as_strided (x,newshape,newstrides).sum(axis)

如果一个维度没有平均地划分为相应的x维度,则剩余的元素将丢失。在

验证:

^{pr2}$

我想你可以用skimage的^{}来做大部分精细的工作。这个函数是implemented using ^{},所以它非常有效(它只是改变步幅信息来重塑数组)。因为它是用Python/NumPy编写的,所以如果没有安装skimage,您可以随时复制代码。在

在应用该函数之后,只需要求整形数组的N个尾轴的和(其中N是bucket_size元组的长度)。这里有一个新的bucket()函数:

from skimage.util import view_as_blocks

def bucket(x, bucket_size):
    blocks = view_as_blocks(x, bucket_size)
    tup = tuple(range(-len(bucket_size), 0))
    return blocks.sum(axis=tup)

然后举例来说:

^{pr2}$

相关问题 更多 >