【從零學習OpenCV】保存和讀取XML和YMAL文件

2021-02-13 小白學視覺

重磅乾貨,第一時間送達

經過幾個月的努力,小白終於完成了市面上第一本OpenCV 4入門書籍《從零學習OpenCV 4》。為了更讓小夥伴更早的了解最新版的OpenCV 4,小白與出版社溝通,提前在公眾號上連載部分內容,請持續關注小白。

除了圖像數據之外,有時程序中的尺寸較小的Mat類矩陣、字符串、數組等

數據也需要進行保存,這些數據通常保存成XML文件或者YAML文件。本小節中將介紹如何利用OpenCV 4中的函數將數據保存成XML文件或者YAML文件以及如何讀取這兩種文件中的數據。

XML是一種元標記語言,所謂元標記就是使用者可以根據自身需求定義自己的標記,例如可以用<age>、<color>等標記來定義數據的含義,例如用<age>24</age>來表示age數據的數值為24。XML是一種結構化的語言,通過XML語言可以知道數據之間的隸屬關係,例如<color><red>100</red><blue>150</blue></color>表示在color數據中含有兩個名為red和blue的數據,兩者的數值分別是100和150。通過標記的方式,無論以任何形式保存數據,只要文件滿足XML格式,那麼讀取出來的數據就不會出現混淆和歧義。XML文件的擴展名是「.xml」。

YMAL是一種以數據為中心的語言,通過「變量:數值」的形式來表示每個數據的數值,通過不同的縮進來表示不同數據之間的結構和隸屬關係。YMAL可讀性高,常用來表達資料序列的格式,它參考了多種語言,包括XML、C語言、Python、Perl等。YMAL文件的擴展名是「.ymal」或者「.yml」。

OpenCV 4中提供了用於生成和讀取XML文件和YMAL文件的FileStorage類,類中定義了初始化類、寫入數據和讀取數據等方法。我們在使用該FileStorage類時首先需要對其進行初始化,初始化可以理解為聲明需要操作的文件和操作類型。OpenCV 4提供了兩種初始化的方法,分別是不輸入任何參數的初始化(可以理解為只定義,並未初始化)和輸入文件名稱和操作類型的初始化。後者初始化構造函數的函數原型在代碼清單2-35中給出。

代碼清單2-35 FileStorage()函數原型
cv::FileStorage::FileStorage(const String & filename,
                                  int  flags,
                                  const String & encoding = String()
                                  )

表2-8 FileStorage()構造函數中對文件操作類型常用標誌及含義

標誌參數

簡記

含義

READ

0

讀取文件中的數據

WRITE

1

向文件中重新寫入數據,會覆蓋之前的數據

APPEND

2

向文件中繼續寫入數據,新數據在原數據之後

MEMORY

4

將數據寫入或者讀取到內部緩衝區

該函數是FileStorage類的構造函數,用於聲明打開的文件名稱和操作的類型。函數第一個參數是打開的文件名稱,參數是字符串類型,文件的擴展名是「.xml」、「.ymal」或者「.yml」。打開得文件可以已經存在或者未存在,但是當對文件進行讀取操作時需要是已經存在的文件。第二個參數是對文件進行的操作類型標誌,例如對文件進行讀取操作、寫入操作等,常用參數及含義在表2-8給出,由於該標誌量在FileStorage類中,因此在使用時需要加上類名作為前綴,例如「FileStorage::WRITE」。最後一個參數是文件的編碼格式,目前不支持UTF-16 XML編碼,需要使用UTF-8 XML編碼,通常情況下使用該參數的默認值即可。

打開文件後,可以通過FileStorage類中的isOpened()函數判斷是否成功打開文件,如果成功打開文件,該函數返回true,如果打開文件失敗,則該函數返回false。

FileStorage類中默認構造函數沒有任何參數,因此沒有聲明打開的文件和操作的類型,此時需要通過FileStorage類中的open()函數單獨進行聲明,該函數的函數原型在代碼清單2-36中給出。

代碼清單2-36 open()函數原型
virtual bool cv::FileStorage::open(const String & filename,
                                         int  flags,
                                         const String & encoding = String()
                                         )

該函數補充了默認構造函數沒有聲明打開文件的缺點,函數可以指定FileStorage類打開的文件,如果成功打開文件,則返回值為true,否則為false。函數中所有的參數及含義都與代碼清單2-35中的相同,因此這裡不再進行贅述。同樣,通過該函數打開文件後仍然可以通過FileStorage類中的isOpened()函數判斷是否成功打開文件。

打開文件後,類似C++中創建的數據流,可以通過「<<」操作符將數據寫入文件中,或者通過「>>」操作符從文件中讀取數據。除此之外,還可以通過FileStorage類中的write()函數將數據寫入文件中,該函數的函數原型在代碼清單2-37中給出。

代碼清單2-37 write()函數原型
void cv::FileStorage::write(const String & name,
                   int  val
              )

該函數能夠將不同數據類型的變量名稱和變量值寫入到文件中。該函數的第一個參數是寫入文件中的變量名稱。第二個參數是變量值,代碼清單2-37中的變量值是int類型,但是在FileStorage類中提供了write()函數的多個重載函數,分別用於實現將double、String、Mat、vector<String>類型的變量值寫入到文件中。

使用操作符向文件中寫入數據時與write()函數類似,都需要聲明變量名和變量值,例如變量名為「age」,變量值為「24」,可以通過「file<<」age」<<24」來實現。如果某個變量的數據是一個數組,可以用「[]」將屬於同一個變量的變量值標記出來,例如「file<<」age」<<「[」<<24<<25<<」]」」。如果某些變量隸屬於某個變量,可以用「{}」表示變量之間的隸屬關係,例如「file<<」age」<<「{」<<」Xiaoming」<<24<<」Wanghua」<<25<<」}」」。

讀取文件中的數據時,只需要通過變量名就可以讀取變量值。例如「file ["x"] >> xRead」是讀取變量名為x的變量值。但是,當某個變量中含有多個數據或者含有子變量時,就需要通過FileNode節點類型和迭代器FileNodeIterator進行讀取,例如某個變量的變量值是一個數組,首先需要定義一個file ["age"]的FileNode節點類型變量,之後通過迭代器遍歷其中的數據。另外一種方法可以不使用迭代器,通過在變量後邊添加「[]」地址的形式讀取數據,例如FileNode[0]表示數組變量中的第一個數據,FileNode[「Xiaoming」]表示「age」變量中的「Xiaoming」變量的數據,依次向後添加「[]」地址實現多節點數據的讀取。

為了了解如何生成和讀取XML文件和YMAL文件,在代碼清單2-38中給出了實現文件寫入和讀取的示例程序。程序中使用write()函數和「<<」操作符兩種方式向文件中寫入數據,使用迭代器和「[]」地址兩種方式從文件中讀取數據。數據的寫入和讀取方法在前面已經介紹,在代碼清單2-38中需要重點了解如何通過程序實現寫入與讀取。程序生成的XML文件和YMAL文件中的數據在圖2-10給出,讀取文件數據的結果在圖2-9給出。

代碼清單2-38 myXMLandYAML.cpp保存和讀取XML和YAML文件
1.  #include <opencv2/opencv.hpp>
2.  #include <iostream>
3.  #include <string>
4.  
5.  using namespace std;
6.  using namespace cv;
7.  
8.  int main(int argc, char** argv)
9. {
10.    system("color F0");
11.    
12.    string fileName = "datas.yaml";
13.    
14.    FileStorage fwrite(fileName, FileStorage::WRITE);
15.    
16.    
17.    Mat mat = Mat::eye(3, 3, CV_8U);
18.    fwrite.write("mat", mat);
19.    
20.    float x = 100;
21.    fwrite << "x" << x;
22.    
23.    String str = "Learn OpenCV 4";
24.    fwrite << "str" << str;
25.    
26.    fwrite << "number_array" << "[" <<4<<5<<6<< "]";
27.    
28.    fwrite << "multi_nodes" << "{" << "month" << 8 << "day" << 28 << "year"
29.      << 2019 << "time" << "[" << 0 << 1 << 2 << 3 << "]" << "}";
30.  
31.    
32.    fwrite.release();
33.  
34.    
35.    FileStorage fread(fileName, FileStorage::READ);
36.    
37.    if (!fread.isOpened())
38.    {
39.      cout << "打開文件失敗,請確認文件名稱是否正確!" << endl;
40.      return -1;
41.    }
42.  
43.    
44.    float xRead;
45.    fread["x"] >> xRead;
46.    cout << "x=" << xRead << endl;
47.  
48.    
49.    string strRead;
50.    fread["str"] >> strRead;
51.    cout << "str=" << strRead << endl;
52.  
53.    
54.    FileNode fileNode = fread["number_array"];
55.    cout << "number_array=[";
56.    
57.    for (FileNodeIterator i = fileNode.begin(); i != fileNode.end(); i++)
58.    {
59.      float a;
60.      *i >> a;
61.      cout << a<<" ";
62.    }
63.    cout << "]" << endl;
64.  
65.    
66.    Mat matRead;
67.    fread["mat="] >> matRead;
68.    cout << "mat=" << mat << endl;
69.  
70.    
71.    FileNode fileNode1 = fread["multi_nodes"];
72.    int month = (int)fileNode1["month"];
73.    int day = (int)fileNode1["day"];
74.    int year = (int)fileNode1["year"];
75.    cout << "multi_nodes:" << endl 
76.      << " month=" << month << " day=" << day << " year=" << year;
77.    cout << " time=[";
78.    for (int i = 0; i < 4; i++)
79.    {
80.      int a = (int)fileNode1["time"][i];
81.      cout << a << " ";
82.    }
83.    cout << "]" << endl;
84.    
85.    
86.    fread.release();
87.    return 0;
88.  }

圖2-9 myXMLandYAML.cpp程序文件讀取結果

圖2-10 myXMLandYAML.cpp程序生成的XML文件和YAML文件

經過幾個月的努力,市面上第一本OpenCV 4入門書籍《從零學習OpenCV 4》將於今年12月左右由人民郵電出版社發行。如果小夥伴覺得內容有幫助,希望到時候多多支持!

關注小白的小夥伴可以提前看到書中的內容,我們創建了學習交流群,歡迎各位小夥伴添加小白微信加入交流群,添加小白時請備註「學習OpenCV 4」。

覺得文章對自己有幫助的小夥伴點個「在看」

相關焦點

  • 【從零學習OpenCV】 視頻數據的讀取&攝像頭的直接調用
    重磅乾貨,第一時間送達經過幾個月的努力,小白終於完成了市面上第一本OpenCV 4入門書籍《從零學習OpenCV 4
  • python3 讀取XML文件的入坑經歷
    背景由於需要從XML文件裡,讀取圖片的列表。
  • opencv學習記錄1——視頻讀取與寫入
    為了敦促自己的學習計劃和進度,本期作為opencv的學習專項計劃記錄,希望這些記錄能夠為以後的學習提供一些記憶和練習資料,同時,恩公偶為需要的童鞋提供微不足道的幫助和學習計劃
  • 【從零學習OpenCV 4】圖像讀取函數imread
    重磅乾貨,第一時間送達經過幾個月的努力,小白終於完成了市面上第一本OpenCV 4入門書籍《從零學習OpenCV 4
  • python+opencv實現車牌識別
    文章目錄:一、前言二、訓練分類器2.1、準備訓練用單字符圖片2.2、圖片預處理2.3、用opencv的preprocess_hog()處理圖片2.4、用SVM訓練分類器三、車牌定位四、字符分割五、字符識別六、Mysql保存七、總結八、參考資料一、 前言:最近一直在學習機器學習,花了段時間把《機器學習實戰》(【美】Peter Harrington著
  • 給OpenCV初學者的禮物——OpenCV人臉檢測入門教程
    很榮幸能成為大家學習OpenCV的領路人。作者祝大家都能在學習的過程中找人生到真正的意義。本文的參考文檔見https://docs.opencv.org/4.0.1/d1/dfb/intro.html圖像的基本操作對於人類來說,圖像可以解構為畫面結構、色彩和非常豐富的意象。
  • 每日一課 | Python –讀取XML文件(DOM示例)
    在此示例中,我們將向您展示如何通過Python xml.dom.minidom
  • 第27篇 Qt5之XML(一)使用DOM讀取XML文檔
    相對於資料庫表格的二維表示,XML使用的樹形結構更能表現出數據的包含關係,作為一種文本文件格式,XML簡單明了的特性使得它在信息存儲和描述領域非常流行。       在Qt中提供了Qt XML模塊來進行XML文檔的處理,這裡主要提供了兩種解析方法: DOM方法,可以進行讀寫;SAX方法,可以進行讀取。
  • Java文件操作——XML文件的讀取
    閱讀目錄一、邂逅XML文件種類是豐富多彩的,XML作為眾多文件類型的一種,經常被用於數據存儲和傳輸。所以XML在現今應用程式中是非常流行的。本文主要講Java解析和生成XML。用於不同平臺、不同設備間的數據共享通信。
  • 從任意文件讀取到拿webshell
    找到系統存在一個讀取點,利用文件 ID 或者文件名讀取文件的讀取點,確定成功讀取的狀態讀取一個不存在的文件,確定讀取不存在文件時的狀態,標誌性文件可隨意拓展,注意選取標誌性文件時選取讀取權限要求最低的文件
  • AndroidManifest.xml文件安全探索
    最近在做一些apk的安全檢測,對AndroidManifest.xml文件進行了研究和探討,介紹AndroidManifest.xml
  • Python+OpenCV的基礎圖像處理操作匯總
    通過在CMD(命令提示符)中發出以下命令來安裝opencv python(這是一個用於python的非正式預構建opencv包):opencv-contrib-python(包含main和contrib模塊)opencv-python-headless(與opencv-python相同,但沒有
  • ASP.NET讀取XML某節點所有數據返回DataTable實例
    ASP.NET讀取XML某節點所有數據返回DataTable實例 網上有好多ASP.NET讀取XML的例子,比如使用Dataset來讀取,但本文教程卻是使用XmlDocument
  • 數據分析從零開始實戰 (三)
    零、寫在前面前面兩篇文章基礎篇(一)和基礎篇(二)講了數據分析虛擬環境創建和pandas讀寫csv、tsv、json格式的數據,今天我們繼續探索pandas讀取數據。本系列學習筆記參考書籍:《數據分析實戰》託馬茲·卓巴斯一、基本知識概要1.利用pandas讀寫Excel文件2.利用pandas讀寫XML文件二、開始動手動腦1.利用Python讀寫Excel讀取,利用Pandas庫的ExcelFile()方法。
  • 世界上最好的語言PHP:OpenCV與計算機視覺已在我掌控之下
    在本篇文章中,除了那些我看電視節目和玩遊戲的時間,我敘述了在過去六個月的幾乎所有空閒時間裡所做的探索。現今,「機器學習」發展迅速,並有大量相關的文章,包括那些 Medium 上的博客,同時幾乎每位開發人員都開始在工作任務和本地項目中使用機器學習,但是從何處開始以及使用什麼方法總是令人困惑的。
  • 【從零學習OpenCV 4】分割圖像——Mean-Shift分割算法
    碼清單8-25 myPyrMeanShiftFiltering.cpp利用均值漂移法分割圖像#include <opencv2/opencv.hpp>#include <iostream>using namespace cv;using namespace std;int main(){ Mat img =
  • Python 圖像處理 OpenCV (1):入門
    新系列第一件事兒當然是資源推薦,下面是一些有關 OpenCV 的資源連結:資源連結:官方網站:https://opencv.org/GitHub:https://github.com/opencv/opencv官方文檔:https://docs.opencv.org/中文文檔(非官方):http://www.woshicver.com
  • Python讀取圖像文件的三種方式:PIL, OpenCV和GDAL
    使用PYTHON進行圖像處理的首要步驟便是讀入圖像數據,這裡介紹讀入圖像文件的三種方式,包括Pillow(PIL)、OpenCV和GDAL。PillowPillow是PIL(Python Imaging Library)的分支,為Python增強了圖像處理能力。
  • 數據分析從零開始實戰 | 基礎篇(三)
    零、寫在前面前面兩篇文章基礎篇(一)和基礎篇(二)講了數據分析虛擬環境創建和pandas讀寫csv、tsv、json格式的數據,今天我們繼續探索pandas讀取數據。本系列學習筆記參考書籍:《數據分析實戰》託馬茲·卓巴斯一、基本知識概要1.利用pandas讀寫Excel文件2.利用pandas讀寫XML文件二、開始動手動腦1.利用Python讀寫Excel讀取,利用Pandas庫的ExcelFile()方法。
  • 醫學圖像處理與深度學習入門
    在http://opencv.org中,還有很多類似的例子,http://docs.opencv.org/trunk/d6/d00/tutorial_py_root.html , 讀者可以多多練習。現在我們已經了解一些基本的圖像處理知識,下面我們將學習如何處理醫學圖像。