獨家|OpenCV1.8 使用XML和YAML文件實(shí)現文件的輸入/輸出
目標
本小節將回答以下問(wèn)題:
如何使用YAML或XML文件打印和讀取文本輸入到文件和OpenCV?
如何對OpenCV數據結構做相同的操作?
如何為自定義的數據結構做相同的操作?
OpenCV中cv::FileStorage , cv::FileNode 和 cv::FileNodeIterator 的數據結構和使用方法。
源代碼
C ++
可以在原文下載源代碼,也可以在以下目錄中
samples/cpp/tutorial_code/core/file_input_output/file_input_output.cpp 找到 OpenCV的源代碼庫。
這里還有完整的示例代碼。
代碼詳解
在這里,只講解XML和YAML文件輸入。你的輸出(及其對應的輸入)只能是具有XML和YAML擴展名的文件,并帶有XML和YAML數據結構。這里有兩種可以串行化的數據結構:映射(諸如STL映射和Python字典)和元素序列(如STL向量)。二者之間的區別是,映射中的每一個(gè)元素均有唯一的名稱(chēng),可以通過(guò)該名稱(chēng)進(jìn)行訪(fǎng)問(wèn)。對于序列而言,則需要通過(guò)遍歷來(lái)查詢(xún)一個(gè)具體的項目。
1. 打開(kāi)和關(guān)閉XML / YAML文件。在讀寫(xiě)文件內容之前,首先需要打開(kāi)文件,在使用結束時(shí)關(guān)閉文件。OpenCV中的XML / YAML數據結構是CV :: FileStorage。具體來(lái)說(shuō),該結構可以將文件與硬盤(pán)驅動(dòng)器綁定起來(lái),這樣便可以使用它的構造函數或open()函數:
無(wú)論是哪一種數據結構,它的第二個(gè)參數都是一個(gè)常數,可以用來(lái)指定操作類(lèi)型,比如:寫(xiě)入讀取或追加。文件的擴展名還決定了輸出文件的格式。如果輸出文件的擴展名為*.xml.gz*,甚至能夠輸出壓縮文件。
當釋放CV :: FileStorage對象之后,該文件將自動(dòng)關(guān)閉??梢酝ㄟ^(guò)調用release 函數顯式地自動(dòng)關(guān)閉文件:
2. 文本和數字的輸入/輸出。C ++中,數據結構使用STL庫中的<<輸出操作符。Python中,則使用了 )。輸出任何類(lèi)型的數據結構,首先需要指定其名稱(chēng),在C++中,只需要單純地將名稱(chēng)推給數據流。在Python中,寫(xiě)函數的第一個(gè)參數便是名稱(chēng)??梢杂靡韵旅畲蛴∥谋竞蛿底郑?/p>
讀取是一種簡(jiǎn)單的尋址方式(使用 []操作符)、casting操作或使用>>操作符讀出。在Python中,使用real()和getNode()函數來(lái)尋址:
3. OpenCV數據結構的輸入/輸出。該操作與基礎C ++和Python的類(lèi)型完全相同。
4. 向量(數組)的輸入/輸出和相關(guān)映射。正如前文所述,輸出可以是映射和序列(數組,向量)。同樣,可以先打印變量的名稱(chēng),然后指定輸出的序列或映射。
在序列的第一個(gè)元件之前打印“[”字符,在序列的最后一個(gè)元素之后打印 “]”字符。在Python語(yǔ)言中,調用 FileStorage.startWriteStruct(structure_name,struct_type) , 其中struct_type為 cv2.FileNode_MAP或cv2.FileNode_SEQ結構,最后調用FileStorage.endWriteStruct()來(lái)實(shí)現結構:
同理,對用映射,可以使用“{”和“}”分隔符來(lái)代替“[”和]”字符:
在讀操作中,可以使用的和cv::FileNodeIterator兩種數據結構。cv::FileStorage 類(lèi)中的[]操作符(在Python中為 getNode()函數)可以返回一個(gè)數據類(lèi)型。如果節點(diǎn)為序列結構,則可以使用CV :: FileNodeIterator進(jìn)行迭代。在Python中,可以調用at()函數訪(fǎng)問(wèn)序列中的元素,并用size() 函數返回序列長(cháng)度:
對于映射,可以使用[]操作符(在Python中為at()函數)來(lái)訪(fǎng)問(wèn)數據(也可使用>>操作符):
5. 讀/寫(xiě)自定義的數據結構。假定有一個(gè)數據結構,如下所示:
在C ++中,通過(guò)OpenCV 的XML / YAML I / O接口實(shí)現串行化?(僅針對OpenCV的數據結構),為自定義的類(lèi)添加讀取和寫(xiě)入函數。在Python中,可以在類(lèi)的內部一個(gè)讀取和寫(xiě)入函數來(lái)完成類(lèi)似的操作。內部情況如下:
在C ++中,需要在類(lèi)的外部添加下列函數的定義:
如果用戶(hù)試圖讀取一個(gè)不存在的節點(diǎn)時(shí),只返回默認初始值。而更為詳細的解決方案則是為對象ID返回一個(gè)為-1的值。
一旦添加了該函數定義,則這四個(gè)函數便會(huì )使用>>操作符寫(xiě)入和<<操作符讀?。ɑ蚴荘ython中的輸入/輸出函數)
或者可以嘗試讀取一個(gè)不存在的節點(diǎn):
程序運行結果
在大多情況下,只需要將定義好的數值打印出來(lái),在顯示屏幕上可以看到以下運行輸出結果:
更加有趣的是:還可以在輸出的XML文件中看到以下結果:
或者在輸出的YAML文件中看到以下結果:
可以在YouTube網(wǎng)站觀(guān)看這個(gè)示例的運行視頻。
注:本文以C++語(yǔ)言代碼為例,獲取Java和python版本可在原文中查看:
https://docs.opencv.org/4.5.2/dd/d74/tutorial_file_input_output_with_xml_yml.html
*博客內容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀(guān)點(diǎn),如有侵權請聯(lián)系工作人員刪除。