簡體   English   中英

用於 OpenCV Python API 的文件存儲

[英]FileStorage for OpenCV Python API

我目前正在使用FileStorage類使用 OpenCV C++ API 存儲矩陣XML/YAML

但是,我必須編寫一個 Python 腳本來讀取這些XML/YAML文件。

我正在尋找可以讀取由OpenCV C++ API生成的XML/YAML文件的現有 OpenCV Python API

您可以使用PyYAML來解析 YAML 文件。

由於 PyYAML 不理解 OpenCV 數據類型,因此您需要為您嘗試加載的每個 OpenCV 數據類型指定一個構造函數。 例如:

import yaml
def opencv_matrix(loader, node):
    mapping = loader.construct_mapping(node, deep=True)
    mat = np.array(mapping["data"])
    mat.resize(mapping["rows"], mapping["cols"])
    return mat
yaml.add_constructor(u"tag:yaml.org,2002:opencv-matrix", opencv_matrix)

完成后,加載 yaml 文件很簡單:

with open(file_name) as fin:
    result = yaml.load(fin.read())

結果將是一個字典,其中鍵是您在 YAML 中保存的任何內容的名稱。

使用 OpenCV 3.2 中可用的 FileStorage 函數,我成功地使用了它:

import cv2
fs = cv2.FileStorage("calibration.xml", cv2.FILE_STORAGE_READ)
fn = fs.getNode("Camera_Matrix")
print (fn.mat())

除了@misha 的回應之外,OpenCV YAML 與 Python 有點不兼容。

不兼容的幾個原因是:

  1. OpenCV 創建的 Yaml 在“:”之后沒有空格。 而 Python 需要它。 [例如:它應該是a: 2 ,而不是 Python a:2 ]
  2. OpenCV 創建的 YAML 文件的第一行是錯誤的。 將“%YAML:1.0”轉換為“%YAML 1.0”。 或者在閱讀時跳過第一行。

以下函數負責提供:

import yaml
import re
def readYAMLFile(fileName):
    ret = {}
    skip_lines=1    # Skip the first line which says "%YAML:1.0". Or replace it with "%YAML 1.0"
    with open(scoreFileName) as fin:
        for i in range(skip_lines):
            fin.readline()
        yamlFileOut = fin.read()
        myRe = re.compile(r":([^ ])")   # Add space after ":", if it doesn't exist. Python yaml requirement
        yamlFileOut = myRe.sub(r': \1', yamlFileOut)
        ret = yaml.load(yamlFileOut)
    return ret

outDict = readYAMLFile("file.yaml")

注意:以上響應僅適用於 yaml。 XML 有自己的問題,我還沒有完全探討過。

我寫了一個小片段來在 Python 中讀寫與 FileStorage 兼容的 YAML:

# A yaml constructor is for loading from a yaml node.
# This is taken from @misha 's answer: http://stackoverflow.com/a/15942429
def opencv_matrix_constructor(loader, node):
    mapping = loader.construct_mapping(node, deep=True)
    mat = np.array(mapping["data"])
    mat.resize(mapping["rows"], mapping["cols"])
    return mat
yaml.add_constructor(u"tag:yaml.org,2002:opencv-matrix", opencv_matrix_constructor)

# A yaml representer is for dumping structs into a yaml node.
# So for an opencv_matrix type (to be compatible with c++'s FileStorage) we save the rows, cols, type and flattened-data
def opencv_matrix_representer(dumper, mat):
    mapping = {'rows': mat.shape[0], 'cols': mat.shape[1], 'dt': 'd', 'data': mat.reshape(-1).tolist()}
    return dumper.represent_mapping(u"tag:yaml.org,2002:opencv-matrix", mapping)
yaml.add_representer(np.ndarray, opencv_matrix_representer)

#examples 

with open('output.yaml', 'w') as f:
    yaml.dump({"a matrix": np.zeros((10,10)), "another_one": np.zeros((2,4))}, f)

with open('output.yaml', 'r') as f:
    print yaml.load(f)

為了改進@Roy_Shilkrot 之前的回答,我添加了對 numpy 向量和矩陣的支持:

# A yaml constructor is for loading from a yaml node.
# This is taken from @misha 's answer: http://stackoverflow.com/a/15942429
def opencv_matrix_constructor(loader, node):
    mapping = loader.construct_mapping(node, deep=True)
    mat = np.array(mapping["data"])
    if mapping["cols"] > 1:
        mat.resize(mapping["rows"], mapping["cols"])
    else:
        mat.resize(mapping["rows"], )
    return mat
yaml.add_constructor(u"tag:yaml.org,2002:opencv-matrix", opencv_matrix_constructor)


# A yaml representer is for dumping structs into a yaml node.
# So for an opencv_matrix type (to be compatible with c++'s FileStorage) we save the rows, cols, type and flattened-data
def opencv_matrix_representer(dumper, mat):
    if mat.ndim > 1:
        mapping = {'rows': mat.shape[0], 'cols': mat.shape[1], 'dt': 'd', 'data': mat.reshape(-1).tolist()}
    else:
        mapping = {'rows': mat.shape[0], 'cols': 1, 'dt': 'd', 'data': mat.tolist()}
    return dumper.represent_mapping(u"tag:yaml.org,2002:opencv-matrix", mapping)
yaml.add_representer(np.ndarray, opencv_matrix_representer)

例子:

with open('output.yaml', 'w') as f:
    yaml.dump({"a matrix": np.zeros((10,10)), "another_one": np.zeros((5,))}, f)

with open('output.yaml', 'r') as f:
    print yaml.load(f)

輸出:

a matrix: !!opencv-matrix
  cols: 10
  data: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0]
  dt: d
  rows: 10
another_one: !!opencv-matrix
  cols: 1
  data: [0.0, 0.0, 0.0, 0.0, 0.0]
  dt: d
  rows: 5

雖然我無法控制行、列、dt、數據的順序。

pip install opencv-contrib-python 視頻支持安裝特定版本使用 pip install opencv-contrib-python

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM