【python进阶】python动态数组

在医学图像处理领域,我们经常会需要读取大量病人的图像。如何将这些图像全部读取进来并存成一个数组是一个经常遇到的问题。然而,在事前,我们通常只能知道每一张图像的尺寸是多少,而无法准确地知道一共有多少张图片(除非事前遍历一遍)。


很自然地,我们想到了使用数组堆叠的方法来实现它,numpy中的能够进行数组堆叠的方法有conconcatenate,append,stack,hstack,vstackdstack。而后面五种方法,本质上还是调用conconcatenate来实现的,他们的效率并没有显著差异。

下面我们看一下这种方法的实现:

import numpy as np

arrays = np.empty((0, 3, 512, 512)) #创建空数组

for i in range(100):
    image = np.ones(shape=(3, 512, 512)) #使用image模拟一张3通道,512×512的图片
    data = image.reshape((1, 3, 512, 512))
    arrays = np.concatenate((arrays, data), axis=0)

print(np.shape(arrays))
print(type(arrays))

输出:

(100, 3, 512, 512)
<class 'numpy.ndarray'>

可以看到,通过这种方法是可以实现动态数组的。
那么,它的效率如何呢?我们通过调用pycharmProfile模块查看一下:
这里写图片描述
从表格的第二行可以看出,该程序运行总耗时为21066ms,其中调用concatenate函数耗时19863ms,占94.3%之多。可见,整个程序的瓶颈就在concatenate函数处。

那么,有没有其它替代的方法呢?


答案是肯定的。很简单的,我们直接使用pythonlist来实现。

import numpy as np

arrays = [] #创建空列表

for i in range(100):
    data = np.ones(shape=(3, 512, 512)) #使用image模拟一张3通道,512×512的图片
    arrays.append(data)
arrays = np.array(arrays) #将list转换为Numpy数组

print(np.shape(arrays))
print(type(arrays))

输出:

(100, 3, 512, 512)
<class 'numpy.ndarray'>

可以看到,通过list一样是可以实现动态数组的。
那么,它的效率又是怎么样呢?我们同样通过调用pycharmProfile模块查看一下:
这里写图片描述
从表格的第二行可以看出,该程序运行总耗时仅为766ms,只有原程序的4%不到。


那么,为什么会出现这种情况呢?

这是因为,numpy没有动态改变数组大小的功能,每次调用conconcatenate时,系统会重新开辟内存生成一个数组,并将原来的数组复制到新数组中,这个过程是非常耗时的,所以导致整个程序变得非常缓慢。
所以,以后在处理大量数据的过程中呢,尽量不要调用conconcatenate等函数哦~

猜你喜欢

转载自blog.csdn.net/jianjuly/article/details/80549284