在python

时间:2017-02-14 13:44:48

标签: python arrays performance numpy image-processing

我有一个尺寸为1024x1024的PNG图片,其中包含RGB编码的高程数据。 我使用asarray中的numpy来读取图片:

rgb_data = np.asarray(image)

这导致尺寸为(1024, 1024, 4)的3D数组。 (我使用的是RGBA)

我需要对这些数据运行一些过滤器(高斯,中位数),但我需要在解码的高程数据上运行它。

可以使用以下功能解码高程数据:

def decodeRGB(pixel):
    return (pixel[0] * 256 + pixel[1] + pixel[2] / 256) - 32768

解码后,我将得到一个尺寸为(1024, 1024)的二维数组,其中包含已解码的高程数据。 (实际海拔高度)

到目前为止我所拥有的是:

rgb_data = np.asarray(image)
decoded_data = np.zeros(tile.size)

for rownum in range(width):
    for colnum in range(height):
        decoded_data[rownum][colnum] = decodeRGB(rgb_data[rownum][colnum])

不幸的是,这个解决方案很慢。需要约。 1024 x 1024图像为10秒。

是否有更高效的方法来实现它?

我的主要问题是数组的尺寸发生了变化。 我是从(1024, 1024, 4)数组转到(1024, 1024)数组。

我基本上寻找一种快速/有效的方法将函数应用于图像中的每个RGB像素,从而减少数组大小。

非常感谢你的帮助!

2 个答案:

答案 0 :(得分:4)

利用矢量化:

r = rgb_data[..., 0]
g = rgb_data[..., 1]
b = rgb_data[..., 2]
decoded_data = (256*r + g + b/256) - 32768

例如,rgb_data[..., 0]一次选择所有 1024x1024个红色值,256*r将所有红色值一次性加倍,依此类推。由于代码中解释的for循环会带来很大的开销,因此避免它们会大大加快转换速度。

或者你可以使用单行:

decoded_data = (rgb_data[..., :3] * (256, 1, 1/256)).sum(axis=-1) - 32768

还有更多类似的精神方式。看看这篇文章中的评论,可以找到很好的单行集合。

答案 1 :(得分:3)

您可以使用非常强大的np.einsum对流程进行矢量化。只需从系数中生成变换向量。

def decodeRGBArray(rgb_data):
    transf = np.array([256., 1., 1./256., 0.])
    return np.einsum('ijk,k->ij', rgb_data, transf) - 32768