Numpy:用相邻元素的平均值替换数组中的每个值
Numpy: Replace every value in the array with the mean of its adjacent elements
我有一个 ndarray,我想用相邻元素的平均值替换数组中的每个值。下面的代码可以完成这项工作,但是当我有 700 个形状都为 (7000, 7000) 的数组时它非常慢,所以我想知道是否有更好的方法来做到这一点。谢谢!
a = np.array(([1,2,3,4,5,6,7,8,9],[4,5,6,7,8,9,10,11,12],[3,4,5,6,7,8,9,10,11]))
row,col = a.shape
new_arr = np.ndarray(a.shape)
for x in xrange(row):
for y in xrange(col):
min_x = max(0, x-1)
min_y = max(0, y-1)
new_arr[x][y] = a[min_x:(x+2),min_y:(y+2)].mean()
print new_arr
嗯,就是这样 smoothing operation in image processing
, which can be achieved with 2D
convolution. You are working a bit differently on the near-boundary elements. So, if the boundary elements are let off for precision, you can use scipy's convolve2d
-
from scipy.signal import convolve2d as conv2
out = (conv2(a,np.ones((3,3)),'same')/9.0
这个特定的操作是内置在 OpenCV 模块中的 cv2.blur
,并且非常有效。该名称基本上描述了其模糊表示图像的输入数组的操作。我相信效率来自于这样一个事实,即它在内部完全在 C
中实现,以提高性能,并使用薄 Python 包装器来处理 NumPy 数组。
所以,输出也可以用它来计算,就像这样 -
import cv2 # Import OpenCV module
out = cv2.blur(a.astype(float),(3,3))
这是一个相当大的 image/array -
上的时间的快速摊牌
In [93]: a = np.random.randint(0,255,(5000,5000)) # Input array
In [94]: %timeit conv2(a,np.ones((3,3)),'same')/9.0
1 loops, best of 3: 2.74 s per loop
In [95]: %timeit cv2.blur(a.astype(float),(3,3))
1 loops, best of 3: 627 ms per loop
在与@Divakar 的讨论之后,找到 scipy 中存在的不同卷积方法的比较:
import numpy as np
from scipy import signal, ndimage
def conv2(A, size):
return signal.convolve2d(A, np.ones((size, size)), mode='same') / float(size**2)
def fftconv(A, size):
return signal.fftconvolve(A, np.ones((size, size)), mode='same') / float(size**2)
def uniform(A, size):
return ndimage.uniform_filter(A, size, mode='constant')
所有 3 种方法 return 完全相同的值。但是,请注意 uniform_filter
有一个参数 mode='constant'
,它表示滤波器的边界条件,而 constant == 0
与傅立叶域(在其他 2 种方法中)是相同的边界条件强制执行。对于不同的用例,您可以更改边界条件。
现在一些测试矩阵:
A = np.random.randn(1000, 1000)
还有一些时间安排:
%timeit conv2(A, 3) # 33.8 ms per loop
%timeit fftconv(A, 3) # 84.1 ms per loop
%timeit uniform(A, 3) # 17.1 ms per loop
%timeit conv2(A, 5) # 68.7 ms per loop
%timeit fftconv(A, 5) # 92.8 ms per loop
%timeit uniform(A, 5) # 17.1 ms per loop
%timeit conv2(A, 10) # 210 ms per loop
%timeit fftconv(A, 10) # 86 ms per loop
%timeit uniform(A, 10) # 16.4 ms per loop
%timeit conv2(A, 30) # 1.75 s per loop
%timeit fftconv(A, 30) # 102 ms per loop
%timeit uniform(A, 30) # 16.5 ms per loop
所以简而言之,uniform_filter
似乎更快,因为 convolution is separable in two 1D convolutons (similar to gaussian_filter 也是可分离的)。
使用 signal
模块(@Divakar 中的那个)解决方案,其他具有不同内核的不可分离过滤器更有可能更快。
对于不同的内核大小,fftconvolve
和 uniform_filter
的速度保持 不变 ,而 convolve2d
会稍微慢一些。
我最近遇到了类似的问题,由于无法使用 scipy,我不得不寻找不同的解决方案。
import numpy as np
a = np.random.randint(100, size=(7000,7000)) #Array of 7000 x 7000
row,col = a.shape
column_totals = a.sum(axis=0) #Dump the sum of all columns into a single array
new_array = np.zeros([row,col]) #Create an receiving array
for i in range(row):
#Resulting row = the value of all rows minus the orignal row, divided by the row number minus one.
new_array[i] = (column_totals - a[i]) / (row - 1)
print(new_array)
我有一个 ndarray,我想用相邻元素的平均值替换数组中的每个值。下面的代码可以完成这项工作,但是当我有 700 个形状都为 (7000, 7000) 的数组时它非常慢,所以我想知道是否有更好的方法来做到这一点。谢谢!
a = np.array(([1,2,3,4,5,6,7,8,9],[4,5,6,7,8,9,10,11,12],[3,4,5,6,7,8,9,10,11]))
row,col = a.shape
new_arr = np.ndarray(a.shape)
for x in xrange(row):
for y in xrange(col):
min_x = max(0, x-1)
min_y = max(0, y-1)
new_arr[x][y] = a[min_x:(x+2),min_y:(y+2)].mean()
print new_arr
嗯,就是这样 smoothing operation in image processing
, which can be achieved with 2D
convolution. You are working a bit differently on the near-boundary elements. So, if the boundary elements are let off for precision, you can use scipy's convolve2d
-
from scipy.signal import convolve2d as conv2
out = (conv2(a,np.ones((3,3)),'same')/9.0
这个特定的操作是内置在 OpenCV 模块中的 cv2.blur
,并且非常有效。该名称基本上描述了其模糊表示图像的输入数组的操作。我相信效率来自于这样一个事实,即它在内部完全在 C
中实现,以提高性能,并使用薄 Python 包装器来处理 NumPy 数组。
所以,输出也可以用它来计算,就像这样 -
import cv2 # Import OpenCV module
out = cv2.blur(a.astype(float),(3,3))
这是一个相当大的 image/array -
上的时间的快速摊牌In [93]: a = np.random.randint(0,255,(5000,5000)) # Input array
In [94]: %timeit conv2(a,np.ones((3,3)),'same')/9.0
1 loops, best of 3: 2.74 s per loop
In [95]: %timeit cv2.blur(a.astype(float),(3,3))
1 loops, best of 3: 627 ms per loop
在与@Divakar 的讨论之后,找到 scipy 中存在的不同卷积方法的比较:
import numpy as np
from scipy import signal, ndimage
def conv2(A, size):
return signal.convolve2d(A, np.ones((size, size)), mode='same') / float(size**2)
def fftconv(A, size):
return signal.fftconvolve(A, np.ones((size, size)), mode='same') / float(size**2)
def uniform(A, size):
return ndimage.uniform_filter(A, size, mode='constant')
所有 3 种方法 return 完全相同的值。但是,请注意 uniform_filter
有一个参数 mode='constant'
,它表示滤波器的边界条件,而 constant == 0
与傅立叶域(在其他 2 种方法中)是相同的边界条件强制执行。对于不同的用例,您可以更改边界条件。
现在一些测试矩阵:
A = np.random.randn(1000, 1000)
还有一些时间安排:
%timeit conv2(A, 3) # 33.8 ms per loop
%timeit fftconv(A, 3) # 84.1 ms per loop
%timeit uniform(A, 3) # 17.1 ms per loop
%timeit conv2(A, 5) # 68.7 ms per loop
%timeit fftconv(A, 5) # 92.8 ms per loop
%timeit uniform(A, 5) # 17.1 ms per loop
%timeit conv2(A, 10) # 210 ms per loop
%timeit fftconv(A, 10) # 86 ms per loop
%timeit uniform(A, 10) # 16.4 ms per loop
%timeit conv2(A, 30) # 1.75 s per loop
%timeit fftconv(A, 30) # 102 ms per loop
%timeit uniform(A, 30) # 16.5 ms per loop
所以简而言之,uniform_filter
似乎更快,因为 convolution is separable in two 1D convolutons (similar to gaussian_filter 也是可分离的)。
使用 signal
模块(@Divakar 中的那个)解决方案,其他具有不同内核的不可分离过滤器更有可能更快。
对于不同的内核大小,fftconvolve
和 uniform_filter
的速度保持 不变 ,而 convolve2d
会稍微慢一些。
我最近遇到了类似的问题,由于无法使用 scipy,我不得不寻找不同的解决方案。
import numpy as np
a = np.random.randint(100, size=(7000,7000)) #Array of 7000 x 7000
row,col = a.shape
column_totals = a.sum(axis=0) #Dump the sum of all columns into a single array
new_array = np.zeros([row,col]) #Create an receiving array
for i in range(row):
#Resulting row = the value of all rows minus the orignal row, divided by the row number minus one.
new_array[i] = (column_totals - a[i]) / (row - 1)
print(new_array)