使用Python读取含opencv-matrix的YAML文件报错及方案咨询
问题描述
我有如下test.yaml文件:
Camera.ColourOrder: "RGB" Camera.ColourDepth: "UCHAR_8" Camera.Spectrum: "Visible_NearIR" IMU.T_b_c1: !!opencv-matrix rows: 4 cols: 4 dt: f data: [0.999903, -0.0138036, -0.00208099, -0.0202141, 0.0137985, 0.999902, -0.00243498, 0.00505961, 0.0021144, 0.00240603, 0.999995, 0.0114047, 0.0, 0.0, 0.0, 1.0]
因文件包含!!opencv-matrix这类OpenCV相关对象,无法用Python内置YAML模块读取,尝试使用cv2.FileStorage读取时触发错误:
>>> import os >>> 'test.yaml' in os.listdir() True >>> import cv2 >>> fs = cv2.FileStorage("test.yaml", cv2.FILE_STORAGE_READ) cv2.error: OpenCV(4.8.1) /io/opencv/modules/core/src/persistence.cpp:699: error: (-5:Bad argument) Input file is invalid in function 'open' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "<stdin>", line 1, in <module> SystemError: <class 'cv2.FileStorage'> returned a result with an error set
即使移除IMU.T_b_c1部分,仅保留Camera相关配置,仍出现相同错误。请问我忽略了什么?另外,是否有其他模块可读取此类含OpenCV对象的YAML文件?
解决方案
1. 错误核心原因:OpenCV FileStorage不兼容标准YAML写法
OpenCV的FileStorage并非通用YAML解析器,它有严格的格式要求:
- 键名不能包含
.:OpenCV会将.识别为层级分隔符,但标准YAML中带.的键名是合法的,这会直接导致解析失败 - 部分版本要求文件开头必须加
%YAML:1.0声明 !!opencv-matrix的标签写法不符合OpenCV原生存储规范
2. 修复文件适配OpenCV FileStorage
修改test.yaml为以下格式即可正常读取:
%YAML:1.0 Camera: ColourOrder: "RGB" ColourDepth: "UCHAR_8" Spectrum: "Visible_NearIR" IMU: T_b_c1: rows: 4 cols: 4 dt: f data: [0.999903, -0.0138036, -0.00208099, -0.0202141, 0.0137985, 0.999902, -0.00243498, 0.00505961, 0.0021144, 0.00240603, 0.999995, 0.0114047, 0.0, 0.0, 0.0, 1.0]
读取代码示例:
import cv2 fs = cv2.FileStorage("test.yaml", cv2.FILE_STORAGE_READ) # 读取Camera参数 colour_order = fs.getNode("Camera").getNode("ColourOrder").string() # 读取变换矩阵 T_b_c1 = fs.getNode("IMU").getNode("T_b_c1").mat() fs.release()
3. 替代方案:用PyYAML+自定义构造器读取原文件
如果不想修改原文件,可以通过PyYAML配合自定义构造器解析!!opencv-matrix:
- 先安装依赖:
pip install pyyaml numpy - 解析代码:
import yaml import numpy as np # 自定义构造器处理!!opencv-matrix标签 def opencv_matrix_loader(loader, node): mapping = loader.construct_mapping(node, deep=True) rows = mapping['rows'] cols = mapping['cols'] dtype = np.float32 if mapping['dt'] == 'f' else np.float64 return np.array(mapping['data'], dtype=dtype).reshape(rows, cols) yaml.add_constructor('!!opencv-matrix', opencv_matrix_loader) # 读取原文件 with open('test.yaml', 'r') as f: config = yaml.load(f, Loader=yaml.FullLoader) # 访问参数示例 print(config['Camera.ColourOrder']) print(config['IMU.T_b_c1'])
该方法可直接读取原格式文件,并将!!opencv-matrix转换为numpy数组,方便后续处理。
内容的提问来源于stack exchange,提问作者MsA
相关产品推荐
相关产品推荐

