簡體   English   中英

“轉換” Numpy arrays 到 Matlab 反之亦然

[英]"Converting" Numpy arrays to Matlab and vice versa

我正在尋找一種將 Z3B7F949B2343F9E5390​​E29F6EF5E1778Z arrays 傳遞給 Matlab 的方法。

我已經設法做到這一點,方法是使用imread將數組存儲到圖像中,然后使用scipy.misc.imsave加載它,但這當然會導致矩陣包含 0 到 256 之間的值而不是“真實”值。

取這個矩陣除以 256 的乘積,原始 Z3B7F949B2343F9E5390​​E29F6EF5E1778Z 數組中的最大值給了我正確的矩陣,但我覺得這有點乏味。

有沒有更簡單的方法?

當然,只需使用scipy.io.savemat

舉個例子:

import numpy as np
import scipy.io

x = np.linspace(0, 2 * np.pi, 100)
y = np.cos(x)

scipy.io.savemat('test.mat', dict(x=x, y=y))

同樣,還有scipy.io.loadmat

然后使用load test在 matlab 中load test

或者,正如@JAB 建議的那樣,您可以將內容保存到 ascii 制表符分隔的文件(例如numpy.savetxt )。 但是,如果您走這條路線,您將被限制為 2 個維度。 另一方面,ascii 是通用交換格式。 幾乎任何東西都可以處理帶分隔符的文本文件。

一個簡單的解決方案,無需通過文件或外部庫傳遞數據。

Numpy 有一種方法可以將 ndarrays 轉換為列表,並且可以從列表中定義 matlab 數據類型。 所以,什么時候可以像這樣轉換:

np_a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
mat_a = matlab.double(np_a.tolist())

從matlab到python需要更多的關注。 沒有將類型直接轉換為列表的內置函數。 但是我們可以訪問原始數據,這些數據不是經過整形的,而是簡單的。 因此,我們使用reshape (正確格式化)和transpose (因為 MATLAB 和 numpy 存儲數據的方式不同)。 強調這一點非常重要:在您的項目中對其進行測試,主要是在您使用超過 2 個維度的矩陣時。 它適用於 MATLAB 2015a 和 2 個暗淡。

np_a = np.array(mat_a._data.tolist())
np_a = np_a.reshape(mat_a.size).transpose()

這是一個避免在 python 中迭代或使用文件 IO 的解決方案 - 以依賴(丑陋的)matlab 內部為代價:

import matlab
# This is actually `matlab._internal`, but matlab/__init__.py
# mangles the path making it appear as `_internal`.
# Importing it under a different name would be a bad idea.
from _internal.mlarray_utils import _get_strides, _get_mlsize

def _wrapper__init__(self, arr):
    assert arr.dtype == type(self)._numpy_type
    self._python_type = type(arr.dtype.type().item())
    self._is_complex = np.issubdtype(arr.dtype, np.complexfloating)
    self._size = _get_mlsize(arr.shape)
    self._strides = _get_strides(self._size)[:-1]
    self._start = 0

    if self._is_complex:
        self._real = arr.real.ravel(order='F')
        self._imag = arr.imag.ravel(order='F')
    else:
        self._data = arr.ravel(order='F')

_wrappers = {}
def _define_wrapper(matlab_type, numpy_type):
    t = type(matlab_type.__name__, (matlab_type,), dict(
        __init__=_wrapper__init__,
        _numpy_type=numpy_type
    ))
    # this tricks matlab into accepting our new type
    t.__module__ = matlab_type.__module__
    _wrappers[numpy_type] = t

_define_wrapper(matlab.double, np.double)
_define_wrapper(matlab.single, np.single)
_define_wrapper(matlab.uint8, np.uint8)
_define_wrapper(matlab.int8, np.int8)
_define_wrapper(matlab.uint16, np.uint16)
_define_wrapper(matlab.int16, np.int16)
_define_wrapper(matlab.uint32, np.uint32)
_define_wrapper(matlab.int32, np.int32)
_define_wrapper(matlab.uint64, np.uint64)
_define_wrapper(matlab.int64, np.int64)
_define_wrapper(matlab.logical, np.bool_)

def as_matlab(arr):
    try:
        cls = _wrappers[arr.dtype.type]
    except KeyError:
        raise TypeError("Unsupported data type")
    return cls(arr)

到達這里所需的觀察是:

  • Matlab 似乎只看type(x).__name__type(x).__module__來確定它是否理解類型
  • 似乎任何可索引的對象都可以放在._data屬性中

不幸的是,matlab 並沒有在內部有效地使用_data屬性,而是一次迭代一個項目,而不是使用 python memoryview協議:(。所以這種方法的速度增益是微不足道的。

scipy.io.savemat 或 scipy.io.loadmat 不適用於 matlab 數組 --v7.3。 但好的部分是 matlab --v7.3 文件是 hdf5 數據集。 因此可以使用許多工具讀取它們,包括 numpy。

對於 python,您將需要h5py擴展,它需要在您的系統上使用HDF5

import numpy as np, h5py 
f = h5py.File('somefile.mat','r') 
data = f.get('data/variable1') 
data = np.array(data) # For converting to numpy array

前段時間我遇到了同樣的問題,並編寫了以下腳本以允許在交互式會話中輕松地來回復制和粘貼數組。 顯然只適用於小數組,但我發現它比每次保存/加載文件更方便:

MATLAB -> Python

Python -> MATLAB

不確定它是否算作“更簡單”,但我找到了一種解決方案,可以從由 matlab 快速調用的 python 腳本中創建的 numpy 數組中移動數據:

dump_reader.py(python 源代碼):

import numpy

def matlab_test2():
    np_a    = numpy.random.uniform(low = 0.0, high = 30000.0, size = (1000,1000))
    return np_a

dump_read.m(matlab 腳本):

clear classes
mod = py.importlib.import_module('dump_reader');
py.importlib.reload(mod);

if count(py.sys.path,'') == 0
    insert(py.sys.path,int32(0),'');
end

tic
A = py.dump_reader.matlab_test2();
toc
shape = cellfun(@int64,cell(A.shape));
ls = py.array.array('d',A.flatten('F').tolist());
p = double(ls);
toc
C = reshape(p,shape);
toc

它依賴於這樣一個事實,即與單元格/矩陣相比,matlabs double 似乎在數組上有效地工作。 第二個技巧是以有效的方式(通過pythons native array.array)將數據傳遞給matlabs double。

PS 對 necroposting 感到抱歉,但我在它上面掙扎了很多,這個話題是最近的熱門話題之一。 也許它可以幫助某人縮短掙扎的時間。

使用 Matlab R2016b + python 3.5.4(64 位)測試的 PPS

Python 庫Darr允許您以自文檔化和廣泛可讀的格式保存 Python numpy 數組,該格式僅包含二進制文件和文本文件。 保存數組時,它將包含使用各種語言(包括 Matlab)讀取該數組的代碼。 所以本質上,在 Python 中將你的 numpy 數組保存到磁盤,然后從 README.txt 中復制粘貼代碼以將其加載到 Matlab 中只需一行。

披露:我寫了圖書館。

假設您有一個形狀為 (365,10) 的 2D 日常數據保存在np3Darrat數組中,該數據的形狀為 (5,365,10) 五年。 在 python 中保存你的 np 數組:

import scipy.io as sio     #SciPy module to load and save mat-files
m['np3Darray']=np3Darray   #shape(5,365,10)
sio.savemat('file.mat',m)  #Save np 3D array 

然后在 MATLAB 中將 np 3D 數組轉換為 MATLAB 3D matix:

load('file.mat','np3Darray')
M3D=permute(np3Darray, [2 3 1]);   %Convert numpy array with shape (5,365,10) to MATLAB matrix with shape (365,10,5)

In latest R2021a, you can pass a python numpy ndarray to double() and it will convert to a native matlab matrix, even when calling in console the numpy array it will suggest at the bottom "Use double function to convert to a MATLAB array"

從 MATLAB R2022a 開始,matlab.double(和 matlab.int8、ZC41DA48DFBCAC32DCZ6C1DA5791C56FBCZ.int8、ZC41DA48DFBCAC32DCZ6C1DA5791C56FBC.int8 等對象實現緩沖區) 這意味着您可以將它們傳遞給 Z3B7F949B2343F9E5390​​E29F6EF5E1778Z 數組構造函數。 也支持相反方向的施工。 也就是說,matlab 對象可以從實現緩沖協議的對象中構造出來。 因此,例如,可以從 Z3B7F949B2343F9E5390​​E29F6EF5E1778Z 雙數組構造 matlab.double。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM