【问题标题】:I have problem with converting MATLAB code to Python我在将 MATLAB 代码转换为 Python 时遇到问题
【发布时间】:2021-04-05 10:17:55
【问题描述】:

我需要将下面显示的代码块转换为 Python。我分别创建了两个名为uv 的数组,并将它们放在0 到M-1 范围内的for 循环中,我知道find 的工作方式类似于if 条件。我有一个问题,因为 idxu 都是数组。

MATLAB 代码是这样的:

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;

在遇到这个有问题的行之前,我在 Python 中所做的基本上是:

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)

【问题讨论】:

  • 您正在寻找 Numpy。我认为你应该阅读一些 Python 教程。 12。后者有一章专门介绍 Numpy。
  • 谢谢@Cris 我刚刚编辑了我的帖子。
  • 显然,Matlab 脚本是您的输入,而 Python 脚本是您的输出。请将 MatlabPython 脚本作为两个单独的代码块发布。目前,您已将 *** Matlab*** 和 Python 合并到一个代码块中。用井号分隔堆栈溢出后的两个代码块。 ### Original Matlab (input) ###### Attempted Python (output) ###
  • @Samuel,刚刚按照你提到的方式编辑了我的帖子。
  • 显然,您拥有的 MATLAB 代码计算了所谓的“离散傅里叶变换”的采样频率。离散傅里叶变换已得到充分研究。您确实不必必须编写自己的代码来计算离散傅立叶变换的采样频率。如果编写 MATLAB 代码的人没有写注释来解释他们正在计算什么,那么这个人就是一个非常糟糕的程序员。几乎不可能知道没有 cmets 应该做什么代码。为什么不直接使用类似get_fft_frequencies() 的函数?

标签: python arrays matlab image-processing


【解决方案1】:

u = 0:(M-1)Matlab 中做了什么,我们如何在 Python 中做同样的事情?

以下是您原始 Matlab 代码的摘录:

    % BEGIN MATLAB %

    u = 0:(M-1); 

    % END MATLAB %

代码有什么作用?

假设M = 7。那么Matlab代码就简化了:

    u = 0:6; 

结果是一个数组u,从0开始,到6结束:

u = [0   1   2   3   4   5   6]

本质上,您正在初始化一个连续整数数组。

Python中有多种方法可以完成类似的事情:

    # Begin Python   

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

    # End python

请注意,range(0, 7) 看起来像 [0, ..., 5, 6],而不是 [0, ..., 6, 7]
Python的range函数自动从上限中减去1

如果你真的在做 Matlab 类型的东西,那么 numpy 是你想在 Python 中使用的库

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

0 开始的索引与从 1 开始的索引

请注意,Matlab 索引从 1 开始。
Python 索引从 @987654338 开始@.
ARRAY = ["red", "blue", "white", "green"]

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

了解find 函数

findMatlab翻译成英文

考虑 Matlab 中的 find 函数:

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

函数调用find(u) 将在整个数组u 中搜索严格大于M/2 的任何内容。然后find(u) 将返回大于M/2 的所有索引的列表

考虑以下find 函数的示例:

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) 将查找u 的每个元素的索引大于或等于51

考虑代码u(idx) = 22;
我们有以下结果:

+---------------------+------+-----+-----+------+-----+-----+------+-----+------+
|   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   |
+---------------------+------+-----+-----+------+-----+-----+------+-----+------+

数组u 中大于或等于51 的所有内容都替换为22

find英语翻译成Python

假设您在 Python 中有一个数组 u
你想用22替换每个大于或等于51的整数
您可以在 Python 中使用 numpy 库来做到这一点:

# 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)   

注意u[u > 50] = 22和下面的一样:

# THIS IS PYTHON CODE (not matlab)   

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

# THIS IS PYTHON CODE (not matlab)    

findMatlab 转换为 Python

如果您将部分原始代码从 Matlab 转换为 Python,它将如下所示:

MATLAB 输入:

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

PYTHON 输出:

# 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)    

Matlab代码的所有ALL翻译成英文 数学

在文章的开头,我解释了您的 Matlab 代码的几个单独部分的作用。

现在,让我们将整个 Matlab 脚本翻译成英语和数学。

***下面有一些与您的原始/旧 MATLAB 相似的东西 ***

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

*** 表格中的行为***

我认为 Matlab 代码作为表格比作为代码更容易理解:

+--------------+---------------------------+
| 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 |
+--------------+---------------------------+

对于M > 7

  • 数组的左半部分是:[0, 1 , 2, 3, [...], floor(M/2)]
  • 数组的右半部分是:lang-none [(-1)*(x-0), (-1)*(x-1), (-1)*(x-2), [...], -3, -2, -1] 其中 x 等于 floor((M-1)/2)

将所有Matlab代码翻译成Python

以下 Python 脚本与 Matlab 脚本具有相同的输出:

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

我们可以像这样调用 Python 函数:

arr = generate_data(14)
print(arr)

输入14 的输出如下所示:

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

【讨论】:

    【解决方案2】:

    您的 MATLAB 代码

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

    可以通过省略find来更有效地实现:

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

    使用 NumPy 可以轻松地将这种形式转换为 Python:

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

    【讨论】:

    • 暂时假设M/2 是数字34。请注意,> 运算符对 numpy 数组有特殊定义。当unumpy 数组时,代码u > 34 searchers 数组u 用于每个大于34 的元素。我们提前知道u 是数组[0, 1, 2, 3, 4, 5, ...] u 的元素已经排好序并按顺序编号。在整个数组u 中搜索大于34 的元素是浪费时间。为了提高运行时效率,您可以编写 idx = range(1 + M/2, M)idx = range(1+ len(u)/2, len(u))
    • @SamuelMuldoon:我同意。您还可以连接两个半数组并避免减法。只需拨打fftfreq 就更容易了。
    猜你喜欢
    • 2019-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    • 2023-02-04
    相关资源
    最近更新 更多