我有一个关于Python循环速度的问题。 我创建了以下循环来填充数组中的值,但这非常慢。 有没有办法使其处理更快?
winW = 1
winH = 200
runlength = np.zeros(shape=(img.shape[0], img.shape[1]))
for y in range(0, img.shape[0] - winH, 1):
for x in range(0, img.shape[1] - winW, 1):
runlength[y, x] += np.sum(img[y:y + winH, x:x + winW]) / (winH * winW)
runlength[y + winH, x] += np.sum(img[y:y + winH, x:x + winW]) / (winH * winW)
感谢您的帮助
编辑:我精确地说,我只能使用numpy,而不能使用scipy
答案 0 :(得分:2)
让我描述一下如何加快for循环中的第一个操作,该操作由
给出runlength[y, x] += np.sum(img[y:y + winH, x:x + winW]) / (winH * winW)
基本上,您正在图像上移动一个宽度winW
和高度winH
的矩形。从图像的点(0,0)处的矩形的左上角开始,然后对图像中位于该矩形下方的所有值求和,然后将它们除以总点数。位置(0,0)的输出就是该数字。然后将矩形向右移动一个,然后重复该过程,直到位于图像的右端。您向下移动一行并重复。
在图像处理方面:将空间滤镜蒙版应用于图像。该过滤器是宽度winW
和高度winH
的平均过滤器。
要有效地实现此目的,可以使用scipy.ndimage.correlate
函数。 input
是您的图像,weights
包含与矩形下面的元素相乘的权重。在这种情况下,这是一个维度为(winH, winW)
的数组,其中每个元素都包含数字1 / (winH * winW)
。因此,将位于矩形下方的图像的每个点乘以1 / (winH * winW)
,然后将所有内容相加。
要完全匹配您的算法,我们需要将origin
设置为(-np.floor(winH/2), -np.floor(winW/2))
,以指定将矩形的均值放置在输出中矩形的右上角。
最后,为了完全匹配您的算法,我们必须将(img.shape[0] - winH)
以下或(img.shape[1] - winW)
右边的所有点都设置为零。因此,可以将for循环替换为
runlength_corr = correlate(input=img,
weights=np.ones((winH, winW)) / (winW * winH),
origin=(-np.floor(winH/2), -np.floor(winW/2)))
runlength_corr[(img.shape[0] - winH):, :] = 0
runlength_corr[:, (img.shape[1] - winW):] = 0
我在大小为512 x 512的测试图像上比较了嵌套的for循环和correlate
方法的运行时间:
For-loops: Elapsed time: 0.665 sec
Correlate: Elapsed time: 0.085 sec
因此,这可以很好地加速因子8。整个输出的绝对差之和低至7.04e-09
,因此两种方法的输出基本上相同。
答案 1 :(得分:0)
对于初学者来说,您似乎在循环内计算了两次相同的数量。仅此一项就可以节省一半的运行时间。
第二,如果winW
始终为1
,则np.sum(img[y:y + winH, x:x + winW])
仅
np.sum(img[y:y + winH, x])
。这样应该可以加快速度。
剩下的就是如何加快np.sum(img[y:y + winH, x])
的速度。您可以先计算
sum0 = np.sum(img[0: 0 + winH, x])
现在,请注意数量
sum1 = np.sum(img[1: 1 + winH, x])
仅与前一个像素相差两个像素,因此等于sum0 - img[0, x] + img[1 + winH, x]
。对于下一个y
sum2 = sum1 - img[1, x] + img[2 + winH, x]`
以此类推