I have problem with converting MATLAB code to Python

I need to convert the block of code that's shown below to Python. I created two arrays named u and v seperately and put them in a for loop in the range 0 to M-1 and I know find works similar to if condition. I have a problem since both idx and u are arrays.

MATLAB code is this:

u = 0:(M-1); 
v = 0:(N-1); 
idx = find(u > M/2); 
u(idx) = u(idx) - M; #I have a problem here
idy = find(v > N/2); 
v(idy) = v(idy) - N;

Basically what I have done in Python until I got to this problematic line is:

input_image = Image.open('./....image....')
input_image=np.array(input_image)
M,N = input_image.shape[0],input_image.shape[1]

FT_img = fftpack.fftshift(fftpack.fft2(input_image))

# Assign the order value 
n = 2; # one can change this value accordingly 
  
# Assign Cut-off Frequency 
D0 = 60; # one can change this value accordingly 
  
# Designing filter 
u=[]
v=[]
for i in range(M-1):
  u.append(i)

for i in range(N-1):
  v.append(i)

Upvotes: 1

Views: 792

Answers (2)

Toothpick Anemone
Toothpick Anemone

Reputation: 4636

What does u = 0:(M-1) do in Matlab and how can we do the same thing in Python?

The following is one excerpt from your original Matlab code:

    % BEGIN MATLAB %

    u = 0:(M-1); 

    % END MATLAB %

What does the code do?

Suppose that M = 7. Then the Matlab code simplifies:

    u = 0:6; 

The result is an array u beginning at 0 and ending at 6:

u = [0   1   2   3   4   5   6]

Essentially, you are initializing an array of consecutive integers.

There are various ways to accomplish something similar in Python:

    # Begin Python   

    M = 7
    u = list(range(0, M))

    # End python

Note that range(0, 7) looks like [0, ..., 5, 6], not [0, ..., 6, 7]
Python's range function automatically subtracts 1 from the upper limit

If you really are doing Matlab-type stuff, then numpy is the library you want to use in Python:

import numpy as np
u = np.array(range(0, 7))

Indexing beginning at 0 versus indexing beginning at 1

Note that Matlab indexing begins at 1.
Python indexing begins at 0.
ARRAY = ["red", "blue", "white", "green"]

+--------------+-------+--------+---------+---------+
|    ARRAY     | "red" | "blue" | "white" | "green" |
+--------------+-------+--------+---------+---------+
| PYTHON INDEX |     0 |      1 |       2 |       3 |
| MATLAB INDEX |     1 |      2 |       3 |       4 |
+--------------+-------+--------+---------+---------+

Understanding the find function

Translating find from Matlab into English

Consider the find function from Matlab:

idx = find(u > M/2);    % this is matlab-code

The function-call find(u) will search the entire array u for anything strictly larger than M/2. find(u) will then return a list of all indices for things larger than M/2

Consider the following example of the find function:

u  = [98 00 00 87 49 50 51 00 85];
%      1  2  3  4  5  6  7  8  9 .....ARRAY INDICIES
idx = find(u > 50);
disp(idx)
% displays .... 1   4   7   9

find(u > 50) will find the indices of every element of u greater than or equal to 51

Consider the code u(idx) = 22;
We have the following results:

+---------------------+------+-----+-----+------+-----+-----+------+-----+------+
|   MATLAB INDICIES   |  1   |  2  |  3  |  4   |  5  |  6  |  7   |  8  |  9   |
+---------------------+------+-----+-----+------+-----+-----+------+-----+------+
| print(u)            | 99   | 00  | 00  | 99   | 49  | 50  | 51   | 00  | 99   |
+---------------------+------+-----+-----+------+-----+-----+------+-----+------+
| % u > 50?           | %yes | %no | %no | %yes | %no | %no | %yes | %no | %yes |
+---------------------+------+-----+-----+------+-----+-----+------+-----+------+
| idx = find(u > 50); |      |     |     |      |     |     |      |     |      |
| u(idx) = 22;        |      |     |     |      |     |     |      |     |      |
+---------------------+------+-----+-----+------+-----+-----+------+-----+------+
| print(u)            | 22   | 0   | 0   | 22   | 49  | 50  | 22   | 0   | 22   |
+---------------------+------+-----+-----+------+-----+-----+------+-----+------+

Everything inside of array u greater than or equal to 51 was replaced with 22

Translating find from English to Python

Suppose that you have an array u in Python.
You want to replace every integer greater than or equal to 51 with 22
You can do that in Python using the numpy library:

# This is Python (not matlab)
import numpy as np

u = [98 00 00 87 49 50 51 00 85];
u = np.array(u)
u[u > 50] = 22

# THIS IS PYTHON CODE (not matlab)   

Note that u[u > 50] = 22 is the same as the following:

# THIS IS PYTHON CODE (not matlab)   

indicies = type(u).__gt__(u, 50)
u.__setitem__(indicies, 22)  

# THIS IS PYTHON CODE (not matlab)    

Translating find from Matlab to Python

If you translate part of your original code from Matlab to Python it would look like the following:

MATLAB INPUT:

M = 7      
u = 0:(M-1);     
idx = find(u > M/2); 
u(idx) = u(idx) - M;

PYTHON OUTPUT:

# THIS IS PYTHON CODE (not matlab)   
 
import numpy as np
M = 7    
u = np.array(range(0, M))   
idx = u > M/2
u[idx] = u[idx] - M  

# THIS IS PYTHON CODE (not matlab)    

Translating all ALL of the Matlab code into English and Mathematics

In the beginning of the post I explained what a few individual pieces of your Matlab code do.

Now, let us translate the entire Matlab script into English and Math.

*** SOMETHING SIMILAIR TO YOUR ORIGINAL/OLD MATLAB IS BELOW ***

function u = GenerateArray(M)
    u = 0:(M-1); 
    idx = find(u > M/2); 
    u(idx) = u(idx) - M; 
end

M = 7;
u = GenerateArray(M);

N = 9;
v = GenerateArray(N);

*** THE BEHAVIOR AS A TABLE***

I think that the Matlab code is easier to understand as a table, than as code:

+--------------+---------------------------+
| WHOLE NUMBER |           ARRAY           |
| `M`          |  `u`                      |
+--------------+---------------------------+
| 4            | 0   1   2  -1             |
| 5            | 0   1   2  -2  -1         |
| 6            | 0   1   2   3  -2  -1     |
| 7            | 0   1   2   3  -3  -2  -1 |
+--------------+---------------------------+

For M > 7:

  • the left half of the array is: [0, 1 , 2, 3, [...], floor(M/2)]
  • the right half of the array is: lang-none [(-1)*(x-0), (-1)*(x-1), (-1)*(x-2), [...], -3, -2, -1] where x equals floor((M-1)/2)

Translating all of the Matlab code into Python

The following Python script has the same output as the Matlab script:

import numpy as np
import itertools as itts

def generate_data(array_size : int) -> type(np.array(range(0, 1))):
    """
    +--------------+---------------------------+
    | INPUT        |           OUTPUT          |
    +--------------+---------------------------+
    | 4            | 0   1   2  -1             |
    | 5            | 0   1   2  -2  -1         |
    | 6            | 0   1   2   3  -2  -1     |
    | 7            | 0   1   2   3  -3  -2  -1 |
    +--------------+---------------------------+

     * the left side of the array:
         starts at:
             zero

         ends at:
             floor(M/2)

         counts by:
             +1

         looks like:
             [0, 1 , 2,  3,  [...],  floor(M/2)]

     * the right side of the array...
         starts at
            (-1) * floor((M-1)/2)

         ends at:
             -1

         counts by:
             -1

         looks like:
             [
                 (-1) * floor((M-1)/2),
                 (-1) * (floor((M-1)/2) - 1),
                 (-1) * (floor((M-1)/2) - 2),
                 [...],
                 -3,
                 -2,
                 -1
            ]

    """
    # clean_input = int(dirty_input)
    n = int(array_size)

    # make the first element of the left side of the array be zero.
    # left_side_first = 0
    lsf = 0

    # left_side_last = clean_input // 2
    lsl = n // 2

    # left_side_iterator =  range(left_side_first, 1 + left_side_last)
    lsit = range(lsf, 1 + lsl)
    # `list` stands for "left side iterator"

    right_side_first = (-1) * ((n - 1) // 2)
    right_side_last = -1
    right_side_iterator = range(right_side_first, 1 + right_side_last)

    # merged_iterator = chain(left_side_iterator, right_side_iterator)
    merged_iterator = itts.chain(lsit, right_side_iterator)

    output = np.array(list(merged_iterator))

    # We convert the iterator to a `list` because the following
    # direct use of the iterator does not work:
    #
    #    output = np.array(merged_iterator)

    return output

We can call the Python function like so:

arr = generate_data(14)
print(arr)

The output for input 14 is shown below:

[ 0  1  2  3  4  5  6  7 -6 -5 -4 -3 -2 -1]

Upvotes: 3

Cris Luengo
Cris Luengo

Reputation: 60695

Your MATLAB code

u = 0:(M-1);
idx = find(u > M/2);
u(idx) = u(idx) - M;

can be more efficiently implemented by leaving out find:

u = 0:(M-1);
idx = u > M/2;
u(idx) = u(idx) - M;

This form is trivially translatable to Python with NumPy:

u = np.arange(0, M)
idx = u > M/2
u[idx] = u[idx] - M

Upvotes: 1

Related Questions