1

Suppose you have the following code in MATLAB:

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

And you want to implement this code in Python. Imagee is a predefined, synthetic image represented by a 10x10 array with values 0,1,2. What would be the most efficient method of accomplishing this? I know you could iteratively walk through the entire matrix and modify values as you go, but I'm sure python has a faster method than that.

EDIT: to clarify on imagee:(I have translated this to python already)

    C= np.zeros((L,L), int)
    C[:L/2,:L/2]=1
    C[L/2:L,:L/2]=2
3
  • 1
    I don't think you have to devectorize anything here. Just use numpy and write the vectorized python equivalent. I don't think there's anything in there that cannot be translated 1 to 1 into operations on whole numpy arrays. Commented May 30, 2015 at 18:44
  • 1
    "Imagee is a predefined, synthetic image represented by a 10x10 array with values 0,1,2. " <- To improve the question you could instead define imagee with a line or two of runnable Matlab code. Commented May 30, 2015 at 21:24
  • Thanks, I have made the necessary adjustment.In matlab, Imagee is the same dimensions as the array defined in my edit. Commented May 31, 2015 at 1:26

1 Answer 1

5

I see you're already using numpy, which is a step in the right direction. Now, let's go through each statement one at a time and get the numpy equivalent of what you're after. It says that your matrix is 10 x 10, and so I'm going to assume that L = 10. Here's what we'll start with (in 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]])

Now, let's go through each line one at a time.


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

imv basically gives you a vector of all values in imagee+0.1 that are non-zero. However, what you need to keep in mind is that MATLAB will return these values in column-major order whereas numpy will do the same operation in row-major order. If you want to replicate the same behaviour in Python, you'll need to transpose the matrix first. As such, I'll create a new matrix which transposes imagee and adds 0.1 to every entry for convenience. However, I'm a bit confused because if imagee already consists of 0,1,2, if you add every value in this matrix by 0.1, imv will return all values in imagee+0.1.... and that seems pointless to me. Nevertheless, you can use numpy.nonzero to give you the locations of the non-zero elements. Once you find these non-zero elements, you can simply index into the transpose of C added with 0.1 to get the values you want. numpy.nonzero will return a tuple of two elements where the first element is an array that tells you the row locations of those values that were non-zero in C+0.1 and the second element is an array that tells you the column locations that were non-zero in 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])

If you did the same operation in MATLAB, you'll notice that imv in both Python and MATLAB give the same order of values.


imv = imv - 0.1;

That's easy:

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');

The first part of this statement (inside the abs call) is performing the 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 to help you do this outer product step. Take note that for 1D arrays, numpy does not distinguish between row vectors and column vectors and so multiplying a vector with the transpose of another unfortunately won't give you what you expect. However, if you want this behaviour, you must explicitly define a 2D matrix that has a singleton dimension of 1 (either the rows or the columns), but let's put that aside for this post.

The second part of this statement also performs an outer product but on the transposed version of the first part of the statement.

Therefore:

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.]])

The first part of the code declares a vector of ones for convenience. After that, we calculate what you desire.


Hope this helps!

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks a bunch! Your step-by-step walkthrough really helped me understand more about converting between matlab matrices and python numpy arrays.
One more question I discovered after implementation: in np.outer(imv,0), documentation states that the second parameter is the second vector. Why is this zero? Why is it not a vector full of ones?
EDIT: I just now remembered we initialized 0 as our vector of ones. It must be too early for me to code. :)
@BrandonGinley - lol sorry. I probably should choose my variables more carefully. I've changed O to ones_vector. Thanks for checking!
@BrandonGinley - Made a small edit to my post. I forgot that MATLAB did things in column-major.... but it actually doesn't change what the final answer is. However, to be 100% correct I did a small change at the beginning of the code followed by some explanations. Good luck!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.