昊虹AI笔记网

 找回密码
 立即注册
搜索
查看: 882|回复: 0
收起左侧

利用opencv中的类FileStorage生成和读取XML和YAML文件

[复制链接]

238

主题

241

帖子

931

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
931
昊虹君 发表于 2022-10-29 09:11 | 显示全部楼层 |阅读模式
利用opencv中的类FileStorage生成和读取XML和YAML文件

有时候程序中的变量值、字符串、数组等数据也需要独立于源代码本身保存,这个时候就需要用到XML和YAML文件进行保存。

OpenCV4提供了用于生成和读取XML文件和YAML文件的类FileStorage,该类的构造函数原型有两种,分别如下:

其构造函数的第一种原型如下:
C++:
  1. cv::FileStorage::FileStorage()
复制代码

Python:
  1. <FileStorage object> = cv.FileStorage()
复制代码

其构造函数的第二种原型如下:
C++:
  1. cv::FileStorage::FileStorage(const String & filename,int flags,const String & encoding = String() )
复制代码

Python:
  1. <FileStorage object> = cv.FileStorage(filename, flags[, encoding])
复制代码

构造函数的第一种原型基本大家都不用,因为没有任何初始化参数,相当于只定义,不做初始化。

通常用的都是构造函数的第二种原型。
第二种构造函数原型中各参数的意义如下:
filename---生成或读取的XML或YAML文件名称,可以使用的后缀名有.xml、.yml/.yaml 、 .json。

flags—操作模式选择。其可选值及意义如下:
  • READ---读取文件中的数据
  • WRITE ---向打开的文件中写入数据,如果文件不存在,则生成新的文件
  • APPEND ---向打开的文件的末尾写入数据,如果文件不存在,则生成新的文件
  • MEMORY ---read data from source or write data to the internal buffer(从source读取数据或者写入数据到内部缓冲,这里source该怎么理解?是理解为“源文件”?)
  • FORMAT_MASK---mask for format flags(格式标志的掩码...这个具体是什么意思博主也不清楚...有清楚的请在此博文下留言吧!博主猜想应该是对文件格式控制的需要,但具体是怎么控制的,估计得用过相关的格式控制才会知道)
  • FORMAT_AUTO ---自动格式模式?
  • FORMAT_XML ---XML 格式
  • FORMAT_YAML ---YAML格式
  • FORMAT_JSON ---JSON 格式
  • BASE64---write rawdata in Base64 by default.(对原始数据采用Base64编码,Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64编码常用于在HTTP环境下传递较长的标识信息。)
  • WRITE_BASE64---enable both WRITE and BASE64(同时选择 WRITE 和 BASE64)

值得注意的是:在Python中,上面的flags参数可选值都要加上cv.FileStorage_的前缀,比如READ要写为“cv.FileStorage_READ”。

接下来通过一个简单的Python例子来说明类FileStorage的使用。
代码如下:
[Python] 纯文本查看 复制代码
# -*- coding: utf-8 -*-
# 出处:昊虹AI笔记网(hhai.cc)
# 用心记录计算机视觉和AI技术

# 博主微信/QQ 2487872782
# QQ群 271891601
# 欢迎技术交流与咨询

# OpenCV的版本为4.4.0

import cv2 as cv
import numpy as np

if __name__ == '__main__':
    # 创建FileStorage对象file,用于写入数据
    # file = cv.FileStorage('F:/material/data/my_data_file.yaml', cv.FileStorage_WRITE)
    file = cv.FileStorage('F:/material/data/my_data_file.xml', cv.FileStorage_WRITE)

    # 写入数据到XML文件或YAML文件
    file.write('name', '毛晓彤')
    file.write('age', 34)
    file.write('birth_date', '1988-02-16')
    scores = np.array([[92, 98, 98], [94, 98, 99], [92, 96, 95]])
    file.write('scores', scores)

    # 释放对象
    file.release()

    # 创建FileStorage对象file1,用于从文件中读取数据
    file1 = cv.FileStorage('F:/material/data/my_data_file.xml', cv.FileStorage_READ)

    # 判断my_data_file.xml文件是否成功打开
    if file1.isOpened():
        # 从XML或YAML文件中读取数据
        name_read = file1.getNode('name').string()
        age_read = file1.getNode('age').real()
        date_read = file1.getNode('birth_date').string()
        scores_read = file1.getNode('scores').mat()

        # 显示读取结果
        print('姓名:{}'.format(name_read))
        print('年龄:{}'.format(age_read))
        print('生日:{}'.format(date_read))
        print('成绩单:{}'.format(scores_read))
    else:
        print('Can\'t open my_data_file.xml.')

    # 释放对象
    file1.release()

上面页面提供的源码的作用为:
创建一个包含数据的yaml或xml文件,然后再通过读取它获取相应的变量值。
代码说明如下:
先说成员函数cv.FileStorage.write(),这个函数可用于将变量名称和变量值写入XML或YAML文件。这个成员函数的原型如下:
C++原型有五种,分别如下:
  1. void cv::FileStorage::write(const String &name,int val)
  2. void cv::FileStorage::write(const String &name,doble val)
  3. void cv::FileStorage::write(const String &name,const String &val)
  4. void cv::FileStorage::write(const String &name,const Mat &val)
  5. void cv::FileStorage::write(const String &name,const std::vector<String> &val)
复制代码

参数name是要写入XML或YAML文件的变量的名称,参数val是对应变量的值。
从以上五个原型可以看出,val可以是下面五种类型:
int、double、String、Mat、std::vector<String>
而由于Python不是强制类型语言,所以在OpenCV-Python中,FileStorage.write()只有一种原型,如下:
  1. None = cv.FileStorage.write(name, val)
复制代码

对于Python而言,val在这里的类型可以有三种,分别为实数、字符串和矩阵这三种类型的数据。

值得注意的是,把要写入文件的变量用FileStorage.write()写入文件之后,必须要用成员FileStorage的成员函数release()作一次释放操作,否则不会生成相应的文件,相关的代码如上面代码中的语句“file.release()”。

再说成员函数cv.FileStorage.getNode(),这个成员函数用于从XML或YAML文件中读取对应变量名的值。其函数原型如下:
C++原型有两种:
  1. cv::FileStorage::operator[](const String & nodename) const
  2. cv::FileStorage::operator[](const char * nodename) const
复制代码

可见在OpenCV的C++版本中,并没有成员函数FileStorage.getNode(),它用操作符“[]”代替了函数名“getNode”。如果你要问上面原型末尾的const是怎么回事?可以参见博文 C++类中成员函数声明后面的const的含义

其Python原型有三种,如下:
  1. # 读取实数数据时需要用下面这种原型
  2. retval = cv.FileStorage.getNode(nodename).real()
  3. # 读取字符串数据时需要用下面这种原型
  4. retval = cv.FileStorage.getNode(nodename).string()
  5. # 读取矩阵数据时需要用下面这种原型
  6. retval = cv.FileStorage.getNode(nodename).mat()
复制代码

三种原型的作用已写于上面的注释中,这里就不多做赘述了。

程序运行时生成的yaml和xml文件分别如下,大家可以对照着程序看一看,这样很容易就理解yaml、xml其格式风格分别是怎么样的了。
生成的yaml文件内容如下:
  1. name: "毛晓彤"
  2. age: 34
  3. birth_date: "1988-02-16"
  4. scores: !!opencv-matrix
  5.    rows: 3
  6.    cols: 3
  7.    dt: i
  8.    data: [ 92, 98, 98, 94, 98, 99, 92, 96, 95 ]
复制代码


生成的xml文件内容如下:
  1. <?xml version="1.0"?>
  2. <opencv_storage>
  3. <name>"毛晓彤"</name>
  4. <age>34</age>
  5. <birth_date>"1988-02-16"</birth_date>
  6. <scores type_id="opencv-matrix">
  7.   <rows>3</rows>
  8.   <cols>3</cols>
  9.   <dt>i</dt>
  10.   <data>
  11.     92 98 98 94 98 99 92 96 95</data></scores>
  12. </opencv_storage>
复制代码

对比一下,昊虹君觉得yaml看着更舒服呢。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|昊虹AI笔记网 ( 蜀ICP备2024076726 )

GMT+8, 2024-5-19 12:07 , Processed in 0.021077 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表