当前位置:   article > 正文

Opencv YAML和XML格式文件操作详解

opencv yaml文件解析数组


本系列文章由 @YhL_Leo 出品,转载请注明出处。
文章链接: http://blog.csdn.net/yhl_leo/article/details/47660943


本文参考Opencv 2.4.11 documentation整理对YAMLXML文件实现I/O操作的方法。

官网:YAMLhttp://www.yaml.org XML :http://www.w3c.org/XML

1.YAML与XML文件的打开和关闭

YAML格式的文件拓展名包括:.yml.yaml,两个都表示YAML文件;
XML格式的文件拓展名为: .xml

1.1 文件打开

Opencv中,使用FileStorage进行文件读写。XML文件操作与YAML一样,不过存在一些细小差别。

  1. std::string fileName = "E:\\test.yml"; // YAML
  2. std::string fileName2 = "E:\\test.xml"; // XML
  3. // write file
  4. cv::FileStorage fs(fileName , cv::FileStorage::WRITE);
  5. // read file
  6. cv::FileStorage fs2(fileName , cv::FileStorage::READ);
  7. // or use: cv::FileStorage::open
  8. fs2.open(fileName , cv::FileStorage::READ);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

FileStorage的文件操作模式一共分为四种:READWRITEAPPENDMEMORY

20150814134114446

文档打开后很关心的一件事就是,进行确认是否成功。FileStorage有自己的成员函数返回文件打开状态:

  1. // bool FileStorage::isOpened() const;
  2. if ( !fs.isOpened() ) // failed
  3. {
  4. std::cout<<"Save File Failed!"<<std::endl;
  5. return ;
  6. }
  7. else // succeed
  8. {
  9. ...
  10. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

1.2 文件关闭

FileStorage文件关闭比较简单:

fs.release();
  • 1

2.文件读写

FileStorage文件读与写的方法与C++语言中的文件流对象的使用很像,对>><<进行了重载,分别用于文件读取和写入。很棒的是,FileStorage支持一些常用格式的直接读写,例如字符、字符串、数字、cv::Mat等。对于不支持的数据结构,只能按照规则自己去写啦~

2.1 写入

  1. fs << "frameCount" << 5; // 字符和数字
  2. cv::Mat_<double> cameraMat = cv::Mat_<double>::zeros(3, 3);
  3. fs << "Camera Intrinsic Matrix" << cameraMat; // cv::Mat
  • 1
  • 2
  • 3

注意:

  • fs << "frameCount" <<5""内输出的字符串是有限制的,对于YAML有效范围是:[a-z],[A-Z],[0-9],”-“,”_”和空格。XML与YAML基本一致,但是YAML字符之间加空格是允许的,XML不允许。如果出现以下BUG,请不要慌张,检查一下输入的字符是否有效就OK~

20150814194439582

20150814205622393

20150814205646126

2.2 读取

文件读取的方法有两种:

  1. // first method: use (type) operator on FileNode.
  2. int frameCount = (int)fs2["frameCount"];
  3. // second second method: use cv::FileNode::operator >>
  4. int frameCount;
  5. fs2["frameCount"] >> frameCount;
  • 1
  • 2
  • 3
  • 4
  • 5

2.3 Mat的操作

这一点真的很不错,而且与C++的输入输出方法很接近(链接:常用的三种Mat类型):

  1. cv::Mat_<double> cameraMat = cv::Mat_<double>::zeros(3, 3);
  2. cv::Mat_<double> distCoeffes = ( cv::Mat_<double>(5, 1)<< 0.1, 0.01, -0.001, 0.0, 0.0 );
  3. // C++
  4. std::cout<<"Camera Matrix"<<std::endl<<cv::Mat::Mat(cameraMat)<<std::endl;
  5. std::cout<<"Distortion Coefficients"<<std::endl<<cv::Mat::Mat(distCoeffes)<<std::endl;
  6. // cv::FileStorage
  7. fs << "Camera Matrix" << cameraMat;
  8. fs << "Distortion Coefficients"<<distCoeffes;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

运行结果对比如下:

C++ C++
YAML YAML
XML YAML

2.4 集合的操作

Opencv中将集合分为两类:映射和序列。

映射集合(Mappings, 又称named collections):每个元素有一个名字或者说关键字,并且可以通过名字访问其数据,类似于Key-Value结构。使用方法为:

  1. // Mappings write
  2. int x(1.0), y(0.0);
  3. fs << "features" << "["; // also can be "[:"
  4. fs <<"{:" << "x" << x << "y" << "}" << "]";
  • 1
  • 2
  • 3
  • 4
  • "{""{:"输出的结果是不一样的,YAML使用":"后,使输出的文本具有Python的风格,映射集合会按照一行排列,不适用时,按照每个元素与其值单独一行的方法排列。XML使用":"后输出结果会有不同,但基本可以视为把":"忽略。

YAML { Map1
YAML {: Map2
XML { Map3
XML {: Map4

  1. // Mappings read
  2. cv::FileNode features = fs2["features"];
  3. // 遍历查看
  4. cv::FileNodeIterator it = features.begin();
  5. std::cout<<
  6. "x="<<(int)(*it)["x"]<<
  7. " y="<<(int)(*it)["y"]<<
  8. " z="<<(int)(*it)["z"]<<std::endl;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

输出结果:Output

  • 编程的时候,不在Mapping的"{ }"外加上"[ ]"输出的效果是不一样的,而且在数据读取的时候,加上"[
    ]"
    的Mapping结构会被认为是Mapping结构,否则会出错,以上述的Mappings write代码为例: 对于 fs <<
    "fearures" << "[" << "{" << ... << "}" << "]"
    结构,用上述方法可以读取成功; 对于 fs
    << "features" << "{" << ... << "}"
    结构,用上述方法时就会出错:
    20150815110912348

序列集合(Sequences,又称unnamed collections):数据没有名字名字或者关键字,一般通过序号(indices)访问数据,例如最常见的数组。

与映射类似,序列集合需要在输出开始前加"[",结束后使用"]",并且"[:""["在输出风格上与映射集合类似。

  1. // Sequences write
  2. int mySeq[5] = {0, 1, 2, 3, 4};
  3. fs << "mySeq" << "[";
  4. for ( int idx=0; idx<5; idx++ )
  5. {
  6. fs << mySeq[idx];
  7. }
  8. fs << "]";
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  1. // Sequences read
  2. cv::FileNode mySeq2 = fs2["mySeq"];
  3. std::vector<int> seq;
  4. cv::FileNodeIterator it = mySeq2.begin(), it_end = mySeq2.end();
  5. for ( ; it != it_end; it++ )
  6. {
  7. seq.push_back( (int)( *it ) );
  8. // std::cout<<(int)(*it)<<" "<<std::endl;
  9. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

3.Opencv documentation 源码示例

下面贴出Opencv documentation中的示例代码,可以作为参考:

  1. // file write
  2. #include "opencv2/opencv.hpp"
  3. #include <time.h>
  4. using namespace cv;
  5. using namespace std;
  6. int main(int, char** argv)
  7. {
  8. FileStorage fs("test.yml", FileStorage::WRITE);
  9. fs << "frameCount" << 5;
  10. time_t rawtime; time(&rawtime);
  11. fs << "calibrationDate" << asctime(localtime(&rawtime));
  12. Mat cameraMatrix = (Mat_<double>(3,3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1);
  13. Mat distCoeffs = (Mat_<double>(5,1) << 0.1, 0.01, -0.001, 0, 0);
  14. fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;
  15. fs << "features" << "[";
  16. for( int i = 0; i < 3; i++ )
  17. {
  18. int x = rand() % 640;
  19. int y = rand() % 480;
  20. uchar lbp = rand() % 256;
  21. fs << "{:" << "x" << x << "y" << y << "lbp" << "[:";
  22. for( int j = 0; j < 8; j++ )
  23. fs << ((lbp >> j) & 1);
  24. fs << "]" << "}";
  25. }
  26. fs << "]";
  27. fs.release();
  28. return 0;
  29. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  1. // results
  2. %YAML:1.0
  3. frameCount: 5
  4. calibrationDate: "Fri Jun 17 14:09:29 2011\n"
  5. cameraMatrix: !!opencv-matrix
  6. rows: 3
  7. cols: 3
  8. dt: d
  9. data: [ 1000., 0., 320., 0., 1000., 240., 0., 0., 1. ]
  10. distCoeffs: !!opencv-matrix
  11. rows: 5
  12. cols: 1
  13. dt: d
  14. data: [ 1.0000000000000001e-01, 1.0000000000000000e-02,
  15. -1.0000000000000000e-03, 0., 0. ]
  16. features:
  17. - { x:167, y:49, lbp:[ 1, 0, 0, 1, 1, 0, 1, 1 ] }
  18. - { x:298, y:130, lbp:[ 0, 0, 0, 1, 0, 0, 1, 1 ] }
  19. - { x:344, y:158, lbp:[ 1, 1, 0, 0, 0, 0, 1, 0 ] }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  1. // file read
  2. FileStorage fs2("test.yml", FileStorage::READ);
  3. // first method: use (type) operator on FileNode.
  4. int frameCount = (int)fs2["frameCount"];
  5. std::string date;
  6. // second method: use FileNode::operator >>
  7. fs2["calibrationDate"] >> date;
  8. Mat cameraMatrix2, distCoeffs2;
  9. fs2["cameraMatrix"] >> cameraMatrix2;
  10. fs2["distCoeffs"] >> distCoeffs2;
  11. cout << "frameCount: " << frameCount << endl
  12. << "calibration date: " << date << endl
  13. << "camera matrix: " << cameraMatrix2 << endl
  14. << "distortion coeffs: " << distCoeffs2 << endl;
  15. FileNode features = fs2["features"];
  16. FileNodeIterator it = features.begin(), it_end = features.end();
  17. int idx = 0;
  18. std::vector<uchar> lbpval;
  19. // iterate through a sequence using FileNodeIterator
  20. for( ; it != it_end; ++it, idx++ )
  21. {
  22. cout << "feature #" << idx << ": ";
  23. cout << "x=" << (int)(*it)["x"] << ", y=" << (int)(*it)["y"] << ", lbp: (";
  24. // you can also easily read numerical arrays using FileNode >> std::vector operator.
  25. (*it)["lbp"] >> lbpval;
  26. for( int i = 0; i < (int)lbpval.size(); i++ )
  27. cout << " " << (int)lbpval[i];
  28. cout << ")" << endl;
  29. }
  30. fs.release();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

转载于:https://www.cnblogs.com/hehehaha/p/6332247.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/274706
推荐阅读
相关标签
  

闽ICP备14008679号