如何利用OpenCV持久化自己的数据结构?我们来看看OpenCV中的一个例子

MyData.hpp定义自己的数据结构MyData如下:

#ifndef MYDATA_HPP
#define MYDATA_HPP #include <opencv2/core/core.hpp>
#include <iostream>
#include <string> using namespace std;
using namespace cv; class MyData
{
public:
MyData() : A(), X(), id()
{}
explicit MyData(int) : A(), X(CV_PI), id("mydata1234") // explicit to avoid implicit conversion
{}
void write(FileStorage& fs) const //Write serialization for this class
{
fs << "{" << "A" << A << "X" << X << "id" << id << "}";
}
void read(const FileNode& node) //Read serialization for this class
{
A = (int)node["A"];
X = (double)node["X"];
id = (string)node["id"];
}
public: // Data Members
int A;
double X;
string id;
}; //These write and read functions must be defined for the serialization in FileStorage to work
static void write(FileStorage& fs, const std::string&, const MyData& x)
{
x.write(fs);
} static void read(const FileNode& node, MyData& x, const MyData& default_value = MyData())
{
if(node.empty())
x = default_value;
else
x.read(node);
} // This function will print our custom class to the console
static ostream& operator<<(ostream& out, const MyData& m)
{
out << "{ id = " << m.id << ", ";
out << "X = " << m.X << ", ";
out << "A = " << m.A << "}";
return out;
} #endif // MYDATA_HPP

注意,外部静态函数 write 和 read 必须定义,即:

static void write(FileStorage& fs, const std::string&, const MyData& x);
static void read(const FileNode& node, MyData& x, const MyData& default_value = MyData());

原因稍后说明。

主函数main.cpp如下:
 #include <QtCore/QCoreApplication>
#include "MyData.hpp" int main(int argc, char *argv[])
{
// QCoreApplication a(argc, argv);
// return a.exec(); string filename = "../file/test.xml";
{ //write
Mat R = Mat_<uchar>::eye(, ),
T = Mat_<double>::zeros(, );
MyData m(); FileStorage fs(filename, FileStorage::WRITE); fs << "iterationNr" << ;
fs << "strings" << "["; // text - string sequence
fs << "image1.jpg" << "Awesomeness" << "baboon.jpg";
fs << "]"; // close sequence fs << "Mapping"; // text - mapping
fs << "{" << "One" << ;
fs << "Two" << << "}"; fs << "R" << R; // cv::Mat
fs << "T" << T; fs << "MyData" << m; // your own data structures fs.release(); // explicit close
cout << "Write Done." << endl;
} {//read
cout << endl << "Reading: " << endl;
FileStorage fs;
fs.open(filename, FileStorage::READ); int itNr;
//fs["iterationNr"] >> itNr;
itNr = (int) fs["iterationNr"];
cout << itNr;
if (!fs.isOpened())
{
cerr << "Failed to open " << filename << endl;
//help(av);
return ;
} FileNode n = fs["strings"]; // Read string sequence - Get node
if (n.type() != FileNode::SEQ)
{
cerr << "strings is not a sequence! FAIL" << endl;
return ;
} FileNodeIterator it = n.begin(), it_end = n.end(); // Go through the node
for (; it != it_end; ++it)
cout << (string)*it << endl; n = fs["Mapping"]; // Read mappings from a sequence
cout << "Two " << (int)(n["Two"]) << "; ";
cout << "One " << (int)(n["One"]) << endl << endl; MyData m;
Mat R, T; fs["R"] >> R; // Read cv::Mat
fs["T"] >> T;
fs["MyData"] >> m; // Read your own structure_ cout << endl
<< "R = " << R << endl;
cout << "T = " << T << endl << endl;
cout << "MyData = " << endl << m << endl << endl; //Show default behavior for non existing nodes
cout << "Attempt to read NonExisting (should initialize the data structure with its default).";
fs["NonExisting"] >> m;
cout << endl << "NonExisting = " << endl << m << endl;
} cout << endl
<< "Tip: Open up " << filename << " with a text editor to see the serialized data." << endl; return ;
}

可以看到第29行: fs << "MyData" << m; 

当执行到 fs << "MyData" 时,将调用OpenCV源码operations.hpp中的输出操作符:

static inline FileStorage& operator << (FileStorage& fs, const char* str)

返回 FileStorage 的引用,继续输入自定义的数据m时,将调用operations.hpp中的模板函数:

 template<typename _Tp> static inline FileStorage& operator << (FileStorage& fs, const _Tp& value)
{
if( !fs.isOpened() )
return fs;
if( fs.state == FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP )
CV_Error( CV_StsError, "No element name has been given" );
write( fs, fs.elname, value );
if( fs.state & FileStorage::INSIDE_MAP )
fs.state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP;
return fs;
}

可以看到第7行:write( fs, fs.elname, value );

在operations.hpp中,可以看到两个OpenCV导出函数:

CV_EXPORTS_W void write( FileStorage& fs, const string& name, const Mat& value );
CV_EXPORTS void write( FileStorage& fs, const string& name, const SparseMat& value );
CV_EXPORTS_W void read(const FileNode& node, Mat& mat, const Mat& default_mat=Mat() );
CV_EXPORTS void read(const FileNode& node, SparseMat& mat, const SparseMat& default_mat=SparseMat() );

回到上面的问题,为什么必须要定义外部静态函数write和read:

static void write(FileStorage& fs, const std::string&, const MyData& x);
static void read(const FileNode& node, MyData& x, const MyData& default_value = MyData());

因此,我们在MyData.hpp中定义的外部静态函数write和read重载了OpenCV中operations.hpp的read和write函数。

所以,上述调用第7行:write( fs, fs.elname, value ) 将调用我们自己定义的 write和read 函数。然后如MyData.hpp所示,在MyData类内部定义方法实现自定义数据结构的持久化。

而对外接口用起来就像 fs << "MyData" << m; 这句这么简单。

最后输出结果如下:

OpenCV持久化(二)的更多相关文章

  1. 开发环境配置--Ubuntu+Qt4+OpenCV(二)

    同系列文章 1. 开发环境配置--Ubuntu+Qt4+OpenCV(一) 2. 开发环境配置--Ubuntu+Qt4+OpenCV(二) 3. 开发环境配置--Ubuntu+Qt4+OpenCV(三 ...

  2. 使用OpenCV查找二值图中最大连通区域

    http://blog.csdn.net/shaoxiaohu1/article/details/40272875 使用OpenCV查找二值图中最大连通区域 标签: OpenCVfindCoutour ...

  3. OpenCV教程二 - Mat对象与它各种用法

    学习OpenCV大家都会遇到一个对象叫做Mat,此对象非常神奇,支持各种操作.很多初学者因此被搞得头晕脑胀,它各种用法太多太杂,搞得初学者应接不暇,感觉有心无力.无处下手之感.这里我们首先要正本清源, ...

  4. opencv 删除二值化图像中面积较小的连通域

    对于上图的二值化图像,要去除左下角和右上角的噪点,方法:使用opencv去掉黑色面积较小的连通域. 代码 CvSeq* contour = NULL; double minarea = 100.0; ...

  5. OpenCV持久化(一)

    在OpenCV中,采用FileStorage类进行数据持久化,可以采用XML或YAML格式存储数据. 将数据写入XML或YAML文件,可采用以下步骤: 1.创建FileStorage对象.可以调用构造 ...

  6. OpenCV使用二维特征点(Features2D)和单映射(Homography)寻找已知物体

    使用二维特征点(Features2D)和单映射(Homography)寻找已知物体 目标 在本教程中我们将涉及以下内容: 使用函数 findHomography 寻找匹配上的关键点的变换. 使用函数  ...

  7. opencv图像二值化的函数cvThreshold()。 cvAdaptiveThreshol

    OpenCV中对图像进行二值化的关键函数——cvThreshold(). 函数功能:采用Canny方法对图像进行边缘检测 函数原型: void cvThreshold( const CvArr* sr ...

  8. Opencv+Zbar二维码识别(标准条形码/二维码识别)

    使用Opencv+Zbar组合可以很容易的识别图片中的二维码,特别是标准的二维码,这里标准指的是二维码成像清晰,图片中二维码的空间占比在40%~100%之间,这样标准的图片,Zbar识别起来很容易,不 ...

  9. OpenCV图像变换二 投影变换与极坐标变换实现圆形图像修正

    投影变换 在放射变换中,物体是在二维空间中变换的.如果物体在三维空间中发生了旋转,那么这种变换就成为投影变换,在投影变换中就会出现阴影或者遮挡,我们可以运用二维投影对三维投影变换进行模块化,来处理阴影 ...

随机推荐

  1. jvm系列(三):GC算法 垃圾收集器

    原文出处:纯洁的微笑 这篇文件将给大家介绍GC都有哪几种算法,以及JVM都有那些垃圾回收器,它们的工作原理. 概述 垃圾收集 Garbage Collection 通常被称为"GC" ...

  2. 使用SSH-Xsheel文件传输

    借助XShell,使用linux命令sz可以很方便的将服务器上的文件下载到本地,使用rz命令则是把本地文件上传到服务器. 使用命令前需要 apt-get install lrzsz 如果提示源找不到 ...

  3. IOS TableView滑动不灵敏问题

    TableView的默认的不常用的属性,我们尽量不要去改,如下面标注的几个

  4. 科学计算三维可视化---Mayavi入门(Mayavi库的基本元素和绘图实例)

    一:Mayavi库的基本元素 .处理图形可视化和图形操作的mlab模块 .操作管线对象,窗口对象的api (一)mlab模块 (二)mayavi的api 二:快速绘图实例 (一)mlab.mesh的使 ...

  5. 视音频数据处理入门:UDP-RTP协议解析

    ===================================================== 视音频数据处理入门系列文章: 视音频数据处理入门:RGB.YUV像素数据处理 视音频数据处理 ...

  6. memset函数使用详解

    1.void *memset(void *s,int c,size_t n) 总的作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c. 2.例子#include void main(){cha ...

  7. 11 Facts about Data Science that you must know

    11 Facts about Data Science that you must know Statistics, Machine Learning, Data Science, or Analyt ...

  8. 51nod 小Z的trie(Trie+广义SAM)

    [题目链接] http://www.51nod.com/contest/problem.html#!problemId=1647 [题意] 给定一个n个字符串的Trie,每次询问一个字符串在Trie上 ...

  9. 20155330 2016-2017-2 《Java程序设计》第八周学习总结

    20155330 2016-2017-2 <Java程序设计>第八周学习总结 教材学习内容总结 学习目标 了解NIO 会使用Channel.Buffer与NIO2 会使用日志API.国际化 ...

  10. PHP面向对象__set(赋值方法)

    //类Ren里面的变量都是私有的,子类$r里面直接取是取不到的,正常给变量赋值的方法为$r->__set("age",20);,但是可以直接写成$r->age = 20 ...