赞
踩
这两种文件可以作为参数配置文件。
这两种文件有着特定的格式,表示这是能被opencv读取的。你不要记住这格式怎么写,只需要大概了解样子就行,格式填充会由程序编译自动填写。
<?xml version="1.0"?>
<opencv_storage>
<!--主体内容-->
</opencv_storage>
也叫xxx.yml
文件
%YAML:1.0
---
如果你想了解这东西怎么手动写:配置文件 .yml 写法小结
对于这两种文件,读写的函数操作都一样,只要你指定文件名的后缀xxx.xml
还是xxx.yaml
,就能输出读取相应格式的文件。
注意:不能用一个FileStorage
句柄同时读写,也不能使用两个FileStorage
句柄同时读写,必须一个执行完关闭后再打开另一个进行操作。
我们使用FileStorage
类作为文件的句柄,类似c的FILE
cv::FileStorage::FileStorage(
const String & filename,
int flags,
const String & encoding = String()
)
参数:
xxx.xml
是xml文件,xxx.yaml
是yaml文件FileStorage::WRITE
:写入FileStorage::READ
:读取FileStorage::APPEND
:附加例如:
// 打开文件,写操作
string filename = "myXML.xml";
FileStorage fs(filename, FileStorage::WRITE);
virtual bool cv::FileStorage::open (
const String & filename,
int flags,
const String & encoding = String()
)
例如:
// 打开文件,写操作
string filename = "myXML.xml";
FileStorage fs;
fs.open(filename, FileStorage::WRITE);
virtual bool cv::FileStorage::isOpened() const
返回值:
virtual void cv::FileStorage::release()
虽然会自动关闭,但建议手动调用。
类型 | 写入 | xml中 | 读出 |
---|---|---|---|
int | 100 | 100 | 100 |
double | 100.1 | 1.0009999999999999e+02 | 100.1 |
bool | true | 1 | true |
string | "hello" | hello | hello |
string | "hello world" | "hello world" | "hello world" |
使用操作符<<
:fs_write << "xml中变量的名字" << 变量的值;
fs_write << "speed" << 100;
xml中:
<speed>100</speed>
方式一:
使用操作符>>
:先声明变量变量的类型 变量的名字;
,再fs_read["xml中变量的名字"] >> 变量的名字;
int speed;
fs_read["speed"] >> speed;
方式二:
强制类型转化:(变量的类型)fs_read["xml中变量的名字"];
。
int speed = (int)fs_read["speed"];
cout << (int)fs_write["speed"] << endl;
可以用vector
的
// 读
vector<int> v1(2, 2);
fs_write << "std_vector" << v1;
// 写
vector<int> v2;
fs_read["std_vector"] >> v2;
for (int i = 0; i < v2.size(); i++)
{
cout << v2[i] << endl;
}
操作同上
类型 | 写入 | xml中 | 读出 |
---|---|---|---|
Mat | (Mat_<uchar>(2, 3) << 1, 2, 3, 4, 5, 6); | ![]() | 一样 |
Size | Size(200,100); | ![]() | 一样 |
Vec3i | Vec3i(1,2,3); | ![]() | 一样 |
后面就不试了
都只有第一种读法,比如Mat类型:
// 写
fs_write << "opencv_matrix" << (Mat_<uchar>(2, 3) << 1, 2, 3, 4, 5, 6);
// 读
Mat result;
fs_read["opencv_matrix"] >> result;
cout << result << endl;
// 报错
// cout << (Mat)fs_read["opencv_matrix"] << endl;
sequence
是处理类型STL的vector
的xml和yaml的数据类型。
mapping
是处理类型STL的map
的xml和yaml的数据类型。
sequence
模仿vector
,而opencv的数据类型中也有模仿vector
的Vec
,而Vec
中只能存数字类型。所以简单的数字类型直接用Vec
就行,复杂的数据类型如string
,我们再用sequence
。
写:在数据前后加了个[
和]
表示sequence
类型。
读:类似List链表遍历,先读取该链表块FileNode
,再用迭代器FileNodeIterator
遍历链表节点,每个节点的读的方式和上面一样有两种。
// 写 fs_write << "sequence_names" << "[" << 132 << 223 << 323 << "]"; // 读 FileNode fn_sequence_names = fs_read["sequence_names"]; if (fn_sequence_names.type() != FileNode::SEQ) { cout << "the type is not sequence!\n"; return 0; } int v[3]; int i = 0; for (FileNodeIterator fni = fn_sequence_names.begin(); fni != fn_sequence_names.end(); fni++) { *fni >> v[i++]; // 或者(int)*fni >> v[i++]; }
xml中:可以看到和opencv的存储样式一样。
写:在数据前后加了个{
和}
表示mappping
类型,单个键值对是先键后值 << "键名" << 值
读:类似map根据键获得值,先读取该链表块FileNode
,再用键获得值。每个键值对的读的方式和上面一样有两种。
PS:键必须字符串类型,键不能重复;同一个mapping中的值的类型可以不一样,值可以重复。
// 写 fs_write << "mapping_names" << "{" << "banana" << "chicken" << "apple" << 223 << "lemon" << 323 << "}"; // 读 FileNode fn_mapping_names = fs_read["mapping_names"]; if (fn_mapping_names.type() != FileNode::MAP) { cout << "the type is not mapping!\n"; return 0; } string banana; fn_mapping_names["banana"] >> banana; int apple = (int)fn_mapping_names["apple"];
#include <iostream> #include <opencv2/opencv.hpp> using namespace cv; using namespace std; int main() { string filename = "myXML.xml"; /*********************************** 打开文件,写操作 ************************************/ FileStorage fs_write; fs_write.open(filename, FileStorage::WRITE); /* 写入 */ // c++ fs_write << "cpp_speed" << 100; // std::vector vector<int> v1(2, 2); fs_write << "std_vector" << v1; // Opencv fs_write << "opencv_matrix" << (Mat_<uchar>(2, 3) << 1, 2, 3, 4, 5, 6); // sequence fs_write << "sequence_names" << "[" << 132 << 223 << 323 << "]"; // mapping fs_write << "mapping_names" << "{" << "banana" << "chicken" << "apple" << 223 << "lemon" << 323 << "}"; fs_write.release(); /************************************* 打开文件,读操作 ************************************/ FileStorage fs_read; fs_read.open(filename, FileStorage::READ); /* 读取 */ // c++ cout << (int)fs_read["cpp_speed"] << endl; // std::vector vector<int> v2; fs_read["std_vector"] >> v2; for (int i = 0; i < v2.size(); i++) { cout << v2[i] << endl; } // Opencv Mat result; fs_read["opencv_matrix"] >> result; cout << result << endl; // !cout << (Mat)fs_read["opencv_matrix"] << endl; // sequence FileNode fn_sequence_names = fs_read["sequence_names"]; if (fn_sequence_names.type() != FileNode::SEQ) { cout << "the type is not sequence!\n"; return 0; } for (FileNodeIterator fni = fn_sequence_names.begin(); fni != fn_sequence_names.end(); fni++) { cout << (int)*fni << endl; } // mapping FileNode fn_mapping_names = fs_read["mapping_names"]; if (fn_mapping_names.type() != FileNode::MAP) { cout << "the type is not mapping!\n"; return 0; } cout << (string)fn_mapping_names["banana"] << endl; cout << (int)(fn_mapping_names)["apple"] << endl; cout << (int)(fn_mapping_names)["lemon"] << endl; fs_read.release(); return 0; }
#include <iostream> #include <opencv2/opencv.hpp> using namespace cv; using namespace std; class MyData { public: MyData() : A(0), X(0), id() {} explicit MyData(int A) : A(A), X(CV_PI), id("mydata1234") {} public: int A; double X; string id; public: // inside of your class 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"]; } }; // outside of your class void write(FileStorage &fs, const std::string &, const MyData &x) { x.write(fs); } void read(const FileNode &node, MyData &x, const MyData &default_value = MyData()) { if (node.empty()) x = default_value; else x.read(node); } // 这个和主题无关,只是让其可以直接用cout输出MyData的值是什么而已 ostream &operator<<(ostream &out, const MyData &m) { out << "id = " << m.id << ", " << "X = " << m.X << ", " << "A = " << m.A; return out; } int main() { string filename = "myXML.xml"; /*********************************** 打开文件,写操作 ************************************/ FileStorage fs_write; fs_write.open(filename, FileStorage::WRITE); MyData m1(1); fs_write << "MyData" << m1; fs_write.release(); /************************************* 打开文件,读操作 ************************************/ FileStorage fs_read; fs_read.open(filename, FileStorage::READ); MyData m2; fs_read["MyData"] >> m2; cout << m2 << endl; fs_read.release(); return 0; }
opencv3.4.6官方文档:tutorial_file_input_output_with_xml_yml.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。