numpy:如何快速转换数组类型

15 投票
1 回答
39035 浏览
提问于 2025-04-15 16:55

我觉得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

撰写回答