C/C++开发,opencv基于FileStorage读写文件介绍及示例

news2024/9/25 1:24:30

目录

一、FileStorage类

        1.1 FileStorage类说明

        1.2 FileStorage类写入说明

        1.3 FileStorage类读取说明

二、FileStorage类应用示例

        2.1 应用代码

        2.2 工程组织(Makefile)

        2.3 编译及测试


一、FileStorage类

        1.1 FileStorage类说明

        FileStorage类在opencv2\core\persistence.hpp中定义:

namespace cv {
//...
    class CV_EXPORTS_W FileStorage
    {
        //...
    };
}

        FileStorage类支持XML(.xml,<http://www.w3c.org/XML>)、YAML(.yml or .yaml,<http://www.yaml.org>)、JSON(.json,<http://www.json.org/>)格式的文件读写。XML使用嵌套标记来表示层次结构,而YAML则使用缩进(类似于Python编程语言)。

XML:
@code{.xml}
    <?xml version="1.0">
    <opencv_storage>
    <A type_id="opencv-matrix">
      <rows>3</rows>
      <cols>3</cols>
      <dt>f</dt>
      <data>1. 0. 0. 0. 1. 0. 0. 0. 1.</data>
    </A>
    </opencv_storage>
@endcode
YAML:
@code{.yaml}
    %YAML:1.0
    A: !!opencv-matrix
      rows: 3
      cols: 3
      dt: f
      data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1.]
@endcode

        FileStorage类支持默认构造或指定文件名的构造方式:

CV_WRAP FileStorage();
CV_WRAP FileStorage(const String& filename, int flags, const String& encoding=String());

        如果采用默认构造时,需要稍后使用open函数打开指定文件:

CV_WRAP virtual bool open(const String& filename, int flags, const String& encoding=String());

        一旦成功打开了想要写入的文件,便可以像对标准输出流输出数据一样使用操作符cv::FileStorage::operator<<()进行写入操作,或cv::FileStorage::operator>>()进行读取操作。可以以这种简单的方式写入,是因为函数内部为调用开发者完成了许多复杂的工作。

        cv::FileStorage支持读写、追加内容等文件操作,通过内置的枚举值Mode来明确的,需要进行flags指定,flags可以是多个枚举值的并集,例如READ|WRITE。同时还内置了操作状态State,在cv::FileStorage类进行写入数据操作(operator <<)时需要进行cv::FileStorage对象的状态判断:

    //! file storage mode
    enum Mode
    {
        READ        = 0, //!< value, open the file for reading
        WRITE       = 1, //!< value, open the file for writing
        APPEND      = 2, //!< value, open the file for appending
        MEMORY      = 4, /**< flag, read data from source or write data to the internal buffer (which is
                              returned by FileStorage::release) */
        FORMAT_MASK = (7<<3), //!< mask for format flags
        FORMAT_AUTO = 0,      //!< flag, auto format
        FORMAT_XML  = (1<<3), //!< flag, XML format
        FORMAT_YAML = (2<<3), //!< flag, YAML format
        FORMAT_JSON = (3<<3), //!< flag, JSON format

        BASE64      = 64,     //!< flag, write rawdata in Base64 by default. (consider using WRITE_BASE64)
        WRITE_BASE64 = BASE64 | WRITE, //!< flag, enable both WRITE and BASE64
    };
    enum State
    {
        UNDEFINED      = 0,
        VALUE_EXPECTED = 1,
        NAME_EXPECTED  = 2,
        INSIDE_MAP     = 4
    };

        1.2 FileStorage类写入说明

        cv::FileStorage内部数据的存储主要有两种形式,“mapping”(键/值对)和“sequence”(一系列未命名的条目)。在最顶层,所写入的数据都在一个mapping中,在该mapping中,可以放置其他的mappings或者sequences,甚至在mapping中继续放入mapping等,只要愿意。

myFileStorage <<"someInteger"<< 27;// save an array
myFileStorage <<"anArray"<<cv::Mat::eye(3,3,CV_32F);// save an integer

        如果要创建一个序列条目,首先你得为它提供一个string类型的名字,接下来才是序列数据。条目内容可以是数字(整型或浮点型等),一个字符串或者别的OpenCV数据类型。

        如果想要创建一个新的mapping或者sequence,可以使用特殊符号{(用于mapping)或者[(用于sequence)。一旦开始创建,就可以为其添加元素,最终以}或者]分别结束一个mapping或者sequence。

myFileStorage <<"theCat"<<"{";
myFileStorage <<"fur"<<"gray"<<"eyes"<<"green"<<"weightLbs"<< 16;
myFileStorage <<"}";

        一旦完成创建一个mapping,需要按顺序输入条目名以及对应的值,像你在最顶层的mapping完成的工作一样。如果创建的是sequence,只需要一个接一个地输入元素即可,直到sequence结束。

myFileStorage<<"theTeam"<<"[";
myFileStorage <<"eddie"<<"tom"<<"scott";
myFileStorage <<"]";

        一旦完成写工作,便可以使用成员函数cv::FileStorage::release()关闭该文件。

        1.3 FileStorage类读取说明

        FileStorage类在使用操作符cv::FileStorage::operator>>()进行读取操作时,实际返回时FileNode类的实例对象。

        FileNode类同样定义在opencv2\core\persistence.hpp中:

namespace cv {
//...
    class CV_EXPORTS_W_SIMPLE FileNode
    {
        //...
    };
}

        当成功构建一个cv::FileNode对象之后,便可以利用它来完成许多工作。如果它直接表示一个实际的对象(或者一个数字或者字符串),你就可以直接使用重载操作符cv::FileNode::operator>>(),将它的值加载到对应类型的变量之中。

cv::Mat anArray;
myFileStorage["calibrationMatrix"]>> anArray;

       cv::FileNode对象同样支持直接赋值给一些基本数据类型。 cv::FileNode类支持的数据类型如下:

    //! type of the file storage node
    enum
    {
        NONE      = 0, //!< empty node
        INT       = 1, //!< an integer
        REAL      = 2, //!< floating-point number
        FLOAT     = REAL, //!< synonym or REAL
        STR       = 3, //!< text string in UTF-8 encoding
        STRING    = STR, //!< synonym for STR
        SEQ       = 4, //!< sequence
        MAP       = 5, //!< mapping
        TYPE_MASK = 7,

        FLOW      = 8,  //!< compact representation of a sequence or mapping. Used only by YAML writer
        UNIFORM   = 8,  //!< if set, means that all the collection elements are numbers of the same type (real's or int's).
        //!< UNIFORM is used only when reading FileStorage; FLOW is used only when writing. So they share the same bit
        EMPTY     = 16, //!< empty structure (sequence or mapping)
        NAMED     = 32  //!< the node has a name (i.e. it is element of a mapping).
    };

        通过cv::FileNode对象输出操作符获取数据和采用赋值操作符获取数据是等价的:

int aNumber;
myFileStorage["someInteger"]>> aNumber;

        与下面这种方式等价:

int aNumber;
aNumber =(int)myFileStorage["someInteger"];

        针对cv::FileNode类,还提供了一种标准的STL表示法, 即FileNodeIterator,node.begin(),node.end()表示序列的开始和结束,存储在node中,也可以通过operator ++ ()或operator ++ (int)进行移动。

namespace cv {
//...
    class CV_EXPORTS FileNodeIterator
    {
        //...
    };
}

二、FileStorage类应用示例

        2.1 应用代码

        在opencv2\core\persistence.hpp中,还给出了FileStorage类写入及读取.yml文件的示例代码,本文将在基于该示例代码上,编写一个完整的案例工程,先创建.yml格式文件并写入内容,再通过一个新的FileStorage实例对象读取该文件内存,并解析打印显示相关内容;

        先创建一个目录文件file_storage,在该文件目录下,创建文件main.cpp和Makefile文件,其中main.cpp如下,通过fileCreateAndSave函数创建 一个tets.yml文件并写入数据,再通过fileReadAndShow函数读取该文件内容并打印输出显示。其中main.cpp源码如下:

#include <opencv2/opencv.hpp>
#include <time.h>
#include <iostream>

void fileCreateAndSave()
{
    cv::FileStorage fs("test.yml",cv::FileStorage::WRITE);
    fs <<"frameCount"<< 5;
    time_t rawtime; time(&rawtime);fs<<"calibrationDate"<< asctime(localtime(&rawtime));
    cv::Mat cameraMatrix =(
        cv::Mat_<double>(3,3)
        <<1000,0,320,0,1000,240,0,0,1
    );
    cv::Mat distCoeffs =(
        cv::Mat_<double>(5,1)
        <<0.1,0.01,-0.001,0,0
    );
    fs <<"cameraMatrix"<< cameraMatrix<<"distCoeffs"<< distCoeffs;
    fs <<"features"<<"[";
    for( int i=0; i<3;i++)
    {
        int x = rand()% 640;
        int y = rand()% 480;
        uchar lbp = rand()% 256;
        fs<<"{:"<<"x"<<x<<"y"<<y<<"lbp"<<"[:";
        for( int j=0;j<8;j++)
            fs <<((lbp >>j)&1);
        fs<<"]"<<"}";
    }
    fs<<"]";
    fs.release();

}

void fileReadAndShow()
{
    cv::FileStorage fs2("test.yml",cv::FileStorage::READ);
    // first method: use (type) operator on FileNode.
    int frameCount =(int)fs2["frameCount"];
    // second method: use cv::FileNode::operator >>
    //
    std::string date;
    fs2["calibrationDate"]  >> date;
    cv::Mat cameraMatrix2, distCoeffs2;
    fs2["cameraMatrix"]     >> cameraMatrix2;
    fs2["distCoeffs"]       >> distCoeffs2;
    std::cout <<"frameCount:"       << frameCount   <<std::endl
            <<"calibration date:"   << date         <<std::endl
            <<"camera matrix:"      << cameraMatrix2<<std::endl
            <<"distortion coeffs:"  << distCoeffs2  <<std::endl;
    cv::FileNode features  = fs2["features"];
    cv::FileNodeIterator it = features.begin(), it_end = features.end();
    int idx=0;
    std::vector<uchar> lbpval;
    // iterate through a sequence using FileNodeIterator
    for(; it != it_end;++it,idx++)
    {
        std::cout <<"feature #"<<idx<<":";
        std::cout <<"x="<<(int)(*it)["x"]<<",y="<<(int)(*it)["y"]<<",lbp:(";
        //(Note: easily read numerical arrays using FileNode >> std::vector.)
        //
        (*it)["lbp"]>>lbpval;
        for( int i=0; i<(int)lbpval.size(); i++)
            std::cout <<""<<(int)lbpval[i];
        std::cout <<")"<<std::endl;
    }
    fs2.release();
}

int main( int argc,char* argv[])
{
    fileCreateAndSave();
    fileReadAndShow();
    return 0;
};

        2.2 工程组织(Makefile)

        工程组织Makefile文件如下(本文是采用win下MinGW方式编译的,如何搭建opencv库+MinGW编译的请参考本专栏的opencv库安装编译博文,C/C++开发,win下OpenCV+MinGW编译环境搭建_搭建mingw编译环境_py_free-物联智能的博客-CSDN博客)。

#/bin/sh
CX= g++ 

BIN 		:= ./
TARGET      :=  fileStorage.exe
FLAGS		:= -std=c++11 -static
SRCDIR 		:= ./
#INCLUDES
INCLUDEDIR 	:= -I"../../opencv_MinGW/include" 
staticDir   := ../../opencv_MinGW/x64/mingw/staticlib/

LIBDIR 	    := -L $(staticDir) -lopencv_world460 -lade -lIlmImf -lquirc -lzlib \
				-llibjpeg-turbo -llibopenjp2 -llibpng -llibprotobuf -llibtiff -llibwebp \
				-lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid 
source		:= $(wildcard $(SRCDIR)/*.cpp) 

$(TARGET) :
	$(CX) $(FLAGS) $(INCLUDEDIR) $(source)  -o $(BIN)/$(TARGET) $(LIBDIR)

clean:
	rm  $(BIN)/$(TARGET)

        2.3 编译及测试

        进入file_storage目录,make -j*编译案例,如下:

         运行程序如下:

         输出的test.yml文件如下:

%YAML:1.0
---
frameCount: 5
calibrationDate: "Sun Jul  2 16:49:48 2023\n"
cameraMatrix: !!opencv-matrix
   rows: 3
   cols: 3
   dt: d
   data: [ 1000., 0., 320., 0., 1000., 240., 0., 0., 1. ]
distCoeffs: !!opencv-matrix
   rows: 5
   cols: 1
   dt: d
   data: [ 1.0000000000000001e-01, 1.0000000000000000e-02,
       -1.0000000000000000e-03, 0., 0. ]
features:
   - { x:41, y:227, lbp:[ 0, 1, 1, 1, 1, 1, 0, 1 ] }
   - { x:260, y:449, lbp:[ 0, 0, 1, 1, 0, 1, 1, 0 ] }
   - { x:598, y:78, lbp:[ 0, 1, 0, 0, 1, 0, 1, 0 ] }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/710255.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

6.S081——并发与锁部分(自旋锁的实现)——xv6源码完全解析系列(9)

0.briefly speaking 并发(Concurrency)指的是在多处理器系统(multiprocessor)中的并行&#xff0c;线程切换和中断导致的多个指令流交互错杂的情况&#xff0c;再和现代处理器体系结构中的多发射、乱序执行、Cache一致性等话题结合起来&#xff0c;这几乎变成了一个相当相当复…

装饰器设计模式应⽤-JDK源码⾥⾯的Stream IO流

装饰器设计模式在JDK源码⾥⾯应⽤场景 抽象组件&#xff08;Component&#xff09;&#xff1a;InputStream 定义装饰⽅法的规范被装饰者&#xff08;ConcreteComponent) : FileInputStream、ByteArrayInputStream Component的具体实现&#xff0c;也就是我们要装饰的具体对…

09-属性描述符Object.getOwnPropertyDescriptor(),原始数据不可重写

把原始数据作为属性值传入新对象中&#xff0c;发生原始数据修改丢失的问题怎么办&#xff1f; 应该使用Object.defineProperty()设置该属性用Object.defineProperty()设置的属性&#xff0c;默认writable、enumerable、configurable均为false并且自定义提醒该属性设置了不可重…

掌握Python的X篇_6_常量与变量、常见运算符、字符型变量

文章目录 1. 常量与变量1.1 常量与变量定义1.2 数字型变量 2. 常见运算符3. 字符型变量( 字符 )3.1 字符串变量的格式化 1. 常量与变量 简单理解&#xff0c;直接使用的数据&#xff0c;就是常量&#xff0c;最常见的常量有数字和字符串 采用ipython进行交互式编程 1.1 常量…

5.1阻塞和非阻塞、同步和异步 5.2Unix、Linux上的五种IO模型

5.1阻塞和非阻塞、同步和异步 典型的一次IO的两个阶段是什么&#xff1f;数据就绪和数据读写 数据就绪&#xff1a;根据IO操作的就绪状态 阻塞非阻塞 数据读写&#xff1a;根据应用程序和内核的交互方式 同步异步 陈硕&#xff1a;在处理IO的时候&#xff0c;阻塞和非阻塞都…

FPGA时序约束--实战篇(时序收敛优化)

目录 一、模块运行时钟频率 二、HDL代码 1、HDL代码风格 2、HDL代码逻辑优化 三、组合逻辑层数 1、插入寄存器 2、逻辑展平设计 3、防止变量被优化 四、高扇出 1、使用max_fanout 2、复位信号高扇出 五、资源消耗 1、优化代码逻辑&#xff0c;减少资源消耗。 2、…

基于图层自动识别算法在CAD图纸基础上快速创建Revit BIM模型 - VS2022 + AutoCAD2024 + ObjectARX环境搭建

引言 CAD 技术将建筑师、工程师们从手工绘图推向计算机辅助制图&#xff0c;实现了工程设计领域的第一次信息革命。从 CAD 技术普及以来&#xff0c;设计成果一般都是 CAD 图纸形式表达。但是近些年来&#xff0c;随着建筑的复杂程度日益增加&#xff0c;专业间的配合更加紧密…

行业观察 | 芯片设计产业链:上游至下游

本文简单总结、介绍芯片设计产业链全流程。 更新&#xff1a;2023 / 7 / 2 文章目录 集成电路产业链常见的芯片架构图数字IC设计流程概略版详解版前后端前端&#xff1a;RTL -> Netlist后端&#xff1a;Netlist -> Layout 示例&#xff1a;基于标准单元&#xff08;STD …

通过串口控制LED-单片机

1.输入数据控制LED灯状态00-ff。同时会接收输入的数据。 中断和定时器配置 void UART_Init() //4800bps11.0592MHz { SCON0X50;//sm00,sm11,ren1 PCON & 0x7F; //波特率不倍速 TMOD & 0x0F; //设置定时器模式 T1 TMOD | 0x20; …

【人工智能与机器学习】决策树ID3及其python实现

文章目录 1 决策树算法1.1 特征选择1.2 熵&#xff08;entropy&#xff09;1.3 信息增益 2 ID3算法的python实现总结 1 决策树算法 决策树&#xff08;Decision Tree)是一类常见的机器学习方法&#xff0c;是一种非常常用的分类方法&#xff0c;它是一种监督学习。常见的决策树…

ModaHub魔搭社区:向量数据库MIlvus服务端配置(一)

目录 服务端配置 配置概述 Milvus 文件结构 配置修改 编辑配置文件 运行时修改 server_config.yaml 参数说明 cluster 区域 general 区域 network 区域 服务端配置 配置概述 以下配置说明可同时应用于单机或者分布式场景。 Milvus 文件结构 成功启动 Milvus 服务后…

加速优化WooCommerce跨境电商网站的15种简单方法

Neil Patel和 Google所做的研究表明&#xff0c;如果加载时间超过三秒&#xff0c;将近一半的用户会离开网站。页面加载时间每增加一秒&#xff08;最多5秒&#xff09;&#xff0c;您的收入可能就会减少。在本教程中&#xff0c;我们将学习如何优化加速WooCommerce商店。 目录…

【20220605】文献翻译:高维数据动态可视化研究综述

A Review of the State-of-the-Art on Tours for Dynamic Visualization of High-dimensional Data Visualization of High-dimensional Data) Lee, Stuart, et al. “A Review of the State-of-the-Art on Tours for Dynamic Visualization of High-dimensional Data.” arXiv…

【书评】一本Android系统性能优化的新书

Android性能优化&#xff0c;是一个合格的Android程序员必备的技能&#xff0c;现如今几乎所有的Android面试内容都会或多或少涉及性能优化方面的话题。 学习Android性能优化可以让我们在简历上展示自己的专业技能和项目经验&#xff0c;证明自己具备高效开发和优化Android应用…

java jwt生成token并在网关设置全局过滤器进行token的校验

1、首先引入jjwt的依赖 <dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version> </dependency>2、编写生成token的工具类 package com.jjw.result.util;import com.jjw.res…

【UnityDOTS 三】Component的理解

Component的理解 文章目录 Component的理解前言一、托管Component与非托管Component1.非托管Component2.托管Component 二、各功能的Component三、在Editor中的Component的区分总结 前言 Component作为ECS中承载数据的结构&#xff0c;了解他相关内容是非常必要的&#xff0c;…

基于Jsp+Servlet+Mysql学生信息管理系统

基于JspServletMysql学生信息管理系统 一、系统介绍二、功能展示1. 系统的部署2.导入数据库3. 系统介绍 四、其它1.其他系统实现五.获取源码 一、系统介绍 项目类型&#xff1a;Java web项目/Java EE项目/ 项目名称&#xff1a;基于sevelet的学生信息管理系统 当前版本&…

用Python制作一个简单时间、日期显示工具

Python是一款强大的编程软件&#xff0c;可以轻松实现我们的多种开发需求。今天我们拿Python中自带的tkinter来开发一个时钟显示器。如下图所示&#xff1a; 时间显示器 一、编程要求 用tkinter写一个漂亮、五彩的时间显示器&#xff0c;要求显示时、分、秒&#xff0c;即时变…

【JAVA】十分钟带你了解java的前世今生

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【初始JAVA】 文章目录 前言JAVA介绍诞生&#x1f52c;名字与图标&#x1f916;发展&#x1f6e9;️未来&#x1fa84; 前言 玩过我的世界的朋友想必对JAVA以及它的图标都很熟悉&#xff0c;在游戏开始画面…

Java程序所在机器性能监控

Java程序所在机器性能监控 背景 问题单&#xff1a;程序故障&#xff08;OOM、网络不通、操作卡顿&#xff09;问题单&#xff1a;服务连接不上需求 1、监控本地机器性能 告警日志UI2、监控服务接口服务 告警日志UI方案 固定间隔获取机器网络CPU内存数据设置阈值&#xff0c;告…