【问题标题】:How to extract Camera calibration parameters from matlab matrix .mat to python numpy arrays?如何从matlab矩阵.mat中提取相机校准参数到python numpy数组?
【发布时间】:2021-05-08 10:26:26
【问题描述】:
  • 我已经通过 Matlab 2019a 完成了相机校准,然后我保存了变量 cameraParams,它变成了所有的相机参数,但我只对 内在矩阵 感兴趣>失真系数

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

  • 澄清:(Intrinsic矩阵,是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],
       [         1],
       [         1]], dtype=uint32))]
__function_workspace__ [[ 0  1 73 ...  0  0  0]]

【问题讨论】:

    标签: python matlab numpy camera-calibration


    【解决方案1】:

    您已经了解 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
    

    最后两项已经是 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])
    

    【讨论】:

    • 是的,它们确实是numpy 数组,我的问题是:如何获得我的参数的正确索引(9 表示内在矩阵,4、5、8 可能是 12 表示失真)从答案中的最后一个 numpy 数组开始。
    • 最好看源码看看loadmat()的输出是如何构造的,源码中包含了一些直接按名称访问值的例子,见我回答底部的更新
    【解决方案2】:

    在 Ipython 会话中:

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

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

    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 表示某种不能完全转换为 Python/numpy 的 MATLAB 对象或类。但这里它包含一个结构化数组:

    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')])
    

    我们可以从中选择字段:

    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)
    

    【讨论】:

    • 感谢您的详细回答,我的困惑是:如何从最后一个中提取内在参数(3x3)矩阵= 9个元素,以及可以是4、5、8、12个元素的失真结果33848在您的回答中,我只是对如何找到正确的索引感到困惑。
    • MatlabOpaque 表示loadmat 无法查看它的内部 - 它是一个“不透明”,可能是某种无法转换为 Python/numpy 的 MATLAB 类或函数。您能做的最好的事情就是返回 MATLAB 源代码,并将这些参数写为单独的变量。
    【解决方案3】:

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

    您还可以查看this repo,以便轻松将 .mat 转换为 numpy。

    【讨论】:

      猜你喜欢
      • 2011-05-13
      • 2015-03-16
      • 1970-01-01
      • 1970-01-01
      • 2013-10-07
      • 1970-01-01
      • 2014-09-13
      • 2015-01-30
      • 1970-01-01
      相关资源
      最近更新 更多