python 读取 opencv yaml 文件

在 python 中, yaml 文件可以通过自带的 yaml 模块读取。然而读取 opencv 生成的 yaml 文件时发现,opencv 生成的 yaml 文件的格式跟标准的 yaml 文件有所不同,不能直接用 yaml 模块读取,需要用 opencv 提供的 API 读取。

在 opencv 中,可以通过FileStorage类读取 yaml 文件。然而,官方文档仅对 c++ 版的FileStorage 有比较详细的说明,而对 python 版的介绍较少,故对 python 版的接口进行了梳理。

样例文件

下面是一个存有相机标定参数的 yaml 文件,命名为 camera.yaml

%YAML:1.0
---
CameraExtrinsicMat: !!opencv-matrix
   rows: 1
   cols: 4
   dt: d                
   data: [1.363278865814209,-0.028192594647407532,-0.0095728300511837,-0.02877083793282509]
         #[height,pitch,roll,yaw]
CameraMat: !!opencv-matrix
   rows: 3
   cols: 3
   dt: d
   data: [ 1863.498779296875, 0., 1007.947998046875, 0.,1863.498779296875, 550.4793090820313, 0., 0., 1. ]
         #[fx,0,u0,0,fy,v0,0,0,1]
DistCoeff: !!opencv-matrix
   rows: 1
   cols: 5
   dt: d
   data: [-0.36602261662483215,0.13647031784057617, -0.0006322107510641217, -9.143427450908348e-05,0]
ImageSize: [ 1920, 1080 ]
ReprojectionError: 0
DistModel: plumb_bob

yaml 文件以 key-value 对的形式储存数据,相当于一个哈希表。可以看到,在上面的 yaml 文件中,主要有以下几种数据类型:

  • opencv-matrix: 这是 opencv 规定的矩阵类型
  • 列表(数组):即文件中的 “ImageSize”。在 opencv 中也叫 sequence。
  • 数值:即文件中的 “ReprojectionError”。在 opencv 中称 real。
  • 字符串:文件中的 “DistModel” 储存的是字符串。

下面将介绍如何用 opencv-python 读取 camera.yaml 中不同种类的数值

使用流程

opencv-python 读取 yaml 文件的基本流程如下:

  1. 实例化 FileStorage
  2. 根据 key 获得 FileNode,并转换它的数据类型
yamlpath = "./camera.yaml"
cv_file = cv2.FileStorage(yamlpath, cv2.FILE_STORAGE_READ) # 实例化一个 FileStorage
mat = cv_file.getNode("...").mat() # getNode 成员函数将获得一个 FileNode 类型的对象,mat() 函数将 FileNode 转换为矩阵

可以看到 FileStorage 通过 getNode 成员函数得到 FileNode 类型的对象。FileNode 类型再作为桥梁,转换为我们想要的数据类型。下面介绍 FileNode 类进行数据转换的方法。

  • 转换为矩阵
mat = cv_file.getNode("...").mat()
  • 转换为实数
val = cv_file.getNode("...").real()
  • 转换为字符串
str_ = cv_file.getNode("...").string()
  • 转换为列表(数组):将 FileNode 转换为列表较为麻烦。下面只介绍如何将 FileNode 转换为一个存有实数的列表
res = []
    for i in range(filenode.size()):
        res.append(filenode.at(i).real())

实例:读取 camera.yaml

介绍完 opencv-python 读取 yaml 文件的流程后,最后介绍下如何用前面的知识来读取 camera.yaml 文件。
具体代码如下:

def readListInFileNode(filenode):
    assert(filenode.isSeq())
    res = []
    for i in range(filenode.size()):
        res.append(filenode.at(i).real())
    return res

def readCameraCfg(yamlpath):
    cv_file = cv2.FileStorage(yamlpath, cv2.FILE_STORAGE_READ)

    res = {
            "CameraExtrinsicMat": cv_file.getNode("CameraExtrinsicMat").mat(),
            "CameraMat": cv_file.getNode("CameraMat").mat(),
            "DistCoeff": cv_file.getNode("DistCoeff").mat(),
            "ImageSize": readListInFileNode(cv_file.getNode("ImageSize")),
            "ReprojectionError": cv_file.getNode("ReprojectionError").real(),
            "DistModel": cv_file.getNode("DistModel").string()
            }
    return res

filepath = "/home/yxhuang/data/CICV/task4/task4/camera.yaml"
camera_cfg = readCameraCfg(filepath)
print(camera_cfg)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值