5

我正在编写一个 python 模块,它需要计算 1000 多个数组(相同维度)中像素值的平均值和标准差。

我正在寻找最快的方法来做到这一点。

目前我正在遍历数组并使用 numpy.dstack 将 1000 个数组堆叠成一个相当大的 3d 数组......然后将计算第三(?)维度的平均值。每个数组都有形状(5000,4000)。

这种方法需要相当长的时间!

任何人都可以就解决此问题的更有效方法提出建议吗?

4

3 回答 3

2

也许你可以计算meanstd以这样的累积方式(未经测试):

im_size = (5000,4000)

cum_sum = np.zeros(im_size)
cum_sum_of_squares = np.zeros(im_size)
n = 0

for filename in filenames:
    image = read_your_image(filename)
    cum_sum += image
    cum_sum_of_squares += image**2
    n += 1

mean_image = cum_sum / n
std_image = np.sqrt(cum_sum_of_squares / n - (mean_image)**2)

这可能受到您从磁盘读取图像的速度的限制。它不受内存限制,因为您一次只有一个图像在内存中。以这种方式计算std可能会遇到数值问题,因为您可能要减去两个大数。如果这是一个问题,您必须遍历文件两次,首先计算平均值,然后(image - mean_image)**2在第二遍中累积。

于 2013-08-29T21:15:47.473 回答
1

预分配和填充。这将我的运行时间缩短了大约 1000 秒到 20 秒

data_stack = numpy.empty((321, 720, 1000), dtype=numpy.float32)
for index in range(len(data)):
  data_stack[0:321,0:720,index] = data[index]

我正在做类似的事情。dstack 不是解决这个问题的好方法。一位同事让我想起了动态数组问题和摊销分析。 http://anh.cs.luc.edu/363/notes/06A_Amortizing.html

当你想扩展一个动态数组时,你需要分配一个新的数组来保存原始数据和新数据。然后将旧数组复制到新数组中,将新数据复制到新数组中。这是一项昂贵的操作。

假设您有一个大小为 10 的数组,并且您想一次向其中添加 2 个项目。要添加第一个项目,您需要将数组扩展为 11 大小并复制 11 个项目(原始 10 + 1 个新项目)。要添加第二个项目,您需要将数组扩展为 12 大小并复制 12 个项目。如果您提前知道要添加 2 个项目,则可以将数组的大小调整为 12,然后只复制 12 个项目而不是总共 23 个。事实证明,每次用完数组的大小都会加倍空间是一个更有效的解决方案。

这在这里如何应用: dstack 不会将 ndarray 的大小加倍,它意味着只分配所需的内存。因此,每次调用 dstack 时,都会将 ndarray 中的所有数据复制到一个新的 ndarray 中,并为新数据留出空间。请注意,每次调用 dstack 的时间都会增加。

于 2013-09-13T19:52:59.650 回答
0

如果您想大幅减少计算时间,可以选择多线程解决方案。像这样的python有几个库。

于 2013-09-14T11:09:45.690 回答