欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++ OpenCV讀寫XML或YAML文件的方法詳解

 更新時(shí)間:2022年05月09日 10:20:35   作者:求則得之,舍則失之  
XML是一種元標(biāo)記語言。所謂元標(biāo)記,就是開發(fā)者可以根據(jù)自身需要定義自己的標(biāo)記。YAML是一個(gè)可讀性高,用來表達(dá)資料序列的格式。本文將通過C++和OpenCV實(shí)現(xiàn)這兩種文件的讀寫,需要的可以參考一下

前言

本節(jié)我們將認(rèn)識XML和YAML這兩種文件類型。

所謂XML,即eXtensible Markup Language,翻譯成中文為“可擴(kuò)展標(biāo)識語言”。首先,XML是一種元標(biāo)記語言。所謂元標(biāo)記,就是開發(fā)者可以根據(jù)自身需要定義自己的標(biāo)記,比如可以定義標(biāo)記<book>、<name>。任何滿足XML命名規(guī)則的名稱都可以標(biāo)記,這就向不同的應(yīng)用程序打開了的大門。此外,XML是一種語義、結(jié)構(gòu)化語言,它描述了文檔的結(jié)構(gòu)與語義。

YAML是YAML Ain’t a Markup Language(YAML不是一種置標(biāo)語言)的縮寫。YAML是一個(gè)可讀性高,用來表達(dá)資料序列的格式。它參考了其他多種語言,包括:XML、C語言、Python、Perl以及電子郵件格式RFC2822。

1.如何使用

XML和YAML是使用非常廣泛的文件格式??梢岳肵ML或者YAML格式的文件存儲(chǔ)和還原各式各樣的數(shù)據(jù)結(jié)構(gòu)。當(dāng)然,它們還可以存儲(chǔ)和載入任意復(fù)雜的數(shù)據(jù)結(jié)構(gòu),其中就包括了OpenCV相關(guān)周邊的數(shù)據(jù)結(jié)構(gòu),以及各種原始數(shù)據(jù)類型,如整數(shù)、浮點(diǎn)數(shù)和文本字符串。

我們一般使用如下過程來寫入或者讀取數(shù)據(jù)到XML或YAML文件中。

(1)實(shí)例化一個(gè)FileStorage類的對象,用默認(rèn)帶參數(shù)的構(gòu)造函數(shù)完成初始化,或者用FileStorage::open()成員函數(shù)輔助初始化。

(2)使用流操作符<<進(jìn)行文件寫入操作,或者>>進(jìn)行文件讀取操作,類似C++中的文件輸入輸出流。

(3)使用FileStorage::release()函數(shù)析構(gòu)掉FileStorage類對象,同時(shí)關(guān)閉文件。

1.1第一步:XML、YAML文件的打開

(1)準(zhǔn)備文件寫操作

FileStorage是OpenCV中XML和YAML文件的存儲(chǔ)類,封裝了所有相關(guān)的信息。它是OpenCV從文件中讀數(shù)據(jù)或向文件中寫數(shù)據(jù)時(shí)必須要使用的一個(gè)類。

此類的構(gòu)造函數(shù)為FileStorage::FileStorage,有兩個(gè)重載,如下:

C++:FileStorage::FileStorage()
C++:FileStorage::FileStorage(const string& source, int flags, const string& encoding=string())

構(gòu)造函數(shù)在實(shí)際使用中,一般有兩種方法。

1)對于第二種帶參數(shù)的構(gòu)造函數(shù),進(jìn)行寫操作范例如下:

FileStorage fs("abc.xml", FileStorage::WRITE);

2)對于第一種不帶參數(shù)的構(gòu)造函數(shù),可以使用其成員函數(shù)FileStorage::open進(jìn)行數(shù)據(jù)的寫操作,范例如下:

FileStorage fs;
fs.open("abc.xml",FileStorage::WRITE);

(2)準(zhǔn)備文件讀操作

上面講到的都是以FileStorage::WRITE為標(biāo)識符的寫操作,而讀操作,采用FileStorage::READ標(biāo)識符即可,相關(guān)示例代碼如下:

1)第一種方式

FileStorage fs(“abc.xml”, FileStorage::READ);

2)第二種方式

FileStorage fs;
fs.open(“abc.xml”, FileStorage::READ);

另外需要注意的是,上面的這些操作示例是對XML文件為例子作演示的,而對YAML文件,操作方法是類似的,就是將XML文件換為YAML文件即可。

1.2 第二步:進(jìn)行文件讀寫操作

(1)文本和數(shù)字的輸入和輸出

定義好FileStorage類對象之后,寫入文件可以使用<<運(yùn)算符,例如:

fs<<"iterationNr"<<100;

而讀取文件,使用>>運(yùn)算符,例如:

int itNr;
fs["iterationNr"]>>itNr;
itNr = (int) fs["iterationNr"];

(2)OpenCV數(shù)據(jù)結(jié)構(gòu)的輸入和輸出

關(guān)于OpenCV數(shù)據(jù)結(jié)構(gòu)的輸入和輸出,和基本的C++形式相同,范例如下:

// 數(shù)據(jù)結(jié)構(gòu)的初始化
Mat R = Mat_<uchar>::eye(3,3);
Mat T = Mat_<double>::zeros(3, 1);
// 向Mat中寫入數(shù)據(jù)
fs << "R" << R;
fs << "T" << T;
// 從Mat中讀取數(shù)據(jù)
fs["R"]  >>  R;
fs["T"] >> T;

1.3 第三步:vector(array)和map的輸入和輸出

對于vector結(jié)構(gòu)的輸出和輸出,要注意在第一個(gè)元素前加上”[“,在最后一個(gè)元素后加上”]“。例如:

fs << "strings"<<"[";  //開始讀入string文本序列
fs << "image1.jpg" << "Awesomeness" << "baboon.jpg";
fs << "]"; //關(guān)閉序列

而對于map結(jié)構(gòu)的操作,使用的符號是”{“和”}“,例如:

fs << "Mapping";//開始讀入Mapping文本
fs << "{" << "One" << 1;
fs << "Two" << 2 << "}";

讀取這些數(shù)據(jù)結(jié)構(gòu)的時(shí)候,會(huì)用到FileNode和FileNodeIterator數(shù)據(jù)結(jié)構(gòu)。對FileStorage類的“[”、“]”操作符會(huì)返回FileNode數(shù)據(jù)類型;對于一連串的node,可以使用FileNodeIterator結(jié)構(gòu),例如:

```cpp
FileNode n = fs["strings"];//讀取字符串序列以得到節(jié)點(diǎn)
if (n.type()!=FileNode::SEQ)
{
    cerr << "發(fā)生錯(cuò)誤!字符串不是一個(gè)序列" << endl;
    return 1;
}
FileNodeIterator it = n.begin(),it_end = n.end(); //遍歷節(jié)點(diǎn)
for(;it!=it_end;it++)
cout << (string)*it << endl;

1.4 第四步:文件關(guān)閉

需要注意的是,文件關(guān)閉操作會(huì)在FileStorage類銷毀時(shí)自動(dòng)進(jìn)行,但我們也可以顯式調(diào)用其析構(gòu)函數(shù)FileStorage::release()實(shí)現(xiàn)。FileStorage::release()函數(shù)會(huì)析構(gòu)掉FileStorage類對象,同時(shí)關(guān)閉文件。

調(diào)用過程非常簡單,如下:fs.release();

2.代碼展示

2.1 寫文件

#include<opencv2/opencv.hpp>
#include<time.h>
using namespace cv;

int main()
{
    //初始化
    FileStorage fs("test.yaml", FileStorage::WRITE);

    //開始文件寫入
    fs << "frameCount" << 5;
    time_t rawtime; time(&rawtime);
    fs << "calibrationDate" << asctime(localtime(&rawtime));//讀取時(shí)間量
     Mat cameraMatrix = (Mat_<double>(3, 3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1);
    Mat distCoeffs = (Mat_<double>(5, 1) << 0.1, 0.01, -0.001, 0, 0);//畸變參數(shù)
    fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;//讀取Mat型cameraMatrix,distcoeffs的內(nèi)容
    fs << "feature" << "[";
    for (int i = 0; i < 3; i++)
    {
        int x = rand() % 640;
        int y = rand() % 480;
        uchar ibp = rand() % 256;

        fs << "{:" << "x" << x << "y" << y << "ibp" << "[:";
        for (int j = 0; j < 8; j++)
            fs << ((ibp >> j) & 1);
        fs << "]" << "}";
    }
    fs << "]";
    fs.release();
    printf("完畢,請?jiān)诠こ棠夸浵虏榭次募?");
    getchar();

    return 0;
}

上面的示例將一個(gè)整數(shù)、一個(gè)文本字符串(標(biāo)定日期)、2 個(gè)矩陣和一個(gè)自定義結(jié)構(gòu)“feature”存儲(chǔ)到 YML,其中包括特征坐標(biāo)和 LBP(局部二進(jìn)制模式)值。這是樣本的輸出:

%YAML:1.0
frameCount: 5
calibrationDate: "Fri Jun 17 14:09:29 2011\n"
cameraMatrix: !!opencv-matrix
   rows: 3
   cols: 3
   dt: d
   data: [ 1000., 0., 320., 0., 1000., 240., 0., 0., 1. ]
distCoeffs: !!opencv-matrix
   rows: 5
   cols: 1
   dt: d
   data: [ 1.0000000000000001e-01, 1.0000000000000000e-02,
       -1.0000000000000000e-03, 0., 0. ]
features:
   - { x:167, y:49, lbp:[ 1, 0, 0, 1, 1, 0, 1, 1 ] }
   - { x:298, y:130, lbp:[ 0, 0, 0, 1, 0, 0, 1, 1 ] }
   - { x:344, y:158, lbp:[ 1, 1, 0, 0, 0, 0, 1, 0 ] }

作為練習(xí),您可以將上面示例中的“.yml”替換為“.xml”或“.json”,然后查看相應(yīng)的 XML 文件的外觀。

通過查看示例代碼和輸出可以注意到幾件事:

  • 生成的 YAML(和 XML/JSON)由可以嵌套的異構(gòu)集合組成。有兩種類型的集合:命名集合(映射)和未命名集合(序列)。在映射中,每個(gè)元素都有一個(gè)名稱并通過名稱訪問。這類似于 C/C++ 中的std::map結(jié)構(gòu)以及 Python 中的字典。在序列中元素沒有名稱,它們通過索引訪問。這類似于 C/C++ 中的std::vector數(shù)組以及 Python 中的列表、元組。“異構(gòu)”意味著每個(gè)單一集合的元素可以有不同的類型。
  • YAML/XML/JSON 中的頂級集合是一個(gè)映射。每個(gè)矩陣存儲(chǔ)為一個(gè)映射,矩陣元素存儲(chǔ)為一個(gè)序列。然后,有一個(gè)特征序列,其中每個(gè)特征都表示一個(gè)映射,以及嵌套序列中的 lbp 值。
  • 當(dāng)您寫入映射(結(jié)構(gòu))時(shí),您寫入元素名稱后跟其值。當(dāng)您寫入一個(gè)序列時(shí),您只需一個(gè)一個(gè)地寫入元素。OpenCV 數(shù)據(jù)結(jié)構(gòu)(例如cv::Mat)的編寫方式與簡單的 C 數(shù)據(jù)結(jié)構(gòu)完全相同 - 使用<<運(yùn)算符。
  • 要編寫映射,首先寫入特殊字符串{,然后將元素作為對 ( fs << <element_name> << <element_value>) 寫入,然后寫入結(jié)束符}。
  • 要編寫一個(gè)序列,首先要編寫特殊的字符串[,然后編寫元素,然后編寫結(jié)束]。
  • 在 YAML/JSON(但不是 XML)中,映射和序列可以以類似 Python 的緊湊內(nèi)聯(lián)形式編寫。在上面的示例中,矩陣元素以及每個(gè)特征,包括它的 lbp 值,都以這種內(nèi)聯(lián)形式存儲(chǔ)。要以緊湊的形式存儲(chǔ)映射/序列,請放在:開始字符之后,例如使用{:代替{和[:代替[。當(dāng)數(shù)據(jù)寫入 XML 時(shí),那些額外:的將被忽略。

2.2 讀文件

#include<opencv2/opencv.hpp>
#include<time.h>
using namespace cv;
using namespace std;

int main()
{
    //改變consolo字體顏色
    system("color 6F");

    //初始化
    FileStorage fs2("test.yaml", FileStorage::READ);

    //開始文件讀取
    //法一,對FileNode操作
    int frameCount2 = (int)fs2["framecount2"];
    std::string date;//定義字符串 date

    //法二,使用FileNode運(yùn)算符>>
    fs2["calibrationDate"] >> date;

    Mat cameraMatrix2, distCoeffs2;
    fs2["cameraMatrix"] >> cameraMatrix2;
    fs2["distCoeffs"] >> distCoeffs2;//讀取

    cout << "frameCount2:" << frameCount2 << endl
        << "calibration date:" << date << endl
        << "camera matrix:" << cameraMatrix2 << endl
        << "distortion coeffs:" << distCoeffs2 << endl;

    FileNode feature = fs2["feature"];
    FileNodeIterator it = feature.begin(), it_end = feature.end();//定義it
    int idx = 0;
    std::vector<uchar>ibpval;//定義向量容器ibpal

    //使用FileNodeIterator歷遍序列(讀?。?
    for (; it != it_end; it++, idx++)
    {
        cout << "feature#" << idx << ":";
        cout << "x=" << (int)(*it)["x"] << ",y=" << (int)(*it)["y"] << ",ibp:(";
        //也可以使用filenod>>std::vector操作符很容易讀取數(shù)值陣列
        (*it)["ibp"] >> ibpval;
        for (int i = 0; i < (int)ibpval.size(); i++)
            cout << "" << (int)ibpval[i];
        cout << ")" << endl;
    }


    fs2.release();
    printf("讀取完畢,請按任意鍵結(jié)束-");
    getchar();

    return 0;
}

2.3 完整的示例代碼

/*
 * filestorage_sample demonstrate the usage of the opencv serialization functionality
 */
#include "opencv2/core.hpp"
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;
using std::cerr;
using std::ostream;
using namespace cv;
static void help(char** av)
{
  cout << "\nfilestorage_sample demonstrate the usage of the opencv serialization functionality.\n"
      << "usage:\n"
      <<  av[0] << " outputfile.yml.gz\n"
      << "\n   outputfile above can have many different extensions, see below."
      << "\nThis program demonstrates the use of FileStorage for serialization, that is in use << and >>  in OpenCV\n"
      << "For example, how to create a class and have it serialize, but also how to use it to read and write matrices.\n"
      << "FileStorage allows you to serialize to various formats specified by the file end type."
          << "\nYou should try using different file extensions.(e.g. yaml yml xml xml.gz yaml.gz etc...)\n" << endl;
}
struct MyData
{
  MyData() :
    A(0), X(0), id()
  {
  }
  explicit MyData(int) :
    A(97), X(CV_PI), id("mydata1234")
  {
  }
  int A;
  double X;
  string id;
  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"];
  }
};
//These write and read functions must exist as per the inline functions in operations.hpp
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;
  else
    x.read(node);
}
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)
{
  cv::CommandLineParser parser(ac, av,
    "{@input||}{help h ||}"
  );
  if (parser.has("help"))
  {
    help(av);
    return 0;
  }
  string filename = parser.get<string>("@input");
  if (filename.empty())
  {
    help(av);
    return 1;
  }
  //write
  {
    FileStorage fs(filename, FileStorage::WRITE);
    cout << "writing images\n";
    fs << "images" << "[";
    fs << "image1.jpg" << "myfi.png" << "baboon.jpg";
    cout << "image1.jpg" << " myfi.png" << " baboon.jpg" << endl;
    fs << "]";
    cout << "writing mats\n";
    Mat R =Mat_<double>::eye(3, 3),T = Mat_<double>::zeros(3, 1);
    cout << "R = " << R << "\n";
    cout << "T = " << T << "\n";
    fs << "R" << R;
    fs << "T" << T;
    cout << "writing MyData struct\n";
    MyData m(1);
    fs << "mdata" << m;
    cout << m << endl;
  }
  //read
  {
    FileStorage fs(filename, FileStorage::READ);
    if (!fs.isOpened())
    {
      cerr << "failed to open " << filename << endl;
      help(av);
      return 1;
    }
    FileNode n = fs["images"];
    if (n.type() != FileNode::SEQ)
    {
      cerr << "images is not a sequence! FAIL" << endl;
      return 1;
    }
    cout << "reading images\n";
    FileNodeIterator it = n.begin(), it_end = n.end();
    for (; it != it_end; ++it)
    {
      cout << (string)*it << "\n";
    }
    Mat R, T;
    cout << "reading R and T" << endl;
    fs["R"] >> R;
    fs["T"] >> T;
    cout << "R = " << R << "\n";
    cout << "T = " << T << endl;
    MyData m;
    fs["mdata"] >> m;
    cout << "read mdata\n";
    cout << m << endl;
    cout << "attempting to read mdata_b\n";   //Show default behavior for empty matrix
    fs["mdata_b"] >> m;
    cout << "read mdata_b\n";
    cout << m << endl;
  }
  cout << "Try opening " << filename << " to see the serialized data." << endl << endl;
  //read from string
  {
    cout << "Read data from string\n";
    string dataString =
        "%YAML:1.0\n"
        "mdata:\n"
        "   A: 97\n"
        "   X: 3.1415926535897931e+00\n"
        "   id: mydata1234\n";
    MyData m;
    FileStorage fs(dataString, FileStorage::READ | FileStorage::MEMORY);
    cout << "attempting to read mdata_b from string\n";   //Show default behavior for empty matrix
    fs["mdata"] >> m;
    cout << "read mdata\n";
    cout << m << endl;
  }
  //write to string
  {
    cout << "Write data to string\n";
    FileStorage fs(filename, FileStorage::WRITE | FileStorage::MEMORY | FileStorage::FORMAT_YAML);
    cout << "writing MyData struct\n";
    MyData m(1);
    fs << "mdata" << m;
    cout << m << endl;
    string createdString = fs.releaseAndGetString();
    cout << "Created string:\n" << createdString << "\n";
  }
  return 0;
}

到此這篇關(guān)于C++ OpenCV讀寫XML或YAML文件的方法詳解的文章就介紹到這了,更多相關(guān)C++讀寫XML YAML文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言中字符串的存儲(chǔ)方法

    C語言中字符串的存儲(chǔ)方法

    這篇文章主要為大家詳細(xì)介紹了C語言中字符串的存儲(chǔ)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • C語言通過三步翻轉(zhuǎn)法實(shí)現(xiàn)單詞倒置詳解

    C語言通過三步翻轉(zhuǎn)法實(shí)現(xiàn)單詞倒置詳解

    這篇文章主要為大家分享了用三步翻轉(zhuǎn)法將一句話的單詞進(jìn)行倒置的方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-05-05
  • C語言中指針的加減運(yùn)算方法示例

    C語言中指針的加減運(yùn)算方法示例

    這篇文章主要給大家介紹了關(guān)于C語言中指針的加減運(yùn)算的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用C語言具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • c++ primer中的const限定符

    c++ primer中的const限定符

    這篇文章主要介紹了c++ primer中的const限定符,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • Qt繪制時(shí)鐘效果

    Qt繪制時(shí)鐘效果

    這篇文章主要為大家詳細(xì)介紹了Qt繪制時(shí)鐘效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • Qt學(xué)習(xí)教程之表格控件螞蟻線詳解

    Qt學(xué)習(xí)教程之表格控件螞蟻線詳解

    如果有用過PS的選區(qū)工具應(yīng)該就會(huì)知道螞蟻線是什么東西了,就是用來表示選區(qū)的一種虛線,關(guān)鍵還是要?jiǎng)討B(tài)的!下面這篇文章主要給大家介紹了關(guān)于Qt學(xué)習(xí)教程之表格控件螞蟻線的相關(guān)資料,需要的朋友可以參考下
    2018-07-07
  • visual?studio?2022?編譯出來的文件被刪除并監(jiān)視目錄中的文件變更(示例詳解)

    visual?studio?2022?編譯出來的文件被刪除并監(jiān)視目錄中的文件變更(示例詳解)

    這篇文章主要介紹了visual?studio?2022?編譯出來的文件被刪除?并監(jiān)視目錄中的文件變更,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • C語言常見的指針筆試題解析

    C語言常見的指針筆試題解析

    在我們學(xué)習(xí)指針之后,應(yīng)該在實(shí)際應(yīng)用中去理解和掌握它,畢竟實(shí)踐才是檢驗(yàn)真理的唯一標(biāo)準(zhǔn),我們以后在找工作的過程中免不了會(huì)遇到與指針相關(guān)的試題,本篇文章可以幫助我們提前了解一些常見的指針考點(diǎn),需要的可以了解一下
    2022-10-10
  • C語言實(shí)現(xiàn)銀行管理系統(tǒng)

    C語言實(shí)現(xiàn)銀行管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)銀行管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • C語言函數(shù)的遞歸和調(diào)用實(shí)例分析

    C語言函數(shù)的遞歸和調(diào)用實(shí)例分析

    一個(gè)函數(shù)在它的函數(shù)體內(nèi)調(diào)用它自身稱為遞歸調(diào)用。這種函數(shù)稱為遞歸函數(shù)。C語言允許函數(shù)的遞歸調(diào)用。在遞歸調(diào)用中,主調(diào)函數(shù)又是被調(diào)函數(shù)。執(zhí)行遞歸函數(shù)將反復(fù)調(diào)用其自身,每調(diào)用一次就進(jìn)入新的一層
    2013-07-07

最新評論