我正在生成一些过滤器,以实现对图像进行快速傅立叶变换模糊和锐化操作。过滤器可以正确生成,但是计算会持续很长时间。
我当前生成过滤器的方式是逐项迭代所需过滤器的尺寸。我知道我需要使用Numpy来解决此问题,但是我不知道具体如何。这是我用于生成高斯滤波器的代码:
def gaussian_filter(mode, size, cutoff):
filterImage = np.zeros(size, np.float64)
cutoffTerm = 2 * (cutoff ** 2)
v = np.asarray([size[0] // 2, size[1] // 2])
for px in range(0, size[0]):
for py in range(0, size[1]):
u = np.asarray([px, py])
Duv = np.linalg.norm(u - v)
distance = -1 * (Duv ** 2)
result = pow(np.e, distance / cutoffTerm)
if mode == 'low':
filterImage.itemset((px, py), result)
elif mode == 'high':
filterImage.itemset((px, py), 1 - result)
return filterImage
生成1920 x 1080大小的滤镜需要70.36秒,这是完全不可接受的。任何想法将不胜感激。
答案 0 :(得分:2)
这是一个利用broadcasting
-向量的人-
def gaussian_filter_vectorized(mode, size, cutoff):
cutoffTerm = 2 * (cutoff ** 2)
v = np.asarray([size[0] // 2, size[1] // 2])
I,J = np.ogrid[:size[0],:size[1]]
p,q = I-v[0],J-v[1]
Dsq = p**2 + q**2
d = -1 * Dsq
R = np.power(np.e,d/cutoffTerm)
if mode == 'low':
return R
elif mode == 'high':
return 1-R
大size
上的时间-
In [80]: N = 100
...: %timeit gaussian_filter(mode='low', size=(N,N), cutoff=N)
...: %timeit gaussian_filter_vectorized(mode='low', size=(N,N), cutoff=N)
10 loops, best of 3: 65.2 ms per loop
1000 loops, best of 3: 225 µs per loop
In [81]: N = 1000
...: %timeit gaussian_filter(mode='low', size=(N,N), cutoff=N)
...: %timeit gaussian_filter_vectorized(mode='low', size=(N,N), cutoff=N)
1 loop, best of 3: 6.5 s per loop
10 loops, best of 3: 29.8 ms per loop
200x+
加速!
numexpr
可以进一步提高性能。增强在处理大数据时,如果预期的操作可以表示为算术运算,我们也可以使用支持多核处理的numexpr
module。为了解决我们的问题,我们可以使用Dsq = p**2 + q**2
函数将R = np.power(np.e,d/cutoffTerm)
和numexpr
的步骤替换为numexpr.evaluate
等效的步骤。
所以,我们最终会得到这样的东西-
import numexpr as ne
def gaussian_filter_vectorized_numexpr(mode, size, cutoff):
cutoffTerm = 2 * (cutoff ** 2)
I,J = np.ogrid[:size[0],:size[1]]
v0,v1 = size[0] // 2, size[1] // 2
p,q = I-v0,J-v1
E = np.e
if mode == 'low':
return ne.evaluate('E**(-1*(p**2+q**2)/cutoffTerm)')
elif mode == 'high':
return ne.evaluate('1-E**(-1*(p**2+q**2)/cutoffTerm)')
1920x1080
大小的图像上的时间-
In [2]: M,N=1920,1080
...: %timeit gaussian_filter(mode='low', size=(M,N), cutoff=N)
...: %timeit gaussian_filter_vectorized(mode='low', size=(M,N), cutoff=N)
...: %timeit gaussian_filter_vectorized_numexpr(mode='low',size=(M,N),cutoff=N)
1 loop, best of 3: 13.9 s per loop
10 loops, best of 3: 63.3 ms per loop
100 loops, best of 3: 9.48 ms per loop
在此处接近 1500x
加速!
这是8
个线程。因此,随着更多线程可用于计算,它应该进一步改进。 Related post
了解如何控制多核功能。