1.安装MATLAB Engine API并验证
1.1安装MATLAB Engine API
在MATLAB官网上有用于连接python的api
官网地址:用于安装 MATLAB Engine API 的 Python 设置脚本 - MATLAB & Simulink - MathWorks 中国
在Windows系统下只需要找到电脑中MATLAB安装地址中的python文件夹地址(该文件夹下有setup.py 文件)
以我为例即是E:\MATLAB\extern\engines\python
在cmd中切换到该地址并输入python setup.py install之后按下回车即可
1.2验证安装成功
在pycharm中引入该包
可以看到该包没有标红
至此MATLAB Engine API已经安装成功
需要注意的是该API是根据用户电脑的环境变量的python环境下载的,能运行的只有电脑中环境变量的python环境,虚拟环境是行不通的,故在编译器中记得选择正确的环境
2.在python中运行MATLAB函数
单纯的在python中调用MATLAB函数及其简单,只需要启动运行MATLAB包中的引擎经即可
用以下例子说明:
% mat.m
function a = mat()
a = 'Hello, World!';
end
import matlab.engine
#启动MATLAB引擎,并将引擎对象赋值给变量eng
eng = matlab.engine.start_matlab()
# 调用MATLAB函数
print(eng.mat())
# 关闭MATLAB引擎
eng.quit()
mat函数运行结果为返回一个“Hello,World”
在python中先导入matlat包,再初始化matlab引擎并赋值给eng,之后的调用matlab函数的操作就由eng完成,最后关闭引擎
这是输出结果:
3.在Django中连接并运行MATLAB
在Django中调用MATLAB函数就不像单纯在python中调用那么简单
首先我们按照之前的思路写一个helloworld代码:
%mat.m
function returning = mat()
returning = 'hello world';
end
from django.shortcuts import render
import matlab.engine
def helloworld(request):
eng = matlab.engine.start_matlab()
a = eng.mat()
eng.quit()
return render(request, 'helloworld.html', {"n1": a})
<!--helloworld.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello World Display</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
}
img {
max-width: 100%;
height: auto;
margin-top: 20px;
}
</style>
</head>
<body>
<h1>Hello World Display</h1>
<div>{{ n1 }}</div>
</body>
</html>
该代码按理来说运行成功之后会在前端界面上打印“hello world”
然而事实是
后来查到原因可能是因为MATLAB的引擎找不到该函数的路径
解决方法是在代码中添加一行
eng.cd('/*函数所在文件夹*/', nargout=0)
以我为例,修改后的代码即为:
def helloworld(request):
eng = matlab.engine.start_matlab()
eng.cd('D:\PycharmProjects\djangotest3\index', nargout=0)
a = eng.mat()
eng.quit()
return render(request, 'helloworld.html', {"n1": a})
运行一下
运行成功!
至此运行MATLAB函数并将数据打印到前端界面上已经成功
现在只剩最后一项
4.在Django中打印出MATLAB运行的图片结果
想要打印图片就必须得先获取图片,这点是最难难搞的,在尝试了许多办法之后,最后还是靠GPT跑出来的一段代码运行成功的,该方法需要获取到MATLAB的图像句柄之后,将图像以 Base64 编码的形式传递给模板。
首先,启动MATLAB引擎,调用m函数并获取图形句柄
# 启动 MATLAB 引擎
eng = matlab.engine.start_matlab()
eng.cd('D:\PycharmProjects\djangotest3\index', nargout=0)
# 执行 MATLAB 脚本文件
eng.eval("run('test.m');", nargout=0)
# 获取当前图形句柄
fig_handle = eng.gcf()
# 将图像数据传输到 Python 中
matlab_image_data = eng.getframe(fig_handle, nargout=1)
接着,检查并转换图像数据格式,如果数据格式符合预期,将图像数据转换为 NumPy 数组;否则,抛出异常
# 检查数据类型并转换为 NumPy 数组
if isinstance(matlab_image_data, dict) and 'cdata' in matlab_image_data:
matlab_image = np.asarray(matlab_image_data['cdata'], dtype=np.uint8)
else:
raise ValueError("Unexpected image data format from MATLAB")
关闭引擎
eng.quit()
将 NumPy 数组中的图像数据转换为 PIL 图像对象
image = Image.fromarray(matlab_image)
将 PIL 图像对象转换为字节流,并进行 Base64 编码
# 将 PIL 图像对象转换为字节流
image_stream = BytesIO()
image.save(image_stream, format='PNG') # 你可以根据实际情况选择图像格式
# 获取字节流的 Base64 编码
image_base64 = base64.b64encode(image_stream.getvalue()).decode('utf-8')
最后,将 Base64 编码后的图像数据传递到模板中,并渲染模板
# 将图像数据传递到模板
return render(request, 'imgshow.html', {'image_data': image_base64})
以下是完整代码:
%test.m
% 定义x的范围,从-10到10
x = -10:0.1:10;
% 计算y = 3 * x
y = 3 * x;
% 绘制折线图
plot(x, y)
% 添加图表标题
title('y = 3 * x')
% 添加x轴和y轴的标签
xlabel('x')
ylabel('y')
% 显示网格
grid on
<!--imgshow.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MATLAB Image</title>
</head>
<body>
<h1>MATLAB Image</h1>
<img src="data:image/png;base64,{{ image_data }}" alt="Matplotlib Image">
</body>
</html>
from PIL import Image
from django.shortcuts import render
import numpy as np
import matlab.engine
from io import BytesIO
import base64
def imgshow(request):
# 启动 MATLAB 引擎
eng = matlab.engine.start_matlab()
eng.cd('D:\PycharmProjects\djangotest3\index', nargout=0)
# 执行 MATLAB 脚本文件
eng.eval("run('test.m');", nargout=0)
# 获取当前图形句柄
fig_handle = eng.gcf()
# 将图像数据传输到 Python 中
matlab_image_data = eng.getframe(fig_handle, nargout=1)
# 检查数据类型并转换为 NumPy 数组
if isinstance(matlab_image_data, dict) and 'cdata' in matlab_image_data:
matlab_image = np.asarray(matlab_image_data['cdata'], dtype=np.uint8)
else:
raise ValueError("Unexpected image data format from MATLAB")
# 关闭 MATLAB 引擎
eng.quit()
# 将图像数据转换为 PIL 图像对象
image = Image.fromarray(matlab_image)
image.show()
# 将 PIL 图像对象转换为字节流
image_stream = BytesIO()
image.save(image_stream, format='PNG') # 你可以根据实际情况选择图像格式
# 获取字节流的 Base64 编码
image_base64 = base64.b64encode(image_stream.getvalue()).decode('utf-8')
# 将图像数据传递到模板
return render(request, 'imgshow.html', {'image_data': image_base64})
最后输出结果:
当然,不排除有更加简单的方法,但碍于实力有限,且网上没有相关教程,目前只有这种方法能成功运行
至此,在Django中的MATLAB的一系列操作便已完成