我在 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,但它也带来了错误。
注意:我用 Octave 尝试过此操作,因为我没有 MATLAB 许可证。
正如评论中已经暗示的那样,MATLAB 脚本和 Python 脚本之间的通信缺少两个基本方面:
这是更容易的部分:
system('python script.py argA argB')
会导致使用命令行参数 script.py
和 argA
调用 Python 脚本 argB
。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 脚本中完成所有数据处理后,您需要以某种方式将结果返回给 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 对象。
以下示例...
n
作为命令行参数发送到 Python;n×n
方阵,其中包含值 0,1,…,n²-2,n²-1
作为 2D Numpy 数组,然后打印相应 float64
值的原始字节;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 结果)。