通过scipy.io.loadmat将matlab 3D矩阵传输到python 3D数组是错误的
我正在考虑一个有关Matlab矩阵和Python numpy数组的问题。我有一个用于医学图像处理的代码,给定一个3D数组作为输入(512x512个图像,80个切片->大小(图像)=(512512,80)。 输入最初由NifTI结构提供。 当我在matlab中加载Nii文件时,得到的大小是512x512x80。 在python中加载Nii文件时,我得到80x512x512作为大小(使用array.shape) 通过试用TestMatrix,我发现: Matlabs大小语法:(x=行,y=列,z=第三维度的切片) 大小的python语法:(z=第三维度中的切片,x=行,y=列) 现在我必须测试另一个数据,不是作为nii文件提供的,而是保存在mat文件中的。 使用Scipy的loadmat,我可以轻松地将矩阵加载到python程序中。 但是:现在在python中矩阵的大小也是(512512,80),下面的代码现在在第三维中采用512个切片,512行和80列(而不是80个切片,512x512个图像)。 我希望这是可以理解的解释 一个简单的例子: 我通过以下方式在Matlab中加载矩阵:通过scipy.io.loadmat将matlab 3D矩阵传输到python 3D数组是错误的,python,matlab,numpy,matrix,multidimensional-array,Python,Matlab,Numpy,Matrix,Multidimensional Array,我正在考虑一个有关Matlab矩阵和Python numpy数组的问题。我有一个用于医学图像处理的代码,给定一个3D数组作为输入(512x512个图像,80个切片->大小(图像)=(512512,80)。 输入最初由NifTI结构提供。 当我在matlab中加载Nii文件时,得到的大小是512x512x80。 在python中加载Nii文件时,我得到80x512x512作为大小(使用array.shape) 通过试用TestMatrix,我发现: Matlabs大小语法:(x=行,y=列,z=第
a = 1:12;
a = reshape(a, [1 3 4])
a(:,:,1) =
1 2 3
a(:,:,2) =
4 5 6
a(:,:,3) =
7 8 9
a(:,:,4) =
10 11 12
size(a)
ans =
1 3 4
与
我将一个文件保存在mat文件中。
现在我继续我的python代码,使用import scipy.io作为spio,我可以访问matfile:
mat = spio.loadmat('a.mat')
a = mat['a']
print(a)
Output:
[[[1 4 7 10]
[2 5 8 11]
[3 6 9 12]]]
print(a.shape)
Output:
(1,3,4)
但这是错误的!它在三维中没有4个切片,而是一个3x4矩阵。
我应该:
[[[ 1 2 3]]
[[ 4 5 6]]
[[ 7 8 9]]
[[10 11 12]]]
with shape (4,1,3)
那么,如何以python的精确顺序加载Matlab矩阵,从而使我的代码获得正确的切片呢?
此外,我还想再次将生成的python数组转换回matlab矩阵
非常感谢您!您误解了matlab的可视化:
a(:,:,1) =
1 2 3
不是否意味着a
的最后一个轴包含1 2 3
,这意味着第二个轴的第一个元素组是1 2 3
。Python只显示了完整的数组,matlab显示了该数组的列(我将列调用到第二个轴,假设忽略第一个轴,因为它是空的)
通过键入python,可以检查加载matlab和python的数组是否等效:
>>> a[:, :, 0]
array([[1, 2, 3]], dtype=uint8)
它给出的结果与matlab的可视化结果相同
Python和matlab只是有不同的可视化三维数组的方法
注意,matlab是Fortran排序的,这意味着数组中的列排在第一位,然后是行
matlab> reshape(1:6, [2, 3])
ans =
1 3 5
2 4 6
这一次,由于矩阵只有2列,因此可视化是您所期望的。如果您用python加载该矩阵,它也将被正确加载(python足够聪明,可以加载具有Fortran排序的numpy数组)。但是,请注意,当您尝试用python创建等效矩阵时,结果会截然不同:
python> np.arange(1,7).reshape(2, 3)
array([[1, 2, 3],
[4, 5, 6]])
顺序不同。在numpy中,数组默认为C顺序
最后,对于任何最新的numpy/scipy版本,您应该能够从matlab导入/导出矩阵,而无需任何修改
matlab> a = rand(512, 512, 10);
matlab> save /tmp/a.mat a
然后在python中加载它:
python> a = spio.loadmat('/tmp/a.mat')['a']
python> a.shape
(512, 512, 10)
矩阵是相同的。因此,matlab->python转换没有问题。您似乎只是希望在python中使用转置版本
如果需要pythonic
(10、512、512)
数组,只需将其转置:
python> a = np.ascontiguousarray(a.T)
如果您只想转置第二个轴和最后一个轴(如您的示例中所示),则可以使用交换键进行转置:
python> a = np.ascontiguousarray(np.swapaxes(a, 1, 2))
请注意,ascontiguousarray
将把数组(如果需要)复制到一个C顺序的连续内存块中。对于进一步的numpy处理例程来说效率更高
最后,以虚拟样本a
矩阵为例:
>>> np.swapaxes(a, 1, 2)
array([[[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]]], dtype=uint8)
我仍然会用np.ascontiguousarray
包装它,以确保数据被复制到新的内存块中
>>> np.swapaxes(a, 1, 2)
array([[[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]]], dtype=uint8)