OpenCV中XML文件和YAML文件的读写
OpenCV中XML文件和YAML文件的讀寫
代碼如下:
#include <opencv2/core/core.hpp> #include <iostream> #include <string>using namespace cv; using namespace std;static void help(char** av) {cout << endl<< av[0] << " shows the usage of the OpenCV serialization functionality." << endl<< "usage: " << endl<< av[0] << " outputfile.yml.gz" << endl<< "The output file may be either XML (xml) or YAML (yml/yaml). You can even compress it by "<< "specifying this in its extension like xml.gz yaml.gz etc... " << endl<< "With FileStorage you can serialize objects in OpenCV by using the << and >> operators" << endl<< "For example: - create a class and have it serialized" << endl<< " - use it to read and write matrices." << endl; }class MyData { public:MyData() : A(0), X(0), id(){}explicit MyData(int) : A(97), 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 Membersint 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;elsex.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; }int main(int ac, char** av) {if (ac != 2){help(av);return 1;}string filename = av[1];{ //writeMat R = Mat_<uchar>::eye(3, 3),T = Mat_<double>::zeros(3, 1);MyData m(1);FileStorage fs(filename, FileStorage::WRITE);fs << "iterationNr" << 100;fs << "strings" << "["; // text - string sequencefs << "image1.jpg" << "Awesomeness" << "../data/baboon.jpg";fs << "]"; // close sequencefs << "Mapping"; // text - mappingfs << "{" << "One" << 1;fs << "Two" << 2 << "}";fs << "R" << R; // cv::Matfs << "T" << T;fs << "MyData" << m; // your own data structuresfs.release(); // explicit closecout << "Write Done." << endl;}{//readcout << 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 1;}FileNode n = fs["strings"]; // Read string sequence - Get nodeif (n.type() != FileNode::SEQ){cerr << "strings is not a sequence! FAIL" << endl;return 1;}FileNodeIterator it = n.begin(), it_end = n.end(); // Go through the nodefor (; it != it_end; ++it)cout << (string)*it << endl;n = fs["Mapping"]; // Read mappings from a sequencecout << "Two " << (int)(n["Two"]) << "; ";cout << "One " << (int)(n["One"]) << endl << endl;MyData m;Mat R, T;fs["R"] >> R; // Read cv::Matfs["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 nodescout << "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 0; }Explanation
這里只討論XML 和 YAML 文件的讀取,這是兩種不同的可能會序列化的數據結構: mappings (類似STL的map) 和 element sequence (類似STL的vector). 兩種結構的區(qū)別為 map 的每一個元素都有一個具有唯一性的名字,通過具有唯一性的名字(鍵)可以訪問對應的元素值.對于序列,你需要通過他們來查詢一個特定的項目.
1 XML/YAML 文件的代開和關閉
OpenCV中XML/YAML數據結構類型為cv::FileStorage,要打開硬盤上的文件,可以基于構造函數或者open()函數
string filename = "I.xml"; FileStorage fs(filename, FileStorage::WRITE); //... fs.open(filename, FileStorage::READ);函數中的第二個參數為: WRITE, READ 或 APPEND,表示不同的操作類型(寫,讀或追加)。文件的擴展名表明輸出文件的格式,當時用擴展名*.xml.gz*.時文件會被壓縮。
當cv::FileStorage對象銷毀時,文件會被自動關閉,可以通過顯式調用關閉文件。
fs.release(); // explicit close2 文本和數字的輸入輸出 數據結構采用和STL標準庫一樣的輸出操作符<< ,輸出任何類型的數據結構首先需要指定文件名.
int itNr; fs["iterationNr"] >> itNr; itNr = (int) fs["iterationNr"]; 3 OpenCV 數據結構的讀入和輸出.? C++風格的方法:
4 vectors (arrays) 和 associative maps的輸入輸出
向前面說的,我們可以輸出maps 和 sequences (array, vector) 。首先我們輸出變量的名字,然后指定類型為 sequence 或者 map.
對于 sequence在第一個元素前輸出 "[" 字符 并且在最后一個元素后輸出 "]" 字符:
fs << "strings" << "["; // text - string sequence fs << "image1.jpg" << "Awesomeness" << "baboon.jpg"; fs << "]"; // close sequence對于 maps the drill是同樣的,但是使用 "{" 和 "}" 分割字符:
fs << "Mapping"; // text - mapping fs << "{" << "One" << 1; fs << "Two" << 2 << "}";
讀取操作使用 cv::FileNode 和? cv::FileNodeIterator 數據結構.??? cv::FileStorage 的操作符[]返回的是 cv::FileNode 數據類型. If the node is sequential we can use the cv::FileNodeIterator to iterate through the items:
對于 maps 使用[] 操作符訪問給定的條目(或者 >> 操作符): n = fs["Mapping"]; // Read mappings from a sequence cout << "Two " << (int)(n["Two"]) << "; "; cout << "One " << (int)(n["One"]) << endl << endl; 5 讀寫自己的數據結構 假設有如下結構: class MyData { public:MyData() : A(0), X(0), id() {} public: // Data Membersint A;double X;string id; };
通過 在自定義類的內部和外部添加讀寫函數,借助OpenCV I/O XML/YAML 接口序列化是可能的 (就像 OpenCV的數據結構一樣 ) 。
類內部的部分:
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"]; } 類外部的部分:
接下來將會定義讀取不存在的節(jié)點將會發(fā)生的情況. 這種情況下返回默認的初始化值, 然而,一個更詳細的解決辦法是對于實例返回一個負值作為object ID.
一旦添加了使用 >>作為寫操作符,使用 <<為讀操作符的4個函數:
MyData m(1); fs << "MyData" << m; // your own data structures fs["MyData"] >> m; 或者執(zhí)行一個不存在讀:fs["NonExisting"] >> m; // Do not add a fs << "NonExisting" << m command for this to work cout << endl << "NonExisting = " << endl << m << endl;
結果
只打印出定義的數字。在控制臺屏幕上看到:
Write Done. Reading: 100image1.jpg Awesomeness baboon.jpg Two 2; One 1 R = [1, 0, 0;0, 1, 0;0, 0, 1] T = [0; 0; 0] MyData = { id = mydata1234, X = 3.14159, A = 97} Attempt to read NonExisting (should initialize the data structure with its default). NonExisting = { id = , X = 0, A = 0} Tip: Open up output.xml with a text editor to see the serialized data.輸出的XML文件
輸出的 YAML 文件:
%YAML:1.0 iterationNr: 100 strings:- "image1.jpg"- Awesomeness- "baboon.jpg" Mapping:One: 1Two: 2 R: !!opencv-matrixrows: 3cols: 3dt: udata: [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ] T: !!opencv-matrixrows: 3cols: 1dt: ddata: [ 0., 0., 0. ] MyData:A: 97X: 3.1415926535897931e+000id: mydata1234
總結
以上是生活随笔為你收集整理的OpenCV中XML文件和YAML文件的读写的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCV在图像上画线、矩形、椭圆、多
- 下一篇: 基于OpenCV完成离散傅里叶变换