gpt4 book ai didi

python - 在 Python 中向移动窗口添加唯一值过滤器

转载 作者:行者123 更新时间:2023-12-01 03:14:02 25 4
gpt4 key购买 nike

我已经找到了两种步幅移动窗口的解决方案,可以计算平均值、最大值、最小值、方差等。现在,我希望按轴添加唯一值函数的计数。通过轴,我的意思是单次计算所有二维数组。

len(numpy.unique(array)) 可以做到,但需要大量迭代来计算所有数组。我可能会使用大至 2000 x 2000 的图像,因此迭代不是一个好的选择。这一切都与性能和内存效率有关。

以下是跨步移动窗口的两种解决方案:

First 直接取自 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 .

def compute_window_mean_and_var_strided(image, window_w, window_h):
w, h = image.shape
strided_image = np.lib.stride_tricks.as_strided(image,
shape=[w - window_w + 1, h - window_h + 1, window_w, window_h],
strides=image.strides + image.strides)
# important: trying to reshape image will create complete 4-dimensional compy
means = strided_image.mean(axis=(2,3))
mean_squares = (strided_image ** 2).mean(axis=(2, 3))
maximums = strided_image.max(axis=(2,3))

variations = mean_squares - means ** 2
return means, maximums, variations

image = np.random.random([500, 500])
compute_window_mean_and_var_strided(image, 20, 20)

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

说明:基本上,我需要一个用于 2D 数组的唯一值过滤器,就像 numpy.ndarray.mean 一样。

谢谢你

亚历克斯

最佳答案

这是一种使用 scikit-image's view_as_windows 的方法用于高效的滑动窗口提取。

涉及的步骤:

  • 获取滑动窗口。

  • reshape 为二维数组。请注意,这将创建一个副本,因此我们将失去 View 的效率,但保持其矢量化。

  • 沿合并 block 轴的轴排序。

  • 获取沿该轴的微分并计算不同元素的数量,当添加 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)

示例运行 -

In [233]: a = np.random.randint(0,10,(6,7))

In [234]: a
Out[234]:
array([[6, 0, 5, 7, 0, 8, 5],
[3, 0, 7, 1, 5, 4, 8],
[5, 0, 5, 1, 7, 2, 3],
[5, 1, 3, 3, 7, 4, 9],
[9, 0, 7, 4, 9, 1, 1],
[7, 0, 4, 1, 6, 3, 4]])

In [235]: sliding_uniq_count(a, [3,3])
Out[235]:
array([[5, 4, 4, 7, 7],
[5, 5, 4, 6, 7],
[6, 6, 6, 6, 6],
[7, 5, 6, 6, 6]])

混合方法

为了使其能够处理非常大的数组,将所有内容容纳到内存中,我们可能必须保留一个循环来迭代输入数据的每一行,如下所示 -

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

混合方法 - 版本 II

混合版本的另一个版本,显式使用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

关于python - 在 Python 中向移动窗口添加唯一值过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42635342/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com