在Python中添加一个独特的值过滤器来移动窗口

2024-09-30 01:19:52 发布

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

我已经找到了两种可以计算平均值、最大值、最小值、方差等的跨距移动窗口的解决方案。现在,我希望通过轴添加一个唯一值函数的计数。我指的是在一个过程中计算所有二维阵列。在

莱恩(纽比。独一无二(array)可以实现,但需要大量迭代来计算所有数组。我可能使用大到2000 x 2000的图像,所以迭代不是一个好的选择。这一切都是关于性能和记忆的有效性。在

这里有两种解决方案可以帮助您快速移动窗口:

第一个直接取自Erik Rigtorp的http://www.mail-archive.com/numpy-discussion@scipy.org/msg29450.html

import numpy as np

def rolling_window_lastaxis(a, window):
    if window < 1:
       raise ValueError, "`window` must be at least 1."
    if window > a.shape[-1]:
       raise ValueError, "`window` is too long."
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

def rolling_window(a, window):
    if not hasattr(window, '__iter__'):
        return rolling_window_lastaxis(a, window)
    for i, win in enumerate(window):
        if win > 1:
            a = a.swapaxes(i, -1)
            a = rolling_window_lastaxis(a, win)
            a = a.swapaxes(-2, i)
    return a

filtsize = (3, 3)
a = np.zeros((10,10), dtype=np.float)
a[5:7,5] = 1

b = rolling_window(a, filtsize)
blurred = b.mean(axis=-1).mean(axis=-1)

第二个来自Alex Rogozhnikov,电话:http://gozhnikov.github.io/2015/09/30/NumpyTipsAndTricks2.html。在

^{pr2}$

有没有办法在一个或两个解决方案中添加/实现一个唯一值函数的计数?在

<2D>基本上需要一个唯一的数组,比如一个过滤器平均数. 在

谢谢你

亚历克斯


Tags: 函数numpyhttpreturnifnp数组解决方案
2条回答

np.mean在给定轴上操作,而不进行任何复制。只看as_strided数组的形状,它看起来比原始数组大得多。但是因为每个“窗口”都是一个视图,所以它不会占用任何额外的空间。像mean这样的还原运算符可以很好地处理这种视图。在

但是请注意,您的第二个示例警告reshape。它将创建一个副本;它复制所有这些窗口中的值。在

unique开头为

ar = np.asanyarray(ar).flatten()

所以马上就要做一个重塑的拷贝。它是一个拷贝,并且是1d。然后它对元素进行排序,寻找重复项等等

有很多方法可以找到unique行,但它们需要将行转换为大型结构化数组元素。实际上是将2d数组转换为unique可以使用的1d。在

这里有一种使用^{}'s ^{}的方法,可以有效地提取滑动窗口。在

涉及的步骤:

  • 推拉窗户。

  • 重塑为二维阵列。{但是我们要保持这个向量化的效率。

  • 沿合并块轴的轴排序。

  • 沿着这个轴求微分并计算不同元素的数量,当加上1时,这将是每个滑动窗口中唯一值的计数,从而得到最终的预期结果。

执行方式如下-

from skimage.util import view_as_windows as viewW

def sliding_uniq_count(a, BSZ):
    out_shp = np.asarray(a.shape) - BSZ + 1
    a_slid4D = viewW(a,BSZ)    
    a_slid2D = np.sort(a_slid4D.reshape(-1,np.prod(BSZ)),axis=1)    
    return ((a_slid2D[:,1:] != a_slid2D[:,:-1]).sum(1)+1).reshape(out_shp)

样本运行-

^{pr2}$

混合方法

为了使它能与非常大的数组一起工作,为了将所有内容都放入内存中,我们可能需要保持一个循环,它将沿着输入数据的每一行进行迭代,如下-

def sliding_uniq_count_oneloop(a, BSZ):
    S = np.prod(BSZ)
    out_shp = np.asarray(a.shape) - BSZ + 1
    a_slid4D = viewW(a,BSZ)    
    out = np.empty(out_shp,dtype=int)
    for i in range(a_slid4D.shape[0]):
        a_slid2D_i = np.sort(a_slid4D[i].reshape(-1,S),-1)
        out[i] = (a_slid2D_i[:,1:] != a_slid2D_i[:,:-1]).sum(-1)+1
    return out

混合方法-第二版

混合1的另一个版本,显式使用np.lib.stride_tricks.as_strided-

def sliding_uniq_count_oneloop(a, BSZ):
    S = np.prod(BSZ)
    out_shp = np.asarray(a.shape) - BSZ + 1   
    strd = np.lib.stride_tricks.as_strided
    m,n = a.strides
    N = out_shp[1]
    out = np.empty(out_shp,dtype=int)
    for i in range(out_shp[0]):
        a_slid3D = strd(a[i], shape=((N,) + tuple(BSZ)), strides=(n,m,n))
        a_slid2D_i = np.sort(a_slid3D.reshape(-1,S),-1)
        out[i] = (a_slid2D_i[:,1:] != a_slid2D_i[:,:-1]).sum(-1)+1
    return out

相关问题 更多 >

    热门问题