Python 带模式功能的块缩减(下采样)3D阵列

Python 带模式功能的块缩减(下采样)3D阵列,python,numpy,scikit-image,downsampling,Python,Numpy,Scikit Image,Downsampling,我想通过获取原始值中最频繁的值(模式),对3d数组进行下采样。经过一些研究,我在skimage库中发现了block\u reduce函数。例如,如果我想取块的平均值,我可以很容易地做到: from skimage.measure import block_reduce image = np.arange(4*4*4).reshape(4, 4, 4) new_image = block_reduce(image, block_size=(2,2,2), func=np.mean, cval=np

我想通过获取原始值中最频繁的值(模式),对3d数组进行下采样。经过一些研究,我在
skimage
库中发现了
block\u reduce
函数。例如,如果我想取块的平均值,我可以很容易地做到:

from skimage.measure import block_reduce
image = np.arange(4*4*4).reshape(4, 4, 4)
new_image = block_reduce(image, block_size=(2,2,2), func=np.mean, cval=np.mean(grades))
在我的例子中,我想把func参数传递给mode函数。但是,numpy没有模式函数。根据文档,传递的函数应该接受“axis”作为参数。我尝试了一些变通方法,比如编写自己的函数,并将
np.unique
np.argmax
组合,以及将
scipy.stats.mode
作为函数传递。他们都失败了

我编写了一些嵌套for循环来实现这一点,但对于大型数组来说,它的速度太慢了。有没有一个简单的方法可以做到这一点?我不一定需要使用sci工具包图像库


提前谢谢。

让我们先假设输入图像形状可被
块大小
整除,即相应的形状尺寸可被
块大小
的每个大小参数整除

因此,作为预处理,我们需要从输入的
图像
中去掉块,如下所示-

def blockify(image, block_size):
    shp = image.shape
    out_shp = [s//b for s,b in zip(shp, block_size)]
    reshape_shp = np.c_[out_shp,block_size].ravel()
    nC = np.prod(block_size)
    return image.reshape(reshape_shp).transpose(0,2,4,1,3,5).reshape(-1,nC)
接下来,对于
模式
查找的特定情况,我们将使用aglongWith
argmax
-

# https://stackoverflow.com/a/46256361/ @Divakar
def bincount2D_vectorized(a):    
    N = a.max()+1
    a_offs = a + np.arange(a.shape[0])[:,None]*N
    return np.bincount(a_offs.ravel(), minlength=a.shape[0]*N).reshape(-1,N)

out = bincount2D_vectorized(blockify(image, block_size=(2,2,2))).argmax(1)
或者,我们可以使用-


最后,如果整除性的初始假设不成立,我们需要使用适当的pad值进行填充。同样,我们可以使用
np.pad
,作为
blockify
方法的一部分。

非常感谢,它工作得非常好。我不完全理解行
如何返回image.reformate(reformate_shp).transpose(0,2,4,1,3,5).reformate(-1,nC)
工作。在转置函数中,这些数字是从哪里来的?@user2847666我们基本上是在重塑,将每个轴分成两个,然后转置轴,将块放入相邻的内存位置。这应该有助于理解这些概念-。
out = mode(blockify(image, block_size=(2,2,2)), axis=1)[0]