OpenCV-Utils学习日志:FileStorage使用样例

         FileStorage是CV开发经常使用的文件IO工具,可以极其简便地读写C++及OpenCV数据类型,且支持XML/YAML/JSON等纵多盛行的文件格式。

1.支持的数据类型

         (1)C++静态类型:所有。

         (2)C++容器类型:典型地string、vector<type>、vector<vector<type>>,这里的type是FileStorage,最多支持两重vector。

         (3)CV静态类型:截至OpenCV4.5,支持除TermCriteria、Matx和Affine等外的所有类型。

         (4)CV容器类型:Mat

         (5)自定义类型:可重载运算符<<,支持自定义类型。

2.常用的成员函数

         (1)type()=int:返回NONE/INT/REAL=FLOAT/STR=STRING/SEQ/MAP、TYPE_MASK/FLOW=UNIFORM/EMPTY/NAMED。

         (2)isNone()、isInt()、isReal()、isString()、isSeq()、isMap()、isNamed()=bl:判断类型及是否有名。

         (3)real()=db、string()=str、mat()=mat、()=int/flt/db/str、name()=str:返回结点值及结点名。

         (4)size()=int:返回序列或集合的子结点数。

         (5)keys()=strs:返回地图所有子结点名。

         (6)begin()、end()=iter:返回首末迭代器。

3.遍历方法

         (1)方式一:begin()和end()结合既能遍历向量也能遍历地图

         (2)方式二:size()=int和FileNode[index]结合遍历向量,keys()和FileNode[name]结合遍历地图

         注意点:截至OpenCV4.5还无OpenCV类型识别接口,但截至OpenCV4.5中数据结构也只有Mat是MAP类型,也就是说如果只读写C++和OpenCV数据类型,若读到MAP类型,要么是root结点要么是cv::Mat。

4.使用样例

         以下提供FileStorage的使用样例以供参数,封装在类AboutFileStorage,其功能要点如下:

         (1)如何读写非序列类型:以读写C++::int、C++::string、cv::Rect、cv::Mat为例

         (2)如何写读序列类型:以vector<…>、vector<vector<…>>为例。

         (3)如何使用begin()和end()遍历FileStorage。

         (4)如何使用size()、keys()及FileNode[id/name]遍历FileStorage。

         (5)如何复制如下特点的FileStorage:结点深度为1(即只有root和first level)、每个结点只能是静态类型或Mat或它们vector<…>或vector<vector<…>>。

 

         以下是详细代码,依赖于C++14、OpenCV4.x和Spdlog。

OpenCV-Utils学习日志:FileStorage使用样例

  1 #include <opencv2/opencv.hpp>
  2 #include <opencv2/core/utils/filesystem.hpp>
  3 #include <spdlog/spdlog.h>
  4 using namespace std;
  5 using namespace cv;
  6 
  7 #ifndef StrPairKey
  8 #define StrPairKey(key) make_pair(#key, key)
  9 #define StrPairVal(val) make_pair(val, #val)
 10 #endif
 11 
 12 class AboutFileStorage
 13 {
 14 public:
 15     map<int, string> fnTypes = //for (map<key, val>::iterator it = map.begin(); it != map.end(); ++it) it->first; it->second;
 16     {
 17         StrPairVal(FileNode::NONE),
 18         StrPairVal(FileNode::INT),
 19         StrPairVal(FileNode::REAL),//=FLOAT
 20         StrPairVal(FileNode::STR),//=STRING
 21         StrPairVal(FileNode::SEQ),
 22         StrPairVal(FileNode::MAP),
 23         StrPairVal(FileNode::NAMED),
 24         StrPairVal(FileNode::TYPE_MASK),
 25         StrPairVal(FileNode::FLOW),//=UNIFORM
 26         StrPairVal(FileNode::EMPTY)//for SEQ and MAP
 27     };
 28 
 29     string traverseFS(FileNode fn, int level, bool useIndex = true)
 30     {
 31         string str; for (int k = 0; k < level; ++k) str += "t";
 32         str += fmt::format("<L{}>-<{}>-<{}>: ", level, fnTypes[fn.type()], (fn.isNamed() ? fn.name() : "noName"));
 33 
 34         if (fn.isInt()) str += std::to_string(int(fn));
 35         if (fn.isReal()) str += std::to_string(fn.real());
 36         if (fn.isString()) str += fn.string();
 37         if (useIndex)
 38         {
 39             if (fn.isSeq()) for (size_t k = 0; k < fn.size(); ++k) str += "n" + traverseFS(fn[k], level + 1);
 40             if (fn.isMap()) for (size_t k = 0; k < fn.keys().size(); ++k) str += "n" + traverseFS(fn[fn.keys()[k]], level + 1);
 41         }
 42         else if (fn.isSeq() || fn.isMap()) for (FileNodeIterator it = fn.begin(); it != fn.end(); ++it) str += "n" + traverseFS(*it, level + 1);
 43         return str;
 44     };
 45 
 46     void copyFS(FileStorage srcFS, FileStorage dstFS)
 47     {
 48         //(1)Node support: to the first level
 49         //(2)Type support: C++ static, OpenCV static, std::string, std::vector, cv::Mat
 50         for (FileNodeIterator it = srcFS.root(0).begin(); it != srcFS.root(0).end(); ++it)
 51         {
 52             //Scalar
 53             FileNode fn0 = *it;
 54             if (fn0.isInt()) dstFS << fn0.name() << int(fn0);
 55             if (fn0.isReal()) dstFS << fn0.name() << fn0.real();
 56             if (fn0.isString()) dstFS << fn0.name() << fn0.string();
 57             if (fn0.isMap()) dstFS << fn0.name() << fn0.mat();
 58 
 59             //Vector
 60             FileNode fn1 = *(fn0.begin());
 61             if (fn0.isSeq() && fn1.isInt()) { vector<int> int1D; srcFS[fn0.name()] >> int1D; dstFS << fn0.name() << int1D; }
 62             if (fn0.isSeq() && fn1.isReal()) { vector<double> flt1D; srcFS[fn0.name()] >> flt1D; dstFS << fn0.name() << flt1D; }
 63             if (fn0.isSeq() && fn1.isString()) { vector<string> str1D; srcFS[fn0.name()] >> str1D; dstFS << fn0.name() << str1D; }
 64             if (fn0.isSeq() && fn1.isMap()) { vector<Mat> mat1D; srcFS[fn0.name()] >> mat1D; dstFS << fn0.name() << mat1D; }
 65 
 66             //VectorVector
 67             FileNode fn2 = *(fn1.begin());
 68             if (fn0.isSeq() && fn1.isSeq() && fn2.isInt()) { vector<vector<int>> int2D; srcFS[fn0.name()] >> int2D; dstFS << fn0.name() << int2D; }
 69             if (fn0.isSeq() && fn1.isSeq() && fn2.isReal()) { vector<vector<double>> flt2D; srcFS[fn0.name()] >> flt2D; dstFS << fn0.name() << flt2D; }
 70             if (fn0.isSeq() && fn1.isSeq() && fn2.isString()) { vector<vector<string>> str2D; srcFS[fn0.name()] >> str2D; dstFS << fn0.name() << str2D; }
 71             if (fn0.isSeq() && fn1.isSeq() && fn2.isMap()) { vector<vector<Mat>> mat2D; srcFS[fn0.name()] >> mat2D; dstFS << fn0.name() << mat2D; }
 72         }
 73     };
 74 
 75 public:
 76     void testFS(int argc = 0, char** argv = 0)
 77     {
 78         string fsPath0 = "./fs0.yml";
 79         string fsPath1 = "./fs1.yml";
 80         string fsPath2 = "./fs2.yml";
 81         string fsAllPath1 = "./fsAllData1.txt";
 82         string fsAllPath2 = "./fsAllData2.txt";
 83         string fsRootPath = "./fsRootInfo.txt";
 84 
 85         //1.GetSourceFS
 86         {
 87             FileStorage fs(fsPath0, FileStorage::WRITE);
 88 
 89             //1.1 C++int
 90             int int0D = 111;
 91             vector<int> int1D(2, int0D); for (size_t k = 0; k < int1D.size(); ++k) int1D[k] += int(k + 1);
 92             vector<vector<int>> int2D(3, int1D); for (size_t i = 0; i < int2D.size(); ++i) for (size_t j = 0; j < int2D[i].size(); ++j) int2D[i][j] += int(i + j);
 93             fs << "int0D" << int0D << "int1D" << int1D << "int2D" << int2D;
 94 
 95             //1.2 C++string
 96             string str0D("abc");
 97             vector<string> str1D(2, str0D); for (size_t k = 0; k < str1D.size(); ++k) str1D[k] += std::to_string(k);
 98             vector<vector<string>> str2D(3, str1D);  for (size_t i = 0; i < str2D.size(); ++i) for (size_t j = 0; j < str2D[i].size(); ++j) str2D[i][j] += fmt::format("{}{}", i, j);
 99             fs << "str0D" << str0D << "str1D" << str1D << "str2D" << str2D;
100 
101             //1.3 OpenCVRect
102             Rect rect0D(111, 222, 333, 444);
103             vector<Rect> rect1D(2); cv::randu(rect1D, 111, 999);
104             vector<vector<Rect>> rect2D(3, vector<Rect>(2)); for (size_t k = 0; k < rect2D.size(); ++k) cv::randu(rect2D[k], 111, 999);
105             fs << "rect0D" << rect0D << "rect1D" << rect1D << "rect2D" << rect2D;
106 
107             //1.4 OpenCVMat
108             Mat_<Vec3i> mat0D(3, 3, Vec3i(111, 222, 333));
109             vector<Mat_<Vec3i>> mat1D(2); for (int k = 0; k < mat1D.size(); ++k) { mat1D[k].create(3, 3); cv::randu(mat1D[k], 111, 999); }
110             vector<vector<Mat_<Vec3i>>> mat2D(3, vector<Mat_<Vec3i>>(2));  for (size_t i = 0; i < mat2D.size(); ++i) for (size_t j = 0; j < mat2D[i].size(); ++j) { mat2D[i][j].create(3, 3); cv::randu(mat2D[i][j], 111, 999); }
111             fs << "mat0D" << mat0D << "mat1D" << mat1D << "mat2D" << mat2D;
112         }
113 
114         //2.ReadFS0AndWriteFS1
115         {
116             FileStorage fs0(fsPath0, FileStorage::READ);
117             FileStorage fs1(fsPath1, FileStorage::WRITE);
118 
119             //2.1 C++int
120             int int0D; fs0["int0D"] >> int0D;
121             vector<int> int1D; fs0["int1D"] >> int1D;
122             vector<vector<int>> int2D; fs0["int2D"] >> int2D;
123             fs1 << "int0D" << int0D << "int1D" << int1D << "int2D" << int2D;
124 
125             //2.2 C++string
126             string str0D; fs0["str0D"] >> str0D;
127             vector<string> str1D; fs0["str1D"] >> str1D;
128             vector<vector<string>> str2D; fs0["str2D"] >> str2D;
129             fs1 << "str0D" << str0D << "str1D" << str1D << "str2D" << str2D;
130 
131             //2.3 OpenCVRect
132             Rect rect0D; fs0["rect0D"] >> rect0D;
133             vector<Rect> rect1D; fs0["rect1D"] >> rect1D;
134             vector<vector<Rect>> rect2D; fs0["rect2D"] >> rect2D;
135             fs1 << "rect0D" << rect0D << "rect1D" << rect1D << "rect2D" << rect2D;
136 
137             //2.4 OpenCVMat
138             Mat_<Vec3b> mat0D; fs0["mat0D"] >> mat0D;
139             vector<Mat_<Vec3b>> mat1D; fs0["mat1D"] >> mat1D;
140             vector<vector<Mat_<Vec3i>>> mat2D; fs0["mat2D"] >> mat2D;
141             fs1 << "mat0D" << mat0D << "mat1D" << mat1D << "mat2D" << mat2D;
142         }
143 
144         //3.CopyFS0ToFS2
145         {
146             FileStorage fs0(fsPath0, FileStorage::READ);
147             FileStorage fs2(fsPath2, FileStorage::WRITE);
148             copyFS(fs0, fs2);
149         }
150 
151         //4.TranverseFS
152         string rets;
153         {
154             auto SaveTraverseFS = [this](string fsPath, string fsTraPath, bool useIndex)->string
155             {
156                 FileStorage fs(fsPath, FileStorage::READ);
157                 string str = traverseFS(fs.root(), 0, useIndex);
158                 fs.release();
159                 FILE* file = fopen(fsTraPath.c_str(), "w");
160                 fprintf(file, "%s", str.c_str());
161                 fclose(file);
162                 return str;
163             };
164             rets += "nn" + SaveTraverseFS(fsPath0, fsAllPath1, true);
165             rets += "nn" + SaveTraverseFS(fsPath0, fsAllPath2, false);
166         }
167 
168         //5.CheckRootNode
169         {
170             auto PrintNode = [this](FileNode fn)->string
171             {
172                 string str = fmt::format("ntfn.name(): {}tfn.type(): {}tfn.size(): {}t", (fn.isNamed() ? fn.name() : "noName"), fnTypes[fn.type()], fn.size());
173                 if (fn.isMap()) { str += fmt::format("fn.keys(): "); for (size_t k = 0; k < fn.keys().size(); ++k) str += fmt::format("{}   ", fn.keys()[k]); }
174                 return str;
175             };
176 
177             FileStorage fs(fsPath0, FileStorage::READ);
178             string str = fmt::format("fs.root(0): the zero level has only one node {}nn", PrintNode(fs.root(0)));
179             str + fmt::format("fs.getFirstTopLevelNode(): the first level: the first node {} nn", PrintNode(fs.getFirstTopLevelNode()));
180             str += "fs.root(0).begin()...fs.root(0).end(): the first level: the first node...the final node"; for (FileNodeIterator it = fs.root(0).begin(); it != fs.root(0).end(); ++it) str += PrintNode(*it); str += "nn";
181             str += fmt::format("fs[rect0D]: the first level: the specific node {}nn", PrintNode(fs["rect0D"]));
182             rets += "nn" + str;
183 
184             FILE* file = fopen(fsRootPath.c_str(), "w");
185             fprintf(file, "%s", str.c_str());
186             fclose(file);
187         }
188         spdlog::info(rets);
189     }
190 };
191 
192 int main(int argc, char** argv) { AboutFileStorage afs; afs.testFS(argc, argv); return 0; }

View Code

原文链接: https://www.cnblogs.com/dzyBK/p/13908299.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    OpenCV-Utils学习日志:FileStorage使用样例

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/326441

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月1日 下午3:49
下一篇 2023年3月1日 下午3:50

相关推荐