如何从 matlab 矩阵 .mat 中提取相机校准参数到 python numpy 数组?

How to extract Camera calibration parameters from matlab matrix .mat to python numpy arrays?

import scipy.io as sio
import numpy as np

Mat = sio.loadmat('CameraParams.mat')

for key in Mat :
    print(key, Mat[key])

输出为:

__header__ b'MATLAB 5.0 MAT-file, Platform: PCWIN64, Created on: Tue Feb  2 12:32:06 2021'
__version__ 1.0
__globals__ []
None [(b'cameraParams', b'MCOS', b'cameraParameters', array([[3707764736],
       [         2],
       [         1],
       [         1],
       [         1],
       [         1]], dtype=uint32))]
__function_workspace__ [[ 0  1 73 ...  0  0  0]]

IMO你已经弄明白了。请注意,使用 type()isinstance() 来查看您正在处理的变量类型很有用。 在我的代码中,numpy 数组在 if instance() 语句下作为 v 可用:

import scipy.io as sio
import numpy as np

Mat = sio.loadmat('CameraParams.mat')

for k, v in Mat.items():
    print("\n\n", k, type(v), v)
    if isinstance(v, np.ndarray):  # Numpy array?
        print(' --> Numpy array')

输出:

 __header__ <class 'bytes'> b'MATLAB 5.0 MAT-file, Platform: PCWIN64, Created on: Tue Feb  2 12:32:06 2021'


 __version__ <class 'str'> 1.0


 __globals__ <class 'list'> []


 None <class 'scipy.io.matlab.mio5_params.MatlabOpaque'> [(b'cameraParams', b'MCOS', b'cameraParameters', array([[3707764736],
       [         2],
       [         1],
       [         1],
       [         1],
       [         1]], dtype=uint32))]
 --> Numpy array


 __function_workspace__ <class 'numpy.ndarray'> [[ 0  1 73 ...  0  0  0]]
 --> Numpy array

最后 2 项已经是 numpy 数组,仅供参考 MatlabOpaque class returns 一个 numpy 数组: https://github.com/scipy/scipy/blob/master/scipy/io/matlab/mio5_params.py#L247

至于loadmat()方法的输出,似乎有些元素如果你知道它们的名字就可以直接访问https://github.com/scipy/scipy/blob/v1.6.0/scipy/io/matlab/mio.py#L214

matstruct_squeezed = sio.loadmat(matstruct_fname, squeeze_me=True)
matstruct_squeezed['teststruct']['complexfield'].item()
array([ 1.41421356+1.41421356j,  2.71828183+2.71828183j,
        3.14159265+3.14159265j])

在 Ipython 会话中:

In [385]: data = loadmat('../Downloads/CameraParams.mat')

data是一个dict,从中我们可以使用keys从文件中查看变量:

In [386]: data
Out[386]: 
{'__header__': b'MATLAB 5.0 MAT-file, Platform: PCWIN64, Created on: Tue Feb  2 12:32:06 2021',
 '__version__': '1.0',
 '__globals__': [],
 'None': MatlabOpaque([(b'cameraParams', b'MCOS', b'cameraParameters', array([[3707764736],
        [         2],
        [         1],
        [         1],
        [         1],
        [         1]], dtype=uint32))],
              dtype=[('s0', 'O'), ('s1', 'O'), ('s2', 'O'), ('arr', 'O')]),
 '__function_workspace__': array([[ 0,  1, 73, ...,  0,  0,  0]], dtype=uint8)}

MatlabOpaque 表示某种 MATLAB 对象或 class 不能完全转换为 Python/numpy。但是这里它包含一个结构化数组:

In [387]: data['None']
Out[387]: 
MatlabOpaque([(b'cameraParams', b'MCOS', b'cameraParameters', array([[3707764736],
       [         2],
       [         1],
       [         1],
       [         1],
       [         1]], dtype=uint32))],
             dtype=[('s0', 'O'), ('s1', 'O'), ('s2', 'O'), ('arr', 'O')])
In [388]: data['None'].dtype
Out[388]: dtype([('s0', 'O'), ('s1', 'O'), ('s2', 'O'), ('arr', 'O')])

从中我们可以 select 个字段:

In [389]: data['None']['s0']
Out[389]: MatlabOpaque([b'cameraParams'], dtype=object)

In [390]: data['None']['arr']
Out[390]: 
MatlabOpaque([array([[3707764736],
       [         2],
       [         1],
       [         1],
       [         1],
       [         1]], dtype=uint32)], dtype=object)

并使用 item 将数组从对象 dtype 包装器中拉出:

In [391]: data['None']['arr'].item()
Out[391]: 
array([[3707764736],
       [         2],
       [         1],
       [         1],
       [         1],
       [         1]], dtype=uint32)

那是一个(6,1)数组。

In [392]: data['__function_workspace__']
Out[392]: array([[ 0,  1, 73, ...,  0,  0,  0]], dtype=uint8)
In [393]: data['__function_workspace__'].shape
Out[393]: (1, 33848)

问题是无法访问 mbauman's answer 中所述的 MatlabOpaque 对象。最简单的解决方案是在 MATLAB 中将对象重新保存为 struct(CameraParams).

您还可以检查 this repo 以便从 .mat 轻松转换为 numpy。