如何从 matlab 矩阵 .mat 中提取相机校准参数到 python numpy 数组?
How to extract Camera calibration parameters from matlab matrix .mat to python numpy arrays?
我通过Matlab 2019a做了相机标定,然后我保存了变量cameraParams
,它变成了所有相机参数,但我只对[=26=感兴趣]内在矩阵和畸变系数.
如何从 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],
[ 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。
我通过Matlab 2019a做了相机标定,然后我保存了变量
cameraParams
,它变成了所有相机参数,但我只对[=26=感兴趣]内在矩阵和畸变系数.如何从
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],
[ 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。