Numpy将3D可变大小卷的列表转换为4D阵列

时间:2016-08-16 17:00:02

标签: python arrays numpy 3d 4d

我在神经网络上工作,我通过旋转增加数据并改变每个输入音量的大小。

让我备份,网络输入是一个3D卷。我生成可变大小的3D体积,然后用零填充每个体积,使输入体积恒定。检查here我遇到的填充问题(现已解决)。

我生成一个可变大小的3D卷,将其附加到列表中,然后将列表转换为numpy数组。此时,填充还没有发生,因此将其转换为4D元组是没有意义的......

input_augmented_matrix = []
label_augmented_matrix = []
for i in range(n_volumes):
    if i % 50 == 0:
        print ("Augmenting step #" + str(i))
    slice_index = randint(0,n_input)
    z_max = randint(5,n_input)
    z_rand = randint(3,5)
    z_min = z_max - z_rand
    x_max = randint(75, n_input_x)
    x_rand = randint(60, 75)
    x_min = x_max - x_rand
    y_max = randint(75, n_input_y)
    y_rand = randint(60, 75)
    y_min = y_max - y_rand
    random_rotation = randint(1,4) * 90
    for j in range(2):
        temp_volume = np.empty((z_rand, x_rand, y_rand))
        k = 0
        for z in range(z_min, z_max):
            l = 0
            for x in range(x_min, x_max):
                m = 0
                for y in range(y_min, y_max):
                    if j == 0:
                        #input volume
                        try:
                            temp_volume[k][l][m] = input_matrix[z][x][y]
                        except:
                            pdb.set_trace()
                    else:
                        #ground truth volume
                        temp_volume[k][l][m] = label_matrix[z][x][y]
                    m = m + 1
                l = l + 1
            k = k + 1
        temp_volume = np.asarray(temp_volume)
        temp_volume = np.rot90(temp_volume,random_rotation)
        if j == 0:
            input_augmented_matrix.append(temp_volume)
        else:
            label_augmented_matrix.append(temp_volume)

input_augmented_matrix = np.asarray(input_augmented_matrix)
label_augmented_matrix = np.asarray(label_augmented_matrix)

此时input_augmented_matrix的尺寸为(N,)

然后我用以下代码填充......

for i in range(n_volumes):
    print("Padding volume #" + str(i))
    input_augmented_matrix[i] = np.lib.pad(input_augmented_matrix[i], ((0,n_input_z - int(input_augmented_matrix[i][:,0,0].shape[0])),
                                                (0,n_input_x - int(input_augmented_matrix[i][0,:,0].shape[0])),
                                                (0,n_input_y - int(input_augmented_matrix[i][0,0,:].shape[0]))),
                                'constant', constant_values=0)
    label_augmented_matrix[i] = np.lib.pad(label_augmented_matrix[i], ((0,n_input_z - int(label_augmented_matrix[i][:,0,0].shape[0])),
                                                (0,n_input_x - int(label_augmented_matrix[i][0,:,0].shape[0])),
                                                (0,n_input_y - int(label_augmented_matrix[i][0,0,:].shape[0]))),
                                'constant', constant_values=0)

此时,即使列表中的每个元素都是常量,维度仍为(N,)。例如input_augmented_matrix[0] = input_augmented_matrix[1]

目前我只是循环并创建一个新数组,但它需要太长时间,我宁愿某种自动化的方法。我用以下代码做到了......

input_4d = np.empty((n_volumes, n_input_z, n_input_x, n_input_y))
label_4d = np.empty((n_volumes, n_input_z, n_input_x, n_input_y))
for i in range(n_volumes):
    print("Converting to 4D tuple #" + str(i))
    for j in range(n_input_z):
        for k in range(n_input_x):
            for l in range(n_input_y):
                input_4d[i][j][k][l] = input_augmented_matrix[i][j][k][l]
                label_4d[i][j][k][l] = label_augmented_matrix[i][j][k][l]

有更清洁,更快捷的方法吗?

1 个答案:

答案 0 :(得分:1)

我理解这部分

k = 0
for z in range(z_min, z_max):
    l = 0
    for x in range(x_min, x_max):
        m = 0
        for y in range(y_min, y_max):
            if j == 0:
                #input volume
                try:
                    temp_volume[k][l][m] = input_matrix[z][x][y]
                except:
                    pdb.set_trace()
            else:
                #ground truth volume
                temp_volume[k][l][m] = label_matrix[z][x][y]
            m = m + 1
        l = l + 1
    k = k + 1

你只想这样做

temp_input = input_matrix[z_min:z_max, x_min:x_max, y_min:y_max]
temp_label = label_matrix[z_min:z_max, x_min:x_max, y_min:y_max]

然后

temp_input = np.rot90(temp_input, random_rotation)
temp_label = np.rot90(temp_label, random_rotation)

input_augmented_matrix.append(temp_input)
label_augmented_matrix.append(temp_label)

下面

input_augmented_matrix[i] = np.lib.pad(
    input_augmented_matrix[i],
    ((0,n_input_z - int(input_augmented_matrix[i][:,0,0].shape[0])),
     (0,n_input_x - int(input_augmented_matrix[i][0,:,0].shape[0])),
     (0,n_input_y - int(input_augmented_matrix[i][0,0,:].shape[0]))),
    'constant', constant_values=0)

最好这样做,因为shape属性为您提供所有维度的数组大小

ia_shape = input_augmented_matrix[i].shape
input_augmented_matrix[i] = np.lib.pad(
    input_augmented_matrix[i],
    ((0, n_input_z - ia_shape[0]),
     (0, n_input_x - ia_shape[1])),
     (0, n_input_y - ia_shape[2]))),
    'constant',
    constant_values=0)

我想现在您已经准备好使用NumPy的魔术索引来重构代码的最后部分。

我的共同建议:

  • 使用函数重复代码部分,以避免像循环级联中那样的缩进;
  • 如果您需要这么多嵌套循环,请考虑递归,如果没有它们就无法处理;
  • 在官方documentation中探索NumPy的能力:它们真的令人兴奋;)例如,indexing对此任务有帮助;
  • 使用PyLintFlake8包来检查代码的质量。

你想自己编写神经网络,还是只想解决一些模式识别任务? SciPy库可能包含您需要的内容,它基于NumPy