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

问题描述

  • 我已经通过 Matlab 2019a 完成了相机校准,然后我保存了变量 cameraParams,它变成了所有相机参数,但我只对 内在矩阵感兴趣> 和 失真系数

  • 如何从 cameraParams.mat 文件提取这两个数组?Mat file attached here

  • 说明:(内在矩阵是3x3矩阵,畸变系数在Matlab中是4个,径向畸变2个,切向畸变2个)

  • 我尝试了以下代码,但不知道如何提取数组:

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]],dtype=uint32))]
__function_workspace__ [[ 0  1 73 ...  0  0  0]]

解决方法

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

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]],dtype=uint32))]
 --> Numpy array


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

最后 2 项已经是 numpy 数组,仅供参考 MatlabOpaque 类返回一个 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 会话中:

 check() async {

    final storage = new FlutterSecureStorage();

    String imi = await storage.read(key: "imei");
    //print(imi);
    showDialog(
        context: context,barrierDismissible: false,builder: (BuildContext context) {
          return Center(
              child: const SpinKitWave(
                  color: kPrimaryColor,type: SpinKitWaveType.center));
        });

    if (imi == "loginhuavaha") {
      setState(() {
        this._query();
        checkLogin = true;
      });
    }
  }

In [385]: data = loadmat('../Downloads/CameraParams.mat') 是一个 data,从中我们可以使用键来查看文件中的变量:

dict

In [386]: data Out[386]: {'__header__': b'MATLAB 5.0 MAT-file,Created on: Tue Feb 2 12:32:06 2021','__version__': '1.0','__globals__': [],'None': MatlabOpaque([(b'cameraParams',dtype=uint32))],dtype=[('s0','O'),('s1',('s2',('arr','O')]),'__function_workspace__': array([[ 0,1,73,...,0]],dtype=uint8)} 表示某种无法完全转换为 Python/numpy 的 MATLAB 对象或类。但这里它包含一个结构化数组:

MatlabOpaque

我们可以从中选择字段:

In [387]: data['None']
Out[387]: 
MatlabOpaque([(b'cameraParams','O')])
In [388]: data['None'].dtype
Out[388]: dtype([('s0','O')])

并使用 In [389]: data['None']['s0'] Out[389]: MatlabOpaque([b'cameraParams'],dtype=object) In [390]: data['None']['arr'] Out[390]: MatlabOpaque([array([[3707764736],dtype=uint32)],dtype=object) 将数组从对象数据类型包装器中取出:

item

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

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