在python中从(2,MN)矩阵读取(M,N)图像的值

时间:2018-10-30 11:40:56

标签: python vectorization

假设我有一个(M,N)图像J(形状为(M,N,3))。我有一个(2,MN)矩阵K,像这样:

0 0 0 ... 0 1 1 1 ... 1 ............. M M M ... M

0 1 2 ... N 1 2 3 ... N ............. 1 2 3 ... N

现在,我将上述矩阵乘以2 x 2矩阵,得到一个新的矩阵T,其大小与K相同。

现在我要创建一个新图像,其中新图像中的像素(r,s)等于r * N +中旧图像像素的(R,G,B)值T的M列。

如果可能的话,我想以向量化的方式进行。我不想使用for循环(我已经知道如何使用for循环来做到这一点,但这非常慢)。实际上,我对这个问题的兴趣是因为我想以矢量化方式应用单应性变换。

感谢您的帮助。这是让我想清楚的内容的循环版本:

for r in range(0,M):
    for s in range(0,N):
        x, y = T[:,r*N+s]
        new_image[r,s] = J[x,y]

1 个答案:

答案 0 :(得分:1)

由于内部索引的幸运布局,您几乎可以直接使用索引数组:

import numpy as np

# set up dummy input
M,N = 300,400
J = np.random.rand(M, N, 3)
T = np.array([np.random.randint(0, M, M*N), np.random.randint(0, N, M*N)])

# original    
new_image = np.empty_like(J)
for r in range(0,M):
    for s in range(0,N):
        x, y = T[:,r*N+s]
        new_image[r,s] = J[x,y]

# vectorized new
new_image_vect = J[tuple(T)].reshape(J.shape)

检查:

>>> np.array_equal(new_image, new_image_vect)
True

上面的工作方式并不完全是琐碎的,因为advanced indexing is a fickle thing。我上面写的等同于

J[(T[0,...], T[1,...])].reshape(J.shape) -> J[T[0,...], T[1,...]].reshape(J.shape)

现在第一部分更清楚:将T第一行中的每个元素用作J的第一索引,然后将{{1}第二行中的对应元素}},并将其用作T的相应第二个索引。这部分内容涵盖了循环版本中的J

但是,由于我们实际上是使用长度为J[x,y]的一维数组索引数组,因此,所得数组的形状沿其第一维(以及大小的尾随维)也将具有形状M*N 3)。因此,我们需要将M*N的结果返回到reshape

这仅可直接使用,因为(M,N,3)中的索引是根据C连续内存顺序存储的。如果不是这种情况,我们必须来回T数组,以生成具有正确布局的结果数组。