使用system在MATLAB中运行python代码时输入变量

问题描述 投票:0回答:1

我在 MATLAB 脚本的这一部分中尝试运行 python 代码:

%%% MATLAB %%%
system(sprintf('python "%s" "%s" "%s"', 'Merge_CT_MRI_targets.py', num2str(OriginalPatients(index_target)), num2str(target_list(index_target))));
disp('test1')

这是Python脚本:

### PYTHON ###
import itk
import numpy as np
import os
import time

MRI_target = itk.imread("MRI_"+target+"_"+originalPatient+".nii", itk.F)

但是,看起来变量在 python 脚本中没有被正确调用:

% matlab command window %
Traceback (most recent call last): 
  File "Merge_CT_MRI_targets.py", line 23, in <module> 
    MRI_target = itk.imread("MRI_"+target+"_"+originalPatient+".nii", itk.F) 
                                   ^^^^^^ 
NameError: name 'target' is not defined 

如有任何帮助,我们将不胜感激。我之前尝试过使用pyrunfile,但它也带来了错误。

python matlab
1个回答
0
投票

注意:我用 Octave 尝试过此操作,因为我没有 MATLAB 许可证。

正如评论中已经暗示的那样,MATLAB 脚本和 Python 脚本之间的通信缺少两个基本方面:

  • 在 Python 脚本中处理 Python 脚本的输入。
  • 在 MATLAB 脚本中处理 Python 脚本的结果。

处理 Python 脚本的输入

这是更容易的部分:

  • 从 MATLAB 调用
    system('python script.py argA argB')
    会导致使用命令行参数
    script.py
    argA
    调用 Python 脚本
    argB
  • 在调用的 Python 脚本
    script.py
    中,可以通过
    sys.argv
    (字符串列表)使用命令行参数。

假设您有一个 Python 脚本

script.py
,其中包含以下内容:

### Contents of 'script.py' ###
import sys
print(sys.argv)

通过以下调用从命令行调用此脚本:

$ python script.py argA argB

然后你的输出将如下所示:

['script.py', 'argA', 'argB']

如您所见,所有命令行参数都可以作为字符串使用,前面加上被调用脚本本身的名称(或路径)。您现在可以在脚本中实际使用它们;例如,将它们转换为数字以进行计算,或者按照您的情况,将它们用作要加载的文件的名称。

处理 Python 脚本的输出

这是更棘手的部分,我不确定我的解决方案是否是最好的解决方案:

在 Python 脚本中完成所有数据处理后,您需要以某种方式将结果返回给 MATLAB。一种非常简单的方法是在 Python 脚本中打印结果,然后捕获输出作为 MATLAB 脚本中

system()
调用的返回值的一部分。

假设您还有Python脚本

script.py
,其内容与上面相同。另外,现在假设我们有一个 MATLAB 脚本
script.m
,其中包含以下内容:

%%% Contents of 'script.m' %%%
[status, output] = system('python script.py argA argB');
sprintf('From python: %s', output)

通过以下调用从命令行调用此脚本(同样,我在这里使用 Octave):

$ octave script.m

然后你的输出将如下所示:

ans = From python: ['script.py', 'argA', 'argB']

如您所见,我们得到了相同的输出,但这次来自 MATLAB 脚本(并且仅来自 MATLAB 脚本)。 MATLAB 脚本捕获

output
变量中的 Python 输出,然后对其进行处理(通过在前面添加
'From python: '
),并再次打印它。

将它们放在一起成为一个(某种程度上)更有用的示例

我们可以使用相同的方法不仅传递字符串,还传递实际数据。对于这种情况,我们可能希望将原始字节写入 Python 脚本中的输出,然后从 MATLAB 脚本中解析它们并将它们转换为相应的 MATLAB 对象。

以下示例...

  • (在 MATLAB 中)将数字
    n
    作为命令行参数发送到 Python;
  • (在 Python 中)创建一个
    n×n
    方阵,其中包含值
    0,1,…,n²-2,n²-1
    作为 2D Numpy 数组,然后打印相应
    float64
    值的原始字节;
  • (在 MATLAB 中)捕获原始字节并将其转换为相应的
    double
    值的 2D MATLAB 数组。

Python 脚本

script.py
:

### Contens of 'script.py' ###
import sys
import numpy as np

# Convert 1st argument to integer, then create square matrix of doubles with it
num = int(sys.argv[1])
data = np.arange(num*num, dtype=np.float64).reshape(num, num)
# Write resulting bytes to stdout
sys.stdout.buffer.write(data.tobytes())

MATLAB 脚本

script.m
:

%%% Contents of 'script.m' %%%
rows_cols = 3;
[status, res] = system(sprintf('python script.py %d', rows_cols));
numpy_data = reshape(typecast(uint8(res), 'double'), [rows_cols, rows_cols])'

Octave的命令行调用及相应输出:

$ octave script.m
numpy_data =

   0   1   2
   3   4   5
   6   7   8

如您所见,二维数组已成功重新实例化为 MATLAB 数组

numpy_data

实际上,这当然可能会更棘手:例如,如果Python脚本产生的输出不仅仅是我们真正感兴趣的原始数据,那么我们需要过滤掉我们感兴趣的部分(在MATLAB 端)或抑制所有不相关的输出(在 Python 端)。此外,正确获取字节数、形状和维度顺序可能并不总是像给定示例中那样简单(请注意,我们需要转置最终的 MATLAB 结果)。

© www.soinside.com 2019 - 2024. All rights reserved.