小记:静默如初,安之若素
1. FileStorage的定义
FileStorage是opencv中提供的一种序列化与反序列化的机制,用于将不同数据类型的数据以YAML或者XML格式写入磁盘或者从磁盘中读取,这些方法可以用来加载或者保存任何opnecv的数据变量(包括基本数据变量,例如int 和 float等)
2. FileStorage的写入
1):声明对象
FileStorage::FileStorage();
FileStorage::FileStorage(string filename, int flag);
//filename : 表示写入的文件名,
//flag设为:cv::FileStorage::WRITE 或者 cv::FileStorage::APPEND
2):打开文件: 调用cv::FileStorage::open()函数;
3):写入数据: 调用cv::FileStorage::operator<<();
//cv::FilsStorage内部数据的存储形式:“mapping”(键/值对)和 “sequence”(一系列未命名的条目)
4):关闭文件:调用cv::FileStorage::release()函数关闭文件。
示例程序
1 #include <iostream>
2 #include <opencv2/opencv.hpp>
3 #include <ctime>
4 using namespace std;
5
6 int main(int argc, char * argv[])
7 {
//数据写入
8 cv::FileStorage fs("test.yaml", cv::FileStorage::WRITE);
9
10 fs << "frameCount" << 5;
11
12 time_t rawtime;
13 time(&rawtime);
14 fs<< "calibrationDate" << asctime(localtime(&rawtime));
15
16 cv::Mat cameraMatrix = (
17 cv::Mat_<double>(3, 3)
18 << 1000, 0, 320, 0, 1000, 240, 0, 0, 1
19 );
20
21 cv::Mat distCoeffs = (
22 cv::Mat_<double>(5, 1)
23 << 0.1, 0.01, -0.001, 0, 0
24 );
25
26 fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;
27
28 fs << "features" << "[";
29 for(int i = 0; i < 3; i++)
30 {
31 int x = rand() % 640;
32 int y = rand() % 480;
33 uchar lbp = rand() % 256;
34 fs << "{:" << "x" << x << "y" << y << "lbp" << "[:";
35 for(int j = 0; j < 8; j++)
36 {
37 fs << ((lbp >> j) & 1);
38 }
39 fs << "]" << "}";
40 }
41
42 fs << "]";
43 fs.release();
44 return 0;
45 }
3. 使用cv::FileStorage读取文件
1):声明对象,此处与打开的区别是flag的参数设为:cv::FileStorage::READ
FileStorage::FileStorage();
FileStorage::FileStorage(string filename, int flag);
2):打开文件: 调用cv::FileStorage::open()函数;
3):读取数据:
3.1)读取数据时首先需要确认要读取的数据名,即FileStorage最顶层的mapping关键字
可以通过调用cv::FileStorage::operator获取所需的数据;
(注:操作符直接返回的值是一个FileNode对象,而不是所想要的数据,需要进一步转换才可以)
3.2)数据转换:
基本类型可以直接进行强制类型转换;
mapping对象需要通过重载操作符[],并给定所需关键字进行访问;
sequence对象可以通过重载的[]和一个整型参数进行数据访问,也可以通过cv::FileNodeIterator迭代器进行数据访问。
//cv::FilsStorage内部数据的存储形式:“mapping”(键/值对)和 “sequence”(一系列未命名的条目)
4):关闭文件:调用cv::FileStorage::release()函数关闭文件。
示例程序
1 #include <iostream>
2 #include <opencv2/opencv.hpp>
3 #include <ctime>
4 using namespace std;
5
6 int main(int argc, char * argv[])
7 {
//数据读取
45 cv::FileStorage fs2("test.yaml", cv::FileStorage::READ);
46
47 int frameCount = (int)fs2["frameCount"];
48
49 std::string data;
50 fs2["calibrationDatea"] >> data;
51
52 cv::Mat cameraMatrix2, distCoeffs2;
53 fs2["cameraMatrix"] >> cameraMatrix2;
54 fs2["distCoeffs"] >> distCoeffs2;
55
56 cout << "frameCount : " << frameCount << endl
57 << "calibration date : " << data << endl
58 << "camera Matrix : " << cameraMatrix2 <<endl
59 << "distCoeffs : " << distCoeffs2 << endl;
60 cv::FileNode features = fs2["features"];
61
62 cv::FileNodeIterator it = features.begin(), it_end = features.end();
63 int idx = 0;
64
65 std::vector<uchar> lbpval;
66
67 for(; it != it_end; ++it, idx++)
68 {
69 cout << "features # " << idx << ":";
70 cout << "x = " << (int)(*it)["x"] << ", y = " << (int)(*it)["y"] << ", lbp : (";
71 (*it)["lbp"] >> lbpval;
72 for(int i = 0; i < (int)lbpval.size(); i++)
73 {
74 cout << " " << (int)lbpval[i];
75 }
76 cout << ")" <<endl;
77 }
78 fs2.release();
79 return 0;
80 }
编译上述程序需要使用opencv库函数,下面提供一种通过CMakeList.txt进行编译的方式:
CMakeList.txt
1 cmake_minimum_required( VERSION 2.8 )
2 project( opencvTest )
3
4 set( CMAKE_BUILD_TYPE "Debug" )
5 set( CMAKE_CXX_FLAGS "-std=c++11" )
6
7 find_package(OpenCV REQUIRED)
8 message(STATUS "Found Opencv: ${OpenCV_VERSION}")
9
10 add_executable(opencvTest main.cc )
11 target_link_libraries(opencvTest ${OpenCV_LIBS}
运行
mkdir build
cd build
./opencvTest
4. FileNode解释
CvFileNode;此结构只用于从文件存储器中检索数据使用(也就是用于从文件载入数据)。当数据被写入文件中时它将使用最小的缓存,顺序的完成。没有数据被存在文件存储器这结构中。
相反,当从文件中读数据时,所有文件在内存中像树一样被解析和描绘。树的每一个节点被CvFileNode表现出来。文件节点N的类型能够通过CV_NODE_TYPE(N->tag) 被重新找到。一些节点(叶结点)作为变量:字符串文本,整数,浮点数。其它的文件节点是集合文件节点,有两个类型集合:序列和图表 (我们这里使用 YAML 符号,无论用哪种方法,对于XML符号流也是同样有效)。序列(不要与CvSeq混淆) 是由有序的非指定文件节点(注:没有关键字)构成的,图表是由无序的指定文件节点(注:有关键字)构成的。因而 ,序列的数据是通过索引(cvGetSepElem)来存取,图形的数据是通过名字(cvGetFileNodeByName)来存取 。下表描述不同类型的节点:
/* 文件节点类型 */
#define CV_NODE_NONE 0
#define CV_NODE_INT 1
#define CV_NODE_INTEGER CV_NODE_INT
#define CV_NODE_REAL 2
#define CV_NODE_FLOAT CV_NODE_REAL
#define CV_NODE_STR 3
#define CV_NODE_STRING CV_NODE_STR
#define CV_NODE_REF 4 /* not used */
#define CV_NODE_SEQ 5
#define CV_NODE_MAP 6
#define CV_NODE_TYPE_MASK 7
/* 可选标记 */
#define CV_NODE_USER 16
#define CV_NODE_EMPTY 32
#define CV_NODE_NAMED 64
#define CV_NODE_TYPE(tag) ((tag) & CV_NODE_TYPE_MASK)
#define CV_NODE_IS_INT(tag) (CV_NODE_TYPE(tag) == CV_NODE_INT)
#define CV_NODE_IS_REAL(tag) (CV_NODE_TYPE(tag) == CV_NODE_REAL)
#define CV_NODE_IS_STRING(tag) (CV_NODE_TYPE(tag) == CV_NODE_STRING)
#define CV_NODE_IS_SEQ(tag) (CV_NODE_TYPE(tag) == CV_NODE_SEQ)
#define CV_NODE_IS_MAP(tag) (CV_NODE_TYPE(tag) == CV_NODE_MAP)
#define CV_NODE_IS_COLLECTION(tag) (CV_NODE_TYPE(tag) >= CV_NODE_SEQ)
#define CV_NODE_IS_FLOW(tag) (((tag) & CV_NODE_FLOW) != 0)
#define CV_NODE_IS_EMPTY(tag) (((tag) & CV_NODE_EMPTY) != 0)
#define CV_NODE_IS_USER(tag) (((tag) & CV_NODE_USER) != 0)
#define CV_NODE_HAS_NAME(tag) (((tag) & CV_NODE_NAMED) != 0)
#define CV_NODE_SEQ_SIMPLE 256
#define CV_NODE_SEQ_IS_SIMPLE(seq) (((seq)->flags & CV_NODE_SEQ_SIMPLE) != 0)
typedef struct CvString
{
int len;
char* ptr;
}
CvString;
/*所有已读存储在文件元素的关键字被存储在hash表中,这样可以加速查找操作 */
typedef struct CvStringHashNode
{
unsigned hashval;
CvString str;
struct CvStringHashNode* next;
}
CvStringHashNode;
/* 文件存储器的基本元素是-标量或集合*/
typedef struct CvFileNode
{
int tag;
struct CvTypeInfo* info; /* 类型信息(只能用于用户自定义对象,对于其它对象它为0) */
union
{
double f; /* 浮点数*/
int i; /* 整形数 */
CvString str; /* 字符文本 */
CvSeq* seq; /* 序列 (文件节点的有序集合) */
struct CvMap* map; /*图表 (指定的文件节点的集合 ) */
} data;
}
CvFileNode;
FileNode详细解释