从MATLAB到Python的实现,无需迭代

Bra*_*ley 1 python arrays iteration matlab numpy

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

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

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

编辑:澄清imagee :(我已经把它翻译成python)

    C= np.zeros((L,L), int)
    C[:L/2,:L/2]=1
    C[L/2:L,:L/2]=2
Run Code Online (Sandbox Code Playgroud)

ray*_*ica 5

我看到你已经在使用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]])
Run Code Online (Sandbox Code Playgroud)

现在,让我们一次一个地浏览每一行.


[xi yi imv] = find(imagee+0.1);
Run Code Online (Sandbox Code Playgroud)

imv基本上给你一个非零的所有值的向量imagee+0.1.但是,您需要记住的是,MATLAB将按列主要顺序返回这些值,numpy将以行主顺序执行相同的操作.如果要在Python中复制相同的行为,则需要首先转置矩阵.因此,imagee为了方便起见,我将创建一个新的矩阵,用于转换每个条目并添加0.1.但是,我有点困惑,因为如果imagee已经包含0,1,2,如果你将此矩阵中的每个值加0.1,imv将返回....中的所有imagee+0.1,这对我来说似乎毫无意义.不过,您可以使用它numpy.nonzero来为您提供非零元素的位置.一旦找到这些非零元素,您就可以简单地索引C添加的转置0.1以获取所需的值. numpy.nonzero将返回两个元素的元组,其中第一个元素是一个数组,告诉你那些非零的值的行位置,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])
Run Code Online (Sandbox Code Playgroud)

如果你在MATLAB中做了相同的操作,你会发现imv在Python和MATLAB中都给出了相同的值顺序.


imv = imv - 0.1;
Run Code Online (Sandbox Code Playgroud)

这很简单:

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.])
Run Code Online (Sandbox Code Playgroud)
wv = abs(imv*ones(1,length(imv)) - ones(length(imv),1)*imv');
Run Code Online (Sandbox Code Playgroud)

本声明的第一部分(在abs调用内)是执行两个向量的外积.在MATLAB中,imv将是N x 1,并且您将它与一个1 x N向量相乘.您可以使用它numpy.outer来帮助您执行此外部产品步骤.请注意,对于1D数组,numpy不区分行向量和列向量,因此将向量与另一个向量相乘可能不会给出您期望的结果.但是,如果您需要此行为,则必须显式定义单个维度为1(行或列)的2D矩阵,但是让我们将此放在此帖子中.

本声明的第二部分也执行外部产品,但是在声明第一部分的转置版本上.

因此:

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.]])
Run Code Online (Sandbox Code Playgroud)

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


希望这可以帮助!