[Python]Call matlab function from python(matlab engine)

Posted by John on 2018-11-12
Words 947 and Reading Time 3 Minutes
Viewed Times

這幾天我在研究一個matlab的程式碼,原本想看懂內容在用python自己實作一次,因為自己還是對python環境比較熟……但是我看不懂。

對。不是數學系出生的我怎麼看就是看不懂我需要的那段matlab的code再寫啥,崩潰。

於是念頭一轉,我有沒有辦法直接在python裡面呼叫matlab的function呢?嘿嘿,還真的有這個東西:MATLAB API for Python,所以我今天就來介紹它啦~

matlab engine安裝

首先必須先安裝MATLAB Engine API for python,方法如下:

  1. 使用cmd進到matlab的安裝目錄
  2. 進extern/engines/pythonpython
  3. setup.py install

安裝完後,就可以來使用matlab engine了!很簡單吧!

啊…先說我的matlab是2018b版本…

matlab engine for python範例

拿幾個官方範例先來一些簡單的介紹:

單純呼叫matlab檔案內的程式碼(沒有function)

先用matlab建立一個名稱為demo.m的檔案,輸入以下內容

b = 5;
h = 3;
a = 0.5*(b.* h)

接下來在同一個目錄下建立一個python檔案,輸入以下程式碼

1
2
3
import matlab.engine
eng = matlab.engine.start_matlab()
eng.demo(nargout=0)

簡單來說,就是我先import相關的package,然後啟動matlab engine,要怎麼引入寫好的matlab檔案呢?就是eng.demo,demo為matlab檔案的檔名,所以記得要放在同一個目錄下,而參數nargout=0代表沒有輸出的參數,這個之後會再講詳細一點。

呼叫matlab內的function

如果要呼叫matlab的function該怎麼辦呢?

首先,matlab要被呼叫的function名稱必須和檔名相同(這裡不是很確定,也有可能是matlab本來的規定),所以如果matlab內的程式碼長這樣(檔名為demo_function.m):

1
2
3
function out = demo_function()
out = 10;
end

那在python內呼叫他基本上跟第一個範例相同,不過因為function有一個回傳值,我們就可以用個變數去接住它。

1
2
3
4
import matlab.engine
eng = matlab.engine.start_matlab()
out = eng.demo_function(nargout=1)
print(out)

那,如果我說,愛我沒有如果…不是,如果function有多個參數呢?

1
2
3
4
function [out1, out2] = demo_function()
out1 = 10;
out2 = 20;
end

python那邊只要改一行就好了,分別是nargout的值跟接收回傳的變數,也就是說,回傳值有幾個變數nargout就要是多少。

1
2
[out1,out2] = eng.demo_function(nargout=2)
print(out1, out2)

換個寫法,當我有多個輸出的時候我也可以用matlab的struct包起來一起回傳,對應到python就會是dict型態的回傳值,你問我為什麼知道他是dict?matlab官方文擋(Handle Data Returned from MATLAB to Python)給了一個對照表讓我們可以了解語言之間型態的對應為何。

[sourcecode language=”matlab”] function out_struct = demo_function() out1 = 10; out2 = 20; out_struct = struct(out1, out2) end [/sourcecode]

呼叫matlab內的function,並傳入矩陣進行運算

我這次要做的事情是希望透過python傳入矩陣給matlab算完後再回傳結果給我就好,問題來了,matlab的矩陣在python是相同的型態嗎?顯然不是,而且python也沒matrix,傳ndarray也是不行的(我幫各位試過了),那到底要傳什麼進去matlab才會是矩陣呢?

官方文擋這篇有提到(MATLAB Arrays as Python Variables),我們可以用list來構構造矩陣結構,當成參數傳到matlab時對應到的就會是matrix,但只用list還是不夠的,還需要先透過他們的api進行轉換,如下方的python code:

1
2
3
A = [[1, 2], [2, 2], [3, 2]]
A = matlab.double(A)
engine.matlab_function_name(A)

上方的code中我將list透過matlab的api轉換成了double的matrix,不過這是對matlab來說,如果在python把他印出來仍然是一個list(型態都變成double了)。

好啦,今日的教學就到這裡了,如果有講錯的地方還請告訴我,謝謝~


>