从 MATLAB 到 Python 的无迭代实现

Implementation from MATLAB to Python without iterations

假设您在 MATLAB 中有以下代码:

    [xi yi imv] = find(imagee+0.1);
    imv = imv - 0.1;
    wv = abs(imv*ones(1,length(imv)) - ones(length(imv),1)*imv');

并且您想在 Python 中实现此代码。 Imagee 是预定义的合成图像,由值为 0、1、2 的 10x10 数组表示。完成此任务的最有效方法是什么?我知道您可以迭代遍历整个矩阵并随时修改值,但我确信 python 有比这更快的方法。

编辑:澄清图像:(我已经将其翻译成python)

    C= np.zeros((L,L), int)
    C[:L/2,:L/2]=1
    C[L/2:L,:L/2]=2

我看到您已经在使用 numpy,这是朝着正确方向迈出的一步。现在,让我们一次一个地检查每个语句,并获得与您所追求的等效的 numpy。它说你的矩阵是 10 x 10,所以我假设 L = 10。这是我们开始的内容(IPython):

In [2]: import numpy as np

In [3]: L = 10

In [4]: C= np.zeros((L,L), int)

In [5]: C[:L/2,:L/2]=1

In [6]: C[L/2:L,:L/2]=2

In [7]: C
Out[7]:
array([[1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [2, 2, 2, 2, 2, 0, 0, 0, 0, 0],
       [2, 2, 2, 2, 2, 0, 0, 0, 0, 0],
       [2, 2, 2, 2, 2, 0, 0, 0, 0, 0],
       [2, 2, 2, 2, 2, 0, 0, 0, 0, 0],
       [2, 2, 2, 2, 2, 0, 0, 0, 0, 0]])

现在,让我们逐行逐行查看。


[xi yi imv] = find(imagee+0.1);

imv 基本上为您提供 imagee+0.1 中所有非零值的向量。但是,您需要记住的是,MATLAB 将 return 这些值 列优先 顺序,而 numpy 将在 [=64] 中执行相同的操作=]行优先顺序。如果您想在 Python 中复制相同的行为,您需要先 转置 矩阵。因此,为了方便起见,我将创建一个转置 imagee 并为每个条目添加 0.1 的新矩阵。但是,我有点困惑,因为如果 imagee 已经包含 0,1,2,如果您将此矩阵中的每个值都加上 0.1,imv 将 return all imagee+0.1 中的值...这对我来说似乎毫无意义。不过,您可以使用 numpy.nonzero 为您提供非零元素的位置。一旦你找到这些非零元素,你可以简单地索引到 C 添加 0.1 的转置以获得你想要的值。 numpy.nonzero 将 return 一个包含两个元素的元组,其中第一个元素是一个数组,告诉您 C+0.1 中那些非零值的行位置,第二个元素是一个数组告诉您 C+0.1:

中非零的列位置
In [9]: CT = C.T + 0.1

In [10]: ind = CT.nonzero()

In [11]: imv = CT[ind[0], ind[1]]

In [12]: imv
Out[12]:
array([ 1.1,  1.1,  1.1,  1.1,  1.1,  2.1,  2.1,  2.1,  2.1,  2.1,  1.1,
    1.1,  1.1,  1.1,  1.1,  2.1,  2.1,  2.1,  2.1,  2.1,  1.1,  1.1,
    1.1,  1.1,  1.1,  2.1,  2.1,  2.1,  2.1,  2.1,  1.1,  1.1,  1.1,
    1.1,  1.1,  2.1,  2.1,  2.1,  2.1,  2.1,  1.1,  1.1,  1.1,  1.1,
    1.1,  2.1,  2.1,  2.1,  2.1,  2.1,  0.1,  0.1,  0.1,  0.1,  0.1,
    0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,
    0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,
    0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,
    0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,
    0.1])

如果您在 MATLAB 中执行相同的操作,您会注意到 Python 和 MATLAB 中的 imv 给出相同的值顺序。


imv = imv - 0.1;

这很简单:

In [22]: imv = imv - 0.1

In [23]: imv
Out[23]:
array([ 1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,  2.,  2.,  1.,  1.,  1.,
        1.,  1.,  2.,  2.,  2.,  2.,  2.,  1.,  1.,  1.,  1.,  1.,  2.,
        2.,  2.,  2.,  2.,  1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,  2.,
        2.,  1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,  2.,  2.,  0.,  0.,
        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])

wv = abs(imv*ones(1,length(imv)) - ones(length(imv),1)*imv');

此语句的第一部分(在 abs 调用内)执行 outer product of two vectors. In MATLAB, imv would be N x 1, and you are multiplying this with a 1 x N vector of ones. You can use numpy.outer 以帮助您执行此外积步骤。请注意,对于一维数组,numpy 不区分行向量和列向量,因此不幸的是,将一个向量与另一个向量的转置相乘不会得到您期望的结果。但是,如果您想要这种行为,则必须显式定义一个二维矩阵,其单维度为 1(行或列),但我们将其放在一边 post.

此语句的第二部分也执行外积,但在语句第一部分的转置版本上。

因此:

In [24]: ones_vector = np.ones(len(imv))

In [25]: wv = np.abs(np.outer(imv, ones_vector) - np.outer(ones_vector, imv))

In [26]: wv
Out[26]:
array([[ 0.,  0.,  0., ...,  1.,  1.,  1.],
   [ 0.,  0.,  0., ...,  1.,  1.,  1.],
   [ 0.,  0.,  0., ...,  1.,  1.,  1.],
   ...,
   [ 1.,  1.,  1., ...,  0.,  0.,  0.],
   [ 1.,  1.,  1., ...,  0.,  0.,  0.],
   [ 1.,  1.,  1., ...,  0.,  0.,  0.]])

为了方便起见,代码的第一部分声明了一个向量。之后,我们计算你想要的。


希望对您有所帮助!