如何使用Python 2.7中的NumPy数组加速操作

时间:2017-12-18 09:18:48

标签: python arrays numpy

我尝试处理许多表示为NumPy数组的图像,但这需要太长时间。这就是我想要做的事情

# image is a list with images
max = np.amax(image[k])# k is current image index in loop
# here i try to normalize SHORT color to BYTE color and make it fill all range from 0 to 255
# in images max color value is like 30000 min is usually 0
i = 0
while i < len(image[k]):
    j = 0
    while j < len(image[k][i]):
        image[k][i][j] = float(image[k][i][j]) / (max) * 255
        j += 1
    i += 1

如果我只读图像(总共170张(图像是512x512))而不需要大约7秒,如果我这样做,则需要20分钟。它完全在代码中。在这里,我尝试使我的图像着色

maskLoot1=np.zeros([len(mask1), 3*len(mask1[0])])
for i in range(len(mask1)):
    for j in range(len(mask1[0])):
        maskLoot1[i][j*3]=mask1[i][j]
        maskLoot1[i][j*3+1]=mask1[i][j]
        maskLoot1[i][j*3+2]=mask1[i][j]

接下来,我尝试用彩色像素替换所选区域像素,例如120(灰色) - &gt; (255 40 0)在rgb模型中。

            for i in range(len(mask1)):
                for j in range(len(mask1[0])):
                #mask is NumPy array with selected pixel painted in white (255)
                    if (mask[i][j] > 250):
                        maskLoot1[i][j * 3] = lootScheme[mask1[i][j]][1] #red chanel
                        maskLoot1[i][j * 3+1] = lootScheme[mask1[i][j]][2] #green chanel
                        maskLoot1[i][j * 3+2] = lootScheme[mask1[i][j]][3] #bluechanel

它也需要很长时间,而不是20分钟,但长时间使我的脚本滞后。我认为它只是我在阵列上的许多操作中的两个,如果是第二种情况,我们可以为其他人使用一些bultin函数是不太可能的。那么有没有办法加快我的工作?

3 个答案:

答案 0 :(得分:1)

对于你的面具制作代码,请尝试将此替换为循环:

maskLoot1 = np.dstack(3*[mask1]).reshape((mask1.shape[0],3*mask1.shape[1]))

实现上述目的还有许多其他方式/变化,例如,

maskLoot1 = np.tile(mask1[:,:,None], 3).reshape((mask1.shape[0],3*mask1.shape[1]))

至于你问题的第一部分,最好的答案是@furas对你的问题的第一个评论

答案 1 :(得分:1)

首先,考虑转向Python 3. *。 Numpy正在放弃对Python Numpy is dropping support for Python 2.7 from 2020的支持。

您的代码问题。你错过了在下面使用Numpy的观点。 Numpy是从较低级别的库编译而且运行速度非常快,你不应该在Python中循环索引,你应该将矩阵抛给Numpy。

问题1 使用listcomp和np.array

进行规范化非常快
import numpy as np
import time

# create dummy image structure (k, i, j, c) or (k, i, j)
# k is image index, i is row, j is columns, c is channel RGB
images = np.random.uniform(0, 30000, size=(170, 512, 512))

t_start = time.time()
norm_images = np.array([(255*images[k, :, :]/images[k, :, :].max()).astype(int) for k in range(170)])
t_end = time.time()

print("Processing time = {} seconds".format(t_end-t_start))
print("Input shape = {}".format(images.shape))
print("Output shape = {}".format(norm_images.shape))
print("Maximum input value = {}".format(images.max()))
print("Maximum output value = {}".format(norm_images.max()))

创建以下输出

Processing time = 0.2568979263305664 seconds
Input shape = (170, 512, 512)
Output shape = (170, 512, 512)
Maximum input value = 29999.999956185838
Maximum output value = 255

需要0.25秒!

问题2 不确定你的意思,但如果你想将单色图像的值克隆到RGB值,你可以这样做

# coloring (by copying value and keeping your structure)
color_img = np.array([np.tile(images[k], 3) for k in range(170)])
print("Output shape = {}".format(color_img.shape))

哪个产生

Output shape = (170, 512, 1536)

如果您想要保留(c,i,j,k)结构

color_img = np.array([[images[k]]*3 for k in range(170)])  # that creates (170, 3, 512, 512)
color_img = np.swapaxes(np.swapaxes(color_img, 1,2), 2, 3) # that creates (170, 512, 512, 3)

这一切都需要0.26秒!

问题3 着色某些区域,我会再次使用一个函数和一个listcomp。由于这是一个例子,我使用了默认着色(255,40,0)但你可以使用任何东西,包括LUT。

# create mask of zeros and ones
mask = np.floor(np.random.uniform(0,256, size=(512,512)))
default_scheme = (255, 40, 0)

def substitute(cimg, mask, scheme):
  ind = mask > 250
  cimg[ind, :] = scheme
  return cimg

new_cimg = np.array([substitute(color_img[k], mask, default_scheme) for k in range(170)])

答案 2 :(得分:0)

通常,for循环比while循环快得多。还使用了

的功能
maskLoot1[i][j*3]=mask1[i][j]
maskLoot1[i][j*3+1]=mask1[i][j]
maskLoot1[i][j*3+2]=mask1[i][j]

并在循环中调用该函数应该可以显着加快该过程。