![]() |
OpenCV 4.12.0
开源计算机视觉
|
上一个教程: 离散傅里叶变换
下一个教程: 如何使用 OpenCV parallel_for_ 并行化你的代码
| 原始作者 | Bernát Gábor |
| 兼容性 | OpenCV >= 3.0 |
你将找到以下问题的答案
这里我们只讨论 XML、YAML 和 JSON 文件输入。你的输出(及其相应的输入)文件可能只有这些扩展名之一以及由此产生的结构。你可以序列化两种数据结构:映射(如 STL map 和 Python 字典)和元素序列(如 STL vector)。它们之间的区别在于,在映射中,每个元素都有一个唯一的名称,你可以通过该名称访问它。对于序列,你需要遍历它们以查询特定项。
XML/YAML/JSON 文件打开和关闭。 在向此类文件写入任何内容之前,你需要打开它,并在结束时关闭它。OpenCV 中的 XML/YAML/JSON 数据结构是 cv::FileStorage。要指定此结构绑定到硬盘上的文件,你可以使用其构造函数或此结构的 open() 函数。
无论你使用哪种方式,第二个参数都是一个常量,指定你可以对它们执行的操作类型:WRITE(写入)、READ(读取)或 APPEND(追加)。文件名称中指定的扩展名也决定了将使用的输出格式。如果指定 .xml.gz 等扩展名,输出甚至可以被压缩。
当 cv::FileStorage 对象被销毁时,文件会自动关闭。但是,你可以通过使用 release 函数显式调用它。
向量(数组)和关联映射的输入/输出。 如前所述,我们也可以输出映射和序列(数组、向量)。同样,我们首先打印变量的名称,然后必须指定输出是序列还是映射。
对于序列,在第一个元素之前打印“[”字符,在最后一个元素之后打印“]”字符。在 Python 中,调用 FileStorage.startWriteStruct(structure_name, struct_type),其中 struct_type 是 cv2.FileNode_MAP 或 cv2.FileNode_SEQ,以开始写入结构。调用 FileStorage.endWriteStruct() 以完成结构。
对于映射,操作相同,但现在我们使用“{”和“}”分隔符。
要从这些结构中读取数据,我们使用 cv::FileNode 和 cv::FileNodeIterator 数据结构。cv::FileStorage 类的 [] 运算符(或 Python 中的 getNode() 函数)返回 cv::FileNode 数据类型。如果节点是序列,我们可以使用 cv::FileNodeIterator 遍历各项。在 Python 中,可以使用 at() 函数访问序列的元素,size() 函数返回序列的长度。
对于映射,你可以再次使用 [] 运算符(Python 中的 at() 函数)来访问给定项(或 >> 运算符)。
读取和写入自己的数据结构。 假设你有一个数据结构,例如
在 C++ 中,可以通过在类内部和外部添加读写函数来通过 OpenCV I/O XML/YAML 接口(就像 OpenCV 数据结构一样)序列化它。在 Python 中,可以通过在类内部实现读写函数来接近这个目标。对于内部部分:
在这里你可以观察到,在读取部分,我们定义了如果用户尝试读取一个不存在的节点时会发生什么。在这种情况下,我们只返回默认初始化值,但一个更详细的解决方案是返回例如对象 ID 的负一值。
一旦你添加了这四个函数,就可以使用 >> 运算符进行写入,使用 << 运算符进行读取(或者 Python 中定义的输入/输出函数)。
或者尝试读取一个不存在的数据。
我们主要只是打印出定义的数字。在你的控制台屏幕上你可以看到:
然而,更有趣的是你在输出 XML 文件中可能看到的内容:
或者 YAML 文件:
你可以在此处在 YouTube 上观看此内容的运行时实例。