zoukankan      html  css  js  c++  java
  • 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。

      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 += "	";
     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 += "
    " + traverseFS(fn[k], level + 1);
     40             if (fn.isMap()) for (size_t k = 0; k < fn.keys().size(); ++k) str += "
    " + 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 += "
    " + 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 += "
    
    " + SaveTraverseFS(fsPath0, fsAllPath1, true);
    165             rets += "
    
    " + SaveTraverseFS(fsPath0, fsAllPath2, false);
    166         }
    167 
    168         //5.CheckRootNode
    169         {
    170             auto PrintNode = [this](FileNode fn)->string
    171             {
    172                 string str = fmt::format("
    	fn.name(): {}	fn.type(): {}	fn.size(): {}	", (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 {}
    
    ", PrintNode(fs.root(0)));
    179             str + fmt::format("fs.getFirstTopLevelNode(): the first level: the first node {} 
    
    ", 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 += "
    
    ";
    181             str += fmt::format("fs[rect0D]: the first level: the specific node {}
    
    ", PrintNode(fs["rect0D"]));
    182             rets += "
    
    " + 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
  • 相关阅读:
    Linux之cd、pwd、mkdir、rmdir
    Linux之目录结构配置
    Linux之chgrp
    Linux之chown
    Linux之chmod
    Linux之用户组、文件权限详解
    Linux命令之shutdown
    Linux命令之man
    Git-.gitignore配置
    Linux内核移植到JZ2440
  • 原文地址:https://www.cnblogs.com/dzyBK/p/13908299.html
Copyright © 2011-2022 走看看