numpy:如何快速转换数组类型
我觉得numpy数组的astype()方法效率不是很高。我有一个包含300万个Uint8点的数组。把它乘以一个3x3的矩阵需要2秒,但把结果从uint16转换成uint8又要花1秒。
更具体来说:
print time.clock()
imgarray = np.dot(imgarray, M)/255
print time.clock()
imgarray = imgarray.clip(0, 255)
print time.clock()
imgarray = imgarray.astype('B')
print time.clock()
点乘和缩放需要2秒
裁剪需要200毫秒
类型转换需要1秒
考虑到其他操作所花的时间,我本以为astype
会更快。有没有更快的方法来进行类型转换,还是我对类型转换的难度估计错了?
补充:目标是把最终的8位数组保存到文件中。
1 个回答
27
当你使用 imgarray = imgarray.astype('B')
时,你会得到一个新的数组,这个数组的类型被转换成了你指定的类型。这会需要额外的内存,因为你实际上是创建了一个新的数组,然后让 imgarray
指向这个新数组。
如果你使用 imgarray.view('uint8')
,那么你得到的是数组的一个视图。这个视图使用的是相同的数据,只不过它被解释为 uint8
类型,而不是 imgarray.dtype
的原始类型。
(np.dot
返回的是一个 uint32
类型的数组,所以在执行 np.dot
之后,imgarray
的类型变成了 uint32
。)
不过,使用 view
的问题在于,一个32位的整数会被视为4个8位的整数,而我们只关心最后8位的值。因此,我们需要每隔4个8位整数取一次。我们可以通过切片来实现这一点:
imgarray.view('uint8')[:,::4]
IPython 的 %timeit 命令显示,使用这种方式可以显著提高速度:
In [37]: %timeit imgarray2 = imgarray.astype('B')
10000 loops, best of 3: 107 us per loop
In [39]: %timeit imgarray3 = imgarray.view('B')[:,::4]
100000 loops, best of 3: 3.64 us per loop