系统环境:
win10
matlab 2017b
python 3.6
主要有两种方式:
a. python安装mlab库 (截至目前最新版是1.1.4)
支持的matlab版本为R2006~R2014 a/b发行版都支持。支持系统函数调用及自定义函数调用(该方式可使用部分matlab工具箱)。
b. 使用matlab的python引擎
这种方式个人是从matlab R2015开始使用的,matlab官网有详细说明,但个人觉得这种方式功能比较受限。
-- linxwhut的回答 - 知乎 https://www.zhihu.com/question/39453532/answer/249530218
实际还有第三种。由于启动matlab引擎太慢,跨语言调用实际测试比直接运行更慢,而本机的进程通信是很快的,可以考虑把python作为服务器,matlab作为客户端,用socket通信来进行数据传递。
https://blog.csdn.net/tiancai13579/article/details/53039437
这里我选择了第二种方式。
Windows cmd打开,cd到:(matlab的目录)\extern\engines\python
输入:
python setup.py install
出错记录:本人在个人笔记本window10安装之后调用成功。
但是在服务器安装出现了一些问题。首先,服务器个人anaconda下安装,要么sudo下执行上述命令之后把build/matlab文件下复制到对应的anaconda3/envs/py36/lib/python3.6/site-packages目录下。或者把上述命令替换为:sudo /home/your_usr_name/anaconda3/envs/py36/bin/python setup.py install。
这之后又出现import的错误,奇怪的是并不是 import matlab.engine 的时候出错,而是在import scipy和 matplptlib中的plt时出错。报错主要部分如下:
这个问题再网上查,说是gcc更新之后这个动态链接库没有更新,需要把报错目录下的软链接删除换成最新的,BUT那个目录是服务器根目录下的,小的不敢轻举妄动啊!!!一阵纠结之后,尝试了不同的import的顺序,居然发现只要 from matplptlib import pyplot 在 import matlab.engine之前这两个都不会报错啦!!! 暂时可以解决这个问题。
import matlab.engine
eng = matlab.engine.start_matlab()
# 在python中使用,即可调用matlab函数等
# 例如
print(eng.sqrt(4.)) # 2.0
engine.sqrt([1.,2.,3.,4.,5.]) # Some error,MATLAB函数对于输入数据的类型有着比较严格的要求,一般python的list类型变量只需加上matlab.double就可以完成转换
engine.sqrt(matlab.double([1.,2.,3.,4.,5.])) # 返回matlab.double类型
eng.plot(matlab.int32([1, 2, 3, 4]), matlab.int32([1, 2, 3, 4]))
# 当我们需要执行某些Matlab命令时,可以利用eval函数对其进行输入
eng.eval("hold on", nargout=0)
eng.eval("plot([4, 3, 2, 1], [1, 2, 3, 4])", nargout=0)
eng.eval("hold on", nargout=0)
eng.eval("plot([4, 3, 2, 1], [1, 2, 3, 4])", nargout=0)
eng.eval("x = 3", nargout=0)
eng.eval("y = 41", nargout=0)
eng.eval("z = [213, 123]", nargout=0)
print(eng.workspace)
print(eng.workspace['x'], eng.workspace['z'])
"""
Name Size Bytes Class Attributes
x 1x1 8 double
y 1x1 8 double
z 1x2 16 double
3.0 [[213.0,123.0]]
"""
input("Press Enter to exit.") #???
# 退出引擎
eng.quit()
来自
Matlab的console界面显示的结果在Python中也会输出,
调用函数时需要设置nargout参数,当未设置时默认为1,即默认只返回1个参数,当知道Matlab返回参数的数量时,通过nargout进行设置来获取所有需要的参数。无参数返回时请设为0。
注意,在python中调用的函数名应该是文件名,且建议文件名和函数名一致。
遇到问题:找不到自定义的函数
在python命令行输入:
os.getcwd() # 返回 '路径A',为当前python文件路径
eng.edit('triarea',nargout=0) # 这里打开的路径是路径B,是matlab默认路径
分析,调用matlab函数,需要该函数在matlab的搜索路径中,而非python的搜索路径。
# 数组的基本使用,其基本使用方法与numpy类似,但是reshape()函数略有不同,
import matlab.engine
# Basic usage
int_8 = matlab.int8([1, 2, 3, 4, 5, 6])
print(int_8) # [[1, 2, 3, 4, 5, 6]]
print(int_8.size) # (1, 6)
int_8.reshape((2, 3)) # reshape function is different from numpy
print(int_8) # [[1, 3, 5], [2, 4, 6]]
double = matlab.double([[1, 2, 3], [4, 5, 6]])
print(double) # [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]
print(double[0]) # [1.0, 2.0, 3.0]
print(double[1][2]) # 6.0
# 对于数组的切片,Matlab的array与Python的list也有所不同,官网给出的解释在于,Matlab数组切片返回的是一个视图,而不是像Python中返回一个浅拷贝。
import matlab.engine
eng = matlab.engine.start_matlab()
# Slice array
py = [[1, 2, 3], [4, 5, 6]]
mt = matlab.int32([[1, 2, 3], [4, 5, 6]])
py[0] = py[0][::-1]
mt[0] = mt[0][::-1]
# Slicing a Matlab array returns a view instead of a shallow copy
print(py) # [[3, 2, 1], [4, 5, 6]]
print(mt) # [[3, 2, 3], [4, 5, 6]]
来自
from scipy.io import loadmat
m = loadmat(mat_file) # m是一个dict数据结构
etype = m['etype'][0].astype("int")
根据dict中的关键字对应mat文件中保存的变量名,
注意m中的每个遍历都是一个二维np数组。比如上面的etype在mat文件中为1为数组,m['etype']为二维数组。
读取的dict中到的数据均为np数组,
其中的数据类型整数自动转为uint8/uint16(小于255为uint8,超过255为uint16)
浮点类型自动转为对应的float型。
这里跟直接使用matlab引擎调用函数返回的数据类型不一样,调用matlab引擎返回的数据都是matlab特殊格式的数据,对于数组类型可以使用np.array转换,如果时list的话注意遍历转换。